Browse Source

refactor: 抽取 useMonitorLive 直播会话逻辑

main
xiaosi 3 weeks ago
parent
commit
d178a3f6b9
  1. 93
      src/composables/useMonitorLive.js
  2. 92
      src/views/MonitorView/MonitorView.vue

93
src/composables/useMonitorLive.js

@ -0,0 +1,93 @@
import { computed, reactive } from 'vue'
import { getLivePlayURL, heartbeatLive, joinLive, leaveLive } from '@/api/live'
export function useMonitorLive({ getDockId, ui, getLivePlayer }) {
const live = reactive({ session: null, dockId: '', playUrl: '', heartbeatTimer: null })
const livePhaseText = computed(() => {
if (!live.session) return '待机'
const phase = live.session.phase
if (phase === 'streaming') return live.playUrl.startsWith('fake://') ? '模拟直播' : '直播中'
if (phase === 'starting') return '启动中'
if (phase === 'reconnecting') return '重连中'
if (phase === 'stopping') return '停止中'
if (phase === 'failed') return '启动失败'
return '已停止'
})
const canFullscreenLive = computed(() => !!live.playUrl && !live.playUrl.startsWith('fake://'))
function toggleLive() {
if (live.session) closeLive()
else openLive()
}
function fullscreenLive() {
if (!canFullscreenLive.value) {
ui.toast('当前无可全屏播放的视频流')
return
}
const ok = getLivePlayer()?.requestFullscreen?.()
if (!ok) ui.toast('当前浏览器不支持全屏')
}
async function openLive() {
const dockId = getDockId?.()
if (!dockId) return
try {
const result = await joinLive(dockId)
live.session = result.session
live.dockId = dockId
scheduleLiveHeartbeat(result.leaseExpiresAt)
if (result.session.phase === 'streaming') await refreshPlayURL()
} catch (e) {
ui.toast(e.message || '打开直播失败')
}
}
async function refreshPlayURL() {
if (!live.dockId) return
const play = await getLivePlayURL(live.dockId)
live.playUrl = play.playUrl || ''
}
function scheduleLiveHeartbeat(expiresAt) {
window.clearTimeout(live.heartbeatTimer)
const delay = Math.max(5000, (Number(expiresAt) * 1000 - Date.now()) / 2)
live.heartbeatTimer = window.setTimeout(async () => {
try {
const result = await heartbeatLive(live.dockId, live.session.id)
live.session = result.session
scheduleLiveHeartbeat(result.leaseExpiresAt)
if (result.session.phase === 'streaming' && !live.playUrl) await refreshPlayURL()
} catch (e) {
ui.toast(e.message || '直播观看已结束')
await closeLive(false)
}
}, delay)
}
async function closeLive(sendRequest = true) {
window.clearTimeout(live.heartbeatTimer)
const session = live.session
const dockId = live.dockId
live.session = null
live.dockId = ''
live.playUrl = ''
if (sendRequest && session && dockId) {
try {
await leaveLive(dockId, session.id)
} catch (_) {}
}
}
return {
live,
livePhaseText,
canFullscreenLive,
toggleLive,
fullscreenLive,
openLive,
closeLive,
}
}

92
src/views/MonitorView/MonitorView.vue

@ -90,8 +90,8 @@ import MonitorDeviceList from '@/components/MonitorDeviceList.vue'
import DockStatusDialog from '@/components/DockStatusDialog.vue' import DockStatusDialog from '@/components/DockStatusDialog.vue'
import CommandProgressFloat from '@/components/CommandProgressFloat.vue' import CommandProgressFloat from '@/components/CommandProgressFloat.vue'
import MonitorMapChrome from '@/components/MonitorMapChrome.vue' import MonitorMapChrome from '@/components/MonitorMapChrome.vue'
import { getLivePlayURL, heartbeatLive, joinLive, leaveLive } from '@/api/live'
import { useCommandProgress } from '@/composables/useCommandProgress' import { useCommandProgress } from '@/composables/useCommandProgress'
import { useMonitorLive } from '@/composables/useMonitorLive'
const DEVICE_SOURCE = 'monitor-devices' const DEVICE_SOURCE = 'monitor-devices'
@ -118,8 +118,19 @@ const userStore = useUserStore()
const isAdmin = computed(() => userStore.isAdmin()) const isAdmin = computed(() => userStore.isAdmin())
const selectedId = ref(null) const selectedId = ref(null)
const live = reactive({ session: null, dockId: '', playUrl: '', heartbeatTimer: null })
const detailPanelRef = ref(null) const detailPanelRef = ref(null)
const {
live,
livePhaseText,
canFullscreenLive,
toggleLive,
fullscreenLive,
closeLive,
} = useMonitorLive({
getDockId: () => selectedDock.value?.dockId,
ui,
getLivePlayer: () => detailPanelRef.value?.livePlayerRef,
})
const filter = ref('all') const filter = ref('all')
const search = ref('') const search = ref('')
@ -689,18 +700,6 @@ const droneMissionState = computed(() => {
return record.value.status || '停放待命' return record.value.status || '停放待命'
}) })
const livePhaseText = computed(() => {
if (!live.session) return '待机'
const phase = live.session.phase
if (phase === 'streaming') return live.playUrl.startsWith('fake://') ? '模拟直播' : '直播中'
if (phase === 'starting') return '启动中'
if (phase === 'reconnecting') return '重连中'
if (phase === 'stopping') return '停止中'
if (phase === 'failed') return '启动失败'
return '已停止'
})
const canFullscreenLive = computed(() => !!live.playUrl && !live.playUrl.startsWith('fake://'))
const detailHeader = computed(() => { const detailHeader = computed(() => {
const asset = selectedAsset.value const asset = selectedAsset.value
if (!asset) return null if (!asset) return null
@ -791,71 +790,6 @@ function onDetailCommand({ title, desc }) {
runCommand(title, desc) runCommand(title, desc)
} }
function toggleLive() {
if (live.session) closeLive()
else openLive()
}
function fullscreenLive() {
if (!canFullscreenLive.value) {
ui.toast('当前无可全屏播放的视频流')
return
}
const ok = detailPanelRef.value?.livePlayerRef?.requestFullscreen?.()
if (!ok) ui.toast('当前浏览器不支持全屏')
}
async function openLive() {
const dockId = selectedDock.value?.dockId
if (!dockId) return
try {
const result = await joinLive(dockId)
live.session = result.session
live.dockId = dockId
scheduleLiveHeartbeat(result.leaseExpiresAt)
if (result.session.phase === 'streaming') await refreshPlayURL()
} catch (e) {
ui.toast(e.message || '打开直播失败')
}
}
async function refreshPlayURL() {
if (!live.dockId) return
const play = await getLivePlayURL(live.dockId)
live.playUrl = play.playUrl || ''
}
function scheduleLiveHeartbeat(expiresAt) {
window.clearTimeout(live.heartbeatTimer)
const delay = Math.max(5000, (Number(expiresAt) * 1000 - Date.now()) / 2)
live.heartbeatTimer = window.setTimeout(async () => {
try {
const result = await heartbeatLive(live.dockId, live.session.id)
live.session = result.session
scheduleLiveHeartbeat(result.leaseExpiresAt)
if (result.session.phase === 'streaming' && !live.playUrl) await refreshPlayURL()
} catch (e) {
ui.toast(e.message || '直播观看已结束')
await closeLive(false)
}
}, delay)
}
async function closeLive(sendRequest = true) {
window.clearTimeout(live.heartbeatTimer)
const session = live.session
const dockId = live.dockId
live.session = null
live.dockId = ''
live.playUrl = ''
if (sendRequest && session && dockId) {
try {
await leaveLive(dockId, session.id)
} catch (_) {}
}
}
function displayWithUnit(value, unit, digits) { function displayWithUnit(value, unit, digits) {
if (value == null || value === '') return '--' if (value == null || value === '') return '--'
const num = Number(value) const num = Number(value)

Loading…
Cancel
Save