diff --git a/src/views/iot/device/profile/details.vue b/src/views/iot/device/profile/details.vue index e6c5d879..5d21b38c 100644 --- a/src/views/iot/device/profile/details.vue +++ b/src/views/iot/device/profile/details.vue @@ -54,6 +54,11 @@ > + +
+ +
+
- +
- +
@@ -105,11 +110,7 @@ />
- -
- -
-
+ diff --git a/src/views/iot/device/profile/functionWrap.vue b/src/views/iot/device/profile/functionWrap.vue index 0399d6a1..6dc977dc 100644 --- a/src/views/iot/device/profile/functionWrap.vue +++ b/src/views/iot/device/profile/functionWrap.vue @@ -18,18 +18,10 @@
- - + +
@@ -44,195 +36,88 @@
-
- - - - - - + + +
+ 执行 + +
+
- +
- 执行 - 重置 + 执行 +
@@ -242,24 +127,21 @@
执行结果:
-
- - - - - - - -
{{ item.data }}
+
+ + + + + + + + +
{{ item.data }}
{{ item.time }}
- - - + + +
@@ -269,35 +151,56 @@
暂无功能
- - 刷新列表 -
- - 添加卡号 + + + + + + + + + + + + + + + + + + - + + + + 刷新列表 +
+ + 添加卡号 +
+ @@ -305,26 +208,19 @@ 取 消 - 确 定 + 确 定
- + 取 消 确 定 @@ -339,6 +235,62 @@ import DeviceAlarmConfig from "@/views/profile/DeviceAlarmConfig/DeviceAlarmConf import DeviceTimingConfig from "@/views/profile/DeviceTimingConfig/DeviceTimingConfig"; import { addCard, delCard, getCard, setCardQuery } from "@/api/iot/cardNumber"; import MyMonacoEditor from '@/views/components/my-monaco-editor' +import MD5 from 'crypto-js/md5'; + +const dataTypeOptions = [ + { + value: 'int', + label: 'int(整数型)', + }, + { + value: 'long', + label: 'long(长整数型)', + }, + { + value: 'float', + label: 'float(单精度浮点型)', + }, + { + value: 'double', + label: 'double(双精度浮点数)', + }, + { + value: 'string', + label: 'text(字符串)', + }, + { + value: 'boolean', + label: 'boolean(布尔型)', + }, + { + value: 'date', + label: 'date(时间戳)', + }, + { + value: 'enum', + label: 'enum(枚举)', + }, + // { + // value: 'array', + // label: 'array(数组)', + // }, + // { + // value: 'object', + // label: 'object(结构体)', + // }, + // { + // value: 'file', + // label: 'file(文件)', + // }, + // { + // value: 'password', + // label: 'password(密码)', + // }, + // { + // value: 'geoPoint', + // label: 'geoPoint(地理位置)', + // } +]; export default { name: "functionWrap", @@ -390,16 +342,45 @@ export default { }, activeFunction: "", // 当前选中的功能ID currentFunction: null, // 当前选中的功能对象 - executionResults: [] // 执行结果列表 + currentInputs: [], // 当前选中的功能输入参数列表 + executionResults: [], // 执行结果列表 + selectedRowKeys: [], //参数多选列表 + submitFunctionParameters: {}, + // 校验弹窗相关 + preCheckVisible: false, + preCheckType: '', // 'userPassword' | 'staticPassword' | 'userSms' + preCheckForm: { + password: '', + phone: '', + smsCode: '' + }, + smsCodeLoading: false, + smsCountdown: 0 }; }, + computed: { + tableDataSource() { + return this.currentInputs.map((input) => ({ + key: input.id, + id: input.id, + name: input.name, + dataType: + dataTypeOptions.find( + (option) => option.value === input.valueParams.dataType, + ).label || input.valueParams.dataType, + required: input.required, + formType: input.valueParams.formType, + valueParams: input.valueParams, + })); + } + }, created() { if (this.deviceInfo.deviceId) { this.getProdFunctionList(); } }, watch: { - deviceInfo: function(val) { + deviceInfo: function (val) { if (val.deviceId) { // 清空之前的数据 this.formData = {}; @@ -418,6 +399,25 @@ export default { } }, methods: { + handleSelectionChange(val) { + this.selectedRowKeys = val; + }, + initializeSelectedRows() { + this.$nextTick(() => { + this.currentInputs.forEach((item) => { + if (item.required) { + this.$refs.multipleTable.toggleRowSelection(this.tableDataSource.find((row) => row.id === item.id), true); + } + }) + }) + }, + checkSelectable(row) { + // 如果 required 存在且为 true,则禁用选择 + if (row.hasOwnProperty('required') && row.required === true) { + return false; // 不可选择 + } + return true; // 可以选择 + }, // 获取精简模式表格数据 getSimpleTableData() { if (!this.currentFunction || !this.currentFunction.inputs) { @@ -439,7 +439,7 @@ export default { let functionList = []; try { - let json = JSON.parse(this.deviceInfo.prodJson); + let json = JSON.parse(this.deviceInfo.metadata); functionList = json.functions || []; } catch (error) { console.log(error); @@ -447,12 +447,15 @@ export default { console.log("this.deviceInfo", this.deviceInfo); this.functionList = functionList || []; - // 初始化表单数据 - this.initFormData(); + // 默认选中第一个功能 if (this.functionList.length > 0) { this.activeFunction = this.functionList[0].id; this.currentFunction = this.functionList[0]; + this.currentInputs = this.functionList[0].inputs || []; + // 初始化表单数据 + this.initFormData(); + this.initializeSelectedRows(); // 更新高级模式编辑器内容 if (this.functionMode === 'advanced') { this.updateAdvancedModeCode(); @@ -460,6 +463,7 @@ export default { } else { this.activeFunction = ""; this.currentFunction = null; + this.currentInputs = []; this.monacoValue = "{}"; } }, @@ -468,158 +472,240 @@ export default { console.log(e._props.name); this.functionMode = "simple"; this.activeFunction = e._props.name; - this.currentFunction = this.functionList.find( + const currentFunction = this.functionList.find( item => item.id === e._props.name ); + if (currentFunction) { + this.currentFunction = currentFunction; + this.currentInputs = currentFunction.inputs || []; + this.initFormData(); + this.initializeSelectedRows(); + } // 如果是高级模式,更新编辑器内容 if (this.functionMode === 'advanced') { this.updateAdvancedModeCode(); } }, + convertFormat(format) { + if (!format) return '' + // 将 YYYY 转换为 yyyy,其他格式保持不变 + return format.replace(/YYYY/g, 'yyyy') + }, // 初始化表单数据 initFormData(type) { - let formData = {}; - this.functionList.forEach(item => { - this.formData[item.id] = {}; - formData[item.id] = {}; - item.inputs.forEach(input => { - // 根据不同类型设置默认值 - if (['int', 'long'].includes(input.valueType.type)) { - formData[item.id][input.id] = 0; - } else if (['float'].includes(input.valueType.type)) { - formData[item.id][input.id] = 0.0; - } else if (['double'].includes(input.valueType.type)) { - formData[item.id][input.id] = 0.00; - } else if (input.valueType.type === 'boolean') { - formData[item.id][input.id] = false; - } else if (input.valueType.type === 'date') { - formData[item.id][input.id] = new Date(); - } else if (input.valueType.type === 'enum' && input.valueType.elements && input.valueType.elements.length > 0) { - formData[item.id][input.id] = input.valueType.elements[0].value; - } else if (input.valueType.type === 'array') { - formData[item.id][input.id] = []; - } else if (input.valueType.type === 'object') { - formData[item.id][input.id] = '{}'; - } else { - formData[item.id][input.id] = ''; + + const defaultData = {}; + this.currentInputs.forEach((input) => { + const { formType, scale } = input.valueParams; + + // 为不同类型的组件设置默认值 + switch (formType) { + case 'number': { + // 数字输入框默认为最小值或0 + defaultData[input.id] = scale + ? Number.parseFloat((input.valueParams.min || 0).toFixed(scale)) + : input.valueParams.min || 0; + break; } - }); + case 'progress': { + // 滚动条默认为最小值 + defaultData[input.id] = scale + ? Number.parseFloat((input.valueParams.min || 0).toFixed(scale)) + : input.valueParams.min || 0; + break; + } + case 'select': { + // 下拉框默认为第一个选项 + if ( + input.valueParams.enumConf && + input.valueParams.enumConf.length > 0 + ) { + defaultData[input.id] = input.valueParams.enumConf[0].value; + } + break; + } + case 'switch': { + // 开关默认值根据数据类型设置 + defaultData[input.id] = + input.valueParams.dataType === 'boolean' + ? false + : input.valueParams.falseValue || 'false'; + break; + } + default: { + // 其他类型保持undefined,让用户手动输入 + break; + } + } }); - if(type==='advanced'){ - let monacoValue= JSON.stringify(formData[this.currentFunction.id], null, 2); + if (type === 'advanced') { + let monacoValue = JSON.stringify(defaultData[this.currentFunction.id], null, 2); this.$nextTick(() => { this.$set(this, 'monacoValue', monacoValue); }) } + this.defaultData = defaultData; this.$nextTick(() => { - this.$set(this, 'formData', formData); + this.$set(this, 'formData', defaultData); }) - }, - // 提交功能 - submitFunction(item,type) { - if(type==='simple'){ + submitCheckFormatParams(item, type) { + + let parameters = {}; + let shouldReturn = false; // 标志变量 + if (type === 'simple') { + // 检查是否有选中的参数 + if (this.selectedRowKeys.length === 0) { + this.$message.error('请至少选择一个参数'); + return; + } this.$refs["form_" + item.id].validate(valid => { if (valid) { this.loading = true; + // 处理表单数据,确保对象类型正确解析 - const processedData = {}; + const formValues = this.formData; - // 复制表单数据 - for (const key in this.formData[item.id]) { - const value = this.formData[item.id][key]; + for (var i = 0; i < this.currentInputs.length; i++) { + var input = this.currentInputs[i]; + if (this.selectedRowKeys.some(item => item.id === input.id)) { - // 查找对应的输入定义 - const inputDef = item.inputs.find(input => input.id === key); + var value = formValues[input.id]; + var formType = input.valueParams.formType; - // 如果是对象类型且值是字符串,尝试解析为对象 - if (inputDef && inputDef.valueType.type === 'object' && typeof value === 'string') { - try { - processedData[key] = JSON.parse(value); - } catch (error) { - processedData[key] = {}; - console.error('解析对象失败:', error); + // 根据不同的表单类型判断是否为空值 + var isEmpty = false; + + if (formType === 'switch') { + // if 分支:switch 类型 + isEmpty = value === undefined || value === null; + } else { + // else 分支:其他类型 + isEmpty = value === undefined || + value === null || + value === '' || + (typeof value === 'string' && value.trim() === ''); + } + + if (isEmpty) { + this.$message.error('请填写参数:' + input.name); + this.loading = false; // 重置loading状态 + shouldReturn = true; // 设置标志 + return; } - } else { - processedData[key] = value; } } - let params = { - input: processedData, - deviceKey: this.deviceInfo.deviceKey, - funcId:item.id - }; - setFunctionControl(params).then(response => { - console.log("下发事件", response); - this.loading = false; - if (response?.code == 200) { - this.msgSuccess("添加成功"); - // 添加执行结果 - const result = { - time: new Date().toLocaleString(), - functionName: item.name, - success: Math.random() > 0.2, // 模拟成功/失败 - data: JSON.stringify(processedData, null, 2) - }; - this.executionResults.unshift(result); - // 控制结果列表最大数量 - if (this.executionResults.length > 20) { - this.executionResults.pop(); - } - // 滚动到顶部 - this.$nextTick(() => { - if (this.$refs.resultContent) { - this.$refs.resultContent.scrollTop = 0; + + this.selectedRowKeys.forEach(({ key }) => { + const value = formValues[key]; + // 对于开关类型,false 也是有效值,不应该被过滤掉 + const input = this.currentInputs.find((item) => item.id === key); + const isSwitch = input?.valueParams?.formType === 'switch'; + + if ( + (value !== undefined && value !== null) || + (isSwitch && value === false) + ) { + if (input) { + const { dataType, formType, format } = input.valueParams; + let processedValue = value; + + // 根据dataType和formType处理数据类型转换 + if (formType === 'switch') { + if (dataType === 'boolean') { + // boolean类型的开关,提交布尔值 + processedValue = Boolean(value); + } else if (dataType === 'string') { + // string类型的开关,提交字符串值 + processedValue = value; + } + } else if (formType === 'time' && dataType === 'date') { + // date类型的时间选择器,提交时间戳 + if (value && typeof value === 'object' && value.valueOf) { + processedValue = value.valueOf(); // 转换为时间戳 + console.log( + `时间字段 ${key} (date): ${value} -> ${processedValue}`, + ); + } else if (value && typeof value === 'string') { + let timeValue = value; + if (format === 'YYYY-MM-DD') { + timeValue += ' 00:00:00'; + } + processedValue = new Date(timeValue).getTime(); // 字符串转时间戳 + } } - }); - } else { - this.$message.error("功能执行失败"); + + parameters[key] = processedValue; + } else { + parameters[key] = value; + } } }); } }); - }else{ + } else { this.loading = true; - // 模拟API调用 - setTimeout(() => { - this.loading = false; - - // 添加执行结果 - const result = { - time: new Date().toLocaleString(), - functionName: item.name, - success: Math.random() > 0.2, // 模拟成功/失败 - data: this.monacoValue - }; - - this.executionResults.unshift(result); - - // 控制结果列表最大数量 - if (this.executionResults.length > 20) { - this.executionResults.pop(); - } - - // 显示执行结果提示 - if (result.success) { - this.$message.success("功能执行成功"); - } else { - this.$message.error("功能执行失败"); - } - - // 滚动到顶部 - this.$nextTick(() => { - if (this.$refs.resultContent) { - this.$refs.resultContent.scrollTop = 0; - } - }); - }, 1000); + // 高级模式:验证JSON格式 + try { + parameters = JSON.parse(this.monacoValue); + } catch { + this.$message.error('JSON格式错误,请检查格式'); + return; + } } + if (shouldReturn) return; + + // 检查是否需要预检查 + if (this.checkPreCheck()) { + return; // 显示预检查弹窗,等待用户输入 + } + this.submitFunctionParameters = parameters; + this.submitFunction(null); + }, + submitFunction(checkValue){ + const submitData = { + productKey: this.deviceInfo.prodKey, + deviceKey: this.deviceInfo.deviceKey, + funcId: this.currentFunction.id, + params: this.submitFunctionParameters, + }; + // 如果有预检查值,添加到提交数据中 + if (checkValue) { + submitData.checkValue = checkValue; + } + // 添加执行结果 + const result = { + time: new Date().toLocaleString(), + functionName: this.currentFunction.name, + success: Math.random() > 0.2, // 模拟成功/失败 + data: JSON.stringify(submitData, null, 2) + }; + this.executionResults.unshift(result); + + // 控制结果列表最大数量 + if (this.executionResults.length > 20) { + this.executionResults.pop(); + } + // 滚动到顶部 + this.$nextTick(() => { + if (this.$refs.resultContent) { + this.$refs.resultContent.scrollTop = 0; + } + }); + setFunctionControl(submitData).then(response => { + this.loading = false; + if (response.code == 200) { + this.msgSuccess("添加成功"); + } else { + this.$message.error("功能执行失败"); + } + }); }, // 重置表单 @@ -629,31 +715,12 @@ export default { // 更新高级模式编辑器的内容 updateAdvancedModeCode() { - if (this.currentFunction && this.formData[this.currentFunction.id]) { - // 处理表单数据,确保对象类型正确解析 - const processedData = {}; - - // 复制表单数据 - for (const key in this.formData[this.currentFunction.id]) { - const value = this.formData[this.currentFunction.id][key]; - - // 查找对应的输入定义 - const inputDef = this.currentFunction.inputs.find(input => input.id === key); - - // 如果是对象类型且值是字符串,尝试解析为对象 - if (inputDef && inputDef.valueType.type === 'object' && typeof value === 'string') { - try { - processedData[key] = JSON.parse(value); - } catch (error) { - processedData[key] = {}; - console.error('解析对象失败:', error); - } - } else { - processedData[key] = value; - } - } - this.monacoValue = JSON.stringify(processedData, null, 2); - } + const params = {}; + this.currentInputs.forEach((item) => { + params[item.id] = null; + }); + this.monacoValue = JSON.stringify(params, null, 2); + // } }, // 显示数组输入框 @@ -739,8 +806,8 @@ export default { getCard(params) .then(response => { console.log("获取卡号列表", response); - if (response?.code == 200) { - let data = response?.data || []; + if (response.code == 200) { + let data = response.data || []; this.tableData = data.map(item => { return { cardNumber: item @@ -797,7 +864,7 @@ export default { }; addCard(params).then(response => { console.log("添加卡号", response); - if (response?.code == 200) { + if (response.code == 200) { this.msgSuccess("添加成功"); this.getCardNumberList(); } @@ -810,11 +877,146 @@ export default { deviceId: this.deviceInfo.deviceId }; delCard(params).then(response => { - if (response?.code == 200) { + if (response.code == 200) { this.msgSuccess("删除成功"); this.getCardNumberList(); } }); + }, + // 校验弹窗相关 + checkPreCheck(){ + const currentFunc = this.currentFunction; + if (currentFunc?.expands?.preCheck) { + this.preCheckType = currentFunc.expands.checkType || 'userPassword'; + this.preCheckForm = { + password: '', + phone: '', + smsCode: '', + }; + this.preCheckVisible = true; + return true; + } + return false; + }, + getPreCheckTitle() { + switch (this.preCheckType) { + case 'userPassword': + return '用户密码验证' + case 'staticPassword': + return '固定密码验证' + case 'userSms': + return '短信验证' + default: + return '安全验证' + } + }, + + handlePreCheckConfirm() { + this.$refs.preCheckFormRef.validate((valid) => { + if (valid) { + // 验证通过,执行确认逻辑 + this.submitPreCheck() + } else { + return false + } + }) + }, + + handlePreCheckCancel() { + this.preCheckVisible = false + this.resetPreCheckForm() + }, + + getSmsCode() { + // 验证手机号格式 + if (!/^1[3-9]\d{9}$/.test(this.preCheckForm.phone)) { + this.$message.error('请输入正确的手机号') + return + } + + this.smsCodeLoading = true + // 调用获取验证码接口 + // yourApi.getSmsCode({ phone: this.preCheckForm.phone }).then(() => { + // this.$message.success('验证码发送成功') + // this.startSmsCountdown() + // }).catch(() => { + // this.$message.error('验证码发送失败') + // }).finally(() => { + // this.smsCodeLoading = false + // }) + + // 模拟请求 + setTimeout(() => { + this.smsCodeLoading = false + this.$message.success('验证码发送成功') + this.startSmsCountdown() + }, 1000) + }, + + startSmsCountdown() { + this.smsCountdown = 60 + const timer = setInterval(() => { + this.smsCountdown-- + if (this.smsCountdown <= 0) { + clearInterval(timer) + } + }, 1000) + }, + + resetPreCheckForm() { + this.preCheckForm = { + password: '', + phone: '', + smsCode: '' + } + // 清除表单验证 + this.$nextTick(() => { + if (this.$refs.preCheckFormRef) { + this.$refs.preCheckFormRef.clearValidate() + } + }) + }, + + async submitPreCheck() { + let checkValue = ''; + // 根据预检查类型构造checkValue + switch (this.preCheckType) { + case 'staticPassword': { + const hashResult = MD5(this.preCheckForm.password).toString(); // 得到 MD5 哈希值 + checkValue = hashResult; + break; + } + case 'userPassword': { + checkValue = this.preCheckForm.password; + break; + } + case 'userSms': { + checkValue = this.preCheckForm.smsCode; + break; + } + } + + // 关闭预检查弹窗 + this.preCheckVisible = false; + + console.log('提交预检查数据:', checkValue) + // 执行实际提交 + await this.submitFunction(checkValue); + // 调用API进行验证 + // yourApi.submitPreCheck(params).then(() => { + // this.$message.success('验证成功') + // this.preCheckVisible = false + // this.resetPreCheckForm() + // }).catch(() => { + // this.$message.error('验证失败') + // }) + }, + + // 打开弹窗的方法 + openPreCheck(type) { + this.preCheckType = type + this.preCheckVisible = true + this.resetPreCheckForm() } } }; @@ -829,6 +1031,7 @@ export default { justify-content: space-between; border-bottom: 1px solid #dedddd; padding: 10px 2px; + &:last-child { border-bottom: none; } @@ -838,8 +1041,10 @@ export default { .model-function-list { .function-container { display: flex; + .function-tabs { width: 130px; + /* 调整标签栏样式 */ ::v-deep .is-left.el-tabs__header { width: 130px; @@ -851,20 +1056,35 @@ export default { padding: 0 20px; } } + .function-params { flex: 5; padding: 0 20px; + .params-header { text-align: left; margin-bottom: 10px; } - ::v-deep .el-form-item{ + + ::v-deep .el-form-item { margin-bottom: 0; } - .btn-box{ + + ::v-deep .e-switch-c.el-switch .el-switch__core, + ::v-deep .el-switch .el-switch__label { + min-width: 20px !important; + text-align: center; + } + + ::v-deep .el-form-item__content { + text-align: right; + } + + .btn-box { margin-top: 10px; text-align: right; } + .advanced-mode { height: 100%; @@ -881,29 +1101,35 @@ export default { } } } + .function-result { flex: 3; padding: 0 20px; - .result-header{ + + .result-header { font-size: 13px; padding-bottom: 5px; } - .result-content{ + + .result-content { height: calc(100% - 30px); max-height: 50vh; overflow-y: auto; border: 1px solid #999; border-radius: 5px; padding: 10px; - .result-item{ + + .result-item { margin-bottom: 10px; - .result-time{ + + .result-time { text-align: right; } } } } } + .function-header { display: flex; justify-content: space-between; @@ -954,17 +1180,20 @@ export default { } .eldaialog-wrap { - .el-dialog__header { - } + .el-dialog__header {} + .el-radio { width: 90px; } + .el-dialog__body { padding: 0px; } + .cus-itme.el-form-item--mini .el-form-item__content { margin-left: 0px !important; } + .select { // width: 92%; display: inline-block; @@ -972,20 +1201,24 @@ export default { display: inline-block; float: left; margin-right: 4px; + .el-input { width: 100%; } } + .el-textarea { width: 92%; width: calc(92% - 50px); width: 100%; } + .el-input { width: 92%; width: calc(92% - 50px); width: 100%; } + .info { width: 100%; float: left; @@ -995,6 +1228,7 @@ export default { font-size: 16px; font-weight: 600; } + .span { width: calc(100% - 91px); display: block; @@ -1008,6 +1242,7 @@ export default { margin-left: 80px; margin-top: -10px; } + .form-buttons-div { height: 45px; display: flex; @@ -1022,10 +1257,13 @@ export default { .el-dialog__header { border-bottom: 1px solid #ccc; } + .el-dialog__body { padding: 28px; + .el-form-item { margin-bottom: 0; + .el-form-item__label { line-height: 30px; } @@ -1033,4 +1271,10 @@ export default { } } } +::v-deep .pre-check-dialog .el-dialog__body{ + padding: 10px 20px 0 20px; +} +::v-deep .pre-check-dialog .el-dialog__footer{ + padding: 10px 20px; +} diff --git a/src/views/profile/DeviceRunStarts/index.vue b/src/views/profile/DeviceRunStarts/index.vue index 00a6bbda..e76e47e6 100644 --- a/src/views/profile/DeviceRunStarts/index.vue +++ b/src/views/profile/DeviceRunStarts/index.vue @@ -2,91 +2,38 @@
- - - - 分组名称: - - + +
-
+
暂无数据
-
+
- {{ item.funName }} + {{ item.name }} 查看
- - - - - + + {{ formatValue(item) }}
- {{ item.unitName }} - + {{ item.valueParams.unit || '' }} + {{ item.timestamp }}
-
- - - - + + @@ -127,16 +74,59 @@ export default { properties: [], events: [] }, - activeCmd: "" + runtimeProperties: [], + selectedGroup: "all", + metadata:{ + properties: [], + propertyGroups: [] + } }; }, + computed: { + groupOptions() { + + const groups = this.metadata?.propertyGroups || []; + return [ + { label: '全部', value: 'all' }, + ...groups.map((group) => ({ label: group.name, value: group.id })), + ]; + }, + filteredProperties() { + let properties = [...this.runtimeProperties]; + + if (this.selectedGroup !== 'all') { + const group = (this.metadata?.propertyGroups || []).find( + (g) => g.id === this.selectedGroup, + ); + if (group?.properties) { + const ids = new Set(group.properties.map((p) => p.id)); + properties = properties.filter((p) => ids.has(p.id)); + } + } + + // properties = properties.filter((p) => { + // const type = p.expands?.type || 'R'; + // return selectedTypes.value.includes(type); + // }); + + return properties; + } + }, created() { + this.getMetaDate(); this.getProdObj(); - this.getCmdList(); + // this.getCmdList(); // this.connection(); }, methods: { + getMetaDate(){ + try { + this.metadata = JSON.parse(this.deviceInfo.metadata); + } catch (error) { + console.log(error); + } + }, changeCmd(e) { if (e != "") { const filterObj = @@ -150,42 +140,57 @@ export default { }); } }, - getProdObj() { - let prodJson = { - properties: [], - events: [] - }; - try { - prodJson = JSON.parse(this.deviceInfo.prodJson); - } catch (error) { - console.log(error); + formatValue(property) { + const { value, valueParams } = property; + if (value === undefined || value === null) return '--'; + + let displayValue = value; + + if (valueParams?.formType === 'input' && valueParams?.length) { + displayValue = value.slice(0, valueParams.length); } - if (prodJson.properties) { - let list = prodJson.properties.filter(item => item.show === true) || []; - let properties = list.map(item => { - if (item.dataFormat) { - let dataFormat = item.dataFormat; - item.dataFormatType = dataFormat.type; - if (dataFormat.list && dataFormat.type === "ENUM") { - try { - item.dataFormatObj = JSON.parse( - dataFormat.list.replace(/\\/g, "") - ); - } catch (e) { - item.dataFormatObj = {}; - } - } - } - return item; - }); - this.prodObj.properties = properties; + + if (valueParams?.formType === 'switch') { + return value.toString() === valueParams.trueValue + ? valueParams.trueText + : valueParams.falseText; + } + + if (valueParams?.formType === 'select') { + return valueParams.enumConf.find((item) => item.value === value)?.text; + } + + if (valueParams?.formType === 'time' && valueParams?.dataType !== 'string') { + return moment(value).format(valueParams.format); + } + + if ( + valueParams?.formType === 'number' || + valueParams?.formType === 'progress' + ) { + if (valueParams?.scale) return value.toFixed(valueParams.scale); + return value; + } + + return displayValue; + }, + getProdObj() { + if (this.metadata.properties) { + let list = this.metadata.properties.filter((item) => item.show === true) || []; + let properties = list.map(item => ({ + ...item, + value: null, + timestamp: moment().format('YYYY-MM-DD HH:mm:ss') + })); + this.runtimeProperties = properties; this.$nextTick(() => { - this.$set(this.filterProdObj, "properties", properties); + this.$set(this, "runtimeProperties", properties); + }); } else { - this.prodObj.properties = []; + this.runtimeProperties = []; } - this.prodObj.events = prodJson.events || []; + this.connection(); }, formatTime(date) { // 检查时间戳长度 @@ -242,32 +247,58 @@ export default { this.$forceUpdate(); }, recursionSet(list, result) { - if (result.type === "properties") { - if (result.tags.device_key === this.deviceInfo.deviceKey) { - this.prodObj.properties = this.prodObj.properties.map(item => ({ - ...item, - ...(item.funKey in result.properties && { - lastValue: result.properties[item.funKey], - lastTime: result.properties.timestamp - }) - })); - this.filterProdObj.properties = this.filterProdObj.properties.map( - item => ({ - ...item, - ...(item.funKey in result.properties && { - lastValue: result.properties[item.funKey], - lastTime: result.properties.timestamp - }) - }) - ); - } - } - if(result.type === "state"){ - this.$emit("updateDeviceState",{ - deviceKey: this.deviceInfo.deviceKey, - state: result.state + if (result.type === "result" && result.topic.endsWith('/report') && result.payload) { + // 更函数式的写法,避免直接修改 + this.runtimeProperties = this.runtimeProperties.map(property => { + const propValue = result.payload.value[property.id]; + if (propValue !== undefined) { + return { + ...property, + value: propValue, + timestamp: moment(result.payload.timeString).format('YYYY-MM-DD HH:mm:ss') + }; + } + return property; }); + // 更新实时属性数据 + // Object.entries(result.payload).forEach(([propId, propValue]) => { + // const property = this.runtimeProperties.find( + // (p) => p.id === propId, + // ); + // if (property) { + // property.value = propValue; + // property.timestamp = moment(data.payload.timeString).format( + // 'YYYY-MM-DD HH:mm:ss', + // ); + // } + // }); } + // if (result.type === "properties") { + // if (result.tags.device_key === this.deviceInfo.deviceKey) { + // this.prodObj.properties = this.prodObj.properties.map(item => ({ + // ...item, + // ...(item.funKey in result.properties && { + // lastValue: result.properties[item.funKey], + // lastTime: result.properties.timestamp + // }) + // })); + // this.filterProdObj.properties = this.filterProdObj.properties.map( + // item => ({ + // ...item, + // ...(item.funKey in result.properties && { + // lastValue: result.properties[item.funKey], + // lastTime: result.properties.timestamp + // }) + // }) + // ); + // } + // } + // if (result.type === "state") { + // this.$emit("updateDeviceState", { + // deviceKey: this.deviceInfo.deviceKey, + // state: result.state + // }); + // } // for (var i = 0; i < list.length; i++) { @@ -309,7 +340,7 @@ export default { if (this.socket_flag) { this.socket_flag = false; let self = this; - setTimeout(function() { + setTimeout(function () { self.socket_flag = true; self.connection(); }, 10000); @@ -375,7 +406,7 @@ export default { ]; } this.connection(); - }).catch(error=>{ + }).catch(error => { this.connection(); }); }, @@ -415,7 +446,7 @@ export default { // } // }, realTimeData: { - handler: function() { + handler: function () { this.setListData(this.realTimeData); }, deep: true @@ -429,11 +460,13 @@ export default { display: flex; flex-wrap: wrap; overflow: auto; + //padding: 10px; .el-button--medium { position: absolute; right: 30px; } + .cmd-list { width: 100%; /* height: auto; */ @@ -441,9 +474,11 @@ export default { flex-wrap: wrap; cursor: default; padding: 10px; + &:first-child { padding-top: 0; } + .cmd-title-wrap { width: 100%; display: flex; @@ -451,6 +486,7 @@ export default { font-size: 16px; align-items: center; margin-bottom: 20px; + .cmd-title { font-size: 14px; color: #a9a6a6; @@ -459,6 +495,7 @@ export default { letter-spacing: 1px; } } + .param-item { height: 130px; // border: 1px solid #777474; @@ -475,6 +512,7 @@ export default { margin-left: 15px; margin-top: 15px; box-shadow: 0px 0px 3px 0px #b7b4b4; + .title-top { height: 30px; display: flex; @@ -483,23 +521,27 @@ export default { border-bottom: 1px dotted #c5c3c3; padding-bottom: 3px; justify-content: space-between; + .name-wr { font-size: 18px; color: #1890ff; } + .type-wr { font-size: 14px; color: #1890ff; } } + .value-info { height: 55px; display: flex; margin-top: 5px; align-items: center; width: 100%; - .value-wrap { - } + + .value-wrap {} + .val-span { color: #03a9f4; font-size: 20px; @@ -520,6 +562,7 @@ export default { color: #908c8c; } } + .param-item2 { height: 150px; width: 300px; @@ -534,6 +577,7 @@ export default { margin-left: -1px; margin-top: -1px; border-color: #e0e0e0; + .title-top { height: 30px; display: flex; @@ -542,28 +586,33 @@ export default { border-bottom: 1px dotted #c5c3c3; padding-bottom: 3px; justify-content: space-between; + .name-wr { font-size: 18px; // color: #1890ff; } + .type-wr { font-size: 14px; // color: #606266; color: #1890ff; } + .type-wr:hover { color: #1890ff; cursor: pointer; } } + .value-info { height: 55px; display: flex; margin-top: 5px; align-items: center; width: 100%; - .value-wrap { - } + + .value-wrap {} + .val-span { color: #03a9f4; font-size: 20px; @@ -586,10 +635,12 @@ export default { } } } + .device-run-state-dailog { .el-dialog__header { border-bottom: 1px solid #b6b6b6; } + .el-dialog__footer { border-top: 1px solid #b6b6b6; padding-bottom: 10px;