feat(iot): 新增产品物模型查看功能

- 在模型和模型系列页面添加物模型按钮和对话框
- 调整对接系列和型号代码
- 优化属性和函数的展示方式
- 添加 JSON 查看器组件vue-json-viewer用于展示物模型数据
This commit is contained in:
fhysy 2025-05-19 14:45:11 +08:00
parent 868fd9b46f
commit bae4c40a65
9 changed files with 202 additions and 111 deletions

View File

@ -78,6 +78,7 @@
"vue-count-to": "1.0.13", "vue-count-to": "1.0.13",
"vue-cron-editor-buefy": "^0.2.17", "vue-cron-editor-buefy": "^0.2.17",
"vue-cropper": "0.5.5", "vue-cropper": "0.5.5",
"vue-json-viewer": "^2.2.22",
"vue-router": "3.4.9", "vue-router": "3.4.9",
"vue-seamless-scroll": "^1.1.23", "vue-seamless-scroll": "^1.1.23",
"vuedraggable": "2.24.3", "vuedraggable": "2.24.3",

View File

@ -92,7 +92,7 @@ const attribute = {
InitAttributeAndGroup({ commit, state }, data) { InitAttributeAndGroup({ commit, state }, data) {
commit('SET_ATTRIBUTE_LIST', data.attrList) commit('SET_ATTRIBUTE_LIST', data.attrList)
commit('SET_GROUP_LIST', data.groupList) commit('SET_GROUP_LIST', data.groupList)
commit('SET_FUNCTIon_LIST', data.functionList) commit('SET_FUNCTION_LIST', data.functionList)
console.log('res:', state, data) console.log('res:', state, data)
}, },
// 新增 属性 // 新增 属性

View File

@ -258,7 +258,8 @@
position: relative; position: relative;
top: -10px;" top: -10px;"
> >
<el-button icon="el-icon-menu" style="width: 200px; height: 40px;" type="primary" @click="openTableSelectScriesDialog">选择型号系列</el-button> <el-button icon="el-icon-s-platform" style="height: 40px;" type="primary" @click="openModelDialog">物模型</el-button>
<el-button icon="el-icon-menu" style="height: 40px;" type="primary" @click="openTableSelectScriesDialog">选择型号系列</el-button>
</el-col> </el-col>
<el-col :span="24"> <el-col :span="24">
@ -394,6 +395,24 @@
> >
</div> </div>
</dialog-template> </dialog-template>
<el-dialog
:visible.sync="modelOpen"
class="params-eldialog"
title="物模型"
top="5vh"
width="800px"
>
<params-json-wrap
v-if="modelOpen === true"
:other="{
action: '',
prodPK: this.form.prodKey,
cmdKey: '',
}"
:paramsList="modelValue"
></params-json-wrap>
</el-dialog>
</div> </div>
</template> </template>
@ -420,6 +439,7 @@ import attributeForm from "@/views/profile/attribute/attributeForm";
import groupForm from "@/views/profile/attribute/groupForm"; import groupForm from "@/views/profile/attribute/groupForm";
import paramsJson from "@/views/profile/attribute/paramsJson"; import paramsJson from "@/views/profile/attribute/paramsJson";
import { listModelSeries, getModelSeries } from "@/api/iot/modelSeries"; import { listModelSeries, getModelSeries } from "@/api/iot/modelSeries";
import ParamsJsonWrap from "@/views/profile/attribute/paramsJson";
const deviceStartsOpt = { const deviceStartsOpt = {
0: "禁用", 0: "禁用",
@ -436,9 +456,12 @@ export default {
attributeForm, attributeForm,
groupForm, groupForm,
paramsJson, paramsJson,
ParamsJsonWrap
}, },
data() { data() {
return { return {
modelOpen: false,
modelValue: "",
componectVal: "attributeForm", componectVal: "attributeForm",
childOpt: { childOpt: {
type: "add", type: "add",
@ -618,6 +641,15 @@ export default {
}; };
this.selectTableShow = true; this.selectTableShow = true;
}, },
openModelDialog() {
this.modelOpen=true;
this.modelValue = JSON.parse(
JSON.stringify({
properties:this.$store.getters.attributeList,
functions:this.$store.getters.functionList,
})
);
},
openTableSelectScriesDialog() { openTableSelectScriesDialog() {
this.selectResult = {}; this.selectResult = {};
this.tableSelectOption = { this.tableSelectOption = {
@ -914,6 +946,7 @@ export default {
}, },
// //
resuleClick() { resuleClick() {
debugger
switch(this.selectResult.tableType) { switch(this.selectResult.tableType) {
case 'vendor': case 'vendor':
this.form.vendorId = this.selectResult.vendorId; this.form.vendorId = this.selectResult.vendorId;
@ -936,6 +969,7 @@ export default {
_this.$refs.attributeref.handleInitData(); _this.$refs.attributeref.handleInitData();
_this.$refs.attributeref.forceUpdateList('groupForm'); _this.$refs.attributeref.forceUpdateList('groupForm');
_this.$refs.attributeref.forceUpdateList('attributeForm'); _this.$refs.attributeref.forceUpdateList('attributeForm');
_this.$refs.attributeref.forceUpdateList('functionForm');
}, 100); }, 100);
break; break;

View File

@ -178,11 +178,21 @@
<el-form-item label="产品PK" prop="prodKey"> <el-form-item label="产品PK" prop="prodKey">
<el-input <el-input
v-model="form.prodKey" v-model="form.prodKey"
:disabled="form.seriesId || form.seriesId === 0" :disabled="form.seriesId !== undefined && form.seriesId !== null && form.seriesId !== ''"
placeholder="请填写产品PK" placeholder="请填写产品PK"
></el-input> ></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24" style="
display: flex;
justify-content: flex-end;
height: 0;
z-index: 99;
position: relative;
top: -10px;"
>
<el-button icon="el-icon-s-platform" style="height: 40px;" type="primary" @click="openModelDialog">物模型</el-button>
</el-col>
<el-col :span="24"> <el-col :span="24">
<el-form-item <el-form-item
@ -284,6 +294,23 @@
> >
</div> </div>
</dialog-template> </dialog-template>
<el-dialog
:visible.sync="modelOpen"
class="params-eldialog"
title="物模型"
top="5vh"
width="800px"
>
<params-json-wrap
v-if="modelOpen === true"
:other="{
action: '',
prodPK: this.form.prodKey,
cmdKey: '',
}"
:paramsList="modelValue"
></params-json-wrap>
</el-dialog>
</div> </div>
</template> </template>
@ -297,6 +324,7 @@ import groupForm from "@/views/profile/attribute/groupForm";
import paramsJson from "@/views/profile/attribute/paramsJson"; import paramsJson from "@/views/profile/attribute/paramsJson";
import ParamWrap from "@/components/ParamWrap/deviceParam"; import ParamWrap from "@/components/ParamWrap/deviceParam";
import AttributeView from "@/views/profile/attribute/index"; import AttributeView from "@/views/profile/attribute/index";
import ParamsJsonWrap from "@/views/profile/attribute/paramsJson";
export default { export default {
name: "ModelSeries", name: "ModelSeries",
@ -307,9 +335,12 @@ export default {
paramsJson, paramsJson,
AttributeView, AttributeView,
ParamWrap, ParamWrap,
ParamsJsonWrap
}, },
data() { data() {
return { return {
modelOpen: false,
modelValue: "",
// //
loading: true, loading: true,
// //
@ -380,6 +411,15 @@ export default {
this.getList(); this.getList();
}, },
methods: { methods: {
openModelDialog() {
this.modelOpen=true;
this.modelValue = JSON.parse(
JSON.stringify({
properties:this.$store.getters.attributeList,
functions:this.$store.getters.functionList,
})
);
},
indexFormatter(val) { indexFormatter(val) {
return ( return (
val + 1 + (this.queryParams.pageNum - 1) * this.queryParams.pageSize val + 1 + (this.queryParams.pageNum - 1) * this.queryParams.pageSize
@ -392,7 +432,10 @@ export default {
(this.childOpt.paramIdx = data.paramIdx); (this.childOpt.paramIdx = data.paramIdx);
this.AttributeViewShow = true; this.AttributeViewShow = true;
this.functionList = JSON.parse( this.functionList = JSON.parse(
JSON.stringify(this.$store.getters.attributeList) JSON.stringify({
properties:this.$store.getters.attributeList,
functions:this.$store.getters.groupList,
})
); );
this.componectVal = data.component; this.componectVal = data.component;
}, },

View File

@ -32,8 +32,8 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="分组:" prop="cmdKey"> <el-form-item label="参数分组:" prop="cmdKey">
<el-select v-model="form.cmdKey" placeholder="请选分组"> <el-select v-model="form.cmdKey" placeholder="请选参数分组">
<el-option <el-option
v-for="(item, idx) in groupList" v-for="(item, idx) in groupList"
:key="idx" :key="idx"
@ -240,10 +240,13 @@ export default {
funValidTypeOption, funValidTypeOption,
dataFormatTypeOption, dataFormatTypeOption,
form: { form: {
show: true, funDataType: 'INT32',
funRwType: 'READWRITE',
sort: 100, sort: 100,
show: true,
funValidType:'NOT',
dataFormat: { dataFormat: {
type: null, type: 'null',
list: "" list: ""
} }
}, },
@ -252,7 +255,7 @@ export default {
funName: [ funName: [
{ required: true, message: "参数名称不能为空", trigger: "blur" }, { required: true, message: "参数名称不能为空", trigger: "blur" },
], ],
cmdKey: [{ required: true, message: "分组不能为空", trigger: "blur" }], // cmdKey: [{ required: true, message: "", trigger: "blur" }],
funKey: [ funKey: [
{ required: true, message: "标识符不能为空", trigger: "blur" }, { required: true, message: "标识符不能为空", trigger: "blur" },
], ],

View File

@ -6,15 +6,15 @@
>新增</el-button >新增</el-button
> >
</el-col> </el-col>
<el-col :span="1.5"> <!-- <el-col :span="1.5">-->
<el-button <!-- <el-button-->
icon="el-icon-s-platform" <!-- icon="el-icon-s-platform"-->
size="mini" <!-- size="mini"-->
type="primary" <!-- type="primary"-->
@click="handleParams" <!-- @click="handleParams"-->
>物模型参数</el-button <!-- >物模型</el-button-->
> <!-- >-->
</el-col> <!-- </el-col>-->
</el-row> </el-row>
<el-table v-loading="loading" :data="functionList" height="300px"> <el-table v-loading="loading" :data="functionList" height="300px">
@ -221,23 +221,23 @@
</div> </div>
</el-dialog> </el-dialog>
<el-dialog <!-- <el-dialog-->
:visible.sync="paramsOpen" <!-- :visible.sync="paramsOpen"-->
class="params-eldialog" <!-- class="params-eldialog"-->
title="物模型参数" <!-- title="物模型"-->
top="5vh" <!-- top="5vh"-->
width="800px" <!-- width="800px"-->
> <!-- >-->
<params-json-wrap <!-- <params-json-wrap-->
v-if="paramsOpen === true" <!-- v-if="paramsOpen === true"-->
:other="{ <!-- :other="{-->
action: '', <!-- action: '',-->
prodPK: sourceId, <!-- prodPK: sourceId,-->
cmdKey: '', <!-- cmdKey: '',-->
}" <!-- }"-->
:paramsList="functionList" <!-- :paramsList="functionList"-->
></params-json-wrap> <!-- ></params-json-wrap>-->
</el-dialog> <!-- </el-dialog>-->
</div> </div>
</template> </template>
@ -352,11 +352,12 @@ export default {
console.log('666', res) console.log('666', res)
this.functionList = res this.functionList = res
this.$forceUpdate() this.$forceUpdate()
this.loading = false this.loading = false
}); });
}, 50) }, 50)
}, },
setList(list) { setList(list) {
debugger
this.loading = true this.loading = true
this.functionList = [] this.functionList = []
setTimeout(() => { setTimeout(() => {

View File

@ -124,22 +124,22 @@
<template slot-scope="scope"> <template slot-scope="scope">
<el-input <el-input
v-model="scope.row.value" v-model="scope.row.value"
:class="{ 'is-error': scope.row.valueError }" :class="{ 'is-error': scope.row.value }"
placeholder="请输入值" placeholder="请输入值"
@blur="validateEnumItem(scope.row, 'value', scope.$index)" @blur="validateEnumItem(scope.row, 'value', scope.$index)"
></el-input> ></el-input>
<div v-if="scope.row.valueError" class="el-form-item__error">值不能为空</div> <div v-if="scope.row.value" class="el-form-item__error">值不能为空</div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="描述" prop="text"> <el-table-column label="描述" prop="text">
<template slot-scope="scope"> <template slot-scope="scope">
<el-input <el-input
v-model="scope.row.text" v-model="scope.row.text"
:class="{ 'is-error': scope.row.textError }" :class="{ 'is-error': scope.row.text }"
placeholder="请输入描述" placeholder="请输入描述"
@blur="validateEnumItem(scope.row, 'text', scope.$index)" @blur="validateEnumItem(scope.row, 'text', scope.$index)"
></el-input> ></el-input>
<div v-if="scope.row.textError" class="el-form-item__error">描述不能为空</div> <div v-if="scope.row.text" class="el-form-item__error">描述不能为空</div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" label="操作" width="80"> <el-table-column align="center" label="操作" width="80">
@ -433,18 +433,18 @@ export default {
// //
const newEnumItem = JSON.parse(JSON.stringify(defaultenumForm)); const newEnumItem = JSON.parse(JSON.stringify(defaultenumForm));
newEnumItem.valueError = false; newEnumItem.value = false;
newEnumItem.textError = false; newEnumItem.text = false;
this.inputFormObj.form.valueType.elements.push(newEnumItem); this.inputFormObj.form.valueType.elements.push(newEnumItem);
}, },
validateEnumItem(item, field, index) { validateEnumItem(item, field, index) {
if (field === 'value') { if (field === 'value') {
item.valueError = !item.value; item.value = !item.value;
} else if (field === 'text') { } else if (field === 'text') {
item.textError = !item.text; item.text = !item.text;
} }
return !item.valueError && !item.textError; return !item.value && !item.text;
}, },
// //
@ -465,9 +465,9 @@ export default {
let hasError = false; let hasError = false;
for (let i = 0; i < this.inputFormObj.form.valueType.elements.length; i++) { for (let i = 0; i < this.inputFormObj.form.valueType.elements.length; i++) {
const item = this.inputFormObj.form.valueType.elements[i]; const item = this.inputFormObj.form.valueType.elements[i];
item.valueError = !item.value; item.value = !item.value;
item.textError = !item.text; item.text = !item.text;
if (item.valueError || item.textError) { if (item.value || item.text) {
hasError = true; hasError = true;
} }
} }

View File

@ -11,7 +11,7 @@
/> />
</div> </div>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="分组" name="group"> <el-tab-pane label="参数分组" name="group">
<div class="tabs-body"> <div class="tabs-body">
<group-view <group-view
v-if="activeName === 'group'" v-if="activeName === 'group'"
@ -96,7 +96,7 @@ export default {
case "param": case "param":
this.$emit("handleEvent", { this.$emit("handleEvent", {
type: data.type, type: data.type,
title: "物模型参数", title: "物模型",
component: "paramsJson", component: "paramsJson",
paramIdx: null, paramIdx: null,
}); });
@ -158,7 +158,7 @@ export default {
case "param": case "param":
this.$emit("handleEvent", { this.$emit("handleEvent", {
type: data.type, type: data.type,
title: "物模型参数", title: "物模型",
component: "paramsJson", component: "paramsJson",
paramIdx: null, paramIdx: null,
}); });
@ -190,7 +190,9 @@ export default {
if (component === "groupForm") { if (component === "groupForm") {
this.$refs.groupref && this.$refs.groupref.setList(groupList); this.$refs.groupref && this.$refs.groupref.setList(groupList);
} else if (component === "attributeForm") { } else if (component === "attributeForm") {
this.$refs.attributeref && this.$refs.attributeref.setList(arttributeList); this.$refs.attributeref && this.$refs.attributeref.setList(arttributeList.properties);
} else if (component === "functionForm") {
this.$refs.functionref && this.$refs.functionref.setList(arttributeList.functions);
} }
}, },
handleInitData() { handleInitData() {
@ -205,7 +207,7 @@ export default {
functionList = json.functions; functionList = json.functions;
}else{ }else{
arttributeList = json; arttributeList = json;
arttributeList = []; functionList = json.functions;
} }
} catch (error) { } catch (error) {
arttributeList = []; arttributeList = [];

View File

@ -1,62 +1,69 @@
<template> <template>
<div class="prod-params-json"> <div class="prod-params-json">
<div class="left-cmds"> <!-- <div class="left-cmds">-->
<el-form v-if="paramsList.properties && paramsList.properties.length > 0" ref="loginForm" :model="form.data.params" label-width="120px"> <!-- <el-form v-if="paramsList.properties && paramsList.properties.length > 0" ref="loginForm" :model="form.data.params" label-width="120px">-->
<!--" 不校验的判断 --> <!-- &lt;!&ndash;" 不校验的判断 &ndash;&gt;-->
<el-form-item <!-- <el-form-item-->
v-for="paramsItem in paramsList.properties" <!-- v-for="paramsItem in paramsList.properties"-->
:key="paramsItem.funId" <!-- :key="paramsItem.funId"-->
:label="paramsItem.funName + ''" <!-- :label="paramsItem.funName + ''"-->
:prop="paramsItem.funKey" <!-- :prop="paramsItem.funKey"-->
> <!-- >-->
<!-- :rules="retrunRules(paramsItem)" 验证 --> <!-- &lt;!&ndash; :rules="retrunRules(paramsItem)" 验证 &ndash;&gt;-->
<el-select <!-- <el-select-->
v-if="paramsItem.funValidType === 'ENUM'" <!-- v-if="paramsItem.funValidType === 'ENUM'"-->
v-model="form.data.params[paramsItem.funKey]" <!-- v-model="form.data.params[paramsItem.funKey]"-->
clearable <!-- clearable-->
style="width: 85%;" <!-- style="width: 85%;"-->
> <!-- >-->
<el-option <!-- <el-option-->
v-for="(keys, valus) in strtoJson(paramsItem.funObj)" <!-- v-for="(keys, valus) in strtoJson(paramsItem.funObj)"-->
:key="valus" <!-- :key="valus"-->
:label="keys" <!-- :label="keys"-->
:value="valus" <!-- :value="valus"-->
></el-option> <!-- ></el-option>-->
</el-select> <!-- </el-select>-->
<el-input-number <!-- <el-input-number-->
v-else-if="paramsItem.funValidType === 'RANGE' && (paramsItem.funDataType === 'FLOAT' || paramsItem.funDataType === 'INT32')" <!-- v-else-if="paramsItem.funValidType === 'RANGE' && (paramsItem.funDataType === 'FLOAT' || paramsItem.funDataType === 'INT32')"-->
v-model="form.data.params[paramsItem.funKey]" <!-- v-model="form.data.params[paramsItem.funKey]"-->
:max="Number(paramsItem.funValMax) || 0" <!-- :max="Number(paramsItem.funValMax) || 0"-->
:min="Number(paramsItem.funValMin) || 0" <!-- :min="Number(paramsItem.funValMin) || 0"-->
clearable <!-- clearable-->
style="width: 85%;" <!-- style="width: 85%;"-->
></el-input-number> <!-- ></el-input-number>-->
<el-input-number <!-- <el-input-number-->
v-else-if="paramsItem.funValidType === 'NOT' && (paramsItem.funDataType === 'FLOAT' || paramsItem.funDataType === 'INT32')" <!-- v-else-if="paramsItem.funValidType === 'NOT' && (paramsItem.funDataType === 'FLOAT' || paramsItem.funDataType === 'INT32')"-->
v-model="form.data.params[paramsItem.funKey]" <!-- v-model="form.data.params[paramsItem.funKey]"-->
clearable <!-- clearable-->
style="width: 85%;" <!-- style="width: 85%;"-->
></el-input-number> <!-- ></el-input-number>-->
<el-input <!-- <el-input-->
v-else-if="paramsItem.funDataType === 'TEXT'" <!-- v-else-if="paramsItem.funDataType === 'TEXT'"-->
v-model="form.data.params[paramsItem.funKey]" <!-- v-model="form.data.params[paramsItem.funKey]"-->
clearable <!-- clearable-->
style="width: 85%;" <!-- style="width: 85%;"-->
/> <!-- />-->
</el-form-item> <!-- </el-form-item>-->
</el-form> <!-- </el-form>-->
<span v-else>暂无数据</span> <!-- <span v-else>暂无数据</span>-->
</div> <!-- </div>-->
<div class="right-json"> <div class="right-json">
<div class="option-wrap"> <div style="border: 1px solid #ccc; margin-top: -15px;width: 100%; height: 600px; overflow: scroll">
<el-button type="text" @click="copeText">复制</el-button> <json-viewer :expand-depth="10" :value="paramsList" copyable>
<template v-slot:copy>复制</template>
</json-viewer>
</div> </div>
<pre>{{paramsList}}</pre> <!-- <div class="option-wrap">-->
<!-- <el-button type="text" @click="copeText">复制</el-button>-->
<!-- </div>-->
<!-- <pre>{{paramsList}}</pre>-->
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import JsonViewer from 'vue-json-viewer';
import 'vue-json-viewer/style.css';
export default { export default {
name: "ParamsJson", name: "ParamsJson",
props: { props: {
@ -90,6 +97,7 @@ export default {
} }
}; };
}, },
components:{ JsonViewer },
created() { created() {
if (this.paramsList) { if (this.paramsList) {
this.form.action = this.other.action; this.form.action = this.other.action;
@ -106,7 +114,6 @@ export default {
return str ? JSON.parse(str.replace(/\\\"/g, '"')) : {}; return str ? JSON.parse(str.replace(/\\\"/g, '"')) : {};
}, },
handelList() { handelList() {
var result = {}; var result = {};
console.log("this.paramsList.properties",this.paramsList) console.log("this.paramsList.properties",this.paramsList)
this.paramsList.properties.forEach(v => { this.paramsList.properties.forEach(v => {
@ -125,13 +132,13 @@ export default {
width: 100%; width: 100%;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
.left-cmds { //.left-cmds {
width: 50%; // width: 50%;
display: flex; // display: flex;
justify-content: center; // justify-content: center;
} //}
.right-json { .right-json {
width: 50%; width: 100%;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
.option-wrap { .option-wrap {