Files
yudao-ui-admin-vben/apps/web-antd/src/views/mes/tm/tool/data.ts
YunaiV 61172b9a68 fix(mes): 修复 MES 迁移 review 发现的问题(B001-B032)
系统性修复 MES migration review(INDEX.md,MES-R001~R042)发现的迁移问题,
覆盖 web-antd 与 web-ele 两端,按严重级别从 P0 到 P3。

P0
- B001: DICT_TYPE/BarcodeBizTypeEnum 等常量从 'vue' 误导入致 TS2305/运行时崩溃,
  改从 @vben/constants 导入(20 个文件)。

P1
- B002 itemreceipt 入库单名称误必填;B003 条码工单选择补 CONFIRMED 过滤;
  B004 库存台账冻结开关补更新权限禁用;B005 returnsales 上架明细批次号误必填;
  B006 checkrecord/maintenrecord 计划/执行人误必填;B007 returnsales 退货行
  rqcCheckFlag 默认改回 false;B019 OQC 预填 checkQuantity 缺省取 outQuantity;
  B024 repair 完成维修态放开 finishDate 录入;B025 tool 编码管理类型库存数量锁定为 1;
  B027 详情态自动编码按钮隐藏/禁用(md/cal/dv/tm 13 模块)。

P2
- B008 IPQC 废品数量补 0 默认值;B009 共享选择器去掉 catch+console.error 吞错;
  B011 route 自定义 SFC 改 markRaw;B012 ele 自动编码按钮去 type:'default';
  B014 md 编辑态编码字段误禁用;B015 dv/subject 选择器仅展示启用项(保留历史回显);
  B016 盘点结果回填 batchId;B017 源 vue3 miscissue 业务类型字典误用 getStrDictOptions;
  B018 stocktaking/plan 盘点条件表单 schema 化;B020 清理 TODO @AI;
  B026 repair 验收信息字段按状态门控只读。

P3
- B010 QcIndicatorSelect 去吞错;B013/B019/B030/B031 componentProps、列对象多行化等
  code style;B021 自动编码循环方式列条件展示;B022 盘点结果选中清单行后字段禁用;
  B023 质检指标 resultSpecification 抽 ResultSpecificationInput 消除重复 fieldName;
  B032 barcode/batch/sn API 字段补注释。

风格统一
- getTitle 统一为「特殊态 if 提前 return + create/update 三元」(pro/card、
  stocktaking/task、repair);headerReadonly 抽 isHeaderReadonly 辅助函数对齐
  pro/workorder/transfer 写法;computed 解释注释移入 computed 内部。

验证:
- 两端 pnpm exec eslint 改动文件通过
- 两端 pnpm -F @vben/web-antd / @vben/web-ele exec vue-tsc 过滤 src/views/mes、
  api/mes 无报错
- git diff --check 通过

备注:R037(defectrecord 命名漂移)经复核为原 finding 前提有误(两端本就一致),
已 rejected,未占 MES-B 编号。R008/R009 为 disputed 待裁决。
本提交仅含 src/views/mes 与 src/api/mes 下文件,排除 .env.development、vite.config.ts、
infra/codegen、docs changelog 等无关旁支改动。
2026-05-31 10:21:23 +08:00

328 lines
8.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import type { VbenFormApi, VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { MesTmToolApi } from '#/api/mes/tm/tool';
import { h, markRaw } from 'vue';
import { DICT_TYPE, MesAutoCodeRuleCode, MesMaintenTypeEnum, MesToolStatusEnum } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { formatDateTime } from '@vben/utils';
import { Button } from 'ant-design-vue';
import { z } from '#/adapter/form';
import { generateAutoCode } from '#/api/mes/md/autocode/record';
import { TmToolTypeSelect } from './type/components';
/** 表单类型 */
export type FormType = 'create' | 'detail' | 'update';
/** 新增/修改工具的表单 */
export function useFormSchema(
formType: FormType,
formApi?: VbenFormApi,
): VbenFormSchema[] {
return [
{
fieldName: 'id',
component: 'Input',
dependencies: {
triggerFields: [''],
show: () => false,
},
},
{
// 选中工具类型是否「编码管理」,用于锁定库存数量为 1隐藏字段
fieldName: 'codeFlag',
component: 'Input',
dependencies: {
triggerFields: [''],
show: () => false,
},
},
{
fieldName: 'code',
label: '工具编码',
component: 'Input',
componentProps: {
placeholder: '请输入工具编码',
},
dependencies: {
triggerFields: ['id'],
componentProps: (values) => ({ disabled: !!values.id }),
},
rules: 'required',
suffix:
formType === 'detail'
? undefined
: () =>
h(
Button,
{
type: 'default',
onClick: async () => {
const code = await generateAutoCode(MesAutoCodeRuleCode.TM_TOOL_CODE);
await formApi?.setFieldValue('code', code);
},
},
{ default: () => '生成' },
),
},
{
fieldName: 'name',
label: '工具名称',
component: 'Input',
componentProps: {
placeholder: '请输入工具名称',
},
rules: 'required',
},
{
fieldName: 'toolTypeId',
label: '工具类型',
component: markRaw(TmToolTypeSelect),
componentProps: {
placeholder: '请选择工具类型',
onChange: async (row: any) => {
// 记录是否编码管理;编码管理类型库存数量锁定为 1
await formApi?.setFieldValue('codeFlag', row?.codeFlag === true);
if (row?.codeFlag === true) {
await formApi?.setFieldValue('quantity', 1);
await formApi?.setFieldValue('availableQuantity', 1);
}
},
},
rules: 'selectRequired',
},
{
fieldName: 'brand',
label: '品牌',
component: 'Input',
componentProps: {
placeholder: '请输入品牌',
},
},
{
fieldName: 'specification',
label: '型号规格',
component: 'Input',
componentProps: {
placeholder: '请输入型号规格',
},
},
{
fieldName: 'quantity',
label: '库存数量',
component: 'InputNumber',
componentProps: {
class: '!w-full',
min: 1,
onChange: async (value?: number) => {
const values = (await formApi?.getValues()) as MesTmToolApi.Tool | undefined;
if (!values?.id) {
await formApi?.setFieldValue('availableQuantity', value);
}
},
precision: 0,
},
rules: 'required',
// 编码管理类型库存数量锁定为 1禁止修改
dependencies: {
triggerFields: ['codeFlag'],
componentProps: (values) => ({
disabled: values.codeFlag === true,
}),
},
},
{
fieldName: 'availableQuantity',
label: '可用数量',
component: 'InputNumber',
componentProps: {
class: '!w-full',
disabled: true,
min: 0,
precision: 0,
},
rules: z.number().default(1),
},
{
fieldName: 'status',
label: '状态',
component: 'Select',
componentProps: {
disabled: true,
options: getDictOptions(DICT_TYPE.MES_TM_TOOL_STATUS, 'number'),
},
rules: z.number().default(MesToolStatusEnum.STORE),
},
{
fieldName: 'maintenType',
label: '保养维护类型',
component: 'Select',
componentProps: {
allowClear: true,
options: getDictOptions(DICT_TYPE.MES_TM_MAINTEN_TYPE, 'number'),
placeholder: '请选择保养维护类型',
},
},
{
fieldName: 'nextMaintenDate',
label: '下次保养日期',
component: 'DatePicker',
componentProps: {
format: 'YYYY-MM-DD HH:mm:ss',
showTime: true,
valueFormat: 'x',
},
dependencies: {
triggerFields: ['maintenType'],
show: (values) => values.maintenType === MesMaintenTypeEnum.REGULAR,
},
},
{
fieldName: 'nextMaintenPeriod',
label: '下次保养周期',
component: 'InputNumber',
componentProps: {
class: '!w-full',
min: 1,
precision: 0,
},
dependencies: {
triggerFields: ['maintenType'],
show: (values) => values.maintenType === MesMaintenTypeEnum.USAGE,
},
},
{
fieldName: 'remark',
label: '备注',
component: 'Textarea',
formItemClass: 'col-span-3',
componentProps: {
placeholder: '请输入备注',
rows: 3,
},
},
];
}
/** 列表的搜索表单 */
export function useGridFormSchema(): VbenFormSchema[] {
return [
{
fieldName: 'code',
label: '工具编码',
component: 'Input',
componentProps: {
allowClear: true,
placeholder: '请输入工具编码',
},
},
{
fieldName: 'name',
label: '工具名称',
component: 'Input',
componentProps: {
allowClear: true,
placeholder: '请输入工具名称',
},
},
{
fieldName: 'brand',
label: '品牌',
component: 'Input',
componentProps: {
allowClear: true,
placeholder: '请输入品牌',
},
},
{
fieldName: 'specification',
label: '型号规格',
component: 'Input',
componentProps: {
allowClear: true,
placeholder: '请输入型号规格',
},
},
{
fieldName: 'status',
label: '状态',
component: 'Select',
componentProps: {
allowClear: true,
options: getDictOptions(DICT_TYPE.MES_TM_TOOL_STATUS, 'number'),
placeholder: '请选择状态',
},
},
];
}
/** 列表的字段 */
export function useGridColumns(): VxeTableGridOptions<MesTmToolApi.Tool>['columns'] {
return [
{
field: 'code',
title: '工具编码',
minWidth: 140,
slots: {
default: 'code',
},
},
{ field: 'name', title: '工具名称', minWidth: 150 },
{ field: 'toolTypeName', title: '工具类型', minWidth: 140 },
{ field: 'brand', title: '品牌', minWidth: 120 },
{ field: 'specification', title: '型号规格', minWidth: 140 },
{ field: 'quantity', title: '库存数量', width: 100 },
{ field: 'availableQuantity', title: '可用数量', width: 100 },
{
field: 'maintenType',
title: '保养维护类型',
width: 140,
cellRender: {
name: 'CellDict',
props: { type: DICT_TYPE.MES_TM_MAINTEN_TYPE },
},
},
{
field: 'nextMaintenDate',
title: '下次保养',
width: 180,
formatter: ({ row }) => {
if (row.maintenType === MesMaintenTypeEnum.REGULAR) {
return row.nextMaintenDate ? formatDateTime(row.nextMaintenDate) : '-';
}
if (row.maintenType === MesMaintenTypeEnum.USAGE) {
return row.nextMaintenPeriod == null ? '-' : `${row.nextMaintenPeriod}`;
}
return '-';
},
},
{
field: 'status',
title: '状态',
width: 120,
cellRender: {
name: 'CellDict',
props: { type: DICT_TYPE.MES_TM_TOOL_STATUS },
},
},
{
field: 'createTime',
title: '创建时间',
width: 180,
formatter: 'formatDateTime',
},
{
title: '操作',
width: 180,
fixed: 'right',
slots: {
default: 'actions',
},
},
];
}