feat(product): 添加设备类型筛选功能并优化物模型管理

- 在查询表单中新增设备类型筛选条件
- 在表格列中显示设备类型信息
- 在编辑表单中添加设备类型选择字段
- 更新数据字典配置以支持设备类型
- 修复标识符重复验证提示信息,明确指出同设备类型下不能重复
- 优化数据类型转换逻辑,确保前后端数据一致性
- 修复重置查询时devType字段的处理逻辑
This commit is contained in:
Gjm
2026-04-09 16:26:49 +08:00
parent 4f468c4569
commit ba4d30f048
2 changed files with 183 additions and 138 deletions

View File

@@ -248,7 +248,7 @@
"product.product-things-model.142341-1": "导入通用物模型", "product.product-things-model.142341-1": "导入通用物模型",
"product.product-things-model.142341-2": "刷新", "product.product-things-model.142341-2": "刷新",
"product.product-things-model.142341-3": "查看物模型", "product.product-things-model.142341-3": "查看物模型",
"product.product-things-model.142341-4": "注意:标识符不能重复", "product.product-things-model.142341-4": "注意:同设备类型下标识符不能重复",
"product.product-things-model.142341-5": "请选择设备从机:", "product.product-things-model.142341-5": "请选择设备从机:",
"product.product-things-model.142341-6": "请选择设备从机", "product.product-things-model.142341-6": "请选择设备从机",
"product.product-things-model.142341-7": "网关物模型", "product.product-things-model.142341-7": "网关物模型",
@@ -377,6 +377,10 @@
"product.product-things-model.142341-133": "搜索", "product.product-things-model.142341-133": "搜索",
"product.product-things-model.142341-134": "重置", "product.product-things-model.142341-134": "重置",
"product.product-things-model.142341-135": "分组", "product.product-things-model.142341-135": "分组",
"product.product-things-model.142341-136": "设备类型",
"product.product-things-model.142341-137": "请选择设备类型",
"product.product-things-model.142341-138": "模型名称",
"product.product-things-model.142341-139": "请选择模型名称",
"product.product-modbus.562372-0": "网关子设备配置", "product.product-modbus.562372-0": "网关子设备配置",
"product.product-modbus.562372-1": "网关子设备配置默认的子设备地址,轮询方式", "product.product-modbus.562372-1": "网关子设备配置默认的子设备地址,轮询方式",
"product.product-modbus.562372-2": "编辑设备配置", "product.product-modbus.562372-2": "编辑设备配置",

View File

@@ -1,28 +1,30 @@
<template> <template>
<div style="padding-left: 20px"> <div style="padding-left: 20px">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="108px"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="108px">
<!-- <el-form-item :label="$t('product.product-things-model.142341-127')" prop="isAPP"> <!-- <el-form-item :label="$t('product.product-things-model.142341-138')" prop="modelName">-->
<el-select v-model="queryParams.isAPP" :placeholder="$t('product.product-things-model.142341-128')" clearable <!-- <el-input v-model="queryParams.modelName" :placeholder="$t('product.product-things-model.142341-139')" clearable size="small" @keyup.enter.native="handleQuery" />-->
size="small"> <!-- </el-form-item>-->
<el-option v-for="dict in dict.type.iot_yes_no" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item> -->
<el-form-item :label="$t('product.product-things-model.142341-129')" prop="type">
<el-select v-model="queryParams.type" :placeholder="$t('product.product-things-model.142341-130')" clearable size="small">
<el-option v-for="dict in dict.type.iot_things_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item :label="$t('product.product-things-model.142341-131')" prop="isHistory">
<el-select v-model="queryParams.isHistory" :placeholder="$t('product.product-things-model.142341-132')" clearable size="small">
<el-option v-for="dict in dict.type.iot_yes_no" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">{{ $t('product.product-things-model.142341-133') }}</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">{{ $t('product.product-things-model.142341-134') }}</el-button>
</el-form-item>
</el-form>
<el-form-item :label="$t('product.product-things-model.142341-129')" prop="type">
<el-select v-model="queryParams.type" :placeholder="$t('product.product-things-model.142341-130')" clearable size="small">
<el-option v-for="dict in dict.type.iot_things_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item :label="$t('product.product-things-model.142341-136')" prop="devType">
<el-select v-model="queryParams.devType" :placeholder="$t('product.product-things-model.142341-137')" clearable size="small">
<el-option v-for="dict in dict.type.model_dev_type" :key="dict.value" :label="dict.label" :value="Number(dict.value)" />
</el-select>
</el-form-item>
<el-form-item :label="$t('product.product-things-model.142341-131')" prop="isHistory">
<el-select v-model="queryParams.isHistory" :placeholder="$t('product.product-things-model.142341-132')" clearable size="small">
<el-option v-for="dict in dict.type.iot_yes_no" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">{{ $t('product.product-things-model.142341-133') }}</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">{{ $t('product.product-things-model.142341-134') }}</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8"> <el-row :gutter="10" class="mb8">
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-if="productInfo.status == 1 && productInfo.isOwner != 0" v-hasPermi="['iot:model:add']"> <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-if="productInfo.status == 1 && productInfo.isOwner != 0" v-hasPermi="['iot:model:add']">
@@ -98,6 +100,11 @@
<div v-html="formatSpecsDisplay(scope.row.specs)"></div> <div v-html="formatSpecsDisplay(scope.row.specs)"></div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('product.product-things-model.142341-136')" align="center" prop="devType" width="80">
<template slot-scope="scope">
<dict-tag :options="dict.type.model_dev_type" :value="scope.row.devType" />
</template>
</el-table-column>
<el-table-column :label="$t('product.product-things-model.142341-19')" align="center" prop="formula" /> <el-table-column :label="$t('product.product-things-model.142341-19')" align="center" prop="formula" />
<el-table-column :label="$t('product.product-things-model.142341-20')" align="center" prop="modelOrder" width="80" /> <el-table-column :label="$t('product.product-things-model.142341-20')" align="center" prop="modelOrder" width="80" />
<el-table-column :label="$t('product.product-things-model.142341-21')" align="center" class-name="small-padding fixed-width" fixed="right"> <el-table-column :label="$t('product.product-things-model.142341-21')" align="center" class-name="small-padding fixed-width" fixed="right">
@@ -133,6 +140,11 @@
<el-radio-button label="3">{{ $t('product.product-things-model.142341-33') }}</el-radio-button> <el-radio-button label="3">{{ $t('product.product-things-model.142341-33') }}</el-radio-button>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item :label="$t('product.product-things-model.142341-136')" prop="devType">
<el-select v-model="form.devType" :placeholder="$t('product.product-things-model.142341-137')" clearable style="width: 385px">
<el-option v-for="dict in dict.type.model_dev_type" :key="dict.value" :label="dict.label" :value="String(dict.value)" />
</el-select>
</el-form-item>
<el-form-item :label="$t('product.product-things-model.142341-34')" prop="property"> <el-form-item :label="$t('product.product-things-model.142341-34')" prop="property">
<el-checkbox name="isChart" :label="$t('product.product-things-model.142341-12')" @change="isChartChange" v-show="form.type == 1" v-model="form.isChart" :true-label="1" :false-label="0"></el-checkbox> <el-checkbox name="isChart" :label="$t('product.product-things-model.142341-12')" @change="isChartChange" v-show="form.type == 1" v-model="form.isChart" :true-label="1" :false-label="0"></el-checkbox>
<el-checkbox <el-checkbox
@@ -391,7 +403,7 @@ import importBatch from './components/batchImportThingsModel';
export default { export default {
name: 'product-things-model', name: 'product-things-model',
dicts: ['iot_things_type', 'iot_data_type', 'iot_yes_no'], dicts: ['iot_things_type', 'iot_data_type', 'iot_yes_no', 'model_dev_type'],
components: { components: {
productSelectTemplate, productSelectTemplate,
thingsParameter, thingsParameter,
@@ -537,6 +549,7 @@ export default {
modelOrder: 0, modelOrder: 0,
type: 1, type: 1,
datatype: 'integer', datatype: 'integer',
devType: null,
isSys: null, isSys: null,
isChart: 1, isChart: 1,
isHistory: 1, isHistory: 1,
@@ -564,16 +577,19 @@ export default {
}; };
this.resetForm('form'); this.resetForm('form');
}, },
/** 搜索按钮操作 */ /** 搜索按钮操作 */
handleQuery() { handleQuery() {
this.queryParams.pageNum = 1; this.queryParams.pageNum = 1;
this.getList(); this.getList();
}, },
/** 重置按钮操作 */
resetQuery() { /** 重置按钮操作 */
this.resetForm('queryForm'); resetQuery() {
this.handleQuery(); this.resetForm('queryForm');
}, // 重置后确保 devType 为 undefined 而不是空字符串
this.queryParams.devType = undefined;
this.handleQuery();
},
/** 新增按钮操作 */ /** 新增按钮操作 */
handleAdd() { handleAdd() {
this.reset(); this.reset();
@@ -581,43 +597,55 @@ export default {
this.title = this.$t('product.product-things-model.142341-99'); this.title = this.$t('product.product-things-model.142341-99');
}, },
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { /** 修改按钮操作 */
this.reset(); handleUpdate(row) {
const modelId = row.modelId; this.reset();
getModel(modelId).then((response) => { const modelId = row.modelId;
let tempForm = response.data; getModel(modelId).then((response) => {
this.open = true; let tempForm = response.data;
this.title = this.$t('product.product-things-model.142341-100'); this.open = true;
// Json转对象 this.title = this.$t('product.product-things-model.142341-100');
tempForm.specs = JSON.parse(tempForm.specs); // devType类型转换确保与下拉选项类型一致String类型
if (!tempForm.specs.enumList) { if (tempForm.devType != null && tempForm.devType !== '') {
tempForm.specs.showWay = 'select'; tempForm.devType = String(tempForm.devType);
tempForm.specs.enumList = [ } else {
{ tempForm.devType = undefined;
value: '', }
text: '', // Json转对象
}, tempForm.specs = JSON.parse(tempForm.specs);
]; if (!tempForm.specs.enumList) {
} tempForm.specs.showWay = 'select';
if (!tempForm.specs.arrayType) { tempForm.specs.enumList = [
tempForm.specs.arrayType = 'integer'; {
} value: '',
if (!tempForm.specs.arrayCount) { text: '',
tempForm.specs.arrayCount = 5; },
} ];
if (!tempForm.specs.params) { }
tempForm.specs.params = []; if (!tempForm.specs.arrayType) {
} tempForm.specs.arrayType = 'integer';
// 对象和数组中参数删除前缀 }
if ((tempForm.specs.type == 'array' && tempForm.specs.arrayType == 'object') || tempForm.specs.type == 'object') { if (!tempForm.specs.arrayCount) {
for (let i = 0; i < tempForm.specs.params.length; i++) { tempForm.specs.arrayCount = 5;
tempForm.specs.params[i].id = String(tempForm.specs.params[i].id).substring(String(tempForm.identifier).length + 1); }
} if (!tempForm.specs.params) {
} tempForm.specs.params = [];
this.form = tempForm; }
}); // 对象和数组中参数删除前缀
}, if ((tempForm.specs.type == 'array' && tempForm.specs.arrayType == 'object') || tempForm.specs.type == 'object') {
/**查看物模型 */ for (let i = 0; i < tempForm.specs.params.length; i++) {
tempForm.specs.params[i].id = String(tempForm.specs.params[i].id).substring(String(tempForm.identifier).length + 1);
}
}
this.form = tempForm;
// 强制更新视图
this.$nextTick(() => {
this.$set(this.form, 'devType', this.form.devType);
});
});
},
/**查看物模型 */
handleOpenThingsModel() { handleOpenThingsModel() {
this.title = this.$t('product.product-things-model.142341-101'); this.title = this.$t('product.product-things-model.142341-101');
// 生成物模型 // 生成物模型
@@ -702,74 +730,87 @@ export default {
// 使用正则表达式检查值中是否包含下划线 // 使用正则表达式检查值中是否包含下划线
return /_/.test(value); return /_/.test(value);
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm() { submitForm() {
this.$refs['form'].validate((valid) => { this.$refs['form'].validate((valid) => {
if (valid) { if (valid) {
// 验证对象或对象数组中的参数不能为空 // 验证对象或对象数组中的参数不能为空
if (this.form.datatype == 'object' || (this.form.datatype == 'array' && this.form.specs.arrayType == 'object')) { if (this.form.datatype == 'object' || (this.form.datatype == 'array' && this.form.specs.arrayType == 'object')) {
if (!this.form.specs.params || this.form.specs.params == 0) { if (!this.form.specs.params || this.form.specs.params == 0) {
this.$modal.msgError(this.$t('product.product-things-model.142341-102')); this.$modal.msgError(this.$t('product.product-things-model.142341-102'));
return; return;
} }
if (this.containsUnderscore(this.form.identifier)) { if (this.containsUnderscore(this.form.identifier)) {
this.$modal.msgError(this.$t('product.product-things-model.142341-103')); this.$modal.msgError(this.$t('product.product-things-model.142341-103'));
return; return;
} }
} }
// 验证对象参数标识符不能相同 // 验证对象参数标识符不能相同
if (this.form.specs.params && this.form.specs.params.length > 0) { if (this.form.specs.params && this.form.specs.params.length > 0) {
let arr = this.form.specs.params.map((item) => item.id).sort(); let arr = this.form.specs.params.map((item) => item.id).sort();
for (let i = 0; i < arr.length; i++) { for (let i = 0; i < arr.length; i++) {
if (arr[i] == arr[i + 1]) { if (arr[i] == arr[i + 1]) {
this.$modal.msgError('参数标识 ' + arr[i] + ' 重复'); this.$modal.msgError('参数标识 ' + arr[i] + ' 重复');
return; return;
}
}
}
//验证模型特性为图表展示时,数据类型是否为整数或者小数
if (this.form.isChart == 1 && this.form.datatype != 'integer' && this.form.isChart == 1 && this.form.datatype != 'decimal') {
this.$modal.msgError(this.$t('product.product-things-model.142341-106'));
} else if (this.form.modelId != null) {
// 格式化specs
let tempForm = JSON.parse(JSON.stringify(this.form));
tempForm.specs = this.formatThingsSpecs();
if (this.form.type == 2) {
tempForm.isMonitor = 0;
tempForm.isChart = 0;
} else if (this.form.type == 3) {
tempForm.isMonitor = 0;
tempForm.isChart = 0;
}
updateModel(tempForm).then((response) => {
this.$modal.msgSuccess(this.$t('product.product-things-model.142341-107'));
this.open = false;
this.getList();
this.$emit('updateModel');
});
} else {
// 格式化specs
let tempForm = JSON.parse(JSON.stringify(this.form));
tempForm.specs = this.formatThingsSpecs();
tempForm.productId = this.productInfo.productId;
tempForm.productName = this.productInfo.productName;
if (this.form.type == 2) {
tempForm.isMonitor = 0;
} else if (this.form.type == 3) {
tempForm.isMonitor = 0;
tempForm.isChart = 0;
}
addModel(tempForm).then((response) => {
this.$modal.msgSuccess(this.$t('product.product-things-model.142341-108'));
this.open = false;
this.getList();
this.$emit('updateModel');
});
}
} }
}); }
}, }
/** 删除按钮操作 */ //验证模型特性为图表展示时,数据类型是否为整数或者小数
if (this.form.isChart == 1 && this.form.datatype != 'integer' && this.form.isChart == 1 && this.form.datatype != 'decimal') {
this.$modal.msgError(this.$t('product.product-things-model.142341-106'));
} else if (this.form.modelId != null) {
// 格式化specs
let tempForm = JSON.parse(JSON.stringify(this.form));
tempForm.specs = this.formatThingsSpecs();
// devType类型转换String转Number如果devType有值
if (tempForm.devType != null && tempForm.devType !== '' && tempForm.devType !== undefined) {
tempForm.devType = Number(tempForm.devType);
} else {
tempForm.devType = null;
}
if (this.form.type == 2) {
tempForm.isMonitor = 0;
tempForm.isChart = 0;
} else if (this.form.type == 3) {
tempForm.isMonitor = 0;
tempForm.isChart = 0;
}
updateModel(tempForm).then((response) => {
this.$modal.msgSuccess(this.$t('product.product-things-model.142341-107'));
this.open = false;
this.getList();
this.$emit('updateModel');
});
} else {
// 格式化specs
let tempForm = JSON.parse(JSON.stringify(this.form));
tempForm.specs = this.formatThingsSpecs();
// devType类型转换String转Number如果devType有值
if (tempForm.devType != null && tempForm.devType !== '' && tempForm.devType !== undefined) {
tempForm.devType = Number(tempForm.devType);
} else {
tempForm.devType = null;
}
tempForm.productId = this.productInfo.productId;
tempForm.productName = this.productInfo.productName;
if (this.form.type == 2) {
tempForm.isMonitor = 0;
} else if (this.form.type == 3) {
tempForm.isMonitor = 0;
tempForm.isChart = 0;
}
addModel(tempForm).then((response) => {
this.$modal.msgSuccess(this.$t('product.product-things-model.142341-108'));
this.open = false;
this.getList();
this.$emit('updateModel');
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
const modelIds = row.modelId; const modelIds = row.modelId;
this.$modal this.$modal