diff --git a/ruoyi-ui/src/views/childRoom/LeftMenu.vue b/ruoyi-ui/src/views/childRoom/LeftMenu.vue index 749ce85..fb8a2d5 100644 --- a/ruoyi-ui/src/views/childRoom/LeftMenu.vue +++ b/ruoyi-ui/src/views/childRoom/LeftMenu.vue @@ -113,6 +113,11 @@ export default { type: Array, default: () => [] }, + /** 与 index 中 defaultMenuItems 一致,用于从选择图标中恢复内置项时使用稳定 id */ + defaultMenuItems: { + type: Array, + default: () => [] + }, position: { type: String, default: 'left' @@ -175,18 +180,22 @@ export default { }, confirmAddIcons(selectedItems) { + const defaults = this.defaultMenuItems || [] selectedItems.forEach(item => { - const newId = Date.now().toString() + Math.random().toString(36).substr(2, 9) - const newMenuItem = { - id: newId, - name: item.name, - icon: item.icon, - action: item.id + const preset = defaults.find(d => d.id === item.id) + if (preset) { + this.localMenuItems.push({ ...preset }) + } else { + const newId = Date.now().toString() + Math.random().toString(36).substr(2, 9) + this.localMenuItems.push({ + id: newId, + name: item.name, + icon: item.icon, + action: item.id + }) } - this.localMenuItems.push(newMenuItem) }) this.$emit('update:menuItems', this.localMenuItems) - this.$emit('add-items', selectedItems) }, quickDelete(item) { diff --git a/ruoyi-ui/src/views/childRoom/index.vue b/ruoyi-ui/src/views/childRoom/index.vue index 299f23d..f7ad240 100644 --- a/ruoyi-ui/src/views/childRoom/index.vue +++ b/ruoyi-ui/src/views/childRoom/index.vue @@ -180,14 +180,14 @@ :menu-items="menuItems" :active-menu="activeMenu" :is-edit-mode="isIconEditMode" - :available-icons="topNavItems" + :available-icons="iconPickerCatalog" + :default-menu-items="defaultMenuItems" :position="menuPosition" @hide="hideMenu" @select="selectMenu" @menu-action="handleMenuAction" @update:menu-items="updateMenuItems" @drag-end="handleMenuDragEnd" - @add-items="handleAddMenuItems" @delete="handleDeleteMenuItem" @save-menu-items="handleSaveMenuItems" @exit-icon-edit="exitIconEdit" @@ -1071,6 +1071,13 @@ export default { if (editor && Number(editor.userId) !== Number(myId)) ids.push(Number(rid)); }); return ids; + }, + /** 左侧「选择图标」:全部默认菜单样式 + 不与默认 id 重复的扩展项 */ + iconPickerCatalog() { + const defs = this.defaultMenuItems || []; + const seen = new Set(defs.map(d => d.id)); + const extras = (this.topNavItems || []).filter(t => !seen.has(t.id)); + return [...defs, ...extras]; } }, mounted() { @@ -3789,19 +3796,6 @@ export default { this.menuItems = newItems }, - handleAddMenuItems(selectedItems) { - selectedItems.forEach(item => { - const newId = Date.now().toString() + Math.random().toString(36).substr(2, 9) - const newMenuItem = { - id: newId, - name: item.name, - icon: item.icon, - action: item.id - } - this.menuItems.push(newMenuItem) - }) - }, - handleMenuAction(actionId) { const actionMap = { 'savePlan': () => this.savePlan(), @@ -4495,43 +4489,32 @@ export default { } }, - /** 加载当前用户的左侧菜单配置(登录且有过保存时生效) */ + /** 加载当前用户的左侧菜单配置(以数据库为准,不自动补回已删除的默认项) */ async loadUserMenuConfig() { try { const res = await getMenuConfig() const data = res && res.data if (!data) return - if (data.menuItems) { + if (data.menuItems != null && data.menuItems !== '') { let arr = [] try { arr = typeof data.menuItems === 'string' ? JSON.parse(data.menuItems) : data.menuItems - } catch (e) { /* 解析失败保留默认 */ } - if (Array.isArray(arr) && arr.length > 0) { - const defaultMap = (this.defaultMenuItems || []).reduce((m, it) => { m[it.id] = it; return m }, {}) - const savedIds = new Set(arr.map(i => i.id)) - // 合并缺失的默认项(如新增的4T),按 defaultMenuItems 顺序插入 - const defaultOrder = (this.defaultMenuItems || []).map(d => d.id) - defaultOrder.forEach(defId => { - if (!savedIds.has(defId) && defaultMap[defId]) { - const insertAfterId = defaultOrder[defaultOrder.indexOf(defId) - 1] - const refIdx = insertAfterId ? arr.findIndex(i => i.id === insertAfterId) : -1 - const insertIdx = refIdx >= 0 ? refIdx + 1 : 0 - arr.splice(insertIdx, 0, { ...defaultMap[defId] }) - savedIds.add(defId) - } - }) - this.menuItems = arr.map(item => { - const def = defaultMap[item.id] - if (def) return { ...item, name: def.name, icon: def.icon, action: def.action } - return item - }) + } catch (e) { + return } + if (!Array.isArray(arr)) return + const defaultMap = (this.defaultMenuItems || []).reduce((m, it) => { m[it.id] = it; return m }, {}) + this.menuItems = arr.map(item => { + const def = defaultMap[item.id] + if (def) return { ...item, name: def.name, icon: def.icon, action: def.action } + return item + }) } if (data.position && ['left', 'top', 'bottom'].includes(data.position)) { this.menuPosition = data.position } } catch (e) { - // 未登录或接口失败则使用默认菜单,不提示 + // 未登录或接口失败则使用 mounted 中的默认菜单,不提示 } }, diff --git a/ruoyi-ui/src/views/dialogs/IconSelectDialog.vue b/ruoyi-ui/src/views/dialogs/IconSelectDialog.vue index 459dde0..e307dbc 100644 --- a/ruoyi-ui/src/views/dialogs/IconSelectDialog.vue +++ b/ruoyi-ui/src/views/dialogs/IconSelectDialog.vue @@ -16,7 +16,8 @@ :class="{ selected: selectedIcons.includes(item.id) }" @click="toggleIcon(item)" > - + + {{ item.name }}
@@ -72,6 +73,9 @@ export default { } }, methods: { + isSvgIcon(icon) { + return icon && typeof icon === 'string' && !icon.startsWith('el-icon-') + }, toggleIcon(item) { const index = this.selectedIcons.indexOf(item.id) if (index > -1) { @@ -143,15 +147,23 @@ export default { background: rgba(22, 93, 255, 0.1); } -.icon-item i { +.icon-item i, +.icon-item .icon-select-svg { font-size: 28px; color: #555; margin-bottom: 8px; transition: color 0.3s; } +.icon-item .icon-select-svg { + width: 28px; + height: 28px; +} + .icon-item:hover i, -.icon-item.selected i { +.icon-item:hover .icon-select-svg, +.icon-item.selected i, +.icon-item.selected .icon-select-svg { color: #165dff; }