From d9edd739d6e3827d673c8b86a48a100d2bc51dbe Mon Sep 17 00:00:00 2001 From: sion123 <450702724@qq.com> Date: Thu, 12 Feb 2026 00:51:09 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web-gold/src/components/SidebarNav.vue | 127 +++++------- frontend/app/web-gold/src/router/index.js | 196 +++++++++++------- 2 files changed, 169 insertions(+), 154 deletions(-) diff --git a/frontend/app/web-gold/src/components/SidebarNav.vue b/frontend/app/web-gold/src/components/SidebarNav.vue index aa1cf75d4f..992a796f74 100644 --- a/frontend/app/web-gold/src/components/SidebarNav.vue +++ b/frontend/app/web-gold/src/components/SidebarNav.vue @@ -1,106 +1,60 @@ +.nav-item__icon { + width: 18px; + height: 18px; + display: inline-flex; + align-items: center; + justify-content: center; +} +.nav-item__label { + font-size: 14px; +} + diff --git a/frontend/app/web-gold/src/router/index.js b/frontend/app/web-gold/src/router/index.js index e74cc7d922..0997c38ee6 100644 --- a/frontend/app/web-gold/src/router/index.js +++ b/frontend/app/web-gold/src/router/index.js @@ -3,84 +3,139 @@ import { useUserStore } from '@/stores/user' import tokenManager from '@gold/utils/token-manager' import MainLayout from '@/layouts/MainLayout.vue' +// ============ 导航配置(统一定义) ============ +const navConfig = [ + { + group: '功能', + order: 1, + items: [ + { name: '对标分析', path: 'content-style/benchmark', icon: 'grid', component: () => import('../views/content-style/Benchmark.vue') }, + { name: '文案创作', path: 'content-style/copywriting', icon: 'text', component: () => import('../views/content-style/Copywriting.vue') }, + { name: '热点趋势', path: 'trends/forecast', icon: 'text', component: () => import('../views/trends/Forecast.vue') }, + ] + }, + { + group: '数字人', + order: 2, + items: [ + { name: '数字人', path: 'digital-human/kling', icon: 'user', component: () => import('../views/kling/IdentifyFace.vue') }, + { name: '人声克隆', path: 'digital-human/voice-copy', icon: 'mic', component: () => import('../views/dh/VoiceCopy.vue') }, + ] + }, + { + group: '素材库', + order: 3, + items: [ + { name: '素材列表', path: 'material/list', icon: 'grid', component: () => import('../views/material/MaterialListNew.vue') }, + { name: '智能混剪', path: 'material/mix', icon: 'scissors', component: () => import('../views/material/Mix.vue') }, + { name: '任务中心', path: 'system/task-management/:type', icon: 'video', component: () => import('../views/system/task-management/layout/TaskLayout.vue'), requiresAuth: true, params: { type: 'mix-task' } }, + ] + }, + { + group: '系统', + order: 4, + requiresAuth: true, + items: [ + { name: '风格设置', path: 'system/style-settings', icon: 'text', component: () => import('../views/system/style-settings/index.vue') }, + ] + } +] + +// 导航图标定义 +const navIcons = { + home: '', + grid: '', + text: '', + mic: '', + wave: '', + user: '', + video: '', + folder: '', + scissors: '' +} + +// ============ 辅助函数 ============ +function findOrCreateParentRoute(routes, parentPath) { + let parentRoute = routes.find(r => r.path === parentPath) + if (!parentRoute) { + parentRoute = { path: parentPath, children: [], meta: {} } + routes.push(parentRoute) + } + return parentRoute +} + +function addChildRoute(parentRoute, path, name, component, meta) { + parentRoute.children.push({ path, name, component, meta }) +} + +function setDefaultRedirect(parentRoute, redirectPath) { + if (!parentRoute.children.some(c => c.path === '')) { + parentRoute.children.unshift({ path: '', redirect: redirectPath }) + } +} + +// ============ 从导航配置生成路由 ============ +function buildRoutesFromNav(config) { + const parentRoutes = [] + + config.forEach(group => { + group.items.forEach(item => { + const [parentPath, ...childSegments] = item.path.split('/') + const childPath = childSegments.join('/') || '' + const parentRoute = findOrCreateParentRoute(parentRoutes, parentPath) + + parentRoute.meta.navGroup = group.group + parentRoute.meta.navGroupOrder = group.order + if (group.requiresAuth) { + parentRoute.meta.requiresAuth = true + } + + addChildRoute(parentRoute, childPath, item.name, item.component, { + navIcon: item.icon, + navLabel: item.name, + requiresAuth: item.requiresAuth + }) + + setDefaultRedirect(parentRoute, `/${item.path}`) + }) + }) + + const hiddenRoutes = [ + { path: 'trends/heat', name: '热度分析', component: () => import('../views/trends/Heat.vue'), meta: { hidden: true } }, + { path: 'material/mix-task', name: '混剪任务', component: () => import('../views/material/MixTaskList.vue'), meta: { hidden: true } }, + { path: 'material/group', name: '素材分组', component: () => import('../views/material/MaterialGroup.vue'), meta: { hidden: true } } + ] + + hiddenRoutes.forEach(route => { + const [parentPath, childPath] = route.path.split('/') + const parentRoute = findOrCreateParentRoute(parentRoutes, parentPath) + addChildRoute(parentRoute, childPath, route.name, route.component, route.meta) + }) + + return parentRoutes +} + const routes = [ - // 登录页面 - 独立渲染,不使用Layout + // 登录页面 { path: '/login', name: '登录', component: () => import('../views/auth/Login.vue'), - meta: { - requiresAuth: false - } + meta: { requiresAuth: false } }, - // 主布局路由 - 所有需要Layout的页面都在这里 + // 主布局 { path: '/', component: MainLayout, redirect: '/content-style/benchmark', - children: [ - { - path: 'content-style', - name: '内容风格分析', - children: [ - { path: '', redirect: '/content-style/benchmark' }, - { path: 'benchmark', name: '对标分析', component: () => import('../views/content-style/Benchmark.vue') }, - { path: 'copywriting', name: '文案创作', component: () => import('../views/content-style/Copywriting.vue') }, - ] - }, - { - path: 'trends', - name: '热点趋势分析', - children: [ - { path: '', redirect: '/trends/heat' }, - { path: 'heat', name: '热度分析', component: () => import('../views/trends/Heat.vue') }, - { path: 'forecast', name: '热点预测', component: () => import('../views/trends/Forecast.vue') }, - ] - }, - { - path: 'digital-human', - name: '数字人', - children: [ - { path: '', redirect: '/digital-human/voice-copy' }, - { path: 'kling', name: '数字人生成', component: () => import('../views/kling/IdentifyFace.vue') }, - { path: 'voice-copy', name: '人声克隆', component: () => import('../views/dh/VoiceCopy.vue') }, - ] - }, - { - path: 'material', - name: '素材库', - children: [ - { path: '', redirect: '/material/list' }, - { path: 'list', name: '素材列表', component: () => import('../views/material/MaterialListNew.vue') }, - { path: 'mix', name: '智能混剪', component: () => import('../views/material/Mix.vue') }, - { path: 'mix-task', name: '混剪任务', component: () => import('../views/material/MixTaskList.vue') }, - { path: 'group', name: '素材分组', component: () => import('../views/material/MaterialGroup.vue') }, - ] - }, - { - path: 'system', - name: '系统', - children: [ - { path: '', redirect: '/system/style-settings' }, - { path: 'style-settings', name: '风格设置', component: () => import('../views/system/style-settings/index.vue') }, - { - path: 'task-management/:type', - name: '任务中心', - component: () => import('../views/system/task-management/layout/TaskLayout.vue') - } - ], - meta: { - requiresAuth: true - } - }, - ], - meta: { - requiresAuth: true - } + children: buildRoutesFromNav(navConfig), + meta: { requiresAuth: true } }, - ] +// 导出配置供 SidebarNav 使用 +export { navConfig, navIcons } + const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes, @@ -91,23 +146,17 @@ router.beforeEach(async (to, from, next) => { const userStore = useUserStore() const authenToken = tokenManager.getAccessToken() - // 路由访问控制 if (to.meta.requiresAuth && !authenToken) { - // 需要认证但未登录,跳转到登录页并记录当前路径 - next({ - path: '/login', - query: { redirect: to.fullPath } - }) + next({ path: '/login', query: { redirect: to.fullPath } }) return } - // 已登录用户访问登录页,重定向到首页 if (to.path === '/login' && authenToken) { next({ path: '/content-style/benchmark', replace: true }) return } - if (authenToken && !userStore.isLoggedIn.value) { + if (authenToken && !userStore.isLoggedIn) { userStore.fetchUserInfo() } @@ -115,4 +164,3 @@ router.beforeEach(async (to, from, next) => { }) export default router -