reminder_service.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. import type { VariablesContext } from "../middlewares.ts";
  2. export class ReminderService {
  3. private c: VariablesContext;
  4. constructor(context: VariablesContext) {
  5. this.c = context;
  6. }
  7. /**
  8. * 检查即将超时的工单并发送提醒
  9. * @param hoursBefore 超前多少小时提醒
  10. */
  11. async checkUpcomingDeadlines(hoursBefore = 2): Promise<void> {
  12. const apiClient = this.c.get('apiClient');
  13. const now = new Date();
  14. const deadlineThreshold = new Date(now.getTime() + hoursBefore * 60 * 60 * 1000);
  15. // 获取即将超时的工单
  16. // 获取6小时内已提醒的工单ID
  17. const remindedOrders = await apiClient.database.table('work_order_reminders')
  18. .where('reminded_at', '>=', new Date(now.getTime() - 6 * 60 * 60 * 1000).toISOString())
  19. .select('work_order_id');
  20. const orders = await apiClient.database.table('work_orders')
  21. .where('status', 'in_progress')
  22. .where('deadline', '<=', deadlineThreshold.toISOString())
  23. .where('deadline', '>', now.toISOString())
  24. .whereNot('id', 'in', remindedOrders.map(o => o.work_order_id))
  25. .select();
  26. for (const order of orders) {
  27. // 发送提醒
  28. await this.sendReminder(order);
  29. // 记录提醒日志
  30. await apiClient.database.table('work_order_reminders').insert({
  31. work_order_id: order.id,
  32. reminded_at: now,
  33. deadline: order.deadline,
  34. recipient_id: order.assignee_id,
  35. created_at: now
  36. });
  37. }
  38. }
  39. /**
  40. * 发送超时提醒通知
  41. * @param order 工单信息
  42. */
  43. private async sendReminder(order: any): Promise<void> {
  44. const apiClient = this.c.get('apiClient');
  45. // 这里实现实际的通知逻辑,例如:
  46. // 1. 发送站内消息
  47. await apiClient.database.table('messages').insert({
  48. user_id: order.assignee_id,
  49. title: `工单即将超时: #${order.id}`,
  50. content: `您的工单 #${order.id} 将在2小时内超时,请及时处理`,
  51. created_at: apiClient.database.fn.now()
  52. });
  53. // 2. 记录系统日志
  54. await apiClient.database.table('system_logs').insert({
  55. action: 'work_order_reminder',
  56. target_id: order.id,
  57. user_id: 0, // system
  58. details: JSON.stringify({
  59. order_id: order.id,
  60. assignee_id: order.assignee_id,
  61. deadline: order.deadline
  62. }),
  63. created_at: apiClient.database.fn.now()
  64. });
  65. }
  66. /**
  67. * 检查已超时工单
  68. */
  69. async checkTimeoutOrders(): Promise<void> {
  70. const apiClient = this.c.get('apiClient');
  71. const now = new Date();
  72. const orders = await apiClient.database.table('work_orders')
  73. .where('status', 'in_progress')
  74. .where('deadline', '<', now.toISOString())
  75. .select();
  76. for (const order of orders) {
  77. // 记录超时日志
  78. await apiClient.database.table('work_order_timeout_logs').insert({
  79. work_order_id: order.id,
  80. timeout_at: now,
  81. created_at: now
  82. });
  83. // 更新超时计数
  84. await apiClient.database.table('work_orders')
  85. .where('id', order.id)
  86. .update({
  87. timeout_count: apiClient.database.raw('timeout_count + 1'),
  88. updated_at: now
  89. });
  90. }
  91. }
  92. }