Files
klp-oa/klp-ui/src/views/wms/coil/split.vue

1111 lines
31 KiB
Vue
Raw Normal View History

<template>
<div class="split-coil-container">
<!-- 顶部操作栏 -->
<div class="header-bar">
<div class="header-title">
<i class="el-icon-s-operation"></i>
2025-11-11 12:21:16 +08:00
<span>钢卷分条</span>
</div>
<div class="header-actions">
2025-11-11 12:21:16 +08:00
<el-button v-if="!readonly" type="primary" size="small" @click="handleSave" :loading="loading">保存分条</el-button>
2025-11-03 17:03:03 +08:00
<el-button size="small" @click="handleCancel" :disabled="loading">{{ readonly ? '返回' : '取消' }}</el-button>
</div>
</div>
<!-- 流程图区域 -->
<div class="flow-container">
<!-- 左侧母卷信息 -->
<div class="flow-left">
<div class="flow-section-title">
<span>母卷信息</span>
</div>
<div class="coil-card mother-coil">
<div class="coil-header">
<i class="el-icon-s-grid"></i>
2025-11-03 17:03:03 +08:00
<span class="coil-title">钢卷信息</span>
</div>
<div class="coil-body">
<div class="coil-info-row">
2025-11-03 17:03:03 +08:00
<span class="label">入场钢卷号</span>
<span class="value">{{ motherCoil.enterCoilNo || '—' }}</span>
</div>
<div class="coil-info-row">
2025-11-03 17:03:03 +08:00
<span class="label">当前钢卷号</span>
<span class="value">{{ motherCoil.currentCoilNo || '—' }}</span>
</div>
<div class="coil-info-row">
2025-11-03 17:03:03 +08:00
<span class="label">当前库区</span>
<span class="value">{{ motherCoil.warehouseName || '未分配' }}</span>
</div>
<div class="coil-info-row">
2025-11-03 17:03:03 +08:00
<span class="label">班组</span>
<span class="value">{{ motherCoil.team || '—' }}</span>
</div>
2025-11-03 17:03:03 +08:00
<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>
</div>
<div class="coil-info-row">
<span class="label">净重</span>
<span class="value">{{ motherCoil.netWeight ? motherCoil.netWeight + ' t' : '—' }}</span>
</div>
<!-- BOM参数展示 -->
<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>
</div>
</div>
<!-- 中间流程箭头 -->
<div class="flow-middle">
<div class="flow-arrow-container">
<div class="arrow-line" v-for="(item, index) in splitList" :key="index">
<div class="arrow-start"></div>
<div class="arrow-body"></div>
<div class="arrow-end"></div>
</div>
</div>
<div class="flow-label">
<i class="el-icon-d-arrow-right"></i>
<span>分割</span>
</div>
</div>
<!-- 右侧子卷列表 -->
<div class="flow-right">
<div class="flow-section-title">
<span>子卷列表</span>
2025-11-03 17:03:03 +08:00
<div>
<el-button v-if="!readonly" type="text" size="mini" @click="copyToAllSubCoils" icon="el-icon-document-copy">复制到全部</el-button>
<el-button v-if="!readonly" type="text" size="mini" @click="addSplitItem" icon="el-icon-plus">添加子卷</el-button>
</div>
</div>
2025-11-03 17:03:03 +08:00
<div class="split-list">
<div class="sub-coil-card" v-for="(item, index) in splitList" :key="index">
<div class="sub-coil-header">
<span class="sub-coil-number">{{ index + 1 }}</span>
2025-11-03 17:03:03 +08:00
<el-button
v-if="!readonly"
type="text"
size="mini"
icon="el-icon-delete"
@click="removeSplitItem(index)"
class="btn-remove"
></el-button>
</div>
<div class="sub-coil-body">
2025-11-03 17:03:03 +08:00
<el-form size="small" label-width="90px">
<el-form-item label="卷号" required>
<el-input v-model="item.currentCoilNo" placeholder="输入子卷卷号" :disabled="readonly"></el-input>
</el-form-item>
<el-form-item label="班组" required>
<el-input v-model="item.team" placeholder="输入班组名称" :disabled="readonly"></el-input>
</el-form-item>
2025-11-11 12:21:16 +08:00
<el-form-item label="材料类型" required>
2025-11-11 14:21:46 +08:00
<el-select
v-model="item.materialType"
placeholder="请选择材料类型"
style="width: 100%"
:disabled="readonly"
@change="handleMaterialTypeChange(item, index)">
2025-11-11 12:21:16 +08:00
<el-option label="原料" value="原料" />
<el-option label="成品" value="成品" />
<el-option label="废品" value="废品" />
</el-select>
</el-form-item>
<!-- 物品类型由材料类型自动决定不显示选择框 -->
<el-form-item
:label="getItemLabel(item.materialType)"
:required="item.materialType !== '废品'">
<el-select
v-model="item.itemId"
:placeholder="getItemPlaceholder(item.materialType)"
filterable
remote
:remote-method="(query) => searchItemsForSplit(query, index)"
:loading="itemSearchLoading"
style="width: 100%"
:disabled="readonly || !item.materialType"
>
<el-option
v-for="option in getItemListForSplit(item.itemType)"
:key="option.id"
:label="option.name"
:value="option.id"
/>
</el-select>
</el-form-item>
2025-11-03 17:03:03 +08:00
<el-form-item label="毛重(t)" required>
<el-input
v-model.number="item.grossWeight"
placeholder="请输入毛重"
type="number"
step="0.01"
:disabled="readonly"
>
<template slot="append"></template>
</el-input>
</el-form-item>
<el-form-item label="净重(t)" required>
<el-input
v-model.number="item.netWeight"
placeholder="请输入净重"
type="number"
step="0.01"
:disabled="readonly"
>
<template slot="append"></template>
</el-input>
</el-form-item>
<el-form-item label="逻辑库区" required>
2025-11-03 17:03:03 +08:00
<el-select
v-model="item.warehouseId"
placeholder="请选择逻辑库区"
2025-11-03 17:03:03 +08:00
style="width: 100%"
filterable
:disabled="readonly"
>
<el-option
v-for="warehouse in warehouseList"
:key="warehouse.warehouseId"
:label="warehouse.warehouseName"
:value="warehouse.warehouseId"
/>
</el-select>
</el-form-item>
<el-form-item label="真实库区" required>
<ActualWarehouseSelect
v-model="item.actualWarehouseId"
placeholder="请选择真实库区"
style="width: 100%"
filterable
: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';
2025-11-03 17:03:03 +08:00
import { listWarehouse } from '@/api/wms/warehouse';
import { listRawMaterial } from '@/api/wms/rawMaterial';
import { listProduct } from '@/api/wms/product';
import { completeAction } from '@/api/wms/pendingAction';
import CoilSelector from '@/components/CoilSelector';
import ActualWarehouseSelect from "@/components/KLPService/ActualWarehouseSelect";
export default {
name: 'SplitCoil',
components: {
CoilSelector,
2025-11-11 12:21:16 +08:00
ActualWarehouseSelect
},
data() {
return {
// 母卷信息
motherCoil: {
coilId: null,
2025-11-03 17:03:03 +08:00
enterCoilNo: '',
currentCoilNo: '',
2025-11-03 17:03:03 +08:00
team: '',
warehouseId: null,
2025-11-03 17:03:03 +08:00
warehouseName: '',
itemType: null,
itemId: null,
2025-11-03 17:03:03 +08:00
materialName: '',
productName: '',
grossWeight: null,
netWeight: null,
bomItems: []
},
// 子卷列表
splitList: [
2025-11-03 17:03:03 +08:00
{
currentCoilNo: '',
team: '',
2025-11-11 12:21:16 +08:00
materialType: null,
2025-11-03 17:03:03 +08:00
itemType: null,
itemId: null,
grossWeight: null,
netWeight: null,
warehouseId: null,
actualWarehouseId: null
2025-11-03 17:03:03 +08:00
}
],
loading: false,
// 钢卷选择器可见性
2025-11-03 17:03:03 +08:00
coilSelectorVisible: false,
// 库区列表
warehouseList: [],
// 原材料和产品列表
rawMaterialList: [],
productList: [],
2025-11-11 16:21:45 +08:00
// 原始完整列表备份(用于搜索过滤)
allRawMaterials: [],
allProducts: [],
2025-11-03 17:03:03 +08:00
itemSearchLoading: false,
// 只读模式
readonly: false,
// 待操作ID
actionId: null
};
},
computed: {
},
2025-11-03 17:03:03 +08:00
async created() {
// 先加载库区列表
await this.loadWarehouses();
2025-11-11 12:21:16 +08:00
// 🔥 页面加载时直接加载所有原料和产品列表
await this.loadAllItems();
// 从路由参数获取coilId、actionId和readonly
const coilId = this.$route.query.coilId;
const actionId = this.$route.query.actionId;
2025-11-03 17:03:03 +08:00
const readonly = this.$route.query.readonly;
if (coilId) {
2025-11-03 17:03:03 +08:00
await this.loadMotherCoil(coilId);
}
// 保存待操作ID
if (actionId) {
this.actionId = actionId;
}
2025-11-03 17:03:03 +08:00
// 设置只读模式
if (readonly === 'true' || readonly === true) {
this.readonly = true;
}
},
methods: {
2025-11-11 14:21:46 +08:00
// 处理材料类型变化
handleMaterialTypeChange(item, index) {
// 清空物品选择
this.$set(item, 'itemId', null);
2025-11-11 16:21:45 +08:00
// 根据材料类型设置物品类型并恢复完整列表
2025-11-11 14:21:46 +08:00
if (item.materialType === '成品') {
this.$set(item, 'itemType', 'product');
2025-11-11 16:21:45 +08:00
// 恢复完整产品列表
this.productList = [...this.allProducts];
2025-11-11 14:21:46 +08:00
} else if (item.materialType === '原料' || item.materialType === '废品') {
this.$set(item, 'itemType', 'raw_material');
2025-11-11 16:21:45 +08:00
// 恢复完整原料列表
this.rawMaterialList = [...this.allRawMaterials];
2025-11-11 14:21:46 +08:00
}
},
2025-11-11 12:21:16 +08:00
// 动态获取标签
getItemLabel(materialType) {
if (materialType === '成品') {
return '产品类型';
} else if (materialType === '原料' || materialType === '废品') {
return '原料类型';
}
return '物品';
},
// 动态获取占位符
getItemPlaceholder(materialType) {
if (materialType === '成品') {
return '请选择产品类型';
} else if (materialType === '原料') {
return '请选择原料类型';
} else if (materialType === '废品') {
return '请选择原料类型(非必填)';
}
return '请先选择材料类型';
},
2025-11-03 17:03:03 +08:00
// 获取子卷的物品列表
getItemListForSplit(itemType) {
if (itemType === 'raw_material') {
2025-11-11 14:52:41 +08:00
return this.rawMaterialList.map(item => ({
2025-11-03 17:03:03 +08:00
id: item.rawMaterialId,
name: this.formatItemName(item)
2025-11-03 17:03:03 +08:00
}));
} else if (itemType === 'product') {
2025-11-11 14:52:41 +08:00
return this.productList.map(item => ({
2025-11-03 17:03:03 +08:00
id: item.productId,
name: this.formatItemName(item)
2025-11-03 17:03:03 +08:00
}));
}
return [];
},
// 格式化物品名称添加规格和BOM信息
formatItemName(item) {
if (!item) return '';
// 获取名称(原材料或产品)
const name = item.rawMaterialName || item.productName || '';
if (!name) return '';
let displayName = name;
const specs = [];
// 1. 优先显示规格从对象的specification字段
if (item.specification) {
specs.push(item.specification);
}
// 2. 添加BOM参数最多2个
if (item.bomItems && item.bomItems.length > 0) {
const bomParams = item.bomItems
.filter(bomItem => bomItem.attrKey && bomItem.attrValue)
.slice(0, 2); // 最多2个BOM参数
bomParams.forEach(param => {
specs.push(`${param.attrKey}:${param.attrValue}`);
});
}
// 3. 拼接成最终格式
if (specs.length > 0) {
displayName += `${specs.join(' ')}`;
}
return displayName;
},
2025-11-03 17:03:03 +08:00
// 物品类型变化
handleItemTypeChange(index) {
this.splitList[index].itemId = null;
this.loadItemListForSplit(this.splitList[index].itemType);
},
2025-11-11 16:21:45 +08:00
// 搜索子卷物品(前端过滤,支持名称和规格搜索)
2025-11-03 17:03:03 +08:00
async searchItemsForSplit(query, index) {
2025-11-11 12:21:16 +08:00
const item = this.splitList[index];
const itemType = item.itemType;
2025-11-03 17:03:03 +08:00
if (!itemType) {
2025-11-11 12:21:16 +08:00
this.$message.warning('请先选择材料类型');
2025-11-03 17:03:03 +08:00
return;
}
2025-11-11 16:21:45 +08:00
// 如果没有输入,恢复完整列表
if (!query || query.trim() === '') {
2025-11-03 17:03:03 +08:00
if (itemType === 'raw_material') {
2025-11-11 16:21:45 +08:00
this.rawMaterialList = [...this.allRawMaterials];
2025-11-03 17:03:03 +08:00
} else if (itemType === 'product') {
2025-11-11 16:21:45 +08:00
this.productList = [...this.allProducts];
2025-11-03 17:03:03 +08:00
}
2025-11-11 16:21:45 +08:00
return;
}
// 前端过滤:在已加载的数据中搜索
const searchQuery = query.toLowerCase().trim();
if (itemType === 'raw_material') {
// 从备份列表中过滤原材料
this.rawMaterialList = this.allRawMaterials.filter(item => {
// 搜索名称
const nameMatch = item.rawMaterialName && item.rawMaterialName.toLowerCase().includes(searchQuery);
// 搜索规格
const specMatch = item.specification && item.specification.toLowerCase().includes(searchQuery);
// 搜索 BOM 参数
const bomMatch = item.bomItems && item.bomItems.some(bom =>
(bom.attrKey && bom.attrKey.toLowerCase().includes(searchQuery)) ||
(bom.attrValue && bom.attrValue.toLowerCase().includes(searchQuery))
);
return nameMatch || specMatch || bomMatch;
});
} else if (itemType === 'product') {
// 从备份列表中过滤产品
this.productList = this.allProducts.filter(item => {
// 搜索名称
const nameMatch = item.productName && item.productName.toLowerCase().includes(searchQuery);
// 搜索规格
const specMatch = item.specification && item.specification.toLowerCase().includes(searchQuery);
// 搜索 BOM 参数
const bomMatch = item.bomItems && item.bomItems.some(bom =>
(bom.attrKey && bom.attrKey.toLowerCase().includes(searchQuery)) ||
(bom.attrValue && bom.attrValue.toLowerCase().includes(searchQuery))
);
return nameMatch || specMatch || bomMatch;
});
2025-11-03 17:03:03 +08:00
}
},
2025-11-11 12:21:16 +08:00
// 页面加载时一次性加载所有原料和产品列表
async loadAllItems() {
try {
// 同时加载原料和产品
const [rawMaterialRes, productRes] = await Promise.all([
listRawMaterial({ pageNum: 1, pageSize: 99999, withBom: true }),
listProduct({ pageNum: 1, pageSize: 99999, withBom: true })
]);
if (rawMaterialRes.code === 200) {
this.rawMaterialList = rawMaterialRes.rows || [];
2025-11-11 16:21:45 +08:00
this.allRawMaterials = rawMaterialRes.rows || []; // 保存完整备份
2025-11-11 12:21:16 +08:00
}
if (productRes.code === 200) {
this.productList = productRes.rows || [];
2025-11-11 16:21:45 +08:00
this.allProducts = productRes.rows || []; // 保存完整备份
2025-11-11 12:21:16 +08:00
}
} catch (error) {
2025-11-11 14:52:41 +08:00
console.error('加载物品列表失败', error);
2025-11-11 12:21:16 +08:00
}
},
2025-11-03 17:03:03 +08:00
// 加载子卷物品列表
async loadItemListForSplit(itemType) {
2025-11-11 12:21:16 +08:00
if (!itemType) {
return;
}
2025-11-03 17:03:03 +08:00
try {
this.itemSearchLoading = true;
if (itemType === 'raw_material') {
const response = await listRawMaterial({
pageNum: 1,
pageSize: 100,
withBom: true
});
2025-11-03 17:03:03 +08:00
if (response.code === 200) {
this.rawMaterialList = response.rows || [];
}
} else if (itemType === 'product') {
const response = await listProduct({
pageNum: 1,
pageSize: 100,
withBom: true
});
2025-11-03 17:03:03 +08:00
if (response.code === 200) {
this.productList = response.rows || [];
}
}
} catch (error) {
2025-11-11 12:21:16 +08:00
console.error('split.vue 加载物品列表失败', error);
2025-11-03 17:03:03 +08:00
} finally {
this.itemSearchLoading = false;
}
},
// 显示钢卷选择器
showCoilSelector() {
this.coilSelectorVisible = true;
},
// 钢卷选择回调
handleCoilSelect(coil) {
this.motherCoil = {
coilId: coil.coilId,
2025-11-03 17:03:03 +08:00
enterCoilNo: coil.enterCoilNo || '',
currentCoilNo: coil.currentCoilNo || '',
2025-11-03 17:03:03 +08:00
team: coil.team || '',
warehouseId: coil.warehouseId,
2025-11-03 17:03:03 +08:00
warehouseName: coil.warehouseName || '',
itemType: coil.itemType,
itemId: coil.itemId,
2025-11-03 17:03:03 +08:00
materialName: coil.materialName || '',
productName: coil.productName || '',
grossWeight: coil.grossWeight,
netWeight: coil.netWeight,
bomItems: coil.bomItemList || coil.bomItems || []
};
this.$message.success('母卷选择成功');
},
// 加载母卷信息
async loadMotherCoil(coilId) {
try {
this.loading = true;
const response = await getMaterialCoil(coilId);
if (response.code === 200 && response.data) {
const data = response.data;
this.motherCoil = {
coilId: data.coilId,
2025-11-03 17:03:03 +08:00
enterCoilNo: data.enterCoilNo || '',
currentCoilNo: data.currentCoilNo || '',
2025-11-03 17:03:03 +08:00
team: data.team || '',
warehouseId: data.warehouseId,
2025-11-03 17:03:03 +08:00
warehouseName: data.warehouseName || (data.warehouse ? data.warehouse.warehouseName : ''),
itemType: data.itemType,
itemId: data.itemId,
2025-11-03 17:03:03 +08:00
materialName: data.materialName || (data.rawMaterial ? data.rawMaterial.rawMaterialName : ''),
productName: data.productName || (data.product ? data.product.productName : ''),
grossWeight: data.grossWeight,
netWeight: data.netWeight,
bomItems: data.bomItemList || data.bomItems || []
};
}
} catch (error) {
this.$message.error('加载母卷信息失败');
console.error(error);
} finally {
this.loading = false;
}
},
2025-11-03 17:03:03 +08:00
// 加载库区列表
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);
}
},
// 添加子卷
addSplitItem() {
this.splitList.push({
currentCoilNo: '',
2025-11-03 17:03:03 +08:00
team: '',
2025-11-11 12:21:16 +08:00
materialType: null,
2025-11-03 17:03:03 +08:00
itemType: null,
itemId: null,
grossWeight: null,
netWeight: null,
warehouseId: null,
actualWarehouseId: null
});
},
2025-11-03 17:03:03 +08:00
// 删除子卷
removeSplitItem(index) {
if (this.splitList.length > 1) {
this.splitList.splice(index, 1);
} else {
this.$message.warning('至少保留一个子卷');
}
},
2025-11-03 17:03:03 +08:00
2025-11-11 12:21:16 +08:00
// 保存分条
async handleSave() {
// 验证母卷信息
if (!this.motherCoil.coilId) {
this.$message.error('请先选择母卷');
return;
}
// 验证子卷数量
if (this.splitList.length < 1) {
this.$message.error('至少需要一个子卷');
return;
}
// 验证子卷信息
for (let i = 0; i < this.splitList.length; i++) {
const item = this.splitList[i];
if (!item.currentCoilNo || item.currentCoilNo.trim() === '') {
this.$message.error(`${i + 1}个子卷的卷号不能为空`);
return;
}
2025-11-03 17:03:03 +08:00
if (!item.team || item.team.trim() === '') {
this.$message.error(`${i + 1}个子卷的班组不能为空`);
return;
}
if (!item.itemType) {
this.$message.error(`${i + 1}个子卷的物品类型不能为空`);
return;
}
if (!item.itemId) {
this.$message.error(`${i + 1}个子卷的物品不能为空`);
return;
}
if (item.grossWeight === null || item.grossWeight === undefined || item.grossWeight === '') {
this.$message.error(`${i + 1}个子卷的毛重不能为空`);
return;
}
if (item.netWeight === null || item.netWeight === undefined || item.netWeight === '') {
this.$message.error(`${i + 1}个子卷的净重不能为空`);
return;
}
if (!item.warehouseId) {
2025-11-03 17:03:03 +08:00
this.$message.error(`${i + 1}个子卷的目标库区不能为空`);
return;
}
}
const loadingInstance = this.$loading({
lock: true,
2025-11-11 12:21:16 +08:00
text: '正在分条,请稍后...',
background: 'rgba(0, 0, 0, 0.7)'
})
try {
this.loading = true;
2025-11-11 12:21:16 +08:00
// 构造分条数据
const splitData = {
coilId: this.motherCoil.coilId,
2025-11-03 17:03:03 +08:00
enterCoilNo: this.motherCoil.enterCoilNo, // 入场钢卷号(必填)
currentCoilNo: this.motherCoil.currentCoilNo,
2025-11-11 12:21:16 +08:00
hasMergeSplit: 1, // 1表示分条
newCoils: this.splitList.map(item => ({
2025-11-03 17:03:03 +08:00
enterCoilNo: this.motherCoil.enterCoilNo, // 子卷继承母卷的入场钢卷号
currentCoilNo: item.currentCoilNo,
2025-11-03 17:03:03 +08:00
team: item.team,
2025-11-11 12:21:16 +08:00
materialType: item.materialType,
2025-11-03 17:03:03 +08:00
itemType: item.itemType || this.motherCoil.itemType,
itemId: item.itemId || this.motherCoil.itemId,
grossWeight: item.grossWeight,
netWeight: item.netWeight,
warehouseId: item.warehouseId,
actualWarehouseId: item.actualWarehouseId,
2025-11-03 17:03:03 +08:00
hasMergeSplit: 1
}))
};
const response = await splitMaterialCoil(splitData);
if (response.code === 200) {
2025-11-11 12:21:16 +08:00
this.$message.success('分条保存成功');
// 如果是从待操作列表进来的,标记操作为完成
if (this.actionId) {
await completeAction(this.actionId);
}
// 延迟返回,让用户看到成功提示
setTimeout(() => {
this.$router.back();
}, 1000);
} else {
2025-11-11 12:21:16 +08:00
this.$message.error(response.msg || '分条保存失败');
}
} catch (error) {
2025-11-11 12:21:16 +08:00
this.$message.error('分条保存失败');
console.error(error);
} finally {
this.loading = false;
loadingInstance.close();
}
},
2025-11-03 17:03:03 +08:00
// 取消操作
handleCancel() {
this.$router.back();
2025-11-03 17:03:03 +08:00
},
// 复制到全部子卷
copyToAllSubCoils() {
if (!this.motherCoil.coilId) {
this.$message.warning('请先加载母卷信息');
return;
}
// 复制到所有子卷
this.splitList.forEach((item, index) => {
// 自动生成卷号:母卷号-1, 母卷号-2, 母卷号-3...
if (!item.currentCoilNo) {
item.currentCoilNo = `${this.motherCoil.currentCoilNo}-${index + 1}`;
}
// 复制班组
if (!item.team) {
item.team = this.motherCoil.team;
}
2025-11-11 12:21:16 +08:00
// 不复制 itemType 和 itemId让它们由 materialType 自动决定
2025-11-03 17:03:03 +08:00
});
// 加载物品列表
if (this.motherCoil.itemType) {
this.loadItemListForSplit(this.motherCoil.itemType);
}
this.$message.success('已复制到所有子卷');
}
}
};
</script>
<style scoped lang="scss">
.split-coil-container {
padding: 20px;
background: #f5f7fa;
min-height: calc(100vh - 84px);
}
/* 顶部操作栏 */
.header-bar {
display: flex;
justify-content: space-between;
align-items: center;
background: #fff;
padding: 16px 20px;
margin-bottom: 20px;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.header-title {
font-size: 18px;
font-weight: 500;
color: #303133;
display: flex;
align-items: center;
gap: 8px;
2025-11-03 17:03:03 +08:00
i {
color: #0066cc;
font-size: 20px;
}
}
/* 流程图容器 */
.flow-container {
display: flex;
gap: 40px;
background: #fff;
padding: 30px;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
min-height: 600px;
}
.flow-left {
flex: 0 0 300px;
}
.flow-middle {
flex: 0 0 120px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: relative;
}
.flow-right {
flex: 1;
min-width: 0;
}
.flow-section-title {
font-size: 16px;
font-weight: 500;
color: #303133;
margin-bottom: 16px;
padding-left: 12px;
border-left: 4px solid #0066cc;
display: flex;
justify-content: space-between;
align-items: center;
2025-11-03 17:03:03 +08:00
.el-button--text {
font-size: 12px;
}
}
/* 母卷卡片 */
.mother-coil {
border: 2px solid #0066cc;
box-shadow: 0 4px 12px rgba(0, 102, 204, 0.15);
}
.coil-card {
background: #fff;
border: 1px solid #e4e7ed;
border-radius: 8px;
overflow: hidden;
}
.coil-header {
background: #0066cc;
color: #fff;
padding: 16px 20px;
display: flex;
align-items: center;
gap: 10px;
2025-11-03 17:03:03 +08:00
i {
font-size: 20px;
}
2025-11-03 17:03:03 +08:00
.coil-title {
flex: 1;
font-size: 16px;
font-weight: 600;
}
}
.coil-body {
padding: 20px;
}
.coil-info-row {
display: flex;
2025-11-03 17:03:03 +08:00
align-items: flex-start;
margin-bottom: 12px;
2025-11-03 17:03:03 +08:00
&:last-child {
margin-bottom: 0;
}
2025-11-03 17:03:03 +08:00
.label {
color: #909399;
font-size: 14px;
2025-11-03 17:03:03 +08:00
min-width: 100px;
flex-shrink: 0;
}
2025-11-03 17:03:03 +08:00
.value {
color: #303133;
font-size: 14px;
font-weight: 500;
2025-11-03 17:03:03 +08:00
flex: 1;
word-break: break-all;
&.highlight {
color: #0066cc;
font-size: 16px;
font-weight: 600;
}
}
}
2025-11-03 17:03:03 +08:00
/* BOM参数展示 */
.bom-params {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 10px;
margin-top: 10px;
}
.param-item {
display: flex;
align-items: center;
font-size: 13px;
.param-name {
color: #909399;
min-width: 80px;
}
.param-value {
color: #303133;
font-weight: 500;
}
}
/* 流程箭头 */
.flow-arrow-container {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 100%;
}
.arrow-line {
position: relative;
height: 3px;
margin: 20px 0;
display: flex;
align-items: center;
}
.arrow-start {
width: 8px;
height: 8px;
background: #0066cc;
border-radius: 50%;
}
.arrow-body {
flex: 1;
height: 3px;
background: #0066cc;
}
.arrow-end {
width: 0;
height: 0;
border-left: 12px solid #0066cc;
border-top: 8px solid transparent;
border-bottom: 8px solid transparent;
}
.flow-label {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background: #ecf5ff;
color: #0066cc;
padding: 8px 16px;
border-radius: 20px;
font-size: 14px;
font-weight: 500;
display: flex;
align-items: center;
gap: 6px;
border: 1px solid #d9ecff;
}
/* 子卷列表 */
.split-list {
max-height: 500px;
overflow-y: auto;
margin-bottom: 20px;
padding-right: 10px;
2025-11-03 17:03:03 +08:00
&::-webkit-scrollbar {
width: 6px;
}
2025-11-03 17:03:03 +08:00
&::-webkit-scrollbar-thumb {
background: #dcdfe6;
border-radius: 3px;
}
}
.sub-coil-card {
background: #fff;
border: 1px solid #e4e7ed;
border-radius: 8px;
margin-bottom: 16px;
transition: all 0.3s;
2025-11-03 17:03:03 +08:00
&:hover {
border-color: #0066cc;
box-shadow: 0 2px 8px rgba(0, 102, 204, 0.15);
}
}
.sub-coil-header {
background: #f5f7fa;
padding: 12px 16px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #e4e7ed;
}
.sub-coil-number {
font-size: 16px;
font-weight: 600;
color: #0066cc;
width: 32px;
height: 32px;
border-radius: 50%;
background: #ecf5ff;
display: flex;
align-items: center;
justify-content: center;
}
.btn-remove {
color: #f56c6c;
padding: 0;
2025-11-03 17:03:03 +08:00
&:hover {
color: #f56c6c;
}
}
.sub-coil-body {
padding: 16px;
}
/* 汇总卡片 */
.summary-card {
background: #ecf5ff;
border: 1px solid #d9ecff;
border-radius: 8px;
padding: 16px 20px;
display: flex;
justify-content: space-around;
}
.summary-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
}
.summary-label {
font-size: 13px;
color: #606266;
}
.summary-value {
font-size: 20px;
font-weight: 600;
color: #0066cc;
2025-11-03 17:03:03 +08:00
&.error {
color: #f56c6c;
}
}
2025-11-03 17:03:03 +08:00
// 优化按钮文字颜色
// 实心primary按钮白色文字
::v-deep .el-button--primary.el-button--small:not(.is-plain) {
color: #fff;
}
// plain按钮和text按钮蓝色文字
::v-deep .el-button--primary.el-button--small.is-plain,
::v-deep .el-button--text {
color: #409eff;
&:hover {
color: #66b1ff;
}
}
// 修复数字输入框的上下箭头溢出
.sub-coil-body {
::v-deep input[type="number"] {
appearance: textfield;
-moz-appearance: textfield;
&::-webkit-outer-spin-button,
&::-webkit-inner-spin-button {
-webkit-appearance: none;
appearance: none;
margin: 0;
}
}
}
</style>