feat: 用户与权限管理
新增 PermissionCode 权限类型与用户/权限 API,路由注册用户设置/创建/权限页与无权访问页并接入权限守卫,AppSidebar 按权限过滤菜单并新增用户设置入口,auth store 与 mock 适配器同步支持用户管理与新登录认证,回归脚本与 npm 脚本注册。
This commit is contained in:
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user