Browse Source

feat(report): 添加出货报告打印功能

- 在路由配置中新增 shipmentReport 页面路由
- 添加 IQC 检验单列表和明细查询 API 接口
- 添加属性模板相关 API 接口(模板列表、明细、项目列表等)
- 新建出货报告打印页面组件,实现完整的报表功能
- 实现检验单选择、属性模板选择、检验项目匹配回填等功能
- 添加报表打印功能和相应的样式适配
master
qiankanghui 2 days ago
parent
commit
91201481f2
  1. 13
      src/api/qc/qc_report.js
  2. 1
      src/router/index.js
  3. 971
      src/views/modules/report/shipment_report.vue

13
src/api/qc/qc_report.js

@ -2,6 +2,10 @@ import { createAPI } from "@/utils/httpRequest.js";
// IQC报表查询
export const getIQCReport = data => createAPI('/pms/qcReport/getIQCReport','post',data)
// IQC检验单列表(仅主表 qc_iqc_record,不关联明细,出货报告选择检验单用)
export const getIQCRecordList = data => createAPI('/pms/qcReport/getIQCRecordList','post',data)
// IQC检验单明细项目(qc_iqc_detailed_record,出货报告“选择检验项目”回填结果用)
export const getIQCDetailedRecordList = data => createAPI('/pms/qcReport/getIQCDetailedRecordList','post',data)
// IPQC报表查询
export const getIPQCReport = data => createAPI('/pms/qcReport/getIPQCReport','post',data)
// FAI报表查询
@ -34,6 +38,15 @@ export const getOQCDetailReport = data => createAPI('/pms/qcReport/getOQCDetailR
// 导出
export const downloadQcDetailRecord = data => createAPI('/pms/qcReport/downloadQcDetailRecord','post',data, 'download')
// 属性模板列表(选择模板弹窗)
export const getPropertiesModelList = data => createAPI('/pms/qcReport/getPropertiesModelList','post',data)
// 属性模板明细(含属性项目默认值)
export const getPropertiesModelDetail = data => createAPI('/pms/qcReport/getPropertiesModelDetail','post',data)
// 属性项目列表(选择属性项目弹窗)
export const getPropertiesItemList = data => createAPI('/pms/qcReport/getPropertiesItemList','post',data)
// 物料属性实际值(选检验单后按 site+partNo+codeNo 查询,回填结果列)
export const getPartPropertiesValue = data => createAPI('/pms/qcReport/getPartPropertiesValue','post',data)
// SPC 过程能力报表
export const getSpcMaterials = data => createAPI('/pms/qcReport/getSpcMaterials', 'post', data)
export const getSpcInspectionItems = data => createAPI('/pms/qcReport/getSpcInspectionItems', 'post', data)

1
src/router/index.js

@ -49,6 +49,7 @@ const globalRoutes = [
{ path: '/biBoard', component: _import('modules/board/biBoard'), name: 'biBoard', meta: { title: 'BI报表' } },
{ path: '/vulcanization', component: _import('modules/board/VulcanizationDispatchOrder'), name: 'vulcanizationDispatchOrder', meta: { title: '硫化派工单跟踪看板' } },
{ path: '/inventory', component: _import('modules/board/partInventory'), name: 'inventory', meta: { title: '库存信息' } },
{ path: '/shipmentReport', component: _import('modules/report/shipment_report'), name: 'shipmentReport', meta: { title: '出货报告打印' } },
]
// 主入口路由(需嵌套上左右整体布局)

971
src/views/modules/report/shipment_report.vue

@ -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>
Loading…
Cancel
Save