From 7972f0a6d969e80aa32962ab2ecffe0abdd8faa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=89=AB=E5=9C=B0=E5=83=A7?= <357099073@qq.com> Date: Sun, 2 Nov 2025 18:34:04 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=9F=A5=E8=AF=86=E5=BA=93?= =?UTF-8?q?=E7=9A=84=E6=A0=87=E7=AD=BE=E7=AE=A1=E7=90=86=E5=92=8C=E5=88=86?= =?UTF-8?q?=E7=B1=BB=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pc/src/components/CommonAside.vue | 41 +- pc/src/components/CommonHeader.vue | 5 - pc/src/router/dynamicRoutes.js | 51 +- pc/src/router/index.js | 36 +- pc/src/views/apps/index.vue | 6 +- .../views/apps/knowledge/category/index.vue | 550 +++++++++++++++--- pc/src/views/apps/knowledge/index.vue | 17 +- pc/src/views/apps/knowledge/tag/index.vue | 392 ++++++++++--- pc/src/views/settings/index.vue | 6 +- pc/src/views/settings/systeminfo/index.vue | 426 +++++++++++++- pc/src/views/system/files/index.vue | 339 ++++++++--- server/controllers/knowledge.go | 45 +- server/database/add_knowledge_menus.sql | 65 +++ server/models/knowledge.go | 27 +- 14 files changed, 1675 insertions(+), 331 deletions(-) create mode 100644 server/database/add_knowledge_menus.sql diff --git a/pc/src/components/CommonAside.vue b/pc/src/components/CommonAside.vue index f0565a2..67fccdc 100644 --- a/pc/src/components/CommonAside.vue +++ b/pc/src/components/CommonAside.vue @@ -205,36 +205,19 @@ const transformMenuData = (menus) => { const fetchMenus = async () => { loading.value = true; try { - // 优先从 localStorage 读取 - const cachedMenus = localStorage.getItem('menuData'); - let menuData = null; - - if (cachedMenus) { - try { - menuData = JSON.parse(cachedMenus); - } catch (e) { - console.warn('缓存菜单数据解析失败:', e); - } + // 直接从接口获取菜单数据,不使用缓存 + const res = await getAllMenus(); + if (res && res.success && res.data) { + const menuData = res.data; + // 转换并排序菜单数据 + const transformedMenus = transformMenuData(menuData); + list.value = transformedMenus; + } else { + console.error('获取菜单失败:', res?.message || '未知错误'); + list.value = []; + loading.value = false; + return; } - - // 如果缓存中没有或解析失败,从接口获取 - if (!menuData) { - const res = await getAllMenus(); - if (res && res.success && res.data) { - menuData = res.data; - // 保存到缓存 - localStorage.setItem('menuData', JSON.stringify(menuData)); - } else { - console.error('获取菜单失败:', res?.message || '未知错误'); - list.value = []; - loading.value = false; - return; - } - } - - // 转换并排序菜单数据 - const transformedMenus = transformMenuData(menuData); - list.value = transformedMenus; } catch (error) { console.error('获取菜单异常:', error); list.value = []; diff --git a/pc/src/components/CommonHeader.vue b/pc/src/components/CommonHeader.vue index 248dc94..ac7cd90 100644 --- a/pc/src/components/CommonHeader.vue +++ b/pc/src/components/CommonHeader.vue @@ -130,11 +130,6 @@ const handleCommand = (command) => { //清除租户数据 localStorage.removeItem('tenant'); sessionStorage.removeItem('tenant'); - //清除菜单数据 - localStorage.removeItem('menus'); - sessionStorage.removeItem('menus'); - localStorage.removeItem('menuData'); - sessionStorage.removeItem('menuData'); router.push('/login'); } }; diff --git a/pc/src/router/dynamicRoutes.js b/pc/src/router/dynamicRoutes.js index 29f72a5..bfe2729 100644 --- a/pc/src/router/dynamicRoutes.js +++ b/pc/src/router/dynamicRoutes.js @@ -42,16 +42,30 @@ export function convertMenusToRoutes(menus) { // 子菜单添加到父菜单的 children 中 const parentRoute = menuMap[menu.parentId]; if (parentRoute) { - // 修正子路由路径:相对于父路由的路径 - const parentPath = parentRoute.path; // 例如 "system" - const childFullPath = currentRoute.path; // 例如 "system/users" + // 修正子路由路径:使用原始菜单路径来准确匹配 + // 使用原始路径(menuPath)来准确计算相对路径 + const parentOriginalPath = parentRoute.meta?.menuPath || parentRoute.path; + const childOriginalPath = currentRoute.meta?.menuPath || currentRoute.path; + + // 确保路径格式一致(去掉前导斜杠) + const parentPath = parentOriginalPath.startsWith('/') ? parentOriginalPath.substring(1) : parentOriginalPath; + const childFullPath = childOriginalPath.startsWith('/') ? childOriginalPath.substring(1) : childOriginalPath; // 如果子路径以父路径开头,则只保留剩余部分 if (childFullPath.startsWith(parentPath + '/')) { - currentRoute.path = childFullPath.substring(parentPath.length + 1); // "users" - } else if (childFullPath.startsWith('/')) { - // 如果仍然有前导斜杠,去掉它 - currentRoute.path = childFullPath.substring(1); + currentRoute.path = childFullPath.substring(parentPath.length + 1); // "users" 或 "knowledge/category" + } else { + // 如果子路径不以父路径开头,尝试直接使用子路径的最后一部分 + // 这处理了路径不连续的情况 + const pathParts = childFullPath.split('/'); + const parentPathParts = parentPath.split('/'); + // 找到子路径相对于父路径的部分 + if (pathParts.length > parentPathParts.length) { + currentRoute.path = pathParts.slice(parentPathParts.length).join('/'); + } else { + // 如果无法确定相对路径,使用最后一个路径段 + currentRoute.path = pathParts[pathParts.length - 1]; + } } if (!parentRoute.children) { @@ -64,6 +78,29 @@ export function convertMenusToRoutes(menus) { } } }); + + // 2.5. 为有子路由但没有 component 的父路由自动添加默认组件 + const addDefaultComponent = (routeList) => { + routeList.forEach(route => { + // 如果路由有子路由但没有组件,尝试添加默认组件 + if (route.children && route.children.length > 0 && !route.component) { + // 使用原始菜单路径(menuPath)来推断组件路径,而不是修正后的路径 + const originalPath = route.meta?.menuPath || route.path; + // 确保路径以 / 开头 + const normalizedPath = originalPath.startsWith('/') ? originalPath : `/${originalPath}`; + const defaultComponentPath = `${normalizedPath}/index.vue`; + const defaultComponent = createComponentLoader(defaultComponentPath); + if (defaultComponent) { + route.component = defaultComponent; + } + } + // 递归处理子路由 + if (route.children && route.children.length > 0) { + addDefaultComponent(route.children); + } + }); + }; + addDefaultComponent(routes); // 3. 按 order 排序 const sortRoutes = (routesList) => { diff --git a/pc/src/router/index.js b/pc/src/router/index.js index c3969cf..f502787 100644 --- a/pc/src/router/index.js +++ b/pc/src/router/index.js @@ -142,24 +142,24 @@ function addDynamicRoutes(menus) { // 添加知识库的子路由(详情页和编辑页) // 直接在 Main 路由下添加完整路径的子路由 - router.addRoute('Main', { - path: 'apps/knowledge/detail/:id', - name: 'apps-knowledge-detail', - component: () => import('@/views/apps/knowledge/components/detail.vue'), - meta: { - requiresAuth: true, - title: '知识详情' - } - }); - router.addRoute('Main', { - path: 'apps/knowledge/edit/:id', - name: 'apps-knowledge-edit', - component: () => import('@/views/apps/knowledge/components/edit.vue'), - meta: { - requiresAuth: true, - title: '编辑知识' - } - }); + // router.addRoute('Main', { + // path: 'apps/knowledge/detail/:id', + // name: 'apps-knowledge-detail', + // component: () => import('@/views/apps/knowledge/components/detail.vue'), + // meta: { + // requiresAuth: true, + // title: '知识详情' + // } + // }); + // router.addRoute('Main', { + // path: 'apps/knowledge/edit/:id', + // name: 'apps-knowledge-edit', + // component: () => import('@/views/apps/knowledge/components/edit.vue'), + // meta: { + // requiresAuth: true, + // title: '编辑知识' + // } + // }); dynamicRoutesAdded = true; } diff --git a/pc/src/views/apps/index.vue b/pc/src/views/apps/index.vue index 04d3b9a..2ce359b 100644 --- a/pc/src/views/apps/index.vue +++ b/pc/src/views/apps/index.vue @@ -1,11 +1,11 @@ diff --git a/pc/src/views/apps/knowledge/category/index.vue b/pc/src/views/apps/knowledge/category/index.vue index 9252099..ad4affb 100644 --- a/pc/src/views/apps/knowledge/category/index.vue +++ b/pc/src/views/apps/knowledge/category/index.vue @@ -1,29 +1,139 @@ + + + + + diff --git a/pc/src/views/apps/knowledge/index.vue b/pc/src/views/apps/knowledge/index.vue index 785bef2..3098c50 100644 --- a/pc/src/views/apps/knowledge/index.vue +++ b/pc/src/views/apps/knowledge/index.vue @@ -1,5 +1,10 @@ diff --git a/pc/src/views/settings/index.vue b/pc/src/views/settings/index.vue index 04d3b9a..6c91165 100644 --- a/pc/src/views/settings/index.vue +++ b/pc/src/views/settings/index.vue @@ -1,11 +1,11 @@ diff --git a/pc/src/views/settings/systeminfo/index.vue b/pc/src/views/settings/systeminfo/index.vue index 44e898f..0d98122 100644 --- a/pc/src/views/settings/systeminfo/index.vue +++ b/pc/src/views/settings/systeminfo/index.vue @@ -1,16 +1,420 @@ - + + + - diff --git a/pc/src/views/system/files/index.vue b/pc/src/views/system/files/index.vue index 57315b4..4fd1fee 100644 --- a/pc/src/views/system/files/index.vue +++ b/pc/src/views/system/files/index.vue @@ -120,7 +120,7 @@
diff --git a/server/controllers/knowledge.go b/server/controllers/knowledge.go index 3ed8d11..fa99877 100644 --- a/server/controllers/knowledge.go +++ b/server/controllers/knowledge.go @@ -290,12 +290,13 @@ func (c *KnowledgeController) GetTags() { var result []map[string]interface{} for _, tag := range tags { result = append(result, map[string]interface{}{ - "tagId": tag.TagId, - "tagName": tag.TagName, - "tagColor": tag.TagColor, - "usageCount": tag.UsageCount, - "createTime": tag.CreateTime, - "updateTime": tag.UpdateTime, + "tagId": tag.TagId, + "tagName": tag.TagName, + "tagColor": tag.TagColor, + "tagBackground": tag.TagBackground, + "usageCount": tag.UsageCount, + "createTime": tag.CreateTime, + "updateTime": tag.UpdateTime, }) } @@ -322,7 +323,8 @@ func (c *KnowledgeController) AddCategory() { return } - id, err := models.AddCategory(&category) + // 不处理id,直接添加,表自动递增 + _, err = models.AddCategory(&category) if err != nil { c.Data["json"] = map[string]interface{}{ "code": 1, @@ -336,12 +338,12 @@ func (c *KnowledgeController) AddCategory() { c.Data["json"] = map[string]interface{}{ "code": 0, "message": "添加成功", - "data": map[string]interface{}{"categoryId": id}, + "data": nil, } c.ServeJSON() } -// AddTag 添加标签 +// AddTag 添加或更新标签 // @router /api/knowledge/tag/add [post] func (c *KnowledgeController) AddTag() { var tag models.KnowledgeTag @@ -356,6 +358,31 @@ func (c *KnowledgeController) AddTag() { return } + // 判断是添加还是更新 + if tag.TagId > 0 { + // 更新操作 + err = models.UpdateTag(&tag) + if err != nil { + c.Data["json"] = map[string]interface{}{ + "code": 1, + "message": "更新标签失败: " + err.Error(), + "data": nil, + } + c.ServeJSON() + return + } + + c.Data["json"] = map[string]interface{}{ + "code": 0, + "message": "更新成功", + "data": map[string]interface{}{"tagId": tag.TagId}, + } + c.ServeJSON() + return + } + + // 添加操作:确保 TagId 为 0,让数据库自动生成 + tag.TagId = 0 id, err := models.AddTag(&tag) if err != nil { c.Data["json"] = map[string]interface{}{ diff --git a/server/database/add_knowledge_menus.sql b/server/database/add_knowledge_menus.sql new file mode 100644 index 0000000..5011e1c --- /dev/null +++ b/server/database/add_knowledge_menus.sql @@ -0,0 +1,65 @@ +-- 添加知识库管理相关的菜单项 +-- 注意:需要先查询知识库菜单的ID(parent_id),假设为 11 + +-- 如果知识库菜单ID为11,添加分类管理和标签管理菜单 +-- 请根据实际数据库中的知识库菜单ID修改下面的 parent_id 值 + +-- 查询知识库菜单ID(如果需要) +-- SELECT id FROM yz_menus WHERE path = '/apps/knowledge'; + +-- 添加分类管理菜单(如果不存在) +INSERT INTO yz_menus ( + name, + path, + parent_id, + icon, + `order`, + status, + component_path, + menu_type, + description +) +SELECT + '分类管理', + '/apps/knowledge/category', + id, + 'fa-solid fa-folder', + 2, + 1, + '@/views/apps/knowledge/category/index.vue', + 1, + '知识库分类管理' +FROM yz_menus +WHERE path = '/apps/knowledge' +AND NOT EXISTS ( + SELECT 1 FROM yz_menus WHERE path = '/apps/knowledge/category' +); + +-- 添加标签管理菜单(如果不存在) +INSERT INTO yz_menus ( + name, + path, + parent_id, + icon, + `order`, + status, + component_path, + menu_type, + description +) +SELECT + '标签管理', + '/apps/knowledge/tag', + id, + 'fa-solid fa-tags', + 3, + 1, + '@/views/apps/knowledge/tag/index.vue', + 1, + '知识库标签管理' +FROM yz_menus +WHERE path = '/apps/knowledge' +AND NOT EXISTS ( + SELECT 1 FROM yz_menus WHERE path = '/apps/knowledge/tag' +); + diff --git a/server/models/knowledge.go b/server/models/knowledge.go index 38c24ff..813eb07 100644 --- a/server/models/knowledge.go +++ b/server/models/knowledge.go @@ -54,12 +54,13 @@ func (kc *KnowledgeCategory) TableName() string { // KnowledgeTag 知识库标签模型 type KnowledgeTag struct { - TagId int `orm:"column(tag_id);pk;auto" json:"tagId"` - TagName string `orm:"column(tag_name);size(50);unique" json:"tagName"` - TagColor string `orm:"column(tag_color);size(20);null" json:"tagColor"` - UsageCount int `orm:"column(usage_count);default(0)" json:"usageCount"` - CreateTime time.Time `orm:"column(create_time);auto_now_add;type(datetime)" json:"createTime"` - UpdateTime time.Time `orm:"column(update_time);auto_now;type(datetime)" json:"updateTime"` + TagId int `orm:"column(tag_id);pk;auto" json:"tagId"` + TagName string `orm:"column(tag_name);size(50);unique" json:"tagName"` + TagColor string `orm:"column(tag_color);size(20);null" json:"tagColor"` + TagBackground string `orm:"column(tag_background);size(20);null" json:"tagBackground"` + UsageCount int `orm:"column(usage_count);default(0)" json:"usageCount"` + CreateTime time.Time `orm:"column(create_time);auto_now_add;type(datetime)" json:"createTime"` + UpdateTime time.Time `orm:"column(update_time);auto_now;type(datetime)" json:"updateTime"` } // TableName 设置表名 @@ -286,9 +287,23 @@ func AddCategory(category *KnowledgeCategory) (int64, error) { return id, err } +// UpdateCategory 更新分类 +func UpdateCategory(category *KnowledgeCategory) error { + o := orm.NewOrm() + _, err := o.Update(category, "CategoryName", "CategoryDesc", "ParentId", "SortOrder") + return err +} + // AddTag 添加标签 func AddTag(tag *KnowledgeTag) (int64, error) { o := orm.NewOrm() id, err := o.Insert(tag) return id, err } + +// UpdateTag 更新标签 +func UpdateTag(tag *KnowledgeTag) error { + o := orm.NewOrm() + _, err := o.Update(tag, "TagName", "TagColor", "TagBackground") + return err +}