feat(mes): 迁移 ipqc、oqc、rqc 功能(优化)

pull/350/head
YunaiV 2026-05-29 21:10:18 +08:00
parent eeff84b63f
commit f79dffcf2e
16 changed files with 268 additions and 23 deletions

View File

@ -22,8 +22,11 @@ defineOptions({ name: 'DefectRecordInlineList' });
const emit = defineEmits(['success']);
/** 表单类型父级检验单的模式detail 时弹窗只读) */
type FormType = 'create' | 'detail' | 'update';
interface CtxData {
formType?: string;
formType?: FormType;
lineId: number;
qcId: number;
qcType: number;

View File

@ -0,0 +1,239 @@
<script lang="ts" setup>
import type { FormType } from '../data';
import type { MesQcIpqcApi } from '#/api/mes/qc/ipqc';
import { computed, ref } from 'vue';
import { confirm, useVbenModal } from '@vben/common-ui';
import { Button, Descriptions, message, Tabs } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
import {
createIpqc,
finishIpqc,
getIpqc,
updateIpqc,
} from '#/api/mes/qc/ipqc';
import { $t } from '#/locales';
import { MesQcStatusEnum, MesQcTypeEnum } from '#/views/mes/utils/constants';
import { QcIndicatorResultList } from '../../indicatorresult/components';
import { useFormSchema } from '../data';
import LineList from './line-list.vue';
const emit = defineEmits(['success']);
const formType = ref<FormType>('create');
const formData = ref<MesQcIpqcApi.Ipqc>();
const subTabsName = ref('line');
const originalSnapshot = ref(''); // finish
const isDetail = computed(() => formType.value === 'detail');
const canFinish = computed(
() =>
formType.value === 'update' &&
formData.value?.status === MesQcStatusEnum.DRAFT,
);
const getTitle = computed(() => {
if (formType.value === 'detail') {
return $t('ui.actionTitle.view', ['过程检验单']);
}
return formType.value === 'update'
? $t('ui.actionTitle.edit', ['过程检验单'])
: $t('ui.actionTitle.create', ['过程检验单']);
});
const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-1',
labelWidth: 110,
},
wrapperClass: 'grid-cols-3',
layout: 'horizontal',
schema: [],
showDefaultActions: false,
});
/** 子表变更后刷新主表头数据(缺陷统计等) */
async function handleRefresh() {
if (!formData.value?.id) {
return;
}
formData.value = await getIpqc(formData.value.id);
}
/** 提交表单 */
async function handleSubmit(): Promise<boolean> {
const { valid } = await formApi.validate();
if (!valid) {
return false;
}
const data = (await formApi.getValues()) as MesQcIpqcApi.Ipqc;
if (formData.value?.id) {
await updateIpqc({ ...data, id: formData.value.id });
formData.value = { ...formData.value, ...data };
} else {
const id = await createIpqc(data);
formData.value = {
...data,
id: id as unknown as number,
status: MesQcStatusEnum.DRAFT,
};
await formApi.setFieldValue('id', formData.value.id);
await formApi.setFieldValue('status', formData.value.status);
formType.value = 'update';
}
// id / status finish
originalSnapshot.value = JSON.stringify(await formApi.getValues());
return true;
}
/** 完成检验单:表单有修改时先保存,再调用完成接口 */
async function handleFinish() {
const id = formData.value?.id;
if (!id) {
return;
}
const { valid } = await formApi.validate();
if (!valid) {
return;
}
try {
await confirm('是否完成过程检验单编制?【完成后将不能更改】');
} catch {
return;
}
modalApi.lock();
try {
const current = JSON.stringify(await formApi.getValues());
if (current !== originalSnapshot.value) {
const data = (await formApi.getValues()) as MesQcIpqcApi.Ipqc;
await updateIpqc({ ...data, id });
formData.value = { ...formData.value, ...data };
originalSnapshot.value = current;
}
await finishIpqc(id);
message.success('完成成功');
await modalApi.close();
emit('success');
} finally {
modalApi.unlock();
}
}
const [Modal, modalApi] = useVbenModal({
async onConfirm() {
if (isDetail.value) {
await modalApi.close();
return;
}
modalApi.lock();
try {
//
const ok = await handleSubmit();
if (!ok) {
return;
}
//
message.success($t('ui.actionMessage.operationSuccess'));
await modalApi.close();
emit('success');
} finally {
modalApi.unlock();
}
},
async onOpenChange(isOpen: boolean) {
if (!isOpen) {
formData.value = undefined;
originalSnapshot.value = '';
return;
}
formApi.setState({ schema: useFormSchema(formApi) });
subTabsName.value = 'line';
//
const data = modalApi.getData<{
formType: FormType;
id?: number;
prefill?: MesQcIpqcApi.Ipqc;
}>();
formType.value = data.formType;
formApi.setDisabled(formType.value === 'detail');
modalApi.setState({ showConfirmButton: formType.value !== 'detail' });
if (data?.id) {
modalApi.lock();
try {
formData.value = await getIpqc(data.id);
// values
await formApi.setValues(formData.value);
} finally {
modalApi.unlock();
}
} else if (data?.prefill) {
//
formData.value = { ...data.prefill };
// values
await formApi.setValues(data.prefill);
}
originalSnapshot.value = JSON.stringify(await formApi.getValues());
},
});
</script>
<template>
<Modal :title="getTitle" class="w-4/5">
<Form class="mx-4" />
<!-- 缺陷统计只读 -->
<div v-if="formData?.id" class="mx-4 mt-4">
<Descriptions title="缺陷情况" :column="3" bordered size="small">
<Descriptions.Item label="致命缺陷数">
{{ formData.criticalQuantity ?? 0 }}
</Descriptions.Item>
<Descriptions.Item label="严重缺陷数">
{{ formData.majorQuantity ?? 0 }}
</Descriptions.Item>
<Descriptions.Item label="轻微缺陷数">
{{ formData.minorQuantity ?? 0 }}
</Descriptions.Item>
<Descriptions.Item label="致命缺陷率">
{{ formData.criticalRate ?? 0 }}%
</Descriptions.Item>
<Descriptions.Item label="严重缺陷率">
{{ formData.majorRate ?? 0 }}%
</Descriptions.Item>
<Descriptions.Item label="轻微缺陷率">
{{ formData.minorRate ?? 0 }}%
</Descriptions.Item>
</Descriptions>
</div>
<Tabs
v-if="formData?.id"
v-model:active-key="subTabsName"
class="mx-4 mt-4"
>
<Tabs.TabPane key="line" tab="检验项">
<LineList
:form-type="formType"
:ipqc-id="formData.id"
@refresh="handleRefresh"
/>
</Tabs.TabPane>
<Tabs.TabPane key="result" tab="检测结果">
<QcIndicatorResultList
:qc-id="formData.id"
:qc-type="MesQcTypeEnum.IPQC"
:readonly="isDetail"
/>
</Tabs.TabPane>
</Tabs>
<template #prepend-footer>
<div class="flex flex-auto items-center gap-2">
<Button v-if="canFinish" type="primary" @click="handleFinish">
完成
</Button>
</div>
</template>
</Modal>
</template>

View File

@ -9,10 +9,10 @@ import { getIpqcLinePage } from '#/api/mes/qc/ipqc/line';
import { MesQcTypeEnum } from '#/views/mes/utils/constants';
import { DefectRecordInlineList } from '../../defectrecord/components';
import { useLineGridColumns } from '../data';
import { type FormType, useLineGridColumns } from '../data';
const props = defineProps<{
formType?: string;
formType?: FormType;
ipqcId: number;
}>();

View File

@ -9,10 +9,10 @@ import { getIqcLinePage } from '#/api/mes/qc/iqc/line';
import { MesQcTypeEnum } from '#/views/mes/utils/constants';
import { DefectRecordInlineList } from '../../defectrecord/components';
import { useLineGridColumns } from '../data';
import { type FormType, useLineGridColumns } from '../data';
const props = defineProps<{
formType?: string;
formType?: FormType;
iqcId: number;
}>();

View File

@ -27,7 +27,7 @@ const emit = defineEmits(['success']);
const formType = ref<FormType>('create');
const formData = ref<MesQcOqcApi.Oqc>();
const subTabsName = ref('line');
const originalSnapshot = ref('');
const originalSnapshot = ref(''); // finish
const isDetail = computed(() => formType.value === 'detail');
const canFinish = computed(
() =>

View File

@ -9,10 +9,10 @@ import { getOqcLinePage } from '#/api/mes/qc/oqc/line';
import { MesQcTypeEnum } from '#/views/mes/utils/constants';
import { DefectRecordInlineList } from '../../defectrecord/components';
import { useLineGridColumns } from '../data';
import { type FormType, useLineGridColumns } from '../data';
const props = defineProps<{
formType?: string;
formType?: FormType;
oqcId: number;
}>();

View File

@ -27,7 +27,7 @@ const emit = defineEmits(['success']);
const formType = ref<FormType>('create');
const formData = ref<MesQcRqcApi.Rqc>();
const subTabsName = ref('line');
const originalSnapshot = ref('');
const originalSnapshot = ref(''); // finish
const isDetail = computed(() => formType.value === 'detail');
const canFinish = computed(
() =>

View File

@ -9,10 +9,10 @@ import { getRqcLinePage } from '#/api/mes/qc/rqc/line';
import { MesQcTypeEnum } from '#/views/mes/utils/constants';
import { DefectRecordInlineList } from '../../defectrecord/components';
import { useLineGridColumns } from '../data';
import { type FormType, useLineGridColumns } from '../data';
const props = defineProps<{
formType?: string;
formType?: FormType;
rqcId: number;
}>();

View File

@ -22,8 +22,11 @@ defineOptions({ name: 'DefectRecordInlineList' });
const emit = defineEmits(['success']);
/** 表单类型父级检验单的模式detail 时弹窗只读) */
type FormType = 'create' | 'detail' | 'update';
interface CtxData {
formType?: string;
formType?: FormType;
lineId: number;
qcId: number;
qcType: number;

View File

@ -34,7 +34,7 @@ const emit = defineEmits(['success']);
const formType = ref<FormType>('create');
const formData = ref<MesQcIpqcApi.Ipqc>();
const subTabsName = ref('line');
const originalSnapshot = ref('');
const originalSnapshot = ref(''); // finish
const isDetail = computed(() => formType.value === 'detail');
const canFinish = computed(
() =>

View File

@ -9,10 +9,10 @@ import { getIpqcLinePage } from '#/api/mes/qc/ipqc/line';
import { MesQcTypeEnum } from '#/views/mes/utils/constants';
import { DefectRecordInlineList } from '../../defectrecord/components';
import { useLineGridColumns } from '../data';
import { type FormType, useLineGridColumns } from '../data';
const props = defineProps<{
formType?: string;
formType?: FormType;
ipqcId: number;
}>();

View File

@ -9,10 +9,10 @@ import { getIqcLinePage } from '#/api/mes/qc/iqc/line';
import { MesQcTypeEnum } from '#/views/mes/utils/constants';
import { DefectRecordInlineList } from '../../defectrecord/components';
import { useLineGridColumns } from '../data';
import { type FormType, useLineGridColumns } from '../data';
const props = defineProps<{
formType?: string;
formType?: FormType;
iqcId: number;
}>();

View File

@ -34,7 +34,7 @@ const emit = defineEmits(['success']);
const formType = ref<FormType>('create');
const formData = ref<MesQcOqcApi.Oqc>();
const subTabsName = ref('line');
const originalSnapshot = ref('');
const originalSnapshot = ref(''); // finish
const isDetail = computed(() => formType.value === 'detail');
const canFinish = computed(
() =>

View File

@ -9,10 +9,10 @@ import { getOqcLinePage } from '#/api/mes/qc/oqc/line';
import { MesQcTypeEnum } from '#/views/mes/utils/constants';
import { DefectRecordInlineList } from '../../defectrecord/components';
import { useLineGridColumns } from '../data';
import { type FormType, useLineGridColumns } from '../data';
const props = defineProps<{
formType?: string;
formType?: FormType;
oqcId: number;
}>();

View File

@ -34,7 +34,7 @@ const emit = defineEmits(['success']);
const formType = ref<FormType>('create');
const formData = ref<MesQcRqcApi.Rqc>();
const subTabsName = ref('line');
const originalSnapshot = ref('');
const originalSnapshot = ref(''); // finish
const isDetail = computed(() => formType.value === 'detail');
const canFinish = computed(
() =>

View File

@ -9,10 +9,10 @@ import { getRqcLinePage } from '#/api/mes/qc/rqc/line';
import { MesQcTypeEnum } from '#/views/mes/utils/constants';
import { DefectRecordInlineList } from '../../defectrecord/components';
import { useLineGridColumns } from '../data';
import { type FormType, useLineGridColumns } from '../data';
const props = defineProps<{
formType?: string;
formType?: FormType;
rqcId: number;
}>();