云
2026-10-26 bae93b624d8d68ed2fe540c381a58b47082c1309
src/views/mes/pro/route/data.ts
@@ -19,12 +19,15 @@
import { z } from '#/adapter/form';
import { generateAutoCode } from '#/api/mes/md/autocode/record';
import { getTemplatePage } from '#/api/mes/pro/processdesign/template';
import { getWarehouseSimpleList } from '#/api/mes/wm/warehouse';
import { getWarehouseAreaSimpleList } from '#/api/mes/wm/warehouse/area';
import { getWarehouseLocationSimpleList } from '#/api/mes/wm/warehouse/location';
import {
  MdItemSelect,
  MdProductBomSelect,
} from '#/views/mes/md/item/components';
import { RouteColorPicker } from './components';
import { RouteColorPicker, RouteOutputAttribution } from './components';
/** 表单类型 */
export type FormType = 'create' | 'detail' | 'update';
@@ -167,7 +170,7 @@
      field: 'createTime',
      title: '创建时间',
      width: 180,
      formatter: 'formatDate',
      formatter: 'formatDateTime',
    },
    {
      title: '操作',
@@ -181,6 +184,7 @@
/** 工艺路线工序明细表单 */
export function useRouteProcessFormSchema(
  processOptions: Array<{ label: string; value: number }>,
  products: MesProRouteProductApi.RouteProduct[] = [],
): VbenFormSchema[] {
  return [
    {
@@ -231,36 +235,38 @@
    },
    {
      fieldName: 'yieldRate',
      label: '收率',
      label: '工序收率',
      component: 'InputNumber',
      help: '产出量 ÷ 投入量;未填写按 100% 参与排产计算。',
      componentProps: {
        class: '!w-full',
        min: 0.0001,
        max: 1,
        step: 0.01,
        precision: 4,
        placeholder: '产出/投入,如 0.98',
        placeholder: '如 0.98(98%)',
      },
      rules: z.number().min(0.0001).max(1).nullish(),
    },
    {
      fieldName: 'outputs',
      label: '本工序产出',
      component: markRaw(RouteOutputAttribution),
      componentProps: {
        products,
      },
      formItemClass: 'col-span-2',
    },
    {
      fieldName: 'linkType',
      label: '与下道工序关系',
      component: 'Select',
      help: () =>
        h(
          'div',
          {
            style:
              'white-space: pre-line; max-width: 320px; line-height: 1.6;',
          },
          '0=开始-开始(SS):本工序开始后,下道工序才能开始(可重叠并行开工)\n1=结束-结束(FF):下道工序必须等到本工序结束才能结束(并行但同步完工)\n2=开始-结束(SF):本工序开始后,下道工序才能结束\n3=结束-开始(FS):本工序结束后,下道工序才能开始(默认值)',
        ),
      componentProps: {
        allowClear: true,
        options: getDictOptions(DICT_TYPE.MES_PRO_LINK_TYPE, 'number'),
        placeholder: '请选择',
      },
      rules: z.number().optional(),
      rules: z.number().default(3),
    },
    {
      fieldName: 'colorCode',
@@ -284,6 +290,16 @@
      componentProps: {
        checkedChildren: '是',
        unCheckedChildren: '否',
      },
      rules: z.boolean().default(false),
    },
    {
      fieldName: 'backflushFlag',
      label: '报工自动扣料',
      component: 'Switch',
      componentProps: {
        checkedChildren: '自动',
        unCheckedChildren: '手动',
      },
      rules: z.boolean().default(false),
    },
@@ -329,6 +345,25 @@
    { field: 'sort', title: '序号', width: 70, align: 'center', fixed: 'left' },
    { field: 'processCode', title: '工序编码', width: 140, fixed: 'left' },
    { field: 'processName', title: '工序名称', width: 140, fixed: 'left' },
    {
      field: 'outputItemNames',
      title: '本工序产出',
      minWidth: 240,
      formatter: ({ cellValue, row }) => {
        const outputs = row.outputs ?? [];
        if (!outputs.length) {
          return cellValue ?? '';
        }
        return outputs
          .map((output) => {
            const name = output.itemName ?? output.itemCode ?? output.itemId;
            return output.productId == null
              ? `${name}(通用)`
              : `${name}(${output.productName ?? output.productId})`;
          })
          .join('、');
      },
    },
    { field: 'nextProcessName', title: '下一道工序', width: 140 },
    {
      field: 'linkType',
@@ -357,6 +392,15 @@
        props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING },
      },
    },
    {
      field: 'backflushFlag',
      title: '自动扣料',
      width: 100,
      cellRender: {
        name: 'CellDict',
        props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING },
      },
    },
    { field: 'prepareTime', title: '准备时间(分)', width: 110 },
    { field: 'waitTime', title: '等待时间(分)', width: 110 },
    {
@@ -378,11 +422,14 @@
/** 工艺路线产品列表字段 */
export function useRouteProductGridColumns(): VxeTableGridOptions<MesProRouteProductApi.RouteProduct>['columns'] {
  return [
    { field: 'itemCode', title: '产品物料编码', width: 150 },
    { field: 'itemName', title: '产品物料名称', width: 150 },
    { field: 'itemCode', title: '产出编码', width: 150 },
    { field: 'itemName', title: '产出名称', width: 150 },
    { field: 'specification', title: '规格型号', width: 150 },
    { field: 'unitName', title: '单位', width: 80 },
    { field: 'quantity', title: '生产数量', width: 100 },
    { field: 'warehouseName', title: '报工入库仓', width: 140 },
    { field: 'locationName', title: '入库库区', width: 120 },
    { field: 'areaName', title: '入库库位', width: 120 },
    {
      field: 'productionTime',
      title: '生产用时',
@@ -402,8 +449,8 @@
/** 工艺路线产品 BOM 列表字段 */
export function useRouteProductBomGridColumns(): VxeTableGridOptions<MesProRouteProductBomApi.RouteProductBom>['columns'] {
  return [
    { field: 'itemCode', title: 'BOM 物料编码', width: 150 },
    { field: 'itemName', title: 'BOM 物料名称', width: 150 },
    { field: 'itemCode', title: '投料编码', width: 150 },
    { field: 'itemName', title: '投料名称', width: 150 },
    { field: 'specification', title: '规格型号', width: 150 },
    { field: 'unitName', title: '单位', width: 80 },
    { field: 'quantity', title: '用料比例', width: 100 },
@@ -420,6 +467,7 @@
/** 工艺路线产品表单 */
export function useRouteProductFormSchema(
  onItemChange?: (item: any) => void,
  getFormApi?: () => VbenFormApi,
): VbenFormSchema[] {
  return [
    {
@@ -435,11 +483,12 @@
    // 产品物料:使用业务自定义选择器,change 回填编码/名称/规格/单位
    {
      fieldName: 'itemId',
      label: '产品',
      label: '产出物料',
      component: markRaw(MdItemSelect),
      componentProps: {
        onChange: onItemChange,
      },
      help: '可选择主数据类型为成品或半成品的物料,也兼容 MES 成品/半成品分类;已有路线产品可继续修改仓位。',
      formItemClass: 'col-span-2',
      rules: 'selectRequired',
    },
@@ -455,6 +504,63 @@
      rules: z.number().default(1),
    },
    {
      fieldName: 'warehouseId',
      label: '报工仓库',
      component: 'ApiSelect',
      componentProps: {
        api: getWarehouseSimpleList,
        labelField: 'name',
        valueField: 'id',
        placeholder: '请选择报工产出仓库',
        onChange: async () => {
          await getFormApi?.().setFieldValue('locationId', undefined);
          await getFormApi?.().setFieldValue('areaId', undefined);
        },
      },
      rules: 'selectRequired',
    },
    {
      fieldName: 'locationId',
      label: '报工库区',
      component: 'Select',
      dependencies: {
        triggerFields: ['warehouseId'],
        disabled: (values) => !values.warehouseId,
        async componentProps(values) {
          const options = values.warehouseId
            ? await getWarehouseLocationSimpleList(values.warehouseId)
            : [];
          return {
            fieldNames: { label: 'name', value: 'id' },
            options,
            placeholder: '请选择报工产出库区',
            onChange: async () => getFormApi?.().setFieldValue('areaId', undefined),
          };
        },
      },
      rules: 'selectRequired',
    },
    {
      fieldName: 'areaId',
      label: '报工库位',
      component: 'Select',
      dependencies: {
        triggerFields: ['locationId'],
        disabled: (values) => !values.locationId,
        async componentProps(values) {
          const options = values.locationId
            ? await getWarehouseAreaSimpleList(values.locationId)
            : [];
          return {
            fieldNames: { label: 'name', value: 'id' },
            options,
            placeholder: '请选择报工产出库位',
          };
        },
      },
      rules: 'selectRequired',
    },
    {
      fieldName: 'productionTime',
      label: '生产用时',
      component: 'InputNumber',