|
|
@@ -210,14 +210,16 @@
|
|
|
</el-col>
|
|
|
<el-col :span="12">
|
|
|
<el-form-item label="设备类型" prop="equipmentTypeId">
|
|
|
- <el-select v-model="form.equipmentTypeId" placeholder="请选择设备类型" style="width: 100%">
|
|
|
- <el-option
|
|
|
- v-for="item in equipmentTypeOptions"
|
|
|
- :key="item.typeId"
|
|
|
- :label="item.typeName"
|
|
|
- :value="item.typeId"
|
|
|
- />
|
|
|
- </el-select>
|
|
|
+ <el-tree-select
|
|
|
+ v-model="form.equipmentTypeId"
|
|
|
+ :data="equipmentTypeTree"
|
|
|
+ node-key="typeId"
|
|
|
+ :props="{ label: 'typeName', children: 'children', disabled: 'disabled' }"
|
|
|
+ default-expand-all
|
|
|
+ :render-after-expand="false"
|
|
|
+ placeholder="请选择设备类型"
|
|
|
+ style="width: 100%"
|
|
|
+ />
|
|
|
</el-form-item>
|
|
|
</el-col>
|
|
|
<el-col :span="12">
|
|
|
@@ -406,6 +408,68 @@ const typeNameMap = computed(() => {
|
|
|
}, {});
|
|
|
});
|
|
|
|
|
|
+// parentTypeId 为 0(或空)表示父类
|
|
|
+function isTopLevelType(item) {
|
|
|
+ const parentTypeId = item?.parentTypeId;
|
|
|
+ return parentTypeId === 0 || parentTypeId === "0" || parentTypeId === null || parentTypeId === undefined || parentTypeId === "";
|
|
|
+}
|
|
|
+
|
|
|
+const equipmentTypeTree = computed(() => {
|
|
|
+ const list = equipmentTypeOptions.value || [];
|
|
|
+ const entries = [];
|
|
|
+ // 同时按 typeId / id 建索引,兼容 parentTypeId 指向不同主键字段的情况
|
|
|
+ const nodeIndex = {};
|
|
|
+
|
|
|
+ list.forEach((item) => {
|
|
|
+ const node = {
|
|
|
+ typeId: item.typeId,
|
|
|
+ typeName: item.typeName,
|
|
|
+ disabled: isTopLevelType(item),
|
|
|
+ children: []
|
|
|
+ };
|
|
|
+ entries.push({ item, node });
|
|
|
+ [item.typeId, item.id].forEach((key) => {
|
|
|
+ if (key !== undefined && key !== null) {
|
|
|
+ nodeIndex[String(key)] = node;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ const roots = [];
|
|
|
+ // 父节点不在返回列表中时兜底归类,避免子类型在下拉中丢失
|
|
|
+ const fallbackNode = { typeId: "__other__", typeName: "未分类", disabled: true, children: [] };
|
|
|
+
|
|
|
+ entries.forEach(({ item, node }) => {
|
|
|
+ if (isTopLevelType(item)) {
|
|
|
+ roots.push(node);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const parent = nodeIndex[String(item.parentTypeId)];
|
|
|
+ if (parent && parent !== node) {
|
|
|
+ parent.children.push(node);
|
|
|
+ } else {
|
|
|
+ fallbackNode.children.push(node);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 带子级的节点(即父类)统一禁选,叶子节点可选;空 children 去掉渲染为叶子
|
|
|
+ const prune = (node) => {
|
|
|
+ if (node.children && node.children.length) {
|
|
|
+ node.disabled = true;
|
|
|
+ node.children.forEach(prune);
|
|
|
+ } else {
|
|
|
+ delete node.children;
|
|
|
+ }
|
|
|
+ return node;
|
|
|
+ };
|
|
|
+
|
|
|
+ const result = roots.map(prune);
|
|
|
+ if (fallbackNode.children.length) {
|
|
|
+ result.push(prune(fallbackNode));
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+});
|
|
|
+
|
|
|
const statusMap = computed(() => {
|
|
|
return equipmentStatusList.value.reduce((acc, item) => {
|
|
|
acc[item.equipmentId] = item;
|