spring
2026-07-03 2540d86f0dbd77f654f558c3bf9d5ddbe7422f16
src/views/mes/pd/project/data.ts
@@ -1,381 +1,340 @@
import type { VbenFormApi, VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { MesMdItemApi } from '#/api/mes/md/item';
import type { MesPdProjectApi } from '#/api/mes/pd/project';
import type { ExtendedFormApi, VbenFormSchema } from "#/adapter/form";
import type { VxeTableGridOptions } from "#/adapter/vxe-table";
import type { MesMdItemApi } from "#/api/mes/md/item";
import type { MesPdProjectApi } from "#/api/mes/pd/project";
import { h, markRaw } from 'vue';
import { h, markRaw } from "vue";
import {
  DICT_TYPE,
  MesAutoCodeRuleCode,
  MesPdDocumentTypeEnum,
} from '#/packages/constants/src';
import { getDictOptions } from '#/packages/effects/hooks/src';
} from "#/packages/constants/src";
import { getDictOptions } from "#/packages/effects/hooks/src";
import { Button } from 'ant-design-vue';
import { Button } from "ant-design-vue";
import { generateAutoCode } from '#/api/mes/md/autocode/record';
import { isPdMockEnabled } from '#/api/mes/pd/mock/enabled';
import { mockNextCode } from '#/api/mes/pd/mock/utils';
import { getRangePickerDefaultProps } from '#/utils';
import { MdItemSelect } from '#/views/mes/md/item/components';
import { generateAutoCode } from "#/api/mes/md/autocode/record";
export type FormType = 'create' | 'detail' | 'update';
import { MdItemSelect } from "#/views/mes/md/item/components";
import PdUserSelect from "../project/modules/user-select.vue";
async function generateTaskCode(formApi?: VbenFormApi) {
  const code = isPdMockEnabled()
    ? mockNextCode('DT-2026', Math.floor(Date.now() % 10_000))
    : await generateAutoCode(MesAutoCodeRuleCode.PD_PROJECT_CODE);
  await formApi?.setFieldValue('code', code);
export type FormType = "create" | "detail" | "update";
/** 弹窗内 DatePicker:挂载到 dialog 内,避免 focus-outside 拦截日历点击 */
function useModalDatePickerProps(options?: {
  disabled?: boolean;
  placeholder?: string;
}) {
  return {
    allowClear: true,
    class: "!w-full",
    disabled: options?.disabled,
    format: "YYYY-MM-DD",
    getPopupContainer: (node: HTMLElement) =>
      (node.closest('[data-slot="dialog-content"]') as HTMLElement) ??
      document.body,
    inputReadOnly: true,
    placeholder: options?.placeholder ?? "请选择日期",
    valueFormat: "x",
  };
}
async function generateTaskCode(formApi?: ExtendedFormApi) {
  const code = await generateAutoCode(MesAutoCodeRuleCode.PD_PROJECT_CODE);
  await formApi?.setFieldValue("taskCode", code);
}
async function syncTaskNameFromProduct(
  formApi: VbenFormApi | undefined,
  productName?: string,
  formApi: ExtendedFormApi | undefined,
  productName?: string
) {
  const version = (await formApi?.getFieldValue('version')) as
    | string
    | undefined;
  const values = await formApi?.getValues();
  const version = values?.version as string | undefined;
  const name = productName?.trim();
  if (name && version?.trim()) {
    await formApi?.setFieldValue('name', `${name} ${version.trim()} 设计`);
    await formApi?.setFieldValue("taskName", `${name} ${version.trim()} 设计`);
  }
}
/** 产品选择:选择后自动带出产品编码 */
function useProductSelectSchema(
  formApi: VbenFormApi | undefined,
  readonly: boolean,
  formApi: ExtendedFormApi | undefined,
  readonly: boolean
): VbenFormSchema[] {
  if (readonly) {
    return [
      {
        fieldName: 'productCode',
        label: '产品编码',
        component: 'Input',
        fieldName: "productCode",
        label: "产品编码",
        component: "Input",
        componentProps: { disabled: true },
      },
      {
        fieldName: 'productName',
        label: '产品名称',
        component: 'Input',
        fieldName: "productName",
        label: "产品名称",
        component: "Input",
        componentProps: { disabled: true },
      },
    ];
  }
  return [
    {
      fieldName: 'productId',
      label: '产品',
      fieldName: "productId",
      label: "产品",
      component: markRaw(MdItemSelect),
      componentProps: {
        placeholder: '请选择产品',
        placeholder: "请选择产品",
        onChange: async (item: MesMdItemApi.Item | undefined) => {
          await formApi?.setFieldValue('productCode', item?.code ?? '');
          await formApi?.setFieldValue('productName', item?.name ?? '');
          await formApi?.setFieldValue("productCode", item?.code ?? "");
          await formApi?.setFieldValue("productName", item?.name ?? "");
          await syncTaskNameFromProduct(formApi, item?.name);
        },
      },
      rules: 'selectRequired',
      rules: "selectRequired",
    },
    {
      fieldName: 'productCode',
      label: '产品编码',
      component: 'Input',
      fieldName: "productCode",
      label: "产品编码",
      component: "Input",
      componentProps: {
        disabled: true,
        placeholder: '选择产品后自动带出',
        placeholder: "选择产品后自动带出",
      },
      rules: 'required',
      rules: "required",
    },
    {
      fieldName: 'productName',
      component: 'Input',
      dependencies: { triggerFields: [''], show: () => false },
      fieldName: "productName",
      component: "Input",
      dependencies: { triggerFields: [""], show: () => false },
    },
  ];
}
/** 发起设计任务表单 */
export function useCreateTaskSchema(formApi?: VbenFormApi): VbenFormSchema[] {
/** 发起设计任务 / 创建表单 */
export function useCreateFormSchema(
  formApi?: ExtendedFormApi
): VbenFormSchema[] {
  return [
    {
      fieldName: 'id',
      component: 'Input',
      dependencies: { triggerFields: [''], show: () => false },
      fieldName: "id",
      component: "Input",
      dependencies: { triggerFields: [""], show: () => false },
    },
    {
      fieldName: 'code',
      label: '任务编码',
      component: 'Input',
      componentProps: { placeholder: '请点击生成任务编码' },
      rules: 'required',
      fieldName: "taskCode",
      label: "任务编码",
      component: "Input",
      componentProps: { placeholder: "请点击生成任务编码" },
      rules: "required",
      suffix: () =>
        h(
          Button,
          { type: 'default', onClick: () => generateTaskCode(formApi) },
          { default: () => '生成' },
          { type: "default", onClick: () => generateTaskCode(formApi) },
          { default: () => "生成" }
        ),
    },
    ...useProductSelectSchema(formApi, false),
    {
      fieldName: 'version',
      label: '设计版本',
      component: 'Input',
      componentProps: { placeholder: '如 V1.0、V2.1' },
      rules: 'required',
      fieldName: "version",
      label: "版本号",
      component: "Input",
      componentProps: { placeholder: "如 V1.0、V2.1" },
      rules: "required",
    },
    {
      fieldName: 'name',
      label: '任务名称',
      component: 'Input',
      componentProps: { placeholder: '将根据产品与版本自动生成,可修改' },
      rules: 'required',
      fieldName: "taskName",
      label: "任务名称",
      component: "Input",
      componentProps: { placeholder: "将根据产品与版本自动生成,可修改" },
      rules: "required",
      dependencies: {
        triggerFields: ['productName', 'version'],
        triggerFields: ["productName", "version"],
        trigger(values: Record<string, string>, form) {
          const productName = values.productName?.trim();
          const version = values.version?.trim();
          if (productName && version) {
            form.setFieldValue('name', `${productName} ${version} 设计`);
            form.setFieldValue("taskName", `${productName} ${version} 设计`);
          }
        },
      },
    },
    {
      fieldName: 'designerName',
      label: '主设计师',
      component: 'Input',
      componentProps: { placeholder: '请输入主设计师' },
      rules: 'required',
      fieldName: "chiefDesigner",
      label: "主设计师",
      component: markRaw(PdUserSelect),
      componentProps: { placeholder: "请选择主设计师" },
      rules: "selectRequired",
    },
    {
      fieldName: 'reviewerName',
      label: '审核人',
      component: 'Input',
      componentProps: { placeholder: '资料审核负责人' },
      rules: 'required',
      fieldName: "reviewer",
      label: "审核人",
      component: markRaw(PdUserSelect),
      componentProps: { placeholder: "请选择审核人" },
      rules: "selectRequired",
    },
    {
      fieldName: 'planDateRange',
      label: '计划周期',
      component: 'RangePicker',
      componentProps: getRangePickerDefaultProps(),
      rules: 'required',
      fieldName: "planFinishTime",
      label: "计划完成时间",
      component: "DatePicker",
      componentProps: useModalDatePickerProps({
        placeholder: "请选择计划完成时间",
      }),
    },
    {
      fieldName: 'remark',
      label: '任务说明',
      component: 'Textarea',
      fieldName: "remark",
      label: "备注",
      component: "Textarea",
      componentProps: {
        placeholder: '简述本次设计目标、变更背景等',
        placeholder: "简述本次设计目标、变更背景等",
        rows: 3,
      },
      formItemClass: 'col-span-2',
      formItemClass: "col-span-2",
    },
  ];
}
/** 发布任务确认表单 */
export function usePublishFormSchema(): VbenFormSchema[] {
  return [
    {
      fieldName: 'publishRemark',
      label: '发布说明',
      component: 'Textarea',
      componentProps: {
        placeholder: '可选,填写发布要求或注意事项',
        rows: 3,
      },
      formItemClass: 'col-span-2',
    },
  ];
}
export type WorkflowActionType = 'approve' | 'archive' | 'submit-review';
export interface WorkflowActionConfig {
  title: string;
  alertMessage: string;
  alertDescription: string;
  remarkLabel: string;
  remarkTag: string;
  remarkPlaceholder: string;
  successMessage: string;
  alertType: 'info' | 'success' | 'warning';
}
export const WORKFLOW_ACTION_CONFIG: Record<
  WorkflowActionType,
  WorkflowActionConfig
> = {
  'submit-review': {
    title: '提交资料审核',
    alertMessage: '确认提交审核',
    alertDescription:
      '提交后将进入资料审核环节,请确认设计资料已上传完整。提交后设计师将无法继续修改资料。',
    remarkLabel: '提交说明',
    remarkTag: '【提交说明】',
    remarkPlaceholder: '可选,填写提交审核的补充说明',
    successMessage: '已提交资料审核',
    alertType: 'info',
  },
  approve: {
    title: '审核通过',
    alertMessage: '确认审核通过',
    alertDescription:
      '审核通过后任务进入「已通过」状态,可进行归档操作。请确认设计资料符合要求。',
    remarkLabel: '审核意见',
    remarkTag: '【审核意见】',
    remarkPlaceholder: '可选,填写审核通过意见',
    successMessage: '资料审核通过',
    alertType: 'success',
  },
  archive: {
    title: '归档设计任务',
    alertMessage: '确认归档',
    alertDescription:
      '归档后将生成本版本归档台账记录,任务状态变为已归档,设计资料将锁定不可修改。',
    remarkLabel: '归档说明',
    remarkTag: '【归档说明】',
    remarkPlaceholder: '可选,填写归档备注',
    successMessage: '任务已归档',
    alertType: 'warning',
  },
};
/** 流程操作确认表单 */
export function useWorkflowActionFormSchema(
  action: WorkflowActionType,
): VbenFormSchema[] {
  const config = WORKFLOW_ACTION_CONFIG[action];
  return [
    {
      fieldName: 'actionRemark',
      label: config.remarkLabel,
      component: 'Textarea',
      componentProps: {
        placeholder: config.remarkPlaceholder,
        rows: 3,
      },
      formItemClass: 'col-span-2',
    },
  ];
}
/** 网格搜索表单 */
export function useGridFormSchema(): VbenFormSchema[] {
  return [
    {
      fieldName: 'code',
      label: '任务编码',
      component: 'Input',
      componentProps: { placeholder: '请输入任务编码' },
      fieldName: "taskCode",
      label: "任务编码",
      component: "Input",
      componentProps: { placeholder: "请输入任务编码" },
    },
    {
      fieldName: 'name',
      label: '任务名称',
      component: 'Input',
      componentProps: { placeholder: '请输入任务名称' },
      fieldName: "taskName",
      label: "任务名称",
      component: "Input",
      componentProps: { placeholder: "请输入任务名称" },
    },
    {
      fieldName: 'productCode',
      label: '产品编码',
      component: 'Input',
      componentProps: { placeholder: '请输入产品编码' },
      fieldName: "productCode",
      label: "产品编码",
      component: "Input",
      componentProps: { placeholder: "请输入产品编码" },
    },
    {
      fieldName: 'status',
      label: '任务状态',
      component: 'Select',
      fieldName: "productName",
      label: "产品名称",
      component: "Input",
      componentProps: { placeholder: "请输入产品名称" },
    },
    {
      fieldName: "status",
      label: "任务状态",
      component: "Select",
      componentProps: {
        allowClear: true,
        options: getDictOptions(DICT_TYPE.MES_PD_PROJECT_STATUS, 'number'),
        placeholder: '请选择项目状态',
        options: getDictOptions(DICT_TYPE.MES_PD_PROJECT_STATUS, "number"),
        placeholder: "请选择项目状态",
      },
    },
  ];
}
export function useGridColumns(): VxeTableGridOptions['columns'] {
/** 网格列定义 */
export function useGridColumns(): VxeTableGridOptions["columns"] {
  return [
    { field: 'code', title: '任务编码', minWidth: 140, slots: { default: 'code' } },
    { field: 'name', title: '任务名称', minWidth: 160 },
    { field: 'productCode', title: '产品编码', minWidth: 120 },
    { field: 'productName', title: '产品名称', minWidth: 140 },
    { field: 'version', title: '版本号', minWidth: 90 },
    {
      field: 'status',
      title: '状态',
      field: "taskCode",
      title: "任务编码",
      minWidth: 140,
      slots: { default: "taskCode" },
    },
    { field: "taskName", title: "任务名称", minWidth: 160 },
    { field: "productCode", title: "产品编码", minWidth: 120 },
    { field: "productName", title: "产品名称", minWidth: 140 },
    { field: "version", title: "版本号", minWidth: 90 },
    {
      field: "status",
      title: "状态",
      minWidth: 100,
      cellRender: {
        name: 'CellDict',
        name: "CellDict",
        props: { type: DICT_TYPE.MES_PD_PROJECT_STATUS },
      },
    },
    { field: 'designerName', title: '主设计师', minWidth: 100 },
    { field: 'reviewerName', title: '审核人', minWidth: 100 },
    { field: 'planEndDate', title: '计划完成', minWidth: 120, formatter: 'formatDate' },
    { field: 'createTime', title: '创建时间', minWidth: 160, formatter: 'formatDateTime' },
    { field: 'action', title: '操作', width: 220, fixed: 'right', slots: { default: 'actions' } },
    { field: "chiefDesignerNickname", title: "主设计师", minWidth: 100 },
    { field: "reviewerNickname", title: "审核人", minWidth: 100 },
    {
      field: "planFinishTime",
      title: "计划完成",
      minWidth: 120,
      formatter: "formatDate",
    },
    {
      field: "createTime",
      title: "创建时间",
      minWidth: 160,
      formatter: "formatDateTime",
    },
    {
      field: "action",
      title: "操作",
      width: 260,
      fixed: "right",
      slots: { default: "actions" },
    },
  ];
}
/** 编辑/详情表单 */
export function useFormSchema(
  formType: FormType,
  formApi?: VbenFormApi,
  formApi?: ExtendedFormApi
): VbenFormSchema[] {
  const readonly = formType === 'detail';
  const readonly = formType === "detail";
  return [
    {
      fieldName: 'id',
      component: 'Input',
      dependencies: { triggerFields: [''], show: () => false },
      fieldName: "id",
      component: "Input",
      dependencies: { triggerFields: [""], show: () => false },
    },
    {
      fieldName: 'code',
      label: '任务编码',
      component: 'Input',
      componentProps: { disabled: readonly, placeholder: '请输入任务编码' },
      rules: 'required',
      fieldName: "taskCode",
      label: "任务编码",
      component: "Input",
      componentProps: { disabled: readonly, placeholder: "请输入任务编码" },
      rules: "required",
      suffix:
        formType === 'detail'
        formType === "detail"
          ? undefined
          : () =>
              h(
                Button,
                {
                  type: 'default',
                  type: "default",
                  onClick: async () => {
                    const code = isPdMockEnabled()
                      ? mockNextCode(
                          'DT-2026',
                          Math.floor(Date.now() % 10_000),
                        )
                      : await generateAutoCode(
                          MesAutoCodeRuleCode.PD_PROJECT_CODE,
                        );
                    await formApi?.setFieldValue('code', code);
                    const code = await generateAutoCode(
                      MesAutoCodeRuleCode.PD_PROJECT_CODE
                    );
                    await formApi?.setFieldValue("taskCode", code);
                  },
                },
                { default: () => '生成' },
                { default: () => "生成" }
              ),
    },
    ...useProductSelectSchema(formApi, readonly),
    {
      fieldName: 'version',
      label: '版本号',
      component: 'Input',
      componentProps: { disabled: readonly, placeholder: '如 V1.0' },
      rules: 'required',
      fieldName: "version",
      label: "版本号",
      component: "Input",
      componentProps: { disabled: readonly, placeholder: "如 V1.0" },
      rules: "required",
    },
    {
      fieldName: 'name',
      label: '任务名称',
      component: 'Input',
      componentProps: { disabled: readonly, placeholder: '如:智能温控模组 V1.0 设计' },
      rules: 'required',
      fieldName: "taskName",
      label: "任务名称",
      component: "Input",
      componentProps: {
        disabled: readonly,
        placeholder: "如:智能温控模组 V1.0 设计",
      },
      rules: "required",
      dependencies: {
        triggerFields: ['productName', 'version'],
        triggerFields: ["productName", "version"],
        trigger(values: Record<string, string>, form) {
          if (readonly) {
            return;
@@ -383,152 +342,145 @@
          const productName = values.productName?.trim();
          const version = values.version?.trim();
          if (productName && version) {
            form.setFieldValue('name', `${productName} ${version} 设计`);
            form.setFieldValue("taskName", `${productName} ${version} 设计`);
          }
        },
      },
    },
    {
      fieldName: 'status',
      label: '任务状态',
      component: 'Select',
      fieldName: "status",
      label: "任务状态",
      component: "Select",
      componentProps: {
        disabled: true,
        options: getDictOptions(DICT_TYPE.MES_PD_PROJECT_STATUS, 'number'),
        options: getDictOptions(DICT_TYPE.MES_PD_PROJECT_STATUS, "number"),
      },
      dependencies: { triggerFields: [''], show: () => formType !== 'create' },
      dependencies: { triggerFields: [""], show: () => formType !== "create" },
    },
    {
      fieldName: 'designerName',
      label: '主设计师',
      component: 'Input',
      componentProps: { disabled: readonly, placeholder: '请输入主设计师' },
      fieldName: "chiefDesigner",
      label: "主设计师",
      component: markRaw(PdUserSelect),
      componentProps: { disabled: readonly, placeholder: "请选择主设计师" },
    },
    {
      fieldName: 'reviewerName',
      label: '审核人',
      component: 'Input',
      componentProps: { disabled: readonly, placeholder: '请输入审核人' },
      fieldName: "reviewer",
      label: "审核人",
      component: markRaw(PdUserSelect),
      componentProps: { disabled: readonly, placeholder: "请选择审核人" },
    },
    {
      fieldName: 'planDateRange',
      label: '计划周期',
      component: 'RangePicker',
      componentProps: {
        ...getRangePickerDefaultProps(),
      fieldName: "planFinishTime",
      label: "计划完成时间",
      component: "DatePicker",
      componentProps: useModalDatePickerProps({
        disabled: readonly,
      },
        placeholder: "请选择计划完成时间",
      }),
    },
    {
      fieldName: 'remark',
      label: '备注',
      component: 'Textarea',
      componentProps: { disabled: readonly, placeholder: '请输入备注', rows: 3 },
      formItemClass: 'col-span-3',
      fieldName: "remark",
      label: "备注",
      component: "Textarea",
      componentProps: {
        disabled: readonly,
        placeholder: "请输入备注",
        rows: 3,
      },
      formItemClass: "col-span-3",
    },
  ];
}
/** 设计资料类型选项(上传时选择) */
/** 设计资料类型选项 */
export function getPdDocumentTypeOptions() {
  return [
    { label: '设计方案', value: MesPdDocumentTypeEnum.SCHEME },
    { label: '设计图纸', value: MesPdDocumentTypeEnum.DRAWING },
    { label: '设计模型', value: MesPdDocumentTypeEnum.MODEL },
    { label: '产品设计', value: MesPdDocumentTypeEnum.PRODUCT_DESIGN },
    { label: 'BOM 清单', value: MesPdDocumentTypeEnum.BOM },
    { label: '其他附件', value: MesPdDocumentTypeEnum.OTHER },
    { label: "设计方案", value: MesPdDocumentTypeEnum.SCHEME },
    { label: "设计图纸", value: MesPdDocumentTypeEnum.DRAWING },
    { label: "设计模型", value: MesPdDocumentTypeEnum.MODEL },
    { label: "产品设计", value: MesPdDocumentTypeEnum.PRODUCT_DESIGN },
    { label: "BOM 清单", value: MesPdDocumentTypeEnum.BOM },
    { label: "其他附件", value: MesPdDocumentTypeEnum.OTHER },
  ];
}
/** 统一设计资料列表列 */
/** 资料列表搜索表单 */
export function useMaterialListGridFormSchema(): VbenFormSchema[] {
  return [
    {
      fieldName: 'name',
      label: '资料名称',
      component: 'Input',
      componentProps: { placeholder: '请输入资料名称' },
      fieldName: "documentName",
      label: "资料名称",
      component: "Input",
      componentProps: { placeholder: "请输入资料名称" },
    },
    {
      fieldName: 'documentType',
      label: '资料类型',
      component: 'Select',
      fieldName: "documentType",
      label: "资料类型",
      component: "Select",
      componentProps: {
        allowClear: true,
        options: getPdDocumentTypeOptions(),
        placeholder: '请选择资料类型',
        placeholder: "请选择资料类型",
      },
    },
  ];
}
export function useMaterialListGridColumns(): VxeTableGridOptions['columns'] {
/** 资料列表列定义 */
export function useMaterialListGridColumns(): VxeTableGridOptions["columns"] {
  return [
    {
      field: 'documentType',
      title: '资料类型',
      field: "documentType",
      title: "资料类型",
      minWidth: 110,
      formatter: ({ cellValue }: { cellValue: number }) => {
      formatter: ({ cellValue }: { cellValue: string }) => {
        const option = getPdDocumentTypeOptions().find(
          (item) => item.value === cellValue,
          (item) => item.value === cellValue
        );
        return option?.label ?? String(cellValue ?? '');
        return option?.label ?? String(cellValue ?? "");
      },
    },
    { field: 'name', title: '资料名称', minWidth: 180 },
    { field: 'version', title: '版本', minWidth: 90 },
    { field: 'fileName', title: '文件名', minWidth: 200 },
    { field: 'uploaderName', title: '上传人', minWidth: 100 },
    { field: "documentName", title: "资料名称", minWidth: 180 },
    { field: "documentVersion", title: "版本", minWidth: 90 },
    {
      field: 'createTime',
      title: '上传时间',
      field: "fileUrl",
      title: "文件",
      minWidth: 140,
      slots: { default: "file" },
    },
    { field: "fileName", title: "文件名", minWidth: 160 },
    { field: "uploadUserNickname", title: "上传人", minWidth: 100 },
    {
      field: "uploadTime",
      title: "上传时间",
      minWidth: 160,
      formatter: 'formatDateTime',
      formatter: "formatDateTime",
    },
    {
      field: 'action',
      title: '操作',
      field: "action",
      title: "操作",
      width: 140,
      fixed: 'right',
      slots: { default: 'actions' },
      fixed: "right",
      slots: { default: "actions" },
    },
  ];
}
/** @deprecated 按类型分 Tab 时使用,请改用 useMaterialListGridColumns */
export function useDocumentGridColumns(documentType: number): VxeTableGridOptions['columns'] {
  const typeLabel =
    documentType === MesPdDocumentTypeEnum.SCHEME
      ? '方案'
      : documentType === MesPdDocumentTypeEnum.DRAWING
        ? '图纸'
        : documentType === MesPdDocumentTypeEnum.MODEL
          ? '模型'
          : documentType === MesPdDocumentTypeEnum.PRODUCT_DESIGN
            ? '产品设计'
            : '资料';
  return [
    { field: 'name', title: `${typeLabel}名称`, minWidth: 180 },
    { field: 'version', title: '版本', minWidth: 90 },
    { field: 'fileName', title: '文件名', minWidth: 200 },
    { field: 'uploaderName', title: '上传人', minWidth: 100 },
    { field: 'createTime', title: '上传时间', minWidth: 160, formatter: 'formatDateTime' },
    { field: 'action', title: '操作', width: 140, slots: { default: 'actions' } },
  ];
}
/** BOM 表格列 */
export function useBomGridColumns(): VxeTableGridOptions['columns'] {
export function useBomGridColumns(): VxeTableGridOptions["columns"] {
  return [
    { field: 'itemCode', title: '物料编码', minWidth: 120 },
    { field: 'itemName', title: '物料名称', minWidth: 160 },
    { field: 'specification', title: '规格型号', minWidth: 140 },
    { field: 'unitMeasureName', title: '单位', minWidth: 80 },
    { field: 'quantity', title: '用量', minWidth: 90 },
    { field: 'remark', title: '备注', minWidth: 140 },
    { field: 'action', title: '操作', width: 140, slots: { default: 'actions' } },
    { field: "itemCode", title: "物料编码", minWidth: 120 },
    { field: "itemName", title: "物料名称", minWidth: 160 },
    { field: "specification", title: "规格型号", minWidth: 140 },
    { field: "unitMeasureName", title: "单位", minWidth: 80 },
    { field: "quantity", title: "用量", minWidth: 90 },
    { field: "remark", title: "备注", minWidth: 140 },
    {
      field: "action",
      title: "操作",
      width: 140,
      slots: { default: "actions" },
    },
  ];
}