useFaultRecord.ts 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import { computed, onBeforeUnmount, ref } from 'vue'
  2. import { useRoute } from 'vue-router'
  3. import {
  4. cancelFaultRecordOperation,
  5. createFaultRecordOperation,
  6. getFaultRecordOperation,
  7. } from '@/service/faultRecord'
  8. import type {
  9. FaultRecordCreateReq,
  10. FaultRecordEnv,
  11. FaultRecordOpDetail,
  12. } from '@/service/faultRecord/interface'
  13. import { ENV_LABEL, errText, isTerminal } from './constants'
  14. /** 当前页面所属环境(来自路由 meta.env) */
  15. export function useFaultRecordEnv() {
  16. const route = useRoute()
  17. const env = computed<FaultRecordEnv>(() => (route.meta.env === 'test' ? 'test' : 'prod'))
  18. const envLabel = computed(() => ENV_LABEL[env.value])
  19. return { env, envLabel }
  20. }
  21. // 轮询间隔:开始后 10 秒内每 2 秒(及时看到设备应答),之后每 5 秒(等待 379/上传/下载,状态变化慢)
  22. const POLL_FAST_INTERVAL = 2000
  23. const POLL_FAST_PERIOD = 10_000
  24. const POLL_SLOW_INTERVAL = 5000
  25. /** 创建操作并轮询状态,直到结束 */
  26. export function useOperation(onFinished?: (d: FaultRecordOpDetail) => void) {
  27. const detail = ref<FaultRecordOpDetail>()
  28. const running = ref(false)
  29. const error = ref('')
  30. let timer: ReturnType<typeof setTimeout> | undefined
  31. let watchingId = ''
  32. // 每次开始轮询递增;只有最新一轮可以继续排下一次,避免请求在途时重复开始导致多条轮询并行
  33. let generation = 0
  34. let startedAt = 0
  35. function stop() {
  36. generation++
  37. if (timer) clearTimeout(timer)
  38. timer = undefined
  39. running.value = false
  40. }
  41. async function poll(gen: number) {
  42. const id = watchingId
  43. try {
  44. const d = await getFaultRecordOperation(id)
  45. if (gen !== generation) return
  46. detail.value = d
  47. if (isTerminal(d.status)) {
  48. stop()
  49. onFinished?.(d)
  50. return
  51. }
  52. } catch (e) {
  53. if (gen !== generation) return
  54. error.value = errText(e)
  55. }
  56. const interval = Date.now() - startedAt < POLL_FAST_PERIOD ? POLL_FAST_INTERVAL : POLL_SLOW_INTERVAL
  57. timer = setTimeout(poll, interval, gen)
  58. }
  59. /** 查看某个已有操作(如从历史中选择),未结束时继续轮询;对正在轮询的同一操作重复调用不会重新开始 */
  60. function watch(id: string) {
  61. if (id === watchingId && running.value) return
  62. stop()
  63. watchingId = id
  64. error.value = ''
  65. running.value = true
  66. startedAt = Date.now()
  67. poll(generation)
  68. }
  69. async function start(req: FaultRecordCreateReq) {
  70. error.value = ''
  71. detail.value = undefined
  72. const { id } = await createFaultRecordOperation(req)
  73. watch(id)
  74. return id
  75. }
  76. async function cancel() {
  77. if (!detail.value) return
  78. await cancelFaultRecordOperation(detail.value.id)
  79. }
  80. onBeforeUnmount(stop)
  81. return { detail, running, error, start, watch, cancel, stop }
  82. }