From c1a9bd81744474027abc73abcc778fd2798ec7ec Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期五, 18 九月 2026 14:39:43 +0800
Subject: [PATCH] feat(mes): 增加质检指标详情查看功能并调整接口配置
---
src/views/mes/qc/iqc/index.vue | 22 +++++
src/views/mes/qc/indicatorresult/components/data.ts | 2
src/views/mes/qc/ipqc/data.ts | 2
src/packages/constants/src/biz-mes-enum.ts | 6 +
src/views/mes/qc/iqc/data.ts | 2
src/views/mes/qc/indicatorresult/components/form.vue | 76 ++++++++++++++----
src/views/mes/qc/oqc/data.ts | 2
src/views/mes/qc/ipqc/index.vue | 22 +++++
.env.development | 2
src/views/mes/qc/oqc/index.vue | 22 +++++
vite.config.ts | 2
src/views/mes/qc/rqc/index.vue | 22 +++++
src/api/mes/qc/indicatorresult/index.ts | 32 +++++++
src/views/mes/qc/indicatorresult/components/list.vue | 19 ++++
src/views/mes/qc/rqc/data.ts | 2
15 files changed, 209 insertions(+), 26 deletions(-)
diff --git a/.env.development b/.env.development
index 5ade162..d5e3ed6 100644
--- a/.env.development
+++ b/.env.development
@@ -4,7 +4,7 @@
VITE_BASE=/
# 璇锋眰璺緞
-VITE_BASE_URL=http://127.0.0.1:48080
+VITE_BASE_URL=http://127.0.0.1:48081
# 鎺ュ彛鍦板潃
VITE_GLOB_API_URL=/admin-api
# 鏂囦欢涓婁紶绫诲瀷锛歴erver - 鍚庣涓婁紶锛� client - 鍓嶇鐩磋繛涓婁紶锛屼粎鏀寔S3鏈嶅姟
diff --git a/src/api/mes/qc/indicatorresult/index.ts b/src/api/mes/qc/indicatorresult/index.ts
index dfa8a7f..32600e0 100644
--- a/src/api/mes/qc/indicatorresult/index.ts
+++ b/src/api/mes/qc/indicatorresult/index.ts
@@ -3,18 +3,34 @@
import { requestClient } from '#/api/request';
export namespace MesQcIndicatorResultApi {
- /** MES 妫�楠岀粨鏋滄槑缁� */
+ /** 骞宠娴嬮噺鍗曟壒娆″�� */
+ export interface IndicatorResultMeasure {
+ detailId?: number; // 鏄庣粏缂栧彿
+ resultId?: number; // 鍏宠仈妫�楠岀粨鏋� ID
+ measureNo?: number; // 娴嬮噺鎵规鍙�
+ value?: string; // 妫�娴嬪��
+ remark?: string; // 澶囨敞
+ }
+
+ /** MES 妫�楠岀粨鏋滄槑缁嗭紙鎺ュ彛杩斿洖涓哄垎缁勬爲锛宑hildren 鎸傚瓙椤癸級 */
export interface IndicatorResultDetail {
id?: number; // 缂栧彿
resultId?: number; // 鍏宠仈妫�楠岀粨鏋� ID
indicatorId?: number; // 妫�娴嬫寚鏍� ID
- value?: string; // 妫�娴嬪�硷紙缁熶竴瀛樹负瀛楃涓诧級
+ value?: string; // 妫�娴嬪�硷紙缁熶竴瀛樹负瀛楃涓诧紝鍏煎绗竴鎵规祴閲忓�硷級
valueNumber?: number; // UI 鏁板�肩粦瀹氾紙鎻愪氦鍓嶈浆瀛楃涓诧級
remark?: string; // 澶囨敞
+ measures?: IndicatorResultMeasure[]; // 骞宠娴嬮噺澶氭壒娆″��
// 鍏宠仈鏌ヨ瀛楁锛堟潵鑷� indicator锛�
indicatorName?: string; // 妫�娴嬫寚鏍囧悕绉�
+ parentId?: number; // 鐖跺垎缁勬寚鏍� ID
+ itemType?: number; // 鎸囨爣椤圭被鍨嬶紙1 褰曞叆椤� / 2 鍒嗙粍锛�
+ formulaText?: string; // 鍏紡鏂囨湰
+ unitText?: string; // 鍗曚綅鏂囨湰
+ sortOrder?: number; // 鎺掑簭鍙�
valueType?: number; // 璐ㄦ鍊肩被鍨�
valueSpecification?: string; // 鍊煎睘鎬�
+ children?: IndicatorResultDetail[]; // 鍒嗙粍瀛愰」
}
/** MES 妫�楠岀粨鏋� */
@@ -71,3 +87,15 @@
export function deleteIndicatorResult(id: number) {
return requestClient.delete(`/mes/qc/indicator-result/delete?id=${id}`);
}
+
+/** 瀵煎嚭浜у搧妫�楠屽崟 Word锛坬cType锛�1=IQC銆�2=IPQC銆�3=OQC銆�4=RQC锛況esultId 鍙�夛紝榛樿鍙栨渶鏃╂牱鍝侊級 */
+export function exportProductWord(params: {
+ qcId: number;
+ qcType: number;
+ resultId?: number;
+}) {
+ return requestClient.download(
+ '/mes/qc/indicator-result/export-product-word',
+ { params },
+ );
+}
diff --git a/src/packages/constants/src/biz-mes-enum.ts b/src/packages/constants/src/biz-mes-enum.ts
index 1ac585c..848c41d 100644
--- a/src/packages/constants/src/biz-mes-enum.ts
+++ b/src/packages/constants/src/biz-mes-enum.ts
@@ -440,6 +440,12 @@
WIP_VIRTUAL: 'WIP_VIRTUAL',
} as const;
+/** MES 璐ㄦ鎸囨爣椤圭被鍨嬫灇涓撅紙瀵瑰簲鍚庣 MesQcIndicatorItemTypeEnum锛� */
+export const MesQcIndicatorItemType = {
+ RECORD: 1,
+ GROUP: 2,
+} as const;
+
/** MES 璐ㄦ缁撴灉鍊肩被鍨嬫灇涓� */
export const MesQcResultValueType = {
FLOAT: 1,
diff --git a/src/views/mes/qc/indicatorresult/components/data.ts b/src/views/mes/qc/indicatorresult/components/data.ts
index 694a01c..586d2e8 100644
--- a/src/views/mes/qc/indicatorresult/components/data.ts
+++ b/src/views/mes/qc/indicatorresult/components/data.ts
@@ -11,7 +11,7 @@
import { generateAutoCode } from '#/api/mes/md/autocode/record';
/** 琛ㄥ崟绫诲瀷 */
-export type FormType = 'create' | 'update';
+export type FormType = 'create' | 'detail' | 'update';
/** 鏂板/淇敼妫�娴嬬粨鏋滅殑琛ㄥ崟 */
export function useQcIndicatorResultFormSchema(
diff --git a/src/views/mes/qc/indicatorresult/components/form.vue b/src/views/mes/qc/indicatorresult/components/form.vue
index c6481b2..fc345f8 100644
--- a/src/views/mes/qc/indicatorresult/components/form.vue
+++ b/src/views/mes/qc/indicatorresult/components/form.vue
@@ -6,7 +6,7 @@
import { computed, ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
-import { MesQcResultValueType } from '@vben/constants';
+import { MesQcIndicatorItemType, MesQcResultValueType } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import {
@@ -43,11 +43,49 @@
const items = ref<MesQcIndicatorResultApi.IndicatorResultDetail[]>([]);
const ctxData = ref<CtxData>();
-const getTitle = computed(() =>
- formType.value === 'update'
+const isDetail = computed(() => formType.value === 'detail');
+
+const getTitle = computed(() => {
+ if (formType.value === 'detail') {
+ return $t('ui.actionTitle.view', ['妫�楠岀粨鏋�']);
+ }
+ return formType.value === 'update'
? $t('ui.actionTitle.edit', ['妫�楠岀粨鏋�'])
- : $t('ui.actionTitle.create', ['妫�楠岀粨鏋�']),
-);
+ : $t('ui.actionTitle.create', ['妫�楠岀粨鏋�']);
+});
+
+/** 鍒嗙粍鏍戝钩閾轰负褰曞叆椤瑰垪琛細鍒嗙粍鑺傜偣涓嶅睍绀猴紝浠呭睍寮�鍏跺瓙椤� */
+function flattenRecordItems(
+ nodes: MesQcIndicatorResultApi.IndicatorResultDetail[] | undefined,
+ out: MesQcIndicatorResultApi.IndicatorResultDetail[],
+) {
+ (nodes ?? []).forEach((node) => {
+ if (node.itemType === MesQcIndicatorItemType.GROUP) {
+ flattenRecordItems(node.children, out);
+ return;
+ }
+ out.push({
+ ...node,
+ valueNumber:
+ (node.valueType === MesQcResultValueType.FLOAT ||
+ node.valueType === MesQcResultValueType.INTEGER) &&
+ node.value != null
+ ? Number(node.value)
+ : undefined,
+ });
+ });
+}
+
+/** 璇︽儏灞曠ず鍊硷細骞宠娴嬮噺澶氭壒娆¢】鍙峰悎骞讹紝鍏煎鏃ф暟鎹崟鍊� */
+function measureText(item: MesQcIndicatorResultApi.IndicatorResultDetail) {
+ const vals = (item.measures ?? [])
+ .map((m) => m.value)
+ .filter((v) => v !== undefined && v !== null && v !== '');
+ if (vals.length > 0) {
+ return vals.join('銆�');
+ }
+ return item.value ?? '';
+}
const [Form, formApi] = useVbenForm({
commonConfig: {
@@ -135,6 +173,9 @@
const data = modalApi.getData<CtxData>();
ctxData.value = data;
formType.value = data.formType;
+ const detailMode = data.formType === 'detail';
+ formApi.setDisabled(detailMode);
+ modalApi.setState({ showConfirmButton: !detailMode });
modalApi.lock();
try {
const detail = await getIndicatorResultDetail(
@@ -142,16 +183,10 @@
data.qcType,
data.id,
);
- // 鍥炲~鏁板�煎瓧娈碉紙鐢ㄤ簬 InputNumber 缁戝畾锛�
- items.value = (detail.items ?? []).map((item) => ({
- ...item,
- valueNumber:
- (item.valueType === MesQcResultValueType.FLOAT ||
- item.valueType === MesQcResultValueType.INTEGER) &&
- item.value !== null
- ? Number(item.value)
- : undefined,
- }));
+ // 鍒嗙粍鏍戝钩閾� + 鍥炲~鏁板�煎瓧娈碉紙鐢ㄤ簬 InputNumber 缁戝畾锛�
+ const flat: MesQcIndicatorResultApi.IndicatorResultDetail[] = [];
+ flattenRecordItems(detail.items, flat);
+ items.value = flat;
// 璁剧疆鍒� values
await formApi.setValues({
id: detail.id,
@@ -179,10 +214,17 @@
class="mb-2"
>
<AForm.Item
- :label="`妫�娴嬮」${index + 1}锛�${item.indicatorName ?? ''}`"
+ :label="`妫�娴嬮」${index + 1}锛�${item.indicatorName ?? ''}${
+ isDetail && item.unitText ? `锛�${item.unitText}锛塦 : ''
+ }`"
>
+ <Input
+ v-if="isDetail"
+ :value="measureText(item) || '/'"
+ disabled
+ />
<InputNumber
- v-if="
+ v-else-if="
item.valueType === MesQcResultValueType.FLOAT ||
item.valueType === MesQcResultValueType.INTEGER
"
diff --git a/src/views/mes/qc/indicatorresult/components/list.vue b/src/views/mes/qc/indicatorresult/components/list.vue
index 48e11bb..d4611a8 100644
--- a/src/views/mes/qc/indicatorresult/components/list.vue
+++ b/src/views/mes/qc/indicatorresult/components/list.vue
@@ -43,6 +43,18 @@
.open();
}
+/** 鏌ョ湅妫�娴嬬粨鏋滆鎯咃紙鍙锛� */
+function handleDetail(row: MesQcIndicatorResultApi.IndicatorResult) {
+ formModalApi
+ .setData({
+ formType: 'detail',
+ id: row.id,
+ qcId: props.qcId,
+ qcType: props.qcType,
+ })
+ .open();
+}
+
/** 缂栬緫妫�娴嬬粨鏋� */
function handleEdit(row: MesQcIndicatorResultApi.IndicatorResult) {
formModalApi
@@ -127,6 +139,13 @@
onClick: handleEdit.bind(null, row),
},
{
+ label: $t('common.detail'),
+ type: 'link',
+ icon: ACTION_ICON.VIEW,
+ ifShow: readonly,
+ onClick: handleDetail.bind(null, row),
+ },
+ {
label: $t('common.delete'),
type: 'link',
danger: true,
diff --git a/src/views/mes/qc/ipqc/data.ts b/src/views/mes/qc/ipqc/data.ts
index 58f1e88..b4979f3 100644
--- a/src/views/mes/qc/ipqc/data.ts
+++ b/src/views/mes/qc/ipqc/data.ts
@@ -491,7 +491,7 @@
},
{
title: '鎿嶄綔',
- width: 180,
+ width: 260,
fixed: 'right',
slots: { default: 'actions' },
},
diff --git a/src/views/mes/qc/ipqc/index.vue b/src/views/mes/qc/ipqc/index.vue
index 32d46c4..82bf057 100644
--- a/src/views/mes/qc/ipqc/index.vue
+++ b/src/views/mes/qc/ipqc/index.vue
@@ -9,6 +9,7 @@
import { Button, message } from 'ant-design-vue';
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
+import { exportProductWord } from '#/api/mes/qc/indicatorresult';
import { deleteIpqc, exportIpqc, getIpqcPage } from '#/api/mes/qc/ipqc';
import { $t } from '#/locales';
@@ -59,6 +60,20 @@
async function handleExport() {
const data = await exportIpqc(await gridApi.formApi.getValues());
downloadFileFromBlobPart({ fileName: '杩囩▼妫�楠屽崟.xls', source: data });
+}
+
+/** 涓嬭浇璐ㄦ鎶ュ憡锛堜骇鍝佹楠屽崟 Word锛屾墦鍗扮敤 Word 鎵撳紑锛� */
+async function handleExportWord(row: MesQcIpqcApi.Ipqc) {
+ const hideLoading = message.loading({ content: '鎶ュ憡瀵煎嚭涓�...', duration: 0 });
+ try {
+ const data = await exportProductWord({ qcId: row.id!, qcType: 2 });
+ downloadFileFromBlobPart({
+ fileName: `${row.code || ''}-浜у搧璐ㄩ噺妫�楠屽崟.docx`,
+ source: data,
+ });
+ } finally {
+ hideLoading();
+ }
}
const [Grid, gridApi] = useVbenVxeGrid({
@@ -151,6 +166,13 @@
auth: ['mes:qc-ipqc:query'],
onClick: handleDetail.bind(null, row),
},
+ {
+ label: '璐ㄦ鎶ュ憡',
+ type: 'link',
+ icon: ACTION_ICON.DOWNLOAD,
+ auth: ['mes:qc-ipqc:query'],
+ onClick: handleExportWord.bind(null, row),
+ },
]"
/>
</template>
diff --git a/src/views/mes/qc/iqc/data.ts b/src/views/mes/qc/iqc/data.ts
index 40cb523..fa7bfa6 100644
--- a/src/views/mes/qc/iqc/data.ts
+++ b/src/views/mes/qc/iqc/data.ts
@@ -436,7 +436,7 @@
},
{
title: '鎿嶄綔',
- width: 180,
+ width: 260,
fixed: 'right',
slots: { default: 'actions' },
},
diff --git a/src/views/mes/qc/iqc/index.vue b/src/views/mes/qc/iqc/index.vue
index 44e0901..75a2d25 100644
--- a/src/views/mes/qc/iqc/index.vue
+++ b/src/views/mes/qc/iqc/index.vue
@@ -12,6 +12,7 @@
import { Button, message } from 'ant-design-vue';
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
+import { exportProductWord } from '#/api/mes/qc/indicatorresult';
import { deleteIqc, exportIqc, getIqcPage } from '#/api/mes/qc/iqc';
import { $t } from '#/locales';
@@ -66,6 +67,20 @@
async function handleExport() {
const data = await exportIqc(await gridApi.formApi.getValues());
downloadFileFromBlobPart({ fileName: '鏉ユ枡妫�楠屽崟.xls', source: data });
+}
+
+/** 涓嬭浇璐ㄦ鎶ュ憡锛堜骇鍝佹楠屽崟 Word锛屾墦鍗扮敤 Word 鎵撳紑锛� */
+async function handleExportWord(row: MesQcIqcApi.Iqc) {
+ const hideLoading = message.loading({ content: '鎶ュ憡瀵煎嚭涓�...', duration: 0 });
+ try {
+ const data = await exportProductWord({ qcId: row.id!, qcType: 1 });
+ downloadFileFromBlobPart({
+ fileName: `${row.code || ''}-浜у搧璐ㄩ噺妫�楠屽崟.docx`,
+ source: data,
+ });
+ } finally {
+ hideLoading();
+ }
}
const [Grid, gridApi] = useVbenVxeGrid({
@@ -165,6 +180,13 @@
auth: ['mes:qc-iqc:query'],
onClick: handleDetail.bind(null, row),
},
+ {
+ label: '璐ㄦ鎶ュ憡',
+ type: 'link',
+ icon: ACTION_ICON.DOWNLOAD,
+ auth: ['mes:qc-iqc:query'],
+ onClick: handleExportWord.bind(null, row),
+ },
]"
/>
</template>
diff --git a/src/views/mes/qc/oqc/data.ts b/src/views/mes/qc/oqc/data.ts
index 0183a35..1143391 100644
--- a/src/views/mes/qc/oqc/data.ts
+++ b/src/views/mes/qc/oqc/data.ts
@@ -439,7 +439,7 @@
},
{
title: '鎿嶄綔',
- width: 220,
+ width: 260,
fixed: 'right',
slots: { default: 'actions' },
},
diff --git a/src/views/mes/qc/oqc/index.vue b/src/views/mes/qc/oqc/index.vue
index 965cfda..8647b27 100644
--- a/src/views/mes/qc/oqc/index.vue
+++ b/src/views/mes/qc/oqc/index.vue
@@ -9,6 +9,7 @@
import { Button, message } from 'ant-design-vue';
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
+import { exportProductWord } from '#/api/mes/qc/indicatorresult';
import { deleteOqc, exportOqc, getOqcPage } from '#/api/mes/qc/oqc';
import { $t } from '#/locales';
@@ -59,6 +60,20 @@
async function handleExport() {
const data = await exportOqc(await gridApi.formApi.getValues());
downloadFileFromBlobPart({ fileName: '鍑鸿揣妫�楠屽崟.xls', source: data });
+}
+
+/** 涓嬭浇璐ㄦ鎶ュ憡锛堜骇鍝佹楠屽崟 Word锛屾墦鍗扮敤 Word 鎵撳紑锛� */
+async function handleExportWord(row: MesQcOqcApi.Oqc) {
+ const hideLoading = message.loading({ content: '鎶ュ憡瀵煎嚭涓�...', duration: 0 });
+ try {
+ const data = await exportProductWord({ qcId: row.id!, qcType: 3 });
+ downloadFileFromBlobPart({
+ fileName: `${row.code || ''}-浜у搧璐ㄩ噺妫�楠屽崟.docx`,
+ source: data,
+ });
+ } finally {
+ hideLoading();
+ }
}
const [Grid, gridApi] = useVbenVxeGrid({
@@ -151,6 +166,13 @@
auth: ['mes:qc-oqc:query'],
onClick: handleDetail.bind(null, row),
},
+ {
+ label: '璐ㄦ鎶ュ憡',
+ type: 'link',
+ icon: ACTION_ICON.DOWNLOAD,
+ auth: ['mes:qc-oqc:query'],
+ onClick: handleExportWord.bind(null, row),
+ },
]"
/>
</template>
diff --git a/src/views/mes/qc/rqc/data.ts b/src/views/mes/qc/rqc/data.ts
index 92d5e1e..0026430 100644
--- a/src/views/mes/qc/rqc/data.ts
+++ b/src/views/mes/qc/rqc/data.ts
@@ -417,7 +417,7 @@
},
{
title: '鎿嶄綔',
- width: 180,
+ width: 260,
fixed: 'right',
slots: { default: 'actions' },
},
diff --git a/src/views/mes/qc/rqc/index.vue b/src/views/mes/qc/rqc/index.vue
index 0cfc6f2..08efd64 100644
--- a/src/views/mes/qc/rqc/index.vue
+++ b/src/views/mes/qc/rqc/index.vue
@@ -9,6 +9,7 @@
import { Button, message } from 'ant-design-vue';
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
+import { exportProductWord } from '#/api/mes/qc/indicatorresult';
import { deleteRqc, exportRqc, getRqcPage } from '#/api/mes/qc/rqc';
import { $t } from '#/locales';
@@ -59,6 +60,20 @@
async function handleExport() {
const data = await exportRqc(await gridApi.formApi.getValues());
downloadFileFromBlobPart({ fileName: '閫�璐ф楠屽崟.xls', source: data });
+}
+
+/** 涓嬭浇璐ㄦ鎶ュ憡锛堜骇鍝佹楠屽崟 Word锛屾墦鍗扮敤 Word 鎵撳紑锛� */
+async function handleExportWord(row: MesQcRqcApi.Rqc) {
+ const hideLoading = message.loading({ content: '鎶ュ憡瀵煎嚭涓�...', duration: 0 });
+ try {
+ const data = await exportProductWord({ qcId: row.id!, qcType: 4 });
+ downloadFileFromBlobPart({
+ fileName: `${row.code || ''}-浜у搧璐ㄩ噺妫�楠屽崟.docx`,
+ source: data,
+ });
+ } finally {
+ hideLoading();
+ }
}
const [Grid, gridApi] = useVbenVxeGrid({
@@ -151,6 +166,13 @@
auth: ['mes:qc-rqc:query'],
onClick: handleDetail.bind(null, row),
},
+ {
+ label: '璐ㄦ鎶ュ憡',
+ type: 'link',
+ icon: ACTION_ICON.DOWNLOAD,
+ auth: ['mes:qc-rqc:query'],
+ onClick: handleExportWord.bind(null, row),
+ },
]"
/>
</template>
diff --git a/vite.config.ts b/vite.config.ts
index 74a95a8..3bb15c1 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -72,7 +72,7 @@
"/admin-api": {
changeOrigin: true,
rewrite: path => path.replace(/^\/admin-api/, ""),
- target: "http://42.63.70.90:9003/admin-api",
+ target: "http://localhost:48081/admin-api",
ws: true,
},
},
--
Gitblit v1.9.3