From 6c0b0dd81a98a3163e45f1b5b5417e02af165fd8 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期六, 29 八月 2026 10:04:13 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_pro2.0' into dev_pro2.0
---
src/views/mes/workbench/components/tabs/FeedbackTab.vue | 264 +++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 238 insertions(+), 26 deletions(-)
diff --git a/src/views/mes/workbench/components/tabs/FeedbackTab.vue b/src/views/mes/workbench/components/tabs/FeedbackTab.vue
index 22e58f9..86b6e25 100644
--- a/src/views/mes/workbench/components/tabs/FeedbackTab.vue
+++ b/src/views/mes/workbench/components/tabs/FeedbackTab.vue
@@ -1,8 +1,10 @@
<script lang="ts" setup>
-import type { PendingTask } from '../../../types';
+import type { PendingTask } from '../../types';
import type { FormType } from '../../../pro/feedback/data';
import { computed, ref, watch } from 'vue';
+
+import dayjs from 'dayjs';
import {
MesAutoCodeRuleCode,
@@ -10,14 +12,15 @@
} from '@vben/constants';
import { useUserStore } from '@vben/stores';
-import { Button, message, Popconfirm } from 'ant-design-vue';
+import { Button, Input, message, Modal, Popconfirm } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
import { generateAutoCode } from '#/api/mes/md/autocode/record';
import {
approveFeedback,
- createFeedback,
+ createFeedback, getBatchRequirements,
getFeedback,
+ getFeedbackPage,
rejectFeedback,
submitFeedback,
updateFeedback,
@@ -26,7 +29,14 @@
import { $t } from '#/locales';
import { useFormSchema } from '../../../pro/feedback/data';
-
+import {
+ loadParamDetails,
+ paramDetails,
+} from '../../../pro/feedback/param-state';
+import BatchInputDialog from '../../../pro/feedback/modules/batch-input-dialog.vue';
+const batchDialogRef = ref<InstanceType<typeof BatchInputDialog>>();
+const batchActionType = ref<'' | 'submit' | 'approve'>('');
+const pendingSubmitMode = ref<'saveAndSubmit' | 'submit'>('submit');
defineOptions({ name: 'WorkbenchFeedbackTab' });
const props = defineProps<{
@@ -67,26 +77,29 @@
wrapperClass: 'grid-cols-3',
});
-/** 鏍规嵁 checkFlag 瀵归綈鏁伴噺 */
+/** 鎻愪氦鍓嶅榻愭暟閲忥細鎶ュ伐鍙~鍐欐姤宸ユ暟閲忥紝鍚堟牸/涓嶈壇/搴熷搧鏁伴噺鐢辫川妫�纭畾锛屾姤宸ョ幆鑺備笉閲囬泦 */
function alignQuantity(data: any) {
- if (data.checkFlag) {
- data.uncheckQuantity = data.feedbackQuantity;
- data.qualifiedQuantity = 0;
- data.unqualifiedQuantity = 0;
- data.laborScrapQuantity = 0;
- data.materialScrapQuantity = 0;
- data.otherScrapQuantity = 0;
- } else {
- data.feedbackQuantity =
- (data.qualifiedQuantity || 0) + (data.unqualifiedQuantity || 0);
- data.uncheckQuantity = 0;
- }
+ data.uncheckQuantity = data.checkFlag ? data.feedbackQuantity : 0;
+ delete data.qualifiedQuantity;
+ delete data.unqualifiedQuantity;
+ delete data.laborScrapQuantity;
+ delete data.materialScrapQuantity;
+ delete data.otherScrapQuantity;
}
async function getAlignedData() {
const data = (await formApi.getValues()) as any;
+ syncParamValues(data);
alignQuantity(data);
return data;
+}
+
+/** 鍚屾宸ヨ壓鍙傛暟鍊煎埌鎶ュ伐鏁版嵁锛堜笌鎻愪氦鏁版嵁涓�鍚屽彂閫佺粰鍚庣锛� */
+function syncParamValues(data: any) {
+ data.paramValues = paramDetails.value.map((detail) => ({
+ detailId: detail.id,
+ value: detail.paramValue,
+ }));
}
/** 鍔犺浇 checkFlag */
@@ -111,11 +124,13 @@
const code = await generateAutoCode(MesAutoCodeRuleCode.PRO_FEEDBACK_CODE);
const checkFlag = await resolveCheckFlag(task.routeId, task.processId);
+ // 鍔犺浇浠诲姟缁戝畾鐨勫伐鑹哄弬鏁帮紙蹇呭~鍙傛暟鏍¢獙 + 鍙傛暟鍊煎洖鏄撅級
+ await loadParamDetails(task.id);
await formApi.setValues({
code,
type: 1,
- feedbackTime: Date.now(),
+ feedbackTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
feedbackUserId: userStore.userInfo?.id,
taskId: task.id,
workOrderId: task.workOrderId,
@@ -127,10 +142,11 @@
itemName: task.itemName,
itemSpecification: task.itemSpecification,
unitMeasureName: task.unitMeasureName,
+ reportableQuantity: task.reportableQuantity,
scheduledQuantity: task.quantity,
+ feedbackApprove: task.feedbackApprove,
checkFlag,
});
-
originalSnapshot.value = JSON.stringify(await getAlignedData());
}
@@ -140,6 +156,7 @@
if (!valid) return;
const data = await getAlignedData();
+ const code = data.code as string;
if (formType.value === 'create') {
const id = await createFeedback(data);
@@ -148,12 +165,78 @@
formType.value = 'update';
formApi.setState({ schema: useFormSchema(formType.value, formApi) });
await formApi.setFieldValue('id', id);
- message.success($t('common.createSuccess'));
} else {
await updateFeedback(data);
- message.success($t('common.updateSuccess'));
}
originalSnapshot.value = JSON.stringify(data);
+
+ // 鏄剧ず鏄剧溂鐨勬垚鍔熸彁绀�
+ Modal.success({
+ title: '淇濆瓨鎴愬姛',
+ content: `鎶ュ伐鍗� ${code} 宸蹭繚瀛榒,
+ centered: true,
+ });
+
+ // 閲嶇疆琛ㄥ崟涓烘柊寤烘ā寮忥紝閲嶆柊鐢熸垚鎶ヨ鍗曞彿
+ if (props.task) {
+ await resetForTask(props.task);
+ }
+
+ emit('reported');
+}
+
+/** 淇濆瓨骞舵彁浜わ紙鍏堜繚瀛橈紝鍐嶆煡璇㈠苟鎻愪氦锛� */
+async function handleSaveAndSubmit() {
+ const { valid } = await formApi.validate();
+ if (!valid) return;
+
+ const data = await getAlignedData();
+ const code = data.code as string;
+
+ // 1. 鍏堜繚瀛�
+ if (formType.value === 'create') {
+ const id = await createFeedback(data);
+ feedbackId.value = id;
+ feedbackStatus.value = MesProFeedbackStatusEnum.PREPARE;
+ formType.value = 'update';
+ formApi.setState({ schema: useFormSchema(formType.value, formApi) });
+ await formApi.setFieldValue('id', id);
+ } else {
+ await updateFeedback(data);
+ }
+ originalSnapshot.value = JSON.stringify(data);
+
+ // 2. 鏌ヨ鎶ュ伐璁板綍锛屽尮閰嶈鎶ュ伐鍗曞彿
+ const pageResult = await getFeedbackPage({ code, pageNo: 1, pageSize: 1 });
+ const record = pageResult.list?.[0];
+
+ // 3. 妫�鏌ユ槸鍚﹀彲鎻愪氦锛堣崏绋跨姸鎬侊級
+ if (!record || record.status !== MesProFeedbackStatusEnum.PREPARE) {
+ message.warning('淇濆瓨鎴愬姛锛屼絾褰撳墠鎶ュ伐鍗曠姸鎬佷笉鍙彁浜�');
+ emit('reported');
+ return;
+ }
+
+ pendingSubmitMode.value = 'saveAndSubmit';
+
+ // 4. 璋冪敤鎻愪氦鎺ュ彛
+ const isDone = await handleOnSubmit(feedbackId.value!,props.task?.feedbackApprove);
+ if (!isDone) return;
+
+ feedbackId.value = record.id;
+ feedbackStatus.value = record.status;
+
+ // 鏄剧ず鏄剧溂鐨勬垚鍔熸彁绀�
+ Modal.success({
+ title: '淇濆瓨骞舵彁浜ゆ垚鍔�',
+ content: `鎶ュ伐鍗� ${code} 宸叉彁浜,
+ centered: true,
+ });
+
+ // 閲嶇疆琛ㄥ崟涓烘柊寤烘ā寮忥紝閲嶆柊鐢熸垚鎶ヨ鍗曞彿
+ if (props.task) {
+ await resetForTask(props.task);
+ }
emit('reported');
}
@@ -167,8 +250,12 @@
await updateFeedback(data);
originalSnapshot.value = JSON.stringify(data);
}
- await submitFeedback(feedbackId.value!);
- message.success('鎶ヨ鍗曞凡鎻愪氦');
+
+ pendingSubmitMode.value = 'submit';
+ const isDone = await handleOnSubmit(feedbackId.value!,props.task?.feedbackApprove);
+ if (!isDone) return;
+
+ message.success('鎶ュ伐鍗曞凡鎻愪氦');
// 閲嶇疆琛ㄥ崟涓烘柊寤烘ā寮�
if (props.task) {
await resetForTask(props.task);
@@ -176,10 +263,53 @@
emit('reported');
}
+
+/** 鎻愪氦鏂规硶 */
+async function handleOnSubmit(id:any,feedbackRate:any): Promise<boolean> {
+ if (feedbackRate&&feedbackRate==true){
+ await submitFeedback({ id: feedbackId.value! });
+ return true;
+ }
+
+ const checkResult = await getBatchRequirements(id);
+ if (checkResult?.needBatchInput) {
+ batchActionType.value = 'submit';
+ batchDialogRef.value?.open({ checkResult });
+ return false;
+ } else {
+ await submitFeedback({ id: feedbackId.value! });
+ return true;
+ }
+}
+
+/** 鎵规纭鍥炶皟 */
+async function handleBatchConfirm(batchData: Record<string, unknown>) {
+ if (batchActionType.value === 'submit') {
+ await submitFeedback({ id: feedbackId.value!, ...batchData });
+
+ if (pendingSubmitMode.value === 'saveAndSubmit') {
+ const data = await getAlignedData();
+ const code = data.code as string;
+ Modal.success({
+ title: '淇濆瓨骞舵彁浜ゆ垚鍔�',
+ content: `鎶ュ伐鍗� ${code} 宸叉彁浜,
+ centered: true,
+ });
+ } else {
+ message.success('鎶ュ伐鍗曞凡鎻愪氦');
+ }
+
+ if (props.task) {
+ await resetForTask(props.task);
+ }
+ emit('reported');
+ }
+}
+
/** 瀹℃壒閫氳繃 */
async function handleApprove() {
if (!feedbackId.value) return;
- const finished = await approveFeedback(feedbackId.value);
+ const finished = await approveFeedback({ id: feedbackId.value });
message.success(
finished ? '鎶ヨ鍗曞凡瀹℃壒瀹屾垚' : '鎶ュ伐鎴愬姛锛岃绛夊緟璐ㄩ噺妫�楠屽畬鎴愶紒',
);
@@ -208,13 +338,15 @@
formType.value = 'update';
formApi.setState({ schema: useFormSchema(formType.value, formApi) });
const checkFlag = await resolveCheckFlag(data.routeId, data.processId);
+ await loadParamDetails(data.taskId);
await formApi.setValues({ ...data, checkFlag });
originalSnapshot.value = JSON.stringify(await getAlignedData());
}
-// 鐩戝惉浠诲姟鍙樻洿锛堜粎褰撲换鍔� ID 鐪熸鍙樺寲鏃舵墠閲嶇疆琛ㄥ崟锛�
+// 鐩戝惉浠诲姟鍙樻洿锛氫换鍔″璞″彉鍖栵紙閫夋嫨浠诲姟 / 鍒楄〃鍒锋柊鍚庡悓姝ョ殑鏈�鏂版暟鎹級鏃堕噸缃〃鍗曪紝
+// 纭繚"鍙姤宸ユ暟閲�"绛変换鍔℃淳鐢熷瓧娈靛缁堝睍绀烘渶鏂板��
watch(
- () => props.task?.id,
+ () => props.task,
() => {
if (props.task) {
resetForTask(props.task);
@@ -229,6 +361,7 @@
<template>
<div class="feedback-tab">
+ <BatchInputDialog ref="batchDialogRef" @confirm="handleBatchConfirm" />
<div v-if="!task" class="feedback-tab__empty">
璇蜂粠宸︿晶宸ュ崟鍒楄〃閫夋嫨涓�鏉′换鍔�
</div>
@@ -244,6 +377,34 @@
<Form class="feedback-tab__form" />
+ <!-- 宸ヨ壓鍙傛暟锛堜换鍔$粦瀹氬弬鏁版椂灞曠ず锛屽繀濉弬鏁版湭濉細琚悗绔嫤鎴級 -->
+ <div v-if="paramDetails.length" class="feedback-tab__params">
+ <div class="feedback-tab__params-title">宸ヨ壓鍙傛暟</div>
+ <div class="feedback-tab__params-grid">
+ <div
+ v-for="detail in paramDetails"
+ :key="detail.id"
+ class="feedback-tab__params-item"
+ >
+ <span class="feedback-tab__params-label">
+ <span v-if="detail.required" class="feedback-tab__params-required"
+ >* </span
+ >
+ {{ detail.paramName || detail.paramCode
+ }}{{
+ detail.unitMeasureName ? `锛�${detail.unitMeasureName}锛塦 : ''
+ }}
+ </span>
+ <Input
+ v-model:value="detail.paramValue"
+ :disabled="!isEditable"
+ placeholder="璇疯緭鍏ュ弬鏁板��"
+ class="feedback-tab__params-input"
+ />
+ </div>
+ </div>
+ </div>
+
<div class="feedback-tab__actions">
<Button
v-if="isEditable"
@@ -251,6 +412,13 @@
@click="handleSave"
>
淇濆瓨
+ </Button>
+ <Button
+ v-if="isEditable"
+ type="primary"
+ @click="handleSaveAndSubmit"
+ >
+ 淇濆瓨骞舵彁浜�
</Button>
<Popconfirm
v-if="canSubmit"
@@ -328,4 +496,48 @@
border-top: 1px solid #f0f0f0;
margin-top: 16px;
}
+
+.feedback-tab__params {
+ margin-top: 16px;
+ padding: 14px 16px;
+ border: 1px solid #f0f0f0;
+ border-radius: 8px;
+ background: #fafbfc;
+}
+
+.feedback-tab__params-title {
+ margin-bottom: 12px;
+ font-size: 15px;
+ font-weight: 600;
+ color: #1a1a1a;
+}
+
+.feedback-tab__params-grid {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: 12px 20px;
+}
+
+.feedback-tab__params-item {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.feedback-tab__params-label {
+ flex-shrink: 0;
+ width: 176px;
+ text-align: right;
+ font-size: 14px;
+ color: #595959;
+}
+
+.feedback-tab__params-required {
+ color: #ff4d4f;
+}
+
+.feedback-tab__params-input {
+ flex: 1;
+ min-width: 0;
+}
</style>
--
Gitblit v1.9.3