| 12345678910111213141516171819202122232425262728293031323334353637 |
- <template>
- <div v-if="loading || error || device?.typeCode === '20' || video.state.cleanupError" class="video-entry" data-video-entry>
- <p v-if="loading" class="video-entry__hint">正在确认视频能力…</p>
- <template v-else-if="device?.typeCode === '20'">
- <button type="button" data-video-open :disabled="device.bound !== true || device.capabilities?.live !== true || Boolean(video.state.cleanupError)" @click="video.open(device)">监控</button>
- <span v-if="!device.capabilities?.live" class="video-entry__hint">{{ device.unavailableReason || '实时视频能力尚未确认' }}</span>
- </template>
- <p v-if="error" class="video-entry__hint" role="status">{{ error }} <button type="button" @click="load">重查视频能力</button></p>
- <p v-if="video.state.cleanupError" class="video-entry__hint" role="alert">{{ video.state.cleanupError }} <button type="button" @click="video.retryCleanup">重试清理</button></p>
- </div>
- </template>
- <script setup>
- import { ref, watch, onBeforeUnmount } from 'vue'
- import { useVideoStore } from '../stores/videoStore.js'
- const props = defineProps({ deviceCode: { type: String, required: true } })
- const video = useVideoStore()
- const device = ref(null), loading = ref(false), error = ref('')
- let generation = 0
- async function load() {
- const version = ++generation
- device.value = null; error.value = ''; loading.value = Boolean(props.deviceCode)
- if (!props.deviceCode) return
- try {
- const result = await video.loadDevice(props.deviceCode)
- if (version === generation) device.value = result
- } catch (failure) { if (version === generation) error.value = failure.message || '视频能力暂不可用' }
- finally { if (version === generation) loading.value = false }
- }
- watch(() => props.deviceCode, load, { immediate: true })
- onBeforeUnmount(() => { generation += 1 })
- </script>
- <style scoped>
- .video-entry { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; padding: 10px 0 14px; }
- .video-entry button { color: #c6f7ff; background: #0b5264; border: 1px solid #39879a; border-radius: 4px; padding: 6px 16px; cursor: pointer; }
- .video-entry button:disabled { color: #82949c; background: #243841; border-color: #45616a; cursor: not-allowed; }
- .video-entry__hint { margin: 0; color: #a7bdc7; font-size: 0.85em; }
- </style>
|