From fe71f18d217b5fd172995fdbecdded37f1466974 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 29 May 2026 16:52:03 +0800 Subject: [PATCH] =?UTF-8?q?feat(mes-qc):=20=E8=BF=81=E7=A7=BB=20ele=20?= =?UTF-8?q?=E6=9D=A5=E6=96=99=E6=A3=80=E9=AA=8C=E5=8F=8A=E6=A3=80=E6=B5=8B?= =?UTF-8?q?=E7=BB=93=E6=9E=9C=E3=80=81=E7=BC=BA=E9=99=B7=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/qc-indicator-result-form.vue | 19 +- .../mes/qc/defectrecord/components/data.ts | 94 ++++ .../components/defect-record-inline-form.vue | 124 +++++ .../components/defect-record-inline-list.vue | 181 ++++++ .../mes/qc/defectrecord/components/index.ts | 2 + .../mes/qc/indicatorresult/components/data.ts | 88 +++ .../qc/indicatorresult/components/index.ts | 2 + .../components/qc-indicator-result-form.vue | 225 ++++++++ .../components/qc-indicator-result-list.vue | 145 +++++ apps/web-ele/src/views/mes/qc/iqc/data.ts | 515 ++++++++++++++++++ apps/web-ele/src/views/mes/qc/iqc/index.vue | 168 ++++++ .../src/views/mes/qc/iqc/modules/form.vue | 237 ++++++++ .../views/mes/qc/iqc/modules/line-list.vue | 98 ++++ 13 files changed, 1884 insertions(+), 14 deletions(-) create mode 100644 apps/web-ele/src/views/mes/qc/defectrecord/components/data.ts create mode 100644 apps/web-ele/src/views/mes/qc/defectrecord/components/defect-record-inline-form.vue create mode 100644 apps/web-ele/src/views/mes/qc/defectrecord/components/defect-record-inline-list.vue create mode 100644 apps/web-ele/src/views/mes/qc/defectrecord/components/index.ts create mode 100644 apps/web-ele/src/views/mes/qc/indicatorresult/components/data.ts create mode 100644 apps/web-ele/src/views/mes/qc/indicatorresult/components/index.ts create mode 100644 apps/web-ele/src/views/mes/qc/indicatorresult/components/qc-indicator-result-form.vue create mode 100644 apps/web-ele/src/views/mes/qc/indicatorresult/components/qc-indicator-result-list.vue create mode 100644 apps/web-ele/src/views/mes/qc/iqc/data.ts create mode 100644 apps/web-ele/src/views/mes/qc/iqc/index.vue create mode 100644 apps/web-ele/src/views/mes/qc/iqc/modules/form.vue create mode 100644 apps/web-ele/src/views/mes/qc/iqc/modules/line-list.vue diff --git a/apps/web-antd/src/views/mes/qc/indicatorresult/components/qc-indicator-result-form.vue b/apps/web-antd/src/views/mes/qc/indicatorresult/components/qc-indicator-result-form.vue index e33a59a8d..d7d7c9f27 100644 --- a/apps/web-antd/src/views/mes/qc/indicatorresult/components/qc-indicator-result-form.vue +++ b/apps/web-antd/src/views/mes/qc/indicatorresult/components/qc-indicator-result-form.vue @@ -6,6 +6,7 @@ import type { MesQcIndicatorResultApi } from '#/api/mes/qc/indicatorresult'; import { computed, ref } from 'vue'; import { useVbenModal } from '@vben/common-ui'; +import { getDictOptions } from '@vben/hooks'; import { Form as AForm, @@ -62,19 +63,9 @@ const [Form, formApi] = useVbenForm({ wrapperClass: 'grid-cols-2', }); -/** 解析字典选项字符串:value=label;value=label */ -function parseValueOptions(spec?: string) { - if (!spec) { - return []; - } - return spec - .split(';') - .map((part) => part.trim()) - .filter(Boolean) - .map((part) => { - const [value, label] = part.split('='); - return { value: value ?? '', label: label ?? value ?? '' }; - }); +/** 获取字典选项(valueSpecification 为系统字典类型名) */ +function getValueOptions(dictType?: string) { + return dictType ? getDictOptions(dictType, 'string') : []; } const [Modal, modalApi] = useVbenModal({ @@ -205,7 +196,7 @@ const [Modal, modalApi] = useVbenModal({ v-else-if="item.valueType === MesQcResultValueType.DICT" v-model:value="item.value" allow-clear - :options="parseValueOptions(item.valueSpecification)" + :options="getValueOptions(item.valueSpecification)" placeholder="请选择" /> ['columns'] { + return [ + { + field: 'name', + title: '缺陷描述', + minWidth: 200, + }, + { + field: 'level', + title: '缺陷等级', + width: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.MES_DEFECT_LEVEL }, + }, + }, + { + field: 'quantity', + title: '缺陷数量', + width: 100, + }, + { + field: 'remark', + title: '备注', + minWidth: 150, + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mes/qc/defectrecord/components/defect-record-inline-form.vue b/apps/web-ele/src/views/mes/qc/defectrecord/components/defect-record-inline-form.vue new file mode 100644 index 000000000..b7645b1d7 --- /dev/null +++ b/apps/web-ele/src/views/mes/qc/defectrecord/components/defect-record-inline-form.vue @@ -0,0 +1,124 @@ + + + diff --git a/apps/web-ele/src/views/mes/qc/defectrecord/components/defect-record-inline-list.vue b/apps/web-ele/src/views/mes/qc/defectrecord/components/defect-record-inline-list.vue new file mode 100644 index 000000000..80b049926 --- /dev/null +++ b/apps/web-ele/src/views/mes/qc/defectrecord/components/defect-record-inline-list.vue @@ -0,0 +1,181 @@ + + + diff --git a/apps/web-ele/src/views/mes/qc/defectrecord/components/index.ts b/apps/web-ele/src/views/mes/qc/defectrecord/components/index.ts new file mode 100644 index 000000000..6a2bd142a --- /dev/null +++ b/apps/web-ele/src/views/mes/qc/defectrecord/components/index.ts @@ -0,0 +1,2 @@ +export { default as DefectRecordInlineForm } from './defect-record-inline-form.vue'; +export { default as DefectRecordInlineList } from './defect-record-inline-list.vue'; diff --git a/apps/web-ele/src/views/mes/qc/indicatorresult/components/data.ts b/apps/web-ele/src/views/mes/qc/indicatorresult/components/data.ts new file mode 100644 index 000000000..c1be4b795 --- /dev/null +++ b/apps/web-ele/src/views/mes/qc/indicatorresult/components/data.ts @@ -0,0 +1,88 @@ +import type { VbenFormApi, VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { MesQcIndicatorResultApi } from '#/api/mes/qc/indicatorresult'; + +import { h } from 'vue'; + +import { ElButton } from 'element-plus'; + +import { generateAutoCode } from '#/api/mes/md/autocode/record'; +import { MesAutoCodeRuleCode } from '#/views/mes/utils/constants'; + +/** 表单类型 */ +export type FormType = 'create' | 'update'; + +/** 新增/修改检测结果的表单 */ +export function useQcIndicatorResultFormSchema( + formApi?: VbenFormApi, +): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'code', + label: '样品编号', + component: 'Input', + componentProps: { + placeholder: '请输入样品编号', + }, + rules: 'required', + suffix: () => + h( + ElButton, + { + onClick: async () => { + try { + const code = await generateAutoCode( + MesAutoCodeRuleCode.QC_INDICATOR_RESULT_CODE, + ); + await formApi?.setFieldValue('code', code); + } catch (error) { + console.error(error); + } + }, + }, + { default: () => '生成' }, + ), + }, + { + fieldName: 'sn', + label: '物资 SN', + component: 'Input', + componentProps: { + placeholder: '请输入物资 SN', + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + formItemClass: 'col-span-2', + componentProps: { + placeholder: '请输入备注', + rows: 2, + }, + }, + ]; +} + +/** 检测结果列表的字段 */ +export function useQcIndicatorResultGridColumns(): VxeTableGridOptions['columns'] { + return [ + { field: 'code', title: '样品编号', width: 200 }, + { field: 'sn', title: '物资SN', minWidth: 200 }, + { field: 'remark', title: '备注', minWidth: 200 }, + { + title: '操作', + width: 150, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mes/qc/indicatorresult/components/index.ts b/apps/web-ele/src/views/mes/qc/indicatorresult/components/index.ts new file mode 100644 index 000000000..590fb8b8e --- /dev/null +++ b/apps/web-ele/src/views/mes/qc/indicatorresult/components/index.ts @@ -0,0 +1,2 @@ +export { default as QcIndicatorResultForm } from './qc-indicator-result-form.vue'; +export { default as QcIndicatorResultList } from './qc-indicator-result-list.vue'; diff --git a/apps/web-ele/src/views/mes/qc/indicatorresult/components/qc-indicator-result-form.vue b/apps/web-ele/src/views/mes/qc/indicatorresult/components/qc-indicator-result-form.vue new file mode 100644 index 000000000..398fac75a --- /dev/null +++ b/apps/web-ele/src/views/mes/qc/indicatorresult/components/qc-indicator-result-form.vue @@ -0,0 +1,225 @@ + + + diff --git a/apps/web-ele/src/views/mes/qc/indicatorresult/components/qc-indicator-result-list.vue b/apps/web-ele/src/views/mes/qc/indicatorresult/components/qc-indicator-result-list.vue new file mode 100644 index 000000000..bc9f555fc --- /dev/null +++ b/apps/web-ele/src/views/mes/qc/indicatorresult/components/qc-indicator-result-list.vue @@ -0,0 +1,145 @@ + + + diff --git a/apps/web-ele/src/views/mes/qc/iqc/data.ts b/apps/web-ele/src/views/mes/qc/iqc/data.ts new file mode 100644 index 000000000..804ef7df4 --- /dev/null +++ b/apps/web-ele/src/views/mes/qc/iqc/data.ts @@ -0,0 +1,515 @@ +import type { VbenFormApi, VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { MesQcIqcApi } from '#/api/mes/qc/iqc'; +import type { MesQcIqcLineApi } from '#/api/mes/qc/iqc/line'; + +import { h, markRaw } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +import { ElButton } from 'element-plus'; + +import { generateAutoCode } from '#/api/mes/md/autocode/record'; +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; +import MdItemSelect from '#/views/mes/md/item/components/md-item-select.vue'; +import MdVendorSelect from '#/views/mes/md/vendor/components/md-vendor-select.vue'; +import { MesAutoCodeRuleCode } from '#/views/mes/utils/constants'; + +/** 表单类型 */ +export type FormType = 'create' | 'detail' | 'update'; + +/** 新增/修改的表单 */ +export function useFormSchema(formApi?: VbenFormApi): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'sourceDocId', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'sourceLineId', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'status', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'code', + label: '检验单编号', + component: 'Input', + componentProps: { + placeholder: '请输入检验单编号', + }, + rules: 'required', + suffix: () => + h( + ElButton, + { + onClick: async () => { + try { + const code = await generateAutoCode( + MesAutoCodeRuleCode.QC_IQC_CODE, + ); + await formApi?.setFieldValue('code', code); + } catch (error) { + console.error(error); + } + }, + }, + { default: () => '生成' }, + ), + }, + { + fieldName: 'name', + label: '检验单名称', + component: 'Input', + componentProps: { + placeholder: '请输入检验单名称', + }, + rules: 'required', + }, + { + fieldName: 'sourceDocType', + label: '来源单据类型', + component: 'Select', + componentProps: { + disabled: true, + options: getDictOptions(DICT_TYPE.MES_QC_SOURCE_DOC_TYPE, 'number'), + placeholder: '来源单据类型', + }, + dependencies: { + triggerFields: ['sourceDocType'], + show: (values) => !!values.sourceDocType, + }, + }, + { + fieldName: 'sourceDocCode', + label: '来源单据编号', + component: 'Input', + componentProps: { + disabled: true, + placeholder: '来源单据编号', + }, + dependencies: { + triggerFields: ['sourceDocType', 'sourceDocId'], + show: (values) => !!values.sourceDocType && !!values.sourceDocId, + }, + }, + { + fieldName: 'itemId', + label: '产品物料', + component: markRaw(MdItemSelect), + componentProps: { + placeholder: '请选择产品物料', + }, + rules: 'selectRequired', + dependencies: { + triggerFields: ['id', 'sourceDocId'], + componentProps: (values) => ({ + disabled: !!values.id || !!values.sourceDocId, + placeholder: '请选择产品物料', + }), + }, + }, + { + fieldName: 'vendorId', + label: '供应商', + component: markRaw(MdVendorSelect), + componentProps: { + placeholder: '请选择供应商', + }, + rules: 'selectRequired', + dependencies: { + triggerFields: ['sourceDocId'], + componentProps: (values) => ({ + disabled: !!values.sourceDocId, + placeholder: '请选择供应商', + }), + }, + }, + { + fieldName: 'vendorBatch', + label: '供应商批次号', + component: 'Input', + componentProps: { + placeholder: '请输入供应商批次号', + }, + }, + { + fieldName: 'receivedQuantity', + label: '本次接收数量', + component: 'InputNumber', + componentProps: { + class: '!w-full', + controlsPosition: 'right', + min: 0, + placeholder: '请输入本次接收数量', + precision: 2, + }, + rules: 'required', + dependencies: { + triggerFields: ['sourceDocId'], + componentProps: (values) => ({ + class: '!w-full', + controlsPosition: 'right', + disabled: !!values.sourceDocId, + min: 0, + placeholder: '请输入本次接收数量', + precision: 2, + }), + }, + }, + { + fieldName: 'qualifiedQuantity', + label: '合格品数量', + component: 'InputNumber', + componentProps: { + class: '!w-full', + controlsPosition: 'right', + min: 0, + placeholder: '请输入合格品数量', + }, + rules: 'required', + }, + { + fieldName: 'unqualifiedQuantity', + label: '不合格品数量', + component: 'InputNumber', + componentProps: { + class: '!w-full', + controlsPosition: 'right', + min: 0, + placeholder: '请输入不合格品数量', + }, + rules: 'required', + }, + { + fieldName: 'receiveDate', + label: '来料日期', + component: 'DatePicker', + componentProps: { + format: 'YYYY-MM-DD', + placeholder: '请选择来料日期', + type: 'date', + valueFormat: 'x', + }, + rules: 'required', + }, + { + fieldName: 'inspectorUserId', + label: '检测人员', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + clearable: true, + labelField: 'nickname', + placeholder: '请选择检测人员', + valueField: 'id', + }, + rules: 'selectRequired', + }, + { + fieldName: 'inspectDate', + label: '检测日期', + component: 'DatePicker', + componentProps: { + format: 'YYYY-MM-DD', + placeholder: '请选择检测日期', + type: 'date', + valueFormat: 'x', + }, + rules: 'required', + }, + { + fieldName: 'checkResult', + label: '检测结果', + component: 'Select', + componentProps: { + clearable: true, + options: getDictOptions(DICT_TYPE.MES_QC_CHECK_RESULT, 'number'), + placeholder: '请选择检测结果', + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + formItemClass: 'col-span-3', + componentProps: { + placeholder: '请输入备注', + rows: 3, + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'code', + label: '检验单编号', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入检验单编号', + }, + }, + { + fieldName: 'vendorId', + label: '供应商', + component: markRaw(MdVendorSelect), + componentProps: { + placeholder: '请选择供应商', + }, + }, + { + fieldName: 'vendorBatch', + label: '供应商批次', + component: 'Input', + componentProps: { + clearable: true, + placeholder: '请输入供应商批次号', + }, + }, + { + fieldName: 'itemId', + label: '产品物料', + component: markRaw(MdItemSelect), + componentProps: { + placeholder: '请选择产品物料', + }, + }, + { + fieldName: 'checkResult', + label: '检测结果', + component: 'Select', + componentProps: { + clearable: true, + options: getDictOptions(DICT_TYPE.MES_QC_CHECK_RESULT, 'number'), + placeholder: '请选择检测结果', + }, + }, + { + fieldName: 'receiveDate', + label: '来料日期', + component: 'DatePicker', + componentProps: { + ...getRangePickerDefaultProps(), + type: 'daterange', + }, + }, + { + fieldName: 'inspectDate', + label: '检测日期', + component: 'DatePicker', + componentProps: { + ...getRangePickerDefaultProps(), + type: 'daterange', + }, + }, + { + fieldName: 'inspectorUserId', + label: '检测人员', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + clearable: true, + labelField: 'nickname', + placeholder: '请选择检测人员', + valueField: 'id', + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'code', + title: '来料检验单编号', + width: 160, + slots: { default: 'code' }, + }, + { + field: 'name', + title: '来料检验单名称', + minWidth: 180, + }, + { + field: 'vendorNickname', + title: '供应商简称', + width: 120, + }, + { + field: 'vendorBatch', + title: '供应商批次号', + width: 130, + }, + { + field: 'itemCode', + title: '产品物料编码', + width: 130, + }, + { + field: 'itemName', + title: '产品物料名称', + minWidth: 150, + }, + { + field: 'receivedQuantity', + title: '接收数量', + width: 100, + }, + { + field: 'checkQuantity', + title: '检测数量', + width: 100, + }, + { + field: 'unqualifiedQuantity', + title: '不合格数', + width: 100, + }, + { + field: 'checkResult', + title: '检测结果', + width: 110, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.MES_QC_CHECK_RESULT }, + }, + }, + { + field: 'receiveDate', + title: '来料日期', + width: 120, + formatter: 'formatDate', + }, + { + field: 'inspectDate', + title: '检测日期', + width: 120, + formatter: 'formatDate', + }, + { + field: 'inspectorNickname', + title: '检测人员', + width: 100, + }, + { + field: 'status', + title: '单据状态', + width: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.MES_ORDER_STATUS }, + }, + }, + { + title: '操作', + width: 180, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 来料检验行子表的字段 */ +export function useLineGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'indicatorName', + title: '检测项名称', + width: 150, + }, + { + field: 'indicatorType', + title: '检测项类型', + width: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.MES_INDICATOR_TYPE }, + }, + }, + { + field: 'tool', + title: '检测工具', + width: 120, + }, + { + field: 'checkMethod', + title: '检测要求', + minWidth: 180, + }, + { + field: 'standardValue', + title: '标准值', + width: 100, + }, + { + field: 'unitMeasureName', + title: '单位', + width: 80, + }, + { + field: 'maxThreshold', + title: '误差上限', + width: 100, + }, + { + field: 'minThreshold', + title: '误差下限', + width: 100, + }, + { + field: 'criticalQuantity', + title: '致命缺陷数', + width: 110, + }, + { + field: 'majorQuantity', + title: '严重缺陷数', + width: 110, + }, + { + field: 'minorQuantity', + title: '轻微缺陷数', + width: 110, + }, + { + field: 'remark', + title: '备注', + minWidth: 150, + }, + { + title: '操作', + width: 110, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/mes/qc/iqc/index.vue b/apps/web-ele/src/views/mes/qc/iqc/index.vue new file mode 100644 index 000000000..eadb60428 --- /dev/null +++ b/apps/web-ele/src/views/mes/qc/iqc/index.vue @@ -0,0 +1,168 @@ + + + diff --git a/apps/web-ele/src/views/mes/qc/iqc/modules/form.vue b/apps/web-ele/src/views/mes/qc/iqc/modules/form.vue new file mode 100644 index 000000000..74817b7d6 --- /dev/null +++ b/apps/web-ele/src/views/mes/qc/iqc/modules/form.vue @@ -0,0 +1,237 @@ + + + diff --git a/apps/web-ele/src/views/mes/qc/iqc/modules/line-list.vue b/apps/web-ele/src/views/mes/qc/iqc/modules/line-list.vue new file mode 100644 index 000000000..eadf2d1cc --- /dev/null +++ b/apps/web-ele/src/views/mes/qc/iqc/modules/line-list.vue @@ -0,0 +1,98 @@ + + +