feat: 新增规格校验功能并优化钢卷号输入处理

1. 新增validSpecification规格校验函数,校验格式为数字.两位小数*数字的钢卷规格
2. 为多个页面的钢卷号输入框添加trim修饰符自动去除首尾空格
3. 在API层统一对钢卷号字段做trim预处理
4. 为原料和产品表单添加规格必填校验和格式校验
5. 新增钢卷信息修正页面,添加生产耗时自动计算功能
6. 优化部分页面的UI和代码冗余
This commit is contained in:
2026-06-15 10:56:28 +08:00
parent 6328b4ac7a
commit 7feaf8021b
14 changed files with 290 additions and 66 deletions

View File

@@ -148,10 +148,10 @@
<el-input v-model="form.enterCoilNo" placeholder="请输入入场钢卷号" :disabled="form.coilId" />
</el-form-item>
<el-form-item label="当前钢卷号" prop="currentCoilNo">
<el-input v-model="form.currentCoilNo" placeholder="请输入当前钢卷号" />
<el-input v-model.trim="form.currentCoilNo" placeholder="请输入当前钢卷号" />
</el-form-item>
<el-form-item label="厂家原料卷号" prop="supplierCoilNo">
<el-input v-model="form.supplierCoilNo" placeholder="请输入厂家原料卷号" />
<el-input v-model.trim="form.supplierCoilNo" placeholder="请输入厂家原料卷号" />
</el-form-item>
<el-form-item label="所在库位" prop="warehouseId">
<warehouse-select v-model="form.warehouseId" placeholder="请选择仓库/库区/库位" style="width: 100%;" clearable />
@@ -212,9 +212,6 @@
<el-form-item label="净重" prop="netWeight">
<el-input v-model="form.netWeight" placeholder="请输入净重" />
</el-form-item>
<el-form-item label="长度" prop="length">
<el-input v-model="form.length" placeholder="请输入长度" />
</el-form-item>
<el-form-item label="实测长度(mm)" prop="actualLength">
<el-input-number :controls="false" v-model="form.actualLength" placeholder="请输入实测长度" type="number"
:step="0.01" />
@@ -242,6 +239,24 @@
<el-form-item label="钢卷表面处理" prop="coilSurfaceTreatment">
<MemoInput storageKey="surfaceTreatmentDesc" v-model="form.coilSurfaceTreatment" placeholder="请输入钢卷表面处理" />
</el-form-item>
<el-form-item label="排产厚度(mm)" prop="scheduleThickness">
<el-input-number :controls="false" v-model="form.scheduleThickness" placeholder="请输入排产厚度" type="number"
:step="0.001" style="width: 100%;" />
</el-form-item>
<el-form-item label="生产开始时间" prop="productionStartTime">
<TimeInput v-model="form.productionStartTime" @input="calculateProductionDuration" />
</el-form-item>
<el-form-item label="生产结束时间" prop="productionEndTime">
<TimeInput v-model="form.productionEndTime" @input="calculateProductionDuration" :show-now-button="true" />
</el-form-item>
<el-form-item label="生产耗时" prop="productionDuration">
<el-input v-model="form.formattedDuration" placeholder="自动计算" disabled />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注" />
</el-form-item>
@@ -286,6 +301,8 @@ import ActualWarehouseSelect from "@/components/KLPService/ActualWarehouseSelect
import ProductSelect from "@/components/KLPService/ProductSelect";
import RawMaterialSelect from "@/components/KLPService/RawMaterialSelect";
import CoilTraceResult from "../panels/CoilTraceResult.vue";
import TimeInput from "@/components/TimeInput";
import ContractSelect from "@/components/KLPService/ContractSelect";
import { getCoilTagPrintType } from '@/views/wms/coil/js/coilPrint'
export default {
@@ -311,6 +328,8 @@ export default {
ProductSelect,
RawMaterialSelect,
CoilTraceResult,
TimeInput,
ContractSelect,
},
data() {
return {
@@ -477,6 +496,10 @@ export default {
{ label: '实测宽度(mm)', prop: 'actualWidth' },
{ label: '实测厚度(mm)', prop: 'actualThickness' },
{ label: '钢卷表面处理', prop: 'coilSurfaceTreatment' },
{ label: '排产厚度(mm)', prop: 'scheduleThickness' },
{ label: '生产开始时间', prop: 'productionStartTime' },
{ label: '生产结束时间', prop: 'productionEndTime' },
{ label: '生产耗时', prop: 'formattedDuration' },
],
title: '详细信息'
},
@@ -559,6 +582,38 @@ export default {
},
methods: {
parseTime,
formatDuration(milliseconds) {
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 remainingHours = hours % 24;
const remainingMinutes = minutes % 60;
let result = '';
if (days > 0) result += `${days}`;
if (remainingHours > 0) result += `${remainingHours}小时`;
if (remainingMinutes > 0) result += `${remainingMinutes}分钟`;
return result || '0分钟';
},
calculateProductionDuration() {
const { productionStartTime, productionEndTime } = this.form;
if (productionStartTime && productionEndTime) {
const start = new Date(productionStartTime).getTime();
const end = new Date(productionEndTime).getTime();
if (end < start) {
this.form.productionDuration = '';
this.form.formattedDuration = '';
} else {
const durationMs = end - start;
this.form.productionDuration = Math.round(durationMs / (1000 * 60));
this.form.formattedDuration = this.formatDuration(durationMs);
}
} else {
this.form.productionDuration = '';
this.form.formattedDuration = '';
}
},
// 进入数字钢卷页面
handleNumberCoilClick(row) {
this.$router.push({
@@ -627,6 +682,12 @@ export default {
coatingType: undefined,
actualLength: undefined,
actualWidth: undefined,
scheduleThickness: undefined,
productionStartTime: undefined,
productionEndTime: undefined,
productionDuration: undefined,
formattedDuration: undefined,
contractId: undefined,
};
this.resetForm("form");
},
@@ -816,6 +877,9 @@ export default {
this.form = {
...row,
};
if (this.form.productionDuration) {
this.form.formattedDuration = this.formatDuration(this.form.productionDuration * 60 * 1000);
}
this.title = "钢卷信息修正";
this.correctVisible = true
},

View File

@@ -232,11 +232,11 @@
<el-form-item label="入场钢卷号" prop="enterCoilNo">
<el-input v-model="form.enterCoilNo" placeholder="请输入入场钢卷号" :disabled="form.coilId" />
</el-form-item>
<el-form-item label="当前钢卷号" prop="currentCoilNo">
<el-input v-model="form.currentCoilNo" placeholder="请输入当前钢卷号" />
<el-form-item label ="当前钢卷号" prop="currentCoilNo">
<el-input v-model.trim="form.currentCoilNo" placeholder="请输入当前钢卷号" />
</el-form-item>
<el-form-item label="厂家原料卷号" prop="supplierCoilNo">
<el-input v-model="form.supplierCoilNo" placeholder="请输入厂家原料卷号" />
<el-input v-model.trim="form.supplierCoilNo" placeholder="请输入厂家原料卷号" />
</el-form-item>
<el-form-item label="所在库位" prop="warehouseId">
<warehouse-select v-model="form.warehouseId" placeholder="请选择仓库/库区/库位" style="width: 100%;" clearable />
@@ -297,9 +297,6 @@
<el-form-item label="净重" prop="netWeight">
<el-input v-model="form.netWeight" placeholder="请输入净重" />
</el-form-item>
<el-form-item label="长度(m)" prop="length">
<el-input v-model="form.length" placeholder="请输入长度" />
</el-form-item>
<el-form-item label="实测长度(m)" prop="actualLength">
<el-input-number :controls="false" v-model="form.actualLength" placeholder="请输入实测长度" type="number"
:step="0.01" />
@@ -327,6 +324,24 @@
<el-form-item label="钢卷表面处理" prop="coilSurfaceTreatment">
<MemoInput storageKey="surfaceTreatmentDesc" v-model="form.coilSurfaceTreatment" placeholder="请输入钢卷表面处理" />
</el-form-item>
<el-form-item label="排产厚度(mm)" prop="scheduleThickness">
<el-input-number :controls="false" v-model="form.scheduleThickness" placeholder="请输入排产厚度" type="number"
:step="0.001" style="width: 100%;" />
</el-form-item>
<el-form-item label="生产开始时间" prop="productionStartTime">
<TimeInput v-model="form.productionStartTime" @input="calculateProductionDuration" />
</el-form-item>
<el-form-item label="生产结束时间" prop="productionEndTime">
<TimeInput v-model="form.productionEndTime" @input="calculateProductionDuration" :show-now-button="true" />
</el-form-item>
<el-form-item label="生产耗时" prop="productionDuration">
<el-input v-model="form.formattedDuration" placeholder="自动计算" disabled />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注" />
</el-form-item>
@@ -366,6 +381,8 @@ import ActualWarehouseSelect from "@/components/KLPService/ActualWarehouseSelect
import ProductSelect from "@/components/KLPService/ProductSelect";
import RawMaterialSelect from "@/components/KLPService/RawMaterialSelect";
import CoilTraceResult from "../panels/CoilTraceResult.vue";
import TimeInput from "@/components/TimeInput";
import ContractSelect from "@/components/KLPService/ContractSelect";
import CoilSelector from '@/components/CoilSelector';
import CoilNo from '@/components/KLPService/Renderer/CoilNo.vue';
import { getCoilTagPrintType } from '@/views/wms/coil/js/coilPrint'
@@ -381,6 +398,8 @@ export default {
ProductSelect,
RawMaterialSelect,
CoilTraceResult,
TimeInput,
ContractSelect,
CoilSelector,
CoilNo
},
@@ -454,6 +473,10 @@ export default {
{ label: '实测宽度(mm)', prop: 'actualWidth' },
{ label: '实测厚度(mm)', prop: 'actualThickness' },
{ label: '钢卷表面处理', prop: 'coilSurfaceTreatment' },
{ label: '排产厚度(mm)', prop: 'scheduleThickness' },
{ label: '生产开始时间', prop: 'productionStartTime' },
{ label: '生产结束时间', prop: 'productionEndTime' },
{ label: '生产耗时', prop: 'formattedDuration' },
],
title: '详细信息'
},
@@ -586,6 +609,39 @@ export default {
methods: {
parseTime,
formatDuration(milliseconds) {
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 remainingHours = hours % 24;
const remainingMinutes = minutes % 60;
let result = '';
if (days > 0) result += `${days}`;
if (remainingHours > 0) result += `${remainingHours}小时`;
if (remainingMinutes > 0) result += `${remainingMinutes}分钟`;
return result || '0分钟';
},
calculateProductionDuration() {
const { productionStartTime, productionEndTime } = this.form;
if (productionStartTime && productionEndTime) {
const start = new Date(productionStartTime).getTime();
const end = new Date(productionEndTime).getTime();
if (end < start) {
this.form.productionDuration = '';
this.form.formattedDuration = '';
} else {
const durationMs = end - start;
this.form.productionDuration = Math.round(durationMs / (1000 * 60));
this.form.formattedDuration = this.formatDuration(durationMs);
}
} else {
this.form.productionDuration = '';
this.form.formattedDuration = '';
}
},
/** 查询用户列表 */
getUsers() {
listUser({ pageNum: 1, pageSize: 1000 }).then(response => {
@@ -794,6 +850,9 @@ export default {
this.form = {
...row,
};
if (this.form.productionDuration) {
this.form.formattedDuration = this.formatDuration(this.form.productionDuration * 60 * 1000);
}
this.title = "钢卷信息修正";
this.correctVisible = true
},
@@ -1017,22 +1076,6 @@ export default {
}
return {}
},
/** 根据操作类型获取图标 */
getActionIcon(actionType) {
const value = parseInt(actionType);
const iconMap = {
1: 'el-icon-connection', // 合卷
2: 'el-icon-s-operation', // 分条
3: 'el-icon-edit', // 更新
4: 'el-icon-truck', // 发货
5: 'el-icon-s-grid', // 移库
101: 'el-icon-scissors', // 纵剪分条
102: 'el-icon-s-operation', // 横切分条
103: 'el-icon-s-unfold' // 开卷分条
};
return iconMap[value] || 'el-icon-s-operation';
},
}
}
</script>

View File

@@ -111,7 +111,7 @@
<el-form size="small" label-width="80px" :model="targetCoil" :rules="rules">
<div class="form-row">
<el-form-item label="卷号" class="form-item-half" prop="currentCoilNo">
<el-input v-model="targetCoil.currentCoilNo" placeholder="输入目标卷号" :disabled="readonly"></el-input>
<el-input v-model.trim="targetCoil.currentCoilNo" placeholder="输入目标卷号" :disabled="readonly"></el-input>
<current-coil-no :current-coil-no="targetCoil.currentCoilNo" />
</el-form-item>
<el-form-item label="班组" class="form-item-half" prop="team">

View File

@@ -32,11 +32,6 @@
<!-- 物料卡片列表 -->
<div v-loading="materialLoading">
<!-- <div v-if="materialCoilList.length === 0" class="empty-state">
<i class="el-icon-box"></i>
<p>暂无待领物料</p>
</div> -->
<KLPTable :data="materialCoilList" height="calc(100vh - 340px)" :floatLayer="true" :floatLayerConfig="floatLayerConfig">
<el-table-column prop="currentCoilNo" label="当前钢卷号">
<template slot-scope="scope">
@@ -52,7 +47,6 @@
<template slot-scope="scope">
<el-button v-loading="buttonLoading" style="margin-left: 0px; padding: 4px !important;" type="default"
size="mini" icon="el-icon-view" @click="handlePreviewLabel(scope.row)" title="预览标签">预览</el-button>
<!-- <i class="el-icon-view param-icon" @click="handlePreviewLabel(scope.row)" title="查看标签"></i> -->
<el-button v-loading="buttonLoading" style="margin-left: 0px; padding: 4px !important;" type="default"
size="mini" icon="el-icon-printer" @click="handlePrintLabel(scope.row)" title="打印标签">打印</el-button>
<el-button v-if="useSpecialSplit" :style="splitButtonStyle" icon="el-icon-scissors" size="mini"
@@ -66,28 +60,7 @@
</el-button>
</template>
</el-table-column>
</KLPTable>
<!-- <coil-card v-for="(item, index) in materialCoilList" :key="item.coilId || index" :coil="item"
:card-style="{ border: item.abnormalCount > 0 ? '1px solid red' : ' 1px solid #e4e7ed' }">
<template slot="header">
<i class="el-icon-view param-icon" @click="handlePreviewLabel(item)" title="查看标签"></i>
<el-button v-loading="buttonLoading" style="margin-left: 0px; padding: 4px !important;" type="text"
size="mini" @click="handlePrintLabel(item)" title="打印标签">打印</el-button>
</template>
<template slot="footer">
<el-button v-if="useSpecialSplit" :style="splitButtonStyle" icon="el-icon-scissors" size="mini"
@click="handleStartSplit(item)" :loading="buttonLoading" class="action-btn">加工</el-button>
<el-button v-else type="primary" icon="el-icon-check" size="mini" @click="handlePickMaterial(item)"
: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="buttonLoading" class="action-btn">
缺陷明细
<span v-if="item.abnormalCount > 0">({{ item.abnormalCount }})</span>
</el-button>
</template>
</coil-card> -->
</div>
<!-- 分页 -->

View File

@@ -116,7 +116,7 @@
<el-input v-model="splitForm.chromePlateCoilNo" placeholder="请输入镀铬卷号" />
</el-form-item>
<el-form-item label="当前钢卷号" prop="currentCoilNo">
<el-input v-model="splitForm.currentCoilNo" placeholder="请输入当前钢卷号" />
<el-input v-model.trim="splitForm.currentCoilNo" placeholder="请输入当前钢卷号" />
<current-coil-no :current-coil-no="splitForm.currentCoilNo" />
</el-form-item>
<el-form-item label="所在库位" prop="warehouseId">

View File

@@ -116,7 +116,7 @@
<el-form size="small" label-width="80px">
<div class="form-row">
<el-form-item label="卷号" required class="form-item-half">
<el-input v-model="item.currentCoilNo" placeholder="输入子卷卷号" :disabled="readonly"></el-input>
<el-input v-model.trim="item.currentCoilNo" placeholder="输入子卷卷号" :disabled="readonly"></el-input>
<current-coil-no :current-coil-no="item.currentCoilNo" />
</el-form-item>
<el-form-item label="班组" required class="form-item-half">

View File

@@ -56,7 +56,7 @@
<el-row>
<el-col :span="16">
<el-form-item label="当前钢卷号" prop="currentCoilNo">
<el-input v-model="updateForm.currentCoilNo" placeholder="请输入当前钢卷号">
<el-input v-model.trim="updateForm.currentCoilNo" placeholder="请输入当前钢卷号">
<template slot="prepend">
<i class="el-icon-document"></i> <current-coil-no
:current-coil-no="updateForm.currentCoilNo"></current-coil-no>

View File

@@ -121,6 +121,7 @@
<script>
import { listProduct, getProduct, delProduct, updateProduct, addProductWithBom } from "@/api/wms/product";
import UserSelect from '@/components/KLPService/UserSelect';
import { validSpecification } from '@/utils/validate';
export default {
name: "Product",
@@ -185,6 +186,10 @@ export default {
// owner: [
// { required: true, message: "负责人不能为空", trigger: "blur" }
// ],
specification: [
{ required: true, message: "规格不能为空", trigger: "blur" },
{ validator: validSpecification, trigger: 'blur' }
],
},
bomDialogVisible: false,
bomId: undefined,

View File

@@ -161,6 +161,7 @@
<script>
import { listRawMaterial, getRawMaterial, delRawMaterial, updateRawMaterial, addRawMaterialWithBom } from "@/api/wms/rawMaterial";
import { validSpecification } from '@/utils/validate';
export default {
name: "RawMaterial",
@@ -233,6 +234,10 @@ export default {
unit: [
{ required: true, message: "计量单位不能为空", trigger: "blur" }
],
specification: [
{ required: true, message: "规格不能为空", trigger: "blur" },
{ validator: validSpecification, trigger: 'blur' }
],
},
paramDialogVisible: false,
paramRow: null,