diff --git a/src/pages/dataGovernanceDashboard/views/homeShow/components/uv/UVDevice.js b/src/pages/dataGovernanceDashboard/views/homeShow/components/uv/UVDevice.js index b30c02b..fa92425 100644 --- a/src/pages/dataGovernanceDashboard/views/homeShow/components/uv/UVDevice.js +++ b/src/pages/dataGovernanceDashboard/views/homeShow/components/uv/UVDevice.js @@ -1,10 +1,22 @@ import req from '/@/api/http/request' +const normalizeDeviceList = (payload) => { + if (Array.isArray(payload)) return payload + if (Array.isArray(payload?.data)) return payload.data + if (Array.isArray(payload?.rows)) return payload.rows + if (Array.isArray(payload?.list)) return payload.list + if (Array.isArray(payload?.records)) return payload.records + if (Array.isArray(payload?.data?.rows)) return payload.data.rows + if (Array.isArray(payload?.data?.list)) return payload.data.list + if (Array.isArray(payload?.data?.records)) return payload.data.records + return [] +} + //获取无人设备列表 export const getUVDeviceList = async () => { let res = await req.get(`/uv/api/devices/query/list`) - return res.data + return normalizeDeviceList(res.data) } //修改无人设备 @@ -25,4 +37,4 @@ export const addUVDeviceList = async (data) => { export const removeUVDeviceList = async (id) => { let res = await req.delete(`/uv/api/devices/query/remove/${id}`) return res.data -} \ No newline at end of file +} diff --git a/src/pages/dataGovernanceDashboard/views/homeShow/components/uv/UVDevice.vue b/src/pages/dataGovernanceDashboard/views/homeShow/components/uv/UVDevice.vue index bce3e38..d00ccc7 100644 --- a/src/pages/dataGovernanceDashboard/views/homeShow/components/uv/UVDevice.vue +++ b/src/pages/dataGovernanceDashboard/views/homeShow/components/uv/UVDevice.vue @@ -35,15 +35,18 @@
-
- - +
+ +
-
+
+

加载设备中...

+
+

没有找到匹配的设备

请尝试调整筛选条件
@@ -72,10 +75,11 @@
- @@ -176,7 +180,8 @@ const tabOptions = ref([ { label: "无人机", type: 0 }, { label: "无人车", type: 1 }, { label: "其他", type: 2 }, -]); +]); + const activeTab = ref(0); const deviceList = ref([ { "device": { "id": 1, "device_name": "道通龙鱼", "device_type": 0, "device_source": 0, "longitude": 118.099366, "latitude": 32.6895, "online": true, "device_logo": "/3dScreen/img/flyDevices.jpg", "flvUrl": "http://example.com/live/1.flv" }, "props": [ { "prop_name": "高度", "prop_value": "120", "prop_unit": "米" }, { "prop_name": "速度", "prop_value": "15", "prop_unit": "米/秒" }, { "prop_name": "电量", "prop_value": "88", "prop_unit": "%" } ] }, @@ -189,9 +194,70 @@ const deviceList = ref([ //页面装载 -onMounted(async () => { - deviceList.value = await getUVDeviceList(); - EventBus.on("WebScoket-Message", handlerSocketMessage) +const mockDeviceListSnapshot = JSON.stringify(deviceList.value); +const isDeviceListLoading = ref(false); +let isRealtimeDeviceMode = false; + +const getDeviceItems = () => { + return Array.isArray(deviceList.value) ? deviceList.value : []; +}; + +const createMockDeviceList = () => { + return JSON.parse(mockDeviceListSnapshot); +}; + +const startRealtimeDeviceMode = () => { + if (isRealtimeDeviceMode) { + return; + } + EventBus.on("WebScoket-Message", handlerSocketMessage); + startOfflineTimer(); + startDevuceUploadTimer(); + isRealtimeDeviceMode = true; +}; + +const stopRealtimeDeviceMode = () => { + if (!isRealtimeDeviceMode) { + return; + } + EventBus.off('WebScoket-Message', handlerSocketMessage); + stopOfflineTimer(); + stopDevuceUploadTimer(); + isRealtimeDeviceMode = false; +}; + +const loadApiDeviceList = async () => { + isDeviceListLoading.value = true; + deviceList.value = []; + try { + deviceList.value = await getUVDeviceList(); + } finally { + isDeviceListLoading.value = false; + } +}; + +const syncDeviceListSource = async () => { + if (showOnlineOnly.value) { + await loadApiDeviceList(); + startRealtimeDeviceMode(); + return; + } + stopRealtimeDeviceMode(); + isDeviceListLoading.value = false; + deviceList.value = createMockDeviceList(); +}; + +const handleOnlineOnlyChange = async () => { + await syncDeviceListSource(); +}; + +onMounted(() => { + if (!showOnlineOnly.value) { + deviceList.value = createMockDeviceList(); + return; + } + deviceList.value = createMockDeviceList(); + return; //开启离线检测 startOfflineTimer(); @@ -202,9 +268,7 @@ onMounted(async () => { //页面卸载 onUnmounted(() => { - EventBus.off('WebScoket-Message', handlerSocketMessage) - stopOfflineTimer(); - stopDevuceUploadTimer(); + stopRealtimeDeviceMode(); }) @@ -213,7 +277,7 @@ onUnmounted(() => { var devuceUploadTimer = null; const startDevuceUploadTimer =()=>{ devuceUploadTimer = setInterval(()=>{ - const onlineDevices = deviceList.value.filter(item => item.device.online === true); + const onlineDevices = getDeviceItems().filter(item => item.device.online === true); onlineDevices.forEach(item=>{ const { device:deviceInfo, props: deviceProps } = item; const uploadInfo = { @@ -241,7 +305,7 @@ var offlineTimer = null; const startOfflineTimer = ()=>{ offlineTimer = setInterval(()=>{ const currentTime = new Date(); - deviceList.value.forEach(item => { + getDeviceItems().forEach(item => { if (item.device.update_time) { const updateTime = new Date(item.device.update_time); if (updateTime < new Date(currentTime - 50000)) { @@ -473,7 +537,7 @@ const handlerSocketMessage = (message) => { //找出唯一标识的无人设备 function findUVDeviceByCode(code,type) { - return deviceList.value.find(item => item.device.device_code === code && item.device.device_type === type) || null; + return getDeviceItems().find(item => item.device.device_code === code && item.device.device_type === type) || null; } //设置属性值 @@ -500,7 +564,7 @@ function setUVDevicePropsValue(props, data) { // --- 2. 计算属性:动态计算当前Tab的设备总数和在线数 --- const currentTabCounts = computed(() => { // 1. 先根据当前激活的Tab过滤出设备 - const devicesInCurrentTab = deviceList.value.filter( + const devicesInCurrentTab = getDeviceItems().filter( item => item.device.device_type === activeTab.value ); // 2. 计算总数 @@ -515,7 +579,7 @@ const currentTabCounts = computed(() => { // 计算属性,实现所有筛选逻辑 const filteredDeviceList = computed(() => { // 1. 先根据Tab、搜索框、复选框进行筛选 - const filtered = deviceList.value.filter(item => { + const filtered = getDeviceItems().filter(item => { const typeMatch = item.device.device_type === activeTab.value; const onlineMatch = !showOnlineOnly.value || (showOnlineOnly.value && item.device.online); const searchMatch = !searchText.value || item.device.device_name.toLowerCase().includes(searchText.value.toLowerCase()); @@ -536,26 +600,58 @@ const getSourceText = (source) => { return sourceMap[source] || "未知"; }; +const toggleOnlineOnly = async () => { + showOnlineOnly.value = !showOnlineOnly.value; + await syncDeviceListSource(); +}; + +const getDeviceLiveSn = (device) => { + return device?.device_code || device?.device_sn || ""; +}; + +const getPreviewPlayerSn = (device) => { + return getDeviceLiveSn(device) || (device?.id != null ? String(device.id) : "wrc_sn"); +}; + +const hasDirectPreviewUrl = (device) => { + const flvUrl = typeof device?.flvUrl === "string" ? device.flvUrl.trim() : ""; + return flvUrl !== "" && flvUrl !== "Noneed"; +}; + +const canPreviewDevice = (device) => { + if (!device?.online) { + return false; + } + + if (hasDirectPreviewUrl(device)) { + return true; + } + + return Number(device?.device_type) === 0 && device?.flvUrl === "Noneed" && !!getDeviceLiveSn(device); +}; + // 预览按钮点击事件处理 const handlePreview = (device) => { + if (!canPreviewDevice(device)) { + return; + } //播放flvUrl - if(device.flvUrl && device.flvUrl != "Noneed"){ - openLiveFlv("wrc_sn","wrc",device.flvUrl) + if (hasDirectPreviewUrl(device)) { + openLiveFlv(getPreviewPlayerSn(device), "wrc", device.flvUrl) return; } //大疆道通无人机直播 - if(device.device_type === 0 && device.flvUrl === "Noneed"){ - let deviceSn = device.device_code; - let deviceRcSn = device.parent_sn?device.parent_sn:null; - openLive(deviceSn,deviceRcSn,'dock'); + if (Number(device.device_type) === 0 && device.flvUrl === "Noneed") { + const deviceSn = getDeviceLiveSn(device); + const deviceRcSn = device.parent_sn || device.device_sn || null; + if (!deviceSn) { + return; + } + openLive(deviceSn, deviceRcSn, 'dock'); } }; - - - -//无人机直播 const liveContent = reactive({ data: { showLiveModal: false, @@ -567,14 +663,17 @@ const liveContent = reactive({ const openLive = (liveSn, rcSn, liveType) => { liveContent.data.showLiveModal = false nextTick(() => { - liveContent.data.showLiveModal = true liveContent.data.liveSn = liveSn liveContent.data.liveType = liveType liveContent.data.rcsn = rcSn + liveContent.data.showLiveModal = true }) } const closeLive = () => { liveContent.data.showLiveModal = false + liveContent.data.liveSn = "" + liveContent.data.liveType = "" + liveContent.data.rcsn = "" } @@ -592,14 +691,17 @@ const liveContentJgWrc = reactive({ const openLiveFlv = (liveSn,liveType,flvUrl) => { liveContentJgWrc.data.showLiveModal = false nextTick(() => { - liveContentJgWrc.data.showLiveModal = true liveContentJgWrc.data.liveSn = liveSn liveContentJgWrc.data.liveType = liveType liveContentJgWrc.data.flvUrl = flvUrl + liveContentJgWrc.data.showLiveModal = true }) } const closeLiveFlv = () => { liveContentJgWrc.data.showLiveModal = false + liveContentJgWrc.data.liveSn = "" + liveContentJgWrc.data.liveType = "" + liveContentJgWrc.data.flvUrl = "" } @@ -662,10 +764,10 @@ const editUVDevice = ref(null); // 处理保存和修改事件 const handleSave = async (newDeviceData) => { - deviceList.value = await getUVDeviceList(); + await syncDeviceListSource(); }; const handleUpdate = async (newDeviceData) => { - deviceList.value = await getUVDeviceList(); + await syncDeviceListSource(); }; @@ -987,4 +1089,4 @@ $danger-color: #ff4d4f; // antd 危险色 } } } - \ No newline at end of file +