feat(wms/coil): 新增镀铬卷号字段与分条校验规则优化

1.  在CoilCard中将长度标签改为参考长度
2.  新增镀铬卷号列到钢卷选择器表格与可选列配置
3.  在钢卷更新和分条页面添加净重、厚度校验规则,区分镀锌/酸轧/镀铬产线豁免情况
4.  优化分条页面的代码格式与组件注册顺序,新增镀铬操作类型判断
5.  分条表单新增镀铬卷号输入项,支持从源卷复制镀铬卷号信息
This commit is contained in:
2026-06-01 14:31:06 +08:00
parent a0cd885fc7
commit bf3967d7b5
4 changed files with 369 additions and 194 deletions

View File

@@ -11,6 +11,12 @@ export const defaultColumns = [
prop: 'currentCoilNo',
showOverflowTooltip: true
},
{
label: '镀铬卷号',
align: 'center',
prop: 'chromelCoilNo',
showOverflowTooltip: true
},
{
label: '存储位置',
align: 'center',
@@ -83,6 +89,12 @@ export const fullPageDefaultColumns = [
prop: 'currentCoilNo',
showOverflowTooltip: true
},
{
label: '镀铬卷号',
align: 'center',
prop: 'chromelCoilNo',
showOverflowTooltip: true
},
{
label: '存储位置',
align: 'center',
@@ -171,6 +183,7 @@ export const fullPageDefaultColumns = [
export const optionalColumns = [
{ label: '入场卷号', value: 'enterCoilNo' },
{ label: '当前卷号', value: 'currentCoilNo' },
{ label: '镀铬卷号', value: 'chromelCoilNo' },
{ label: '厂家钢卷号', value: 'supplierCoilNo' },
{ label: '逻辑库区', value: 'warehouseName' },
{ label: '实际库区', value: 'actualWarehouseName' },

View File

@@ -64,7 +64,7 @@
<span class="param-value">{{ coil.netWeight }}t</span>
</div>
<div class="param-row" v-if="coil.length">
<span class="param-label">长度</span>
<span class="param-label">参考长度</span>
<span class="param-value">{{ coil.length }}m</span>
</div>
<div class="param-row" v-if="coil.actualLength">

View File

@@ -1,5 +1,5 @@
<template>
<div class="split-coil-container" v-loading="loading">
<div v-loading="loading" class="split-coil-container">
<!-- 左右分栏布局 -->
<el-row :gutter="20">
<!-- 左侧钢卷信息 + 新增按钮 + 已分条列表 -->
@@ -7,26 +7,41 @@
<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
v-if="actionStatus != 2"
type="primary"
icon="el-icon-plus"
:loading="buttonLoading"
@click="addSplitForm"
>
新增分条
</el-button>
<!-- 完成分条按钮 -->
<el-button type="success" icon="el-icon-check" @click="completeSplit" :disabled="splitList.length === 0"
:loading="buttonLoading" v-if="actionStatus != 2">
<el-button
v-if="actionStatus != 2"
type="success"
icon="el-icon-check"
:disabled="splitList.length === 0"
:loading="buttonLoading"
@click="completeSplit"
>
完成整体分条
</el-button>
<el-button type="primary" icon="el-icon-refresh" @click="refresh" :loading="buttonLoading">
<el-button type="primary" icon="el-icon-refresh" :loading="buttonLoading" @click="refresh">
刷新
</el-button>
</el-row>
<el-descriptions :column="2" border title="待分条钢卷信息">
<template slot="extra">
<el-button v-if="showSplitForm" type="info" @click="copyFromSourceCoil"
icon="el-icon-document-copy">复制源卷信息</el-button>
<el-button
v-if="showSplitForm"
type="info"
icon="el-icon-document-copy"
@click="copyFromSourceCoil"
>复制源卷信息</el-button>
</template>
<el-descriptions-item label="入场钢卷号">{{ coilInfo.enterCoilNo || '-' }}</el-descriptions-item>
<el-descriptions-item label="当前钢卷号">{{ coilInfo.currentCoilNo || '-' }}</el-descriptions-item>
@@ -47,9 +62,15 @@
</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-descriptions :column="1" border title="已分出的钢卷列表" />
<el-table
v-loading="splitListLoading"
:data="splitList"
highlight-current-row
border
stripe
@row-click="handleSplitItemClick"
>
<el-table-column prop="enterCoilNo" label="入场钢卷号" />
<el-table-column prop="currentCoilNo" label="当前钢卷号" />
@@ -88,28 +109,25 @@
</el-table-column>
</el-table>
<!-- <el-descriptions :column="1" border title="镀锌二级数据"
v-if="actionType == 501 && showSplitForm"></el-descriptions>
<el-table v-if="actionType == 501 && showSplitForm" v-loading="zincLoading" :data="zincList" border stripe
@row-click="handleZincItemClick" highlight-current-row>
<el-table-column type="index" label="序号" width="50" />
<el-table-column prop="enterCoilNo" label="入场钢卷号" />
<el-table-column prop="createTime" label="生产开始时间" />
<el-table-column prop="endTime" label="生产结束时间" />
<el-table-column prop="shiftNo" label="班组" />
</el-table> -->
<!-- 今日排产单 -->
<div v-if="planSheetList.length > 0" class="plan-sheet-section">
<el-descriptions :column="1" border :title="'最近排产单(' + planSheetLineName + ''">
</el-descriptions>
<el-descriptions :column="1" border :title="'最近排产单(' + planSheetLineName + ''" />
<el-tabs v-model="activePlanSheetId" type="card">
<el-tab-pane v-for="sheet in planSheetList" :key="sheet.planSheetId"
<el-tab-pane
v-for="sheet in planSheetList"
:key="sheet.planSheetId"
:name="sheet.planSheetId"
:label="sheet.planCode || ('排产单' + sheet.planSheetId)" />
:label="sheet.planCode || ('排产单' + sheet.planSheetId)"
/>
</el-tabs>
<el-table v-loading="planSheetLoading" :data="activePlanSheetDetails" border stripe size="mini"
max-height="400">
<el-table
v-loading="planSheetLoading"
:data="activePlanSheetDetails"
border
stripe
size="mini"
max-height="400"
>
<el-table-column type="index" label="序号" width="50" />
<el-table-column label="订单信息" header-align="center">
<el-table-column prop="contractCode" label="合同号" width="140" show-overflow-tooltip />
@@ -138,8 +156,7 @@
<!-- 今日排产单空状态 -->
<div v-if="planSheetList.length === 0 && planSheetLineName && !planSheetLoading" class="plan-sheet-section">
<el-descriptions :column="1" border :title="'最近排产单(' + planSheetLineName + ''">
</el-descriptions>
<el-descriptions :column="1" border :title="'最近排产单(' + planSheetLineName + ''" />
<el-empty description="今天暂无排产单" :image-size="80" />
</div>
</div>
@@ -147,19 +164,31 @@
<!-- 右侧分条表单 / 分条详情 -->
<el-col :span="12">
<div class="split-form-card" v-if="showSplitForm">
<div v-if="showSplitForm" class="split-form-card">
<el-card title="分条钢卷信息录入" shadow="hover">
<el-alert v-if="!isExemptFromValidation" type="warning" :closable="false" show-icon style="margin-bottom:12px">
<template slot="title">
子卷的<b>净重</b><b>实测厚度</b>均不能超过父卷完成分条时所有子卷净重总和不能超过父卷净重
</template>
</el-alert>
<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 v-if="isGrindAction" label="镀铬卷号" prop="chromePlateCoilNo">
<el-input v-model="splitForm.chromePlateCoilNo" placeholder="请输入镀铬卷号" />
</el-form-item>
<el-form-item label="当前钢卷号" prop="currentCoilNo">
<el-input v-model="splitForm.currentCoilNo" placeholder="请输入当前钢卷号" />
<current-coil-no :current-coil-no="splitForm.currentCoilNo" />
</el-form-item>
<el-form-item label="所在库位" prop="warehouseId">
<warehouse-select v-model="splitForm.warehouseId" placeholder="请选择仓库/库区/库位" style="width: 100%;"
clearable />
<warehouse-select
v-model="splitForm.warehouseId"
placeholder="请选择仓库/库区/库位"
style="width: 100%;"
clearable
/>
</el-form-item>
<el-form-item label="班组" prop="team">
<el-select v-model="splitForm.team" placeholder="请选择班组" style="width: 100%">
@@ -174,16 +203,30 @@
</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 />
<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-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">
@@ -213,39 +256,64 @@
<el-input v-model="splitForm.length" placeholder="请输入长度" type="number" />
</el-form-item>
<el-form-item label="实测长度(m)" prop="actualLength">
<el-input-number :controls="false" v-model="splitForm.actualLength" placeholder="请输入实测长度" type="number"
:step="0.01" />
<el-input-number
v-model="splitForm.actualLength"
:controls="false"
placeholder="请输入实测长度"
type="number"
:step="0.01"
/>
</el-form-item>
<el-form-item label="实测厚度(mm)" prop="actualThickness">
<el-input-number :controls="false" v-model="splitForm.actualThickness" placeholder="请输入实测厚度"
type="number" :step="0.01" />
<el-input-number
v-model="splitForm.actualThickness"
:controls="false"
placeholder="请输入实测厚度"
type="number"
:step="0.01"
/>
</el-form-item>
<el-form-item label="实测宽度(mm)" prop="actualWidth">
<el-input-number :controls="false" v-model="splitForm.actualWidth" placeholder="请输入实测宽度" type="number"
:step="0.01" />
<el-input-number
v-model="splitForm.actualWidth"
:controls="false"
placeholder="请输入实测宽度"
type="number"
:step="0.01"
/>
</el-form-item>
<el-form-item label="业务目的" prop="businessPurpose">
<el-select v-model="splitForm.businessPurpose" placeholder="业务目的" filterable>
<el-option v-for="item in dict.type.coil_business_purpose" :key="item.value" :value="item.value"
:label="item.label" />
<el-option
v-for="item in dict.type.coil_business_purpose"
:key="item.value"
:value="item.value"
:label="item.label"
/>
</el-select>
</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">
<MemoInput storageKey="coatingType" v-model="splitForm.coatingType" placeholder="请输入镀层种类" />
<MemoInput v-model="splitForm.coatingType" storage-key="coatingType" placeholder="请输入镀层种类" />
</el-form-item>
<el-form-item label="钢卷表面处理" prop="coilSurfaceTreatment">
<MemoInput storageKey="surfaceTreatmentDesc" v-model="splitForm.coilSurfaceTreatment"
placeholder="请输入钢卷表面处理" />
<MemoInput
v-model="splitForm.coilSurfaceTreatment"
storage-key="surfaceTreatmentDesc"
placeholder="请输入钢卷表面处理"
/>
</el-form-item>
<el-form-item label="生产开始时间" prop="productionStartTime">
<TimeInput v-model="splitForm.productionStartTime" @input="calculateProductionDuration" />
</el-form-item>
<el-form-item label="生产结束时间" prop="productionEndTime">
<TimeInput v-model="splitForm.productionEndTime" @input="calculateProductionDuration"
:show-now-button="true" />
<TimeInput
v-model="splitForm.productionEndTime"
:show-now-button="true"
@input="calculateProductionDuration"
/>
</el-form-item>
<el-form-item label="生产耗时" prop="productionDuration">
<el-input v-model="splitForm.formattedDuration" placeholder="自动计算" disabled />
@@ -260,19 +328,28 @@
<el-form-item label="异常信息">
<div class="abnormal-container">
<div v-for="(abnormal, index) in abnormals" :key="index" class="abnormal-item"
@click="editAbnormal(index)">
<div
v-for="(abnormal, index) in abnormals"
:key="index"
class="abnormal-item"
@click="editAbnormal(index)"
>
<div class="abnormal-content">
<div class="abnormal-info">
<div class="abnormal-position">{{ getAbnormalPositionText(abnormal.position) }}</div>
<div class="abnormal-code">{{ getAbnormalCodeText(abnormal.defectCode) }}</div>
</div>
<el-button type="danger" size="mini" icon="el-icon-close" class="abnormal-delete"
@click.stop="deleteAbnormal(index)"></el-button>
<el-button
type="danger"
size="mini"
icon="el-icon-close"
class="abnormal-delete"
@click.stop="deleteAbnormal(index)"
/>
</div>
</div>
<div class="abnormal-add" @click="addAbnormal">
<i class="el-icon-plus"></i>
<i class="el-icon-plus" />
</div>
</div>
</el-form-item>
@@ -287,23 +364,27 @@
</div>
<!-- 分条钢卷详情选中列表项时显示 -->
<div class="split-detail-card" v-else-if="selectedSplitItem">
<div v-else-if="selectedSplitItem" class="split-detail-card">
<el-card title="分条钢卷详情" shadow="hover">
<CoilInfoRender :coilInfo="selectedSplitItem" :column="2" border />
<CoilInfoRender :coil-info="selectedSplitItem" :column="2" border />
</el-card>
</div>
<!-- 初始提示 -->
<div class="empty-tip" v-else>
<el-empty description="请选择左侧已分条钢卷查看详情,或点击「新增分条」创建新分条"></el-empty>
<div v-else class="empty-tip">
<el-empty description="请选择左侧已分条钢卷查看详情,或点击「新增分条」创建新分条" />
</div>
</el-col>
</el-row>
<!-- 异常表单弹窗 -->
<el-dialog :title="currentAbnormalIndex === -1 ? '新增异常' : '编辑异常'" :visible.sync="abnormalDialogVisible"
width="600px" append-to-body>
<abnormal-form ref="abnormalForm" v-model="abnormalForm" :show-coil-selector="false"></abnormal-form>
<el-dialog
:title="currentAbnormalIndex === -1 ? '新增异常' : '编辑异常'"
:visible.sync="abnormalDialogVisible"
width="600px"
append-to-body
>
<abnormal-form ref="abnormalForm" v-model="abnormalForm" :show-coil-selector="false" />
<div slot="footer" class="dialog-footer">
<el-button @click="abnormalDialogVisible = false"> </el-button>
<el-button type="primary" @click="saveAbnormal"> </el-button>
@@ -313,7 +394,7 @@
<!-- 缓存数据展示弹窗 -->
<el-dialog title="发现暂存数据" :visible.sync="cacheDialogVisible" width="800px" append-to-body>
<div>
<el-alert title="检测到您之前有暂存的分条数据,是否恢复使用?" type="info" show-icon :closable="false"></el-alert>
<el-alert title="检测到您之前有暂存的分条数据,是否恢复使用?" type="info" show-icon :closable="false" />
<el-divider content-position="left">暂存的表单数据</el-divider>
<el-descriptions :column="2" border size="small">
<el-descriptions-item label="入场钢卷号">{{ parsedCacheData && parsedCacheData.splitForm &&
@@ -334,10 +415,15 @@
<el-descriptions-item label="备注">{{ parsedCacheData && parsedCacheData.splitForm &&
parsedCacheData.splitForm.remark || '-' }}</el-descriptions-item>
</el-descriptions>
<el-divider v-if="parsedCacheData && parsedCacheData.abnormals && parsedCacheData.abnormals.length > 0"
content-position="left">暂存的异常信息 ({{ parsedCacheData.abnormals.length }})</el-divider>
<div v-if="parsedCacheData && parsedCacheData.abnormals && parsedCacheData.abnormals.length > 0"
class="abnormal-container" style="margin-bottom: 20px;">
<el-divider
v-if="parsedCacheData && parsedCacheData.abnormals && parsedCacheData.abnormals.length > 0"
content-position="left"
>暂存的异常信息 ({{ parsedCacheData.abnormals.length }})</el-divider>
<div
v-if="parsedCacheData && parsedCacheData.abnormals && parsedCacheData.abnormals.length > 0"
class="abnormal-container"
style="margin-bottom: 20px;"
>
<div v-for="(abnormal, index) in parsedCacheData.abnormals" :key="index" class="abnormal-item">
<div class="abnormal-content">
<div class="abnormal-info">
@@ -358,44 +444,26 @@
</template>
<script>
import { getMaterialCoil, listMaterialCoil, createSpecialChild, completeSpecialSplit, updateMaterialCoilSimple, checkCoilNo, delMaterialCoil, getFirstHeatCoilMaterial } from '@/api/wms/coil'
import { getMaterialCoil, listMaterialCoil, createSpecialChild, completeSpecialSplit, updateMaterialCoilSimple, delMaterialCoil, getFirstHeatCoilMaterial } from '@/api/wms/coil'
import { completeAction, getPendingAction, updatePendingAction } from '@/api/wms/pendingAction'
import { saveCoilCache, getCoilCacheByCoilId, delCoilCache } from '@/api/wms/coilCache'
import { getGalvanize1TypingPrefill } from '@/api/pocket/acidTyping';
import { getGalvanize1TypingPrefill } from '@/api/pocket/acidTyping'
import { listPlanSheet } from '@/api/aps/planSheet'
import { listPlanDetail } from '@/api/aps/planDetail'
import ProductSelect from "@/components/KLPService/ProductSelect";
import RawMaterialSelect from "@/components/KLPService/RawMaterialSelect";
import WarehouseSelect from "@/components/KLPService/WarehouseSelect";
import ActualWarehouseSelect from "@/components/KLPService/ActualWarehouseSelect";
import TimeInput from "@/components/TimeInput";
import AbnormalForm from '../components/AbnormalForm';
import { generateCoilNoPrefix } from "@/utils/coil/coilNo";
import ProductInfo from "@/components/KLPService/Renderer/ProductInfo";
import RawMaterialInfo from "@/components/KLPService/Renderer/RawMaterialInfo";
import ContractSelect from "@/components/KLPService/ContractSelect";
import { addCoilContractRel } from "@/api/wms/coilContractRel";
import ProductSelect from '@/components/KLPService/ProductSelect'
import RawMaterialSelect from '@/components/KLPService/RawMaterialSelect'
import WarehouseSelect from '@/components/KLPService/WarehouseSelect'
import ActualWarehouseSelect from '@/components/KLPService/ActualWarehouseSelect'
import TimeInput from '@/components/TimeInput'
import AbnormalForm from '../components/AbnormalForm'
import { generateCoilNoPrefix } from '@/utils/coil/coilNo'
import ProductInfo from '@/components/KLPService/Renderer/ProductInfo'
import RawMaterialInfo from '@/components/KLPService/Renderer/RawMaterialInfo'
import ContractSelect from '@/components/KLPService/ContractSelect'
import { addCoilContractRel } from '@/api/wms/coilContractRel'
export default {
name: 'StepSplit',
props: {
actionId: {
type: [String, Number],
required: true,
},
coilId: {
type: String,
required: true,
},
actionStatus: {
type: Number,
default: 0,
},
actionType: {
type: Number,
required: true,
},
},
components: {
ProductSelect,
RawMaterialSelect,
@@ -405,7 +473,25 @@ export default {
AbnormalForm,
ProductInfo,
RawMaterialInfo,
ContractSelect,
ContractSelect
},
props: {
actionId: {
type: [String, Number],
required: true
},
coilId: {
type: String,
required: true
},
actionStatus: {
type: Number,
default: 0
},
actionType: {
type: Number,
required: true
}
},
dicts: ['coil_quality_status', 'coil_abnormal_position', 'coil_abnormal_code', 'coil_abnormal_degree', 'coil_business_purpose'],
data() {
@@ -439,10 +525,11 @@ export default {
temperGrade: '',
coatingType: '',
remark: '',
chromePlateCoilNo: '',
productionStartTime: '',
productionEndTime: '',
productionDuration: '',
formattedDuration: '',
formattedDuration: ''
},
// 已分条钢卷列表
splitList: [],
@@ -455,22 +542,22 @@ export default {
// 表单验证规则
rules: {
currentCoilNo: [
{ required: true, message: "当前钢卷号不能为空", trigger: "blur" },
{ required: true, message: '当前钢卷号不能为空', trigger: 'blur' },
{
// 当前钢卷号必须大于等于10位
validator: (rule, value, callback) => {
if (value.length < 11) {
callback(new Error('当前钢卷号必须大于等于11位'));
callback(new Error('当前钢卷号必须大于等于11位'))
} else {
callback();
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' }],
warehouseId: [{ required: true, message: '请选择所在库位', trigger: 'change' }]
},
buttonLoading: false,
currentAction: {},
@@ -504,7 +591,7 @@ export default {
planSheetList: [],
planSheetDetailMap: {},
planSheetLoading: false,
activePlanSheetId: null,
activePlanSheetId: null
}
},
computed: {
@@ -518,20 +605,26 @@ export default {
11: '酸轧线',
200: '酸轧线',
520: '酸轧线',
206: '镀锌线',
501: '镀锌线',
521: '镀锌线',
203: '脱脂线',
502: '脱脂线',
522: '脱脂线',
204: '拉矫线',
503: '拉矫线',
523: '拉矫线',
205: '双机架',
504: '双机架',
524: '双机架',
206: '镀铬线',
505: '镀铬线',
525: '镀铬线',
525: '镀铬线'
}
return mapping[this.actionType] || ''
},
@@ -545,6 +638,14 @@ export default {
activePlanSheetDetails() {
return this.planSheetDetailMap[this.activePlanSheetId] || []
},
// 是否是镀铬操作
isGrindAction() {
return this.actionType == 505 || this.actionType == 525 || this.actionType == 206
},
// 镀锌/酸轧产线免验净重和厚度范围
isExemptFromValidation() {
return [11, 200, 520, 206, 501, 521].includes(Number(this.actionType))
}
},
watch: {
coilId: {
@@ -558,13 +659,13 @@ export default {
// 更新父钢卷ID
this.splitForm.parentCoilId = val
}
},
}
},
actionId: {
immediate: true,
handler(val) {
// 若actionId变化需要重新加载数据可在此补充逻辑
},
}
},
actionType: {
immediate: true,
@@ -589,7 +690,7 @@ export default {
const res = await listPlanSheet({
lineName: this.planSheetLineName,
pageSize: 3,
pageNum: 1,
pageNum: 1
})
this.planSheetList = res.rows || []
this.planSheetDetailMap = {}
@@ -610,7 +711,7 @@ export default {
const res = await listPlanDetail({
planSheetId,
pageSize: 100,
pageNum: 1,
pageNum: 1
})
const details = res.rows || []
details.sort((a, b) => {
@@ -624,7 +725,6 @@ export default {
}
},
// 查询待分条的钢卷信息
async getCoilInfo() {
try {
@@ -633,14 +733,13 @@ export default {
this.coilInfo = res.data || {}
// 获取最早的热轧卷板材质
try {
const firstHeatMaterial = await getFirstHeatCoilMaterial(this.coilId);
const firstHeatMaterial = await getFirstHeatCoilMaterial(this.coilId)
if (firstHeatMaterial.code === 200 && firstHeatMaterial.msg) {
this.firstHeatMaterial = firstHeatMaterial.msg
}
} catch {
}
} else {
this.$message.error('查询钢卷信息失败:' + res.msg)
}
@@ -653,7 +752,7 @@ export default {
this.zincLoading = true
const res = await getGalvanize1TypingPrefill({
pageSize: 10,
pageNum: 1,
pageNum: 1
})
this.zincList = res.rows || []
this.zincLoading = false
@@ -664,7 +763,7 @@ export default {
},
async handleDeleteSplit(row) {
this.$modal.confirm('确认删除该分卷吗?').then(async () => {
this.$modal.confirm('确认删除该分卷吗?').then(async() => {
try {
await delMaterialCoil(row.coilId)
this.$message.success('删除成功')
@@ -693,7 +792,7 @@ export default {
}
const action = await getPendingAction(this.actionId)
this.currentAction = action.data || {}
const coilIds = action.data.remark;
const coilIds = action.data.remark
console.log('coilIds', coilIds)
if (!coilIds) {
this.splitList = []
@@ -714,7 +813,7 @@ export default {
actionType: action.data.actionType,
coilId: action.data.coilId,
currentCoilNo: action.data.currentCoilNo,
remark: res.rows.map(item => item.coilId).join(','),
remark: res.rows.map(item => item.coilId).join(',')
})
} catch (error) {
this.$message.error('查询分条列表异常:' + error.message)
@@ -773,26 +872,27 @@ export default {
temperGrade: '',
coatingType: '',
remark: '',
chromePlateCoilNo: '',
productionStartTime: this.currentAction.createTime,
productionEndTime: '',
productionDuration: '',
formattedDuration: '',
parentCoilId: this.coilId,
parentCoilId: this.coilId
}
// 重置异常信息
this.abnormals = [];
this.abnormals = []
},
// 材料类型变更处理
handleMaterialTypeChange(val) {
// 清空物品选择
this.splitForm.itemId = null;
this.splitForm.itemId = null
// 根据材料类型设置物品类型
if (val === '成品') {
this.splitForm.itemType = 'product';
this.splitForm.itemType = 'product'
} else if (val === '原料') {
this.splitForm.itemType = 'raw_material';
this.splitForm.itemType = 'raw_material'
}
},
@@ -812,7 +912,7 @@ export default {
itemType: 'product',
materialType: '成品',
length: row.exitLength,
netWeight: row.exitNetWeight,
netWeight: row.exitNetWeight
}
},
@@ -832,6 +932,22 @@ export default {
if (!valid) {
return
}
// 校验子卷净重和实测厚度不超过父卷(镀锌/酸轧除外)
if (!this.isExemptFromValidation) {
const parentNetWeight = parseFloat(this.coilInfo.netWeight) || 0
const parentThickness = parseFloat(this.coilInfo.actualThickness) || 0
const childNetWeight = parseFloat(this.splitForm.netWeight) || 0
const childThickness = parseFloat(this.splitForm.actualThickness) || 0
if (childNetWeight > 0 && parentNetWeight > 0 && childNetWeight > parentNetWeight) {
this.$message.error(`子卷净重(${childNetWeight}T)不能超过父卷净重(${parentNetWeight}T)`)
return
}
if (childThickness > 0 && parentThickness > 0 && childThickness > parentThickness) {
this.$message.error(`子卷实测厚度(${childThickness}mm)不能超过父卷实测厚度(${parentThickness}mm)`)
return
}
}
try {
// 区分新增/编辑有coilId则为编辑否则为新增
let res
@@ -841,7 +957,7 @@ export default {
const splitData = {
...this.splitForm,
abnormals: this.abnormals
};
}
if (this.splitForm.coilId) {
// 编辑分条:调用更新接口
@@ -853,7 +969,7 @@ export default {
if (this.splitForm.contractId) {
addCoilContractRel({
coilId: res.data.coilId,
contractId: this.splitForm.contractId,
contractId: this.splitForm.contractId
})
}
}
@@ -877,15 +993,34 @@ export default {
// 完成整体分条
async completeSplit() {
// 校验所有子卷(镀锌/酸轧除外)
if (!this.isExemptFromValidation) {
const parentThickness = parseFloat(this.coilInfo.actualThickness) || 0
const parentNetWeight = parseFloat(this.coilInfo.netWeight) || 0
let totalChildNetWeight = 0
for (const child of this.splitList) {
const childThickness = parseFloat(child.actualThickness) || 0
const childNetWeight = parseFloat(child.netWeight) || 0
totalChildNetWeight += childNetWeight
if (childThickness > 0 && parentThickness > 0 && childThickness > parentThickness) {
this.$message.error(`子卷【${child.currentCoilNo}】实测厚度(${childThickness}mm)超过父卷实测厚度(${parentThickness}mm),请先修正`)
return
}
}
if (totalChildNetWeight > 0 && parentNetWeight > 0 && totalChildNetWeight > parentNetWeight) {
this.$message.error(`所有子卷净重总和(${totalChildNetWeight.toFixed(3)}T)超过父卷净重(${parentNetWeight}T),请先修正`)
return
}
}
this.$confirm('确认完成整体分条操作?完成后将无法修改分条信息', '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}).then(async () => {
type: 'warning'
}).then(async() => {
const loading = this.$loading({
lock: true,
text: '正在记录分条操作...',
background: 'rgba(0, 0, 0, 0.7)',
background: 'rgba(0, 0, 0, 0.7)'
})
try {
this.buttonLoading = true
@@ -918,51 +1053,51 @@ export default {
},
// 格式化毫秒值为xx天xx小时xx分钟
formatDuration(milliseconds) {
if (!milliseconds || milliseconds < 0) return '';
if (!milliseconds || milliseconds < 0) return ''
const seconds = Math.floor(milliseconds / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);
const seconds = Math.floor(milliseconds / 1000)
const minutes = Math.floor(seconds / 60)
const hours = Math.floor(minutes / 60)
const days = Math.floor(hours / 24)
const remainingHours = hours % 24;
const remainingMinutes = minutes % 60;
const remainingHours = hours % 24
const remainingMinutes = minutes % 60
let result = '';
if (days > 0) result += `${days}`;
if (remainingHours > 0) result += `${remainingHours}小时`;
if (remainingMinutes > 0) result += `${remainingMinutes}分钟`;
let result = ''
if (days > 0) result += `${days}`
if (remainingHours > 0) result += `${remainingHours}小时`
if (remainingMinutes > 0) result += `${remainingMinutes}分钟`
return result || '0分钟';
return result || '0分钟'
},
// 计算生产耗时
calculateProductionDuration() {
const { productionStartTime, productionEndTime } = this.splitForm;
const { productionStartTime, productionEndTime } = this.splitForm
if (productionStartTime && productionEndTime) {
const start = new Date(productionStartTime).getTime();
const end = new Date(productionEndTime).getTime();
const start = new Date(productionStartTime).getTime()
const end = new Date(productionEndTime).getTime()
if (end < start) {
this.$message({
message: '结束时间不能早于开始时间',
type: 'error',
});
this.$set(this.splitForm, 'productionDuration', '');
this.$set(this.splitForm, 'formattedDuration', '');
type: 'error'
})
this.$set(this.splitForm, 'productionDuration', '')
this.$set(this.splitForm, 'formattedDuration', '')
} else {
const durationMs = end - start;
const durationMinutes = Math.round(durationMs / (1000 * 60));
this.$set(this.splitForm, 'productionDuration', durationMinutes);
this.$set(this.splitForm, 'formattedDuration', this.formatDuration(durationMinutes * 60 * 1000));
const durationMs = end - start
const durationMinutes = Math.round(durationMs / (1000 * 60))
this.$set(this.splitForm, 'productionDuration', durationMinutes)
this.$set(this.splitForm, 'formattedDuration', this.formatDuration(durationMinutes * 60 * 1000))
}
} else {
this.$set(this.splitForm, 'productionDuration', '');
this.$set(this.splitForm, 'formattedDuration', '');
this.$set(this.splitForm, 'productionDuration', '')
this.$set(this.splitForm, 'formattedDuration', '')
}
},
// 新增异常
addAbnormal() {
this.currentAbnormalIndex = -1;
this.currentAbnormalIndex = -1
this.abnormalForm = {
coilId: this.splitForm.coilId || null,
position: null,
@@ -972,15 +1107,15 @@ export default {
defectCode: null,
degree: null,
remark: null
};
this.abnormalDialogVisible = true;
}
this.abnormalDialogVisible = true
},
// 编辑异常
editAbnormal(index) {
this.currentAbnormalIndex = index;
this.abnormalForm = { ...this.abnormals[index] };
this.abnormalDialogVisible = true;
this.currentAbnormalIndex = index
this.abnormalForm = { ...this.abnormals[index] }
this.abnormalDialogVisible = true
},
// 保存异常
@@ -988,19 +1123,19 @@ export default {
this.$refs.abnormalForm.validate(valid => {
if (valid) {
// 计算缺陷长度
this.abnormalForm.length = this.abnormalForm.endPosition - this.abnormalForm.startPosition;
this.abnormalForm.length = this.abnormalForm.endPosition - this.abnormalForm.startPosition
if (this.currentAbnormalIndex === -1) {
// 新增异常
this.abnormals.push({ ...this.abnormalForm });
this.abnormals.push({ ...this.abnormalForm })
} else {
// 编辑异常
this.abnormals[this.currentAbnormalIndex] = { ...this.abnormalForm };
this.abnormals[this.currentAbnormalIndex] = { ...this.abnormalForm }
}
this.abnormalDialogVisible = false;
this.abnormalDialogVisible = false
}
});
})
},
// 删除异常
@@ -1010,32 +1145,32 @@ export default {
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.abnormals.splice(index, 1);
});
this.abnormals.splice(index, 1)
})
},
// 获取异常位置文本
getAbnormalPositionText(position) {
if (!position) return '';
const dict = this.dict.type.coil_abnormal_position;
if (!dict) return position;
const item = dict.find(item => item.value === position);
return item ? item.label : position;
if (!position) return ''
const dict = this.dict.type.coil_abnormal_position
if (!dict) return position
const item = dict.find(item => item.value === position)
return item ? item.label : position
},
// 获取异常代码文本
getAbnormalCodeText(code) {
if (!code) return '';
const dict = this.dict.type.coil_abnormal_code;
if (!dict) return code;
const item = dict.find(item => item.value === code);
return item ? item.label : code;
if (!code) return ''
const dict = this.dict.type.coil_abnormal_code
if (!dict) return code
const item = dict.find(item => item.value === code)
return item ? item.label : code
},
// 复制源卷信息到分条表单
copyFromSourceCoil() {
// 复制除了指定字段之外的其他字段
const excludeFields = ['enterCoilNo', 'currentCoilNo', 'coilId', 'createTime', 'createBy'];
const excludeFields = ['enterCoilNo', 'currentCoilNo', 'coilId', 'createTime', 'createBy']
// 构建要复制的字段
const copiedFields = {
@@ -1057,20 +1192,21 @@ export default {
actualWidth: parseFloat(this.coilInfo.actualWidth) || null,
temperGrade: this.coilInfo.temperGrade,
coatingType: this.coilInfo.coatingType,
chromePlateCoilNo: this.coilInfo.chromePlateCoilNo,
remark: this.coilInfo.remark,
productionStartTime: this.coilInfo.productionStartTime,
productionEndTime: this.coilInfo.productionEndTime,
productionDuration: this.coilInfo.productionDuration,
formattedDuration: this.coilInfo.productionDuration ? this.formatDuration(this.coilInfo.productionDuration * 60 * 1000) : ''
};
}
// 合并到分条表单
this.splitForm = {
...this.splitForm,
...copiedFields
};
}
this.$message.success('已复制源卷信息,请根据需要修改');
this.$message.success('已复制源卷信息,请根据需要修改')
},
// 暂存表单内容
@@ -1114,7 +1250,7 @@ export default {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
}).then(async() => {
try {
await delCoilCache(this.currentCache.cacheId)
this.$message.success('删除缓存成功')
@@ -1124,7 +1260,7 @@ export default {
}
})
}
},
}
}
</script>
@@ -1237,4 +1373,4 @@ export default {
.plan-sheet-section {
margin-top: 16px;
}
</style>
</style>

View File

@@ -60,14 +60,20 @@
</div>
<!-- 右侧更新表单 -->
<div>
<el-card class="form-card">
<div slot="header" class="card-header">
<span><i class="el-icon-edit-outline"></i> {{ '更新信息' }}</span>
<div>
<el-button size="small" @click="saveTemp" :loading="loading">暂存内容</el-button>
<el-button type="primary" size="small" @click="handleSave" :loading="loading">保存更新</el-button>
<el-card class="form-card">
<div slot="header" class="card-header">
<span><i class="el-icon-edit-outline"></i> {{ '更新信息' }}</span>
<div>
<el-button size="small" @click="saveTemp" :loading="loading">暂存内容</el-button>
<el-button type="primary" size="small" @click="handleSave" :loading="loading">保存更新</el-button>
</div>
</div>
</div>
<el-alert v-if="!isExemptFromValidation" type="warning" :closable="false" show-icon style="margin-bottom:12px">
<template slot="title">
更新后的<b>净重</b><b>实测厚度</b>均不能超过源卷的对应值
</template>
</el-alert>
<div v-if="matchedSpec" style="margin-bottom:10px">
<el-tag type="success" size="small">
@@ -530,6 +536,10 @@ export default {
isDrAction() {
return this.actionType === 504 || this.actionType === 524
},
/** 镀锌/酸轧产线免验净重和厚度范围 */
isExemptFromValidation() {
return [11, 120, 200, 201, 520, 202, 501, 521].includes(Number(this.actionType))
},
// 动态显示标签
getItemLabel() {
if (this.updateForm.materialType === '成品') {
@@ -814,6 +824,22 @@ export default {
}
}
// 校验净重和实测厚度不超过源卷(镀锌/酸轧除外)
if (!this.isExemptFromValidation) {
const parentNetWeight = parseFloat(this.currentInfo.netWeight) || 0
const parentThickness = parseFloat(this.currentInfo.actualThickness) || 0
const updateNetWeight = parseFloat(this.updateForm.netWeight) || 0
const updateThickness = parseFloat(this.updateForm.actualThickness) || 0
if (updateNetWeight > 0 && parentNetWeight > 0 && updateNetWeight > parentNetWeight) {
this.$message.error(`更新后净重(${updateNetWeight}T)不能超过源卷净重(${parentNetWeight}T)`)
return false
}
if (updateThickness > 0 && parentThickness > 0 && updateThickness > parentThickness) {
this.$message.error(`更新后实测厚度(${updateThickness}mm)不能超过源卷实测厚度(${parentThickness}mm)`)
return false
}
}
const loadingInstance = this.$loading({
lock: true,
text: '正在更新钢卷信息,请稍后...',