From 173855b299e89930b5ea2ff9a9295fde9d0f55b5 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期六, 07 十一月 2026 08:51:43 +0800
Subject: [PATCH] feat: 同步质检、生产、销售、财务与人事前端功能
---
src/views/mes/pro/feedback/modules/form.vue | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 171 insertions(+), 4 deletions(-)
diff --git a/src/views/mes/pro/feedback/modules/form.vue b/src/views/mes/pro/feedback/modules/form.vue
index 0b5594d..c2ee010 100644
--- a/src/views/mes/pro/feedback/modules/form.vue
+++ b/src/views/mes/pro/feedback/modules/form.vue
@@ -1,7 +1,9 @@
<script lang="ts" setup>
-import type { FormType } from '../data';
+import type { FormType, FeedbackFormHooks } from '../data';
import type { MesProFeedbackApi } from '#/api/mes/pro/feedback';
+import type { MesProTaskApi } from '#/api/mes/pro/task';
+import type { MesProFeedbackWagePreviewApi } from '#/api/mes/pro/wage';
import { computed, ref } from 'vue';
@@ -11,7 +13,7 @@
import { MesAutoCodeRuleCode, MesProFeedbackStatusEnum } from '@vben/constants';
import { useUserStore } from '@vben/stores';
-import { Button, Input, message, Popconfirm, Tabs } from 'ant-design-vue';
+import { Alert, Button, Input, message, Popconfirm, Tabs } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
import { generateAutoCode } from '#/api/mes/md/autocode/record';
@@ -25,6 +27,7 @@
updateFeedback,
} from '#/api/mes/pro/feedback';
import { getWorkOrder } from '#/api/mes/pro/workorder';
+import { previewFeedbackWage } from '#/api/mes/pro/wage';
import { $t } from '#/locales';
import { useFormSchema } from '../data';
@@ -32,6 +35,7 @@
import BatchInputDialog from './batch-input-dialog.vue';
import ItemConsumeList from './item-consume-list.vue';
import ProductProduceList from './product-produce-list.vue';
+import WorktimeAuxInput from './worktime-aux-input.vue';
const emit = defineEmits(['success']);
const formType = ref<FormType>('create');
@@ -40,6 +44,65 @@
const userStore = useUserStore();
const subTabsName = ref('itemConsume');
const originalSnapshot = ref(''); // 琛ㄥ崟鍘熷鏁版嵁蹇収锛岀敤浜� submit 鏃惰烦杩囨湭鍙樻洿鐨勪繚瀛樿姹�
+/** 褰撳墠閫変腑鐨勭敓浜т换鍔★紝鐢ㄤ簬杈呭姪宸ユ椂缁勪欢鎸夊伐搴�/鏈哄彴鍔犺浇閰嶇疆 */
+const currentTask = ref<Partial<MesProTaskApi.Task>>();
+const productionLength = ref<number>();
+const workHours = ref<number>();
+const auxRef = ref<InstanceType<typeof WorktimeAuxInput>>();
+/** 鍚庣宸ヨ祫璇曠畻缁撴灉锛堝惈杈呭姪宸ヨ祫銆佽川閲忚皟鏁达級 */
+const wagePreview = ref<MesProFeedbackWagePreviewApi.PreviewResp>();
+let previewTimer: ReturnType<typeof setTimeout> | undefined;
+
+/** 璋冪敤鍚庣璇曠畻宸ヨ祫锛氭湭鎸囧畾璁惧鏃舵寜宸ュ簭榛樿鍗曚环锛屾寚瀹氳澶囨寜璁惧缁村害瑙勫垯 */
+async function refreshWagePreview() {
+ if (!isEditable.value) {
+ wagePreview.value = undefined;
+ return;
+ }
+ const values = (await formApi.getValues()) as MesProFeedbackApi.Feedback;
+ if (!values.taskId) {
+ wagePreview.value = undefined;
+ return;
+ }
+ try {
+ wagePreview.value = await previewFeedbackWage({
+ taskId: values.taskId,
+ machineryId: values.machineryId,
+ workHours: values.workHours,
+ feedbackQuantity: values.feedbackQuantity,
+ productionLength: values.productionLength,
+ auxList: auxRef.value?.getAuxList(),
+ });
+ } catch {
+ // 璇曠畻澶辫触涓嶉樆鏂綍鍏ワ紝淇濆瓨鏃跺悗绔細缁欏嚭绮剧‘鏍¢獙鎻愮ず
+ wagePreview.value = undefined;
+ }
+}
+
+/** 闃叉姈瑙﹀彂宸ヨ祫璇曠畻锛岄伩鍏嶈繛缁綍鍏ユ椂棰戠箒璇锋眰 */
+function schedulePreview() {
+ if (previewTimer) {
+ clearTimeout(previewTimer);
+ }
+ previewTimer = setTimeout(() => {
+ refreshWagePreview();
+ }, 500);
+}
+
+const formHooks: FeedbackFormHooks = {
+ onTaskChange: (task) => {
+ currentTask.value = task;
+ productionLength.value = undefined;
+ workHours.value = undefined;
+ },
+ onProductionLengthChange: (value) => {
+ productionLength.value = value;
+ },
+ onWorkHoursChange: (value) => {
+ workHours.value = value;
+ },
+ onPreviewWage: () => schedulePreview(),
+};
const isEditable = computed(() =>
['create', 'submit', 'update'].includes(formType.value),
@@ -101,6 +164,10 @@
const data = (await formApi.getValues()) as MesProFeedbackApi.Feedback;
syncParamValues(data);
alignQuantity(data);
+ // 杈呭姪椤规鏁扮敱宸ユ椂缁勪欢缁存姢锛涙爣鍑嗗伐鏃朵互鍚庣淇濆瓨鏃堕噸绠椾负鍑�
+ if (isEditable.value && auxRef.value) {
+ data.auxList = auxRef.value.getAuxList();
+ }
return data;
}
@@ -124,7 +191,9 @@
status: MesProFeedbackStatusEnum.PREPARE,
};
formType.value = 'update';
- formApi.setState({ schema: useFormSchema(formType.value, formApi) });
+ formApi.setState({
+ schema: useFormSchema(formType.value, formApi, formHooks),
+ });
await formApi.setFieldValue('id', id);
message.success($t('common.createSuccess'));
} else {
@@ -305,13 +374,23 @@
subTabsName.value = 'itemConsume';
originalSnapshot.value = '';
paramDetails.value = [];
+ currentTask.value = undefined;
+ productionLength.value = undefined;
+ workHours.value = undefined;
+ wagePreview.value = undefined;
+ if (previewTimer) {
+ clearTimeout(previewTimer);
+ previewTimer = undefined;
+ }
return;
}
// 鍔犺浇鏁版嵁
const data = modalApi.getData<{ formType: FormType; id?: number; showSubmitButton?: boolean }>();
formType.value = data.formType;
showSubmitButton.value = data.showSubmitButton !== false;
- formApi.setState({ schema: useFormSchema(formType.value, formApi) });
+ formApi.setState({
+ schema: useFormSchema(formType.value, formApi, formHooks),
+ });
// 瀹℃壒/璇︽儏鏁磋〃绂佺敤锛岄伩鍏嶅鏍镐汉璇敼鏈彁浜ょ殑瀛楁
formApi.setDisabled(
formType.value === 'approve' || formType.value === 'detail',
@@ -342,8 +421,17 @@
await loadParamDetails(formData.value.taskId);
// 璁剧疆鍒� values
await formApi.setValues({ ...formData.value });
+ // 鍚屾宸ユ椂缁勪欢鎵�闇�鐨勪笂涓嬫枃锛岀紪杈戞椂鎸夊凡鏈夋鏁板洖鏄�
+ currentTask.value = {
+ id: formData.value.taskId,
+ processId: formData.value.processId,
+ workstationId: formData.value.workstationId,
+ };
+ productionLength.value = formData.value.productionLength;
+ workHours.value = formData.value.workHours;
// 璁板綍鍒濆蹇収锛堝惈鏁伴噺瀵归綈缁撴灉锛夛紝submit 鏃剁敤浜庤烦杩囨棤鍙樻洿鐨勪繚瀛樿姹�
originalSnapshot.value = JSON.stringify(await getAlignedData());
+ schedulePreview();
} finally {
modalApi.unlock();
}
@@ -353,7 +441,86 @@
<template>
<Modal :title="getTitle" class="w-3/5">
+ <Alert
+ v-if="formData?.standardWarnFlag && formData?.standardWarnMessage"
+ class="mx-4 mb-3"
+ :description="formData.standardWarnMessage"
+ message="宸ユ椂瓒呭嚭鑰冩牳闃堝��"
+ show-icon
+ type="warning"
+ />
<Form class="mx-4" />
+ <div
+ v-if="isEditable && wagePreview"
+ class="mx-4 mt-4 rounded border border-gray-200 p-4"
+ >
+ <div class="mb-2 flex items-center justify-between">
+ <div class="font-medium">
+ 宸ヨ祫璇曠畻
+ <span class="ml-2 text-xs font-normal text-gray-400">
+ 鍚緟鍔╁伐璧勪笌璐ㄩ噺璋冩暣锛屼繚瀛�/瀹℃壒鏃朵互绯荤粺閲嶇畻缁撴灉涓哄噯
+ </span>
+ </div>
+ <Button size="small" @click="refreshWagePreview">鍒锋柊璇曠畻</Button>
+ </div>
+ <div class="flex flex-wrap gap-x-6 gap-y-1 text-sm">
+ <span>
+ 璁¤柂鏂瑰紡锛�<b>{{ wagePreview.billingType === 1 ? '璁℃椂' : '璁′欢' }}</b>
+ </span>
+ <span>
+ 鍗曚环锛�<b>{{ wagePreview.wageRate ?? 0 }}</b>
+ {{ wagePreview.billingType === 1 ? '鍏�/灏忔椂' : '鍏�/浠�' }}
+ </span>
+ <span v-if="wagePreview.billingType === 1">
+ 宸ユ椂锛�<b>{{ wagePreview.workHours ?? 0 }}</b> 灏忔椂
+ </span>
+ <span v-else>
+ 璁′欢鏁伴噺锛�<b>{{ wagePreview.pieceQuantity ?? 0 }}</b>
+ </span>
+ <span>涓诲伐璧勶細<b>{{ wagePreview.mainWage ?? 0 }}</b> 鍏�</span>
+ <span>
+ 杈呭姪宸ヨ祫锛�<b>{{ wagePreview.auxWage ?? 0 }}</b> 鍏�
+ <span class="text-xs text-gray-400">
+ 锛坽{ wagePreview.auxPaidHours ?? 0 }} 灏忔椂锛�
+ </span>
+ </span>
+ <span v-if="wagePreview.quality?.passRate !== undefined">
+ 鍚堟牸鐜囷細<b>{{ wagePreview.quality?.passRate }}</b>%
+ </span>
+ <span>
+ 鏈�缁堝伐璧勶細<b class="text-blue-600">{{ wagePreview.finalWage ?? 0 }}</b> 鍏�
+ </span>
+ </div>
+ <div
+ v-if="wagePreview.fields?.length"
+ class="mt-2 text-xs text-gray-500"
+ >
+ 宸ヨ祫瀛楁锛�
+ <span v-for="(field, index) in wagePreview.fields" :key="field.code">
+ {{ index > 0 ? '锛�' : '' }}{{ field.name }}={{ field.value ?? '-' }}
+ <template v-if="field.amount !== undefined">
+ 锛坽{ field.amount }} 鍏冿級
+ </template>
+ </span>
+ </div>
+ <Alert
+ v-if="wagePreview.warnings?.length"
+ class="mt-2"
+ :message="wagePreview.warnings.join('锛�')"
+ show-icon
+ type="warning"
+ />
+ </div>
+ <WorktimeAuxInput
+ v-if="isEditable && (currentTask?.id || formData?.taskId)"
+ ref="auxRef"
+ :initial-aux-list="formData?.auxList"
+ :process-id="currentTask?.processId ?? formData?.processId"
+ :production-length="productionLength ?? formData?.productionLength"
+ :task-id="currentTask?.id ?? formData?.taskId"
+ :work-hours="workHours ?? formData?.workHours"
+ :workstation-id="currentTask?.workstationId ?? formData?.workstationId"
+ />
<div v-if="paramDetails.length" class="mx-4 mt-4 rounded border border-gray-200 p-4">
<div class="mb-3 font-medium">宸ヨ壓鍙傛暟</div>
<div class="grid grid-cols-2 gap-3">
--
Gitblit v1.9.3