Browse Source
feat(report): 添加出货报告打印功能
feat(report): 添加出货报告打印功能
- 在路由配置中新增 shipmentReport 页面路由 - 添加 IQC 检验单列表和明细查询 API 接口 - 添加属性模板相关 API 接口(模板列表、明细、项目列表等) - 新建出货报告打印页面组件,实现完整的报表功能 - 实现检验单选择、属性模板选择、检验项目匹配回填等功能 - 添加报表打印功能和相应的样式适配master
3 changed files with 985 additions and 0 deletions
@ -0,0 +1,971 @@ |
|||||
|
<template> |
||||
|
<div class="shipment-report-container"> |
||||
|
<!-- 顶部操作栏 --> |
||||
|
<div class="toolbar"> |
||||
|
<el-button type="warning" @click="openTemplateDialog">选择模板</el-button> |
||||
|
<el-button type="primary" @click="openSelectDialog">选择检验单</el-button> |
||||
|
<el-button type="success" @click="printReport">打印</el-button> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 报表主体 --> |
||||
|
<div class="report-content" v-if="selectedTemplateCode || reportData.inspectionNo"> |
||||
|
<!-- 上半部分:基本信息表格 --> |
||||
|
<div class="report-header"> |
||||
|
<h2 style="text-align: center; margin-bottom: 10px;">出货报告打印报表</h2> |
||||
|
|
||||
|
<table class="info-table"> |
||||
|
<tr> |
||||
|
<td class="label-cell">选择检验单:</td> |
||||
|
<td class="value-cell"> |
||||
|
<el-button size="small" @click="openSelectDialog">{{ reportData.inspectionNo || '请选择' }}</el-button> |
||||
|
</td> |
||||
|
<td class="label-cell">报告日期</td> |
||||
|
<td class="value-cell">{{ currentDate }}</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td class="label-cell">客户:</td> |
||||
|
<td class="value-cell">{{ reportData.customerName || '-' }}</td> |
||||
|
<td class="label-cell">采购单号:</td> |
||||
|
<td class="value-cell">{{ reportData.poOrderNo || '-' }}</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td class="label-cell">零件编号:</td> |
||||
|
<td class="value-cell">{{ reportData.partNo }}</td> |
||||
|
<td class="label-cell">胶料:</td> |
||||
|
<td class="value-cell">{{ reportData.partDesc || '-' }}</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td class="label-cell">材料规格:</td> |
||||
|
<td class="value-cell">{{ reportData.spec || '-' }}</td> |
||||
|
<td class="label-cell">供应商:</td> |
||||
|
<td class="value-cell">{{ reportData.supplierNo || '-' }}</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td class="label-cell">零件描述:</td> |
||||
|
<td class="value-cell" colspan="3">{{ reportData.partDesc || '-' }}</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td class="label-cell">单件重量</td> |
||||
|
<td class="value-cell">-</td> |
||||
|
<td class="label-cell">着色剂:</td> |
||||
|
<td class="value-cell">-</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td class="label-cell">测试标准:</td> |
||||
|
<td class="value-cell" colspan="3"> |
||||
|
<label class="check-option" v-for="item in testStandardOptions" :key="item"> |
||||
|
<input type="checkbox" :value="item" v-model="selectedTestStandards" />{{ item }} |
||||
|
</label> |
||||
|
</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td class="label-cell">制作工艺:</td> |
||||
|
<td class="value-cell" colspan="3"> |
||||
|
<label class="check-option" v-for="item in makingTechnicsOptions" :key="item"> |
||||
|
<input type="checkbox" :value="item" v-model="selectedMakingTechnics" />{{ item }} |
||||
|
</label> |
||||
|
</td> |
||||
|
</tr> |
||||
|
</table> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 下半部分:原始性能项目表格(显示属性模板及属性模板明细默认值) --> |
||||
|
<div class="report-table-section"> |
||||
|
<div class="section-header"> |
||||
|
<h3 style="margin-bottom: 10px;">原始性能项目</h3> |
||||
|
<span class="template-info">属性模板:{{ selectedTemplateDesc || selectedTemplateCode || '-' }}</span> |
||||
|
</div> |
||||
|
<table class="performance-table"> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
<th width="60">序号</th> |
||||
|
<th width="200">属性模板</th> |
||||
|
<th width="300">属性模板明细</th> |
||||
|
<th width="200">检验项目名称</th> |
||||
|
<th width="100" class="no-print">操作</th> |
||||
|
<th width="150">标准值</th> |
||||
|
<th width="100">最大值</th> |
||||
|
<th width="100">最小值</th> |
||||
|
<th width="120">结果</th> |
||||
|
<th width="80">合格</th> |
||||
|
<th width="80">不合格</th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
<tr v-for="(item, index) in attributeTableData" :key="index"> |
||||
|
<td>{{ index + 1 }}</td> |
||||
|
<td>{{ item.codeNo || selectedTemplateCode || '-' }}</td> |
||||
|
<td class="item-cell">{{ item.itemDesc || '-' }}</td> |
||||
|
<td class="item-cell">{{ item.selectedItemDesc || '-' }}</td> |
||||
|
<td class="no-print"> |
||||
|
<el-button size="mini" @click="openAttributeItemDialog(item)">选择</el-button> |
||||
|
</td> |
||||
|
<td>{{ item.stdValue != null && item.stdValue !== '' ? item.stdValue : '-' }}</td> |
||||
|
<td>{{ item.maxValue != null && item.maxValue !== '' ? item.maxValue : '-' }}</td> |
||||
|
<td>{{ item.minValue != null && item.minValue !== '' ? item.minValue : '-' }}</td> |
||||
|
<td class="result-cell">{{ item.textValue || '-' }}</td> |
||||
|
<td class="check-cell">{{ item.itemResult === 'Y' ? '✓' : '' }}</td> |
||||
|
<td class="check-cell">{{ item.itemResult === 'N' ? '✓' : '' }}</td> |
||||
|
</tr> |
||||
|
<tr v-if="attributeTableData.length === 0"> |
||||
|
<td colspan="11">暂无属性模板明细数据,请点击"选择模板"按钮加载</td> |
||||
|
</tr> |
||||
|
</tbody> |
||||
|
</table> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 未选择数据时的提示 --> |
||||
|
<div v-else class="empty-state"> |
||||
|
<i class="el-icon-document" style="font-size: 60px; color: #dcdfe6;"></i> |
||||
|
<p style="color: #909399; margin-top: 20px;">请先点击"选择模板"按钮选择属性模板,再选择检验单</p> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 选择检验单弹窗 --> |
||||
|
<el-dialog |
||||
|
title="选择检验单" |
||||
|
:visible.sync="selectDialogVisible" |
||||
|
width="90%" |
||||
|
top="5vh" |
||||
|
height="70vh" |
||||
|
:modal-append-to-body="false" |
||||
|
:destroy-on-close="true"> |
||||
|
|
||||
|
<!-- 筛选条件 --> |
||||
|
<el-form :inline="true" :model="searchData" size="small"> |
||||
|
<el-form-item label="检验单号"> |
||||
|
<el-input v-model="searchData.inspectionNo" placeholder="请输入" clearable style="width: 150px"></el-input> |
||||
|
</el-form-item> |
||||
|
<el-form-item label="物料编码"> |
||||
|
<el-input v-model="searchData.partNo" placeholder="请输入" clearable style="width: 150px"></el-input> |
||||
|
</el-form-item> |
||||
|
<el-form-item label="物料名称"> |
||||
|
<el-input v-model="searchData.partDesc" placeholder="请输入" clearable style="width: 200px"></el-input> |
||||
|
</el-form-item> |
||||
|
<el-form-item> |
||||
|
<el-button type="primary" @click="searchInspectionList">查询</el-button> |
||||
|
<el-button @click="resetSearch">重置</el-button> |
||||
|
</el-form-item> |
||||
|
</el-form> |
||||
|
|
||||
|
<!-- 数据表格 --> |
||||
|
<el-table |
||||
|
:data="inspectionList" |
||||
|
border |
||||
|
stripe |
||||
|
highlight-current-row |
||||
|
@current-change="handleCurrentChange" |
||||
|
@row-dblclick="handleRowDblClick" |
||||
|
style="width: 100%" |
||||
|
height="450"> |
||||
|
<el-table-column type="index" label="序号" width="60" align="center"></el-table-column> |
||||
|
<el-table-column prop="inspectionNo" label="检验单号" min-width="150"></el-table-column> |
||||
|
<el-table-column prop="inspectionTypeName" label="检验类型" min-width="100"></el-table-column> |
||||
|
<el-table-column prop="partNo" label="物料编码" min-width="120"></el-table-column> |
||||
|
<el-table-column prop="partDesc" label="物料名称" min-width="150"></el-table-column> |
||||
|
<el-table-column prop="customerName" label="客户名称" min-width="120"></el-table-column> |
||||
|
<el-table-column prop="supplierDesc" label="供应商" min-width="120"></el-table-column> |
||||
|
<el-table-column prop="rollQty" label="到货数量" min-width="100" align="right"></el-table-column> |
||||
|
<el-table-column prop="samplingQty" label="抽样数量" min-width="100" align="right"></el-table-column> |
||||
|
<el-table-column prop="inspectionResult" label="检验结论" min-width="100" align="center"> |
||||
|
<template slot-scope="scope"> |
||||
|
<span :style="{ color: scope.row.inspectionResult === '合格' ? 'green' : 'red' }"> |
||||
|
{{ scope.row.inspectionResult }} |
||||
|
</span> |
||||
|
</template> |
||||
|
</el-table-column> |
||||
|
<el-table-column prop="taskDate" label="送检日期" min-width="150"> |
||||
|
<template slot-scope="scope"> |
||||
|
{{ formatDate(scope.row.taskDate) }} |
||||
|
</template> |
||||
|
</el-table-column> |
||||
|
</el-table> |
||||
|
|
||||
|
<!-- 分页 --> |
||||
|
<el-pagination |
||||
|
@size-change="handleSizeChange" |
||||
|
@current-change="handlePageChange" |
||||
|
:current-page="searchData.page" |
||||
|
:page-sizes="[10, 20, 50, 100]" |
||||
|
:page-size="searchData.limit" |
||||
|
:total="totalPage" |
||||
|
layout="total, sizes, prev, pager, next, jumper" |
||||
|
style="margin-top: 10px; text-align: right; padding-bottom: 10px"> |
||||
|
</el-pagination> |
||||
|
|
||||
|
<div slot="footer" class="dialog-footer"> |
||||
|
<el-button @click="selectDialogVisible = false">取消</el-button> |
||||
|
<el-button type="primary" @click="confirmSelectionlection" :disabled="!selectedRow">确定</el-button> |
||||
|
</div> |
||||
|
</el-dialog> |
||||
|
|
||||
|
<!-- 选择模板弹窗(属性模板) --> |
||||
|
<el-dialog |
||||
|
title="选择模板" |
||||
|
:visible.sync="templateDialogVisible" |
||||
|
width="60%" |
||||
|
top="8vh" |
||||
|
:modal-append-to-body="false" |
||||
|
:destroy-on-close="true"> |
||||
|
|
||||
|
<!-- 筛选条件 --> |
||||
|
<el-form :inline="true" :model="templateSearchData" size="small"> |
||||
|
<el-form-item label="模板编号"> |
||||
|
<el-input v-model="templateSearchData.codeNo" placeholder="请输入" clearable style="width: 150px"></el-input> |
||||
|
</el-form-item> |
||||
|
<el-form-item label="模板名称"> |
||||
|
<el-input v-model="templateSearchData.codeDesc" placeholder="请输入" clearable style="width: 200px"></el-input> |
||||
|
</el-form-item> |
||||
|
<el-form-item> |
||||
|
<el-button type="primary" @click="searchTemplateList">查询</el-button> |
||||
|
<el-button @click="resetTemplateSearch">重置</el-button> |
||||
|
</el-form-item> |
||||
|
</el-form> |
||||
|
|
||||
|
<!-- 属性模板列表 --> |
||||
|
<el-table |
||||
|
:data="attributeTemplateList" |
||||
|
border |
||||
|
stripe |
||||
|
highlight-current-row |
||||
|
@current-change="handleTemplateCurrentChange" |
||||
|
@row-dblclick="handleTemplateRowDblClick" |
||||
|
style="width: 100%" |
||||
|
height="400"> |
||||
|
<el-table-column type="index" label="序号" width="60" align="center"></el-table-column> |
||||
|
<el-table-column prop="codeNo" label="属性模板编号" min-width="150"></el-table-column> |
||||
|
<el-table-column prop="codeDesc" label="属性模板名称" min-width="220"></el-table-column> |
||||
|
<el-table-column prop="functionType" label="功能类型" min-width="100"></el-table-column> |
||||
|
</el-table> |
||||
|
|
||||
|
<!-- 分页 --> |
||||
|
<el-pagination |
||||
|
@size-change="handleTemplateSizeChange" |
||||
|
@current-change="handleTemplatePageChange" |
||||
|
:current-page="templateSearchData.page" |
||||
|
:page-sizes="[10, 20, 50, 100]" |
||||
|
:page-size="templateSearchData.limit" |
||||
|
:total="templateTotalPage" |
||||
|
layout="total, sizes, prev, pager, next, jumper" |
||||
|
style="margin-top: 10px; text-align: right;"> |
||||
|
</el-pagination> |
||||
|
|
||||
|
<div slot="footer" class="dialog-footer"> |
||||
|
<el-button @click="templateDialogVisible = false">取消</el-button> |
||||
|
<el-button type="primary" @click="confirmTemplateSelection" :disabled="!selectedTemplateRow">确定</el-button> |
||||
|
</div> |
||||
|
</el-dialog> |
||||
|
|
||||
|
<!-- 选择检验项目弹窗(数据源:当前检验单的 qc_iqc_detailed_record 明细) --> |
||||
|
<el-dialog |
||||
|
title="选择检验项目" |
||||
|
:visible.sync="attributeItemDialogVisible" |
||||
|
width="60%" |
||||
|
top="8vh" |
||||
|
:modal-append-to-body="false" |
||||
|
:destroy-on-close="true"> |
||||
|
|
||||
|
<!-- 筛选条件 --> |
||||
|
<el-form :inline="true" :model="attributeItemSearchData" size="small"> |
||||
|
<el-form-item label="项目名称"> |
||||
|
<el-input v-model="attributeItemSearchData.itemDesc" placeholder="请输入" clearable style="width: 200px"></el-input> |
||||
|
</el-form-item> |
||||
|
<el-form-item> |
||||
|
<el-button type="primary" @click="searchAttributeItemList">查询</el-button> |
||||
|
</el-form-item> |
||||
|
</el-form> |
||||
|
|
||||
|
<!-- 检验项目明细列表 --> |
||||
|
<el-table |
||||
|
:data="attributeItemList" |
||||
|
border |
||||
|
stripe |
||||
|
highlight-current-row |
||||
|
@current-change="handleAttributeItemCurrentChange" |
||||
|
@row-dblclick="handleAttributeItemRowDblClick" |
||||
|
style="width: 100%" |
||||
|
height="400"> |
||||
|
<el-table-column type="index" label="序号" width="60" align="center"></el-table-column> |
||||
|
<el-table-column prop="itemNo" label="检验项目编码" min-width="120"></el-table-column> |
||||
|
<el-table-column prop="itemDesc" label="检验项目名称" min-width="180"></el-table-column> |
||||
|
<el-table-column prop="textValue" label="实测值" min-width="120"></el-table-column> |
||||
|
<el-table-column prop="itemResultDesc" label="结论" min-width="90" align="center"></el-table-column> |
||||
|
</el-table> |
||||
|
|
||||
|
<!-- 分页 --> |
||||
|
<el-pagination |
||||
|
@size-change="handleAttributeItemSizeChange" |
||||
|
@current-change="handleAttributeItemPageChange" |
||||
|
:current-page="attributeItemSearchData.page" |
||||
|
:page-sizes="[10, 20, 50, 100]" |
||||
|
:page-size="attributeItemSearchData.limit" |
||||
|
:total="attributeItemTotalPage" |
||||
|
layout="total, sizes, prev, pager, next, jumper" |
||||
|
style="margin-top: 10px; text-align: right;"> |
||||
|
</el-pagination> |
||||
|
|
||||
|
<div slot="footer" class="dialog-footer"> |
||||
|
<el-button @click="attributeItemDialogVisible = false">取消</el-button> |
||||
|
<el-button type="primary" @click="confirmAttributeItemSelection" :disabled="!selectedAttributeItemRow">确定</el-button> |
||||
|
</div> |
||||
|
</el-dialog> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { getIQCRecordList, getPropertiesModelList, getPropertiesModelDetail, getIQCDetailedRecordList } from "@/api/qc/qc_report.js" |
||||
|
|
||||
|
export default { |
||||
|
name: "出货报告打印报表", |
||||
|
data() { |
||||
|
return { |
||||
|
// 当前日期 |
||||
|
currentDate: '', |
||||
|
|
||||
|
// 报表数据 |
||||
|
reportData: {}, |
||||
|
|
||||
|
// 属性模板明细表格数据(属性模板 + 属性模板明细默认值) |
||||
|
attributeTableData: [], |
||||
|
|
||||
|
// 当前选择的属性模板(PropertiesModelHeader.CodeNo / CodeDesc) |
||||
|
selectedTemplateCode: '', |
||||
|
selectedTemplateDesc: '', |
||||
|
|
||||
|
// 选择模板弹窗 |
||||
|
templateDialogVisible: false, |
||||
|
selectedTemplateRow: null, |
||||
|
attributeTemplateList: [], |
||||
|
templateTotalPage: 0, |
||||
|
templateSearchData: { |
||||
|
codeNo: '', |
||||
|
codeDesc: '', |
||||
|
page: 1, |
||||
|
limit: 10 |
||||
|
}, |
||||
|
|
||||
|
// 选择属性项目弹窗 |
||||
|
attributeItemDialogVisible: false, |
||||
|
selectedAttributeItemRow: null, |
||||
|
currentAttributeRow: null, |
||||
|
attributeItemList: [], |
||||
|
attributeItemTotalPage: 0, |
||||
|
attributeItemSearchData: { |
||||
|
itemDesc: '', |
||||
|
page: 1, |
||||
|
limit: 10 |
||||
|
}, |
||||
|
|
||||
|
// 测试标准选项及用户勾选 |
||||
|
testStandardOptions: ['ASTM', 'JIS', 'DIN', 'ISO', 'G/B'], |
||||
|
selectedTestStandards: [], |
||||
|
|
||||
|
// 制作工艺选项及用户勾选 |
||||
|
makingTechnicsOptions: ['模压', '挤出', '压延', '注塑', '冲切'], |
||||
|
selectedMakingTechnics: [], |
||||
|
|
||||
|
// 选择检验单弹窗 |
||||
|
selectDialogVisible: false, |
||||
|
selectedRow: null, |
||||
|
inspectionList: [], |
||||
|
totalPage: 0, |
||||
|
|
||||
|
// 搜索条件 |
||||
|
searchData: { |
||||
|
taskType: 'IQC', // 默认为 IQC |
||||
|
site: '', |
||||
|
userName: this.$store.state.user.name, |
||||
|
inspectionNo: '', |
||||
|
partNo: '', |
||||
|
partDesc: '', |
||||
|
page: 1, |
||||
|
limit: 10 |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
this.setCurrentDate() |
||||
|
}, |
||||
|
methods: { |
||||
|
// 设置当前日期 |
||||
|
setCurrentDate() { |
||||
|
const now = new Date() |
||||
|
const year = now.getFullYear() |
||||
|
const month = String(now.getMonth() + 1).padStart(2, '0') |
||||
|
const day = String(now.getDate()).padStart(2, '0') |
||||
|
this.currentDate = `${year}/${month}/${day}` |
||||
|
}, |
||||
|
|
||||
|
// 打开选择检验单弹窗(需先选择属性模板) |
||||
|
openSelectDialog() { |
||||
|
if (!this.selectedTemplateCode) { |
||||
|
this.$message.warning('请先选择属性模板') |
||||
|
this.openTemplateDialog() |
||||
|
return |
||||
|
} |
||||
|
this.selectDialogVisible = true |
||||
|
this.resetSearch() |
||||
|
}, |
||||
|
|
||||
|
// 任务类型改变时自动查询 |
||||
|
handleTaskTypeChange() { |
||||
|
this.searchData.page = 1 |
||||
|
this.searchInspectionList() |
||||
|
}, |
||||
|
|
||||
|
// 查询检验单列表 |
||||
|
searchInspectionList() { |
||||
|
// 直接使用 IQC 报表查询 |
||||
|
const queryParams = { |
||||
|
site: this.searchData.site || '', |
||||
|
userName: this.searchData.userName || this.$store.state.user.name, |
||||
|
inspectionNo: this.searchData.inspectionNo || '', |
||||
|
state: '', |
||||
|
inspectionResult: '', |
||||
|
orderNo: '', |
||||
|
operationDesc: '', |
||||
|
buNo: this.searchData.buNo || '', |
||||
|
startDate: '', |
||||
|
endDate: '', |
||||
|
startDate2: '', |
||||
|
endDate2: '', |
||||
|
partNo: this.searchData.partNo || '', |
||||
|
partDesc: this.searchData.partDesc || '', |
||||
|
cinvSourceCode: '', |
||||
|
sku: '', |
||||
|
disposalMeasures: '', |
||||
|
itemResult: '', |
||||
|
seqNo: '', |
||||
|
operatorName: '', |
||||
|
responsiblePersonName: '', |
||||
|
page: this.searchData.page, |
||||
|
limit: this.searchData.limit |
||||
|
} |
||||
|
|
||||
|
console.log('查询参数:', queryParams) |
||||
|
console.log('当前用户:', this.$store.state.user.name) |
||||
|
|
||||
|
getIQCRecordList(queryParams).then(({data}) => { |
||||
|
if (data.code === 0) { |
||||
|
this.inspectionList = data.page.list || [] |
||||
|
this.totalPage = data.page.totalCount || 0 |
||||
|
} else { |
||||
|
this.$message.error(data.msg || '查询失败') |
||||
|
} |
||||
|
}).catch(err => { |
||||
|
console.error(err) |
||||
|
this.$message.error('查询失败') |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
// 重置搜索 |
||||
|
resetSearch() { |
||||
|
this.searchData = { |
||||
|
taskType: 'IQC', |
||||
|
site: '', |
||||
|
userName: this.$store.state.user.name, |
||||
|
inspectionNo: '', |
||||
|
partNo: '', |
||||
|
partDesc: '', |
||||
|
page: 1, |
||||
|
limit: 10 |
||||
|
} |
||||
|
// 重新选择检验单时清空用户勾选项(属性模板独立选择,不在此清空) |
||||
|
this.selectedTestStandards = [] |
||||
|
this.selectedMakingTechnics = [] |
||||
|
this.inspectionList = [] |
||||
|
this.totalPage = 0 |
||||
|
this.selectedRow = null |
||||
|
}, |
||||
|
|
||||
|
// 表格行选中 |
||||
|
handleCurrentChange(row) { |
||||
|
this.selectedRow = row |
||||
|
}, |
||||
|
|
||||
|
// 双击行直接选择检验单 |
||||
|
handleRowDblClick(row) { |
||||
|
this.selectedRow = row |
||||
|
this.confirmSelectionlection() |
||||
|
}, |
||||
|
|
||||
|
// 确认选择检验单:填充报表数据("结果"列改由主表行"选择"检验明细项目赋值) |
||||
|
confirmSelectionlection() { |
||||
|
if (this.selectedRow) { |
||||
|
this.reportData = { ...this.selectedRow } |
||||
|
this.selectDialogVisible = false |
||||
|
// 切换检验单时,先清除属性表格中已回填的检验明细数据 |
||||
|
this.clearAttributeTableFilledData() |
||||
|
// 清空复选框勾选状态 |
||||
|
this.selectedTestStandards = [] |
||||
|
this.selectedMakingTechnics = [] |
||||
|
// 选完检验单后自动带出:按 PropertiesItem.DefaultValue(如 IQC-0001) == 检验明细 item_no 匹配回填 |
||||
|
this.autoFillFromIQCDetail() |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 打开选择模板弹窗 |
||||
|
openTemplateDialog() { |
||||
|
this.resetTemplateSearch() |
||||
|
this.templateDialogVisible = true |
||||
|
this.searchTemplateList() |
||||
|
}, |
||||
|
|
||||
|
// 重置模板搜索条件 |
||||
|
resetTemplateSearch() { |
||||
|
this.templateSearchData = { |
||||
|
codeNo: '', |
||||
|
codeDesc: '', |
||||
|
page: 1, |
||||
|
limit: 10 |
||||
|
} |
||||
|
this.selectedTemplateRow = null |
||||
|
}, |
||||
|
|
||||
|
// 查询属性模板列表(PropertiesModelHeader) |
||||
|
searchTemplateList() { |
||||
|
const params = { |
||||
|
codeNo: this.templateSearchData.codeNo || '', |
||||
|
codeDesc: this.templateSearchData.codeDesc || '', |
||||
|
page: this.templateSearchData.page, |
||||
|
limit: this.templateSearchData.limit |
||||
|
} |
||||
|
getPropertiesModelList(params).then(({data}) => { |
||||
|
if (data && data.code === 0) { |
||||
|
this.attributeTemplateList = (data.page && data.page.list) || [] |
||||
|
this.templateTotalPage = (data.page && data.page.totalCount) || 0 |
||||
|
} else { |
||||
|
this.attributeTemplateList = [] |
||||
|
this.templateTotalPage = 0 |
||||
|
this.$message.error((data && data.msg) || '属性模板查询失败') |
||||
|
} |
||||
|
}).catch(err => { |
||||
|
console.error(err) |
||||
|
this.attributeTemplateList = [] |
||||
|
this.templateTotalPage = 0 |
||||
|
this.$message.error('属性模板查询失败') |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
// 模板列表行选中 |
||||
|
handleTemplateCurrentChange(row) { |
||||
|
this.selectedTemplateRow = row |
||||
|
}, |
||||
|
|
||||
|
// 双击行直接选择模板 |
||||
|
handleTemplateRowDblClick(row) { |
||||
|
this.selectedTemplateRow = row |
||||
|
this.confirmTemplateSelection() |
||||
|
}, |
||||
|
|
||||
|
// 确认选择模板:加载该模板的明细(默认值)并展示到下方表格 |
||||
|
confirmTemplateSelection() { |
||||
|
if (!this.selectedTemplateRow) return |
||||
|
this.selectedTemplateCode = this.selectedTemplateRow.codeNo |
||||
|
this.selectedTemplateDesc = this.selectedTemplateRow.codeDesc || '' |
||||
|
this.templateDialogVisible = false |
||||
|
// 切换模板时,清除已选检验单数据及页面缓存 |
||||
|
this.reportData = {} |
||||
|
this.selectedTestStandards = [] |
||||
|
this.selectedMakingTechnics = [] |
||||
|
this.attributeTableData = [] |
||||
|
this.loadPropertiesModelDetail() |
||||
|
}, |
||||
|
|
||||
|
// 模板弹窗分页 |
||||
|
handleTemplateSizeChange(val) { |
||||
|
this.templateSearchData.limit = val |
||||
|
this.templateSearchData.page = 1 |
||||
|
this.searchTemplateList() |
||||
|
}, |
||||
|
handleTemplatePageChange(val) { |
||||
|
this.templateSearchData.page = val |
||||
|
this.searchTemplateList() |
||||
|
}, |
||||
|
|
||||
|
// 查询属性模板明细(PropertiesModelDetail + PropertiesItem 默认值) |
||||
|
loadPropertiesModelDetail() { |
||||
|
if (!this.selectedTemplateCode) { |
||||
|
this.attributeTableData = [] |
||||
|
return |
||||
|
} |
||||
|
const params = { codeNo: this.selectedTemplateCode } |
||||
|
getPropertiesModelDetail(params).then(({data}) => { |
||||
|
if (data && data.code === 0) { |
||||
|
this.attributeTableData = data.rows || [] |
||||
|
// 若已选检验单,加载模板明细后立即按 item_no 自动带出 |
||||
|
if (this.reportData.inspectionNo) { |
||||
|
this.autoFillFromIQCDetail() |
||||
|
} |
||||
|
} else { |
||||
|
this.attributeTableData = [] |
||||
|
this.$message.error((data && data.msg) || '属性模板明细查询失败') |
||||
|
} |
||||
|
}).catch(err => { |
||||
|
console.error(err) |
||||
|
this.attributeTableData = [] |
||||
|
this.$message.error('属性模板明细查询失败') |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
// 打开选择检验项目弹窗(针对某一行明细,数据源为当前检验单的检验明细) |
||||
|
openAttributeItemDialog(row) { |
||||
|
// 必须先选检验单,才有 site/buNo/inspectionNo 用于查询检验明细 |
||||
|
if (!this.reportData.inspectionNo) { |
||||
|
this.$message.warning('请先选择检验单') |
||||
|
return |
||||
|
} |
||||
|
this.currentAttributeRow = row |
||||
|
this.selectedAttributeItemRow = null |
||||
|
this.attributeItemSearchData = { itemDesc: '', page: 1, limit: 10 } |
||||
|
this.attributeItemList = [] |
||||
|
this.attributeItemTotalPage = 0 |
||||
|
this.attributeItemDialogVisible = true |
||||
|
this.searchAttributeItemList() |
||||
|
}, |
||||
|
|
||||
|
// 查询当前检验单的检验明细项目(qc_iqc_detailed_record) |
||||
|
searchAttributeItemList() { |
||||
|
const params = { |
||||
|
site: this.reportData.site || '', |
||||
|
buNo: this.reportData.buNo || '', |
||||
|
inspectionNo: this.reportData.inspectionNo || '', |
||||
|
itemDesc: this.attributeItemSearchData.itemDesc || '', |
||||
|
page: this.attributeItemSearchData.page, |
||||
|
limit: this.attributeItemSearchData.limit |
||||
|
} |
||||
|
getIQCDetailedRecordList(params).then(({data}) => { |
||||
|
if (data && data.code === 0) { |
||||
|
this.attributeItemList = (data.page && data.page.list) || [] |
||||
|
this.attributeItemTotalPage = (data.page && data.page.totalCount) || 0 |
||||
|
} else { |
||||
|
this.attributeItemList = [] |
||||
|
this.attributeItemTotalPage = 0 |
||||
|
this.$message.error((data && data.msg) || '检验项目查询失败') |
||||
|
} |
||||
|
}).catch(err => { |
||||
|
console.error(err) |
||||
|
this.attributeItemList = [] |
||||
|
this.attributeItemTotalPage = 0 |
||||
|
this.$message.error('检验项目查询失败') |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
// 属性项目弹窗分页 |
||||
|
handleAttributeItemSizeChange(val) { |
||||
|
this.attributeItemSearchData.limit = val |
||||
|
this.attributeItemSearchData.page = 1 |
||||
|
this.searchAttributeItemList() |
||||
|
}, |
||||
|
handleAttributeItemPageChange(val) { |
||||
|
this.attributeItemSearchData.page = val |
||||
|
this.searchAttributeItemList() |
||||
|
}, |
||||
|
|
||||
|
// 属性项目列表行选中 |
||||
|
handleAttributeItemCurrentChange(row) { |
||||
|
this.selectedAttributeItemRow = row |
||||
|
}, |
||||
|
|
||||
|
// 双击行直接选择属性项目 |
||||
|
handleAttributeItemRowDblClick(row) { |
||||
|
this.selectedAttributeItemRow = row |
||||
|
this.confirmAttributeItemSelection() |
||||
|
}, |
||||
|
|
||||
|
// 确认选择检验项目:手动回填标准值/最大值/最小值/结果/合格不合格(与自动带出一致) |
||||
|
confirmAttributeItemSelection() { |
||||
|
if (!this.selectedAttributeItemRow || !this.currentAttributeRow) return |
||||
|
const target = this.attributeTableData.find(item => item === this.currentAttributeRow) |
||||
|
if (target) { |
||||
|
// 手动选择:与自动带出一致,回填标准值/最大值/最小值/结果/合格不合格 |
||||
|
this.fillRowFromDetail(target, this.selectedAttributeItemRow) |
||||
|
} |
||||
|
this.attributeItemDialogVisible = false |
||||
|
}, |
||||
|
|
||||
|
// 把检验明细字段回填到主表行:检验项目名称←item_desc、标准值←default_value、最大值←max_value、最小值←min_value、结果←text_value/number_value、合格不合格←item_result |
||||
|
fillRowFromDetail(target, detail) { |
||||
|
if (!target || !detail) return |
||||
|
this.$set(target, 'selectedItemDesc', detail.itemDesc || '') |
||||
|
this.$set(target, 'stdValue', detail.defaultValue != null ? detail.defaultValue : '') |
||||
|
this.$set(target, 'maxValue', detail.maxValue != null ? detail.maxValue : '') |
||||
|
this.$set(target, 'minValue', detail.minValue != null ? detail.minValue : '') |
||||
|
this.$set(target, 'textValue', detail.textValue || '') |
||||
|
this.$set(target, 'itemResult', detail.itemResult || '') |
||||
|
}, |
||||
|
|
||||
|
// 清除属性表格中已回填的检验明细数据(切换检验单时调用) |
||||
|
clearAttributeTableFilledData() { |
||||
|
this.attributeTableData.forEach(row => { |
||||
|
this.$set(row, 'selectedItemDesc', '') |
||||
|
this.$set(row, 'stdValue', '') |
||||
|
this.$set(row, 'maxValue', '') |
||||
|
this.$set(row, 'minValue', '') |
||||
|
this.$set(row, 'textValue', '') |
||||
|
this.$set(row, 'itemResult', '') |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
// 选完检验单后自动带出:按 主表行.defaultValue(PropertiesItem.DefaultValue, 如 IQC-0001) == 检验明细 item_no 匹配回填 |
||||
|
autoFillFromIQCDetail() { |
||||
|
if (!this.reportData.inspectionNo || !this.attributeTableData || this.attributeTableData.length === 0) return |
||||
|
const params = { |
||||
|
site: this.reportData.site || '', |
||||
|
buNo: this.reportData.buNo || '', |
||||
|
inspectionNo: this.reportData.inspectionNo || '', |
||||
|
itemDesc: '', |
||||
|
page: 1, |
||||
|
limit: 9999 |
||||
|
} |
||||
|
getIQCDetailedRecordList(params).then(({data}) => { |
||||
|
if (data && data.code === 0) { |
||||
|
const details = (data.page && data.page.list) || [] |
||||
|
if (details.length === 0) return |
||||
|
// item_no -> 检验明细 映射 |
||||
|
const map = {} |
||||
|
details.forEach(d => { if (d.itemNo != null && map[d.itemNo] === undefined) map[d.itemNo] = d }) |
||||
|
// 遍历主表行,用 defaultValue(IQC 检验项目编码) 匹配 item_no 自动带出 |
||||
|
this.attributeTableData.forEach(row => { |
||||
|
const key = row.defaultValue |
||||
|
if (key != null && key !== '' && map[key] !== undefined) { |
||||
|
this.fillRowFromDetail(row, map[key]) |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
}).catch(err => { |
||||
|
console.error('自动带出检验明细失败:', err) |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
// 分页大小改变 |
||||
|
handleSizeChange(val) { |
||||
|
this.searchData.limit = val |
||||
|
this.searchData.page = 1 |
||||
|
this.searchInspectionList() |
||||
|
}, |
||||
|
|
||||
|
// 页码改变 |
||||
|
handlePageChange(val) { |
||||
|
this.searchData.page = val |
||||
|
this.searchInspectionList() |
||||
|
}, |
||||
|
|
||||
|
// 格式化日期 |
||||
|
formatDate(date) { |
||||
|
if (!date) return '-' |
||||
|
const d = new Date(date) |
||||
|
const year = d.getFullYear() |
||||
|
const month = String(d.getMonth() + 1).padStart(2, '0') |
||||
|
const day = String(d.getDate()).padStart(2, '0') |
||||
|
const hours = String(d.getHours()).padStart(2, '0') |
||||
|
const minutes = String(d.getMinutes()).padStart(2, '0') |
||||
|
const seconds = String(d.getSeconds()).padStart(2, '0') |
||||
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}` |
||||
|
}, |
||||
|
|
||||
|
// 打印报表(仅打印主页面报表内容) |
||||
|
printReport() { |
||||
|
if (!this.reportData.inspectionNo) { |
||||
|
this.$message.warning('请先选择检验单') |
||||
|
return |
||||
|
} |
||||
|
const reportContent = this.$el.querySelector('.report-content') |
||||
|
if (!reportContent) { |
||||
|
this.$message.warning('未找到报表内容') |
||||
|
return |
||||
|
} |
||||
|
const printWindow = window.open('', '_blank') |
||||
|
printWindow.document.write(` |
||||
|
<!DOCTYPE html> |
||||
|
<html> |
||||
|
<head> |
||||
|
<title>出货报告打印报表</title> |
||||
|
<style> |
||||
|
body { margin: 0; padding: 15px 30px; font-family: 'Microsoft YaHei', sans-serif; } |
||||
|
h2 { text-align: center; margin-bottom: 10px; } |
||||
|
h3 { margin-bottom: 10px; } |
||||
|
.info-table { width: 100%; border-collapse: collapse; margin-top: 5px; } |
||||
|
.info-table td { border: 1px solid #000; padding: 8px 12px; font-size: 14px; height: 32px; } |
||||
|
.info-table .label-cell { font-weight: bold; width: 120px; text-align: center; } |
||||
|
.info-table .value-cell { padding: 8px 12px; text-align: left; } |
||||
|
.performance-table { width: 100%; border-collapse: collapse; margin-top: 10px; } |
||||
|
.performance-table th, .performance-table td { border: 1px solid #000; padding: 8px 12px; font-size: 14px; text-align: center; } |
||||
|
.performance-table th { font-weight: bold; height: 36px; } |
||||
|
.performance-table td { height: 32px; } |
||||
|
.performance-table .result-cell { font-weight: bold; } |
||||
|
.performance-table .item-cell { text-align: left; } |
||||
|
.section-header { display: flex; justify-content: space-between; align-items: center; } |
||||
|
.template-info { font-size: 14px; font-weight: bold; } |
||||
|
.check-option { display: inline-block; margin-right: 20px; } |
||||
|
.check-option input[type="checkbox"] { width: 15px; height: 15px; margin-right: 4px; vertical-align: middle; } |
||||
|
.no-print { display: none !important; } |
||||
|
button, .el-button { display: inline !important; border: none !important; background: none !important; padding: 0 !important; margin: 0 !important; font-size: 14px !important; color: #000 !important; cursor: default !important; } |
||||
|
</style> |
||||
|
</head> |
||||
|
<body> |
||||
|
${reportContent.innerHTML} |
||||
|
</body> |
||||
|
</html> |
||||
|
`) |
||||
|
printWindow.document.close() |
||||
|
printWindow.focus() |
||||
|
setTimeout(() => { |
||||
|
printWindow.print() |
||||
|
printWindow.close() |
||||
|
}, 300) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.shipment-report-container { |
||||
|
padding: 0px 20px 10px; |
||||
|
min-height: calc(100vh - 60px); |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
} |
||||
|
|
||||
|
.toolbar { |
||||
|
margin-bottom: 5px; |
||||
|
text-align: right; |
||||
|
} |
||||
|
|
||||
|
.report-content { |
||||
|
background-color: white; |
||||
|
padding: 15px 30px; |
||||
|
border-radius: 4px; |
||||
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); |
||||
|
flex: 1; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
min-height: 0; |
||||
|
overflow: auto; |
||||
|
} |
||||
|
|
||||
|
/* 测试标准 / 制作工艺 勾选项样式 */ |
||||
|
.check-option { |
||||
|
display: inline-block; |
||||
|
margin-right: 20px; |
||||
|
cursor: pointer; |
||||
|
font-weight: normal; |
||||
|
} |
||||
|
|
||||
|
.check-option input[type="checkbox"] { |
||||
|
width: 15px; |
||||
|
height: 15px; |
||||
|
margin-right: 4px; |
||||
|
vertical-align: middle; |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
|
||||
|
/* 信息表格样式 */ |
||||
|
.info-table { |
||||
|
width: 100%; |
||||
|
border-collapse: collapse; |
||||
|
margin-top: 5px; |
||||
|
} |
||||
|
|
||||
|
.info-table td { |
||||
|
border: 1px solid #dcdfe6; |
||||
|
padding: 8px 12px; |
||||
|
font-size: 14px; |
||||
|
height: 32px; |
||||
|
} |
||||
|
|
||||
|
.info-table .label-cell { |
||||
|
font-weight: bold; |
||||
|
color: #606266; |
||||
|
width: 120px; |
||||
|
text-align: center; |
||||
|
} |
||||
|
|
||||
|
.info-table .value-cell { |
||||
|
padding: 8px 12px; |
||||
|
text-align: left; |
||||
|
} |
||||
|
|
||||
|
/* 性能项目表格样式 */ |
||||
|
.performance-table { |
||||
|
width: 100%; |
||||
|
border-collapse: collapse; |
||||
|
margin-top: 10px; |
||||
|
} |
||||
|
|
||||
|
.performance-table th, |
||||
|
.performance-table td { |
||||
|
border: 1px solid #dcdfe6; |
||||
|
padding: 8px 12px; |
||||
|
font-size: 14px; |
||||
|
text-align: center; |
||||
|
} |
||||
|
|
||||
|
.performance-table th { |
||||
|
font-weight: bold; |
||||
|
color: #606266; |
||||
|
height: 36px; |
||||
|
} |
||||
|
|
||||
|
.performance-table td { |
||||
|
height: 32px; |
||||
|
} |
||||
|
|
||||
|
.performance-table .result-cell { |
||||
|
font-weight: bold; |
||||
|
color: #e6a23c; |
||||
|
} |
||||
|
|
||||
|
/* 下半部分表头区域 */ |
||||
|
.section-header { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.template-info { |
||||
|
font-size: 14px; |
||||
|
font-weight: bold; |
||||
|
color: #606266; |
||||
|
} |
||||
|
|
||||
|
/* 检验项目单元格 */ |
||||
|
.performance-table .item-cell { |
||||
|
text-align: left; |
||||
|
} |
||||
|
|
||||
|
.empty-state { |
||||
|
text-align: center; |
||||
|
padding: 100px 0; |
||||
|
background-color: white; |
||||
|
border-radius: 4px; |
||||
|
flex: 1; |
||||
|
} |
||||
|
|
||||
|
/* 打印样式 */ |
||||
|
@media print { |
||||
|
.toolbar { |
||||
|
display: none; |
||||
|
} |
||||
|
|
||||
|
.no-print { |
||||
|
display: none !important; |
||||
|
} |
||||
|
|
||||
|
.shipment-report-container { |
||||
|
padding: 0; |
||||
|
background-color: white; |
||||
|
} |
||||
|
|
||||
|
.report-content { |
||||
|
box-shadow: none; |
||||
|
overflow: visible; |
||||
|
} |
||||
|
|
||||
|
.info-table td, |
||||
|
.performance-table th, |
||||
|
.performance-table td { |
||||
|
border: 1px solid #000; |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue