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