import { shallowRef } from 'vue' import { defineStore } from 'pinia' import { createVideoApi, VideoRequestError } from '../services/videoApi.js' import { createVideoLiveSession } from '../services/videoLiveSession.js' import { useDetailStore } from './detailStore.js' import { useEnhancementDevicesStore } from './enhancementDevicesStore.js' export const useVideoStore = defineStore('cockpitVideo', () => { const state = shallowRef({ open: false, device: null, ownerSource: 'detail', phase: 'idle', media: null, error: '', cleanupError: '' }) const playerOptions = shallowRef({}) let options = {}, controller const publish = (patch) => { state.value = { ...state.value, ...patch } } function configure(next = {}) { if (controller) throw new Error('请在建立视频会话前配置传输') options = next playerOptions.value = next.playerOptions || {} } const session = () => controller || (controller = createVideoLiveSession(createVideoApi(options), publish, options.timers)) async function loadDevice(deviceCode) { const data = await createVideoApi(options).device(deviceCode) if (data.deviceCode !== deviceCode || typeof data.typeCode !== 'string' || typeof data.capabilities?.live !== 'boolean') { throw new VideoRequestError('INVALID_RESPONSE', '视频能力载荷与当前设备不匹配') } return data } async function open(device, ownerSource = 'detail') { if (!['detail', 'enhancement'].includes(ownerSource)) throw new Error('监控入口来源不合法') const selection = useDetailStore().selection const selectedCode = ownerSource === 'enhancement' ? useEnhancementDevicesStore().selected?.code : selection.level === 'equipment' ? selection.deviceCode : '' // A detached/late entry cannot take ownership from a still-valid viewer. if (!selectedCode || selectedCode !== device?.deviceCode) return if (state.value.open && state.value.device?.deviceCode === device?.deviceCode) { publish({ ownerSource }); return } publish({ open: true, device, ownerSource, error: '' }) if (device?.typeCode !== '20' || device.bound !== true || device.capabilities?.live !== true) { publish({ phase: 'failed', error: '当前设备未确认实时视频能力' }); return } await session().start(device.deviceCode) } async function close() { publish({ open: false }); if (controller) await controller.stop() } async function retry() { if (state.value.device) await session().start(state.value.device.deviceCode) } async function retryCleanup() { if (controller) await controller.stop() } const ready = () => controller?.ready() const fail = (error) => controller?.fail(typeof error === 'string' ? error : error?.message || '视频播放失败') return { state, playerOptions, configure, loadDevice, open, close, retry, retryCleanup, ready, fail } })