src/views/mes/pro/feedback/data.ts
@@ -2,6 +2,7 @@
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { MesProFeedbackApi } from '#/api/mes/pro/feedback';
import type { MesProTaskApi } from '#/api/mes/pro/task';
import type { DescriptionItemSchema } from '#/components/description';
import { h, markRaw } from 'vue';
@@ -10,19 +11,21 @@
  MesAutoCodeRuleCode,
  MesProTaskStatusEnum,
  MesProWorkOrderStatusEnum,
} from '../../../../packages/constants/src';
import { getDictOptions } from '../../../../packages/effects/hooks/src';
} from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { Button } from 'ant-design-vue';
import { generateAutoCode } from '#/api/mes/md/autocode/record';
import { getRouteProcessByRouteAndProcess } from '#/api/mes/pro/route/process';
import { getSimpleUserList } from '#/api/system/user';
import { loadParamDetails } from './param-state';
import { getRangePickerDefaultProps } from '#/utils';
import { MdItemSelect } from '#/views/mes/md/item/components';
import { MdWorkstationSelect } from '#/views/mes/md/workstation/components';
import { ProTaskSelect } from '#/views/mes/pro/task/components';
import { ProWorkOrderSelect } from '#/views/mes/pro/workorder/components';
import { DictTag } from '#/components/dict-tag';
/** 生产报工表单类型 */
export type FormType = 'approve' | 'create' | 'detail' | 'submit' | 'update';
@@ -32,11 +35,11 @@
  return [
    {
      fieldName: 'code',
      label: '报工单号',
      label: '报订单号',
      component: 'Input',
      componentProps: {
        allowClear: true,
        placeholder: '请输入报工单号',
        placeholder: '请输入报订单号',
      },
    },
    {
@@ -51,11 +54,11 @@
    },
    {
      fieldName: 'workOrderId',
      label: '生产工单',
      label: '生产订单',
      component: markRaw(ProWorkOrderSelect),
      componentProps: {
        allowClear: true,
        placeholder: '请选择工单',
        placeholder: '请选择订单',
      },
    },
    {
@@ -118,7 +121,7 @@
  return [
    {
      field: 'code',
      title: '报工单号',
      title: '报订单号',
      width: 160,
      slots: { default: 'code' },
    },
@@ -133,7 +136,7 @@
    },
    { field: 'workstationName', title: '工作站', width: 120 },
    { field: 'processName', title: '工序', width: 100 },
    { field: 'workOrderCode', title: '生产工单编码', width: 160 },
    { field: 'workOrderCode', title: '生产订单编码', width: 160 },
    { field: 'itemCode', title: '产品物料编码', width: 120 },
    { field: 'itemName', title: '产品物料名称', minWidth: 140 },
    { field: 'itemSpecification', title: '规格型号', width: 120 },
@@ -171,9 +174,8 @@
 * - create / update:录入报工主体信息和数量
 * - submit / approve / detail:主体字段只读
 *
 * 数量区域根据 `checkFlag` 和 `unqualifiedQuantity` 动态显示:
 * - 非质检工序:报工数量 = 合格 + 不良;不良 > 0 时再展开工废/料废/其他废品
 * - 质检工序:只填报工数量(视为待检数量)
 * 报工只填写"报工数量";合格品/不良品数量由质检确定,报工环节不采集。
 * 质检工序报工后进入待检验(uncheckQuantity = 报工数量),非质检工序直接完结。
 */
export function useFormSchema(
  formType: FormType,
@@ -209,11 +211,11 @@
    },
    {
      fieldName: 'code',
      label: '报工单号',
      label: '报订单号',
      component: 'Input',
      componentProps: {
        disabled: isHeaderReadonly,
        placeholder: '请输入报工单号',
        placeholder: '请输入报订单号',
      },
      rules: 'required',
      suffix: () =>
@@ -245,13 +247,13 @@
    },
    {
      fieldName: 'workOrderId',
      label: '生产工单',
      label: '生产订单',
      component: markRaw(ProWorkOrderSelect),
      componentProps: {
        disabled: isHeaderReadonly,
        placeholder: '请选择工单',
        placeholder: '请选择订单',
        status: MesProWorkOrderStatusEnum.CONFIRMED,
        // 工单变更:清空任务及任务带出的产品信息、数量区域控制位
        // 订单变更:清空任务及任务带出的产品信息、数量区域控制位
        onChange: async () => {
          await formApi?.setValues({
            checkFlag: true,
@@ -264,6 +266,7 @@
            taskId: undefined,
            unitMeasureName: undefined,
            workstationId: undefined,
            reportableQuantity: undefined,
          });
        },
      },
@@ -277,15 +280,16 @@
        triggerFields: ['workOrderId', 'workstationId'],
        componentProps: (values) => ({
          disabled: isHeaderReadonly || !values.workOrderId,
          placeholder: values.workOrderId ? '请选择任务' : '请先选择工单',
          placeholder: values.workOrderId ? '请选择任务' : '请先选择订单',
          statuses: [MesProTaskStatusEnum.PREPARE],
          workOrderId: values.workOrderId,
          workstationId: values.workstationId,
        }),
      },
      // 任务变更:自动填充关联字段、产品信息、checkFlag
      // 任务变更:自动填充关联字段、产品信息、checkFlag,并加载任务绑定的工艺参数
      componentProps: {
        onChange: async (task?: MesProTaskApi.Task) => {
          await loadParamDetails(task?.id);
          if (!task) {
            return;
          }
@@ -298,6 +302,7 @@
            routeId: task.routeId,
            unitMeasureName: task.unitMeasureName,
            workstationId: task.workstationId,
            reportableQuantity: task.reportableQuantity,
          });
          // 工艺路线工序的 checkFlag 决定数量区域展示
          if (task.routeId && task.processId) {
@@ -377,6 +382,20 @@
      },
    },
    {
      fieldName: 'reportableQuantity',
      label: '可报工数量',
      component: 'InputNumber',
      componentProps: {
        class: 'w-full',
        disabled: true,
        precision: 2,
      },
      dependencies: {
        triggerFields: ['taskId'],
        show: (values) => !!values.taskId && ['create', 'update'].includes(formType),
      },
    },
    {
      fieldName: 'feedbackQuantity',
      label: '报工数量',
      component: 'InputNumber',
@@ -384,151 +403,9 @@
        class: 'w-full',
        min: 0,
        precision: 2,
      },
      dependencies: {
        triggerFields: ['checkFlag'],
        // 非质检工序时,报工数量 = 合格 + 不良,禁用直接编辑
        componentProps: (values) => ({
          class: 'w-full',
          disabled: !values.checkFlag,
          min: 0,
          placeholder: '请输入报工数量',
          precision: 2,
        }),
        placeholder: '请输入报工数量',
      },
      rules: 'required',
    },
    {
      fieldName: 'qualifiedQuantity',
      label: '合格品数量',
      component: 'InputNumber',
      componentProps: {
        class: 'w-full',
        min: 0,
        precision: 2,
        // 合格/不良变更,自动累计为报工数量
        onChange: async () => {
          const values = await formApi?.getValues();
          await formApi?.setFieldValue(
            'feedbackQuantity',
            (values?.qualifiedQuantity || 0) +
              (values?.unqualifiedQuantity || 0),
          );
        },
      },
      defaultValue: 0,
      dependencies: {
        triggerFields: ['checkFlag'],
        show: (values) => !values.checkFlag,
      },
    },
    {
      fieldName: 'unqualifiedQuantity',
      label: '不良品数量',
      component: 'InputNumber',
      componentProps: {
        class: 'w-full',
        min: 0,
        precision: 2,
        // 合格/不良变更,自动累计为报工数量
        onChange: async () => {
          const values = await formApi?.getValues();
          await formApi?.setFieldValue(
            'feedbackQuantity',
            (values?.qualifiedQuantity || 0) +
              (values?.unqualifiedQuantity || 0),
          );
        },
      },
      defaultValue: 0,
      dependencies: {
        triggerFields: ['checkFlag'],
        show: (values) => !values.checkFlag,
      },
    },
    {
      fieldName: 'laborScrapQuantity',
      label: '工废数量',
      component: 'InputNumber',
      componentProps: {
        class: 'w-full',
        min: 0,
        precision: 2,
        // 废品分类变更,自动累计为不良品数量及报工数量
        onChange: async () => {
          const values = await formApi?.getValues();
          const unqualified =
            (values?.laborScrapQuantity || 0) +
            (values?.materialScrapQuantity || 0) +
            (values?.otherScrapQuantity || 0);
          await formApi?.setValues({
            feedbackQuantity: (values?.qualifiedQuantity || 0) + unqualified,
            unqualifiedQuantity: unqualified,
          });
        },
      },
      defaultValue: 0,
      dependencies: {
        triggerFields: ['checkFlag', 'unqualifiedQuantity'],
        show: (values) =>
          !values.checkFlag && (values.unqualifiedQuantity || 0) > 0,
      },
    },
    {
      fieldName: 'materialScrapQuantity',
      label: '料废数量',
      component: 'InputNumber',
      componentProps: {
        class: 'w-full',
        min: 0,
        precision: 2,
        // 废品分类变更,自动累计为不良品数量及报工数量
        onChange: async () => {
          const values = await formApi?.getValues();
          const unqualified =
            (values?.laborScrapQuantity || 0) +
            (values?.materialScrapQuantity || 0) +
            (values?.otherScrapQuantity || 0);
          await formApi?.setValues({
            feedbackQuantity: (values?.qualifiedQuantity || 0) + unqualified,
            unqualifiedQuantity: unqualified,
          });
        },
      },
      defaultValue: 0,
      dependencies: {
        triggerFields: ['checkFlag', 'unqualifiedQuantity'],
        show: (values) =>
          !values.checkFlag && (values.unqualifiedQuantity || 0) > 0,
      },
    },
    {
      fieldName: 'otherScrapQuantity',
      label: '其他废品',
      component: 'InputNumber',
      componentProps: {
        class: 'w-full',
        min: 0,
        precision: 2,
        // 废品分类变更,自动累计为不良品数量及报工数量
        onChange: async () => {
          const values = await formApi?.getValues();
          const unqualified =
            (values?.laborScrapQuantity || 0) +
            (values?.materialScrapQuantity || 0) +
            (values?.otherScrapQuantity || 0);
          await formApi?.setValues({
            feedbackQuantity: (values?.qualifiedQuantity || 0) + unqualified,
            unqualifiedQuantity: unqualified,
          });
        },
      },
      defaultValue: 0,
      dependencies: {
        triggerFields: ['checkFlag', 'unqualifiedQuantity'],
        show: (values) =>
          !values.checkFlag && (values.unqualifiedQuantity || 0) > 0,
      },
    },
    {
      fieldName: 'feedbackUserId',
@@ -554,7 +431,7 @@
        format: 'YYYY-MM-DD HH:mm:ss',
        placeholder: '请选择报工时间',
        showTime: true,
        valueFormat: 'x',
        valueFormat: 'YYYY-MM-DD HH:mm:ss',
      },
      rules: 'required',
    },
@@ -585,3 +462,34 @@
    },
  ];
}
/** 生产报工详情摘要 */
export function useDetailSchema(): DescriptionItemSchema[] {
  return [
    { field: 'code', label: '报订单号' },
    {
      field: 'type',
      label: '报工类型',
      render: (val) =>
        h(DictTag, { type: DICT_TYPE.MES_PRO_FEEDBACK_TYPE, value: val }),
    },
    { field: 'workOrderId', label: '生产订单', render: (_val, data) => data?.workOrderCode },
    { field: 'taskId', label: '生产任务', render: (_val, data) => data?.taskCode },
    { field: 'workstationName', label: '工作站' },
    { field: 'itemCode', label: '产品编码' },
    { field: 'itemName', label: '产品名称' },
    { field: 'unitMeasureName', label: '单位' },
    { field: 'itemSpecification', label: '规格' },
    { field: 'reportableQuantity', label: '可报工数量' },
    { field: 'feedbackQuantity', label: '报工数量' },
    { field: 'qualifiedQuantity', label: '合格品数量' },
    { field: 'unqualifiedQuantity', label: '不良品数量' },
    { field: 'laborScrapQuantity', label: '工废数量' },
    { field: 'materialScrapQuantity', label: '料废数量' },
    { field: 'otherScrapQuantity', label: '其他废品' },
    { field: 'feedbackUserNickname', label: '报工人' },
    { field: 'feedbackTime', label: '报工时间' },
    { field: 'approveUserNickname', label: '审核人' },
    { field: 'remark', label: '备注' },
  ];
}