| | |
| | | |
| | | <el-dialog :title="form.id ? '编辑菜单' : '新增菜单'" :visible.sync="dialogVisible" width="640px" append-to-body> |
| | | <el-form ref="form" :model="form" :rules="rules" label-width="105px"> |
| | | <el-form-item label="上级菜单"><el-input :value="parentName" readonly></el-input></el-form-item> |
| | | <el-form-item label="上级菜单"> |
| | | <el-cascader v-model="form.pid" :options="parentOptions" :props="parentProps" :show-all-levels="false" filterable clearable placeholder="请选择上级菜单" style="width:100%"></el-cascader> |
| | | </el-form-item> |
| | | <el-form-item label="菜单类型"> |
| | | <el-radio-group v-model="form.menuType"> |
| | | <el-radio-button v-for="item in typeOptions" :key="item.value" :label="item.value">{{ item.label }}</el-radio-button> |
| | |
| | | </el-dialog> |
| | | |
| | | <el-dialog :title="'页面按钮配置 - ' + (buttonMenu.name || '')" :visible.sync="buttonDialogVisible" width="620px" append-to-body> |
| | | <p class="dialog-tip">下列按钮来自后端按钮目录,勾选后自动生成按钮类型菜单,可在菜单权限管理中授权给角色。</p> |
| | | <p class="dialog-tip">下列按钮来自后端按钮目录,勾选后自动生成按钮类型菜单,可在角色管理的权限设置中授权给角色。</p> |
| | | <el-checkbox-group v-model="buttonSelected" class="button-list"> |
| | | <el-checkbox v-for="item in buttonAvailable" :key="item.code" :label="item.code" class="button-item"> |
| | | <span class="button-name">{{ item.name }}</span> |
| | |
| | | dialogVisible: false, |
| | | saving: false, |
| | | form: {}, |
| | | parent: null, |
| | | rules: { name: [{ required: true, message: '请输入菜单名称', trigger: 'blur' }] }, |
| | | buttonDialogVisible: false, |
| | | buttonSaving: false, |
| | |
| | | } |
| | | }, |
| | | computed: { |
| | | parentName() { |
| | | if (!this.parent) return this.form.pid && this.form.pid !== 0 ? '上级菜单' : '无(一级菜单)' |
| | | return this.parent.name |
| | | parentProps() { |
| | | return { value: 'id', label: 'name', children: 'children', checkStrictly: true, emitPath: false, expandTrigger: 'hover' } |
| | | }, |
| | | selectedParent() { |
| | | const pid = String(this.form.pid || '0') |
| | | if (pid === '0') return null |
| | | return this.flat.find(item => String(item.id) === pid) || null |
| | | }, |
| | | parentOptions() { |
| | | const excluded = this.excludedMenuIds() |
| | | const allowedType = this.form.menuType === 2 ? 1 : 0 |
| | | const nodes = this.buildParentOptions(this.tree, allowedType, excluded) |
| | | return this.form.menuType === 2 ? nodes : [{ id: '0', name: '无(一级菜单)', children: nodes }] |
| | | }, |
| | | typeOptions() { |
| | | if (this.parent && this.parent.menuType === 1) { |
| | | if (this.selectedParent && this.selectedParent.menuType === 1) { |
| | | return [{ label: '按钮', value: 2 }] |
| | | } |
| | | if (this.parent && this.parent.menuType === 0) { |
| | | if (this.selectedParent && this.selectedParent.menuType === 0) { |
| | | return [{ label: '目录', value: 0 }, { label: '菜单', value: 1 }] |
| | | } |
| | | if (this.form.id && this.form.menuType === 2) { |
| | |
| | | return type === 2 ? 'warning' : type === 0 ? 'info' : 'primary' |
| | | }, |
| | | openCreate(parent) { |
| | | this.parent = parent || null |
| | | const menuType = parent && parent.menuType === 1 ? 2 : parent ? 1 : 0 |
| | | this.form = { |
| | | pid: parent ? parent.id : 0, |
| | | pid: parent ? String(parent.id) : '0', |
| | | name: '', |
| | | url: '', |
| | | icon: menuType === 2 ? '' : 'el-icon-tickets', |
| | |
| | | this.dialogVisible = true |
| | | }, |
| | | openEdit(row) { |
| | | this.parent = this.flat.find(item => item.id === row.pid) || null |
| | | this.form = { ...row } |
| | | this.form = { ...row, pid: row.pid == null || row.pid === 0 ? '0' : String(row.pid) } |
| | | this.dialogVisible = true |
| | | }, |
| | | save() { |
| | |
| | | return |
| | | } |
| | | const payload = { ...this.form } |
| | | if (payload.pid === null || payload.pid === undefined || payload.pid === '') payload.pid = '0' |
| | | if (payload.menuType === 2) { |
| | | payload.url = null |
| | | payload.icon = null |
| | |
| | | }).finally(() => { this.saving = false }) |
| | | }) |
| | | }, |
| | | excludedMenuIds() { |
| | | const excluded = new Set() |
| | | const walk = (nodes, underSelf) => { |
| | | ;(nodes || []).forEach(node => { |
| | | const next = underSelf || String(node.id) === String(this.form.id) |
| | | if (next) excluded.add(String(node.id)) |
| | | walk(node.children, next) |
| | | }) |
| | | } |
| | | walk(this.tree, false) |
| | | return excluded |
| | | }, |
| | | buildParentOptions(nodes, allowedType, excluded) { |
| | | return (nodes || []) |
| | | .filter(node => node.menuType === allowedType && !excluded.has(String(node.id))) |
| | | .map(node => ({ |
| | | id: String(node.id), |
| | | name: node.name, |
| | | children: this.buildParentOptions(node.children, allowedType, excluded) |
| | | })) |
| | | }, |
| | | remove(row) { |
| | | this.$confirm(`确定删除“${row.name}”吗?`, '删除确认', { type: 'warning' }) |
| | | .then(() => api.delete('/system/menu/' + row.id)) |