From ffe06be91f95ffd2459ebdb2f9130d1e38d53ea7 Mon Sep 17 00:00:00 2001
From: zzw <228544128@qq.com>
Date: 星期二, 06 十月 2026 18:32:34 +0800
Subject: [PATCH] fix: preserve manually edited menu names

---
 emergency-repair-web/src/views/system/MenuManage.vue |   55 +++++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 43 insertions(+), 12 deletions(-)

diff --git a/emergency-repair-web/src/views/system/MenuManage.vue b/emergency-repair-web/src/views/system/MenuManage.vue
index 9d1f4af..ec72216 100644
--- a/emergency-repair-web/src/views/system/MenuManage.vue
+++ b/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))

--
Gitblit v1.9.1