zzw
昨天 781b8b3e072a4e00b1cee56f961280c753cbb460
emergency-repair-web/src/views/system/MenuManage.vue
@@ -44,7 +44,9 @@
    <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>
@@ -63,7 +65,7 @@
    </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>
@@ -89,7 +91,6 @@
      dialogVisible: false,
      saving: false,
      form: {},
      parent: null,
      rules: { name: [{ required: true, message: '请输入菜单名称', trigger: 'blur' }] },
      buttonDialogVisible: false,
      buttonSaving: false,
@@ -99,15 +100,25 @@
    }
  },
  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) {
@@ -131,10 +142,9 @@
      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',
@@ -146,8 +156,7 @@
      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() {
@@ -158,6 +167,7 @@
          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
@@ -172,6 +182,27 @@
        }).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))