refactor(wms): 优化钢卷拆分与合并界面的信息展示和交互逻辑

重构钢卷拆分界面,移除参数信息展示,增加规格、材质等字段显示
调整钢卷合并界面,优化待合卷列表展示逻辑,移除冗余代码
统一两个界面的表单控件步长设置方式,提升用户体验
This commit is contained in:
砂糖
2026-01-15 11:01:41 +08:00
parent 580f127d51
commit 95e33a1869
2 changed files with 81 additions and 339 deletions

View File

@@ -19,7 +19,7 @@
<div class="flow-left">
<div class="flow-section-title">
<span>源卷列表</span>
<!-- <el-button v-if="!readonly" type="text" size="mini" @click="addSourceCoil" icon="el-icon-plus">添加</el-button> -->
<el-button v-if="!readonly" type="primary" size="small" @click="addSourceCoil">添加</el-button>
</div>
<div class="source-list">
@@ -68,10 +68,10 @@
</template>
<!-- 第二个位置显示待合卷列表 -->
<template v-else-if="index === 1 && !readonly">
<template v-else-if="!readonly">
<div class="pending-list-title">待合卷钢卷列表</div>
<div class="pending-coil-list" v-if="pendingMergeList.length > 0">
<div class="pending-coil-item" v-for="pending in pendingMergeList" :key="pending.actionId"
<div class="pending-coil-list" v-if="renderPendingMergeList.length > 0">
<div class="pending-coil-item" v-for="pending in renderPendingMergeList" :key="pending.actionId"
@click="selectPendingCoil(pending, index)">
<div class="pending-coil-no">{{ pending.currentCoilNo }}</div>
<div class="pending-coil-info">
@@ -85,12 +85,6 @@
暂无其他待合卷钢卷
</div>
</template>
<!-- 其他位置显示选择按钮 -->
<el-button v-else-if="!readonly" type="text" size="small" @click="selectCoil(index)">
<i class="el-icon-search"></i> 选择钢卷
</el-button>
<div v-else class="empty-tip">未选择钢卷</div>
</div>
</div>
</div>
@@ -140,18 +134,18 @@
</el-select>
</el-form-item>
<el-form-item :label="getItemLabel">
<raw-material-selector v-if="targetCoil.materialType === '原料'"
v-model="targetCoil.itemId" placeholder="请选择原料" style="width: 100%" clearable
:disabled="readonly || !targetCoil.materialType" />
<raw-material-selector v-if="targetCoil.materialType === '原料'" v-model="targetCoil.itemId"
placeholder="请选择原料" style="width: 100%" clearable :disabled="readonly || !targetCoil.materialType" />
<product-selector v-else-if="targetCoil.materialType === '成品'" v-model="targetCoil.itemId"
placeholder="请选择成品" style="width: 100%" clearable :disabled="readonly || !targetCoil.materialType" />
<div v-else>请先选择物料类型</div>
</el-form-item>
<el-form-item label="质量状态" prop="qualityStatus">
<el-form-item label="质量状态" prop="qualityStatus">
<el-select v-model="targetCoil.qualityStatus" placeholder="请选择质量状态" style="width: 100%"
:disabled="readonly">
<el-option v-for="item in dict.type.coil_quality_status" :key="item.value" :label="item.label" :value="item.value" />
<el-option v-for="item in dict.type.coil_quality_status" :key="item.value" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
@@ -178,19 +172,19 @@
</el-form-item>
<el-form-item label="毛重(t)">
<el-input-number precision="3" :controls="false" v-model="targetCoil.grossWeight" placeholder="请输入毛重"
type="number" step="0.01" :disabled="readonly">
type="number" :step="0.01" :disabled="readonly">
<template slot="append"></template>
</el-input-number>
</el-form-item>
<el-form-item label="净重(t)">
<el-input-number precision="3" :controls="false" v-model="targetCoil.netWeight" placeholder="请输入净重"
type="number" step="0.01" :disabled="readonly">
type="number" :step="0.01" :disabled="readonly">
<template slot="append"></template>
</el-input-number>
</el-form-item>
<el-form-item label="长度(m)">
<el-input-number :controls="false" v-model="targetCoil.length" placeholder="请输入长度" type="number"
step="0.01" :disabled="readonly">
:step="0.01" :disabled="readonly">
<template slot="append"></template>
</el-input-number>
</el-form-item>
@@ -219,17 +213,11 @@
</div>
</div>
</div>
<!-- 钢卷选择器 -->
<coil-selector :visible.sync="coilSelectorVisible" @select="handleCoilSelect" />
</div>
</template>
<script>
import { getMaterialCoil, mergeMaterialCoil } from '@/api/wms/coil';
import { listWarehouse } from '@/api/wms/warehouse';
import { listRawMaterialWithBom } from '@/api/wms/rawMaterial';
import { listProductWithBom } from '@/api/wms/product';
import { listPendingAction, completeAction } from '@/api/wms/pendingAction';
import CoilSelector from '@/components/CoilSelector';
import ActualWarehouseSelect from "@/components/KLPService/ActualWarehouseSelect";
@@ -237,7 +225,6 @@ import RawMaterialSelector from "@/components/KLPService/RawMaterialSelect";
import ProductSelector from "@/components/KLPService/ProductSelect";
import WarehouseSelect from "@/components/KLPService/WarehouseSelect";
export default {
name: 'MergeCoil',
components: {
@@ -271,16 +258,6 @@ export default {
},
buttonLoading: false,
loading: false,
// 钢卷选择器可见性
coilSelectorVisible: false,
// 当前选择的源卷索引
currentSelectIndex: -1,
// 库区列表
warehouseList: [],
// 原材料和产品列表(实时搜索,不再保存完整备份)
rawMaterialList: [],
productList: [],
itemSearchLoading: false,
// 只读模式
readonly: false,
// 待合卷列表(其他待操作的合卷任务)
@@ -307,18 +284,10 @@ export default {
}
return '请先选择材料类型';
},
// 当前物品列表(根据物品类型动态切换)
currentItemList() {
if (this.targetCoil.itemType === 'raw_material') {
return this.rawMaterialList.map(item => ({
id: item.rawMaterialId,
name: this.formatItemName(item)
}));
} else if (this.targetCoil.itemType === 'product') {
return this.productList.map(item => ({
id: item.productId,
name: this.formatItemName(item)
}));
renderPendingMergeList() {
// 从pendingMergeList中筛选出不好含在sourceCoils中的,通过enterCoilNo
if (this.pendingMergeList.length > 0) {
return this.pendingMergeList.filter(pending => !this.sourceCoils.some(source => source.enterCoilNo === pending.enterCoilNo))
}
return [];
}
@@ -327,9 +296,6 @@ export default {
// 不再需要watch直接用@change事件处理
},
async created() {
// 加载库区列表
await this.loadWarehouses();
// 不再一次性加载所有数据,改为实时搜索
// await this.loadAllItems();
@@ -392,6 +358,19 @@ export default {
}
},
methods: {
// 处理材料类型变化
handleMaterialTypeChange(value) {
// 清空物品选择
this.$set(this.targetCoil, 'itemId', null);
// 根据材料类型设置物品类型
if (value === '成品') {
this.$set(this.targetCoil, 'itemType', 'product');
} else if (value === '原料') {
this.$set(this.targetCoil, 'itemType', 'raw_material');
}
this.$set(this.targetCoil, 'itemId', undefined);
},
// 加载第一个钢卷(从待操作进入时)
async loadFirstCoil(coilId) {
try {
@@ -458,31 +437,17 @@ export default {
this.pendingLoading = true;
// 分别查询待处理和处理中的记录
const responses = await Promise.all([
listPendingAction({
actionType: 200, // 合卷操作
actionStatus: 0, // 待处理
pageNum: 1,
pageSize: 1000
}),
listPendingAction({
actionType: 200, // 合卷操作
actionStatus: 1, // 处理中
pageNum: 1,
pageSize: 1000
})
]);
// 合并两个列表
const allPending = [
...(responses[0].rows || []),
...(responses[1].rows || [])
];
const responses = await listPendingAction({
actionType: 200, // 合卷操作
actionStatus: 0, // 只要传递了actionStatus就会查询不为2的
pageNum: 1,
pageSize: 1000
});
// 排除当前钢卷
const currentCoilId = this.sourceCoils[0] ? this.sourceCoils[0].coilId : null;
this.pendingMergeList = allPending.filter(item => item.coilId !== currentCoilId);
this.pendingMergeList = responses.rows.filter(item => item.coilId !== currentCoilId);
} catch (error) {
console.error('加载待合卷列表失败', error);
} finally {
@@ -570,75 +535,6 @@ export default {
return displayName;
},
// 加载库区列表
async loadWarehouses() {
try {
const response = await listWarehouse({ pageNum: 1, pageSize: 1000 });
if (response.code === 200) {
this.warehouseList = response.rows || response.data || [];
}
} catch (error) {
console.error('加载库区列表失败', error);
}
},
// 已移除 loadAllItems改为实时搜索
// 已移除 loadItemList改为实时搜索
// 实时搜索物品(后端搜索)
async searchItems(query) {
if (!this.targetCoil.itemType) {
this.$message.warning('请先选择材料类型');
return;
}
// 如果没有输入,清空列表
if (!query || query.trim() === '') {
if (this.targetCoil.itemType === 'raw_material') {
this.rawMaterialList = [];
} else if (this.targetCoil.itemType === 'product') {
this.productList = [];
}
return;
}
try {
this.itemSearchLoading = true;
const searchQuery = query.trim();
if (this.targetCoil.itemType === 'raw_material') {
// 后端搜索原材料(支持名称或规格模糊搜索)
const response = await listRawMaterialWithBom({
pageNum: 1,
pageSize: 20,
rawMaterialName: searchQuery,
specification: searchQuery // 同时传入,后端会使用 OR 条件
});
if (response.code === 200) {
this.rawMaterialList = response.rows || [];
}
} else if (this.targetCoil.itemType === 'product') {
// 后端搜索产品(支持名称或规格模糊搜索)
const response = await listProductWithBom({
pageNum: 1,
pageSize: 20,
productName: searchQuery,
specification: searchQuery // 同时传入,后端会使用 OR 条件
});
if (response.code === 200) {
this.productList = response.rows || [];
}
}
} catch (error) {
console.error('搜索物品失败', error);
this.$message.error('搜索失败,请重试');
} finally {
this.itemSearchLoading = false;
}
},
// 添加源卷
addSourceCoil() {
this.sourceCoils.push({
@@ -665,44 +561,6 @@ export default {
}
},
// 选择钢卷
selectCoil(index) {
this.currentSelectIndex = index;
this.coilSelectorVisible = true;
},
// 钢卷选择回调
handleCoilSelect(coil) {
const index = this.currentSelectIndex;
this.$set(this.sourceCoils, index, {
coilId: coil.coilId,
enterCoilNo: coil.enterCoilNo || '',
currentCoilNo: coil.currentCoilNo || '',
itemType: coil.itemType,
itemId: coil.itemId,
materialType: coil.materialType,
warehouseName: coil.warehouseName || '',
actualWarehouseName: coil.actualWarehouseName || '',
materialName: coil.materialName || '',
productName: coil.productName || '',
specification: coil.rawMaterial?.specification || coil.product?.specification || '',
grossWeight: coil.grossWeight || null,
netWeight: coil.netWeight || null,
length: coil.length || null,
bomItems: coil.bomItemList || []
});
// 如果是第一个源卷,自动填充目标卷信息
if (index === 0) {
this.targetCoil.itemType = coil.itemType;
this.targetCoil.itemId = coil.itemId;
this.targetCoil.warehouseId = coil.warehouseId;
// this.targetCoil.actualWarehouseId = coil.actualWarehouseId;
}
this.$message.success('钢卷选择成功');
},
// 保存合卷
async handleSave() {
// 验证源卷数量
@@ -815,6 +673,12 @@ export default {
// 取消操作
handleCancel() {
console.log('取消合卷操作', this.$tab);
this.$router.back();
},
// closePage 关闭当前页面
closePage() {
this.$router.back();
}
}

View File

@@ -41,10 +41,6 @@
<span class="label">班组</span>
<span class="value">{{ motherCoil.team || '—' }}</span>
</div>
<div class="coil-info-row" v-if="motherCoil.materialName || motherCoil.productName">
<span class="label">物料名称</span>
<span class="value">{{ motherCoil.materialName || motherCoil.productName || '—' }}</span>
</div>
<div class="coil-info-row">
<span class="label">毛重</span>
<span class="value">{{ motherCoil.grossWeight ? motherCoil.grossWeight + ' t' : '—' }}</span>
@@ -53,17 +49,26 @@
<span class="label">净重</span>
<span class="value">{{ motherCoil.netWeight ? motherCoil.netWeight + ' t' : '—' }}</span>
</div>
<!-- 参数参数展示 -->
<template v-if="motherCoil.bomItems && motherCoil.bomItems.length > 0">
<el-divider content-position="left" style="margin: 15px 0 10px;">参数信息</el-divider>
<div class="bom-params">
<div class="param-item" v-for="(param, index) in motherCoil.bomItems" :key="index">
<span class="param-name">{{ param.attrKey }}</span>
<span class="param-value">{{ param.attrValue }}</span>
</div>
</div>
</template>
<div class="coil-info-row">
<span class="label">长度</span>
<span class="value">{{ motherCoil.length ? motherCoil.length + ' m' : '—' }}</span>
</div>
<div class="coil-info-row" v-if="motherCoil.materialName || motherCoil.productName">
<span class="label">物料名称</span>
<span class="value">{{ motherCoil.materialName || motherCoil.productName || '—' }}</span>
</div>
<div class="coil-info-row">
<span class="label">规格</span>
<span class="value">{{ motherCoil.itemSpecification || '—' }}</span>
</div>
<div class="coil-info-row">
<span class="label">材质</span>
<span class="value">{{ motherCoil.itemMaterial || '—' }}</span>
</div>
<div class="coil-info-row">
<span class="label">厂家</span>
<span class="value">{{ motherCoil.itemManufacturer || '—' }}</span>
</div>
</div>
</div>
</div>
@@ -86,7 +91,7 @@
<!-- 右侧子卷列表 -->
<div class="flow-right">
<div class="flow-section-title">
<span>子卷列表</span>
<span>子卷列表 {{ splitList.length }} </span>
<div>
<el-button v-if="!readonly" type="text" size="mini" @click="copyToAllSubCoils"
icon="el-icon-document-copy">复制到全部</el-button>
@@ -124,18 +129,18 @@
<!-- 物品类型由材料类型自动决定不显示选择框 -->
<el-form-item :label="getItemLabel(item.materialType)">
<raw-material-select v-if="item.materialType === '原料'"
v-model="item.itemId" placeholder="请选择原料" style="width: 100%" clearable
:disabled="readonly || !item.materialType" />
<raw-material-select v-if="item.materialType === '原料'" v-model="item.itemId" placeholder="请选择原料"
style="width: 100%" clearable :disabled="readonly || !item.materialType" />
<product-select v-else-if="item.materialType === '成品'" v-model="item.itemId" placeholder="请选择成品"
style="width: 100%" clearable :disabled="readonly || !item.materialType" />
<div v-else>请先选择物料类型</div>
</el-form-item>
<el-form-item label="质量状态" prop="qualityStatus">
<el-form-item label="质量状态" prop="qualityStatus">
<el-select v-model="item.qualityStatus" placeholder="请选择质量状态" style="width: 100%"
:disabled="readonly">
<el-option v-for="item in dict.type.coil_quality_status" :key="item.value" :label="item.label" :value="item.value" />
<el-option v-for="item in dict.type.coil_quality_status" :key="item.value" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
@@ -163,18 +168,18 @@
<el-form-item label="毛重(t)" required>
<el-input-number precision="3" :controls="false" v-model="item.grossWeight" placeholder="请输入毛重"
type="number" step="0.01" :disabled="readonly">
type="number" :step="0.01" :disabled="readonly">
<template slot="append"></template>
</el-input-number>
</el-form-item>
<el-form-item label="净重(t)" required>
<el-input-number precision="3" :controls="false" v-model="item.netWeight" placeholder="请输入净重"
type="number" step="0.01" :disabled="readonly">
type="number" :step="0.01" :disabled="readonly">
<template slot="append"></template>
</el-input-number>
</el-form-item>
<el-form-item label="长度(m)">
<el-input-number :controls="false" v-model="item.length" placeholder="请输入长度" type="number" step="0.01"
<el-input-number :controls="false" v-model="item.length" placeholder="请输入长度" type="number" :step="0.01"
:disabled="readonly">
<template slot="append"></template>
</el-input-number>
@@ -186,36 +191,22 @@
<ActualWarehouseSelect v-model="item.actualWarehouseId" placeholder="请选择真实库区" block
:disabled="readonly" />
</el-form-item> -->
<el-form-item label="备注">
<el-input v-model="item.remark" placeholder="请输入备注" :disabled="readonly"/>
<el-form-item label="备注">
<el-input v-model="item.remark" placeholder="请输入备注" :disabled="readonly" />
</el-form-item>
</el-form>
</div>
</div>
</div>
<!-- 汇总信息 -->
<div class="summary-card">
<div class="summary-item">
<span class="summary-label">子卷数量</span>
<span class="summary-value">{{ splitList.length }}</span>
</div>
</div>
</div>
</div>
<!-- 钢卷选择器 -->
<!-- <coil-selector :visible.sync="coilSelectorVisible" @select="handleCoilSelect" /> -->
</div>
</template>
<script>
import { getMaterialCoil, splitMaterialCoil } from '@/api/wms/coil';
import { listWarehouse } from '@/api/wms/warehouse';
import { listRawMaterialWithBom } from '@/api/wms/rawMaterial';
import { listProductWithBom } from '@/api/wms/product';
import { completeAction } from '@/api/wms/pendingAction';
import CoilSelector from '@/components/CoilSelector';
import ActualWarehouseSelect from "@/components/KLPService/ActualWarehouseSelect";
import RawMaterialSelect from "@/components/KLPService/RawMaterialSelect";
import ProductSelect from "@/components/KLPService/ProductSelect";
@@ -224,7 +215,6 @@ import WarehouseSelect from "@/components/KLPService/WarehouseSelect";
export default {
name: 'SplitCoil',
components: {
CoilSelector,
ActualWarehouseSelect,
RawMaterialSelect,
ProductSelect,
@@ -247,7 +237,10 @@ export default {
productName: '',
grossWeight: null,
netWeight: null,
bomItems: []
itemName: null,
itemManufacturer: null,
itemMaterial: null,
itemSpecification: null,
},
// 子卷列表
splitList: [
@@ -343,21 +336,6 @@ export default {
}
return '请先选择材料类型';
},
// 获取子卷的物品列表
getItemListForSplit(itemType) {
if (itemType === 'raw_material') {
return this.rawMaterialList.map(item => ({
id: item.rawMaterialId,
name: this.formatItemName(item)
}));
} else if (itemType === 'product') {
return this.productList.map(item => ({
id: item.productId,
name: this.formatItemName(item)
}));
}
return [];
},
// 格式化物品名称(添加规格和参数信息)
formatItemName(item) {
@@ -394,96 +372,6 @@ export default {
return displayName;
},
// 物品类型变化(已移除,改为实时搜索)
// handleItemTypeChange(index) {
// this.splitList[index].itemId = null;
// },
// 实时搜索子卷物品(后端搜索)
async searchItemsForSplit(query, index) {
const item = this.splitList[index];
const itemType = item.itemType;
if (!itemType) {
this.$message.warning('请先选择材料类型');
return;
}
// 如果没有输入,清空列表
if (!query || query.trim() === '') {
if (itemType === 'raw_material') {
this.rawMaterialList = [];
} else if (itemType === 'product') {
this.productList = [];
}
return;
}
try {
this.itemSearchLoading = true;
const searchQuery = query.trim();
if (itemType === 'raw_material') {
// 后端搜索原材料(支持名称或规格模糊搜索)
const response = await listRawMaterialWithBom({
pageNum: 1,
pageSize: 20,
rawMaterialName: searchQuery,
specification: searchQuery // 同时传入,后端会使用 OR 条件
});
if (response.code === 200) {
this.rawMaterialList = response.rows || [];
}
} else if (itemType === 'product') {
// 后端搜索产品(支持名称或规格模糊搜索)
const response = await listProductWithBom({
pageNum: 1,
pageSize: 20,
productName: searchQuery,
specification: searchQuery // 同时传入,后端会使用 OR 条件
});
if (response.code === 200) {
this.productList = response.rows || [];
}
}
} catch (error) {
console.error('搜索物品失败', error);
this.$message.error('搜索失败,请重试');
} finally {
this.itemSearchLoading = false;
}
},
// 已移除 loadAllItems改为实时搜索
// 已移除 loadItemListForSplit改为实时搜索
// 显示钢卷选择器
showCoilSelector() {
this.coilSelectorVisible = true;
},
// 钢卷选择回调
handleCoilSelect(coil) {
this.motherCoil = {
coilId: coil.coilId,
enterCoilNo: coil.enterCoilNo || '',
currentCoilNo: coil.currentCoilNo || '',
team: coil.team || '',
warehouseId: coil.warehouseId,
warehouseName: coil.warehouseName || '',
itemType: coil.itemType,
itemId: coil.itemId,
materialName: coil.materialName || '',
productName: coil.productName || '',
grossWeight: coil.grossWeight,
netWeight: coil.netWeight,
length: coil.length,
bomItems: coil.bomItemList || coil.bomItems || []
};
this.$message.success('母卷选择成功');
},
// 加载母卷信息
async loadMotherCoil(coilId) {
try {
@@ -506,7 +394,10 @@ export default {
grossWeight: data.grossWeight,
netWeight: data.netWeight,
length: data.length,
bomItems: data.bomItemList || data.bomItems || []
itemName: data?.rawMaterial?.rawMaterialName || data?.product?.productName || '',
itemManufacturer: data?.rawMaterial?.manufacturer || data?.product?.manufacturer || '',
itemMaterial: data?.rawMaterial?.material || data?.product?.material || '',
itemSpecification: data?.rawMaterial?.specification || data?.product?.specification || '',
};
}
} catch (error) {
@@ -678,19 +569,6 @@ export default {
if (!item.team) {
item.team = this.motherCoil.team;
}
// 不复制 itemType 和 itemId让它们由 materialType 自动决定
if (item.itemType) {
item.itemType = this.motherCoil.itemType;
}
if (item.itemId) {
item.itemId = this.motherCoil.itemId;
}
if (item.materialType) {
item.materialType = this.motherCoil.materialType;
}
});
// 不再预加载物品列表,改为实时搜索