feat: 初始化项目基础架构和核心功能
- 添加项目基础结构:Cargo.toml、.gitignore、设备UID和密钥文件 - 实现前端Vue3项目结构:路由、登录页面、设备管理页面 - 添加核心协议定义(crates/protocol):设备状态、资产、USB事件等 - 实现客户端监控模块:系统状态收集、资产收集 - 实现服务端基础API和插件系统 - 添加数据库迁移脚本:设备管理、资产跟踪、告警系统等 - 实现前端设备状态展示和基本交互 - 添加使用时长统计和水印功能插件
This commit is contained in:
63
web/src/router/index.ts
Normal file
63
web/src/router/index.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
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: 'assets', name: 'Assets', component: () => import('../views/Assets.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') },
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
/** Check if a JWT token is structurally valid and not expired */
|
||||
function isTokenValid(token: string): boolean {
|
||||
if (!token || token.trim() === '') return false
|
||||
try {
|
||||
const parts = token.split('.')
|
||||
if (parts.length !== 3) return false
|
||||
const payload = JSON.parse(atob(parts[1]))
|
||||
if (!payload.exp) return false
|
||||
// Reject if token expires within 30 seconds
|
||||
return payload.exp * 1000 > Date.now() + 30_000
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
router.beforeEach((to, _from, next) => {
|
||||
if (to.path === '/login') {
|
||||
next()
|
||||
return
|
||||
}
|
||||
|
||||
const token = localStorage.getItem('token')
|
||||
if (!token || !isTokenValid(token)) {
|
||||
localStorage.removeItem('token')
|
||||
localStorage.removeItem('refresh_token')
|
||||
next('/login')
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
})
|
||||
|
||||
export default router
|
||||
Reference in New Issue
Block a user