feat(分卷): 实现镀锌工序特殊分卷功能

新增特殊分卷功能,包括分步分条界面、API接口及状态管理。主要修改:
1. 添加分步分条组件,支持新增、编辑、删除分条
2. 扩展分卷API接口,包括开始/完成/取消特殊分卷
3. 优化操作按钮加载状态和错误处理
4. 调整界面布局和样式
This commit is contained in:
砂糖
2026-01-22 16:52:07 +08:00
parent 6f83ae7dae
commit 8adad71acd
7 changed files with 761 additions and 67 deletions

View File

@@ -238,4 +238,68 @@ export function restoreMaterialCoil(coilId) {
url: '/wms/materialCoil/rollback/' + coilId,
method: 'post'
})
}
}
/**
* 开始分条,锁定钢卷
*/
export function startSpecialSplit(coilId) {
if (!coilId) {
return Promise.reject(new Error('coilId is required'))
}
return request({
url: '/wms/materialCoil/specialSplit/start',
method: 'post',
params: {
coilId
}
})
}
/**
* 创建一个分条
*/
export function createSpecialChild(parentCoilId, pendingActionId, data) {
return request({
url: '/wms/materialCoil/specialSplit/createChild',
method: 'post',
data: data,
params: {
parentCoilId,
pendingActionId
}
})
}
/**
* 完成分卷操作
*/
export function completeSpecialSplit(pendingActionId) {
if (!pendingActionId) {
return Promise.reject(new Error('pendingActionId is required'))
}
return request({
url: '/wms/materialCoil/specialSplit/complete',
method: 'post',
params: {
pendingActionId
}
})
}
/**
* 取消镀锌分卷
*/
export function cancelSpecialSplit(pendingActionId) {
if (!pendingActionId) {
return Promise.reject(new Error('pendingActionId is required'))
}
return request({
url: '/wms/materialCoil/specialSplit/cancel',
method: 'post',
params: {
pendingActionId
}
})
}

View File

@@ -1359,6 +1359,7 @@ body {
border-bottom: 1px solid $--border-color-lighter;
// background: $--metal-gradient-dark;
color: $--color-text-primary; // 白色标题
margin-bottom: 0px;
font-weight: 600;
font-size: 14px;
}

View File

@@ -17,7 +17,7 @@ export default {
components: { iframeToggle },
computed: {
cachedViews() {
console.log(this.$store.state.tagsView.cachedViews)
// console.log(this.$store.state.tagsView.cachedViews)
return this.$store.state.tagsView.cachedViews
},
key() {

View File

@@ -415,6 +415,7 @@ export default {
// 特殊处理:发货和移库操作不需要跳转
if (actionType === 4 || actionType === 5 || actionType === 401 || actionType === 402) {
this.$message.info(actionType === 4 ? '发货操作已在移动端完成' : '移库操作已在移动端完成');
this.buttonLoading = false;
return;
}
@@ -429,13 +430,19 @@ export default {
else if (actionType == 200) {
path = '/wms/merge';
}
else if (actionType < 100) {
path = '/wms/typing';
}
// 其他操作类型
else {
path = '/wms/typing';
this.$message.error('特殊操作请到专门的页面进行处理');
this.buttonLoading = false;
return;
}
if (!path) {
this.$message.error('未知的操作类型: ' + row.actionType);
this.buttonLoading = false;
return;
}
@@ -462,7 +469,9 @@ export default {
}).catch(error => {
console.error('更新状态失败:', error);
this.$message.error('更新状态失败: ' + (error.message || error));
})
}).finally(() => {
this.buttonLoading = false;
});
},
/** 取消操作 */
handleCancel(row) {

View File

@@ -1,5 +1,5 @@
<template>
<DoPage :label="actionType" :tabs="tabs" />
<DoPage :label="actionType" :tabs="tabs" :useSpecialSplit="useSpecialSplit" />
</template>
<script>
@@ -14,6 +14,7 @@
return {
actionType: '分卷',
tabs: [],
useSpecialSplit: false,
}
},
watch: {
@@ -53,6 +54,10 @@
{value: '1988151132361519105', label: '镀铬成品库'},
],
}
if (this.actionType === '镀锌工序') {
this.useSpecialSplit = true
}
// 从map中获取默认的查询参数
const defaultWarehouseIds = map[this.actionType] || []
console.log(defaultWarehouseIds, 'defaultWarehouseIds')

View File

@@ -167,7 +167,8 @@
<i class="el-icon-view param-icon" @click="handlePreviewLabel(item)" title="查看标签"></i>
<!-- <el-button style="margin-left: 0px; padding: 4px !important;" type="text" size="mini" @click="handlePreviewLabel(item)" title="查看标签">预览</el-button> -->
<el-button style="margin-left: 0px; padding: 4px !important;" type="text" size="mini" @click="handlePrintLabel(item)" title="打印标签">打印</el-button>
<el-button v-loading="buttonLoading" style="margin-left: 0px; padding: 4px !important;" type="text"
size="mini" @click="handlePrintLabel(item)" title="打印标签">打印</el-button>
</div>
</div>
@@ -196,15 +197,15 @@
</div>
</div>
<el-button style="position: absolute; bottom: 10px; right: 10px;" type="success" icon="el-icon-scissors" size="mini" @click="handleStartSplit(item)"
:loading="item.picking" class="action-btn">分条</el-button>
<el-button style="position: absolute; bottom: 10px; right: 10px;" type="success" icon="el-icon-scissors"
size="mini" @click="handleStartSplit(item)" :loading="buttonLoading" class="action-btn">分条</el-button>
</div>
<div class="card-footer">
<el-button type="primary" icon="el-icon-check" size="mini" @click="handlePickMaterial(item)"
:loading="item.picking" class="action-btn">领料</el-button>
:loading="buttonLoading" class="action-btn">领料</el-button>
<el-button type="danger" icon="el-icon-alarm-clock" :plain="item.abnormalCount == 0" size="mini"
@click="handleAddAbnormal(item)" :loading="item.cancelling" class="action-btn">
@click="handleAddAbnormal(item)" :loading="buttonLoading" class="action-btn">
异常
<span v-if="item.abnormalCount > 0">({{ item.abnormalCount }})</span>
</el-button>
@@ -220,9 +221,25 @@
<!-- 右侧待操作列表 -->
<el-col :span="12">
<div v-if="useSpecialSplit" style="margin-bottom: 20px;" v-loading="stepSpilt.loading">
<div class="section-header">
<h3 class="section-title">进行中的镀锌工序</h3>
<el-button size="mini" icon="el-icon-refresh" @click="getStepSplitList">刷新</el-button>
</div>
<div style="display: flex; align-items: center; gap: 10px;">
<div v-for="item in stepSpilt.list" :key="item.coilId || index" style="text-align: center; padding: 10px; border: 2px solid #e4e7ed; border-radius: 4px;">
<div class="step-item" style="font-size: 24px; font-weight: bold; ">
<span class="step-value">{{ item.currentCoilNo }}</span>
</div>
<el-button type="primary" size="mini" @click="handleContinueSplit(item)">查看</el-button>
<el-button size="mini" @click="handleCancelSplit(item)">取消操作</el-button>
</div>
</div>
</div>
<div class="section-card action-section">
<div class="section-header">
<h3 class="section-title">{{ label }}操作</h3>
<h3 class="section-title">{{ label }}操作记录</h3>
<el-button size="mini" icon="el-icon-refresh" @click="getPendingAction">刷新</el-button>
</div>
@@ -301,27 +318,32 @@
</div>
</div>
<div class="card-footer">
<div class="card-footer" v-if="!useSpecialSplit">
<!-- 待处理状态显示操作按钮 -->
<template v-if="item.actionStatus === 0">
<el-button type="primary" icon="el-icon-edit" size="mini" @click="handleProcess(item)"
class="action-btn">操作</el-button>
<el-button type="danger" icon="el-icon-delete" size="mini" @click="handleDeleteAction(item)"
class="action-btn">删除</el-button>
<el-button :loading="buttonLoading" type="primary" icon="el-icon-edit" size="mini"
@click="handleProcess(item)" class="action-btn">操作</el-button>
<el-button :loading="buttonLoading" type="danger" icon="el-icon-delete" size="mini"
@click="handleDeleteAction(item)" class="action-btn">删除</el-button>
</template>
<!-- 处理中状态显示继续按钮 -->
<template v-else-if="item.actionStatus === 1">
<el-button type="warning" icon="el-icon-edit" size="mini" @click="handleProcess(item)"
class="action-btn">继续</el-button>
<el-button type="info" icon="el-icon-close" size="mini" @click="handleCancel(item)"
class="action-btn">取消</el-button>
<el-button :loading="buttonLoading" type="warning" icon="el-icon-edit" size="mini"
@click="handleProcess(item)" class="action-btn">继续</el-button>
<el-button :loading="buttonLoading" type="info" icon="el-icon-close" size="mini"
@click="handleCancel(item)" class="action-btn">取消</el-button>
</template>
<!-- 已完成或已取消状态显示删除按钮 -->
<template v-else>
<el-button type="danger" icon="el-icon-delete" size="mini" @click="handleDeleteAction(item)"
class="action-btn">删除</el-button>
<el-button :loading="buttonLoading" type="danger" icon="el-icon-delete" size="mini"
@click="handleDeleteAction(item)" class="action-btn">删除</el-button>
</template>
</div>
<div class="card-footer" v-else="!useSpecialSplit">
<el-button :loading="buttonLoading" type="primary" icon="el-icon-edit" size="mini"
@click="handleProcess(item)" class="action-btn">查看</el-button>
</div>
</div>
</div>
@@ -371,18 +393,24 @@
<label-render :content="labelRender.data" :labelType="labelRender.type" />
</el-dialog>
<el-dialog title="分步分条" :visible.sync="stepSpilt.visible" width="1400px" append-to-body>
<step-split @print="handlePrintLabel" @complete="stepSpilt.visible = false" :actionId="stepSpilt.actionId"
:coilId="stepSpilt.coilId" :actionStatus="stepSpilt.actionStatus" />
</el-dialog>
<label-render ref="labelRender" v-show="false" :content="labelRender.data" :labelType="labelRender.type" />
</div>
</template>
<script>
import { listMaterialCoil } from '@/api/wms/coil'
import { listMaterialCoil, startSpecialSplit, cancelSpecialSplit } from '@/api/wms/coil'
import { listPendingAction, startProcess, cancelAction, delPendingAction, addPendingAction } from '@/api/wms/pendingAction'
import { parseTime } from '@/utils/klp'
import ProductInfo from '@/components/KLPService/Renderer/ProductInfo'
import RawMaterialInfo from '@/components/KLPService/Renderer/RawMaterialInfo'
import { addCoilAbnormal } from '@/api/wms/coilAbnormal'
import LabelRender from './LabelRender/index.vue'
import StepSplit from './stepSplit.vue'
export default {
name: 'DoPage',
@@ -395,12 +423,17 @@ export default {
tabs: {
type: Array,
default: () => []
},
useSpecialSplit: {
type: Boolean,
default: false
}
},
components: {
ProductInfo,
RawMaterialInfo,
LabelRender
LabelRender,
StepSplit
},
data() {
return {
@@ -434,7 +467,7 @@ export default {
actionType: null, // 将在created中设置为酸连轧工序的actionType
actionStatus: null
},
buttonLoading: false,
exceptionDialogVisible: false,
exceptionForm: {
coilId: null,
@@ -443,6 +476,14 @@ export default {
defectCode: null,
degree: null,
remark: null
},
stepSpilt: {
list: [],
loading: false,
visible: false,
coilId: null,
actionId: null,
actionStatus: null
}
}
},
@@ -492,7 +533,6 @@ export default {
created() {
// 立即加载物料列表(不依赖字典)
// this.getMaterialCoil()
// 尝试加载待操作列表(如果字典已加载)
this.$nextTick(() => {
if (this.acidRollingActionType) {
@@ -500,6 +540,7 @@ export default {
this.getPendingAction()
}
})
this.getStepSplitList()
},
mounted() {
// 确保在mounted时也尝试加载字典数据可能此时才加载完成
@@ -528,7 +569,21 @@ export default {
})
},
/** 预览标签 */
getStepSplitList() {
this.stepSpilt.loading = true
listPendingAction({ actionType: 501, actionStatus: 0 }).then(response => {
this.stepSpilt.list = response.rows || []
this.stepSpilt.loading = false
})
},
handleComposeSplit() {
this.stepSpilt.visible = false;
this.getStepSplitList()
this.getPendingAction()
},
/** 预览标签 */
handlePreviewLabel(row) {
this.labelRender.visible = true;
const item = row.itemType === 'product' ? row.product : row.rawMaterial;
@@ -631,6 +686,19 @@ export default {
}
this.getPendingAction()
},
async handleCancelSplit(row) {
this.$modal.confirm('是否取消分卷操作?').then(_ => {
this.stepSpilt.loading = true
this.buttonLoading = true
cancelSpecialSplit(row.actionId).then(response => {
this.$message.success('取消分卷成功')
this.stepSpilt.loading = false
this.buttonLoading = false
this.getPendingAction() // 刷新待操作列表
this.getStepSplitList()
})
})
},
/** 重置待操作搜索 */
resetActionQuery() {
this.resetForm('actionQueryForm')
@@ -652,6 +720,12 @@ export default {
return
}
if (actionType === 501) {
// 特殊分条,打开弹窗操作
this.handleContinueSplit(row)
return;
}
// 根据操作类型跳转到不同页面
let path = ''
@@ -753,6 +827,44 @@ export default {
}
})
},
handleStartSplit(row) {
this.buttonLoading = true
this.$modal.confirm('是否确认领料开始分条操作?')
.then(_ => {
this.stepSpilt.loading = true
addPendingAction({
coilId: row.coilId,
currentCoilNo: row.currentCoilNo,
actionType: 501,
actionStatus: 0,
sourceType: 'manual',
priority: 0,
}).then(_ => {
startSpecialSplit(row.coilId).then(_ => {
this.$message.success('分条操作已创建')
this.stepSpilt.loading = false
this.getPendingAction()
// this.getMaterialCoil()
this.getStepSplitList()
}).finally(() => {
this.buttonLoading = false
})
})
})
.finally(() => {
this.buttonLoading = false
})
},
handleContinueSplit(row) {
this.stepSpilt.coilId = row.coilId
this.stepSpilt.actionId = row.actionId
this.stepSpilt.actionStatus = row.actionStatus
this.stepSpilt.visible = true
// this.buttonLoading = true
// this.getPendingAction()
// this.getMaterialCoil()
// this.buttonLoading = false
},
cancelException() {
// 重置表单
this.exceptionForm = {
@@ -855,7 +967,7 @@ export default {
}
}
@media (min-width: 1600px) {
@media (min-width: 2000px) {
grid-template-columns: repeat(4, 1fr);
}
}

View File

@@ -1,54 +1,557 @@
<template>
<div>
分步分条
<div class="split-coil-container" v-loading="loading">
<!-- 左右分栏布局 -->
<el-row :gutter="20">
<!-- 左侧钢卷信息 + 新增按钮 + 已分条列表 -->
<el-col :span="12">
<div class="coil-info-card">
<el-row :gutter="20" flex justify="end">
<!-- 新增分条按钮 -->
<el-button type="primary" icon="el-icon-plus" @click="addSplitForm" :loading="buttonLoading"
v-if="actionStatus != 2">
新增分条
</el-button>
<!-- 完成分条按钮 -->
<el-button type="success" icon="el-icon-check" @click="completeSplit" :disabled="splitList.length === 0"
:loading="buttonLoading" v-if="actionStatus != 2">
完成整体分条
</el-button>
<el-button type="primary" icon="el-icon-refresh" @click="refresh" :loading="buttonLoading">
刷新
</el-button>
</el-row>
<el-descriptions :column="2" border title="待分条钢卷信息">
<el-descriptions-item label="入场钢卷号">{{ coilInfo.enterCoilNo || '-' }}</el-descriptions-item>
<el-descriptions-item label="当前钢卷号">{{ coilInfo.currentCoilNo || '-' }}</el-descriptions-item>
<el-descriptions-item label="厂家原料卷号">{{ coilInfo.supplierCoilNo || '-' }}</el-descriptions-item>
<el-descriptions-item label="所在库位">{{ coilInfo.warehouseName || '-' }}</el-descriptions-item>
<el-descriptions-item label="材料类型">{{ coilInfo.materialType || '-' }}</el-descriptions-item>
<el-descriptions-item label="净重">{{ coilInfo.netWeight || '-' }} kg</el-descriptions-item>
</el-descriptions>
<!-- 已分条钢卷列表 -->
<el-descriptions :column="1" border title="已分出的钢卷列表"></el-descriptions>
<el-table v-loading="splitListLoading" :data="splitList" @row-click="handleSplitItemClick"
highlight-current-row border stripe>
<el-table-column prop="currentCoilNo" label="当前钢卷号" />
<el-table-column prop="materialType" label="材料类型" />
<el-table-column prop="dataType" label="钢卷状态">
<template #default="scope">
<div v-if="scope.row.status == 1">
<el-tag type="info">已发货</el-tag>
</div>
<div v-else-if="scope.row.dataType == 1">
<el-tag type="success">当前在库</el-tag>
</div>
<div v-else-if="scope.row.dataType == 0">
<el-tag type="warning">历史卷</el-tag>
</div>
<div v-else>
<el-tag type="danger">未知状态</el-tag>
</div>
</template>
</el-table-column>
<el-table-column label="操作" width="220">
<template #default="scope">
<div v-if="scope.row.dataType == 1 && scope.row.status == 0">
<el-button @click.stop="handlePrint(scope.row)">打印</el-button>
<el-button @click.stop="handleEditSplit(scope.row)">编辑</el-button>
<el-button @click.stop="handleDeleteSplit(scope.row)">删除</el-button>
</div>
</template>
</el-table-column>
</el-table>
</div>
</el-col>
<!-- 右侧分条表单 / 分条详情 -->
<el-col :span="12">
<div class="split-form-card" v-if="showSplitForm">
<el-card title="分条钢卷信息录入" shadow="hover">
<el-form ref="splitFormRef" :model="splitForm" :rules="rules" label-width="100px" style="max-width: 800px;">
<el-form-item label="入场钢卷号" prop="enterCoilNo">
<el-input v-model="splitForm.enterCoilNo" placeholder="请输入入场钢卷号" disabled />
</el-form-item>
<el-form-item label="当前钢卷号" prop="currentCoilNo">
<el-input v-model="splitForm.currentCoilNo" placeholder="请输入当前钢卷号" />
</el-form-item>
<el-form-item label="厂家原料卷号" prop="supplierCoilNo">
<el-input v-model="splitForm.supplierCoilNo" placeholder="请输入厂家原料卷号" />
</el-form-item>
<el-form-item label="所在库位" prop="warehouseId">
<warehouse-select v-model="splitForm.warehouseId" placeholder="请选择仓库/库区/库位" style="width: 100%;"
clearable />
</el-form-item>
<!-- <el-form-item label="实际库区" prop="actualWarehouseId">
<actual-warehouse-select
v-model="splitForm.actualWarehouseId"
:clearInput="splitForm.coilId != null"
placeholder="请选择实际库区"
style="width: 100%;"
clearable
/>
</el-form-item> -->
<el-form-item label="班组" prop="team">
<el-select v-model="splitForm.team" placeholder="请选择班组" style="width: 100%">
<el-option key="甲" label="甲" value="甲" />
<el-option key="乙" label="乙" value="乙" />
</el-select>
</el-form-item>
<el-form-item label="材料类型" prop="materialType">
<el-select v-model="splitForm.materialType" placeholder="请选择材料类型" @change="handleMaterialTypeChange">
<el-option label="成品" value="成品" />
<el-option label="原料" value="原料" />
</el-select>
</el-form-item>
<el-form-item :label="getItemLabel" prop="itemId">
<product-select v-if="splitForm.itemType === 'product'" v-model="splitForm.itemId" placeholder="请选择成品"
style="width: 100%;" clearable />
<raw-material-select v-else-if="splitForm.itemType === 'raw_material'" v-model="splitForm.itemId"
placeholder="请选择原料" style="width: 100%;" clearable />
<div v-else>请先选择材料类型</div>
</el-form-item>
<el-form-item label="质量状态" prop="qualityStatus">
<el-select v-model="splitForm.qualityStatus" placeholder="请选择质量状态" style="width: 100%">
<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>
<el-form-item label="切边要求" prop="trimmingRequirement">
<el-select v-model="splitForm.trimmingRequirement" placeholder="请选择切边要求" style="width: 100%">
<el-option label="净边料" value="净边料" />
<el-option label="毛边料" value="毛边料" />
</el-select>
</el-form-item>
<el-form-item label="打包状态" prop="packingStatus">
<el-input v-model="splitForm.packingStatus" placeholder="请输入打包状态" />
</el-form-item>
<el-form-item label="包装要求" prop="packagingRequirement">
<el-select v-model="splitForm.packagingRequirement" placeholder="请选择包装要求" style="width: 100%">
<el-option label="裸包" value="裸包" />
<el-option label="普包" value="普包" />
<el-option label="简包" value="简包" />
</el-select>
</el-form-item>
<el-form-item label="毛重" prop="grossWeight">
<el-input v-model="splitForm.grossWeight" placeholder="请输入毛重" type="number" />
</el-form-item>
<el-form-item label="净重" prop="netWeight">
<el-input v-model="splitForm.netWeight" placeholder="请输入净重" type="number" />
</el-form-item>
<el-form-item label="长度" prop="length">
<el-input v-model="splitForm.length" placeholder="请输入长度" type="number" />
</el-form-item>
<el-form-item label="调制度" prop="temperGrade">
<el-input v-model="splitForm.temperGrade" placeholder="请输入调制度" />
</el-form-item>
<el-form-item label="镀层种类" prop="coatingType">
<el-input v-model="splitForm.coatingType" placeholder="请输入镀层种类" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="splitForm.remark" placeholder="请输入备注" type="textarea" />
</el-form-item>
<el-form-item>
<el-button :loading="buttonLoading" type="primary" @click="addSplit">提交分条</el-button>
<el-button :loading="buttonLoading" @click="resetSplitForm">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
<!-- 分条钢卷详情选中列表项时显示 -->
<div class="split-detail-card" v-else-if="selectedSplitItem">
<el-card title="分条钢卷详情" shadow="hover">
<!-- <el-button type="primary" @click="handlePrint(selectedSplitItem)">打印</el-button> -->
<el-descriptions :column="2" border size="large">
<el-descriptions-item label="入场钢卷号">{{ selectedSplitItem.enterCoilNo || '-' }}</el-descriptions-item>
<el-descriptions-item label="当前钢卷号">{{ selectedSplitItem.currentCoilNo || '-' }}</el-descriptions-item>
<el-descriptions-item label="厂家原料卷号">{{ selectedSplitItem.supplierCoilNo || '-' }}</el-descriptions-item>
<el-descriptions-item label="逻辑库位">{{ selectedSplitItem.warehouseName || '-' }}</el-descriptions-item>
<el-descriptions-item label="实际库区">{{ selectedSplitItem.actualWarehouseName || '-'
}}</el-descriptions-item>
<el-descriptions-item label="班组">{{ selectedSplitItem.team || '-' }}</el-descriptions-item>
<el-descriptions-item label="材料类型">{{ selectedSplitItem.materialType || '-' }}</el-descriptions-item>
<el-descriptions-item label="产品/原料">{{ selectedSplitItem.itemName || '-' }}</el-descriptions-item>
<el-descriptions-item label="质量状态">{{ selectedSplitItem.qualityStatus || '-' }}</el-descriptions-item>
<el-descriptions-item label="切边要求">{{ selectedSplitItem.trimmingRequirement || '-'
}}</el-descriptions-item>
<el-descriptions-item label="打包状态">{{ selectedSplitItem.packingStatus || '-' }}</el-descriptions-item>
<el-descriptions-item label="包装要求">{{ selectedSplitItem.packagingRequirement || '-'
}}</el-descriptions-item>
<el-descriptions-item label="毛重">{{ selectedSplitItem.grossWeight || '-' }} kg</el-descriptions-item>
<el-descriptions-item label="净重">{{ selectedSplitItem.netWeight || '-' }} kg</el-descriptions-item>
<el-descriptions-item label="长度" v-if="selectedSplitItem.length">{{ selectedSplitItem.length }}
m</el-descriptions-item>
<el-descriptions-item label="调制度">{{ selectedSplitItem.temperGrade || '-' }}</el-descriptions-item>
<el-descriptions-item label="镀层种类">{{ selectedSplitItem.coatingType || '-' }}</el-descriptions-item>
<el-descriptions-item label="备注" :span="2">{{ selectedSplitItem.remark || '-' }}</el-descriptions-item>
</el-descriptions>
</el-card>
</div>
<!-- 初始提示 -->
<div class="empty-tip" v-else>
<el-empty description="请选择左侧已分条钢卷查看详情,或点击「新增分条」创建新分条"></el-empty>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import { getMaterialCoil, listMaterialCoil } from '@/api/wms/coil'
import { completeAction } from '@/api/wms/pendingAction'
import { getMaterialCoil, listMaterialCoil, createSpecialChild, completeSpecialSplit, updateMaterialCoilSimple, checkCoilNo, delMaterialCoil } from '@/api/wms/coil'
import { completeAction, getPendingAction, updatePendingAction } from '@/api/wms/pendingAction'
import ProductSelect from "@/components/KLPService/ProductSelect";
import RawMaterialSelect from "@/components/KLPService/RawMaterialSelect";
import WarehouseSelect from "@/components/KLPService/WarehouseSelect";
import ActualWarehouseSelect from "@/components/KLPService/ActualWarehouseSelect";
export default {
name: 'StepSplit',
props: {
actionId: {
type: String,
required: true,
export default {
name: 'StepSplit',
props: {
actionId: {
type: String,
required: true,
},
coilId: {
type: String,
required: true,
},
actionStatus: {
type: Number,
default: 0,
},
},
components: {
ProductSelect,
RawMaterialSelect,
WarehouseSelect,
ActualWarehouseSelect,
},
dicts: ['coil_quality_status'],
data() {
return {
// 待分条钢卷基础信息
coilInfo: {},
loading: false,
// 分条表单数据
splitForm: {
coilId: '', // 分条钢卷ID编辑时赋值
enterCoilNo: '',
currentCoilNo: '',
supplierCoilNo: '',
warehouseId: '',
actualWarehouseId: '',
team: '',
materialType: '',
itemType: '', // product/raw_material
itemId: '',
qualityStatus: '',
trimmingRequirement: '',
packingStatus: '',
packagingRequirement: '',
grossWeight: '',
netWeight: '',
length: '',
temperGrade: '',
coatingType: '',
remark: '',
},
coilId: {
type: String,
required: true,
// 已分条钢卷列表
splitList: [],
// 列表加载状态
splitListLoading: false,
// 选中的分条项(用于显示详情)
selectedSplitItem: null,
// 是否显示分条表单
showSplitForm: false,
// 表单验证规则
rules: {
currentCoilNo: [
{ required: true, message: "当前钢卷号不能为空", trigger: "blur" },
// 仅在新增的时候校验
{
validator: (rule, value, callback) => {
// 没有coilId则为新增 触发校验
checkCoilNo({ currentCoilNo: value, coilId: this.splitForm.coilId }).then(res => {
const { duplicateType } = res.data;
if (duplicateType === 'current' || duplicateType === 'both') {
// alert('当前钢卷号重复,请重新输入');
callback(new Error('当前钢卷号重复,请重新输入'));
} else {
callback();
}
})
}, trigger: 'blur'
}
],
materialType: [{ required: true, message: '请选择材料类型', trigger: 'change' }],
itemId: [{ required: true, message: '请选择成品/原料', trigger: 'change' }],
netWeight: [{ required: true, message: '请输入净重', trigger: 'blur' }],
warehouseId: [{ required: true, message: '请选择所在库位', trigger: 'change' }],
},
buttonLoading: false,
}
},
computed: {
// 动态获取成品/原料标签
getItemLabel() {
return this.splitForm.itemType === 'product' ? '成品' : this.splitForm.itemType === 'raw_material' ? '原料' : '材料项'
},
},
watch: {
coilId: {
immediate: true, // 初始化时立即执行
async handler(val) {
if (val) {
this.loading = true
await this.getCoilInfo()
await this.getSplitList()
this.loading = false
// 更新父钢卷ID
this.splitForm.parentCoilId = val
}
},
},
data() {
return {
actionId: {
immediate: true,
handler(val) {
// 若actionId变化需要重新加载数据可在此补充逻辑
},
},
},
methods: {
// 查询待分条的钢卷信息
async getCoilInfo() {
try {
const res = await getMaterialCoil(this.coilId)
if (res.code === 200) {
this.coilInfo = res.data || {}
} else {
this.$message.error('查询钢卷信息失败:' + res.msg)
}
} catch (error) {
this.$message.error('查询钢卷信息异常:' + error.message)
}
},
methods: {
// 查询待分条的钢卷信息
async getCoilInfo() {
},
// 查询钢卷的已分条列表
async getSplitList() {
},
async handlePrint(row) {
this.$emit('print', row)
},
// 新增一个分条表单
async addSplitForm() {
},
async handleDeleteSplit(row) {
this.$modal.confirm('确认删除该分卷吗?').then(async () => {
try {
await delMaterialCoil(row.coilId)
this.$message.success('删除成功')
// 刷新钢卷信息
this.refresh()
} catch (error) {
this.$message.error('删除失败:' + error.message)
}
})
},
// 新增一个分条
async addSplit() {
},
// 刷新分条列表
async refresh() {
this.loading = true
await this.getSplitList()
await this.getCoilInfo()
this.loading = false
},
// 完成整体分条
async completeSplit() {
},
}
}
</script>
// 查询钢卷的已分条列表
async getSplitList() {
this.splitListLoading = true
try {
if (!this.actionId) {
return
}
const action = await getPendingAction(this.actionId)
const coilIds = action.data.remark;
console.log('coilIds', coilIds)
if (!coilIds) {
this.splitList = []
return
}
const res = await listMaterialCoil({
coilIds
})
this.splitList = res.rows || []
updatePendingAction({
actionId: action.data.actionId,
actionStatus: action.data.actionStatus,
actionType: action.data.actionType,
coilId: action.data.coilId,
currentCoilNo: action.data.currentCoilNo,
remark: res.rows.map(item => item.coilId).join(','),
})
} catch (error) {
this.$message.error('查询分条列表异常:' + error.message)
} finally {
this.splitListLoading = false
}
},
// 新增一个分条表单(重置表单并显示)
async addSplitForm() {
this.showSplitForm = true
this.selectedSplitItem = null
this.resetSplitForm()
this.splitForm.enterCoilNo = this.coilInfo.enterCoilNo || ''
},
// 重置分条表单
resetSplitForm() {
this.$refs.splitFormRef?.resetFields()
this.splitForm = {
coilId: undefined,
enterCoilNo: '',
currentCoilNo: '',
supplierCoilNo: '',
warehouseId: '',
actualWarehouseId: '',
team: '',
materialType: '',
itemType: '',
itemId: '',
qualityStatus: '',
trimmingRequirement: '',
packingStatus: '',
packagingRequirement: '',
grossWeight: '',
netWeight: '',
length: '',
temperGrade: '',
coatingType: '',
remark: '',
parentCoilId: this.coilId,
}
},
// 材料类型变更处理
handleMaterialTypeChange(val) {
// 根据材料类型设置itemType
this.splitForm.itemType = val === '成品' ? 'product' : val === '原料' ? 'raw_material' : ''
},
// 选中分条列表项(显示详情)
handleSplitItemClick(row) {
this.selectedSplitItem = row
this.showSplitForm = false
},
// 编辑分条项
async handleEditSplit(row) {
this.showSplitForm = true
this.selectedSplitItem = null
// 赋值表单数据
this.splitForm = { ...row }
// 同步材料类型和长度显示状态
this.handleMaterialTypeChange(row.materialType)
},
// 新增/编辑分条
async addSplit() {
try {
// 表单验证
const valid = await this.$refs.splitFormRef.validate()
if (!valid) {
return
}
// 区分新增/编辑有coilId则为编辑否则为新增
let res
this.buttonLoading = true
if (this.splitForm.coilId) {
// 编辑分条:调用更新接口
res = await updateMaterialCoilSimple(this.splitForm)
} else {
// 新增分条:调用创建接口
res = await createSpecialChild(this.coilId, this.actionId, this.splitForm)
}
this.$message.success(this.splitForm.coilId ? '编辑分条成功' : '新增分条成功')
// 重置表单
this.resetSplitForm()
this.showSplitForm = false
// 刷新分条列表
this.getSplitList()
} catch (error) {
// 表单验证失败时的提示
if (error.name !== 'ValidationError') {
this.$message.error((this.splitForm.coilId ? '编辑' : '新增') + '分条异常:' + error.message)
}
} finally {
this.buttonLoading = false
}
},
// 完成整体分条
async completeSplit() {
this.$confirm('确认完成整体分条操作?完成后将无法修改分条信息', '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}).then(async () => {
try {
this.buttonLoading = true
// 1. 完成分条主流程
const splitRes = await completeSpecialSplit(this.actionId)
if (splitRes.code !== 200) {
this.$message.error('完成分条失败:' + splitRes.msg)
return
}
// 2. 完成待办动作(根据业务逻辑调整)
const actionRes = await completeAction(this.actionId)
if (actionRes.code !== 200) {
this.$message.error('完成待办动作失败:' + actionRes.msg)
return
}
this.buttonLoading = false
this.$message.success('分条操作已完成')
// 通知父组件(如需要)
this.$emit('complete')
} catch (error) {
if (error.message !== 'cancel') { // 排除取消确认的情况
this.$message.error('完成分条异常:' + error.message)
}
}
})
},
},
}
</script>
<style scoped>
.split-coil-container {
padding: 20px;
}
.coil-info-card {
height: 100%;
display: flex;
flex-direction: column;
gap: 10px;
}
.split-form-card,
.split-detail-card {
height: 100%;
}
.empty-tip {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
min-height: 400px;
}
</style>