workflow_engine.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import type { VariablesContext } from "../middlewares.ts";
  2. export class WorkflowEngine {
  3. private c: VariablesContext;
  4. constructor(context: VariablesContext) {
  5. this.c = context;
  6. }
  7. /**
  8. * 检查状态流转是否允许
  9. * @param fromStatus 原状态
  10. * @param toStatus 目标状态
  11. * @param userRoles 用户角色
  12. */
  13. async canTransition(fromStatus: string, toStatus: string, userRoles: string[]): Promise<boolean> {
  14. const apiClient = this.c.get('apiClient');
  15. const rule = await apiClient.database.table('work_order_status_rules')
  16. .where('from_status', fromStatus)
  17. .where('to_status', toStatus)
  18. .first();
  19. if (!rule) return false;
  20. const allowedRoles = rule.allowed_roles.split(',');
  21. return userRoles.some(role => allowedRoles.includes(role));
  22. }
  23. /**
  24. * 获取状态流转规则
  25. * @param fromStatus 原状态
  26. */
  27. async getAvailableTransitions(fromStatus: string): Promise<Array<{
  28. to_status: string;
  29. allowed_roles: string[];
  30. need_comment: boolean;
  31. }>> {
  32. const apiClient = this.c.get('apiClient');
  33. return apiClient.database.table('work_order_status_rules')
  34. .where('from_status', fromStatus)
  35. .select('to_status', 'allowed_roles', 'need_comment');
  36. }
  37. /**
  38. * 记录状态变更历史
  39. * @param workOrderId 工单ID
  40. * @param fromStatus 原状态
  41. * @param toStatus 目标状态
  42. * @param userId 操作用户ID
  43. * @param comment 备注
  44. */
  45. async logStatusChange(
  46. workOrderId: number,
  47. fromStatus: string,
  48. toStatus: string,
  49. userId: number,
  50. comment?: string
  51. ): Promise<void> {
  52. const apiClient = this.c.get('apiClient');
  53. await apiClient.database.table('work_order_status_history').insert({
  54. work_order_id: workOrderId,
  55. from_status: fromStatus,
  56. to_status: toStatus,
  57. changed_by: userId,
  58. comment,
  59. created_at: apiClient.database.fn.now()
  60. });
  61. }
  62. /**
  63. * 检查并处理超时状态
  64. * @param workOrderId 工单ID
  65. */
  66. async checkTimeout(workOrderId: number): Promise<void> {
  67. const apiClient = this.c.get('apiClient');
  68. const [order] = await apiClient.database.table('work_orders')
  69. .where('id', workOrderId)
  70. .select();
  71. if (!order.deadline || order.status !== 'in_progress') return;
  72. const now = new Date();
  73. if (new Date(order.deadline) < now) {
  74. // 记录超时日志
  75. await apiClient.database.table('work_order_timeout_logs').insert({
  76. work_order_id: workOrderId,
  77. timeout_at: now,
  78. created_at: now
  79. });
  80. // 更新超时计数
  81. await apiClient.database.table('work_orders')
  82. .where('id', workOrderId)
  83. .update({
  84. timeout_count: apiClient.database.raw('timeout_count + 1'),
  85. updated_at: now
  86. });
  87. // 如果超时超过3次,自动升级
  88. if (order.timeout_count >= 2) { // 从0开始计数
  89. await apiClient.database.table('work_orders')
  90. .where('id', workOrderId)
  91. .update({
  92. status: 'escalated',
  93. escalation_level: apiClient.database.raw('escalation_level + 1'),
  94. updated_at: now
  95. });
  96. await this.logStatusChange(
  97. workOrderId,
  98. order.status,
  99. 'escalated',
  100. 0, // system user
  101. '自动升级:工单多次超时'
  102. );
  103. }
  104. }
  105. }
  106. }