taskCenter.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. import { defineStore } from 'pinia'
  2. import { taskCenterApi } from '@/api'
  3. export const useTaskCenterStore = defineStore('taskCenter', {
  4. state: () => ({
  5. open: false,
  6. activeTab: 'all',
  7. listLoading: false,
  8. detailLoading: false,
  9. list: [],
  10. total: 0,
  11. selectedId: null,
  12. detail: null,
  13. runningTotal: 0,
  14. statusTotals: {
  15. processing: 0,
  16. failed: 0,
  17. pending: 0
  18. },
  19. pollTimer: null,
  20. listPollTimer: null
  21. }),
  22. getters: {
  23. runningCount(state) {
  24. return state.runningTotal || 0
  25. }
  26. },
  27. actions: {
  28. /**
  29. * 任务开始时调用:打开任务中心并聚焦"运行中"
  30. */
  31. async notifyTaskStarted({ documentId } = {}) {
  32. this.open = true
  33. this.activeTab = 'processing'
  34. this.selectedId = null
  35. this.detail = null
  36. this.fetchRunningCount()
  37. this.fetchStatusTotals()
  38. await this.fetchList({ pageNum: 1, pageSize: 20 })
  39. this.startListPolling()
  40. // 如果传入了 documentId,尝试选中该任务
  41. if (documentId) {
  42. // 等待一小段时间让任务创建完成
  43. setTimeout(async () => {
  44. try {
  45. const detail = await taskCenterApi.getByDocumentId(documentId)
  46. if (detail && detail.id) {
  47. this.selectTask(detail.id)
  48. }
  49. } catch (e) {
  50. console.warn('获取任务详情失败:', e)
  51. }
  52. }, 1000)
  53. }
  54. },
  55. toggleOpen() {
  56. this.open = !this.open
  57. if (!this.open) {
  58. this.stopPolling()
  59. this.stopListPolling()
  60. } else {
  61. this.fetchList()
  62. this.fetchStatusTotals()
  63. this.startListPolling()
  64. }
  65. },
  66. close() {
  67. this.open = false
  68. this.stopPolling()
  69. this.stopListPolling()
  70. },
  71. setActiveTab(tab) {
  72. this.activeTab = tab || 'all'
  73. },
  74. async fetchList({ pageNum = 1, pageSize = 20, silent = false } = {}) {
  75. if (!silent) {
  76. this.listLoading = true
  77. }
  78. try {
  79. const params = {
  80. status: this.activeTab === 'all' ? undefined : this.activeTab,
  81. pageNum,
  82. pageSize
  83. }
  84. const resp = await taskCenterApi.list(params)
  85. // resp 是分页对象 { records, total, current, size }
  86. this.list = resp?.records || []
  87. this.total = resp?.total || 0
  88. } catch (e) {
  89. console.error('获取任务列表失败:', e)
  90. } finally {
  91. if (!silent) {
  92. this.listLoading = false
  93. }
  94. }
  95. },
  96. async fetchRunningCount() {
  97. try {
  98. const resp = await taskCenterApi.list({
  99. status: 'processing',
  100. pageNum: 1,
  101. pageSize: 1
  102. })
  103. this.runningTotal = resp?.total || 0
  104. } catch (e) {
  105. // 失败不影响主流程
  106. }
  107. },
  108. async fetchStatusTotals() {
  109. try {
  110. const stats = await taskCenterApi.getStatistics()
  111. this.statusTotals = {
  112. processing: stats?.processing || 0,
  113. failed: stats?.failed || 0,
  114. pending: stats?.pending || 0
  115. }
  116. } catch (e) {
  117. // 统计失败不影响主流程
  118. }
  119. },
  120. async selectTask(taskId) {
  121. if (!taskId) return
  122. this.selectedId = taskId
  123. await this.fetchDetail(taskId)
  124. this.maybeStartPolling()
  125. },
  126. async fetchDetail(taskId, silent = false) {
  127. if (!silent) {
  128. this.detailLoading = true
  129. }
  130. try {
  131. const resp = await taskCenterApi.getById(taskId)
  132. this.detail = resp
  133. } catch (e) {
  134. console.error('获取任务详情失败:', e)
  135. } finally {
  136. if (!silent) {
  137. this.detailLoading = false
  138. }
  139. }
  140. },
  141. maybeStartPolling() {
  142. this.stopPolling()
  143. if (!this.open) return
  144. const status = this.detail?.status
  145. if (status !== 'processing') return
  146. this.pollTimer = setInterval(async () => {
  147. if (!this.selectedId) return
  148. try {
  149. await this.fetchDetail(this.selectedId, true)
  150. const s = this.detail?.status
  151. if (s === 'completed' || s === 'failed') {
  152. // 任务结束后刷新列表和统计
  153. await this.fetchList({ pageNum: 1, pageSize: 20, silent: true })
  154. this.fetchRunningCount()
  155. this.fetchStatusTotals()
  156. this.stopPolling()
  157. }
  158. } catch (e) {
  159. // 轮询异常不停止
  160. }
  161. }, 3000)
  162. },
  163. stopPolling() {
  164. if (this.pollTimer) {
  165. clearInterval(this.pollTimer)
  166. this.pollTimer = null
  167. }
  168. },
  169. startListPolling(intervalMs = 5000) {
  170. this.stopListPolling()
  171. if (!this.open) return
  172. this.listPollTimer = setInterval(async () => {
  173. if (!this.open) {
  174. this.stopListPolling()
  175. return
  176. }
  177. try {
  178. await this.fetchList({ pageNum: 1, pageSize: 20, silent: true })
  179. this.fetchStatusTotals()
  180. } catch (e) {
  181. // 轮询异常不停止
  182. }
  183. }, intervalMs)
  184. },
  185. stopListPolling() {
  186. if (this.listPollTimer) {
  187. clearInterval(this.listPollTimer)
  188. this.listPollTimer = null
  189. }
  190. },
  191. async deleteTask(taskId) {
  192. try {
  193. await taskCenterApi.delete(taskId)
  194. // 如果删除的是当前选中的任务,清除选中状态
  195. if (this.selectedId === taskId) {
  196. this.selectedId = null
  197. this.detail = null
  198. }
  199. // 刷新列表和统计
  200. await this.fetchList()
  201. this.fetchRunningCount()
  202. this.fetchStatusTotals()
  203. return true
  204. } catch (e) {
  205. throw e
  206. }
  207. }
  208. }
  209. })