feat: 新增电工APP端与定时任务管理功能
- 新增电工APP独立鉴权中间件与登录注册接口 - 新增定时任务管理模块,支持任务配置、执行日志与手动触发 - 新增运维费定价与电工派单成本价目管理 - 新增电工资质证照管理与到期提醒定时任务 - 完善数据库实体与DTO校验,优化权限控制
This commit is contained in:
1 parent
1803ad679c
commit
f4454ad014
57 files changed
+9388
-200
No files matched your search
@@ -5,8 +5,8 @@ import { TokenUtil } from '../util/token';
|
||||
|
||||
@Provide()
|
||||
export class AuthMiddleware implements IMiddleware<Context, NextFunction> {
|
||||
// 中间件匹配范围:全局生效,但跳过公开接口
|
||||
ignore = ['/api/auth/*', '/api/health'];
|
||||
// 中间件匹配范围:全局生效,但跳过公开接口与电工 APP 接口(电工 APP 走独立鉴权)
|
||||
ignore = ['/api/auth/*', '/api/health', '/api/worker-app/*'];
|
||||
|
||||
@Inject()
|
||||
tokenUtil!: TokenUtil;
|
||||
|
||||
@@ -13,6 +13,7 @@ const PERMISSION_MAP: Record<string, string> = {
|
||||
'/api/menus': 'system:menu',
|
||||
'/api/dicts': 'system:dict',
|
||||
'/api/logs': 'system:log',
|
||||
'/api/jobs': 'system:job',
|
||||
'/api/customers': 'customer:list',
|
||||
'/api/customer-departments': 'customer:department',
|
||||
'/api/customer-accounts': 'customer:account',
|
||||
@@ -26,6 +27,9 @@ const PERMISSION_MAP: Record<string, string> = {
|
||||
'/api/install-orders': 'project:install',
|
||||
'/api/acceptances': 'project:acceptance',
|
||||
'/api/visit-records': 'project:visit',
|
||||
'/api/service-prices': 'dispatch:price',
|
||||
'/api/dispatch-prices': 'dispatch:cost',
|
||||
'/api/workers': 'dispatch:worker',
|
||||
};
|
||||
|
||||
// 超级管理员角色编码,拥有全部权限
|
||||
@@ -33,8 +37,17 @@ const ADMIN_ROLE_CODE = 'ADMIN';
|
||||
|
||||
@Provide()
|
||||
export class RbacMiddleware implements IMiddleware<Context, NextFunction> {
|
||||
// 中间件匹配范围:全局生效,跳过公开接口与仪表盘
|
||||
ignore = ['/api/auth/*', '/api/health', '/api/dashboard/*'];
|
||||
// 中间件匹配范围:全局生效,跳过公开接口、仪表盘与电工 APP 接口
|
||||
// /api/workers/options 与 /api/workers/recommend 放行:业务员在「项目勘察派单」页
|
||||
// 仍可调用电工下拉与推荐接口,不受 dispatch:worker 权限限制(本次需求有意设计)
|
||||
ignore = [
|
||||
'/api/auth/*',
|
||||
'/api/health',
|
||||
'/api/dashboard/*',
|
||||
'/api/worker-app/*',
|
||||
'/api/workers/options',
|
||||
'/api/workers/recommend',
|
||||
];
|
||||
|
||||
@Inject()
|
||||
permissionService!: PermissionService;
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
import { Middleware, IMiddleware } from '@midwayjs/core';
|
||||
import { Context, NextFunction } from '@midwayjs/koa';
|
||||
import { Provide, Inject } from '@midwayjs/core';
|
||||
import { TokenUtil } from '../util/token';
|
||||
|
||||
// 电工 APP 独立鉴权中间件:
|
||||
// 与管理端 sys_user 鉴权隔离,仅作用于 /api/worker-app/* 接口,
|
||||
// 登录/注册(/api/worker-app/auth/*)无需鉴权。
|
||||
@Provide()
|
||||
export class WorkerAuthMiddleware implements IMiddleware<Context, NextFunction> {
|
||||
// 注意:Midway 不允许同时声明 match 与 ignore,故仅在 match 生效,
|
||||
// 登录/注册路径(/api/worker-app/auth/*)在内部放行。
|
||||
match = ['/api/worker-app/*'];
|
||||
|
||||
@Inject()
|
||||
tokenUtil!: TokenUtil;
|
||||
|
||||
resolve() {
|
||||
return async (ctx: Context, next: NextFunction) => {
|
||||
if (ctx.path.startsWith('/api/worker-app/auth/')) {
|
||||
await next();
|
||||
return;
|
||||
}
|
||||
|
||||
const authHeader = ctx.header.authorization;
|
||||
|
||||
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
||||
ctx.status = 401;
|
||||
ctx.body = {
|
||||
code: 401,
|
||||
message: '未登录或登录已过期',
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
const token = authHeader.substring(7);
|
||||
|
||||
let decoded: any;
|
||||
try {
|
||||
decoded = this.tokenUtil.verifyWorkerToken(token);
|
||||
} catch (error: any) {
|
||||
if (error.name === 'TokenExpiredError') {
|
||||
ctx.status = 401;
|
||||
ctx.body = {
|
||||
code: 401,
|
||||
message: '未登录或登录已过期',
|
||||
expired: true,
|
||||
};
|
||||
} else {
|
||||
ctx.status = 401;
|
||||
ctx.body = {
|
||||
code: 401,
|
||||
message: '未登录或登录已过期',
|
||||
};
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 写入当前电工上下文,供业务代码取用
|
||||
ctx.state.worker = {
|
||||
workerId: decoded.workerId,
|
||||
phone: decoded.phone,
|
||||
};
|
||||
|
||||
await next();
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user