feat(protocol): 添加补丁管理和行为指标协议类型 feat(client): 实现补丁管理插件采集功能 feat(server): 添加补丁管理和异常检测API feat(database): 新增补丁状态和异常检测相关表 feat(web): 添加补丁管理和异常检测前端页面 fix(security): 增强输入验证和防注入保护 refactor(auth): 重构认证检查逻辑 perf(service): 优化Windows服务恢复策略 style: 统一健康评分显示样式 docs: 更新知识库文档
70 lines
3.2 KiB
TypeScript
70 lines
3.2 KiB
TypeScript
import { createRouter, createWebHistory } from 'vue-router'
|
|
import AppLayout from '../views/Layout.vue'
|
|
|
|
const router = createRouter({
|
|
history: createWebHistory(),
|
|
routes: [
|
|
{ path: '/login', name: 'Login', component: () => import('../views/Login.vue') },
|
|
{
|
|
path: '/',
|
|
component: AppLayout,
|
|
redirect: '/dashboard',
|
|
children: [
|
|
{ path: 'dashboard', name: 'Dashboard', component: () => import('../views/Dashboard.vue') },
|
|
{ path: 'devices', name: 'Devices', component: () => import('../views/Devices.vue') },
|
|
{ path: 'devices/:uid', name: 'DeviceDetail', component: () => import('../views/DeviceDetail.vue') },
|
|
{ path: 'usb', name: 'UsbPolicy', component: () => import('../views/UsbPolicy.vue') },
|
|
{ path: 'alerts', name: 'Alerts', component: () => import('../views/Alerts.vue') },
|
|
{ path: 'settings', name: 'Settings', component: () => import('../views/Settings.vue') },
|
|
// Phase 2: Plugin pages
|
|
{ path: 'plugins/web-filter', name: 'WebFilter', component: () => import('../views/plugins/WebFilter.vue') },
|
|
{ path: 'plugins/usage-timer', name: 'UsageTimer', component: () => import('../views/plugins/UsageTimer.vue') },
|
|
{ path: 'plugins/software-blocker', name: 'SoftwareBlocker', component: () => import('../views/plugins/SoftwareBlocker.vue') },
|
|
{ path: 'plugins/popup-blocker', name: 'PopupBlocker', component: () => import('../views/plugins/PopupBlocker.vue') },
|
|
{ path: 'plugins/usb-file-audit', name: 'UsbFileAudit', component: () => import('../views/plugins/UsbFileAudit.vue') },
|
|
{ path: 'plugins/watermark', name: 'Watermark', component: () => import('../views/plugins/Watermark.vue') },
|
|
{ path: 'plugins/disk-encryption', name: 'DiskEncryption', component: () => import('../views/plugins/DiskEncryption.vue') },
|
|
{ path: 'plugins/print-audit', name: 'PrintAudit', component: () => import('../views/plugins/PrintAudit.vue') },
|
|
{ path: 'plugins/clipboard-control', name: 'ClipboardControl', component: () => import('../views/plugins/ClipboardControl.vue') },
|
|
{ path: 'plugins/plugin-control', name: 'PluginControl', component: () => import('../views/plugins/PluginControl.vue') },
|
|
{ path: 'plugins/patch', name: 'PatchManagement', component: () => import('../views/plugins/PatchManagement.vue') },
|
|
{ path: 'plugins/anomaly', name: 'AnomalyDetection', component: () => import('../views/plugins/AnomalyDetection.vue') },
|
|
],
|
|
},
|
|
],
|
|
})
|
|
|
|
/** Track whether we've already validated auth this session */
|
|
let authChecked = false
|
|
|
|
router.beforeEach(async (to, _from, next) => {
|
|
if (to.path === '/login') {
|
|
next()
|
|
return
|
|
}
|
|
|
|
// If we've already verified auth this session, allow navigation
|
|
// (cookies are sent automatically, no need to check on every route change)
|
|
if (authChecked) {
|
|
next()
|
|
return
|
|
}
|
|
|
|
// Check auth status via /api/auth/me (reads access_token cookie)
|
|
try {
|
|
const { me } = await import('../lib/api')
|
|
await me()
|
|
authChecked = true
|
|
next()
|
|
} catch {
|
|
next('/login')
|
|
}
|
|
})
|
|
|
|
/** Reset auth check flag (called after logout) */
|
|
export function resetAuthCheck() {
|
|
authChecked = false
|
|
}
|
|
|
|
export default router
|