feat(qc): 新增理化检验相关功能及优化质检流程

1. 新增化学成分明细和物理性能明细的API与管理页面
2. 在钢卷详情页添加检验信息展示模块
3. 优化质保书预览的签章显示逻辑,仅审批通过后显示
4. 重构质保书列表为表格形式,新增审批流程功能
5. 优化质保书选择弹窗的钢卷查询条件
6. 新增批量新增质保书明细时自动填充理化数据功能
This commit is contained in:
2026-05-18 17:54:12 +08:00
parent a705c6a4a9
commit 1bd55b12ec
8 changed files with 1177 additions and 313 deletions

View File

@@ -24,7 +24,8 @@
<div class="tab-info">请点击齿轮图标选择质保书</div>
</div>
</div>
<button v-if="certificateList.length > 0 && queryParams.pageNum < totalPage" class="nav-btn next" @click="nextPage">
<button v-if="certificateList.length > 0 && queryParams.pageNum < totalPage" class="nav-btn next"
@click="nextPage">
<i class="el-icon-arrow-right"></i>
</button>
</div>
@@ -62,7 +63,8 @@
</el-col>
<el-col :span="6">
<el-form-item label="签发日期">
<el-date-picker v-model="currentCertificateInfo.issueDate" type="date" @change="handleCertificateInfoChange" />
<el-date-picker v-model="currentCertificateInfo.issueDate" type="date"
@change="handleCertificateInfoChange" />
</el-form-item>
</el-col>
</el-row>
@@ -216,9 +218,14 @@
<el-dialog :title="'选择钢卷'" :visible.sync="coilDialogVisible" width="900px" append-to-body>
<div class="dialog-toolbar">
<el-form :model="coilQueryParams" ref="coilQueryForm" size="small" :inline="true" label-width="68px">
<el-form-item label="钢卷号" prop="coilNo">
<el-input v-model="coilQueryParams.coilNo" placeholder="请输入钢卷号" clearable
<el-form-item label="入场钢卷号" prop="enterCoilNo">
<el-input v-model="coilQueryParams.enterCoilNo" placeholder="请输入入场钢卷号" clearable
@keyup.enter.native="handleCoilQuery" />
</el-form-item>
<el-form-item label="当前钢卷号" prop="currentCoilNo">
<el-input v-model="coilQueryParams.currentCoilNo" placeholder="请输入当前钢卷号" clearable
@keyup.enter.native="handleCoilQuery" />
</el-form-item>
<el-form-item label="材质" prop="material">
@@ -236,18 +243,20 @@
</el-form>
</div>
<el-table v-loading="coilLoading" :data="coilList" height="350px" @row-click="handleCoilSelect">
<el-table-column label="钢卷号" align="center" prop="currentCoilNo" />
<el-table-column label="入场钢卷号" align="center" prop="enterCoilNo" />
<el-table-column label="当前钢卷号" align="center" prop="currentCoilNo" />
<el-table-column label="材质" align="center" prop="material" />
<el-table-column label="规格" align="center" prop="specification" />
<el-table-column label="重量(t)" align="center" prop="netWeight" />
</el-table>
<pagination v-show="coilTotal > 0" :total="coilTotal" :page.sync="coilQueryParams.pageNum"
<pagination v-show="coilTotal > 0" :total="coilTotal" :page.sync="coilQueryParams.pageNum"
:limit.sync="coilQueryParams.pageSize" @pagination="getCoilList" />
</el-dialog>
<el-dialog :title="'选择质保书'" :visible.sync="certificateDialogVisible" width="900px" append-to-body>
<div class="dialog-toolbar">
<el-form :model="certificateQueryParams" ref="certificateQueryForm" size="small" :inline="true" label-width="68px">
<el-form :model="certificateQueryParams" ref="certificateQueryForm" size="small" :inline="true"
label-width="68px">
<el-form-item label="证明书号" prop="certificateNo">
<el-input v-model="certificateQueryParams.certificateNo" placeholder="请输入证明书号" clearable
@keyup.enter.native="handleCertificateQuery" />
@@ -278,9 +287,9 @@
<span>{{ parseTime(scope.row.issueDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
<!-- <el-table-column label="备注" align="center" prop="remark" /> -->
</el-table>
<pagination v-show="certificateTotal > 0" :total="certificateTotal" :page.sync="certificateQueryParams.pageNum"
<pagination v-show="certificateTotal > 0" :total="certificateTotal" :page.sync="certificateQueryParams.pageNum"
:limit.sync="certificateQueryParams.pageSize" @pagination="getCertificateList" />
</el-dialog>
@@ -305,7 +314,8 @@
<el-input v-model="certificateForm.manufacturer" placeholder="请输入生产厂家" />
</el-form-item>
<el-form-item label="签发日期" prop="issueDate">
<el-date-picker v-model="certificateForm.issueDate" value-format="yyyy-MM-dd HH:mm:ss" type="date" placeholder="请选择签发日期" />
<el-date-picker v-model="certificateForm.issueDate" value-format="yyyy-MM-dd HH:mm:ss" type="date"
placeholder="请选择签发日期" />
</el-form-item>
<el-form-item label="质保证明说明" prop="note">
<el-input v-model="certificateForm.note" type="textarea" placeholder="请输入内容" auto-height />
@@ -320,20 +330,12 @@
</div>
</el-dialog>
<CoilSelector
:visible.sync="batchAddDialogVisible"
:use-trigger="false"
:multiple="true"
@confirm="handleBatchAddConfirm"
/>
<CoilSelector :visible.sync="batchAddDialogVisible" :use-trigger="false" :multiple="true"
@confirm="handleBatchAddConfirm" />
<!-- 隐藏的打印组件 -->
<CertificatePrintPreview
ref="certificatePrint"
v-show="false"
:certificate="printCertificateData"
:items="printItemsData"
/>
<CertificatePrintPreview ref="certificatePrint" v-show="false" :certificate="printCertificateData"
:items="printItemsData" />
</div>
</template>
@@ -341,6 +343,8 @@
import { listCertificateItem, getCertificateItem, delCertificateItem, addCertificateItem, updateCertificateItem } from "@/api/mes/qc/certificateItem";
import { listCertificate, getCertificate, updateCertificate, addCertificate } from "@/api/mes/qc/certificate";
import { listMaterialCoil } from "@/api/wms/coil";
import { listChemicalItem } from "@/api/mes/qc/chemicalItem";
import { listPhysicalItem } from "@/api/mes/qc/physicalItem";
import CoilSelector from "@/components/CoilSelector/index.vue";
import CertificatePrintPreview from "./components/CertificatePrintPreview.vue";
import { print as printPdf } from "./lib/printUtils";
@@ -515,13 +519,27 @@ export default {
};
this.getCoilList();
},
handleCoilSelect(row) {
async fetchLatestChemAndPhys(coilId) {
if (!coilId) return {};
const [chemRes, physRes] = await Promise.all([
listChemicalItem({ coilId, pageNum: 1, pageSize: 1 }),
listPhysicalItem({ coilId, pageNum: 1, pageSize: 1 })
]);
const chem = chemRes.rows && chemRes.rows[0] || {};
const phys = physRes.rows && physRes.rows[0] || {};
const { c, si, mn, p, s, als, yieldStrength, tensileStrength, elongation, hardness, bendingTest, surfaceQuality, surfaceStructure, edgeStatus } = { ...chem, ...phys };
return { c, si, mn, p, s, als, yieldStrength, tensileStrength, elongation, hardness, bendingTest, surfaceQuality, surfaceStructure, edgeStatus };
},
async handleCoilSelect(row) {
if (this.currentEditRow) {
this.currentEditRow.coilNo = row.currentCoilNo;
this.currentEditRow.materialType = row.material;
this.currentEditRow.size = row.specification;
this.currentEditRow.weight = row.netWeight;
this.currentEditRow.pieces = 1;
const editRow = this.currentEditRow;
editRow.coilNo = row.currentCoilNo;
editRow.materialType = row.material;
editRow.size = row.specification;
editRow.weight = row.netWeight;
editRow.pieces = 1;
const data = await this.fetchLatestChemAndPhys(row.coilId);
Object.assign(editRow, data);
}
this.coilDialogVisible = false;
this.currentEditRow = null;
@@ -556,7 +574,7 @@ export default {
openBatchAddDialog() {
this.batchAddDialogVisible = true;
},
handleBatchAddConfirm(coils) {
async handleBatchAddConfirm(coils) {
if (!coils || coils.length === 0) {
this.$message.warning('请选择钢卷');
return;
@@ -566,41 +584,36 @@ export default {
let successCount = 0;
let failCount = 0;
coils.forEach((coil, index) => {
const newRow = {
certificateId: this.currentCertificateId,
itemSeqNo: this.certificateItemList.length + index + 1,
coilNo: coil.currentCoilNo,
materialType: coil.material,
size: coil.specification,
weight: coil.netWeight,
pieces: 1
};
addCertificateItem(newRow).then(() => {
for (let index = 0; index < coils.length; index++) {
const coil = coils[index];
try {
const data = await this.fetchLatestChemAndPhys(coil.coilId);
const newRow = {
certificateId: this.currentCertificateId,
itemSeqNo: this.certificateItemList.length + index + 1,
coilNo: coil.currentCoilNo,
materialType: coil.material,
size: coil.specification,
weight: coil.netWeight,
pieces: 1,
...data
};
await addCertificateItem(newRow);
successCount++;
if (successCount + failCount === totalCount) {
this.batchAddDialogVisible = false;
if (successCount === totalCount) {
this.$message.success(`批量新增成功,共新增 ${successCount} 条明细`);
} else {
this.$message.warning(`批量新增完成,成功 ${successCount} 条,失败 ${failCount}`);
}
this.getList();
}
}).catch(() => {
} catch {
failCount++;
if (successCount + failCount === totalCount) {
this.batchAddDialogVisible = false;
if (failCount === totalCount) {
this.$message.error('批量新增失败');
} else {
this.$message.warning(`批量新增完成,成功 ${successCount},失败 ${failCount}`);
}
this.getList();
}
});
});
}
}
this.batchAddDialogVisible = false;
if (failCount === 0) {
this.$message.success(`批量新增成功,共新增 ${successCount}明细`);
} else if (successCount === 0) {
this.$message.error('批量新增失败');
} else {
this.$message.warning(`批量新增完成,成功 ${successCount} 条,失败 ${failCount}`);
}
this.getList();
},
handleAddCertificate() {
this.certificateForm = {