refactor(wms/coil): 重构线圈页面使用基础组件替代复杂逻辑

移除原有的级联选择器实现,改用基础页面组件BasePage来简化代码结构。新实现通过props传递配置参数,使代码更简洁易维护。
This commit is contained in:
砂糖
2025-11-25 09:19:11 +08:00
parent 28d0852a81
commit a7fac2e9e6

View File

@@ -1,212 +1,25 @@
<template>
<div
:class="['actual-warehouse-select', { 'is-block': block }]"
:style="wrapperStyle"
>
<el-cascader
ref="cascader"
v-model="innerPath"
:props="cascaderProps"
:placeholder="placeholder"
:clearable="clearable"
:show-all-levels="true"
:emit-path="true"
style="width: 100%;"
@change="handleChange"
/>
</div>
<BasePage :qrcode="qrcode" :querys="querys" :labelType="labelType" :hideType="hideType" />
</template>
<script>
import { listActualWarehouse } from '@/api/wms/actualWarehouse';
import BasePage from './panels/base.vue';
export default {
name: 'ActualWarehouseSelect',
props: {
// 对外仍然是「单个 ID」即第三级 actualWarehouseId
value: {
type: [Number, String, null],
default: null
},
placeholder: {
type: String,
default: '请选择实际库位'
},
clearable: {
type: Boolean,
default: true
},
// 已经不再显示“最高级”
showTop: {
type: Boolean,
default: false
},
block: {
type: Boolean,
default: false
},
width: {
type: [String, Number],
default: 240
},
size: {
type: String,
default: 'small'
}
components: {
BasePage
},
data() {
return {
// 级联组件内部使用的「路径值」,例如 [一级ID, 二级ID, 三级ID]
innerPath: [],
// 记录所有已加载节点(如果后面要根据 ID 反查路径,可复用)
allLoadedNodes: []
};
},
computed: {
wrapperStyle() {
const widthValue = this.block
? '100%'
: (typeof this.width === 'number' ? `${this.width}px` : this.width);
return { width: widthValue };
},
// el-cascader 的 props 配置
cascaderProps() {
return {
lazy: true,
lazyLoad: this.loadNode, // 懒加载方法
checkStrictly: false, // 只允许选叶子节点
value: 'value',
label: 'label',
children: 'children'
};
}
},
watch: {
// 外部把 value 置空时,同步清空面板
value(val) {
if (val == null || val === '') {
this.innerPath = [];
}
}
},
methods: {
/**
* 级联懒加载
* node.level:
* 0还没选任何东西parentId = 0 -> 加载一级)
* 1一级节点加载二级
* 2二级节点加载三级三级设为叶子不再展开
*/
loadNode(node, resolve) {
const { level, value } = node;
// 超过第三级就不再加载
if (level >= 3) {
resolve([]);
return;
}
const parentId = level === 0 ? 0 : value;
listActualWarehouse({ parentId }).then(res => {
const list = (res.data || []).map(item => {
const nextLevel = level + 1;
const isLeafLevel = nextLevel >= 3; // 第三级为叶子,不能再展开
const nodeData = {
value: item.actualWarehouseId,
label: item.actualWarehouseName,
leaf: isLeafLevel,
// 只有第三级可选;一、二级全部 disabled
disabled: nextLevel < 3 || item.isEnabled === false,
// 保留原始数据和层级
raw: item,
level: nextLevel
};
this.registerNode(nodeData);
return nodeData;
});
resolve(list);
}).catch(err => {
console.error('加载仓库树失败:', err);
resolve([]);
});
},
/** 把节点放进缓存数组里,后面如需扩展可用 */
registerNode(node) {
const id = node.value;
const idx = this.allLoadedNodes.findIndex(
n => String(n.value) === String(id)
);
if (idx === -1) {
this.allLoadedNodes.push(node);
} else {
this.$set(this.allLoadedNodes, idx, {
...this.allLoadedNodes[idx],
...node
});
}
},
/**
* 选中变化:
* value 是路径数组,如 [一级ID, 二级ID, 三级ID]
* 我们对外只抛最后一个第三级ID
*/
handleChange(value) {
if (!Array.isArray(value) || value.length === 0) {
this.$emit('input', null);
this.$emit('select', null);
return;
}
const leafId = value[value.length - 1];
// 拿到当前选中节点,获取完整路径信息
const nodes = this.$refs.cascader.getCheckedNodes();
let payload = null;
if (nodes && nodes.length > 0) {
const node = nodes[0];
const pathNodes = node.path || [];
payload = {
id: leafId,
pathIds: pathNodes.map(n => n.value),
pathLabels: pathNodes.map(n => n.label),
// 原始 data如果需要后台做别的处理可以用
rawPath: pathNodes.map(n => n.data || n.raw || {})
};
}
this.$emit('input', leafId);
this.$emit('select', payload);
},
/** 外部刷新:如果以后需要强制重载,可以扩展这里(目前不需要缓存) */
refresh() {
this.innerPath = [];
this.allLoadedNodes = [];
// el-cascader 的懒加载不需要预载,这里清空即可
qrcode: true,
querys: {
dataType: 1,
// itemType: 'raw_material'
materialType: '原料'
},
labelType: '2',
hideType: true
}
}
};
</script>
<style scoped>
.actual-warehouse-select {
display: inline-block;
width: 100%;
}
.actual-warehouse-select.is-block {
width: 100%;
}
/* 让级联宽度占满容器,其他高度、边框等跟 el-select 共用全局 .el-input__inner 样式 */
.actual-warehouse-select .el-cascader {
width: 100%;
}
</style>
</script>