feat: 新增可配置通知中心,支持扫描式/埋点式通知规则与手动群发

新增通知规则实体、扫描任务、API与管理界面,重构站内通知支持用户/电工双类型,移除硬编码的证照到期提醒,新增工单派单、电工审核结果等通知触发场景,调整菜单与数据库结构适配新通知体系。
This commit is contained in:
andyesfly committed 2026-10-06 11:53:02 +08:00
1 parent 91aa3c06f0
commit 6cf6a3d5b9
36 files changed
+3309 -246

No files matched your search

+37
View File
@@ -10,6 +10,7 @@ import Worker from "../entity/worker.entity";
import SysUserRole from "../entity/sysUserRole.entity";
import SysRole from "../entity/sysRole.entity";
import { LogService } from "./log.service";
import { NoticeRuleService } from "./notice_rule.service";
// 维保派单状态:0已派发 1已完成
const STATUS = { DISPATCHED: 0, COMPLETED: 1 };
@@ -37,6 +38,9 @@ export class MaintenanceService {
@Inject()
logService!: LogService;
@Inject()
noticeRuleService!: NoticeRuleService;
private async isAdmin(userId: number): Promise<boolean> {
const userRoles = await this.userRoleModel.findAll({ where: { userId }, include: [this.roleModel] });
return userRoles.some((ur) => (ur as any).role?.roleCode === "ADMIN");
@@ -199,6 +203,22 @@ export class MaintenanceService {
await this.decorate([vo]);
vo.details = detailRows.map((d) => d.toJSON());
await this.logService.logAction(ctx, "维保派单", "创建", created.maintenanceNo, `创建维保派单 ${created.maintenanceNo}`);
// 派单站内通知(埋点式;通知失败不得阻断业务)
if (created.workerId) {
try {
await this.noticeRuleService.notifyDispatchAssign({
orderTypeName: "维保",
orderNo: created.maintenanceNo,
customerId: Number(created.customerId),
workerId: Number(created.workerId),
detailText: created.maintenanceDate ? `维保日期:${created.maintenanceDate}。` : "",
bizType: "maintenance_order",
bizId: Number(created.id)
});
} catch (err) {
console.error("[notice] 维保派单通知失败:", err);
}
}
return { code: 200, message: "创建维保派单成功", data: vo };
}
@@ -228,6 +248,7 @@ export class MaintenanceService {
const t = await this.orderModel.sequelize!.transaction();
const detailRows: MaintenanceDetail[] = [];
const oldWorkerId = record.workerId ? Number(record.workerId) : null;
try {
await record.update(payload, { transaction: t });
if (details.length) {
@@ -247,6 +268,22 @@ export class MaintenanceService {
await this.decorate([vo]);
vo.details = detailRows.map((d) => d.toJSON());
await this.logService.logAction(ctx, "维保派单", "更新", record.maintenanceNo, `更新维保派单 ${record.maintenanceNo}`);
// 改派站内通知(派单对象变化时提醒新电工)
if (record.workerId && Number(record.workerId) !== oldWorkerId) {
try {
await this.noticeRuleService.notifyDispatchAssign({
orderTypeName: "维保",
orderNo: record.maintenanceNo,
customerId: Number(record.customerId),
workerId: Number(record.workerId),
detailText: record.maintenanceDate ? `维保日期:${record.maintenanceDate}。` : "",
bizType: "maintenance_order",
bizId: Number(record.id)
});
} catch (err) {
console.error("[notice] 维保派单通知失败:", err);
}
}
return { code: 200, message: "更新维保派单成功", data: vo };
}