工作流通知是保障流程顺利执行的重要机制,包括待办提醒、催办通知、流程状态变更通知等。本文详细介绍 IMS 系统的工作流通知实现方案。
通知类型定义
系统支持多种通知类型:
/* 通知类型枚举 */
enum NotificationType {
TASK_ASSIGNED = 'task_assigned', // 任务分配
TASK_COMPLETED = 'task_completed', // 任务完成
TASK_OVERDUE = 'task_overdue', // 任务逾期
TASK_REMINDER = 'task_reminder', // 任务提醒
PROCESS_STARTED = 'process_started', // 流程启动
PROCESS_COMPLETED = 'process_completed', // 流程完成
PROCESS_REJECTED = 'process_rejected', // 流程驳回
PROCESS_TRANSFERRED = 'process_transferred' // 流程转交
}
/* 通知渠道 */
enum Channel {
IN_APP = 'in_app', // 站内消息
EMAIL = 'email', // 邮件
SMS = 'sms', // 短信
WECHAT = 'wechat' // 微信
}
/* 通知消息 */
interface Notification {
id: string;
userId: string;
type: NotificationType;
channels: Channel[];
title: string;
content: string;
data: Record<string, any>;
read: boolean;
createdAt: Date;
}
通知服务架构
通知服务采用发布订阅模式:
/* 通知服务 */
class NotificationService {
constructor() {
this.channels = {
[Channel.IN_APP]: new InAppChannel(),
[Channel.EMAIL]: new EmailChannel(),
[Channel.SMS]: new SMSChannel(),
[Channel.WECHAT]: new WeChatChannel()
};
}
/* 发送通知 */
async send(notification: Notification) {
/* 根据用户设置决定发送渠道 */
const enabledChannels = getEnabledChannels(notification.userId);
const promises = enabledChannels.map(channel => {
return this.channels[channel].send(notification);
});
await Promise.allSettled(promises);
/* 记录通知历史 */
await saveNotificationLog(notification);
}
/* 批量发送 */
async sendBatch(notifications: Notification[]) {
const chunks = chunk(notifications, 100);
for (const chunk of chunks) {
await Promise.all(
chunk.map(n => this.send(n))
);
}
}
}
事件驱动通知
工作流引擎通过事件触发通知:
/* 工作流事件监听器 */
class WorkflowEventListener {
constructor(notificationService) {
this.notificationService = notificationService;
}
/* 任务创建事件 */
async onTaskCreated(task) {
const notification = {
userId: task.assignee,
type: NotificationType.TASK_ASSIGNED,
channels: [Channel.IN_APP, Channel.EMAIL],
title: `新审批任务:${task.processName}`,
content: buildTaskContent(task),
data: { taskId: task.id, processId: task.processId }
};
await this.notificationService.send(notification);
}
/* 任务完成事件 */
async onTaskCompleted(task, result) {
/* 通知流程发起人 */
const process = getProcessById(task.processId);
const notification = {
userId: process.initiator,
type: NotificationType.TASK_COMPLETED,
channels: [Channel.IN_APP],
title: `任务已处理:${task.name}`,
content: `审批人:${result.operator},结果:${result.result}`,
data: { taskId: task.id, result: result.result }
};
await this.notificationService.send(notification);
}
/* 流程驳回事件 */
async onProcessRejected(processInstance) {
const notification = {
userId: processInstance.initiator,
type: NotificationType.PROCESS_REJECTED,
channels: [Channel.IN_APP, Channel.EMAIL],
title: `流程已驳回:${processInstance.name}`,
content: `您的申请已被驳回,请查看详情`,
data: { processId: processInstance.id }
};
await this.notificationService.send(notification);
}
}
定时提醒任务
使用定时任务处理逾期和定期提醒:
/* 定时提醒调度器 */
class ReminderScheduler {
constructor(notificationService) {
this.notificationService = notificationService;
}
/* 每日定时检查逾期任务 */
async checkOverdueTasks() {
const overdueTasks = await taskService.findOverdue();
for (const task of overdueTasks) {
/* 检查是否已发送过逾期通知 */
if (!hasSentOverdueNotification(task.id)) {
await this.notificationService.send({
userId: task.assignee,
type: NotificationType.TASK_OVERDUE,
channels: [Channel.IN_APP, Channel.SMS],
title: `任务已逾期:${task.name}`,
content: `该任务已逾期,请尽快处理`,
data: { taskId: task.id }
});
await markOverdueNotificationSent(task.id);
}
}
}
/* 定期提醒未完成任务 */
async sendTaskReminders() {
/* 获取今天到期的任务 */
const tasksDueToday = await taskService.findDueToday();
for (const task of tasksDueToday) {
await this.notificationService.send({
userId: task.assignee,
type: NotificationType.TASK_REMINDER,
channels: [Channel.IN_APP],
title: `任务待处理:${task.name}`,
content: `该任务今日到期,请及时处理`,
data: { taskId: task.id, dueDate: task.dueDate }
});
}
}
/* 提前提醒 */
async sendAdvanceReminders() {
/* 提前1天、3天提醒 */
const advanceDays = [1, 3];
for (const days of advanceDays) {
const tasks = await taskService.findDueAfterDays(days);
for (const task of tasks) {
await this.notificationService.send({
userId: task.assignee,
type: NotificationType.TASK_REMINDER,
channels: [Channel.IN_APP],
title: `任务提醒:${task.name}`,
content: `该任务将在 ${days} 天后到期`,
data: { taskId: task.id, daysRemaining: days }
});
}
}
}
}
用户订阅管理
支持用户自定义通知偏好:
/* 用户通知设置 */
interface UserNotificationSettings {
userId: string;
enabled: boolean;
channels: {
inApp: boolean;
email: boolean;
sms: boolean;
wechat: boolean;
};
types: {
taskAssigned: boolean;
taskCompleted: boolean;
taskOverdue: boolean;
processCompleted: boolean;
};
quietHours: {
enabled: boolean;
start: string; // "22:00"
end: string; // "08:00"
};
}
/* 获取用户启用的通知渠道 */
function getEnabledChannels(userId) {
const settings = getUserSettings(userId);
if (!settings.enabled) return [];
return Object.entries(settings.channels)
.filter(([, enabled]) => enabled)
.map(([channel]) => channel);
}
通知模板
灵活的消息模板系统:
/* 通知模板 */
const NOTIFICATION_TEMPLATES = {
task_assigned: {
title: '新审批任务:{{processName}}',
content: `您有一个新的审批任务:{{taskName}}
申请人:{{initiator}}
申请时间:{{createTime}}
截止时间:{{dueTime}}`
},
task_overdue: {
title: '任务已逾期:{{taskName}}',
content: `您好,您待处理的任务 "{{taskName}}" 已逾期。
原截止时间:{{dueTime}}
逾期天数:{{overdueDays}}
请尽快处理!`
},
process_completed: {
title: '流程已通过:{{processName}}',
content: `恭喜!您的申请 "{{processName}}" 已通过审批。
处理时间:{{completeTime}}
审批意见:{{comment}}`
}
};
/* 渲染模板 */
function renderTemplate(templateKey, data) {
const template = NOTIFICATION_TEMPLATES[templateKey];
let result = {
title: template.title,
content: template.content
};
for (const [key, value] of Object.entries(data)) {
result.title = result.title.replace(`{{${key}}}`, value);
result.content = result.content.replace(`{{${key}}}`, value);
}
return result;
}
通知优化建议
- 合理设置静默时段,避免打扰用户休息
- 重要通知使用多渠道确保送达
- 逾期任务增加短信通知提高处理率
- 提供用户自定义通知偏好的能力
总结
- 多渠道:支持站内信、邮件、短信、微信
- 事件驱动:工作流事件自动触发通知
- 定时任务:逾期检查和定期提醒
- 用户偏好:支持通知设置和静默时段
- 模板系统:灵活的消息模板支持