reportGenerationStatus.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. const RUNNING_STATE = 0
  2. const SUCCESS_STATE = 1
  3. const FAILED_STATE = -1
  4. function toNumber(value) {
  5. if (value === '' || value === null || value === undefined) return undefined
  6. const numeric = Number(value)
  7. return Number.isNaN(numeric) ? undefined : numeric
  8. }
  9. function pickReportId(source) {
  10. if (source === null || source === undefined) return undefined
  11. if (typeof source === 'number') return source
  12. if (typeof source === 'string') {
  13. const numeric = toNumber(source)
  14. return numeric === undefined ? undefined : numeric
  15. }
  16. if (typeof source !== 'object') return undefined
  17. const direct = toNumber(source.reportId ?? source.id)
  18. if (direct !== undefined) return direct
  19. for (const key of ['data', 'dto', 'info']) {
  20. const nested = pickReportId(source[key])
  21. if (nested !== undefined) return nested
  22. }
  23. return undefined
  24. }
  25. function extractReportId(payload) {
  26. return pickReportId(payload)
  27. }
  28. function normalizeGenerationStatus(payload = {}) {
  29. const source = payload && typeof payload === 'object' ? payload : {}
  30. const state = toNumber(source.state)
  31. return {
  32. reportId: extractReportId(source) ?? '',
  33. state: state === undefined ? RUNNING_STATE : state,
  34. status: source.status || '',
  35. errorMessage: source.errorMessage || ''
  36. }
  37. }
  38. function applyGenerationStatus(payload = {}) {
  39. const generation = normalizeGenerationStatus(payload)
  40. if (generation.state === FAILED_STATE) {
  41. return {
  42. ...generation,
  43. title: '报告生成失败',
  44. subtitle: '',
  45. description: generation.errorMessage || '失败原因:网络延迟',
  46. errorMessage: generation.errorMessage || '网络延迟',
  47. polling: false,
  48. actionText: '重新生成',
  49. imageKey: 'fail'
  50. }
  51. }
  52. if (generation.state === SUCCESS_STATE) {
  53. return {
  54. ...generation,
  55. title: '报告生成成功',
  56. subtitle: '',
  57. description: '报告已生成完成,你可以去我的PREILL报告查阅报告结果。',
  58. errorMessage: '',
  59. polling: false,
  60. actionText: '返回',
  61. imageKey: 'success'
  62. }
  63. }
  64. return {
  65. ...generation,
  66. title: '报告正在生成中~',
  67. subtitle: '预计所需时间1小时左右',
  68. description: '我们会在报告生成完成后提示你,你可以去我的PREILL报告查阅报告结果。',
  69. errorMessage: '',
  70. polling: true,
  71. actionText: '返回',
  72. imageKey: 'success'
  73. }
  74. }
  75. function replaceFirstPage(currentList, nextList) {
  76. void currentList
  77. return Array.isArray(nextList) ? nextList.slice() : []
  78. }
  79. function shouldResumePolling(reportId, generation = {}) {
  80. return Boolean(reportId && normalizeGenerationStatus(generation).state === RUNNING_STATE)
  81. }
  82. function reconcileStatusQueryError(currentGeneration = {}) {
  83. return applyGenerationStatus(normalizeGenerationStatus(currentGeneration))
  84. }
  85. function createStatusRequestState() {
  86. return {
  87. isPageVisible: false,
  88. statusVisibilityToken: 0,
  89. statusRequestSeq: 0,
  90. statusActiveRequestId: 0,
  91. statusRequestInFlight: false
  92. }
  93. }
  94. function setStatusPageVisible(state, visible) {
  95. if (!state || state.isPageVisible === visible) return state ? state.statusVisibilityToken : 0
  96. state.isPageVisible = visible
  97. if (!visible) {
  98. state.statusVisibilityToken += 1
  99. state.statusActiveRequestId = 0
  100. state.statusRequestInFlight = false
  101. }
  102. return state.statusVisibilityToken
  103. }
  104. function beginStatusRequest(state) {
  105. if (!state || !state.isPageVisible || state.statusRequestInFlight) return null
  106. state.statusRequestSeq += 1
  107. state.statusActiveRequestId = state.statusRequestSeq
  108. state.statusRequestInFlight = true
  109. return {
  110. requestId: state.statusActiveRequestId,
  111. visibilityToken: state.statusVisibilityToken
  112. }
  113. }
  114. function shouldApplyStatusResponse(state, meta) {
  115. return Boolean(
  116. state
  117. && meta
  118. && state.isPageVisible
  119. && state.statusRequestInFlight
  120. && state.statusActiveRequestId === meta.requestId
  121. && state.statusVisibilityToken === meta.visibilityToken
  122. )
  123. }
  124. function finishStatusRequest(state, meta) {
  125. if (!state || !meta) return
  126. if (state.statusActiveRequestId === meta.requestId) {
  127. state.statusActiveRequestId = 0
  128. state.statusRequestInFlight = false
  129. }
  130. }
  131. function createListRefreshState() {
  132. return {
  133. refreshGeneration: 0,
  134. inFlightPageRequests: {}
  135. }
  136. }
  137. function beginListRefresh(state) {
  138. if (!state) return 0
  139. state.refreshGeneration += 1
  140. return state.refreshGeneration
  141. }
  142. function createListRequestMeta(generation, page) {
  143. return { generation, page }
  144. }
  145. function shouldApplyListResponse(currentGeneration, meta) {
  146. return Boolean(meta && currentGeneration === meta.generation)
  147. }
  148. function beginListPageRequest(state, generation, page) {
  149. if (!state) return null
  150. const key = `${generation}:${page}`
  151. if (state.inFlightPageRequests[key]) return null
  152. const meta = { generation, page, key }
  153. state.inFlightPageRequests[key] = true
  154. return meta
  155. }
  156. function finishListPageRequest(state, meta) {
  157. if (!state || !meta || !meta.key) return
  158. delete state.inFlightPageRequests[meta.key]
  159. }
  160. module.exports = {
  161. RUNNING_STATE,
  162. SUCCESS_STATE,
  163. FAILED_STATE,
  164. extractReportId,
  165. normalizeGenerationStatus,
  166. applyGenerationStatus,
  167. replaceFirstPage,
  168. shouldResumePolling,
  169. reconcileStatusQueryError,
  170. createStatusRequestState,
  171. setStatusPageVisible,
  172. beginStatusRequest,
  173. shouldApplyStatusResponse,
  174. finishStatusRequest,
  175. createListRefreshState,
  176. beginListRefresh,
  177. createListRequestMeta,
  178. shouldApplyListResponse,
  179. beginListPageRequest,
  180. finishListPageRequest
  181. }