perf: 优化 nest fields 支持是否隐藏

This commit is contained in:
ibuler
2023-05-31 16:16:13 +08:00
committed by Jiangjie.Bai
parent 32fa172197
commit 7276b19a92
8 changed files with 6 additions and 537 deletions

View File

@@ -85,6 +85,10 @@ export class FormFieldGenerator {
field.el = { ...field.el, ...fieldMeta }
field.el.fields = this.generateNestFields(field, fieldMeta, fieldRemoteMeta)
field.el.errors = {}
field.hidden = () => {
const hidden = fieldMeta['hiddenFields'] || (() => field.el.fields.length === 0)
return hidden(fieldMeta, fieldRemoteMeta, field.el.fields)
}
break
default:
type = 'input'

View File

@@ -1,98 +0,0 @@
<template>
<GenericCreateUpdatePage :fields="fields" :initial="initial" :fields-meta="fieldsMeta" :url="url" />
</template>
<script>
import GenericCreateUpdatePage from '@/layout/components/GenericCreateUpdatePage'
import AssetSelect from '@/components/AssetSelect/index'
export default {
name: 'CommandFilterCreateUpdate',
components: { GenericCreateUpdatePage },
data() {
return {
initial: {
},
fields: [
[this.$t('common.Basic'), ['name']],
[this.$t('common.Correlation'), ['users', 'user_groups', 'nodes', 'assets', 'applications', 'system_users']],
[this.$t('common.Other'), ['is_active', 'comment']]
],
fieldsMeta: {
users: {
el: {
value: [],
ajax: {
url: '/api/v1/users/users/?fields_size=mini',
transformOption: (item) => {
return { label: item.name + '(' + item.username + ')', value: item.id }
}
}
}
},
user_groups: {
el: {
value: [],
url: '/api/v1/users/groups/'
}
},
nodes: {
el: {
value: [],
ajax: {
url: '/api/v1/assets/nodes/',
transformOption: (item) => {
return { label: item.full_value, value: item.id }
}
}
}
},
assets: {
type: 'assetSelect',
component: AssetSelect,
label: this.$t('perms.Asset'),
rules: [{
required: false
}],
el: {
value: []
}
},
applications: {
label: this.$t('assets.Applications'),
el: {
value: [],
ajax: {
url: `/api/v1/applications/applications/?category__in=db,cloud`,
transformOption: (item) => {
return { label: item.name + ' (' + item.type_display + ')', value: item.id }
}
}
}
},
system_users: {
el: {
value: [],
ajax: {
url: `/api/v1/assets/system-users/?protocol__in=ssh,telnet,mysql,postgresql,mariadb,oracle,sqlserver,k8s,redis,mongodb,clickhouse`,
transformOption: (item) => {
if (this.$route.query.type === 'k8s') {
return { label: item.name, value: item.id }
}
const username = item.username || '*'
return { label: item.name + '(' + username + ')', value: item.id }
}
}
}
}
},
url: '/api/v1/assets/cmd-filters/'
}
}
}
</script>
<style lang='less' scoped>
</style>

View File

@@ -1,122 +0,0 @@
<template>
<el-row :gutter="20">
<el-col :md="14" :sm="24">
<AutoDetailCard :url="url" :object="object" />
</el-col>
<el-col :md="10" :sm="24">
<RelationCard ref="users" v-bind="userRelationConfig" />
<RelationCard ref="userGroups" type="info" v-bind="userGroupsRelationConfig" class="card-margin" />
<RelationCard ref="applications" type="warning" v-bind="applicationsRelationConfig" class="card-margin" />
<RelationCard ref="systemUsers" type="danger" v-bind="systemUserRelationConfig" class="card-margin" />
</el-col>
</el-row>
</template>
<script>
import AutoDetailCard from '@/components/DetailCard/auto'
import RelationCard from '@/components/RelationCard'
export default {
name: 'Detail',
components: {
AutoDetailCard,
RelationCard
},
props: {
object: {
type: Object,
default: () => {}
}
},
data() {
const disabled = !this.$hasPerm('assets.change_commandfilter')
const defaultTransformOption = (item, filed) => {
const currentFiled = item[filed] ? item[filed] : filed === 'username' ? '*' : ''
return { label: item.name + '(' + currentFiled + ')', value: item.id }
}
return {
userRelationConfig: {
disabled,
icon: 'fa-user',
title: this.$t('common.User'),
objectsAjax: {
url: '/api/v1/users/users/?fields_size=mini',
transformOption: (item) => defaultTransformOption(item, 'username')
},
hasObjectsId: this.object.users,
performAdd: item => this.performAddHandle(item, 'users'),
performDelete: item => this.performDeleteHandle(item, 'users')
},
userGroupsRelationConfig: {
disabled,
icon: 'fa-users',
title: this.$t('users.UserGroups'),
objectsAjax: {
url: '/api/v1/users/groups/'
},
hasObjectsId: this.object.user_groups,
performAdd: item => this.performAddHandle(item, 'user_groups'),
performDelete: item => this.performDeleteHandle(item, 'user_groups')
},
applicationsRelationConfig: {
disabled,
icon: 'fa-th',
title: this.$t('assets.Applications'),
objectsAjax: {
url: `/api/v1/applications/applications/?category__in=db,cloud`,
transformOption: (item) => defaultTransformOption(item, 'type_display')
},
hasObjectsId: this.object.applications,
performAdd: item => this.performAddHandle(item, 'applications'),
performDelete: item => this.performDeleteHandle(item, 'applications')
},
systemUserRelationConfig: {
disabled,
icon: 'fa-info-circle',
title: this.$t('assets.SystemUser'),
objectsAjax: {
url: `/api/v1/assets/system-users/?protocol__in=ssh,telnet,mysql,postgresql,mariadb,oracle,sqlserver,k8s,redis,mongodb,clickhouse`,
transformOption: (item) => defaultTransformOption(item, 'username')
},
hasObjectsId: this.object.system_users,
performAdd: item => this.performAddHandle(item, 'system_users'),
performDelete: item => this.performDeleteHandle(item, 'system_users')
},
url: '/api/v1/assets/cmd-filters/'
}
},
computed: {
},
methods: {
performAddHandle(item, updateField) {
const newDatas = []
const updateFieldRef = _.camelCase(updateField)
const options = this.$refs[updateFieldRef].iHasObjects
const relationUrl = `/api/v1/assets/cmd-filters/${this.object.id}/`
options.forEach(v => newDatas.push(v.value))
item.forEach(v => newDatas.push(v.value))
return this.$axios.patch(relationUrl, { [updateField]: newDatas })
},
performDeleteHandle(item, updateField) {
const newDatas = []
const itemId = item?.value || ''
const updateFieldRef = _.camelCase(updateField)
const options = this.$refs[updateFieldRef].iHasObjects
const relationUrl = `/api/v1/assets/cmd-filters/${this.object.id}/`
options.forEach(v => {
if (v.value !== itemId) {
newDatas.push(v.value)
}
})
return this.$axios.patch(relationUrl, { [updateField]: newDatas })
}
}
}
</script>
<style lang='less' scoped>
.card-margin {
margin-top: 15px;
}
</style>

View File

@@ -1,74 +0,0 @@
<template>
<GenericListTable :table-config="tableConfig" :header-actions="headerActions" />
</template>
<script>
import GenericListTable from '@/layout/components/GenericListTable'
export default {
name: 'Rules',
components: {
GenericListTable
},
props: {
object: {
type: Object,
default: () => {}
}
},
data() {
return {
tableConfig: {
url: `/api/v1/assets/cmd-filters/${this.object.id}/rules/`,
permissions: {
resource: 'commandfilterrule'
},
columns: ['type', 'content', 'ignore_case', 'action', 'priority', 'pattern', 'comment', 'actions'],
columnsMeta: {
type: {
width: '100px'
},
ignore_case: {
width: '100px',
formatterArgs: {
showFalse: false
}
},
priority: {
width: '70px'
},
action: {
width: '90px'
},
actions: {
formatterArgs: {
hasClone: false,
updateRoute: {
name: 'CommandFilterRulesUpdate',
query: {
filter: this.object.id
}
}
}
}
}
},
headerActions: {
hasSearch: true,
hasBulkDelete: false,
hasMoreActions: false,
createRoute: {
name: 'CommandFilterRulesCreate',
query: {
filter: this.object.id
}
}
}
}
}
}
</script>
<style lang='less' scoped>
</style>

View File

@@ -1,100 +0,0 @@
<template>
<GenericCreateUpdatePage
:fields="fields"
:initial="initial"
:fields-meta="fieldsMeta"
:url="url"
:has-detail-in-msg="false"
:get-next-route="getNextRoute"
/>
</template>
<script>
import GenericCreateUpdatePage from '@/layout/components/GenericCreateUpdatePage'
import Select2 from '@/components/FormFields/Select2'
import rules from '@/components/DataForm/rules'
export default {
name: 'RulesCreateUpdate',
components: { GenericCreateUpdatePage },
data() {
const filterId = this.$route.query.filter || '00000000-0000-0000-0000-000000000000'
const regexPlaceholder = 'rm.*|reboot|shutdown'
const commandPlaceholder = 'rm\rreboot'
const commandHelpText = this.$t('assets.CommandFilterRuleContentHelpText')
const vm = this
return {
initial: {
filter: filterId,
type: 'regex',
action: 0
},
fields: [
[this.$t('common.Basic'), ['filter', 'type', 'content', 'ignore_case', 'priority', 'action', 'reviewers', 'comment']]
],
fieldsMeta: {
filter: {
component: Select2,
el: {
ajax: {
url: '/api/v1/assets/cmd-filters/'
},
disabled: true,
multiple: false
}
},
type: {
on: {
change: ([val]) => {
if (val === 'command') {
vm.fieldsMeta.content.el.placeholder = commandPlaceholder
vm.fieldsMeta.content.helpText = commandHelpText
} else {
vm.fieldsMeta.content.el.placeholder = regexPlaceholder
vm.fieldsMeta.content.helpText = ''
}
}
}
},
content: {
type: 'input',
el: {
type: 'textarea',
placeholder: 'rm.*|reboot|shutdown',
rows: 4
},
helpText: ''
},
reviewers: {
hidden: (item) => item.action !== 2,
rules: [rules.RequiredChange],
el: {
value: [],
ajax: {
url: '/api/v1/users/users/?fields_size=mini',
transformOption: (item) => {
return { label: item.name + '(' + item.username + ')', value: item.id }
}
}
}
}
},
getNextRoute(res, method) {
return {
name: 'CommandFilterDetail',
params: {
id: res.filter
},
query: {
activeTable: 'rules'
}
}
},
url: `/api/v1/assets/cmd-filters/${filterId}/rules/`
}
}
}
</script>
<style lang='less' scoped>
</style>

View File

@@ -1,45 +0,0 @@
<template>
<GenericDetailPage :object.sync="TaskDetail" :active-menu.sync="config.activeMenu" v-bind="config" v-on="$listeners">
<keep-alive>
<component :is="config.activeMenu" :object="TaskDetail" />
</keep-alive>
</GenericDetailPage>
</template>
<script>
import { GenericDetailPage, TabPage } from '@/layout/components'
import Detail from './Detail.vue'
import Rules from './Rules.vue'
export default {
components: {
GenericDetailPage,
TabPage,
Detail,
Rules
},
data() {
return {
TaskDetail: {},
config: {
activeMenu: 'Detail',
submenu: [
{
title: this.$t('assets.CommandFilterDetail'),
name: 'Detail'
},
{
title: this.$t('assets.CommandFilterRules'),
name: 'rules',
hidden: () => !this.$hasPerm('assets.view_commandfilterrule')
}
],
hasRightSide: true
}
}
}
}
</script>
<style scoped>
</style>

View File

@@ -1,97 +0,0 @@
<template>
<GenericListPage :table-config="tableConfig" :header-actions="headerActions" :help-message="title" />
</template>
<script>
import { GenericListPage } from '@/layout/components'
import { DetailFormatter } from '@/components/TableFormatters'
export default {
components: {
GenericListPage
},
data() {
return {
tableConfig: {
url: '/api/v1/assets/cmd-filters/',
permissions: {
app: 'assets',
resource: 'commandfilter'
},
columns: [
'name', 'rules', 'users', 'user_groups', 'assets', 'applications', 'system_users', 'is_active',
'created_by', 'date_created', 'comment', 'org_name', 'actions'
],
columnsShow: {
min: ['name', 'actions'],
default: ['name', 'rules', 'comment', 'actions']
},
columnsMeta: {
rules: {
label: this.$t('assets.Rules'),
formatter: DetailFormatter,
formatterArgs: {
getTitle: ({ cellValue }) => {
return cellValue.length
},
routeQuery: {
activeTab: 'rules'
}
}
},
date_created: {
label: this.$t('users.DateJoined')
},
users: {
formatter: function(row, col, cell) {
return cell.length
}
},
user_groups: {
formatter: function(row, col, cell) {
return cell.length
}
},
assets: {
formatter: function(row, col, cell) {
return cell.length
}
},
applications: {
formatter: function(row, col, cell) {
return cell.length
}
},
system_users: {
label: this.$t('assets.SystemUsers'),
formatter: DetailFormatter,
formatterArgs: {
route: 'CommandFilterDetail',
getTitle: ({ cellValue }) => {
return cellValue.length
}
}
}
}
},
headerActions: {
hasRightActions: true,
hasExport: false,
hasImport: false,
hasRefresh: true,
hasSearch: true,
createRoute: 'CommandFilterCreate'
}
}
},
computed: {
title() {
return this.$t('assets.CommandFilterHelpMessage')
}
}
}
</script>
<style>
</style>

View File

@@ -66,7 +66,8 @@ export default {
key: this.$t('assets.Type'),
value: `${this.object.category?.label}/${this.object.type?.label}`
},
'su_method', 'comment'
'su_method', 'date_created', 'date_updated',
'created_by', 'updated_by', 'comment'
],
protocolChoices: null,