From c832bf2e80ac465e71b7a1c1f7a59d4252030989 Mon Sep 17 00:00:00 2001
From: 张含笑 <zhx18749296735@163.com>
Date: Tue, 05 Aug 2025 17:33:08 +0800
Subject: [PATCH] feat:事件工单滚动条
---
src/views/device/components/DockControlPanel.vue | 460 +++++++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 367 insertions(+), 93 deletions(-)
diff --git a/src/views/device/components/DockControlPanel.vue b/src/views/device/components/DockControlPanel.vue
index a17a6ff..6a8d389 100644
--- a/src/views/device/components/DockControlPanel.vue
+++ b/src/views/device/components/DockControlPanel.vue
@@ -8,14 +8,9 @@
<div class="control-cmd-wrapper">
<div class="control-cmd-header">
远程调试
- <el-switch
- v-model:checked="debugStatus"
- @change="onDeviceStatusChange"
- active-text="开"
- inactive-text="关"
- class="debug-btn"
- style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949"
- />
+ <el-switch v-model="debugStatus" @change="onDeviceStatusChange" active-text="开" inactive-text="关"
+ class="debug-btn" style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949" />
+ <el-divider />
</div>
<div class="control-cmd-box">
<div v-for="(cmdItem, index) in cmdList" :key="cmdItem.cmdKey" class="control-cmd-item">
@@ -24,155 +19,339 @@
<div class="item-status">{{ cmdItem.status }}</div>
</div>
<div class="control-cmd-item-right">
- <el-button
- :disabled="!debugStatus || cmdItem.disabled"
- :loading="cmdItem.loading"
- size="small"
- type="primary"
- @click="sendControlCmd(cmdItem, index)"
- >
+ <el-button :disabled="!debugStatus || cmdItem.disabled" :loading="cmdItem.loading" size="small"
+ type="primary" @click="sendControlCmd(cmdItem, index)">
{{ cmdItem.operateText }}
</el-button>
</div>
</div>
+ </div>
+
+ <el-divider v-if="deviceInfo">无人机设置</el-divider>
+ <div class="control-cmd-box" v-for="(item, index) in cameras">
+ <div>
+ <el-form-item label="摄像头设置">
+ <el-select @change="cameraSettings($event, item)" v-model="videoValue" placeholder="请选择">
+ <el-option v-for="item in videoType" :key="item.value" :label="item.label" :value="item.value">
+ </el-option>
+ </el-select>
+ </el-form-item>
+
+ <el-form-item label="调色盘样式" v-if="videoValue == 'ir'">
+ <el-select @change="changs($event, item)" v-model="valueStyle" placeholder="请选择">
+ <el-option v-for="item in paletteOptions" :key="item.value" :label="item.label" :value="item.value">
+ </el-option>
+ </el-select>
+ </el-form-item>
+ </div>
+
+ <div>
+ <el-form-item label="相机模式">
+ <el-select @change="photoAndVideoCmdSettings($event, item)" v-model="cameraModeValue" placeholder="请选择">
+ <el-option v-for="item in cameraMode" :key="item.value" :label="item.label" :value="item.value">
+ </el-option>
+ </el-select>
+ </el-form-item>
+
+ <el-form-item label="照片存储设置" v-if="cameraModeValue == 0">
+ <el-select v-model="photo_storage_settings" collapse-tags @change="photoStorageTypeChang($event, item)"
+ multiple placeholder="请选择">
+ <el-option v-for="item in photoStorageType" :key="item.value" :label="item.label" :value="item.value">
+ </el-option>
+ </el-select>
+ </el-form-item>
+
+ <el-form-item label="视频存储设置" v-if="cameraModeValue == 1">
+ <el-select v-model="video_storage_settings" collapse-tags @change="videoStorageTypeChang($event, item)"
+ multiple placeholder="请选择">
+ <el-option v-for="item in photoStorageType" :key="item.value" :label="item.label" :value="item.value">
+ </el-option>
+ </el-select>
+ </el-form-item>
+ </div>
+
</div>
</div>
</div>
</template>
<script setup>
-import EventBus from '@/event-bus';
-import { EBizCode, ELocalStorageKey, ERouterName } from '@/types';
-import { useConnectWebSocket } from '@/hooks/use-connect-websocket';
-import { getWebsocketUrl } from '@/websocket/util/config';
+import { ElMessage } from 'element-plus';
+import EventBus from '@/event-bus'
+import { EBizCode, ELocalStorageKey, ERouterName } from '@/types'
+import { useConnectWebSocket } from '@/hooks/use-connect-websocket'
+import { getWebsocketUrl } from '@/websocket/util/config'
+import { defineProps, ref, watch, reactive } from 'vue'
+import { cmdList as baseCmdList } from '@/types/device-cmd'
+import { useDockControl } from './use-dock-control'
+import { EDockModeCode } from '@/types/device'
+import { updateDeviceCmdInfoByOsd, updateDeviceCmdInfoByExecuteInfo } from '@/utils/device-cmd'
+import { setThermalCurrentPaletteStyle, setPhotoStorageSet, setVideoStorageSet, getLiveStatus, setStreamsSwitch, photoAndVideoCmd } from '@/api/device-setting'
-import { defineProps, ref, watch } from 'vue';
-import { cmdList as baseCmdList } from '@/types/device-cmd';
-import { useDockControl } from './use-dock-control';
-import { EDockModeCode } from '@/types/device';
-import { updateDeviceCmdInfoByOsd, updateDeviceCmdInfoByExecuteInfo } from '@/utils/device-cmd';
+import Store from '@/store'
-import Store from '@/store';
+const valueStyle = ref(0)
+const cameraModeValue = ref(0)
+const videoValue = ref("zoom")
+const photo_storage_settings = ref([])
+const video_storage_settings = ref([])
-const props = defineProps(['sn', 'deviceInfo']);
-const initCmdList = baseCmdList.map(cmdItem => Object.assign({}, cmdItem));
-const cmdList = ref(initCmdList);
+// 定义一个数据videoList
+const videoList = reactive([])
+// 摄像头信息
+let cameras = reactive([])
+// let cameras = reactive([
+// {
+// camera_mode: 0,
+// liveview_world_region: {
+// bottom: 0.5515424609184265,
+// left: 0.42740535736083984,
+// right: 0.5581043362617493,
+// top: 0.42277535796165466
+// },
+// payload_index: "81-0-0",
+// photo_state: 0,
+// record_time: 0,
+// recording_state: 0,
+// remain_photo_num: 3931,
+// remain_record_duration: 0,
+// zoom_factor: 6.9999943,
+// ir_zoom_factor: 2,
+// photo_storage_settings: [
+// "vision",
+// "ir"
+// ],
+// video_storage_settings: [
+// "vision"
+// ]
+// }
+// ])
+
+// 无人机信息
+let deviceInfo = ref()
+
+// camera_mode {"0":"拍照","1":"录像","2":"智能低光","3":"全景拍照","-1":"不支持的模式"}
+const cameraMode = [
+ { label: '拍照', value: 0 },
+ { label: '录像', value: 1 },
+ { label: '智能低光', value: 2 },
+ { label: '全景拍照', value: 3 },
+ // { label: '不支持的模式', value: -1 },
+]
+
+// 调色盘选项数据
+const paletteOptions = [
+ { label: '白热', value: 0 },
+ { label: '黑热', value: 1 },
+ { label: '描红', value: 2 },
+ { label: '医疗', value: 3 },
+ { label: '彩虹1', value: 5 },
+ { label: '铁红', value: 6 },
+ { label: '北极', value: 8 },
+ { label: '熔岩', value: 11 },
+ { label: '热铁', value: 12 },
+ { label: '彩虹2', value: 13 },
+]
+// 视频类型 ZOOM("zoom"), WIDE("wide"), THERMAL("thermal"), NORMAL("normal"), IR("ir");
+const videoType = [
+ { label: '变焦', value: 'zoom' },
+ { label: '广角', value: 'wide' },
+ // { label: '热红外', value: 'thermal' },
+ // { label: '正常', value: 'normal' },
+ { label: '红外', value: 'ir' },
+]
+// 拍照存储类型{current, wide, zoom, ir},可多选
+const photoStorageType = [
+ { label: '当前', value: 'current' },
+ { label: '广角', value: 'wide' },
+ { label: '变焦', value: 'zoom' },
+ { label: '可见光', value: 'vision' },
+ { label: '红外', value: 'ir' },
+]
+
+const props = defineProps(['sn', 'deviceInfo'])
+const initCmdList = baseCmdList.map(cmdItem => Object.assign({}, cmdItem))
+const cmdList = ref(initCmdList)
+// dock 控制指令
+const debugStatus = ref(props.deviceInfo.mode_code == EDockModeCode.Remote_Debugging)
// 根据机场指令执行状态更新信息
watch(
() => Store.getters.devicesCmdExecuteInfo,
devicesCmdExecuteInfo => {
+ // console.log('设备指令执行状态变化', devicesCmdExecuteInfo)
if (props.sn && devicesCmdExecuteInfo[props.sn]) {
- updateDeviceCmdInfoByExecuteInfo(cmdList.value, devicesCmdExecuteInfo[props.sn]);
+ updateDeviceCmdInfoByExecuteInfo(cmdList.value, devicesCmdExecuteInfo[props.sn])
}
},
{
immediate: true,
deep: true,
}
-);
-
-// 根据设备osd信息更新信息
+)
watch(
- () => props.deviceInfo,
- value => {
- updateDeviceCmdInfoByOsd(cmdList.value, value);
- // console.log('deviceInfo', value)
+ () => Store.state.device.videoSurveillance,
+ newObj => {
+ // console.log('视频类型监听中', newObj)
+ if (newObj && newObj.live_status && newObj.live_status.length) {
+ let arr = newObj.live_status || []
+ if (videoList.length == arr.length) {
+ return
+ }
+ arr.forEach(element => {
+ let video_id = element.video_id
+ element.payIndex = video_id.split('/')[1].split('-')[1]
+ if (props.deviceInfo.child_sn == video_id.split('/')[0]) {
+ if (element.video_type == 'normal' || element.video_type == 'thermal') {
+ videoValue.value = 'wide'
+ } else {
+ videoValue.value = element.video_type
+ }
+ }
+ })
+ videoList.push(...arr) // 添加新元素
+ }
},
{
immediate: true,
deep: true,
}
-);
+)
-// dock 控制指令
-const debugStatus = ref(
- props.deviceInfo.dock?.basic_osd.mode_code === EDockModeCode.Remote_Debugging
-);
-
-async function onDeviceStatusChange(status) {
- let result = false;
- if (status) {
- result = await dockDebugOnOff(props.sn, true);
- } else {
- result = await dockDebugOnOff(props.sn, false);
+// 根据设备osd信息更新信息
+watch(
+ () => Store.getters.deviceState,
+ value => {
+ // console.log('设备状态变化', value)
+ if (props.sn && (value.currentSn === props.deviceInfo.child_sn || value.currentSn === props.deviceInfo.device_sn)) {
+ debugStatus.value = value.dockInfo[props.deviceInfo.device_sn]?.basic_osd?.mode_code === EDockModeCode.Remote_Debugging
+ const devices = {}
+ devices['device'] = value.deviceInfo[props.deviceInfo.child_sn]
+ devices['dock'] = value.dockInfo[props.deviceInfo.device_sn]
+ devices['gateway'] = value.gatewayInfo
+ let cameraList = value.deviceInfo[props.deviceInfo.child_sn]?.cameras || []
+ cameras = cameraList
+ // console.log('设备osd.cameras信息变化', cameras)
+ // 判断cameras列表长度是否为0,如果为0,则不执行后续操作
+ if (cameras.length > 0) {
+ cameraModeValue.value = cameras[0].camera_mode
+ photo_storage_settings.value = cameras[0]?.photo_storage_settings ?? [];
+ video_storage_settings.value = cameras[0]?.video_storage_settings ?? [];
+ }
+ deviceInfo = ref(value.deviceInfo[props.deviceInfo.child_sn])
+ updateDeviceCmdInfoByOsd(cmdList.value, devices)
+ }
+ },
+ {
+ immediate: true,
+ deep: true,
}
+)
+onMounted(() => {
+ getLiveStatuss()
+});
- console.log(result, '---1------');
+async function getLiveStatuss() {
+ let result = await getLiveStatus(props.sn)
+ result.data.data.live_status.forEach(item => {
+ if (props.deviceInfo.child_sn == item.video_id.split('/')[0]) {
+ if (item.video_type == 'normal' || item.video_type == 'thermal') {
+ videoValue.value = 'wide'
+ } else {
+ videoValue.value = item.video_type
+ }
+ }
+ })
+}
+
+
+// 远程控制开关
+async function onDeviceStatusChange(status) {
+ let result = false
+ if (status) {
+ result = await dockDebugOnOff(props.sn, true)
+ } else {
+ result = await dockDebugOnOff(props.sn, false)
+ }
if (!result) {
if (status) {
- debugStatus.value = false;
+ debugStatus.value = false
} else {
- debugStatus.value = true;
+ debugStatus.value = true
}
}
}
-const { sendDockControlCmd, dockDebugOnOff } = useDockControl();
+const { sendDockControlCmd, dockDebugOnOff } = useDockControl()
async function sendControlCmd(cmdItem, index) {
const params = {
sn: props.sn,
cmd: cmdItem.cmdKey,
action: cmdItem.action,
- };
- const success = await sendDockControlCmd(params, true);
+ }
+ const success = await sendDockControlCmd(params, true)
if (success) {
- // updateDeviceSingleCmdInfo(cmdList.value[index])
+ updateDeviceSingleCmdInfo(cmdList.value[index])
}
}
+// webSocket 监听
const messageHandler = async payload => {
if (!payload) {
- return;
+ return
}
-
switch (payload.biz_code) {
case EBizCode.GatewayOsd: {
- Store.commit('SET_GATEWAY_INFO', payload.data);
- break;
+ Store.commit('SET_GATEWAY_INFO', payload.data)
+ break
}
+ // 飞行器
case EBizCode.DeviceOsd: {
- Store.commit('SET_DEVICE_INFO', payload.data);
- break;
+ Store.commit('SET_DEVICE_INFO', payload.data)
+ break
}
+ // 机场
case EBizCode.DockOsd: {
- // if (payload.data.sn === workspace_id.value) {
- Store.commit('SET_DOCK_INFO', payload.data);
- // console.log(payload.data, 'data')
- // }
- break;
+ Store.commit('SET_DOCK_INFO', payload.data)
+ break
}
case EBizCode.MapElementCreate: {
- Store.commit('SET_MAP_ELEMENT_CREATE', payload.data);
- break;
+ Store.commit('SET_MAP_ELEMENT_CREATE', payload.data)
+ break
}
case EBizCode.MapElementUpdate: {
- Store.commit('SET_MAP_ELEMENT_UPDATE', payload.data);
- break;
+ Store.commit('SET_MAP_ELEMENT_UPDATE', payload.data)
+ break
}
case EBizCode.MapElementDelete: {
- Store.commit('SET_MAP_ELEMENT_DELETE', payload.data);
- break;
+ Store.commit('SET_MAP_ELEMENT_DELETE', payload.data)
+ break
}
case EBizCode.DeviceOnline: {
- Store.commit('SET_DEVICE_ONLINE', payload.data);
- break;
+ Store.commit('SET_DEVICE_ONLINE', payload.data)
+ break
}
case EBizCode.DeviceOffline: {
- Store.commit('SET_DEVICE_OFFLINE', payload.data);
- break;
+ Store.commit('SET_DEVICE_OFFLINE', payload.data)
+ break
}
case EBizCode.FlightTaskProgress:
case EBizCode.FlightTaskMediaProgress:
case EBizCode.FlightTaskMediaHighestPriority: {
- EventBus.emit('flightTaskWs', payload);
- break;
+ EventBus.emit('flightTaskWs', payload)
+ break
}
case EBizCode.DeviceHms: {
- Store.commit('SET_DEVICE_HMS_INFO', payload.data);
- break;
+ Store.commit('SET_DEVICE_HMS_INFO', payload.data)
+ break
+ }
+ case EBizCode.VideoSurveillance: {
+ if (payload.data.live_status && payload.data.live_status.length) {
+ Store.commit('SAVE_VIDEO_SURVEILLANCE_INFO', payload.data)
+ }
+ break
}
case EBizCode.DeviceReboot:
case EBizCode.DroneOpen:
@@ -189,25 +368,93 @@
biz_code: payload.biz_code,
timestamp: payload.timestamp,
...payload.data,
- });
- break;
+ })
+ break
}
case EBizCode.ControlSourceChange:
case EBizCode.FlyToPointProgress:
case EBizCode.TakeoffToPointProgress:
case EBizCode.JoystickInvalidNotify:
case EBizCode.DrcStatusNotify: {
- EventBus.emit('droneControlWs', payload);
- break;
+ EventBus.emit('droneControlWs', payload)
+ break
}
default:
- break;
+ break
}
-};
+}
-const webSorketUrl = getWebsocketUrl() + '&workspace-id=' + props.deviceInfo.workspace_id;
+const webSorketUrl = getWebsocketUrl() + '&workspace-id=' + props.deviceInfo.workspace_id
// 监听ws 消息
-useConnectWebSocket(messageHandler, webSorketUrl);
+useConnectWebSocket(messageHandler, webSorketUrl)
+
+// 添加 changs 方法
+async function changs(value, item) {
+ const payload = {
+ [item.payload_index]: {
+ thermal_current_palette_style: value
+ }
+ }
+ console.log('payload', payload)
+ let data = await setThermalCurrentPaletteStyle(props.sn, props.deviceInfo.workspace_id, payload)
+ if (data.data.code === 0) {
+ ElMessage.success('修改成功');
+ }
+}
+// 摄像头设置
+async function cameraSettings(value, item) {
+ const payload = {
+ // 1581F6Q8D245U00G57GJ/81-0-0/normal-0
+ video_id: props.deviceInfo.child_sn + '/' + item.payload_index + '/normal-0',
+ video_type: value
+ }
+ let data = await setStreamsSwitch(payload)
+ if (data.data.code === 0) {
+ ElMessage.success('修改成功');
+ }
+}
+// 相机模式设置
+async function photoAndVideoCmdSettings(value, item) {
+ // photo 0 video_start 1 video_stop
+ item.camera_mode = value
+ let data = await photoAndVideoCmd(props.deviceInfo.child_sn, value)
+ if (data.data.code == 0) {
+ ElMessage.success('修改成功');
+ }
+}
+// 照片存储设置
+async function photoStorageTypeChang(value, item) {
+ // value 不能为空
+ if (!value) {
+ ElMessage.error('请选择存储方式');
+ return;
+ }
+ const payload = {
+ payload_index: item.payload_index,
+ photo_storage_settings: value
+ }
+ item.photo_storage_settings = value
+ let data = await setPhotoStorageSet(props.sn, payload)
+ if (data.data.code == 0) {
+ ElMessage.success('修改成功');
+ }
+}
+// 视频存储设置
+async function videoStorageTypeChang(value, item) {
+ if (!value) {
+ ElMessage.error('请选择存储方式');
+ return;
+ }
+ const payload = {
+ payload_index: item.payload_index,
+ video_storage_settings: value
+ }
+ item.video_storage_settings = value
+ let data = await setVideoStorageSet(props.sn, payload)
+ if (data.data.code == 0) {
+ ElMessage.success('修改成功');
+ }
+}
</script>
<style lang="scss" scoped>
@@ -227,7 +474,7 @@
.debug-btn {
margin-left: 10px;
- border: 1px solid #585858;
+ // border: 1px solid #585858;
}
}
@@ -235,16 +482,18 @@
display: flex;
flex-wrap: wrap;
justify-content: space-between;
- padding: 4px 10px;
+ padding: 4px 15px;
+
.control-cmd-item {
- width: 220px;
+ width: 320px;
height: 58px;
display: flex;
align-items: center;
justify-content: space-between;
border: 1px solid #666;
- margin: 4px 0;
+ margin: 8px 0;
padding: 0 8px;
+ border-radius: 2px;
.control-cmd-item-left {
display: flex;
@@ -257,5 +506,30 @@
}
}
}
+
+ ::v-deep {
+ .el-form {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-between;
+ padding: 4px 15px;
+ }
+
+ .el-form-item {
+ width: 320px;
+ height: 58px;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ border: 1px solid #666;
+ margin: 8px 0;
+ padding: 0 8px;
+ border-radius: 2px;
+ }
+
+ .el-select__wrapper {
+ width: 160px;
+ }
+ }
}
-</style>
+</style>
\ No newline at end of file
--
Gitblit v1.9.3