| | |
| | | <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'; |
| | |
| | | } from '@vben/constants'; |
| | | import { useUserStore } from '@vben/stores'; |
| | | |
| | | import { Button, message, Modal, 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 { $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 batchActionType = ref<'' | 'submit' | 'approve'>(''); |
| | | const pendingSubmitMode = ref<'saveAndSubmit' | 'submit'>('submit'); |
| | | defineOptions({ name: 'WorkbenchFeedbackTab' }); |
| | | |
| | |
| | | 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 */ |
| | |
| | | |
| | | const code = await generateAutoCode(MesAutoCodeRuleCode.PRO_FEEDBACK_CODE); |
| | | const checkFlag = await resolveCheckFlag(task.routeId, task.processId); |
| | | // 加载任务绑定的工艺参数(必填参数校验 + 参数值回显) |
| | | await loadParamDetails(task.id); |
| | | |
| | | await formApi.setValues({ |
| | | code, |
| | |
| | | itemName: task.itemName, |
| | | itemSpecification: task.itemSpecification, |
| | | unitMeasureName: task.unitMeasureName, |
| | | reportableQuantity: task.reportableQuantity, |
| | | scheduledQuantity: task.quantity, |
| | | feedbackApprove: task.feedbackApprove, |
| | | checkFlag, |
| | |
| | | pendingSubmitMode.value = 'saveAndSubmit'; |
| | | |
| | | // 4. 调用提交接口 |
| | | const isDone = await handleOnSubmit(feedbackId.value!,props.task.feedbackApprove); |
| | | const isDone = await handleOnSubmit(feedbackId.value!,props.task?.feedbackApprove); |
| | | if (!isDone) return; |
| | | |
| | | feedbackId.value = record.id; |
| | |
| | | } |
| | | |
| | | pendingSubmitMode.value = 'submit'; |
| | | const isDone = await handleOnSubmit(feedbackId.value!,props.task.feedbackApprove); |
| | | const isDone = await handleOnSubmit(feedbackId.value!,props.task?.feedbackApprove); |
| | | if (!isDone) return; |
| | | |
| | | message.success('报工单已提交'); |
| | |
| | | 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); |
| | |
| | | </div> |
| | | |
| | | <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 |
| | |
| | | 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> |