| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546 |
- 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 }
- })
|