import { defineStore } from 'pinia' import { computed, ref } from 'vue' import { fetchAlarmFilters, fetchAlarms } from '../api/alarms' import type { AlarmRow } from '../types' function pad2(value: number): string { return String(value).padStart(2, '0') } function today(): string { const d = new Date() return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}` } const PLAY_INTERVAL = 5000 export const useAlarmsStore = defineStore('alarms', () => { const devices = ref([]) const alarmTypes = ref([]) const deviceCode = ref('') // 空 = 全部 const alarmType = ref('') // 空 = 全部 const page = ref(1) const pageSize = ref(30) const total = ref(0) const items = ref([]) const loading = ref(false) const selectedId = ref(null) // 播放状态 const playing = ref(false) const paused = ref(false) const displayDate = ref(today()) let playTimer: ReturnType | undefined let playIndex = 0 const selected = computed( () => items.value.find((row) => row.id === selectedId.value) ?? null, ) async function loadFilters(): Promise { const filters = await fetchAlarmFilters() devices.value = filters.devices alarmTypes.value = filters.alarm_types if (!deviceCode.value) { deviceCode.value = devices.value.find((d) => d.replace(/\D/g, '') === '8') ?? devices.value[0] ?? '' } } async function load(): Promise { loading.value = true try { const res = await fetchAlarms({ device_code: deviceCode.value || undefined, alarm_type: alarmType.value || undefined, page: page.value, page_size: pageSize.value, }) items.value = res.items total.value = res.total if (selectedId.value && !items.value.some((row) => row.id === selectedId.value)) { selectedId.value = null } } finally { loading.value = false } } function setDevice(value: string): void { deviceCode.value = value || '' page.value = 1 load() } function setType(value: string): void { alarmType.value = value || '' page.value = 1 load() } function setPage(value: number): void { page.value = value load() } function select(row: AlarmRow): void { selectedId.value = selectedId.value === row.id ? null : row.id } function clearSelected(): void { selectedId.value = null } /** 初始加载完成后自动选中第一条(最新)。 */ function autoSelectFirst(): void { if (selectedId.value === null && items.value[0]) { selectedId.value = items.value[0].id } } /* ---------------- 故障播放(从最早到最新) ---------------- */ function clearTimer(): void { if (playTimer) { clearTimeout(playTimer); playTimer = undefined } } async function showGlobalIndex(globalIndex: number): Promise { const targetPage = Math.floor(globalIndex / pageSize.value) + 1 if (targetPage !== page.value) { page.value = targetPage await load() } const row = items.value[globalIndex % pageSize.value] if (row) { selectedId.value = row.id displayDate.value = row.alarm_time_start.slice(0, 10) } } function schedule(): void { clearTimer() if (!playing.value || paused.value) return playTimer = setTimeout(advance, PLAY_INTERVAL) } async function advance(): Promise { if (!playing.value || paused.value) return playIndex -= 1 if (playIndex < 0) { await resetToInitial() return } await showGlobalIndex(playIndex) schedule() } async function startPlayback(): Promise { if (!total.value) return clearTimer() playing.value = true paused.value = false playIndex = total.value - 1 // 全局最后一条(最早) await showGlobalIndex(playIndex) schedule() } async function resetToInitial(): Promise { clearTimer() playing.value = false paused.value = false page.value = 1 await load() if (items.value[0]) selectedId.value = items.value[0].id displayDate.value = today() } async function stopPlayback(): Promise { await resetToInitial() } function togglePause(): void { if (!playing.value) return paused.value = !paused.value if (paused.value) clearTimer() else schedule() } function reset(): void { clearTimer() items.value = [] total.value = 0 page.value = 1 selectedId.value = null playing.value = false paused.value = false displayDate.value = today() } return { devices, alarmTypes, deviceCode, alarmType, page, pageSize, total, items, loading, selectedId, selected, playing, paused, displayDate, loadFilters, load, setDevice, setType, setPage, select, clearSelected, autoSelectFirst, startPlayback, stopPlayback, togglePause, reset, } })