alarms.ts 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. import { defineStore } from 'pinia'
  2. import { computed, ref } from 'vue'
  3. import { fetchAlarmFilters, fetchAlarms } from '../api/alarms'
  4. import type { AlarmRow } from '../types'
  5. function pad2(value: number): string {
  6. return String(value).padStart(2, '0')
  7. }
  8. function today(): string {
  9. const d = new Date()
  10. return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`
  11. }
  12. const PLAY_INTERVAL = 5000
  13. export const useAlarmsStore = defineStore('alarms', () => {
  14. const devices = ref<string[]>([])
  15. const alarmTypes = ref<string[]>([])
  16. const deviceCode = ref('') // 空 = 全部
  17. const alarmType = ref('') // 空 = 全部
  18. const page = ref(1)
  19. const pageSize = ref(30)
  20. const total = ref(0)
  21. const items = ref<AlarmRow[]>([])
  22. const loading = ref(false)
  23. const selectedId = ref<number | null>(null)
  24. // 播放状态
  25. const playing = ref(false)
  26. const paused = ref(false)
  27. const displayDate = ref(today())
  28. let playTimer: ReturnType<typeof setTimeout> | undefined
  29. let playIndex = 0
  30. const selected = computed<AlarmRow | null>(
  31. () => items.value.find((row) => row.id === selectedId.value) ?? null,
  32. )
  33. async function loadFilters(): Promise<void> {
  34. const filters = await fetchAlarmFilters()
  35. devices.value = filters.devices
  36. alarmTypes.value = filters.alarm_types
  37. if (!deviceCode.value) {
  38. deviceCode.value =
  39. devices.value.find((d) => d.replace(/\D/g, '') === '8') ?? devices.value[0] ?? ''
  40. }
  41. }
  42. async function load(): Promise<void> {
  43. loading.value = true
  44. try {
  45. const res = await fetchAlarms({
  46. device_code: deviceCode.value || undefined,
  47. alarm_type: alarmType.value || undefined,
  48. page: page.value,
  49. page_size: pageSize.value,
  50. })
  51. items.value = res.items
  52. total.value = res.total
  53. if (selectedId.value && !items.value.some((row) => row.id === selectedId.value)) {
  54. selectedId.value = null
  55. }
  56. } finally {
  57. loading.value = false
  58. }
  59. }
  60. function setDevice(value: string): void {
  61. deviceCode.value = value || ''
  62. page.value = 1
  63. load()
  64. }
  65. function setType(value: string): void {
  66. alarmType.value = value || ''
  67. page.value = 1
  68. load()
  69. }
  70. function setPage(value: number): void {
  71. page.value = value
  72. load()
  73. }
  74. function select(row: AlarmRow): void {
  75. selectedId.value = selectedId.value === row.id ? null : row.id
  76. }
  77. function clearSelected(): void {
  78. selectedId.value = null
  79. }
  80. /** 初始加载完成后自动选中第一条(最新)。 */
  81. function autoSelectFirst(): void {
  82. if (selectedId.value === null && items.value[0]) {
  83. selectedId.value = items.value[0].id
  84. }
  85. }
  86. /* ---------------- 故障播放(从最早到最新) ---------------- */
  87. function clearTimer(): void {
  88. if (playTimer) { clearTimeout(playTimer); playTimer = undefined }
  89. }
  90. async function showGlobalIndex(globalIndex: number): Promise<void> {
  91. const targetPage = Math.floor(globalIndex / pageSize.value) + 1
  92. if (targetPage !== page.value) {
  93. page.value = targetPage
  94. await load()
  95. }
  96. const row = items.value[globalIndex % pageSize.value]
  97. if (row) {
  98. selectedId.value = row.id
  99. displayDate.value = row.alarm_time_start.slice(0, 10)
  100. }
  101. }
  102. function schedule(): void {
  103. clearTimer()
  104. if (!playing.value || paused.value) return
  105. playTimer = setTimeout(advance, PLAY_INTERVAL)
  106. }
  107. async function advance(): Promise<void> {
  108. if (!playing.value || paused.value) return
  109. playIndex -= 1
  110. if (playIndex < 0) {
  111. await resetToInitial()
  112. return
  113. }
  114. await showGlobalIndex(playIndex)
  115. schedule()
  116. }
  117. async function startPlayback(): Promise<void> {
  118. if (!total.value) return
  119. clearTimer()
  120. playing.value = true
  121. paused.value = false
  122. playIndex = total.value - 1 // 全局最后一条(最早)
  123. await showGlobalIndex(playIndex)
  124. schedule()
  125. }
  126. async function resetToInitial(): Promise<void> {
  127. clearTimer()
  128. playing.value = false
  129. paused.value = false
  130. page.value = 1
  131. await load()
  132. if (items.value[0]) selectedId.value = items.value[0].id
  133. displayDate.value = today()
  134. }
  135. async function stopPlayback(): Promise<void> {
  136. await resetToInitial()
  137. }
  138. function togglePause(): void {
  139. if (!playing.value) return
  140. paused.value = !paused.value
  141. if (paused.value) clearTimer()
  142. else schedule()
  143. }
  144. function reset(): void {
  145. clearTimer()
  146. items.value = []
  147. total.value = 0
  148. page.value = 1
  149. selectedId.value = null
  150. playing.value = false
  151. paused.value = false
  152. displayDate.value = today()
  153. }
  154. return {
  155. devices, alarmTypes, deviceCode, alarmType, page, pageSize, total, items,
  156. loading, selectedId, selected, playing, paused, displayDate,
  157. loadFilters, load, setDevice, setType, setPage, select, clearSelected,
  158. autoSelectFirst, startPlayback, stopPlayback, togglePause, reset,
  159. }
  160. })