增加了tabs
This commit is contained in:
		
							parent
							
								
									ddf90424ba
								
							
						
					
					
						commit
						8430eb509c
					
				| @ -46,15 +46,14 @@ | |||||||
|   </el-aside> |   </el-aside> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script> | <script setup> | ||||||
| import { ref, computed, onMounted } from "vue"; | import { ref, computed, onMounted, defineEmits } from 'vue'; | ||||||
| import { useRouter, useRoute } from "vue-router"; | import { useRouter, useRoute } from 'vue-router'; | ||||||
| import { useAllDataStore } from "@/stores"; | import { useAllDataStore } from '@/stores'; | ||||||
| import { getAllMenus } from "@/api/menu"; | import { getAllMenus } from '@/api/menu'; | ||||||
|  | 
 | ||||||
|  | const emit = defineEmits(['menu-click']); | ||||||
| 
 | 
 | ||||||
| export default { |  | ||||||
|   name: "CommonAside", |  | ||||||
|   setup() { |  | ||||||
| const router = useRouter(); | const router = useRouter(); | ||||||
| const route = useRoute(); | const route = useRoute(); | ||||||
| const list = ref([]); | const list = ref([]); | ||||||
| @ -63,9 +62,6 @@ export default { | |||||||
| const store = useAllDataStore(); | const store = useAllDataStore(); | ||||||
| const isCollapse = computed(() => store.state.isCollapse); | const isCollapse = computed(() => store.state.isCollapse); | ||||||
| const width = computed(() => store.state.isCollapse ? '64px' : '180px'); | const width = computed(() => store.state.isCollapse ? '64px' : '180px'); | ||||||
|      |  | ||||||
|     // 主题颜色(用于 Element Plus 组件,需要响应式) |  | ||||||
|     // 初始值设为可见的默认值,避免初始化时不可见 |  | ||||||
| const asideBgColor = ref('#0081ff'); | const asideBgColor = ref('#0081ff'); | ||||||
| const asideTextColor = ref('#ffffff'); | const asideTextColor = ref('#ffffff'); | ||||||
| 
 | 
 | ||||||
| @ -259,11 +255,11 @@ export default { | |||||||
|   return sorted; |   return sorted; | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
|     // 菜单点击事件处理 | // 菜单点击事件:emit 通知父组件 | ||||||
| const handleMenuSelect = (index) => { | const handleMenuSelect = (index) => { | ||||||
|   const menuItem = findMenuItemByPath(list.value, index); |   const menuItem = findMenuItemByPath(list.value, index); | ||||||
|   if (menuItem && menuItem.route) { |   if (menuItem && menuItem.route) { | ||||||
|         router.push(menuItem.route); |     emit('menu-click', menuItem); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -280,21 +276,6 @@ export default { | |||||||
|   } |   } | ||||||
|   return null; |   return null; | ||||||
| }; | }; | ||||||
| 
 |  | ||||||
|     return { |  | ||||||
|       list, |  | ||||||
|       sortedMenuList, |  | ||||||
|       store, |  | ||||||
|       isCollapse, |  | ||||||
|       width, |  | ||||||
|       loading, |  | ||||||
|       handleMenuSelect, |  | ||||||
|       route, |  | ||||||
|       asideBgColor, |  | ||||||
|       asideTextColor |  | ||||||
|     }; |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <style scoped lang="less"> | <style scoped lang="less"> | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| import { defineStore } from 'pinia' | import { defineStore } from 'pinia'; | ||||||
| import { ref, computed, reactive } from 'vue' | import { ref, computed, reactive } from 'vue'; | ||||||
| 
 | 
 | ||||||
| // 初始化state数据
 | // ========== 全局状态 Store ==========
 | ||||||
| function initState() { | function initState() { | ||||||
|   return { |   return { | ||||||
|     isCollapse: false, |     isCollapse: false, | ||||||
| @ -19,6 +19,78 @@ export const useAllDataStore = defineStore('allData', () => { | |||||||
|     state, |     state, | ||||||
|     count, |     count, | ||||||
|     doubleCount, |     doubleCount, | ||||||
|         increment |     increment, | ||||||
|  |   }; | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | // ========== 多标签页 Tabs Store ==========
 | ||||||
|  | import { defineStore as defineTabsStore } from 'pinia'; | ||||||
|  | import { ref as vueRef } from 'vue'; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 多标签页Tabs状态管理 | ||||||
|  |  * tabList每个tab结构: { | ||||||
|  |  *   title: 标签显示名, | ||||||
|  |  *   fullPath: 路由路径(唯一key), | ||||||
|  |  *   name: 路由name, | ||||||
|  |  *   icon: 图标(可选) | ||||||
|  |  * } | ||||||
|  |  */ | ||||||
|  | export const useTabsStore = defineTabsStore('tabs', () => { | ||||||
|  |   // 固定首页tab
 | ||||||
|  |   const defaultDashboardPath = '/dashboard'; | ||||||
|  |   const tabList = vueRef([ | ||||||
|  |     { title: '首页', fullPath: defaultDashboardPath, name: 'Dashboard' }, | ||||||
|  |   ]); | ||||||
|  |   const activeTab = vueRef(defaultDashboardPath); | ||||||
|  | 
 | ||||||
|  |   // 添加tab,若已存在则激活
 | ||||||
|  |   function addTab(tab) { | ||||||
|  |     const exist = tabList.value.find((t) => t.fullPath === tab.fullPath); | ||||||
|  |     if (!exist) { | ||||||
|  |       tabList.value.push(tab); | ||||||
|     } |     } | ||||||
| }) |     activeTab.value = tab.fullPath; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // 删除指定tab并切换激活tab
 | ||||||
|  |   function removeTab(fullPath) { | ||||||
|  |     const idx = tabList.value.findIndex((t) => t.fullPath === fullPath); | ||||||
|  |     if (idx > -1) { | ||||||
|  |       tabList.value.splice(idx, 1); | ||||||
|  |       // 只在关闭当前激活tab时切换激活tab
 | ||||||
|  |       if (activeTab.value === fullPath) { | ||||||
|  |         if (tabList.value.length > 0) { | ||||||
|  |           // 优先激活右侧(如无则激活左侧)
 | ||||||
|  |           const newIdx = idx >= tabList.value.length ? tabList.value.length - 1 : idx; | ||||||
|  |           activeTab.value = tabList.value[newIdx].fullPath; | ||||||
|  |         } else { | ||||||
|  |           // 全部关闭,兜底首页
 | ||||||
|  |           activeTab.value = defaultDashboardPath; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // 关闭其他,只留首页和当前激活tab
 | ||||||
|  |   function closeOthers() { | ||||||
|  |     tabList.value = tabList.value.filter( | ||||||
|  |       (t) => t.fullPath === defaultDashboardPath || t.fullPath === activeTab.value | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // 关闭全部,只留首页
 | ||||||
|  |   function closeAll() { | ||||||
|  |     tabList.value = tabList.value.filter((t) => t.fullPath === defaultDashboardPath); | ||||||
|  |     activeTab.value = defaultDashboardPath; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return { | ||||||
|  |     tabList, | ||||||
|  |     activeTab, | ||||||
|  |     addTab, | ||||||
|  |     removeTab, | ||||||
|  |     closeOthers, | ||||||
|  |     closeAll, | ||||||
|  |   }; | ||||||
|  | }); | ||||||
| @ -1,18 +1,148 @@ | |||||||
| <script setup> | <script setup> | ||||||
| import CommonAside from "@/components/CommonAside.vue"; | import CommonAside from '@/components/CommonAside.vue'; | ||||||
| import CommonHeader from "@/components/CommonHeader.vue"; | import CommonHeader from '@/components/CommonHeader.vue'; | ||||||
|  | import { useTabsStore } from '@/stores'; | ||||||
|  | import { useRouter, useRoute } from 'vue-router'; | ||||||
|  | import { ref, watch, reactive, nextTick } from 'vue'; | ||||||
|  | import { More, DArrowRight } from '@element-plus/icons-vue' | ||||||
|  | 
 | ||||||
|  | const tabsStore = useTabsStore(); | ||||||
|  | const router = useRouter(); | ||||||
|  | const route = useRoute(); | ||||||
|  | const defaultDashboardPath = '/dashboard'; | ||||||
|  | 
 | ||||||
|  | // 1. 侧栏菜单点击:加入/激活Tab并切换路由 | ||||||
|  | const handleAsideMenuClick = (menuItem) => { | ||||||
|  |   tabsStore.addTab({ | ||||||
|  |     title: menuItem.label, | ||||||
|  |     fullPath: menuItem.path, | ||||||
|  |     name: menuItem.label, | ||||||
|  |     icon: menuItem.icon | ||||||
|  |   }); | ||||||
|  |   if (route.fullPath !== menuItem.path) { | ||||||
|  |     router.push(menuItem.path); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | const tabsCloseTab = (targetKey) => { | ||||||
|  |   tabsStore.removeTab(targetKey); | ||||||
|  |   if (route.fullPath !== tabsStore.activeTab) { | ||||||
|  |     router.push(tabsStore.activeTab); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | const closeOthers = () => { | ||||||
|  |   tabsStore.closeOthers(); | ||||||
|  |   if (!tabsStore.tabList.find(tab => tab.fullPath === route.fullPath)) { | ||||||
|  |     router.push(tabsStore.activeTab); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | const closeAll = () => { | ||||||
|  |   tabsStore.closeAll(); | ||||||
|  |   router.push(defaultDashboardPath); | ||||||
|  | }; | ||||||
|  | // 主动监听tab激活,保证切tab时内容区切换 | ||||||
|  | watch( | ||||||
|  |   () => tabsStore.activeTab, | ||||||
|  |   (newVal) => { | ||||||
|  |     if (newVal && router.currentRoute.value.fullPath !== newVal) { | ||||||
|  |       router.push(newVal); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | // ========== 右键菜单逻辑 ========== // | ||||||
|  | const contextMenu = reactive({ | ||||||
|  |   visible: false, | ||||||
|  |   x: 0, | ||||||
|  |   y: 0, | ||||||
|  |   tab: null, | ||||||
|  | }); | ||||||
|  | const contextDropdownRef = ref(null); | ||||||
|  | 
 | ||||||
|  | const onTabContextMenu = (event, tab) => { | ||||||
|  |   event.preventDefault(); | ||||||
|  |   contextMenu.visible = true; | ||||||
|  |   contextMenu.x = event.clientX; | ||||||
|  |   contextMenu.y = event.clientY; | ||||||
|  |   contextMenu.tab = tab; | ||||||
|  |   nextTick(() => { | ||||||
|  |     // 溢出优化可扩展 | ||||||
|  |   }); | ||||||
|  |   document.body.addEventListener('click', hideContextMenu, { once: true }); | ||||||
|  | }; | ||||||
|  | function hideContextMenu() { | ||||||
|  |   contextMenu.visible = false; | ||||||
|  |   contextMenu.tab = null; | ||||||
|  | } | ||||||
|  | function closeTabContextTab() { | ||||||
|  |   if (contextMenu.tab && contextMenu.tab.fullPath !== defaultDashboardPath) { | ||||||
|  |     tabsStore.removeTab(contextMenu.tab.fullPath); | ||||||
|  |   } | ||||||
|  |   hideContextMenu(); | ||||||
|  | } | ||||||
|  | function closeOthersContextTab() { | ||||||
|  |   if (contextMenu.tab) { | ||||||
|  |     tabsStore.activeTab = contextMenu.tab.fullPath; | ||||||
|  |     tabsStore.closeOthers(); | ||||||
|  |   } | ||||||
|  |   hideContextMenu(); | ||||||
|  | } | ||||||
|  | function closeAllTabs() { | ||||||
|  |   tabsStore.closeAll(); | ||||||
|  |   hideContextMenu(); | ||||||
|  |   router.push(defaultDashboardPath); | ||||||
|  | } | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <template> | <template> | ||||||
|   <div class="common-layout"> |   <div class="common-layout"> | ||||||
|     <el-container class="main-container"> |     <el-container class="main-container"> | ||||||
|       <common-aside /> |       <common-aside @menu-click="handleAsideMenuClick" /> | ||||||
|       <el-container> |       <el-container> | ||||||
|         <el-header class="main-header"> |         <el-header class="main-header"> | ||||||
|           <common-header /> |           <common-header /> | ||||||
|         </el-header> |         </el-header> | ||||||
|         <el-main class="right-main"> |         <el-main class="right-main"> | ||||||
|           <router-view /> |           <div class="multi-tabs-wrapper"> | ||||||
|  |             <el-tabs | ||||||
|  |               v-model="tabsStore.activeTab" | ||||||
|  |               type="card" | ||||||
|  |               class="multi-tabs" | ||||||
|  |               closable | ||||||
|  |               @tab-remove="tabsCloseTab" | ||||||
|  |             > | ||||||
|  |               <el-tab-pane | ||||||
|  |                 v-for="tab in tabsStore.tabList" | ||||||
|  |                 :key="tab.fullPath" | ||||||
|  |                 :label="tab.title" | ||||||
|  |                 :name="tab.fullPath" | ||||||
|  |                 :closable="tab.fullPath !== defaultDashboardPath" | ||||||
|  |                 @contextmenu="onTabContextMenu($event, tab)" | ||||||
|  |               /> | ||||||
|  |             </el-tabs> | ||||||
|  |             <!-- 跟随浮动到 tabs 最右侧的批量按钮 --> | ||||||
|  |             <div class="floated-tabs-extra-btn"> | ||||||
|  |               <el-dropdown> | ||||||
|  |                 <span class="extra-action-btn"> | ||||||
|  |                   <el-icon><DArrowRight /></el-icon> | ||||||
|  |                 </span> | ||||||
|  |                 <template #dropdown> | ||||||
|  |                   <el-dropdown-menu> | ||||||
|  |                     <el-dropdown-item @click="closeOthers">关闭其他</el-dropdown-item> | ||||||
|  |                     <el-dropdown-item @click="closeAll">关闭全部</el-dropdown-item> | ||||||
|  |                   </el-dropdown-menu> | ||||||
|  |                 </template> | ||||||
|  |               </el-dropdown> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  | 
 | ||||||
|  |           <!-- 主内容毛玻璃卡片容器 --> | ||||||
|  |           <div class="main-panel glass-card"> | ||||||
|  |             <keep-alive :max="10"> | ||||||
|  |               <router-view v-slot="{ Component }"> | ||||||
|  |                 <component :is="Component" /> | ||||||
|  |               </router-view> | ||||||
|  |             </keep-alive> | ||||||
|  |           </div> | ||||||
|         </el-main> |         </el-main> | ||||||
|       </el-container> |       </el-container> | ||||||
|     </el-container> |     </el-container> | ||||||
| @ -20,33 +150,61 @@ import CommonHeader from "@/components/CommonHeader.vue"; | |||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <style scoped lang="less"> | <style scoped lang="less"> | ||||||
| .common-layout, | .common-layout, .main-container { | ||||||
| .main-container { |  | ||||||
|   height: 100vh; |   height: 100vh; | ||||||
|   width: 100%; |   width: 100%; | ||||||
|   display: flex; |   display: flex; | ||||||
|   background-color: var(--bg-color-page); |   background-color: var(--bg-color-page); | ||||||
|   transition: background-color 0.3s ease; |   transition: background-color 0.3s ease; | ||||||
| 
 |  | ||||||
|   :deep(.el-aside) { |   :deep(.el-aside) { | ||||||
|     display: block !important; |     display: block !important; | ||||||
|     visibility: visible !important; |     visibility: visible !important; | ||||||
|     height: 100vh; |     height: 100vh; | ||||||
|   } |   } | ||||||
| 
 |  | ||||||
|   .main-header { |   .main-header { | ||||||
|     background-color: var(--header-bg-color, #0081ff); |     background-color: var(--header-bg-color, #0081ff); | ||||||
|     transition: background-color 0.3s ease; |     transition: background-color 0.3s ease; | ||||||
|     height: 60px; |     height: 60px; | ||||||
|     padding: 0; |     padding: 0; | ||||||
|   } |   } | ||||||
|    |  | ||||||
|   .right-main { |   .right-main { | ||||||
|     background-color: var(--bg-color-page); |     background-color: var(--bg-color-page); | ||||||
|     color: var(--text-color-primary); |     color: var(--text-color-primary); | ||||||
|     transition: background-color 0.3s ease, color 0.3s ease; |     transition: background-color 0.3s ease, color 0.3s ease; | ||||||
|     padding: 20px; |     padding: 20px; | ||||||
|     overflow-y: auto; |     overflow-y: auto; | ||||||
|  |     .multi-tabs-wrapper { | ||||||
|  |       position: relative; | ||||||
|  |       zoom: 1; | ||||||
|  |       min-height: 45px; | ||||||
|  |     } | ||||||
|  |     .floated-tabs-extra-btn { | ||||||
|  |       float: right; | ||||||
|  |       margin-top: -40px; | ||||||
|  |       margin-right: 12px; | ||||||
|  |       z-index: 10; | ||||||
|  |     } | ||||||
|  |     .extra-action-btn { | ||||||
|  |       display: inline-flex; | ||||||
|  |       align-items: center; | ||||||
|  |       font-size: 20px; | ||||||
|  |       cursor: pointer; | ||||||
|  |       color: #888; | ||||||
|  |       background: none; | ||||||
|  |       border: none; | ||||||
|  |       padding: 0 8px; | ||||||
|  |       border-radius: 4px; | ||||||
|  |       transition: color 0.2s; | ||||||
|  |       &:hover { | ||||||
|  |         color: #409eff; | ||||||
|  |         background: none; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     .more-menu { | ||||||
|  |       font-size: 13px; | ||||||
|  |       margin-left: 10px; | ||||||
|  |       cursor: pointer; | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
| </style> | </style> | ||||||
|  | |||||||
							
								
								
									
										0
									
								
								pc/src/views/apps/knowledge/category/edit.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								pc/src/views/apps/knowledge/category/edit.vue
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										13
									
								
								pc/src/views/apps/knowledge/category/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								pc/src/views/apps/knowledge/category/index.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | |||||||
|  | <template> | ||||||
|  |     <div> | ||||||
|  | 123 | ||||||
|  |     </div> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script setup> | ||||||
|  | 
 | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <style lang="scss" scoped> | ||||||
|  | 
 | ||||||
|  | </style> | ||||||
| @ -67,10 +67,20 @@ | |||||||
|     <div class="knowledge-repos"> |     <div class="knowledge-repos"> | ||||||
|       <div class="repos-header"> |       <div class="repos-header"> | ||||||
|         <h2>知识库列表</h2> |         <h2>知识库列表</h2> | ||||||
|  |         <div> | ||||||
|           <el-button type="primary" @click="handleCreate" class="create-btn"> |           <el-button type="primary" @click="handleCreate" class="create-btn"> | ||||||
|             <i class="fa-solid fa-plus"></i> |             <i class="fa-solid fa-plus"></i> | ||||||
|             新建知识库 |             新建知识库 | ||||||
|           </el-button> |           </el-button> | ||||||
|  |           <el-button type="primary" @click="handleCategory" class="create-btn"> | ||||||
|  |             <i class="fas fa-folder-open"></i> | ||||||
|  |             分类管理 | ||||||
|  |           </el-button> | ||||||
|  |           <el-button type="primary" @click="handleTags" class="create-btn"> | ||||||
|  |             <i class="fas fa-tags"></i> | ||||||
|  |             标签管理 | ||||||
|  |           </el-button> | ||||||
|  |         </div> | ||||||
|       </div> |       </div> | ||||||
| 
 | 
 | ||||||
|       <div class="repos-grid"> |       <div class="repos-grid"> | ||||||
| @ -314,6 +324,16 @@ function handleEdit(repo: Knowledge) { | |||||||
|   router.push(`/apps/knowledge/edit/${repo.id}`); |   router.push(`/apps/knowledge/edit/${repo.id}`); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | function handleCategory() { | ||||||
|  |   // 跳转到分类管理页面,使用路径跳转 | ||||||
|  |   router.push(`/apps/knowledge/category`); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function handleTags() { | ||||||
|  |   // 跳转到标签管理页面,使用路径跳转 | ||||||
|  |   router.push(`/apps/knowledge/tags`); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| function handleDelete(repo: Knowledge) { | function handleDelete(repo: Knowledge) { | ||||||
|   ElMessageBox.confirm(`确认删除知识「${repo.title}」?`, "提示", { |   ElMessageBox.confirm(`确认删除知识「${repo.title}」?`, "提示", { | ||||||
|     confirmButtonText: "确定", |     confirmButtonText: "确定", | ||||||
| @ -706,7 +726,8 @@ onMounted(() => { | |||||||
|             color: var(--primary-color); |             color: var(--primary-color); | ||||||
|             border-color: var(--border-color); |             border-color: var(--border-color); | ||||||
|             font-weight: 500; |             font-weight: 500; | ||||||
|             transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease; |             transition: background-color 0.3s ease, color 0.3s ease, | ||||||
|  |               border-color 0.3s ease; | ||||||
|           } |           } | ||||||
| 
 | 
 | ||||||
|           .repo-owner { |           .repo-owner { | ||||||
| @ -744,7 +765,8 @@ onMounted(() => { | |||||||
|           border-color: var(--border-color-lighter); |           border-color: var(--border-color-lighter); | ||||||
|           font-size: 12px; |           font-size: 12px; | ||||||
|           padding: 4px 12px; |           padding: 4px 12px; | ||||||
|           transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease; |           transition: background-color 0.3s ease, color 0.3s ease, | ||||||
|  |             border-color 0.3s ease; | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										0
									
								
								pc/src/views/apps/knowledge/tag/edit.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								pc/src/views/apps/knowledge/tag/edit.vue
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								pc/src/views/apps/knowledge/tag/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								pc/src/views/apps/knowledge/tag/index.vue
									
									
									
									
									
										Normal file
									
								
							| @ -145,7 +145,7 @@ | |||||||
|         > |         > | ||||||
|           <el-input |           <el-input | ||||||
|             v-model="currentMenu.ComponentPath" |             v-model="currentMenu.ComponentPath" | ||||||
|             placeholder="例如:@/views/settings/index.vue" |             placeholder="例如:/apps/knowledge/index.vue" | ||||||
|           /> |           /> | ||||||
|         </el-form-item> |         </el-form-item> | ||||||
| 
 | 
 | ||||||
| @ -440,10 +440,15 @@ const saveMenu = async () => { | |||||||
|   const valid = await menuFormRef.value.validate(); |   const valid = await menuFormRef.value.validate(); | ||||||
|   if (!valid) return; |   if (!valid) return; | ||||||
| 
 | 
 | ||||||
|  |   // 解决后端时间字段问题:过滤掉 CreateTime/UpdateTime | ||||||
|  |   const payload = { ...currentMenu.value }; | ||||||
|  |   delete payload.CreateTime; | ||||||
|  |   delete payload.UpdateTime; | ||||||
|  | 
 | ||||||
|   try { |   try { | ||||||
|     if (currentMenu.value.Id === 0) { |     if (currentMenu.value.Id === 0) { | ||||||
|       // 新增菜单 |       // 新增菜单 | ||||||
|       const result = await createMenu(currentMenu.value as Menu); |       const result = await createMenu(payload as Menu); | ||||||
|       if (result.success) { |       if (result.success) { | ||||||
|         ElMessage.success("菜单添加成功"); |         ElMessage.success("菜单添加成功"); | ||||||
|         dialogVisible.value = false; |         dialogVisible.value = false; | ||||||
| @ -455,7 +460,7 @@ const saveMenu = async () => { | |||||||
|       // 编辑菜单 |       // 编辑菜单 | ||||||
|       const result = await updateMenu( |       const result = await updateMenu( | ||||||
|         currentMenu.value.Id!, |         currentMenu.value.Id!, | ||||||
|         currentMenu.value as Menu |         payload as Menu | ||||||
|       ); |       ); | ||||||
|       if (result.success) { |       if (result.success) { | ||||||
|         ElMessage.success("更新成功"); |         ElMessage.success("更新成功"); | ||||||
|  | |||||||
| @ -167,7 +167,7 @@ func (c *KnowledgeController) Update() { | |||||||
| 	c.Data["json"] = map[string]interface{}{ | 	c.Data["json"] = map[string]interface{}{ | ||||||
| 		"code":    0, | 		"code":    0, | ||||||
| 		"message": "更新成功", | 		"message": "更新成功", | ||||||
| 		"data":    nil, | 		// "data":    nil, | ||||||
| 	} | 	} | ||||||
| 	c.ServeJSON() | 	c.ServeJSON() | ||||||
| } | } | ||||||
|  | |||||||
| @ -105,7 +105,7 @@ func (c *MenuController) UpdateMenu() { | |||||||
| 		c.Data["json"] = map[string]interface{}{ | 		c.Data["json"] = map[string]interface{}{ | ||||||
| 			"success": true, | 			"success": true, | ||||||
| 			"message": "更新菜单成功", | 			"message": "更新菜单成功", | ||||||
| 			"data":    menu, | 			// "data":    menu, | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -248,7 +248,7 @@ func UpdateKnowledge(id int, k *Knowledge) error { | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// 更新字段(不包含category_name,因为它是从联查获取的) | 	// 更新字段 | ||||||
| 	knowledge.Title = k.Title | 	knowledge.Title = k.Title | ||||||
| 	knowledge.CategoryId = k.CategoryId | 	knowledge.CategoryId = k.CategoryId | ||||||
| 	knowledge.Tags = k.Tags | 	knowledge.Tags = k.Tags | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user