Browse Source

新增行车诱导设备

develop
王兴琳 9 hours ago
parent
commit
777b53981b
  1. 73
      ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/Dialogs/DrivingGuidance/components/NewDeviceControlDialog.vue
  2. 730
      ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/Dialogs/DrivingGuidance/components/NewDeviceParam.vue
  3. 198
      ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/Dialogs/DrivingGuidance/index.vue
  4. 287
      ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/HomeDevice/DrivingGuidance.vue
  5. 542
      ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/HomeDevice/NewDeviceDrivingGuidance.vue
  6. 323
      ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/HomeDevice/OldDeviceDrivingGuidance.vue

73
ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/Dialogs/DrivingGuidance/components/NewDeviceControlDialog.vue

@ -0,0 +1,73 @@
<template>
<Dialog v-model="modelVisible" title="设备操作(新设备)" width="600px" style="z-index:1200">
<DeviceParam v-model="modelVisible" ref="DeviceParam" :deviceId="deviceId" :id="id" :deviceType="deviceType"
@update:submitting="(val) => { submitting = val }">
</DeviceParam>
<template #footer>
<Button style="background-color: rgba(0, 179, 204, 0.3)"
@click.native="(modelVisible = false), (submitting = false)">
取消
</Button>
<Button @click.native="handleSubmit" :loading="submitting"> 确定 </Button>
</template>
</Dialog>
</template>
<script>
import Dialog from "@screen/components/Dialog/index.vue";
import Button from "@screen/components/Buttons/Button.vue";
import NewDeviceParam from "./NewDeviceParam.vue";
export default {
name: "NewDeviceControlDialog",
components: {
Dialog,
Button,
DeviceParam: NewDeviceParam,
},
model: {
prop: "visible",
event: "update:value",
},
props: {
visible: Boolean,
deviceId: String,
id: Number,
deviceType: String,
},
data() {
return {
submitting: false,
};
},
computed: {
modelVisible: {
get() {
return this.visible;
},
set(val) {
this.$emit("update:value", val);
},
},
},
methods: {
handleSubmit() {
this.$refs.DeviceParam.handleSubmit();
},
},
};
</script>
<style lang="scss" scoped>
.NewDeviceControlDialog {
width: 450px;
height: 250px;
display: flex;
flex-direction: column;
gap: 15px;
.tips {
font-size: 12px;
}
}
</style>

730
ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/Dialogs/DrivingGuidance/components/NewDeviceParam.vue

@ -0,0 +1,730 @@
<template>
<div class="DeviceControlDialog" :style="{
'margin-top': isMultiControl ? '15px' : undefined,
'width': isMultiControl ? '100%' : undefined,
}">
<Form v-model="formData" class="form" ref="FormConfigRef" :formList="formList" column="1" labelWidth="120px" />
<div class="tips" v-if="formData.deviceMode == 1">
说明: 阈值开关开启时设备将按照设定的开灯时间和关灯时间自动控制
</div>
</div>
</template>
<script>
import Dialog from "@screen/components/Dialog/index.vue";
import Button from "@screen/components/Buttons/Button.vue";
import Form from "@screen/components/FormConfig";
import { Message } from "element-ui";
import request from "@/utils/request";
import { delay } from "@screen/utils/common.js";
const workStatus = [
{
key: "00",
label: "不更新状态",
disabled: false,
},
{
key: "01",
label: "常亮",
},
{
key: "02",
label: "流水",
},
{
key: "03",
label: "闪烁",
},
{
key: "04",
label: "关闭",
disabled: false,
},
];
export default {
name: "NewDeviceParam",
components: {
Dialog,
Button,
Form,
},
model: {
prop: "visible",
event: "update:value",
},
props: {
visible: Boolean,
deviceId: String,
id: [String, Number],
deviceType: String,
isMultiControl: Boolean,
selectItems: {
type: Array,
default: () => []
},
deviceParams: {
type: Object,
default: () => ({})
}
},
data() {
return {
formData: {
onTimePicker: null, //
offTimePicker: null, //
},
//
apiDeviceParams: {},
formList: [
{
label: "模式选择:",
key: "cmd",
type: "RadioGroup",
default: 1,
options: {
type: "circle",
options: [
{
key: 1,
label: "同步",
},
{
key: 2,
label: "流水",
},
{
key: 3,
label: "尾迹",
},
],
},
},
{
label: "亮灯模式:",
key: "mode",
type: "RadioGroup",
default: 0,
options: {
type: "circle",
options: [
{
key: 0,
label: "常亮",
},
{
key: 1,
label: "单闪",
},
{
key: 2,
label: "双闪",
},
{
key: 3,
label: "三闪",
},
],
},
},
{
label: "设备开关:",
key: "sw",
type: "RadioGroup",
default: true,
options: {
type: "circle",
options: [
{
key: true,
label: "开启",
},
{
key: false,
label: "关闭",
},
],
},
},
{
label: "闪灯频率:",
key: "ff",
type: "Input",
required: true,
options: {
placeholder: "请输入闪灯频率 (1-30)",
tip: "数值×5表示一分钟闪烁次数(例如:输入6表示每分钟闪烁30次)"
},
},
{
label: "亮度:",
key: "lum",
type: "Input",
required: true,
options: {
placeholder: "请输入亮度 (0-100)",
tip: "亮度值范围0-100,数值越大亮度越高"
},
},
{
label: "亮灯时长:",
key: "ontime",
type: "Input",
required: true,
options: {
placeholder: "请输入亮灯时长 (50-500)",
tip: "必须为50的倍数,单位为毫秒(例如:50、100、150...500)"
},
},
{
label: "灯光颜色:",
key: "sg",
type: "RadioGroup",
default: "AA",
options: {
type: "circle",
options: [
{
key: "AA",
label: "红色",
},
{
key: "55",
label: "黄色",
},
],
},
},
{
label: "灵敏度:",
key: "cth",
type: "Input",
required: true,
options: {
placeholder: "请输入灵敏度 (0-255)",
tip: "值越高灵敏度越低,范围0-255"
},
},
{
label: "阈值开关:",
key: "deviceMode",
type: "RadioGroup",
default: 0,
options: {
type: "circle",
options: [
{
key: 0,
label: "关闭",
},
{
key: 1,
label: "开启",
},
],
},
},
{
label: "开灯时间:",
key: "onTimePicker",
type: "TimePicker",
required: true,
visible: (data) => data.deviceMode === 1,
options: {
format: "HH:mm",
valueFormat: "HH:mm",
placeholder: "选择开灯时间",
tip: "选择开灯时间(格式:HH:mm,保存时会转换为数字格式如1800)"
},
},
{
label: "关灯时间:",
key: "offTimePicker",
type: "TimePicker",
required: true,
visible: (data) => data.deviceMode === 1,
options: {
format: "HH:mm",
valueFormat: "HH:mm",
placeholder: "选择关灯时间",
tip: "选择关灯时间(格式:HH:mm,保存时会转换为数字格式如0600)"
},
},
],
};
},
mounted() {
console.log('NewDeviceParam 组件 mounted,deviceId:', this.deviceId);
this.$emit("update:submitting", false);
// 使 props deviceParams
if (this.deviceParams && this.hasActualData(this.deviceParams)) {
console.log('使用 props 中的 deviceParams 进行回显');
this.setFormDataFromParams(this.deviceParams);
} else if (!this.isMultiControl) {
console.log('从接口获取设备参数进行回显');
this.reDisplay();
}
},
watch: {
// deviceParams
deviceParams: {
handler(newVal) {
console.log('deviceParams props 变化:', newVal);
if (newVal && this.hasActualData(newVal)) {
this.setFormDataFromParams(newVal);
}
},
immediate: true,
deep: true
},
//
'formData.onTimePicker': {
handler(newVal) {
console.log('onTimePicker 变化:', newVal);
if (newVal) {
this.formData.onTime = this.timeStringToNumber(newVal);
} else {
this.formData.onTime = null;
}
}
},
'formData.offTimePicker': {
handler(newVal) {
console.log('offTimePicker 变化:', newVal);
if (newVal) {
this.formData.offTime = this.timeStringToNumber(newVal);
} else {
this.formData.offTime = null;
}
}
}
},
methods: {
// Vue
hasActualData(obj) {
if (!obj || typeof obj !== 'object') return false;
// __
for (let key in obj) {
if (obj.hasOwnProperty(key) && !key.startsWith('__')) {
return true;
}
}
return false;
},
//
reDisplay() {
console.log('reDisplay 被调用,deviceId:', this.deviceId);
this.fetchDeviceProperty();
},
//
async fetchDeviceProperty() {
try {
console.log('开始从接口获取设备参数,deviceId:', this.deviceId);
//
const requestBody = {
params: {
list: [this.deviceId] // 使 deviceId prop
}
};
console.log('发送请求体:', requestBody);
const response = await request.post(
`business/device/functions/${this.deviceId}/getProperty`,
requestBody
);
console.log('接口响应:', response);
if (response.code === 200 && response.data) {
console.log('获取设备参数成功:', response.data);
this.parseResponseData(response.data);
} else {
console.warn('获取设备参数失败:', response);
Message.error('获取设备参数失败');
}
} catch (error) {
console.error('获取设备参数异常:', error);
Message.error('获取设备参数异常');
}
},
ensureBoolean(value) {
if (value === true || value === 'true') return true;
if (value === false || value === 'false') return false;
return value;
},
//
parseResponseData(data) {
try {
console.log('开始解析数据,数据类型:', typeof data, '值:', data);
//
let rawData = data;
if (Array.isArray(data) && data.length > 0) {
rawData = data[0];
}
// JSON
if (typeof rawData === 'string') {
try {
rawData = JSON.parse(rawData);
} catch (parseError) {
console.error('JSON解析失败:', parseError);
console.error('原始字符串:', rawData);
Message.error('数据解析失败');
return;
}
}
if (rawData && rawData.data) {
const deviceData = rawData.data;
console.log("设备属性数据:", deviceData);
//
const parsedParams = {};
// deviceProperty
if (deviceData.deviceProperty && Array.isArray(deviceData.deviceProperty) && deviceData.deviceProperty.length > 0) {
const property = deviceData.deviceProperty[0];
console.log('设备属性数据:', {
csq: property.csq,
latitude: property.lat,
longitude: property.lng,
voltage: property.vol
});
}
// lampParam
if (deviceData.lampParam && Array.isArray(deviceData.lampParam) && deviceData.lampParam.length > 0) {
const lampParam = deviceData.lampParam[0];
// lampParam
Object.assign(parsedParams, {
cmd: lampParam.cmd || 1,
mode: lampParam.mode || 0,
ff: lampParam.ff || 1,
lum: lampParam.lum || 50,
ontime: lampParam.ontime || 50,
sw: this.ensureBoolean(lampParam.sw),
sg: lampParam.sg || 'AA',
cth: lampParam.cth || 128
});
}
// deviceSetting
if (deviceData.deviceSetting && Array.isArray(deviceData.deviceSetting) && deviceData.deviceSetting.length > 0) {
const deviceSetting = deviceData.deviceSetting[0];
// deviceSetting
Object.assign(parsedParams, {
deviceMode: deviceSetting.mode || 0,
onTime: deviceSetting.onTime || 1800,
offTime: deviceSetting.offTime || 600
});
}
console.log('解析后的设备参数:', parsedParams);
//
this.apiDeviceParams = parsedParams;
this.setFormDataFromParams(parsedParams);
} else {
console.warn('数据格式不正确,没有 data 字段:', rawData);
Message.warning('设备参数数据格式不正确');
}
} catch (error) {
console.error('解析数据失败:', error);
console.error('原始数据:', data);
console.error('错误堆栈:', error.stack);
Message.error('解析设备参数失败');
}
},
//
setFormDataFromParams(params) {
const sourceParams = params || this.deviceParams || this.apiDeviceParams;
if (!sourceParams || !this.hasActualData(sourceParams)) {
console.log('没有有效的设备参数,跳过回显');
return;
}
//
const updates = {};
// cmd
if ('cmd' in sourceParams) {
updates.cmd = sourceParams.cmd;
}
// mode
if ('mode' in sourceParams) {
updates.mode = sourceParams.mode;
}
// sw
if ('sw' in sourceParams) {
updates.sw = this.ensureBoolean(sourceParams.sw);
}
// ff
if ('ff' in sourceParams) {
updates.ff = sourceParams.ff !== undefined ? sourceParams.ff.toString() : '';
}
// lum
if ('lum' in sourceParams) {
updates.lum = sourceParams.lum !== undefined ? sourceParams.lum.toString() : '';
}
// ontime
if ('ontime' in sourceParams) {
updates.ontime = sourceParams.ontime !== undefined ? sourceParams.ontime.toString() : '';
}
// sg
if ('sg' in sourceParams) {
updates.sg = sourceParams.sg;
}
// cth
if ('cth' in sourceParams) {
updates.cth = sourceParams.cth !== undefined ? sourceParams.cth.toString() : '';
}
// deviceMode
if ('deviceMode' in sourceParams) {
updates.deviceMode = sourceParams.deviceMode;
}
//
Object.assign(this.formData, updates);
//
if ('onTime' in sourceParams && sourceParams.onTime !== undefined && sourceParams.onTime !== null) {
this.formData.onTime = sourceParams.onTime;
this.formData.onTimePicker = this.numberToTimeString(sourceParams.onTime);
}
if ('offTime' in sourceParams && sourceParams.offTime !== undefined && sourceParams.offTime !== null) {
this.formData.offTime = sourceParams.offTime;
this.formData.offTimePicker = this.numberToTimeString(sourceParams.offTime);
}
},
// 1800 "18:00"
numberToTimeString(timeNum) {
if (timeNum === undefined || timeNum === null) {
console.log('numberToTimeString: 输入为空', timeNum);
return null;
}
// 40
const numStr = timeNum.toString().padStart(4, '0');
//
const hours = numStr.substring(0, 2);
const minutes = numStr.substring(2, 4);
const result = `${hours}:${minutes}`;
console.log('numberToTimeString 转换:', timeNum, '->', result);
return result;
},
// "18:00" 1800
timeStringToNumber(timeStr) {
if (!timeStr) {
console.log('timeStringToNumber: 输入为空');
return null;
}
//
const [hours, minutes] = timeStr.split(':');
//
const result = parseInt(hours) * 100 + parseInt(minutes);
return result;
},
handleSubmit() {
const formData = this.$refs.FormConfigRef?.formData || this.formData;
console.log('提交的表单数据:', formData);
// 1-30
if (formData.ff) {
const ffValue = parseInt(formData.ff);
if (isNaN(ffValue) || ffValue < 1 || ffValue > 30) {
return Message.error('闪灯频率必须在1-30范围内!');
}
}
// 0-100
if (formData.lum) {
const lumValue = parseInt(formData.lum);
if (isNaN(lumValue) || lumValue < 0 || lumValue > 100) {
return Message.error('亮度必须在0-100范围内!');
}
}
// 50-50050
if (formData.ontime) {
const ontimeValue = parseInt(formData.ontime);
if (isNaN(ontimeValue) || ontimeValue < 50 || ontimeValue > 500) {
return Message.error('亮灯时长必须在50-500范围内!');
}
if (ontimeValue % 50 !== 0) {
return Message.error('亮灯时长必须是50的倍数!');
}
}
// 0-255
if (formData.cth) {
const cthValue = parseInt(formData.cth);
if (isNaN(cthValue) || cthValue < 0 || cthValue > 255) {
return Message.error('灵敏度必须在0-255范围内!');
}
}
//
if (formData.deviceMode == 1) {
//
if (!formData.onTimePicker || !formData.offTimePicker) {
return Message.error('开灯时间和关灯时间不能为空!');
}
//
if (!formData.onTime) {
formData.onTime = this.timeStringToNumber(formData.onTimePicker);
}
if (!formData.offTime) {
formData.offTime = this.timeStringToNumber(formData.offTimePicker);
}
if (formData.onTime < 0 || formData.onTime > 2359 ||
formData.offTime < 0 || formData.offTime > 2359) {
return Message.error('时间必须在0-2359范围内!');
}
}
//
const requiredFields = ['cmd', 'mode', 'sw', 'ff', 'lum', 'ontime', 'sg', 'cth', 'deviceMode'];
for (const field of requiredFields) {
const value = formData[field];
if (value === undefined || value === null || value === '') {
return Message.error(`${this.getFieldLabel(field)}不能为空!`);
}
}
this.$emit("update:submitting", true);
// lampParam
const lampParamData = {
cmd: parseInt(formData.cmd),
mode: parseInt(formData.mode),
ff: parseInt(formData.ff),
lum: parseInt(formData.lum),
ontime: parseInt(formData.ontime),
sw: formData.sw,
sg: formData.sg,
cth: parseInt(formData.cth)
};
// deviceSetting
const deviceSettingData = {
mode: parseInt(formData.deviceMode),
onTime: formData.onTime || 0,
offTime: formData.offTime || 0
};
console.log('发送的数据:', {
lampParam: lampParamData,
deviceSetting: deviceSettingData
});
const requestBody = {
params: {
list: [this.deviceId],
params: {
lampParam: lampParamData,
deviceSetting: deviceSettingData
}
}
};
//
request.post(
`business/device/functions/${this.deviceId}/setDesired`,
requestBody
)
.then(res => {
if (res.code === 200) {
this.$emit("update:value", false);
Message.success('设备操作成功');
} else {
Message.error(res.message || '设备操作失败');
}
})
.catch((err) => {
console.error('设备操作失败:', err);
Message.error('设备操作失败');
})
.finally(() => {
this.$emit("update:submitting", false);
});
},
getFieldLabel(field) {
const labelMap = {
cmd: '模式选择',
mode: '亮灯模式',
sw: '设备开关',
ff: '闪灯频率',
lum: '亮度',
ontime: '亮灯时长',
sg: '灯光颜色',
cth: '灵敏度',
deviceMode: '阈值开关',
onTime: '开灯时间',
offTime: '关灯时间'
};
return labelMap[field] || field;
}
},
};
</script>
<style lang="scss" scoped>
.DeviceControlDialog {
width: 450px;
height: 500px;
display: flex;
flex-direction: column;
gap: 15px;
.tips {
font-size: 12px;
color: #909399;
margin-top: 10px;
}
}
</style>

198
ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/Dialogs/DrivingGuidance/index.vue

@ -1,25 +1,16 @@
<template> <template>
<Dialog v-model="obverseVisible" title="行车诱导" width="470px"> <NewDeviceDrivingGuidance
<div class="DrivingGuidance"> v-if="isNewDevice"
<Video class="video-stream" :camId="camId" img="智能行车诱导" /> :visible="internalVisible"
:data="data"
<ElTabs v-model="activeName" @tab-click="handleClickTabs" class="tabs"> @close="handleClose"
<ElTabPane label="基本信息" name="first"> />
<Descriptions :list="list" :data="data" style="gap: 18px" /> <OldDeviceDrivingGuidance
</ElTabPane> v-else
<!-- <ElTabPane label="设备参数" name="second">设备参数</ElTabPane> --> :visible="internalVisible"
<ElTabPane label="在线率统计" name="third"> :data="data"
<LineChart v-if="activeName === 'third'" :productId="dialogData.id" style="height: 180px" /> @close="handleClose"
</ElTabPane> />
</ElTabs>
<div class="bottom">
<Button v-hasPermi="['business:home:drivingGuidance']" @click.native="onControlClick" :style="dialogData.useState ? '':'background-color:grey'">设备操作</Button>
</div>
</div>
<DeviceControlDialog v-model="deviceControlVisible" :deviceId="dialogData.iotDeviceId" :id="dialogData.id"
:deviceType="dialogData.deviceType" />
</Dialog>
</template> </template>
<script> <script>
@ -27,28 +18,29 @@ import Dialog from "@screen/components/Dialog/index.vue";
import Button from "@screen/components/Buttons/Button.vue"; import Button from "@screen/components/Buttons/Button.vue";
import Descriptions from "@screen/components/Descriptions.vue"; import Descriptions from "@screen/components/Descriptions.vue";
import DeviceControlDialog from "./components/DeviceControlDialog.vue"; import DeviceControlDialog from "./components/DeviceControlDialog.vue";
import { import {getProduct} from "@screen/pages/Home/components/RoadAndEvents/utils/httpList.js";
getRoadInfoByStakeMark,
getProduct,
} from "@screen/pages/Home/components/RoadAndEvents/utils/httpList.js";
import Video from "@screen/components/Video"; import Video from "@screen/components/Video";
import request from "@/utils/request";
import { delay } from "@screen/utils/common.js";
import { handle3CResult } from "@screen/utils/deviceControl.js";
import { inducerModeDic, inducerWorkTypeDic } from "@screen/utils/enum.js";
import { find, assign } from "lodash";
import { dialogDelayVisible } from "./../mixin"; import { dialogDelayVisible } from "./../mixin";
import LineChart from "../../LineChart/index.vue"; import LineChart from "../../LineChart/index.vue";
import NewDeviceDrivingGuidance from '@/views/JiHeExpressway/pages/Home/components/HomeDevice/NewDeviceDrivingGuidance.vue';
import OldDeviceDrivingGuidance from '@/views/JiHeExpressway/pages/Home/components/HomeDevice/OldDeviceDrivingGuidance.vue';
// //
export default { export default {
name: "DrivingGuidance", name: "DrivingGuidance",
mixins: [dialogDelayVisible], mixins: [dialogDelayVisible],
provide() {
return { props: {
requestURL: this.requestURL, visible: {
updateFormData: this.updateFormData type: Boolean,
}; default: false,
},
dialogData: {
type: Object,
required: true,
default: () => ({})
}
}, },
components: { components: {
Dialog, Dialog,
@ -57,145 +49,51 @@ export default {
DeviceControlDialog, DeviceControlDialog,
Video, Video,
LineChart, LineChart,
NewDeviceDrivingGuidance,
OldDeviceDrivingGuidance
}, },
data() { data() {
return { return {
camId: '',
activeName: "first", activeName: "first",
deviceControlVisible: false, internalVisible: this.visible,
data: { data: {
deviceType: "行车诱导",
deviceStation: "k094+079",
roadName: "济菏高速",
direction: "1",
deviceState: "0",
deviceVendors: "XXX厂家",
}, },
list: [
{
label: "设备名称",
key: "deviceName",
},
{
label: "设备桩号",
key: "stakeMark",
},
{
label: "道路名称",
key: "roadName",
},
{
label: "设备方向",
key: "direction",
enum: "CameraDirectionEnum",
},
{
label: "设备状态",
key: "deviceState",
enum: "DeviceTypeEnum",
},
{
label: "设备厂商",
key: "manufacturer",
},
{
label: "工作模式",
key: "workMode",
},
{
label: "上行工作状态",
key: "onWorkStatus",
},
{
label: "下行工作状态",
key: "inWorkStatus",
},
],
camId:null camId:null
}; };
}, },
emits: ['update:visible'],
computed: {
// 86
isNewDevice() {
return this.data?.iotDeviceId?.startsWith('86');
}
},
methods: {
handleClose() {
this.internalVisible = false;
this.$emit('update:visible', false);
}
},
async created() { async created() {
// camid
if(typeof this.dialogData.otherConfig === 'string'){ if(typeof this.dialogData.otherConfig === 'string'){
const oConfig = JSON.parse(this.dialogData.otherConfig) const oConfig = JSON.parse(this.dialogData.otherConfig)
if(oConfig && oConfig.camId){ if(oConfig && oConfig.camId){
this.camId = oConfig.camId this.camId = oConfig.camId
} }
} }
this.data = { ...this.dialogData, roadName: '济菏高速' }; this.data = { ...this.dialogData, roadName: '济菏高速' };
getProduct(this.dialogData.productId) getProduct(this.dialogData.productId)
.then((data) => { .then((data) => {
this.dialogData.brand = data.brand; this.dialogData.brand = data.brand;
}) })
.catch((err) => { }); .catch((err) => { });
// this.requestURL(52)
// .then((result) => {
// this.data.workMode = {
// "00": "",
// "01": "",
// "02": "",
// }[result.mode];
// this.data.onWorkStatus = result.onWorkStatus;
// this.data.inWorkStatus = result.inWorkStatus;
// })
// .catch((err) => { });
this.requestURL().then(async (data) => {
await delay(0);
const formData = {};
formData.controlType = data.mode;
await handle3CResult(data, formData, this.requestURL);
this.updateFormData({ ...formData, workMode: data.mode });
});
// const roadInfo = await getRoadInfoByStakeMark(this.dialogData.stakeMark);
// console.log(
// "%c [ roadInfo ]-103-index.vue",
// "font-size:15px; background:#36347c; color:#7a78c0;",
// roadInfo.roadName
// );
// if (roadInfo) this.data.roadName = roadInfo.roadName;
}, },
methods: {
onControlClick(){
if(this.dialogData.useState){
this.deviceControlVisible = true
}
},
updateFormData(formData) {
formData.workMode &&
this.$set(this.data, "workMode", inducerModeDic[formData.workMode]); //(this.data.workMode = inducerModeDic[formData.controlType]);
formData.inWorkStatus &&
this.$set(this.data, "inWorkStatus", inducerWorkTypeDic[formData.inWorkStatus]); //(this.data.inWorkStatus = inducerWorkTypeDic[formData.inWorkStatus]);
formData.onWorkStatus &&
this.$set(this.data, "onWorkStatus", inducerWorkTypeDic[formData.onWorkStatus]); //(this.data.onWorkStatus = inducerWorkTypeDic[formData.onWorkStatus]);
},
handleClickTabs() { },
requestURL(functionId = 52, options = {}) {
return new Promise((resolve, reject) => {
if (!this.dialogData.iotDeviceId) {
reject();
} else {
request
.post(
`business/device/functions/${this.dialogData.iotDeviceId}/${functionId}`,
options
)
.then((result) => {
if (result.code != 200) return reject();
resolve(result.data[0]);
})
.catch((err) => {
reject();
});
}
});
},
},
}; };
</script> </script>

287
ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/HomeDevice/DrivingGuidance.vue

@ -1,65 +1,26 @@
<template> <template>
<Dialog v-model="visibleModel" <!-- 根据设备类型分发到不同组件 -->
title="行车诱导" width="470px" > <NewDeviceDrivingGuidance v-if="isNewDevice"
<div class="DrivingGuidance"> :visible="visible"
<Video class="video-stream" :camId="camId" img="智能行车诱导" /> :data="data"
@close="$emit('close')" />
<ElTabs v-model="activeName" @tab-click="handleClickTabs" class="tabs"> <OldDeviceDrivingGuidance v-else
<ElTabPane label="基本信息" name="first"> :visible="visible"
<Descriptions :list="list" :data="data" style="gap: 18px" /> :data="data"
</ElTabPane> @close="$emit('close')" />
<!-- <ElTabPane label="设备参数" name="second">设备参数</ElTabPane> --> </template>
<ElTabPane label="在线率统计" name="third">
<LineChart v-if="activeName === 'third'" :productId="dialogData.id" style="height: 180px" /> <script>
</ElTabPane> import NewDeviceDrivingGuidance from './NewDeviceDrivingGuidance.vue';
</ElTabs> import OldDeviceDrivingGuidance from './OldDeviceDrivingGuidance.vue';
<div class="bottom"> export default {
<Button v-hasPermi="['business:home:drivingGuidance']" @click.native="onControlClick" :style="dialogData.useState ? '':'background-color:grey'">设备操作</Button> name: 'DrivingGuidance',
</div> components: {
</div> NewDeviceDrivingGuidance,
<DeviceControlDialog v-model="deviceControlVisible" :deviceId="dialogData.iotDeviceId" :id="dialogData.id" OldDeviceDrivingGuidance
:deviceType="dialogData.deviceType" /> },
</Dialog> props: {
</template>
<script>
import Dialog from "@screen/components/Dialog/index.vue";
import Button from "@screen/components/Buttons/Button.vue";
import Descriptions from "@screen/components/Descriptions.vue";
import DeviceControlDialog from "../Dialogs/DrivingGuidance/components/DeviceControlDialog.vue";
import {
getRoadInfoByStakeMark,
getProduct,
} from "@screen/pages/Home/components/RoadAndEvents/utils/httpList.js";
import Video from "@screen/components/Video";
import request from "@/utils/request";
import { delay } from "@screen/utils/common.js";
import { handle3CResult } from "@screen/utils/deviceControl.js";
import { inducerModeDic, inducerWorkTypeDic } from "@screen/utils/enum.js";
import { find, assign } from "lodash";
import { dialogDelayVisible } from "../Dialogs/mixin.js";
import LineChart from "../LineChart/index.vue";
//
export default {
name: "DrivingGuidance",
mixins: [dialogDelayVisible],
provide() {
return {
requestURL: this.requestURL,
updateFormData: this.updateFormData
};
},
components: {
Dialog,
Button,
Descriptions,
DeviceControlDialog,
Video,
LineChart,
},
props: {
visible: { visible: {
type: Boolean, type: Boolean,
default: true, default: true,
@ -69,200 +30,16 @@
default: null, default: null,
}, },
}, },
emit: ["close"], emits: ['close'],
computed: { computed: {
visibleModel: { // 86
get() { isNewDevice() {
if (this.visible) this.getData(); console.log("判断是否为新设备(以86开头)")
return this.visible; console.log(this.data)
},
set(bool) { console.log(this.data?.iotDeviceId?.startsWith('86'))
this.$emit("close", bool); return this.data?.iotDeviceId?.startsWith('86');
},
},
},
data() {
return {
camId: '',
activeName: "first",
deviceControlVisible: false,
data: {
deviceType: "行车诱导",
deviceStation: "k094+079",
roadName: "济菏高速",
direction: "1",
deviceState: "0",
deviceVendors: "XXX厂家",
},
list: [
{
label: "设备名称",
key: "deviceName",
},
{
label: "设备桩号",
key: "stakeMark",
},
{
label: "道路名称",
key: "roadName",
},
{
label: "设备方向",
key: "direction",
enum: "CameraDirectionEnum",
},
{
label: "设备状态",
key: "deviceState",
enum: "DeviceTypeEnum",
},
{
label: "设备厂商",
key: "manufacturer",
},
{
label: "工作模式",
key: "workMode",
},
{
label: "上行工作状态",
key: "onWorkStatus",
},
{
label: "下行工作状态",
key: "inWorkStatus",
},
],
camId:null
};
},
async created() {
// camid
if(typeof this.data.otherConfig === 'string'){
const oConfig = JSON.parse(this.data.otherConfig)
if(oConfig && oConfig.camId){
this.camId = oConfig.camId
}
}
this.data = { ...this.dialogData, roadName: '济菏高速' };
if(this.dialogData.productId!=null){
getProduct(this.dialogData.productId)
.then((data) => {
this.dialogData.brand = data.brand;
})
.catch((err) => { });
}
// this.requestURL(52)
// .then((result) => {
// this.data.workMode = {
// "00": "",
// "01": "",
// "02": "",
// }[result.mode];
// this.data.onWorkStatus = result.onWorkStatus;
// this.data.inWorkStatus = result.inWorkStatus;
// })
// .catch((err) => { });
this.requestURL().then(async (data) => {
await delay(0);
const formData = {};
formData.controlType = data.mode;
await handle3CResult(data, formData, this.requestURL);
this.updateFormData({ ...formData, workMode: data.mode });
});
// const roadInfo = await getRoadInfoByStakeMark(this.dialogData.stakeMark);
// console.log(
// "%c [ roadInfo ]-103-index.vue",
// "font-size:15px; background:#36347c; color:#7a78c0;",
// roadInfo.roadName
// );
// if (roadInfo) this.data.roadName = roadInfo.roadName;
},
methods: {
getData() {},
onControlClick(){
if(this.dialogData.useState){
this.deviceControlVisible = true
}
},
updateFormData(formData) {
formData.workMode &&
this.$set(this.data, "workMode", inducerModeDic[formData.workMode]); //(this.data.workMode = inducerModeDic[formData.controlType]);
formData.inWorkStatus &&
this.$set(this.data, "inWorkStatus", inducerWorkTypeDic[formData.inWorkStatus]); //(this.data.inWorkStatus = inducerWorkTypeDic[formData.inWorkStatus]);
formData.onWorkStatus &&
this.$set(this.data, "onWorkStatus", inducerWorkTypeDic[formData.onWorkStatus]); //(this.data.onWorkStatus = inducerWorkTypeDic[formData.onWorkStatus]);
},
handleClickTabs() { },
requestURL(functionId = 52, options = {}) {
return new Promise((resolve, reject) => {
if (!this.dialogData.iotDeviceId) {
reject();
} else {
request
.post(
`business/device/functions/${this.dialogData.iotDeviceId}/${functionId}`,
options
)
.then((result) => {
if (result.code != 200) return reject();
resolve(result.data[0]);
})
.catch((err) => {
reject();
});
}
});
},
},
};
</script>
<style lang="scss" scoped>
.DrivingGuidance {
width: 420px;
color: #fff;
display: flex;
flex-direction: column;
.camera-video {
flex: 1.5;
}
.tabs {
flex: 1;
display: flex;
flex-direction: column;
::v-deep {
.el-tabs__content {
flex: 1;
.el-tab-pane {
height: 100%;
}
}
}
}
.bottom {
margin-top: 12px;
display: flex;
gap: 9px;
align-items: center;
justify-content: end;
>div {
font-size: 16px;
padding: 6px 12px;
}
} }
} }
</style> };
</script>

542
ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/HomeDevice/NewDeviceDrivingGuidance.vue

@ -0,0 +1,542 @@
<template>
<Dialog v-model="visibleModel" title="行车诱导(新设备)" width="470px">
<div class="DrivingGuidance">
<Video class="video-stream" :camId="camId" img="智能行车诱导" />
<ElTabs v-model="activeName" @tab-click="handleClickTabs" class="tabs">
<ElTabPane label="基本信息" name="first">
<div class="device-info">
<div class="info-grid">
<div class="info-item" v-for="(item, index) in infoList" :key="index">
<div class="info-label">{{ item.label }}:</div>
<div class="info-value">{{ getInfoValue(item) }}</div>
</div>
</div>
<!-- 新设备特有参数 -->
<div class="device-setting-section" v-if="deviceParams.deviceMode !== undefined">
<div class="section-title">设备设置</div>
<div class="setting-grid">
<div class="setting-item">
<span class="setting-label">阈值开关:</span>
<span class="setting-value" :class="deviceParams.deviceMode === 1 ? 'on' : 'off'">
{{ deviceParams.deviceMode === 1 ? '开启' : '关闭' }}
</span>
</div>
<div class="setting-item">
<span class="setting-label">开灯时间:</span>
<span class="setting-value">{{ formatTime(deviceParams.onTime) }}</span>
</div>
<div class="setting-item">
<span class="setting-label">关灯时间:</span>
<span class="setting-value">{{ formatTime(deviceParams.offTime) }}</span>
</div>
</div>
</div>
</div>
</ElTabPane>
<ElTabPane label="设备参数" name="second">
<div class="device-params">
<div class="param-section">
<div class="section-title">灯控参数</div>
<div class="param-grid">
<div class="param-item">
<span class="param-label">模式:</span>
<span class="param-value">{{ getModeText(deviceParams.cmd) }}</span>
</div>
<div class="param-item">
<span class="param-label">亮灯模式:</span>
<span class="param-value">{{ getLightModeText(deviceParams.mode) }}</span>
</div>
<div class="param-item">
<span class="param-label">闪灯频率:</span>
<span class="param-value">{{ deviceParams.ff ? `${deviceParams.ff * 5}次/分钟` : '-' }}</span>
</div>
<div class="param-item">
<span class="param-label">亮度:</span>
<span class="param-value">{{ deviceParams.lum !== undefined ? `${deviceParams.lum}%` : '-' }}</span>
</div>
<div class="param-item">
<span class="param-label">亮灯时长:</span>
<span class="param-value">{{ deviceParams.ontime ? `${deviceParams.ontime}ms` : '-' }}</span>
</div>
<div class="param-item">
<span class="param-label">开关:</span>
<span class="param-value" :class="{ 'on': deviceParams.sw, 'off': !deviceParams.sw }">
{{ deviceParams.sw ? '开启' : '关闭' }}
</span>
</div>
<div class="param-item">
<span class="param-label">颜色:</span>
<span class="param-value" :style="{ color: getColorStyle(deviceParams.sg) }">
{{ getColorText(deviceParams.sg) }}
</span>
</div>
<div class="param-item">
<span class="param-label">灵敏度:</span>
<span class="param-value">{{ deviceParams.cth !== undefined ? deviceParams.cth : '-' }}</span>
</div>
</div>
</div>
</div>
</ElTabPane>
<ElTabPane label="在线率统计" name="third">
<LineChart v-if="activeName === 'third'" :productId="dialogData.id" style="height: 180px" />
</ElTabPane>
</ElTabs>
<div class="bottom">
<Button v-hasPermi="['business:home:drivingGuidance']"
@click.native="onControlClick"
:style="dialogData.deviceState ? '' : 'background-color:grey'">设备操作</Button>
</div>
</div>
<!-- 新设备控制对话框 -->
<NewDeviceControlDialog v-model="deviceControlVisible"
:deviceId="dialogData.iotDeviceId"
:id="dialogData.id"
:deviceType="dialogData.deviceType"
:deviceParams="deviceParams" />
</Dialog>
</template>
<script>
import Dialog from "@screen/components/Dialog/index.vue";
import Button from "@screen/components/Buttons/Button.vue";
import Video from "@screen/components/Video";
import LineChart from "../LineChart/index.vue";
import NewDeviceControlDialog from "../Dialogs/DrivingGuidance/components/NewDeviceControlDialog.vue";
import request from "@/utils/request";
import { CameraDirectionEnum, DeviceTypeEnum } from "@screen/utils/enum.js";
export default {
name: "NewDeviceDrivingGuidance",
components: {
Dialog,
Button,
NewDeviceControlDialog,
Video,
LineChart,
},
props: {
visible: {
type: Boolean,
default: true,
},
data: {
type: Object,
default: null,
},
},
emits: ["close"],
computed: {
visibleModel: {
get() {
return this.visible;
},
set(bool) {
this.$emit("close", bool);
},
},
dialogData() {
return this.data || {};
}
},
data() {
return {
camId: '',
activeName: "first",
deviceControlVisible: false,
deviceParams: {},
infoList: [
{ label: "设备名称", key: "deviceName" },
{ label: "设备桩号", key: "stakeMark" },
{ label: "道路名称", key: "roadName" },
{ label: "设备方向", key: "direction", enum: "CameraDirectionEnum" },
{ label: "设备状态", key: "deviceState", enum: "DeviceTypeEnum" },
{ label: "设备厂商", key: "manufacturer" },
]
};
},
async created() {
// camId
if (typeof this.dialogData.otherConfig === 'string') {
try {
const oConfig = JSON.parse(this.dialogData.otherConfig);
if (oConfig?.camId) {
this.camId = oConfig.camId;
}
} catch (e) {
console.error('解析otherConfig失败:', e);
}
}
//
await this.fetchDeviceProperty();
},
methods: {
//
async fetchDeviceProperty() {
//
const requestBody = {
params: {
list: [this.dialogData.iotDeviceId]
}
};
console.log('发送请求体:', requestBody);
const lampResponse = await request.post(
`business/device/functions/${this.dialogData.iotDeviceId}/getProperty`,
requestBody
);
if (lampResponse.code === 200 && lampResponse.data) {
console.log('lampParam获取成功:', lampResponse.data);
this.parseResponseData(lampResponse.data);
} else {
console.warn('获取lampParam失败:', lampResponse);
}
},
onControlClick() {
if (this.dialogData.deviceState) {
// 使 deviceParams
// deviceParams
if (Object.keys(this.deviceParams).length === 0) {
console.log('deviceParams 为空,尝试重新获取');
//
this.fetchDeviceProperty().then(() => {
this.deviceControlVisible = true;
});
} else {
console.log('deviceParams 已有数据,打开对话框');
this.deviceControlVisible = true;
}
} else {
this.$message.warning('设备状态不可用,无法操作');
}
},
ensureBoolean(value) {
if (value === true || value === 'true') return true;
if (value === false || value === 'false') return false;
return value;
},
//
parseResponseData(data) {
try {
console.log('开始解析数据,数据类型:', typeof data, '值:', data);
//
let rawData = data;
if (Array.isArray(data) && data.length > 0) {
rawData = data[0];
}
// JSON
if (typeof rawData === 'string') {
try {
rawData = JSON.parse(rawData);
} catch (parseError) {
console.error('JSON解析失败:', parseError);
console.error('原始字符串:', rawData);
return;
}
}
if (rawData && rawData.data) {
const deviceData = rawData.data;
console.log("设备属性数据")
console.log(deviceData)
// deviceProperty
if (deviceData.deviceProperty && Array.isArray(deviceData.deviceProperty) && deviceData.deviceProperty.length > 0) {
const property = deviceData.deviceProperty[0];
console.log('设备属性数据:', {
csq: property.csq,
latitude: property.lat,
longitude: property.lng,
voltage: property.vol
});
}
// lampParam
if (deviceData.lampParam && Array.isArray(deviceData.lampParam) && deviceData.lampParam.length > 0) {
const lampParam = deviceData.lampParam[0];
// lampParam
this.deviceParams = {
cmd: lampParam.cmd || 1,
mode: lampParam.mode || 0,
ff: lampParam.ff || 1,
lum: lampParam.lum || 50,
ontime: lampParam.ontime || 50,
sw: this.ensureBoolean(lampParam.sw),
sg: lampParam.sg || 'AA',
cth: lampParam.cth || 128 //
};
}
// deviceSetting
if (deviceData.deviceSetting && Array.isArray(deviceData.deviceSetting) && deviceData.deviceSetting.length > 0) {
const deviceSetting = deviceData.deviceSetting[0];
// deviceSetting
this.deviceParams = {
...this.deviceParams,
deviceMode: deviceSetting.mode || 0,
onTime: deviceSetting.onTime || 1800,
offTime: deviceSetting.offTime || 600
};
}
//
this.deviceParamType = 'lampParam';
//
this.$forceUpdate();
} else {
console.warn('数据格式不正确,没有 data 字段:', rawData);
}
} catch (error) {
console.error('解析数据失败:', error);
console.error('原始数据:', data);
console.error('错误堆栈:', error.stack);
}
},
handleClickTabs(tab) {
// tab
},
getInfoValue(item) {
const value = this.dialogData[item.key];
if (item.enum) {
if (item.enum === 'CameraDirectionEnum') {
return CameraDirectionEnum[value]?.text || value;
} else if (item.enum === 'DeviceTypeEnum') {
return DeviceTypeEnum[value]?.text || value;
}
}
return value || '-';
},
getModeText(cmd) {
const modeMap = { 1: '同步', 2: '流水', 3: '尾迹' };
return modeMap[cmd] || '-';
},
getLightModeText(mode) {
const lightModeMap = { 0: '常亮', 1: '单闪', 2: '双闪', 3: '三闪' };
return lightModeMap[mode] || '-';
},
getColorText(color) {
const colorMap = { 'AA': '红色', '55': '黄色' };
return colorMap[color] || '-';
},
getColorStyle(color) {
const colorStyleMap = { 'AA': '#ff0000', '55': '#ffff00' };
return colorStyleMap[color] ? { color: colorStyleMap[color] } : {};
},
formatTime(timeValue) {
if (timeValue === undefined || timeValue === null) return '-';
const timeStr = String(timeValue).padStart(4, '0');
const hour = timeStr.substring(0, 2);
const minute = timeStr.substring(2, 4);
return `${hour}:${minute}`;
}
}
};
</script>
<style lang="scss" scoped>
.DrivingGuidance {
width: 420px;
color: #fff;
display: flex;
flex-direction: column;
.video-stream {
height: 200px;
margin-bottom: 15px;
}
.tabs {
flex: 1;
flex-direction: column;
::v-deep {
.el-tabs__content {
flex: 1;
overflow-y: auto;
.el-tab-pane {
height: 100%;
}
}
}
}
.device-info {
padding: 10px;
.info-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 12px;
margin-bottom: 20px;
.info-item {
display: flex;
flex-direction: row; //
align-items: center; //
padding: 8px;
background: rgba(255, 255, 255, 0.05);
border-radius: 4px;
.info-label {
font-size: 13px;
color: #72b6ef;
margin-right: 8px; //
margin-bottom: 0; //
}
.info-value {
font-size: 14px;
font-weight: 500;
}
}
}
.device-setting-section {
margin-top: 15px;
padding: 12px;
background: rgba(255, 255, 255, 0.03);
border-radius: 6px;
border-left: 3px solid #409EFF;
.section-title {
font-size: 15px;
font-weight: bold;
margin-bottom: 12px;
color: #409EFF;
}
.setting-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
.setting-item {
flex-direction: column;
.setting-label {
font-size: 13px;
color: #a0a0a0;
margin-bottom: 4px;
}
.setting-value {
font-size: 14px;
font-weight: 500;
&.on {
color: #67c23a;
}
&.off {
color: #f56c6c;
}
}
}
}
}
}
.device-params {
padding: 10px;
.param-section {
.section-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 15px;
color: #409EFF;
border-left: 4px solid #409EFF;
padding-left: 10px;
}
.param-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 12px;
.param-item {
flex-direction: column;
padding: 10px;
background: rgba(255, 255, 255, 0.05);
border-radius: 4px;
.param-label {
font-size: 13px;
color: #72b6ef;
margin-bottom: 5px;
margin-right: 8px; //
}
.param-value {
font-size: 14px;
font-weight: 500;
&.on {
color: #67c23a;
}
&.off {
color: #f56c6c;
}
}
}
}
}
}
.bottom {
margin-top: 12px;
display: flex;
justify-content: flex-end;
::v-deep button {
font-size: 14px;
padding: 8px 20px;
&:disabled {
background-color: #666 !important;
cursor: not-allowed;
}
}
}
}
</style>

323
ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/HomeDevice/OldDeviceDrivingGuidance.vue

@ -0,0 +1,323 @@
<template>
<Dialog v-model="visibleModel" title="行车诱导" width="470px">
<div class="DrivingGuidance">
<Video class="video-stream" :camId="camId" img="智能行车诱导" />
<ElTabs v-model="activeName" @tab-click="handleClickTabs" class="tabs">
<ElTabPane label="基本信息" name="first">
<Descriptions :list="list" :data="deviceInfoData" style="gap: 18px" />
</ElTabPane>
<ElTabPane label="在线率统计" name="third">
<LineChart v-if="activeName === 'third'" :productId="deviceInfoData.id" style="height: 180px" />
</ElTabPane>
</ElTabs>
<div class="bottom">
<Button v-hasPermi="['business:home:drivingGuidance']" @click.native="onControlClick" :style="deviceInfoData.useState ? '' : 'background-color:grey'">设备操作</Button>
</div>
</div>
<DeviceControlDialog v-model="deviceControlVisible" :deviceId="deviceInfoData.iotDeviceId" :id="deviceInfoData.id"
:deviceType="deviceInfoData.deviceType" />
</Dialog>
</template>
<script>
import Dialog from "@screen/components/Dialog/index.vue";
import Button from "@screen/components/Buttons/Button.vue";
import Descriptions from "@screen/components/Descriptions.vue";
import DeviceControlDialog from "../Dialogs/DrivingGuidance/components/DeviceControlDialog.vue";
import {
getRoadInfoByStakeMark,
getProduct,
} from "@screen/pages/Home/components/RoadAndEvents/utils/httpList.js";
import Video from "@screen/components/Video";
import request from "@/utils/request";
import { delay } from "@screen/utils/common.js";
import { handle3CResult } from "@screen/utils/deviceControl.js";
import { inducerModeDic, inducerWorkTypeDic } from "@screen/utils/enum.js";
import { dialogDelayVisible } from "../Dialogs/mixin.js";
import LineChart from "../LineChart/index.vue";
export default {
name: "OldDeviceDrivingGuidance",
mixins: [dialogDelayVisible],
provide() {
return {
requestURL: this.requestURL,
updateFormData: this.updateFormData
};
},
components: {
Dialog,
Button,
Descriptions,
DeviceControlDialog,
Video,
LineChart,
},
props: {
visible: {
type: Boolean,
default: true,
},
data: { //
type: Object,
default: () => ({})
},
},
emits: ["close"],
computed: {
visibleModel: {
get() {
if (this.visible) this.getData();
return this.visible;
},
set(bool) {
console.log('子组件准备关闭,emit close');
this.$emit('close');
this.$emit("close", bool);
},
},
},
data() {
return {
camId: '',
activeName: "first",
deviceControlVisible: false,
// deviceInfoData props.data
deviceInfoData: {
deviceType: "行车诱导",
deviceStation: "k094+079",
roadName: "济菏高速",
direction: "1",
deviceState: "0",
deviceVendors: "XXX厂家",
},
list: [
{
label: "设备名称",
key: "deviceName",
},
{
label: "设备桩号",
key: "stakeMark",
},
{
label: "道路名称",
key: "roadName",
},
{
label: "设备方向",
key: "direction",
enum: "CameraDirectionEnum",
},
{
label: "设备状态",
key: "deviceState",
enum: "DeviceTypeEnum",
},
{
label: "设备厂商",
key: "manufacturer",
},
{
label: "工作模式",
key: "workMode",
},
{
label: "上行工作状态",
key: "onWorkStatus",
},
{
label: "下行工作状态",
key: "inWorkStatus",
},
]
};
},
watch: {
// props.data
data: {
immediate: true,
deep: true,
handler(newData) {
console.log('收到设备数据:', newData);
this.updateDeviceInfoData(newData);
}
}
},
async created() {
//
this.updateDeviceInfoData(this.data);
//
await delay(100);
// camId
if (typeof this.deviceInfoData.otherConfig === 'string') {
try {
const oConfig = JSON.parse(this.deviceInfoData.otherConfig);
if (oConfig && oConfig.camId) {
this.camId = oConfig.camId;
}
} catch (e) {
console.error('解析otherConfig失败:', e);
}
}
// - productId 访
if (this.deviceInfoData.productId) {
console.log('获取产品信息,productId:', this.deviceInfoData.productId);
getProduct(this.deviceInfoData.productId)
.then((data) => {
console.log('产品信息获取成功:', data);
if (data && data.brand) {
this.$set(this.deviceInfoData, "brand", data.brand);
}
})
.catch((err) => {
console.error('获取产品信息失败:', err);
});
} else {
console.warn('未找到 productId,跳过获取产品信息');
}
//
this.requestURL().then(async (data) => {
await delay(0);
const formData = {};
formData.controlType = data.mode;
await handle3CResult(data, formData, this.requestURL);
this.updateFormData({ ...formData, workMode: data.mode });
}).catch(err => {
console.error('获取设备状态失败:', err);
});
},
methods: {
//
updateDeviceInfoData(newData) {
if (!newData) return;
console.log('更新设备信息数据:', newData);
//
this.deviceInfoData = {
...this.deviceInfoData,
...newData,
roadName: '济菏高速' //
};
// iotDeviceId
if (!this.deviceInfoData.iotDeviceId) {
console.error('警告:设备ID为空');
} else {
console.log('设备ID有效:', this.deviceInfoData.iotDeviceId);
}
},
getData() {},
onControlClick() {
if (this.deviceInfoData.useState) {
this.deviceControlVisible = true;
}
},
updateFormData(formData) {
console.log('更新表单数据:', formData);
if (formData.workMode) {
this.$set(this.deviceInfoData, "workMode", inducerModeDic[formData.workMode]);
}
if (formData.inWorkStatus) {
this.$set(this.deviceInfoData, "inWorkStatus", inducerWorkTypeDic[formData.inWorkStatus]);
}
if (formData.onWorkStatus) {
this.$set(this.deviceInfoData, "onWorkStatus", inducerWorkTypeDic[formData.onWorkStatus]);
}
},
handleClickTabs() { },
requestURL(functionId = 52, options = {}) {
return new Promise((resolve, reject) => {
// ID
if (!this.deviceInfoData.iotDeviceId) {
console.error('请求失败:设备ID为空');
reject(new Error('设备ID为空'));
return;
}
// options 使
const requestBody = options && Object.keys(options).length > 0 ? options : {};
console.log(`发送请求:`, {
url: `business/device/functions/${this.deviceInfoData.iotDeviceId}/${functionId}`,
deviceId: this.deviceInfoData.iotDeviceId,
functionId: functionId,
body: requestBody
});
request
.post(
`business/device/functions/${this.deviceInfoData.iotDeviceId}/${functionId}`,
requestBody //
)
.then((result) => {
if (result.code != 200) {
console.warn('请求返回非200状态:', result);
return reject(result);
}
resolve(result.data[0]);
})
.catch((err) => {
console.error('请求失败:', err);
reject(err);
});
});
},
},
};
</script>
<style lang="scss" scoped>
.DrivingGuidance {
width: 420px;
color: #fff;
display: flex;
flex-direction: column;
.camera-video {
flex: 1.5;
}
.tabs {
flex: 1;
display: flex;
flex-direction: column;
::v-deep {
.el-tabs__content {
flex: 1;
.el-tab-pane {
height: 100%;
}
}
}
}
.bottom {
margin-top: 12px;
display: flex;
gap: 9px;
align-items: center;
justify-content: end;
>div {
font-size: 16px;
padding: 6px 12px;
}
}
}
</style>
Loading…
Cancel
Save