IMS系统工作流通知机制完全指南

工作流通知是保障流程顺利执行的重要机制,包括待办提醒、催办通知、流程状态变更通知等。本文详细介绍 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;
}

通知优化建议

  • 合理设置静默时段,避免打扰用户休息
  • 重要通知使用多渠道确保送达
  • 逾期任务增加短信通知提高处理率
  • 提供用户自定义通知偏好的能力

总结

  • 多渠道:支持站内信、邮件、短信、微信
  • 事件驱动:工作流事件自动触发通知
  • 定时任务:逾期检查和定期提醒
  • 用户偏好:支持通知设置和静默时段
  • 模板系统:灵活的消息模板支持