perf: rechange asset permission accounts

This commit is contained in:
ibuler
2024-06-06 16:55:07 +08:00
parent a89c32e668
commit 659a3864f7
6 changed files with 97 additions and 447 deletions

View File

@@ -30,11 +30,12 @@ export default {
} }
}, },
data() { data() {
const resourceDisplay = this.$t('WordSep') + this.resource.toLowerCase()
return { return {
type: 'all', // all, selected type: 'all', // all, selected
types: [ types: [
{ name: 'all', label: this.$t('All') + this.$t('WordSep') + this.resourceLower }, { name: 'all', label: this.$t('All') + resourceDisplay },
{ name: 'spec', label: this.$t('Spec') + this.$t('WordSep') + this.resourceLower } { name: 'spec', label: this.$t('Spec') + resourceDisplay }
], ],
selected: [] selected: []
} }
@@ -46,9 +47,6 @@ export default {
} else { } else {
return this.selected return this.selected
} }
},
resourceLower() {
return this.resource.toLowerCase()
} }
}, },
mounted() { mounted() {

View File

@@ -177,6 +177,7 @@ export default {
.search-input { .search-input {
flex: 1; flex: 1;
& > > > .el-input__inner { & > > > .el-input__inner {
max-width: 100%; max-width: 100%;
border: none; border: none;
@@ -197,6 +198,7 @@ export default {
display: inherit; display: inherit;
padding-right: 6px; padding-right: 6px;
cursor: pointer; cursor: pointer;
&:hover { &:hover {
color: #999999; color: #999999;
} }

View File

@@ -15,8 +15,6 @@ import { getDayFuture } from '@/utils/time'
import AccountFormatter from './components/AccountFormatter' import AccountFormatter from './components/AccountFormatter'
import { AllAccount } from '../const' import { AllAccount } from '../const'
import ProtocolsSelect from '@/components/Form/FormFields/AllOrSpec.vue' import ProtocolsSelect from '@/components/Form/FormFields/AllOrSpec.vue'
import RealFormatter from './components/RealFormatter.vue'
import VirtualFormatter from './components/VirtualFormatter.vue'
export default { export default {
name: 'AccountFormatter', name: 'AccountFormatter',
@@ -45,7 +43,7 @@ export default {
[this.$t('Basic'), ['name']], [this.$t('Basic'), ['name']],
[this.$t('User'), ['users', 'user_groups']], [this.$t('User'), ['users', 'user_groups']],
[this.$t('Asset'), ['assets', 'nodes']], [this.$t('Asset'), ['assets', 'nodes']],
[this.$t('Account'), ['real_accounts', 'virtual_accounts']], [this.$t('Account'), ['accounts']],
[this.$t('Protocol'), ['protocols']], [this.$t('Protocol'), ['protocols']],
[this.$t('Action'), ['actions']], [this.$t('Action'), ['actions']],
[this.$t('Other'), ['is_active', 'date_start', 'date_expired', 'comment']] [this.$t('Other'), ['is_active', 'date_start', 'date_expired', 'comment']]
@@ -121,12 +119,6 @@ export default {
this.fieldsMeta.accounts.el.nodes = formValue.nodes this.fieldsMeta.accounts.el.nodes = formValue.nodes
} }
}, },
real_accounts: {
component: RealFormatter
},
virtual_accounts: {
component: VirtualFormatter
},
actions: { actions: {
label: this.$t('Action'), label: this.$t('Action'),
helpText: this.$t('ActionsTips') helpText: this.$t('ActionsTips')

View File

@@ -1,10 +1,9 @@
<template> <template>
<el-form @submit.native.prevent> <el-form class="account-content" @submit.native.prevent>
<el-form-item> <el-form-item>
<el-checkbox-group v-model="choicesSelected"> <el-checkbox-group v-model="choicesSelected">
<div class="group-title">资产上的账号</div>
<el-checkbox <el-checkbox
v-for="(i) in choices.slice(0, 2)" v-for="(i) in choices"
:key="i.label" :key="i.label"
:label="i.value" :label="i.value"
@change="handleCheckboxCheck(i, $event)" @change="handleCheckboxCheck(i, $event)"
@@ -16,6 +15,7 @@
</el-checkbox> </el-checkbox>
<div v-if="showSpecAccounts" class="spec-accounts"> <div v-if="showSpecAccounts" class="spec-accounts">
<div class="group-title">{{ $t('SpecAccount') }}</div>
<TagInput <TagInput
:autocomplete="autocomplete" :autocomplete="autocomplete"
:tag-type="getTagType" :tag-type="getTagType"
@@ -26,15 +26,16 @@
<el-button size="mini" type="primary" @click="showTemplateDialog=true"> <el-button size="mini" type="primary" @click="showTemplateDialog=true">
{{ $t('TemplateAdd') }} {{ $t('TemplateAdd') }}
</el-button> </el-button>
<span class="help-block" style="display: inline"> <span class="help-block">
{{ addTemplateHelpText }} {{ addTemplateHelpText }}
</span> </span>
</span> </span>
</div> </div>
<div class="group-title">虚拟账号</div> <div v-if="showVirtualAccountCheckbox">
<div class="group-title">{{ $t('VirtualAccounts') }}</div>
<el-checkbox <el-checkbox
v-for="(i) in choices.slice(2, )" v-for="i in virtualAccounts"
:key="i.label" :key="i.label"
:label="i.value" :label="i.value"
@change="handleCheckboxCheck(i, $event)" @change="handleCheckboxCheck(i, $event)"
@@ -44,8 +45,8 @@
<i class="fa fa-question-circle-o" /> <i class="fa fa-question-circle-o" />
</el-tooltip> </el-tooltip>
</el-checkbox> </el-checkbox>
</div>
</el-checkbox-group> </el-checkbox-group>
</el-form-item> </el-form-item>
<Dialog <Dialog
@@ -108,6 +109,7 @@ export default {
}, },
data() { data() {
const vm = this const vm = this
const virtual = '@VIRTUAL'
const choices = [ const choices = [
{ {
label: AccountLabelMapper[AllAccount], label: AccountLabelMapper[AllAccount],
@@ -119,6 +121,20 @@ export default {
value: SpecAccount, value: SpecAccount,
tip: this.$t('SpecAccountTip') tip: this.$t('SpecAccountTip')
}, },
{
label: this.$t('VirtualAccounts'),
value: virtual,
tip: this.$t('VirtualAccountHelpMsg'),
disabled: !this.showVirtualAccount
}
]
return {
ALL: AllAccount,
SPEC: SpecAccount,
VIRTUAL: virtual,
showTemplateDialog: false,
choices: choices,
virtualAccounts: [
{ {
label: AccountLabelMapper[ManualAccount], label: AccountLabelMapper[ManualAccount],
value: ManualAccount, value: ManualAccount,
@@ -134,15 +150,8 @@ export default {
value: AnonymousAccount, value: AnonymousAccount,
tip: this.$t('AnonymousAccountTip') tip: this.$t('AnonymousAccountTip')
} }
] ],
return { virtualAccountsNames: [ManualAccount, SameAccount, AnonymousAccount],
ALL: AllAccount,
SPEC: SpecAccount,
showTemplateDialog: false,
choices: choices.filter(i => {
const isVirtualAccount = [SameAccount, ManualAccount, AnonymousAccount].includes(i.value)
return !(isVirtualAccount && !this.showVirtualAccount)
}),
choicesSelected: [this.ALL], choicesSelected: [this.ALL],
specAccountsInput: [], specAccountsInput: [],
specAccountsTemplate: [], specAccountsTemplate: [],
@@ -212,6 +221,17 @@ export default {
} }
} }
}, },
computed: {
showVirtualAccountCheckbox() {
if (!this.showVirtualAccount) {
return false
}
const hasVirtual = this.choicesSelected.filter(i => {
return i && i.startsWith('@') && i !== '@ALL' && i !== '@SPEC'
})
return hasVirtual.length > 0
}
},
mounted() { mounted() {
this.initDefaultChoice() this.initDefaultChoice()
setTimeout(() => { setTimeout(() => {
@@ -225,6 +245,8 @@ export default {
methods: { methods: {
initDefaultChoice() { initDefaultChoice() {
const choicesSelected = this.value.filter(i => i.startsWith('@')) const choicesSelected = this.value.filter(i => i.startsWith('@'))
// 是否添加特定账号选择
const specAccountsInput = this.value.filter(i => !i.startsWith('@')) const specAccountsInput = this.value.filter(i => !i.startsWith('@'))
if (specAccountsInput.length > 0 && !choicesSelected.includes(this.ALL)) { if (specAccountsInput.length > 0 && !choicesSelected.includes(this.ALL)) {
choicesSelected.push(this.SPEC) choicesSelected.push(this.SPEC)
@@ -233,6 +255,16 @@ export default {
if (this.value.indexOf(this.SPEC) > -1) { if (this.value.indexOf(this.SPEC) > -1) {
this.showSpecAccounts = true this.showSpecAccounts = true
} }
// 是否添加虚拟账号选择
const hasVirtual = this.value.filter(i => {
return i && i.startsWith('@') && i !== '@ALL' && i !== '@SPEC'
})
if (hasVirtual.length > 0 && !choicesSelected.includes(this.VIRTUAL)) {
this.choicesSelected = [...choicesSelected, this.VIRTUAL]
}
// 如果没有就设置 ALL
if (choicesSelected.length === 0) { if (choicesSelected.length === 0) {
choicesSelected.push(this.ALL) choicesSelected.push(this.ALL)
} }
@@ -260,9 +292,12 @@ export default {
} }
if (item.value === this.ALL) { if (item.value === this.ALL) {
this.choicesSelected = this.choicesSelected.filter(i => i !== this.SPEC) this.choicesSelected = this.choicesSelected.filter(i => i !== this.SPEC)
} } else if (item.value === this.SPEC) {
if (item.value === this.SPEC) {
this.choicesSelected = this.choicesSelected.filter(i => i !== this.ALL) this.choicesSelected = this.choicesSelected.filter(i => i !== this.ALL)
} else if (item.value === this.VIRTUAL) {
if (!checked) {
this.choicesSelected = this.choicesSelected.filter(i => !this.virtualAccountsNames.includes(i))
}
} }
this.outputValue() this.outputValue()
}, },
@@ -290,13 +325,9 @@ export default {
.spec-accounts { .spec-accounts {
::v-deep { ::v-deep {
.el-select { .filter-field {
width: 100%; width: 100%;
margin-bottom: 3px; margin-bottom: 3px !important;
}
.help-block {
display: block !important;
} }
} }
} }
@@ -307,23 +338,19 @@ export default {
} }
.group-title { .group-title {
font-size: 12px; font-size: 13px;
color: var(--color-text-secondary); color: var(--color-text-secondary);
//border-bottom: dashed 1px var(--color-border);
margin-top: 5px;
font-weight: 500;
}
.account-content {
::v-deep {
.el-form-item__content {
width: 90% !important;
}
}
} }
//::v-deep .el-checkbox-group {
// display: grid;
// grid-template-columns: repeat(3, 1fr);
//}
//
//::v-deep .el-checkbox-group label:nth-child(1),
//::v-deep .el-checkbox-group label:nth-child(2) {
// grid-row: 1 / 2;
//}
//
//::v-deep .el-checkbox-group label:nth-child(3),
//::v-deep .el-checkbox-group label:nth-child(4),
//::v-deep .el-checkbox-group label:nth-child(5) {
// grid-row: 2 / 3;
//}
</style> </style>

View File

@@ -1,263 +0,0 @@
<template>
<el-form @submit.native.prevent>
<el-form-item>
<el-radio-group v-model="choiceSelected" @input="handleRadioCheck">
<el-radio
v-for="(i) in choices"
:key="i.label"
:label="i.value"
>
{{ i.label }}
<el-tooltip :content="i.tip" :open-delay="500" placement="top">
<i class="fa fa-question-circle-o" />
</el-tooltip>
</el-radio>
</el-radio-group>
<div v-if="showSpecAccounts" class="spec-accounts">
<TagInput
:autocomplete="autocomplete"
:tag-type="getTagType"
:value="specAccountsInput"
@change="handleTagChange"
/>
<span v-if="showAddTemplate">
<el-button size="mini" type="primary" @click="showTemplateDialog=true">
{{ $t('TemplateAdd') }}
</el-button>
<span class="help-block" style="display: inline">
{{ addTemplateHelpText }}
</span>
</span>
</div>
</el-form-item>
<Dialog
v-if="showTemplateDialog"
:title="$tc('AccountTemplate')"
:visible.sync="showTemplateDialog"
@cancel="handleAccountTemplateCancel"
@confirm="handleAccountTemplateConfirm"
>
<ListTable ref="templateTable" v-bind="accountTemplateTable" />
</Dialog>
</el-form>
</template>
<script>
import { TagInput } from '@/components/Form/FormFields'
import { AccountLabelMapper, AllAccount, SpecAccount } from '@/views/perms/const'
import ListTable from '@/components/Table/ListTable'
import Dialog from '@/components/Dialog'
export default {
components: {
TagInput,
ListTable,
Dialog
},
props: {
value: {
type: [Array, String],
default: () => []
},
assets: {
type: [Array],
default: () => []
},
nodes: {
type: [Array],
default: () => []
},
oid: {
type: String,
default: ''
},
showAddTemplate: {
type: Boolean,
default: true
},
addTemplateHelpText: {
type: String,
default() {
return this.$t('TemplateHelpText')
}
}
},
data() {
const vm = this
const choices = [
{
label: AccountLabelMapper[AllAccount],
value: AllAccount,
tip: this.$t('AllAccountTip')
},
{
label: AccountLabelMapper[SpecAccount],
value: SpecAccount,
tip: this.$t('SpecAccountTip')
}
]
return {
ALL: AllAccount,
SPEC: SpecAccount,
showTemplateDialog: false,
choices: choices,
choiceSelected: this.ALL,
specAccountsInput: [],
specAccountsTemplate: [],
showSpecAccounts: false,
getTagType: (tag) => {
if (vm.specAccountsTemplate.filter(i => i.username === tag).length > 0) {
return 'primary'
} else {
return 'info'
}
},
accountTemplateTable: {
tableConfig: {
url: '/api/v1/accounts/account-templates/',
columns: [
'name', 'username', 'has_secret', 'comment'
],
columnsMeta: {
name: {
formatterArgs: {
openInNewPage: true,
getRoute({ row, col, cellValue }) {
return {
name: 'AccountTemplateDetail',
params: {
id: row.id
}
}
}
}
},
has_secret: {
formatterArgs: {
showFalse: false
}
},
actions: {
has: false
}
}
},
headerActions: {
hasLeftActions: false,
hasImport: false,
hasExport: false
}
},
autocomplete: (query, cb) => {
const data = {
username: query,
assets: this.assets.slice(0, 20),
nodes: this.nodes.slice(0, 20).map(item => {
return typeof item === 'object' ? item.pk : item
})
}
this.$axios.post(
'/api/v1/accounts/accounts/username-suggestions/',
data, { params: { oid: this.oid }}
).then(res => {
if (!res) res = []
const data = res
.filter(item => vm.value.indexOf(item) === -1)
.map(v => ({ value: v, label: v }))
cb(data)
})
}
}
},
mounted() {
this.initDefaultChoice()
},
methods: {
initDefaultChoice() {
this.choiceSelected = this.value.indexOf(this.ALL) >= 0 ? this.ALL : this.SPEC
this.specAccountsInput = this.value.filter(i => !i.startsWith('@'))
if (this.choiceSelected === this.SPEC) {
this.showSpecAccounts = true
}
},
handleAccountTemplateCancel() {
this.showTemplateDialog = false
},
handleAccountTemplateConfirm() {
this.specAccountsTemplate = this.$refs.templateTable.selectedRows
const added = this.specAccountsTemplate.map(i => i.username)
this.specAccountsInput = this.specAccountsInput.filter(i => !added.includes(i)).concat(added)
this.outputValue()
setTimeout(() => {
this.showTemplateDialog = false
this.outputValue()
}, 100)
},
handleRadioCheck(item) {
this.showSpecAccounts = item === this.SPEC
this.outputValue()
},
handleTagChange(val) {
this.specAccountsInput = val
this.outputValue()
},
outputValue() {
let choicesSelected = []
if (this.choiceSelected === this.ALL) {
choicesSelected = [this.ALL]
} else {
const templateIds = this.specAccountsTemplate.map(i => `%${i.id}`)
choicesSelected = [...this.specAccountsInput, ...templateIds]
}
this.$emit('input', choicesSelected)
this.$emit('change', choicesSelected)
}
}
}
</script>
<style lang="scss" scoped>
.select ::v-deep .el-input.el-input--suffix {
width: 100px
}
.spec-accounts {
::v-deep {
.el-select {
width: 100%;
margin-bottom: 3px;
}
.help-block {
display: block !important;
}
}
}
.help-text {
font-size: 12px;
color: #999999;
}
.group-title {
font-size: 12px;
color: var(--color-text-secondary);
}
//::v-deep .el-checkbox-group {
// display: grid;
// grid-template-columns: repeat(3, 1fr);
//}
//
//::v-deep .el-checkbox-group label:nth-child(1),
//::v-deep .el-checkbox-group label:nth-child(2) {
// grid-row: 1 / 2;
//}
//
//::v-deep .el-checkbox-group label:nth-child(3),
//::v-deep .el-checkbox-group label:nth-child(4),
//::v-deep .el-checkbox-group label:nth-child(5) {
// grid-row: 2 / 3;
//}
</style>

View File

@@ -1,106 +0,0 @@
<template>
<el-form @submit.native.prevent>
<el-form-item>
<el-checkbox-group v-model="choicesSelected">
<el-checkbox
v-for="(i) in choices"
:key="i.label"
:label="i.value"
@change="handleCheckboxCheck(i, $event)"
>
{{ i.label }}
<el-tooltip :content="i.tip" :open-delay="500" placement="top">
<i class="fa fa-question-circle-o" />
</el-tooltip>
</el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-form>
</template>
<script>
import { AccountLabelMapper, AnonymousAccount, ManualAccount, SameAccount } from '@/views/perms/const'
export default {
components: {},
props: {
value: {
type: [Array, String],
default: () => []
}
},
data() {
const choices = [
{
label: AccountLabelMapper[ManualAccount],
value: ManualAccount,
tip: this.$t('ManualAccountTip')
},
{
label: AccountLabelMapper[SameAccount],
value: SameAccount,
tip: this.$t('SameAccountTip')
},
{
label: AccountLabelMapper[AnonymousAccount],
value: AnonymousAccount,
tip: this.$t('AnonymousAccountTip')
}
]
return {
choices: choices,
choicesSelected: []
}
},
mounted() {
this.initDefaultChoice()
},
methods: {
initDefaultChoice() {
this.choicesSelected = this.value.filter(i => {
return i.startsWith('@')
}).filter(i => {
return !['@ALL', '@SPEC'].includes(i)
})
},
handleCheckboxCheck() {
this.outputValue()
},
outputValue() {
console.log('outputValue', this.choicesSelected)
this.$emit('input', this.choicesSelected)
this.$emit('change', this.choicesSelected)
}
}
}
</script>
<style lang="scss" scoped>
.select ::v-deep .el-input.el-input--suffix {
width: 100px
}
.spec-accounts {
::v-deep {
.el-select {
width: 100%;
margin-bottom: 3px;
}
.help-block {
display: block !important;
}
}
}
.help-text {
font-size: 12px;
color: #999999;
}
.group-title {
font-size: 12px;
color: var(--color-text-secondary);
}
</style>