refactor: 系统权限模块重构,迁移至PostgreSQL并对齐新设计

- 切换数据库为PostgreSQL,更新依赖与配置
- 重构权限体系,使用sys_user/sys_role/sys_menu等新实体替代旧模型
- 移除旧的用户角色/权限/系统设置相关代码与实体
- 新增字典、菜单管理模块与基础CRUD接口
- 优化鉴权逻辑,基于菜单权限标识进行接口校验
- 前端同步更新API、路由与权限控制逻辑
- 删除冗余的v-permission指令与相关代码
This commit is contained in:
andyesfly committed 2026-08-19 14:11:34 +08:00
1 parent 98c22f6afb
commit 0a8103f33d
67 files changed
+3263 -1924

No files matched your search

+42 -50
View File
@@ -2,56 +2,41 @@ import { Middleware, IMiddleware } from '@midwayjs/core';
import { Context, NextFunction } from '@midwayjs/koa';
import { Provide, Inject } from '@midwayjs/core';
import { InjectRepository } from '@midwayjs/sequelize';
import OperationLog from '../entity/operationLog.entity';
import SysOperationLog from '../entity/sysOperationLog.entity';
@Provide()
export class LogMiddleware implements IMiddleware<Context, NextFunction> {
// 中间件匹配范围:全局生效,跳过日志查询、健康检查与登录(登录由内部记录)
ignore = ['/api/logs/*', '/api/health', '/api/auth/login'];
@InjectRepository(OperationLog)
logModel!: typeof OperationLog;
@InjectRepository(SysOperationLog)
logModel!: typeof SysOperationLog;
resolve() {
return async (ctx: Context, next: NextFunction) => {
const startTime = Date.now();
let logData: any = {};
await next();
try {
logData = {
method: ctx.method,
url: ctx.url,
ipAddress: ctx.ip,
userAgent: ctx.header['user-agent'],
requestParams: JSON.stringify(ctx.request.body || {}),
};
if (ctx.state.user) {
logData.userId = ctx.state.user.userId;
logData.username = ctx.state.user.username;
}
await next();
logData.statusCode = ctx.status;
logData.duration = Date.now() - startTime;
if (['POST', 'PUT', 'DELETE'].includes(ctx.method)) {
logData.action = this.getActionDescription(ctx);
logData.module = this.getModuleFromUrl(ctx.url);
this.saveLog(logData).catch(err => {
console.error('保存操作日志失败:', err);
});
}
} catch (error: any) {
logData.statusCode = 500;
logData.duration = Date.now() - startTime;
logData.errorMessage = error.message;
this.saveLog(logData).catch(() => {});
throw error;
// 仅记录写操作,且要求登录用户存在
if (!['POST', 'PUT', 'DELETE'].includes(ctx.method)) {
return;
}
if (!ctx.state.user) {
return;
}
const logData = {
userId: ctx.state.user.userId,
module: this.getModuleFromUrl(ctx.url),
action: this.getActionDescription(ctx),
method: ctx.method,
params: JSON.stringify(ctx.request.body || {}),
ip: ctx.ip,
};
this.saveLog(logData).catch(err => {
console.error('保存操作日志失败:', err);
});
};
}
@@ -59,23 +44,30 @@ export class LogMiddleware implements IMiddleware<Context, NextFunction> {
const actionMap: Record<string, Record<string, string>> = {
'/api/auth/login': { POST: '用户登录' },
'/api/auth/logout': { POST: '用户登出' },
'/api/user': {
'/api/users': {
POST: '创建用户',
PUT: '更新用户',
DELETE: '删除用户',
},
'/api/role': {
'/api/roles': {
POST: '创建角色',
PUT: '更新角色',
DELETE: '删除角色',
},
'/api/settings': {
PUT: '修改系统设置',
'/api/menus': {
POST: '创建菜单',
PUT: '更新菜单',
DELETE: '删除菜单',
},
'/api/dicts': {
POST: '创建字典',
PUT: '更新字典',
DELETE: '删除字典',
},
};
const basePath = ctx.url.split('?')[0];
if (actionMap[basePath]?.[ctx.method]) {
return actionMap[basePath][ctx.method];
}
@@ -92,10 +84,10 @@ export class LogMiddleware implements IMiddleware<Context, NextFunction> {
private getModuleFromUrl(url: string): string {
const moduleMap: Record<string, string> = {
'/api/auth': '认证',
'/api/user': '用户管理',
'/api/role': '角色管理',
'/api/settings': '系统设置',
'/api/log': '日志管理',
'/api/users': '用户管理',
'/api/roles': '角色管理',
'/api/menus': '菜单管理',
'/api/dicts': '数据字典',
'/api/logs': '日志管理',
'/api/dashboard': '仪表盘',
};