Browse Source

2026-03-31

角色管理页面【权限授权】对话框样式优化
master
fengyuan_yang 3 weeks ago
parent
commit
e91a950c1a
  1. 168
      src/views/modules/sys/role-add-or-update.vue

168
src/views/modules/sys/role-add-or-update.vue

@ -1,30 +1,56 @@
<template> <template>
<el-dialog class="sl-menu-item" width="500px" :title="!dataForm.id ? buttons.add :buttons.edit " :close-on-click-modal="false" :visible.sync="visible">
<el-dialog class="sl-menu-item" width="900px" :title="!dataForm.id ? buttons.add :buttons.edit " :close-on-click-modal="false" :visible.sync="visible">
<el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmit()" label-width="80px"> <el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmit()" label-width="80px">
<el-form-item :label="buttons.roleName||'角色名称'" prop="roleName">
<el-input style="width: 150px" v-model="dataForm.roleName"></el-input>
</el-form-item>
<el-form-item :label="buttons.remark||'备注'" prop="remark">
<el-input style="width: 150px" v-model="dataForm.remark" placeholder="备注"></el-input>
</el-form-item>
<el-row>
<el-col :span="12">
<el-form-item :label="buttons.roleName||'角色名称'" prop="roleName">
<el-input style="width: 100%" v-model="dataForm.roleName"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="buttons.remark||'备注'" prop="remark">
<el-input style="width: 100%" v-model="dataForm.remark" placeholder="备注"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-form-item size="mini" :label="buttons.authorize||'授权'"> <el-form-item size="mini" :label="buttons.authorize||'授权'">
<el-row> <el-row>
<el-col class="down-tree" :span="14">
<el-col :span="24">
<el-input
placeholder="输入关键字进行过滤"
v-model="filterText"
clearable
style="margin-bottom: 10px; width: 100%;">
</el-input>
</el-col>
</el-row>
<el-row>
<el-col class="down-tree" :span="24">
<el-tree <el-tree
:data="menuList" :data="menuList"
:props="menuListTreeProps" :props="menuListTreeProps"
node-key="menuId" node-key="menuId"
ref="menuListTree" ref="menuListTree"
:default-expand-all="false" :default-expand-all="false"
:filter-node-method="filterNode"
@check="handleTreeCheck"
show-checkbox> show-checkbox>
<span class="custom-tree-node" slot-scope="{ node, data }" style="display: flex; align-items: center; width: 100%;">
<span style="margin-right: 20px; white-space: nowrap;">{{ node.label }}</span>
<span v-if="data.buttonList && data.buttonList.length > 0" style="flex: 1; overflow-x: auto;">
<el-checkbox-group v-model="data.checkedButtons" @change="handleButtonChange(data)" @click.native.stop style="display: inline-block;">
<el-checkbox v-for="btn in data.buttonList" :key="btn.menuId" :label="Number(btn.menuId)">{{ btn.name }}</el-checkbox>
</el-checkbox-group>
</span>
</span>
</el-tree> </el-tree>
</el-col> </el-col>
</el-row> </el-row>
</el-form-item> </el-form-item>
</el-form> </el-form>
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
<el-button @click="visible = false">{{ buttons.close || '关闭' }}</el-button>
<el-button type="primary" @click="dataFormSubmit()">{{ buttons.submit || '确定' }}</el-button> <el-button type="primary" @click="dataFormSubmit()">{{ buttons.submit || '确定' }}</el-button>
<el-button type="primary" @click="visible = false">{{ buttons.close || '关闭' }}</el-button>
</span> </span>
</el-dialog> </el-dialog>
</template> </template>
@ -38,6 +64,7 @@ export default {
data() { data() {
return { return {
visible: false, visible: false,
filterText: '',
menuList: [], menuList: [],
menuListTreeProps: { menuListTreeProps: {
label: 'name', label: 'name',
@ -73,19 +100,93 @@ export default {
tempKey: -666666 // key, tree. # tempKey: -666666 // key, tree. #
} }
}, },
watch: {
filterText(val) {
this.$refs.menuListTree.filter(val);
}
},
methods: { methods: {
filterNode(value, data) {
if (!value) return true;
let matchButton = data.buttonList && data.buttonList.some(btn => btn.name.indexOf(value) !== -1);
return data.name.indexOf(value) !== -1 || matchButton;
},
processMenuTree(treeList) {
for (let i = 0; i < treeList.length; i++) {
let node = treeList[i]
this.$set(node, 'buttonList', [])
this.$set(node, 'checkedButtons', [])
if (node.children && node.children.length > 0) {
let normalChildren = []
for (let child of node.children) {
if (child.specificType === 'button' || child.type === 2) {
node.buttonList.push(child)
} else {
normalChildren.push(child)
}
}
node.children = normalChildren
this.processMenuTree(node.children)
}
}
},
populateCheckedButtons(treeList, checkedIds, treeCheckedKeys) {
for (let node of treeList) {
if (checkedIds.includes(Number(node.menuId))) {
if (!node.children || node.children.length === 0) {
treeCheckedKeys.push(Number(node.menuId))
}
}
if (node.buttonList && node.buttonList.length > 0) {
node.checkedButtons = node.buttonList
.filter(btn => checkedIds.includes(Number(btn.menuId)))
.map(btn => Number(btn.menuId))
}
if (node.children) {
this.populateCheckedButtons(node.children, checkedIds, treeCheckedKeys)
}
}
},
handleTreeCheck(data, checkedInfo) {
let isChecked = checkedInfo.checkedKeys.includes(data.menuId)
this.toggleButtons(data, isChecked)
},
toggleButtons(node, isChecked) {
if (isChecked) {
node.checkedButtons = node.buttonList ? node.buttonList.map(b => Number(b.menuId)) : []
} else {
node.checkedButtons = []
}
if (node.children) {
node.children.forEach(child => this.toggleButtons(child, isChecked))
}
},
handleButtonChange(data) {
if (data.checkedButtons.length > 0) {
this.$refs.menuListTree.setChecked(data.menuId, true, false)
}
},
getAllCheckedButtons(treeList, result) {
for (let node of treeList) {
if (node.checkedButtons && node.checkedButtons.length > 0) {
result.push(...node.checkedButtons)
}
if (node.children) {
this.getAllCheckedButtons(node.children, result)
}
}
},
init (row) { init (row) {
let id = row ? row.roleId : 0 let id = row ? row.roleId : 0
// this.getFunctionButtonList()
this.dataForm.id = id || 0 this.dataForm.id = id || 0
this.$http({ this.$http({
url: this.$http.adornUrl('/sys/menu/list'), url: this.$http.adornUrl('/sys/menu/list'),
method: 'get', method: 'get',
params: this.$http.adornParams() params: this.$http.adornParams()
}).then(({data}) => { }).then(({data}) => {
this.menuList = treeDataTranslate(data, 'menuId')
let treeData = treeDataTranslate(data, 'menuId')
this.processMenuTree(treeData)
this.menuList = treeData
}).then(() => { }).then(() => {
this.visible = true this.visible = true
this.$nextTick(() => { this.$nextTick(() => {
@ -107,10 +208,10 @@ export default {
data.role.menuIdList.splice(idx, data.role.menuIdList.length - idx) data.role.menuIdList.splice(idx, data.role.menuIdList.length - idx)
} }
let x1 = data.role.menuIdList.map(Number) let x1 = data.role.menuIdList.map(Number)
let treeCheckedKeys = []
this.populateCheckedButtons(this.menuList, x1, treeCheckedKeys)
this.$nextTick(() => { this.$nextTick(() => {
for (let x1Element of x1) {
this.$refs.menuListTree.setChecked(x1Element, true, false)
}
this.$refs.menuListTree.setCheckedKeys(treeCheckedKeys)
}) })
} }
}) })
@ -122,6 +223,14 @@ export default {
dataFormSubmit () { dataFormSubmit () {
this.$refs['dataForm'].validate((valid) => { this.$refs['dataForm'].validate((valid) => {
if (valid) { if (valid) {
let buttonIds = []
this.getAllCheckedButtons(this.menuList, buttonIds)
let treeKeys = this.$refs.menuListTree.getCheckedKeys()
let halfKeys = this.$refs.menuListTree.getHalfCheckedKeys()
let finalMenuIds = [...new Set([...treeKeys, ...halfKeys, ...buttonIds])]
if (this.tempKey) {
finalMenuIds.push(this.tempKey)
}
this.$http({ this.$http({
url: this.$http.adornUrl(`/sys/role/${!this.dataForm.id ? 'save' : 'update'}`), url: this.$http.adornUrl(`/sys/role/${!this.dataForm.id ? 'save' : 'update'}`),
method: 'post', method: 'post',
@ -129,7 +238,7 @@ export default {
'roleId': this.dataForm.id || undefined, 'roleId': this.dataForm.id || undefined,
'roleName': this.dataForm.roleName, 'roleName': this.dataForm.roleName,
'remark': this.dataForm.remark, 'remark': this.dataForm.remark,
'menuIdList': [].concat(this.$refs.menuListTree.getCheckedKeys(), [this.tempKey], this.$refs.menuListTree.getHalfCheckedKeys())
'menuIdList': finalMenuIds
}) })
}).then(({data}) => { }).then(({data}) => {
if (data && data.code === 0) { if (data && data.code === 0) {
@ -165,8 +274,29 @@ export default {
<style lang="scss"> <style lang="scss">
.down-tree { .down-tree {
height: 300px;
height: 400px;
display: block; display: block;
overflow-y: scroll;
overflow-y: auto;
border: 1px solid #dcdfe6;
border-radius: 4px;
padding: 10px;
background-color: #fff;
}
.custom-tree-node {
.el-checkbox {
margin-right: 15px;
}
.el-checkbox__label {
padding-left: 5px;
}
}
/* 优化树形节点高度和样式 */
.el-tree-node__content {
height: auto;
min-height: 36px;
padding-top: 4px;
padding-bottom: 4px;
} }
</style> </style>
Loading…
Cancel
Save