feat(wms): 添加库位分割合并功能并优化仓库展示

refactor(warehouse): 重构仓库组件为按列展示模式
- 将分层展示改为分列展示,每列包含上下两层库位
- 添加右键菜单支持分割、合并操作
- 优化库位格子样式和交互

feat(crm): 新增订单编辑组件并实现自动保存
- 添加OrderEdit组件支持订单信息编辑
- 实现2秒延迟自动保存功能
- 优化订单详情页面布局

fix(delivery): 在查询参数中添加当前用户ID
- 在mycoil列表查询中添加saleId参数

style(preOrder): 注释掉审核人和审核时间列
- 隐藏预订单列表中的审核信息列

chore(warehouse): 移除仓库实体的导入导出按钮
- 注释掉仓库管理页面的模板下载和导入功能
This commit is contained in:
砂糖
2025-12-19 18:06:55 +08:00
parent a178ee4f5e
commit c821a2f7b9
10 changed files with 703 additions and 202 deletions

View File

@@ -8,14 +8,14 @@
<span class="value">{{ statistics.total }}</span>
</div>
<div class="statistics-item">
<span class="label"></span>
<span class="value">{{ statistics.layerCount }}</span>
<span class="label"></span>
<span class="value">{{ statistics.columnCount }}</span>
</div>
<div class="statistics-item">
<span class="label">库位分布</span>
<span class="label">库位分布</span>
<span class="value">
<span v-for="(count, layer) in statistics.layerDetail" :key="layer">
{{ layer }}{{ count }}
<span v-for="(count, column) in statistics.columnDetail" :key="column">
{{ column }}{{ count }}
</span>
</span>
</div>
@@ -38,28 +38,27 @@
</div>
</div>
<!-- 库位容器 -->
<!-- 库位容器 -->
<div class="layers-container">
<!-- 无数据提示 -->
<div class="empty-tip" v-if="Object.keys(layers).length === 0 && warehouseList.length > 0">
暂无解析到有效的库位分数据
<div class="empty-tip" v-if="Object.keys(columns).length === 0 && warehouseList.length > 0">
暂无解析到有效的库位分数据
</div>
<div class="empty-tip" v-else-if="warehouseList.length === 0">
<div class="empty-text">该分类下暂无库位数据</div>
<el-button type="primary" icon="el-icon-plus" @click="openInitDialog">初始化库位</el-button>
</div>
<warehouse-interlaced v-else="warehouseList.length" :layers="layers" />
<warehouse-interlaced v-else="warehouseList.length" :columns="columns" @split-warehouse="handleSplitWarehouse"/>
</div>
</div>
</template>
<script>
import WarehouseGrid from './WarehouseGrid.vue';
import WarehouseInterlaced from './WarehouseInterlaced.vue';
export default {
name: "WarehouseBird",
components: { WarehouseGrid, WarehouseInterlaced },
components: { WarehouseInterlaced },
props: {
// 原始库位列表
warehouseList: {
@@ -69,18 +68,18 @@ export default {
},
data() {
return {
// 分库位数据
layers: {},
// 统计信息
// 分库位数据核心修改从layers改为columns
columns: {},
// 统计信息(适配分列逻辑)
statistics: {
total: 0,
layerCount: 0,
layerDetail: {}
columnCount: 0,
columnDetail: {}
}
};
},
watch: {
// 监听库位列表变化,重新构建分数据
// 监听库位列表变化,重新构建分数据
warehouseList: {
immediate: true,
handler(newVal) {
@@ -89,8 +88,11 @@ export default {
}
},
methods: {
handleSplitWarehouse(warehouse) {
this.$emit('split-warehouse', warehouse);
},
/**
* 解析库位编码
* 解析第三级库位编码
*/
parseWarehouseCode(code) {
if (!code) return null;
@@ -103,6 +105,7 @@ export default {
}
return {
level: 3,
warehouseFirst: match[1],
warehouseSecond: match[2],
column: Number(match[3]),
@@ -112,60 +115,93 @@ export default {
},
/**
* 构建分层库位数据结构
* 解析第四级库位编码格式为F2A1-01-01-1
*/
parseWarehouseCodeFourth(code) {
if (!code) return null;
const reg = /^([A-Za-z])(\d+[A-Za-z])(\d)-X(\d{2})-(\d+)$/;
const match = code.match(reg);
if (!match) {
console.warn(`库位编码解析失败:${code},格式不符合规范`);
return null;
}
return {
level: 4,
warehouseFirst: match[1],
warehouseSecond: match[2],
column: Number(match[3]),
row: Number(match[4]),
layer: match[5],
};
},
/**
* 重构:按列构建库位数据结构,每列分为两层数组
*/
buildWarehouseBox(list) {
const layerMap = {};
const columnMap = {}; // 按列分组的核心对象
const statistics = {
total: list.length,
layerCount: 0,
layerDetail: {},
columnCount: 0,
columnDetail: {},
};
// 按层分
// 1. 按列分组每列内部分为layer1和layer2两个数
list.forEach((warehouse) => {
const codeInfo = this.parseWarehouseCode(warehouse.actualWarehouseCode);
let codeInfo = {}
if (warehouse.actualWarehouseType == 4) {
codeInfo = this.parseWarehouseCodeFourth(warehouse.actualWarehouseCode);
} else {
codeInfo = this.parseWarehouseCode(warehouse.actualWarehouseCode);
}
if (!codeInfo) return;
const { layer, row, column } = codeInfo;
warehouse.parsedInfo = codeInfo;
if (!layerMap[layer]) {
layerMap[layer] = {
// 初始化列数据结构每列包含layer1、layer2数组以及最大行号
if (!columnMap[column]) {
columnMap[column] = {
maxRow: 0,
maxColumn: 0,
warehouses: [],
emptyCount: 0
layer1: [], // 第一层库位数组
layer2: [], // 第二层库位数组
total: 0 // 该列总库位数
};
}
layerMap[layer].maxRow = Math.max(layerMap[layer].maxRow, row);
layerMap[layer].maxColumn = Math.max(layerMap[layer].maxColumn, column);
layerMap[layer].warehouses.push(warehouse);
// 更新列的最大行号
columnMap[column].maxRow = Math.max(columnMap[column].maxRow, row);
// 根据层数将库位放入对应数组
if (layer === '1' || layer === 1) {
columnMap[column].layer1.push(warehouse);
} else if (layer === '2' || layer === 2) {
columnMap[column].layer2.push(warehouse);
}
// 更新该列总库位数
columnMap[column].total = columnMap[column].layer1.length + columnMap[column].layer2.length;
});
// 处理空占位和排序
Object.keys(layerMap).forEach((layer) => {
const layerData = layerMap[layer];
const totalGrid = layerData.maxRow * layerData.maxColumn;
layerData.emptyCount = Math.max(0, totalGrid - layerData.warehouses.length);
// 按行号+列号排序
layerData.warehouses.sort((a, b) => {
if (a.parsedInfo.row !== b.parsedInfo.row) {
return a.parsedInfo.row - b.parsedInfo.row;
}
return a.parsedInfo.column - b.parsedInfo.column;
});
// 2. 对每列的两层数据分别按行号排序
Object.keys(columnMap).forEach((column) => {
const columnData = columnMap[column];
// 按行号排序(保证展示顺序正确)
columnData.layer1.sort((a, b) => a.parsedInfo.row - b.parsedInfo.row);
columnData.layer2.sort((a, b) => a.parsedInfo.row - b.parsedInfo.row);
});
// 更新统计信息
statistics.layerCount = Object.keys(layerMap).length;
Object.keys(layerMap).forEach((layer) => {
statistics.layerDetail[layer] = layerMap[layer].warehouses.length;
// 3. 更新统计信息(适配分列逻辑)
statistics.columnCount = Object.keys(columnMap).length;
Object.keys(columnMap).forEach((column) => {
statistics.columnDetail[column] = columnMap[column].total;
});
this.layers = layerMap;
// 4. 赋值到响应式数据
this.columns = columnMap;
this.statistics = statistics;
},
@@ -249,7 +285,7 @@ export default {
}
.occupied {
background-color: #111;
background-color: #fafafa;
}
.legend-text {
@@ -259,7 +295,7 @@ export default {
}
}
// 分容器样式
// 分容器样式
.layers-container {
display: flex;