|
@@ -40,7 +40,7 @@
|
|
|
ref="unqualifiedProductRef"
|
|
ref="unqualifiedProductRef"
|
|
|
v-show="activeComp == 'unqualifiedList'"
|
|
v-show="activeComp == 'unqualifiedList'"
|
|
|
@setQualifiedNumber="setQualifiedNumber"
|
|
@setQualifiedNumber="setQualifiedNumber"
|
|
|
- :total="basicInfoData.total || form.total"
|
|
|
|
|
|
|
+ :total="ledgerQuantity || basicInfoData.total || form.total || 0"
|
|
|
@setLossNumber="setLossNumber"
|
|
@setLossNumber="setLossNumber"
|
|
|
:businessType="businessType"
|
|
:businessType="businessType"
|
|
|
></unqualifiedProduct>
|
|
></unqualifiedProduct>
|
|
@@ -228,7 +228,12 @@
|
|
|
template: '',
|
|
template: '',
|
|
|
fileUrl: '',
|
|
fileUrl: '',
|
|
|
// 不良品处置台账未关联质检工单(手工新增等):此时不加载检测报告,只渲染不合格品处置单
|
|
// 不良品处置台账未关联质检工单(手工新增等):此时不加载检测报告,只渲染不合格品处置单
|
|
|
- isUnqualifiedDisposalNoOrder: false
|
|
|
|
|
|
|
+ isUnqualifiedDisposalNoOrder: false,
|
|
|
|
|
+ // 不良品处置台账已关联质检工单:结论/合格数/不合格数全部以工单详情接口为准,
|
|
|
|
|
+ // 明细的处置/删除/加行不得再用 poList 反推覆盖(前端不做兜底、不自己算数)
|
|
|
|
|
+ disposalHasWorkOrder: false,
|
|
|
|
|
+ // 不良品台账的送检总数:明细合格/不合格计算以它为准,不能用质检工单的 total
|
|
|
|
|
+ ledgerQuantity: 0
|
|
|
};
|
|
};
|
|
|
},
|
|
},
|
|
|
mounted() {
|
|
mounted() {
|
|
@@ -236,6 +241,16 @@
|
|
|
},
|
|
},
|
|
|
methods: {
|
|
methods: {
|
|
|
async open() {
|
|
async open() {
|
|
|
|
|
+ // 已办详情复用同一组件实例(不像待办每次新建),open 前重置 tab,
|
|
|
|
|
+ // 避免上一条记录的「不合格品处置单」tab 残留或多次 unshift 重复
|
|
|
|
|
+ this.tabOptions = [
|
|
|
|
|
+ { key: 'main', name: '报告' },
|
|
|
|
|
+ { key: 'unqualifiedList', name: '不良品台账' }
|
|
|
|
|
+ ];
|
|
|
|
|
+ this.activeComp = 'main';
|
|
|
|
|
+ this.ledgerQuantity = 0;
|
|
|
|
|
+ this.disposalHasWorkOrder = false;
|
|
|
|
|
+ this.isUnqualifiedDisposalNoOrder = false;
|
|
|
let api = getDetailById;
|
|
let api = getDetailById;
|
|
|
|
|
|
|
|
let detail = null;
|
|
let detail = null;
|
|
@@ -252,12 +267,32 @@
|
|
|
api = getCertifiById;
|
|
api = getCertifiById;
|
|
|
}
|
|
}
|
|
|
if (this.businessType?.includes('不良品处置')) {
|
|
if (this.businessType?.includes('不良品处置')) {
|
|
|
- const data = await getById(this.businessId);
|
|
|
|
|
- const enterprisePageData = await enterprisePage({
|
|
|
|
|
- pageNum: 1,
|
|
|
|
|
- size: 200
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ let data = null;
|
|
|
|
|
+ try {
|
|
|
|
|
+ data = await getById(this.businessId);
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ // 台账详情拿不到时明确提示,不留一个全空白页面
|
|
|
|
|
+ console.error('不良品台账详情获取失败', this.businessId, error);
|
|
|
|
|
+ this.$message.error(
|
|
|
|
|
+ `不良品处置单数据获取失败:${error?.message || error}`
|
|
|
|
|
+ );
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ let enterprisePageData = null;
|
|
|
|
|
+ try {
|
|
|
|
|
+ enterprisePageData = await enterprisePage({
|
|
|
|
|
+ pageNum: 1,
|
|
|
|
|
+ size: 200
|
|
|
|
|
+ });
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ // 只影响单位名称回填,不中断处置单/台账明细渲染
|
|
|
|
|
+ console.warn('企业信息获取失败,单位名称留空', error);
|
|
|
|
|
+ }
|
|
|
|
|
+ // 台账数量 = 本次送检总数,处置明细的合格/不合格计算以它为准
|
|
|
|
|
+ this.ledgerQuantity = data.quantity || 0;
|
|
|
if (data.qualityWorkOrderId) {
|
|
if (data.qualityWorkOrderId) {
|
|
|
|
|
+ // 已关联质检工单:这几个数字的唯一来源就是工单详情接口
|
|
|
|
|
+ this.disposalHasWorkOrder = true;
|
|
|
detail = await api(data.qualityWorkOrderId);
|
|
detail = await api(data.qualityWorkOrderId);
|
|
|
detail.data.templateList?.forEach((item) => {
|
|
detail.data.templateList?.forEach((item) => {
|
|
|
if (item.inspectImage) {
|
|
if (item.inspectImage) {
|
|
@@ -298,13 +333,37 @@
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
this.activeComp = 'unqualifiedHtml';
|
|
this.activeComp = 'unqualifiedHtml';
|
|
|
- const depData = await getGroupById(this.deptId);
|
|
|
|
|
- console.log(depData, 'depData');
|
|
|
|
|
|
|
+ // 部门ID来源:待办/审批页由流程上下文传入(this.deptId);
|
|
|
|
|
+ // 已办查看页父级只传 businessId,此时只能用台账接口返回的 deptId。
|
|
|
|
|
+ // 两者都没有时不要发请求——/main/group/getGroupById/undefined 会 404 抛错,
|
|
|
|
|
+ // 一旦抛出整个 open() 中断,处置单与台账明细都渲染不出来(表现为整页空白)
|
|
|
|
|
+ const deptId = this.deptId || data.deptId || '';
|
|
|
|
|
+ let deptHeadPerson = '';
|
|
|
|
|
+ if (deptId) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const depData = await getGroupById(deptId);
|
|
|
|
|
+ deptHeadPerson = depData?.data?.managerFirst?.[0]?.name || '';
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ // 部门信息取不到不影响处置单回填:部门负责人字段留空并提示
|
|
|
|
|
+ console.warn('部门信息获取失败,部门负责人留空', deptId, error);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
this.$nextTick(() => {
|
|
this.$nextTick(() => {
|
|
|
- if (data.contentText) {
|
|
|
|
|
- data.contentText = JSON.parse(data.contentText);
|
|
|
|
|
|
|
+ // contentText 是 JSON 字符串,空值/脏数据直接 JSON.parse 会抛错导致整页不回填
|
|
|
|
|
+ if (typeof data.contentText === 'string' && data.contentText) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ data.contentText = JSON.parse(data.contentText);
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('台账 contentText 解析失败,处置单改用台账字段回填', error);
|
|
|
|
|
+ data.contentText = null;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ const htmlRef = this.$refs.unqualifiedHtmlRef;
|
|
|
|
|
+ if (!htmlRef) {
|
|
|
|
|
+ console.error('不合格品处置单组件未渲染,数据无法回填');
|
|
|
|
|
+ return;
|
|
|
}
|
|
}
|
|
|
- this.$refs.unqualifiedHtmlRef.init(
|
|
|
|
|
|
|
+ htmlRef.init(
|
|
|
data.contentText?.basicInfoData
|
|
data.contentText?.basicInfoData
|
|
|
? data.contentText.basicInfoData
|
|
? data.contentText.basicInfoData
|
|
|
: {
|
|
: {
|
|
@@ -320,7 +379,7 @@
|
|
|
feedbackPerson: this.fromUser,
|
|
feedbackPerson: this.fromUser,
|
|
|
feedbackDate: this.createTime,
|
|
feedbackDate: this.createTime,
|
|
|
deptHeadDate: this.createTime,
|
|
deptHeadDate: this.createTime,
|
|
|
- deptHeadPerson: depData?.data?.managerFirst[0]?.name,
|
|
|
|
|
|
|
+ deptHeadPerson,
|
|
|
sampleMeasureUnit: data.measureUnit,
|
|
sampleMeasureUnit: data.measureUnit,
|
|
|
vehiclePhotoUrl: vehiclePhotoUrl?.map(
|
|
vehiclePhotoUrl: vehiclePhotoUrl?.map(
|
|
|
(item) => item.storagePath[0]?.storePath
|
|
(item) => item.storagePath[0]?.storePath
|
|
@@ -344,9 +403,13 @@
|
|
|
|
|
|
|
|
if (detail.data.reportTemplateJson?.template) {
|
|
if (detail.data.reportTemplateJson?.template) {
|
|
|
this.template = detail.data.reportTemplateJson.template;
|
|
this.template = detail.data.reportTemplateJson.template;
|
|
|
- console.log(detail.data, 'detail.data');
|
|
|
|
|
- this.inspectionItems = detail.data.reportTemplateJson.inspectionItems;
|
|
|
|
|
- this.basicInfoData = detail.data.reportTemplateJson?.basicInfoData;
|
|
|
|
|
|
|
+ this.inspectionItems =
|
|
|
|
|
+ detail.data.reportTemplateJson.inspectionItems || [];
|
|
|
|
|
+ // 报告模板里的 basicInfoData 会整体替换页面绑定的对象,
|
|
|
|
|
+ // 因此结论/合格数在下面(模板赋值之后)再统一回填
|
|
|
|
|
+ if (detail.data.reportTemplateJson.basicInfoData) {
|
|
|
|
|
+ this.basicInfoData = detail.data.reportTemplateJson.basicInfoData;
|
|
|
|
|
+ }
|
|
|
this.$nextTick(() => {
|
|
this.$nextTick(() => {
|
|
|
this.$refs.templateRef.init(
|
|
this.$refs.templateRef.init(
|
|
|
this.basicInfoData,
|
|
this.basicInfoData,
|
|
@@ -363,8 +426,51 @@
|
|
|
|
|
|
|
|
// 台账未关联质检工单时没有检测报告可打印,跳过,避免用台账ID请求报告页
|
|
// 台账未关联质检工单时没有检测报告可打印,跳过,避免用台账ID请求报告页
|
|
|
if (!this.isUnqualifiedDisposalNoOrder) {
|
|
if (!this.isUnqualifiedDisposalNoOrder) {
|
|
|
- let url = await getJmPrintViewUrl('qmsqualityinspectionprint');
|
|
|
|
|
- this.fileUrl = `${url}?token=${getToken()}&id=${this.businessId}`;
|
|
|
|
|
|
|
+ try {
|
|
|
|
|
+ const url = await getJmPrintViewUrl('qmsqualityinspectionprint');
|
|
|
|
|
+ this.fileUrl = `${url}?token=${getToken()}&id=${this.businessId}`;
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ // 只影响报告页预览,不影响处置单与台账明细
|
|
|
|
|
+ console.error('检测报告打印地址获取失败,报告预览留空', error);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 不良品处置:结论 / 合格数 / 不合格数唯一来源是「质检工单详情」,
|
|
|
|
|
+ // 台账 getById 从不返回这几个字段。必须放在报告模板覆盖 basicInfoData 之后,
|
|
|
|
|
+ // 否则会被模板里的 undefined 冲掉(表现就是全部显示 0)。
|
|
|
|
|
+ // 台账没有关联质检工单(手工新增)时没有数据来源,保持空即可,不拿明细反推。
|
|
|
|
|
+ if (this.businessType?.includes('不良品处置')) {
|
|
|
|
|
+ const src = detail.data || {};
|
|
|
|
|
+ const hasQualified =
|
|
|
|
|
+ src.qualifiedNumber !== undefined && src.qualifiedNumber !== null;
|
|
|
|
|
+ const hasNoQualified =
|
|
|
|
|
+ src.noQualifiedNumber !== undefined &&
|
|
|
|
|
+ src.noQualifiedNumber !== null;
|
|
|
|
|
+ this.$set(
|
|
|
|
|
+ this.basicInfoData,
|
|
|
|
|
+ 'qualityResults',
|
|
|
|
|
+ src.qualityResults ?? ''
|
|
|
|
|
+ );
|
|
|
|
|
+ this.$set(
|
|
|
|
|
+ this.basicInfoData,
|
|
|
|
|
+ 'qualifiedNumber',
|
|
|
|
|
+ hasQualified ? src.qualifiedNumber : ''
|
|
|
|
|
+ );
|
|
|
|
|
+ this.$set(
|
|
|
|
|
+ this.basicInfoData,
|
|
|
|
|
+ 'noQualifiedNumber',
|
|
|
|
|
+ hasNoQualified ? src.noQualifiedNumber : ''
|
|
|
|
|
+ );
|
|
|
|
|
+ if (!hasQualified && !hasNoQualified) {
|
|
|
|
|
+ // 只在控制台留痕,页面不打扰用户
|
|
|
|
|
+ console.warn(
|
|
|
|
|
+ '[不良品处置] 合格数/不合格数无数据来源:台账未关联质检工单,或工单未返回 qualifiedNumber / noQualifiedNumber',
|
|
|
|
|
+ {
|
|
|
|
|
+ businessId: this.businessId,
|
|
|
|
|
+ qualityWorkOrderId: src.qualityWorkOrderId
|
|
|
|
|
+ }
|
|
|
|
|
+ );
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
@@ -425,20 +531,57 @@
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
setQualifiedNumber(data) {
|
|
setQualifiedNumber(data) {
|
|
|
- this.basicInfoData.qualifiedNumber = data.qualifiedNumber;
|
|
|
|
|
- this.basicInfoData.noQualifiedNumber = data.noQualifiedNumber;
|
|
|
|
|
- if (!data.noQualifiedNumber) {
|
|
|
|
|
- if (data.isQualifiedNumber) {
|
|
|
|
|
- this.basicInfoData.qualityResults = 1;
|
|
|
|
|
- } else {
|
|
|
|
|
- this.basicInfoData.qualityResults = 4;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 不良品处置且台账已关联质检工单:结论 / 合格数 / 不合格数 唯一来源是工单详情接口,
|
|
|
|
|
+ // 明细的处置 / 删除 / 加行只影响明细本身,绝不能拿 poList 反推去覆盖工单返回值。
|
|
|
|
|
+ // 例:台账只有 1 件待处置、工单却是 90 件检验,按台账总数反推会把 89 冲成 0。
|
|
|
|
|
+ if (this.businessType?.includes('不良品处置') && this.disposalHasWorkOrder) {
|
|
|
|
|
+ return;
|
|
|
}
|
|
}
|
|
|
- if (!data.qualifiedNumber) {
|
|
|
|
|
- this.basicInfoData.qualityResults = 2;
|
|
|
|
|
|
|
+ // 合格数 / 不合格数一律以台账接口的 qualifiedNumber / noQualifiedNumber 为准;
|
|
|
|
|
+ // 只有这两类数在页面上被用户改动(处置/删除/切换结论)时才会重新计算后回传
|
|
|
|
|
+ if (data.qualifiedNumber !== undefined && data.qualifiedNumber !== null) {
|
|
|
|
|
+ this.$set(
|
|
|
|
|
+ this.basicInfoData,
|
|
|
|
|
+ 'qualifiedNumber',
|
|
|
|
|
+ data.qualifiedNumber
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+ if (
|
|
|
|
|
+ data.noQualifiedNumber !== undefined &&
|
|
|
|
|
+ data.noQualifiedNumber !== null
|
|
|
|
|
+ ) {
|
|
|
|
|
+ this.$set(
|
|
|
|
|
+ this.basicInfoData,
|
|
|
|
|
+ 'noQualifiedNumber',
|
|
|
|
|
+ data.noQualifiedNumber
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+ // 初次加载只回显数量,不自动改写台账已保存的「结论」
|
|
|
|
|
+ if (data.fromApi) {
|
|
|
|
|
+ return;
|
|
|
}
|
|
}
|
|
|
- if (data.qualifiedNumber && data.noQualifiedNumber) {
|
|
|
|
|
|
|
+ // 用户手动选结论:结论以用户选择为准,只回填数量
|
|
|
|
|
+ if (data.fromSelect) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 数量还没算出来(台账总数为 0 等)时不要改写结论,否则会把用户的选择冲掉
|
|
|
|
|
+ const qualified = Number(data.qualifiedNumber);
|
|
|
|
|
+ const noQualified = Number(data.noQualifiedNumber);
|
|
|
|
|
+ if (
|
|
|
|
|
+ !Number.isFinite(qualified) ||
|
|
|
|
|
+ !Number.isFinite(noQualified) ||
|
|
|
|
|
+ qualified + noQualified <= 0
|
|
|
|
|
+ ) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (qualified > 0 && noQualified > 0) {
|
|
|
this.basicInfoData.qualityResults = 3;
|
|
this.basicInfoData.qualityResults = 3;
|
|
|
|
|
+ } else if (qualified > 0) {
|
|
|
|
|
+ // 明细全部按「让步接收」处置时结论应为整单让步接收
|
|
|
|
|
+ this.basicInfoData.qualityResults =
|
|
|
|
|
+ data.isQualifiedNumber === false ? 4 : 1;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.basicInfoData.qualityResults = 2;
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
async getTableValue() {
|
|
async getTableValue() {
|