statusMachine.ts 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. // statusMachine.ts - 完整修正版
  2. export class OrderStatusMachine {
  3. constructor(row, currentTime) {
  4. this.row = row
  5. this.currentTime = currentTime || Date.now()
  6. }
  7. // 获取当前时间(带时区处理)
  8. getCurrentTime() {
  9. // 如果传入了currentTime就直接使用
  10. if (this.currentTime) return this.currentTime
  11. let timezone = 2; // 目标时区时间,东3区
  12. let offset_GMT = new Date().getTimezoneOffset(); // 本地时间和格林威治的时间差,单位为分钟
  13. let nowDate = new Date().getTime(); // 本地时间距 1970 年 1 月 1 日午夜(GMT 时间)之间的毫秒数
  14. let now = new Date(
  15. nowDate + offset_GMT * 60 * 1000 + timezone * 60 * 60 * 1000
  16. );
  17. return now.getTime()
  18. }
  19. // 是否未过期(当前时间 < 过期时间)
  20. isNotExpired() {
  21. // 如果没有过期时间,视为未过期
  22. if (!this.row.expireTime) return true
  23. const now = this.getCurrentTime()
  24. const expireTime = new Date(this.row.expireTime).getTime()
  25. return now < expireTime
  26. }
  27. // 是否已过期(当前时间 > 过期时间,且不是最终状态)
  28. isExpired() {
  29. const r = this.row
  30. // 如果没有过期时间,不过期
  31. if (!r.expireTime) return false
  32. const now = this.getCurrentTime()
  33. const expireTime = new Date(r.expireTime).getTime()
  34. // 当前时间必须大于过期时间
  35. if (now <= expireTime) return false
  36. // 已取消的不过期
  37. if (this.isCancelled()) return false
  38. // 已拒绝的不过期
  39. if (this.isRefused()) return false
  40. // 已完成的不过期
  41. if (r.type === 1 && this.isCompletedType1()) return false
  42. if (r.type === 2 && this.isCompletedType2()) return false
  43. // 状态5已经在isCancelled中处理了,这里不需要重复判断
  44. return true
  45. }
  46. // 判断是否已完成 (type 1)
  47. isCompletedType1() {
  48. return this.row.status === 2 &&
  49. this.row.executionStatus === 2 &&
  50. this.row.callbackStatus === 1
  51. }
  52. // 判断是否已完成 (type 2)
  53. isCompletedType2() {
  54. return this.row.status === 2 &&
  55. this.row.executionStatus === 2 &&
  56. this.row.submitStatus === 2
  57. }
  58. // 判断是否已拒绝
  59. isRefused() {
  60. return this.row.callbackStatus === 2 ||
  61. this.row.status === 3 ||
  62. this.row.executionStatus === 3
  63. }
  64. // 判断是否已取消
  65. isCancelled() {
  66. return this.row.status === 5
  67. }
  68. // 判断是否为待处理状态 (type 1)
  69. isToBeProcessedType1() {
  70. const r = this.row
  71. return r.status === 1 &&
  72. r.callbackStatus === 0 &&
  73. (r.expireTime === null || this.isNotExpired())
  74. }
  75. // 判断是否为待处理状态 (type 2)
  76. isToBeProcessedType2() {
  77. const r = this.row
  78. return r.status === 1 &&
  79. r.callbackStatus === 0 &&
  80. (r.expireTime === null || this.isNotExpired())
  81. }
  82. // 判断是否为进行中状态 (type 1)
  83. isInProgressType1() {
  84. const r = this.row
  85. // 条件1: status=2, executionStatus=0或1, callbackStatus≠2, 未过期
  86. const condition1 = r.status === 2 &&
  87. [0, 1].includes(r.executionStatus) &&
  88. r.callbackStatus !== 2 &&
  89. (r.expireTime === null || this.isNotExpired())
  90. // 条件2: status=1, callbackStatus=1, 未过期
  91. const condition2 = r.status === 1 &&
  92. r.callbackStatus === 1 &&
  93. (r.expireTime === null || this.isNotExpired())
  94. return condition1 || condition2
  95. }
  96. // 判断是否为进行中状态 (type 2)
  97. isInProgressType2() {
  98. const r = this.row
  99. // 条件1: status=2, executionStatus=0或1, callbackStatus≠2
  100. const condition1 = r.status === 2 &&
  101. [0, 1].includes(r.executionStatus) &&
  102. r.callbackStatus !== 2
  103. // 条件2: status=2, executionStatus=2, callbackStatus=0, submitStatus≠2
  104. const condition2 = r.status === 2 &&
  105. r.executionStatus === 2 &&
  106. r.callbackStatus === 0 &&
  107. r.submitStatus !== 2
  108. return condition1 || condition2
  109. }
  110. // 获取状态码
  111. getStatus() {
  112. const r = this.row
  113. // 1. 优先检查已取消
  114. if (this.isCancelled()) return 6
  115. // 2. 检查已拒绝
  116. if (this.isRefused()) return 4
  117. // 3. 检查是否已完成
  118. if (r.type === 1 && this.isCompletedType1()) return 2
  119. if (r.type === 2 && this.isCompletedType2()) return 2
  120. // 4. 检查是否过期 - 按照原始逻辑,只有不是已完成、已拒绝、已取消才判断过期
  121. if (this.isExpired()) return 5
  122. // 5. 根据类型判断待处理或进行中
  123. if (r.type === 1) {
  124. if (this.isToBeProcessedType1()) return 1
  125. if (this.isInProgressType1()) return 3
  126. } else if (r.type === 2) {
  127. if (this.isToBeProcessedType2()) return 1
  128. if (this.isInProgressType2()) return 3
  129. }
  130. return null
  131. }
  132. // 获取状态信息
  133. getStatusInfo() {
  134. const status = this.getStatus()
  135. const statusMap = {
  136. 1: { text: '待处理', class: 'warning', value: 1 },
  137. 2: { text: '已完成', class: 'success', value: 2 },
  138. 3: { text: '进行中', class: 'processing', value: 3 },
  139. 4: { text: '已拒绝', class: 'danger', value: 4 },
  140. 5: { text: '已过期', class: 'expired', value: 5 },
  141. 6: { text: '已取消', class: 'cancelled', value: 6 }
  142. }
  143. return statusMap[status] || { text: '-', class: '', value: null }
  144. }
  145. // 检查是否可以取消(普通取消)
  146. canCancel() {
  147. const r = this.row
  148. // type=2 且 status=1, callbackStatus=0, 未过期
  149. if (r.type === 2 &&
  150. r.status === 1 &&
  151. r.callbackStatus === 0 &&
  152. (r.expireTime === null || this.isNotExpired())) {
  153. return 'normal'
  154. }
  155. return false
  156. }
  157. // 检查是否可以取消(后台取消)
  158. canCancelBackstage() {
  159. const r = this.row
  160. // type=2 且 status=2, executionStatus=2, backstageStatus=1
  161. if (r.type === 2 &&
  162. r.status === 2 &&
  163. r.executionStatus === 2 &&
  164. r.backstageStatus === 1) {
  165. return 'backstage'
  166. }
  167. return false
  168. }
  169. // 获取可执行的操作列表
  170. getAvailableActions() {
  171. const actions = []
  172. if (this.canCancel()) {
  173. actions.push({
  174. type: 'cancel',
  175. text: '取消',
  176. handler: 'handleCancel'
  177. })
  178. }
  179. if (this.canCancelBackstage()) {
  180. actions.push({
  181. type: 'cancelBackstage',
  182. text: '取消',
  183. handler: 'handleCancelBackstage'
  184. })
  185. }
  186. return actions
  187. }
  188. // 调试方法
  189. debug() {
  190. console.log({
  191. row: this.row,
  192. isCancelled: this.isCancelled(),
  193. isRefused: this.isRefused(),
  194. isCompletedType1: this.isCompletedType1(),
  195. isCompletedType2: this.isCompletedType2(),
  196. isExpired: this.isExpired(),
  197. isNotExpired: this.isNotExpired(),
  198. isToBeProcessedType1: this.isToBeProcessedType1(),
  199. isToBeProcessedType2: this.isToBeProcessedType2(),
  200. isInProgressType1: this.isInProgressType1(),
  201. isInProgressType2: this.isInProgressType2(),
  202. canCancel: this.canCancel(),
  203. canCancelBackstage: this.canCancelBackstage(),
  204. finalStatus: this.getStatus(),
  205. finalStatusInfo: this.getStatusInfo()
  206. })
  207. }
  208. }
  209. // 工厂函数
  210. export const createOrderStatusMachine = (row, currentTime) => {
  211. return new OrderStatusMachine(row, currentTime)
  212. }