feat: 用户与权限管理

新增 PermissionCode 权限类型与用户/权限 API,路由注册用户设置/创建/权限页与无权访问页并接入权限守卫,AppSidebar 按权限过滤菜单并新增用户设置入口,auth store 与 mock 适配器同步支持用户管理与新登录认证,回归脚本与 npm 脚本注册。
This commit is contained in:
caoxiaozhu
2026-07-14 16:10:50 +08:00
parent 2bceb686c6
commit e09c6e81df
8 changed files with 296 additions and 28 deletions

View File

@@ -1,5 +1,6 @@
import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router'
import { useAuthStore } from '@/stores/auth'
import type { PermissionCode } from '@/types'
const routes: RouteRecordRaw[] = [
{
@@ -191,6 +192,12 @@ const routes: RouteRecordRaw[] = [
meta: { title: '数据类型转换' },
},
// 系统设置
{
path: 'permission-denied',
name: 'permission-denied',
component: () => import('@/views/system/PermissionDeniedView.vue'),
meta: { title: '无权访问', skipPermission: true },
},
{
path: 'hardware',
name: 'hardware',
@@ -203,6 +210,24 @@ const routes: RouteRecordRaw[] = [
component: () => import('@/views/system/LogsView.vue'),
meta: { title: '查看日志' },
},
{
path: 'user-settings',
name: 'user-settings',
component: () => import('@/views/system/UserSettingsView.vue'),
meta: { title: '用户设置', pageSurface: 'self', permission: 'user-settings' },
},
{
path: 'user-settings/create',
name: 'user-create',
component: () => import('@/views/system/UserCreateView.vue'),
meta: { title: '创建用户', permission: 'user-settings' },
},
{
path: 'user-settings/:id/permission',
name: 'user-permission',
component: () => import('@/views/system/UserPermissionView.vue'),
meta: { title: '权限设置', permission: 'user-settings' },
},
{
path: 'training-log/:id',
name: 'training-log',
@@ -222,6 +247,29 @@ const router = createRouter({
routes,
})
const permissionBySegment: Record<string, PermissionCode> = {
dashboard: 'dashboard',
'fine-tune': 'fine-tune',
'training-log': 'fine-tune',
'model-eval': 'model-eval',
'model-inference': 'model-inference',
'model-compare': 'model-inference',
'model-manage': 'model-manage',
dataset: 'dataset',
'data-process': 'data-process',
'data-convert': 'data-convert',
tools: 'data-convert',
hardware: 'hardware',
logs: 'logs',
'user-settings': 'user-settings',
}
function requiredPermission(path: string, explicit?: unknown) {
if (explicit) return explicit as PermissionCode
const segment = path.split('/')[1]
return permissionBySegment[segment]
}
// 全局守卫:登录校验 + 会话超时
router.beforeEach((to, _from, next) => {
const auth = useAuthStore()
@@ -242,6 +290,14 @@ router.beforeEach((to, _from, next) => {
return
}
if (!to.meta.skipPermission) {
const permission = requiredPermission(to.path, to.meta.permission)
if (permission && !auth.hasPermission(permission)) {
next({ name: 'permission-denied', replace: true })
return
}
}
// 续期会话
auth.refresh()
next()