Compare commits

...

1 Commits

Author SHA1 Message Date
Ewall555
d79435a96c feat: Asset permossion add account selection component and its dialog and button 2025-06-27 06:09:10 +00:00
2 changed files with 291 additions and 0 deletions

View File

@@ -0,0 +1,221 @@
<template>
<Dialog
:close-on-click-modal="false"
:title="$t('AssetAccount')"
custom-class="account-select-dialog"
top="2vh"
v-bind="$attrs"
width="1000px"
@cancel="handleCancel"
@close="handleClose"
@confirm="handleConfirm"
v-on="$listeners"
>
<AssetTreeTable
ref="ListPage"
:header-actions="headerActions"
:node-url="baseNodeUrl"
:sync-select-to-url="false"
:table-config="tableConfig"
:tree-setting="iTreeSetting"
:tree-url="`${baseNodeUrl}children/tree/`"
:url="baseUrl"
class="tree-table"
v-bind="$attrs"
@loaded="handleTableLoaded"
v-on="$listeners"
/>
</Dialog>
</template>
<script>
import AssetTreeTable from '@/components/Apps/AssetTreeTable/index.vue'
import Dialog from '@/components/Dialog/index.vue'
export default {
componentName: 'AssetSelectDialog',
components: { AssetTreeTable, Dialog },
props: {
baseUrl: {
type: String,
default: '/api/v1/accounts/accounts/'
},
baseNodeUrl: {
type: String,
default: '/api/v1/assets/nodes/'
},
value: {
type: Array,
default: () => []
},
canSelect: {
type: Function,
default(row, index) {
return true
}
},
disabled: {
type: [Boolean, Function],
default: false
},
treeSetting: {
type: Object,
default: () => ({})
}
},
data() {
const vm = this
return {
isLoaded: false,
dialogVisible: false,
rowSelected: _.cloneDeep(this.value) || [],
rowsAdd: [],
tableConfig: {
url: this.baseUrl,
hasTree: true,
canSelect: this.canSelect,
columns: [
{
prop: 'name',
label: this.$t('Name'),
sortable: true
},
{
prop: 'username',
label: this.$t('Username'),
sortable: 'custom'
},
{
prop: 'asset.name',
label: this.$t('Asset'),
sortable: 'custom',
formatter: function(row) {
return row.asset.name
}
},
{
prop: 'asset.platform.name',
label: this.$t('Platform'),
sortable: true,
formatter: function(row) {
return row.asset.platform.name
}
},
{
prop: 'secret_type.label',
label: this.$t('SecretType'),
sortable: true,
formatter: function(row) {
return row.secret_type.label
}
},
{
prop: 'actions',
has: false
}
],
listeners: {
'toggle-row-selection': (isSelected, row) => {
if (isSelected) {
vm.addRowToSelect(row)
} else {
vm.removeRowFromSelect(row)
}
}
}
// theRowDefaultIsSelected: (row) => {
// return this.value.indexOf(row.id) > -1
// }
},
headerActions: {
hasLeftActions: false,
hasRightActions: false,
hasLabelSearch: true,
searchConfig: {
getUrlQuery: false
}
}
}
},
computed: {
iTreeSetting() {
return { ...this.treeSetting, selectSyncToRoute: false }
}
},
methods: {
handleTableLoaded() {
this.isLoaded = true
},
handleClose() {
this.$refs.ListPage.$refs.TreeList.componentKey += 1
},
handleConfirm() {
this.$emit('confirm', this.rowSelected, this.rowsAdd)
if (this.rowSelected.length > 0) {
this.handleClose()
}
},
handleCancel() {
this.$emit('cancel')
this.handleClose()
},
addRowToSelect(row) {
this.rowSelected.push(row.username)
this.rowsAdd.push(row)
// const selectValueIndex = this.rowSelected.indexOf(row.id)
// if (selectValueIndex === -1) {
// this.rowSelected.push(row.id)
// this.rowsAdd.push(row)
// }
},
removeRowFromSelect(row) {
const selectValueIndex = this.rowSelected.indexOf(row.username)
this.rowSelected.splice(selectValueIndex, 1)
// const selectValueIndex = this.rowSelected.indexOf(row.id)
// if (selectValueIndex > -1) {
// this.rowSelected.splice(selectValueIndex, 1)
// }
}
}
}
</script>
<style lang="scss" scoped>
.page ::v-deep .page-heading {
display: none;
}
.el-dialog__wrapper ::v-deep .el-dialog__body {
padding: 0 0 0 3px;
.tree-table {
.search {
}
.left {
padding: 5px;
}
.right {
min-height: 500px;
overflow: auto;
}
.mini {
padding-top: 8px;
}
.transition-box {
padding: 10px 5px;
}
}
}
.page ::v-deep .treebox .ztree {
}
.account-select-dialog ::v-deep .el-icon-circle-check {
display: none;
}
</style>

View File

@@ -27,8 +27,14 @@
<el-button size="mini" type="primary" @click="showTemplateDialog=true">
{{ $t('TemplateAdd') }}
</el-button>
<span v-if="showAddAccount">
<el-button size="mini" type="primary" @click="showAccountSelectDialog=true">
{{ $t('AssetAccount') }}
</el-button>
</span>
<span class="help-block">
{{ addTemplateHelpText }}
{{ addAccountSelectHelpText }}
</span>
</span>
</div>
@@ -73,6 +79,15 @@
>
<ListTable ref="templateTable" v-bind="accountTemplateTable" />
</Dialog>
<AccountSelectDialog
v-if="showAccountSelectDialog"
:value="value"
:visible.sync="showAccountSelectDialog"
v-bind="$attrs"
@cancel="handleCancel"
@confirm="handleConfirm"
v-on="$listeners"
/>
</el-form>
</template>
@@ -92,9 +107,11 @@ import {
} from '@/views/perms/const'
import ListTable from '@/components/Table/ListTable'
import Dialog from '@/components/Dialog'
import AccountSelectDialog from '@/components/Apps/AccountSelect/dialog.vue'
export default {
components: {
AccountSelectDialog,
TagInput,
ListTable,
Dialog
@@ -129,6 +146,16 @@ export default {
default() {
return this.$t('TemplateHelpText')
}
},
addAccountSelectHelpText: {
type: String,
default() {
return this.$t('AccountSelectHelpText')
}
},
showAddAccount: {
type: Boolean,
default: true
}
},
data() {
@@ -140,6 +167,7 @@ export default {
VIRTUAL: virtual,
EXCLUDE: NotAccount,
showTemplateDialog: false,
showAccountSelectDialog: false,
realRadioSelected: this.ALL,
realChoices: realChoices,
virtualChecked: false,
@@ -280,6 +308,19 @@ export default {
this.$emit('input', choicesSelected)
this.$emit('change', choicesSelected)
},
handleConfirm(valueSelected, rowsAdd) {
if (valueSelected === undefined) { return }
const newUsernames = [...new Set(rowsAdd.map(row => row.username))]
this.specAccountsInput = [...new Set([...this.specAccountsInput, ...newUsernames])]
this.outputValue()
setTimeout(() => {
this.showAccountSelectDialog = false
this.outputValue()
}, 100)
},
handleCancel() {
this.showAccountSelectDialog = false
}
}
}
@@ -333,4 +374,33 @@ export default {
}
}
.el-dialog__wrapper ::v-deep .el-dialog__body {
padding: 0 0 0 3px;
.tree-table {
.left {
padding: 5px 0;
.ztree {
height: 100%;
}
}
.right {
.transition-box {
padding-left: 0;
}
}
.mini {
padding-top: 8px;
width: 1px;
}
.transition-box {
padding: 10px 5px;
}
}
}
</style>