- IM: 新增浮窗聊天(ImFloatWindow)、管理页(monitor/config/service/message)、SSE推送 - 工作流: 新增待办/我的流程页面及后端服务 - 打印: 新增打印模板、出库单打印(PrintPage)、模板种子脚本 - 工作台: 增强快捷入口与工作台数据 - 修复: TagsView页签关闭、CrudPage通用表格增强 - 移除导航菜单中的即时通讯入口,改为右下角浮窗
184 lines
4.8 KiB
JavaScript
184 lines
4.8 KiB
JavaScript
import { createRouter, createWebHistory } from 'vue-router'
|
|
import { useUserStore } from '@/stores/user'
|
|
import { useTabsStore } from '@/stores/tabs'
|
|
import { resolveTable, resolveDetail, resolvePrint, resolveWorkflow, SPECIAL_PAGES } from '@/config/table-map'
|
|
|
|
// 静态路由(与权限无关)
|
|
export const constantRoutes = [
|
|
{
|
|
path: '/login',
|
|
name: 'Login',
|
|
component: () => import('@/views/login/index.vue'),
|
|
meta: { title: '登录' }
|
|
},
|
|
{
|
|
path: '/',
|
|
name: 'root',
|
|
component: () => import('@/layout/index.vue'),
|
|
redirect: '/workbench',
|
|
children: [
|
|
{
|
|
path: '/workbench',
|
|
name: 'WorkBench',
|
|
component: () => import('@/views/workbench/index.vue'),
|
|
meta: { title: '工作台', affix: true }
|
|
},
|
|
{
|
|
path: '/404',
|
|
name: 'NotFound',
|
|
component: () => import('@/views/error/404.vue'),
|
|
meta: { title: '页面不存在' }
|
|
},
|
|
{
|
|
path: '/process/zhuangkou-detail/:id',
|
|
name: 'ProcessZhuangkouDetail',
|
|
component: () => import('@/views/process/zhuangkou-detail.vue'),
|
|
meta: { title: '工艺庄口详情', hidden: true }
|
|
},
|
|
{
|
|
path: '/workflow/todo',
|
|
name: 'WorkFlowTodo',
|
|
component: () => import('@/views/workflow/todo.vue'),
|
|
meta: { title: '待办中心' }
|
|
},
|
|
{
|
|
path: '/workflow/my',
|
|
name: 'WorkFlowMy',
|
|
component: () => import('@/views/workflow/my.vue'),
|
|
meta: { title: '我发起的' }
|
|
},
|
|
{
|
|
path: '/im/monitor',
|
|
name: 'ImMonitor',
|
|
component: () => import('@/views/im/monitor.vue'),
|
|
meta: { title: 'IM性能监测' }
|
|
},
|
|
{
|
|
path: '/im/service',
|
|
name: 'ImService',
|
|
component: () => import('@/views/im/service.vue'),
|
|
meta: { title: 'IM服务监测' }
|
|
},
|
|
{
|
|
path: '/im/config',
|
|
name: 'ImConfig',
|
|
component: () => import('@/views/im/config.vue'),
|
|
meta: { title: 'IM配置界面' }
|
|
},
|
|
{
|
|
path: '/im/message',
|
|
name: 'ImMessage',
|
|
component: () => import('@/views/im/message.vue'),
|
|
meta: { title: '消息与公告管理' }
|
|
}
|
|
]
|
|
},
|
|
{
|
|
path: '/:pathMatch(.*)*',
|
|
redirect: '/404',
|
|
meta: { hidden: true }
|
|
}
|
|
]
|
|
|
|
const router = createRouter({
|
|
history: createWebHistory(),
|
|
routes: constantRoutes,
|
|
scrollBehavior: () => ({ top: 0 })
|
|
})
|
|
|
|
// 拍平菜单树,收集页面节点
|
|
export function flattenMenus(menus, arr = []) {
|
|
for (const m of menus || []) {
|
|
if (m.menuType === 1 && !SPECIAL_PAGES.has(m.component)) {
|
|
arr.push(m)
|
|
}
|
|
if (m.children?.length) flattenMenus(m.children, arr)
|
|
}
|
|
return arr
|
|
}
|
|
|
|
// 根据菜单动态注册业务路由
|
|
export function registerDynamicRoutes(menus) {
|
|
const pages = flattenMenus(menus)
|
|
for (const p of pages) {
|
|
if (router.hasRoute(p.name)) continue
|
|
const table = resolveTable(p.component)
|
|
router.addRoute('root', {
|
|
path: p.path,
|
|
name: p.path || p.component,
|
|
component: () => import('@/components/CrudPage.vue'),
|
|
meta: {
|
|
title: p.title || p.name,
|
|
tableName: table,
|
|
component: p.component,
|
|
detailRoute: resolveDetail(p.component),
|
|
printTemplate: resolvePrint(p.component),
|
|
workflow: resolveWorkflow(p.component)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
let guardInited = false
|
|
|
|
router.beforeEach(async (to, from, next) => {
|
|
const userStore = useUserStore()
|
|
|
|
if (to.path === '/login') {
|
|
// 退出登录/未登录跳转登录页时清空页签
|
|
useTabsStore().reset()
|
|
next()
|
|
return
|
|
}
|
|
|
|
if (!userStore.isLogin) {
|
|
next(`/login?redirect=${encodeURIComponent(to.fullPath)}`)
|
|
return
|
|
}
|
|
|
|
// 已登录:首次进入加载菜单并注册动态路由
|
|
if (!userStore.loaded) {
|
|
try {
|
|
await userStore.loadMenus()
|
|
registerDynamicRoutes(userStore.menus)
|
|
initAffixTabs()
|
|
guardInited = true
|
|
next({ ...to, replace: true })
|
|
} catch (e) {
|
|
userStore.logout()
|
|
next(`/login?redirect=${encodeURIComponent(to.fullPath)}`)
|
|
}
|
|
return
|
|
}
|
|
|
|
// 刷新后路由已注册但 guard 标记未恢复(页面刷新时 addRoute 丢失)
|
|
if (!guardInited) {
|
|
registerDynamicRoutes(userStore.menus)
|
|
initAffixTabs()
|
|
guardInited = true
|
|
next({ ...to, replace: true })
|
|
return
|
|
}
|
|
|
|
next()
|
|
})
|
|
|
|
/** 初始化固定页签(工作台) */
|
|
function initAffixTabs() {
|
|
useTabsStore().addTab({
|
|
path: '/workbench',
|
|
fullPath: '/workbench',
|
|
name: 'WorkBench',
|
|
meta: { title: '工作台', affix: true }
|
|
})
|
|
}
|
|
|
|
// 导航完成后:记录页签、同步浏览器标题(格式与 CrudPage 保持一致)
|
|
router.afterEach((to) => {
|
|
useTabsStore().addTab(to)
|
|
const title = to.meta?.title
|
|
document.title = title ? `${title} - F9智慧缫丝系统` : 'F9智慧缫丝系统'
|
|
})
|
|
|
|
export default router
|