mirror of
https://github.com/jumpserver/lina.git
synced 2025-09-16 15:19:25 +00:00
perf: 优化 nest fields 支持是否隐藏
This commit is contained in:
@@ -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'
|
||||
|
@@ -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>
|
@@ -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>
|
@@ -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>
|
@@ -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>
|
@@ -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>
|
@@ -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>
|
@@ -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,
|
||||
|
Reference in New Issue
Block a user