From 8d660404dcb6fe552c9f13c16d7d0b76e0606508 Mon Sep 17 00:00:00 2001 From: nehc <934298133@qq.com> Date: Thu, 31 Jul 2025 13:43:47 +0800 Subject: [PATCH 1/8] =?UTF-8?q?feat(@vben/web-antd):=20erp-stock-stock=20?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E4=BA=A7=E5=93=81=E5=BA=93=E5=AD=98=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增产品库存管理页面,包括库存列表和搜索功能 - 添加导出库存数据功能 - 集成 API 接口和数据处理逻辑 - 优化页面布局和组件使用 --- .../web-antd/src/api/erp/stock/stock/index.ts | 2 +- .../src/views/erp/stock/stock/data.ts | 76 +++++++++++++++ .../src/views/erp/stock/stock/index.vue | 94 ++++++++++++++----- 3 files changed, 147 insertions(+), 25 deletions(-) create mode 100644 apps/web-antd/src/views/erp/stock/stock/data.ts diff --git a/apps/web-antd/src/api/erp/stock/stock/index.ts b/apps/web-antd/src/api/erp/stock/stock/index.ts index 57d4ec229..fa4cfaddb 100644 --- a/apps/web-antd/src/api/erp/stock/stock/index.ts +++ b/apps/web-antd/src/api/erp/stock/stock/index.ts @@ -2,7 +2,7 @@ import type { PageParam, PageResult } from '@vben/request'; import { requestClient } from '#/api/request'; -namespace ErpStockApi { +export namespace ErpStockApi { /** 产品库存信息 */ export interface Stock { id?: number; // 编号 diff --git a/apps/web-antd/src/views/erp/stock/stock/data.ts b/apps/web-antd/src/views/erp/stock/stock/data.ts new file mode 100644 index 000000000..4d0e52b7e --- /dev/null +++ b/apps/web-antd/src/views/erp/stock/stock/data.ts @@ -0,0 +1,76 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { getProductSimpleList } from '#/api/erp/product/product'; +import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse'; + +/** 搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'productId', + label: '产品', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择产品', + allowClear: true, + showSearch: true, + api: getProductSimpleList, + labelField: 'name', + valueField: 'id', + filterOption: false, + }, + }, + { + fieldName: 'warehouseId', + label: '仓库', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择仓库', + allowClear: true, + showSearch: true, + api: getWarehouseSimpleList, + labelField: 'name', + valueField: 'id', + filterOption: false, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'productName', + title: '产品名称', + minWidth: 150, + }, + { + field: 'unitName', + title: '产品单位', + minWidth: 100, + }, + { + field: 'categoryName', + title: '产品分类', + minWidth: 120, + }, + { + field: 'count', + title: '库存量', + minWidth: 100, + cellRender: { + name: 'CellAmount', + props: { + digits: 2, + }, + }, + }, + { + field: 'warehouseName', + title: '仓库', + minWidth: 120, + }, + ]; +} diff --git a/apps/web-antd/src/views/erp/stock/stock/index.vue b/apps/web-antd/src/views/erp/stock/stock/index.vue index 04305f885..8cd51e59c 100644 --- a/apps/web-antd/src/views/erp/stock/stock/index.vue +++ b/apps/web-antd/src/views/erp/stock/stock/index.vue @@ -1,32 +1,78 @@ -- Gitee From 2e6575f368a0ed536e2a2553aee3ce7d7686563e Mon Sep 17 00:00:00 2001 From: nehc <934298133@qq.com> Date: Thu, 31 Jul 2025 14:33:16 +0800 Subject: [PATCH 2/8] =?UTF-8?q?feat(@vben/web-antd):=20erp-stock-record=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=A7=E5=93=81=E5=BA=93=E5=AD=98=E6=98=8E?= =?UTF-8?q?=E7=BB=86=E7=AE=A1=E7=90=86=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 实现了产品库存明细的查询、导出功能 - 添加了搜索表单和列表展示 - 集成了仓库和产品选择器 - 使用了 VxeTable 组件 --- .../src/views/erp/stock/record/data.ts | 146 ++++++++++++++++++ .../src/views/erp/stock/record/index.vue | 94 ++++++++--- 2 files changed, 216 insertions(+), 24 deletions(-) create mode 100644 apps/web-antd/src/views/erp/stock/record/data.ts diff --git a/apps/web-antd/src/views/erp/stock/record/data.ts b/apps/web-antd/src/views/erp/stock/record/data.ts new file mode 100644 index 000000000..3f8054921 --- /dev/null +++ b/apps/web-antd/src/views/erp/stock/record/data.ts @@ -0,0 +1,146 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { getProductSimpleList } from '#/api/erp/product/product'; +import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse'; +import { DICT_TYPE, getDictOptions } from '#/utils'; + +/** 搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'productId', + label: '产品', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择产品', + allowClear: true, + showSearch: true, + api: getProductSimpleList, + labelField: 'name', + valueField: 'id', + filterOption: false, + }, + }, + { + fieldName: 'warehouseId', + label: '仓库', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择仓库', + allowClear: true, + showSearch: true, + api: getWarehouseSimpleList, + labelField: 'name', + valueField: 'id', + filterOption: false, + }, + }, + { + fieldName: 'bizType', + label: '类型', + component: 'Select', + componentProps: { + placeholder: '请选择类型', + allowClear: true, + options: getDictOptions(DICT_TYPE.ERP_STOCK_RECORD_BIZ_TYPE, 'number'), + }, + }, + { + fieldName: 'bizNo', + label: '业务单号', + component: 'Input', + componentProps: { + placeholder: '请输入业务单号', + allowClear: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + placeholder: ['开始日期', '结束日期'], + showTime: true, + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'YYYY-MM-DD HH:mm:ss', + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'productName', + title: '产品名称', + minWidth: 150, + }, + { + field: 'categoryName', + title: '产品分类', + width: 120, + }, + { + field: 'unitName', + title: '产品单位', + width: 100, + }, + { + field: 'warehouseName', + title: '仓库', + width: 120, + }, + { + field: 'bizType', + title: '类型', + width: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.ERP_STOCK_RECORD_BIZ_TYPE }, + }, + }, + { + field: 'bizNo', + title: '出入库单号', + width: 200, + showOverflow: 'tooltip', + }, + { + field: 'createTime', + title: '出入库日期', + width: 180, + cellRender: { + name: 'CellDateTime', + }, + }, + { + field: 'count', + title: '出入库数量', + width: 120, + cellRender: { + name: 'CellAmount', + props: { + digits: 2, + }, + }, + }, + { + field: 'totalCount', + title: '库存量', + width: 100, + cellRender: { + name: 'CellAmount', + props: { + digits: 2, + }, + }, + }, + { + field: 'creatorName', + title: '操作人', + width: 100, + }, + ]; +} \ No newline at end of file diff --git a/apps/web-antd/src/views/erp/stock/record/index.vue b/apps/web-antd/src/views/erp/stock/record/index.vue index 33dddb833..a05f403eb 100644 --- a/apps/web-antd/src/views/erp/stock/record/index.vue +++ b/apps/web-antd/src/views/erp/stock/record/index.vue @@ -1,32 +1,78 @@ -- Gitee From 510ec125824c3949821648718deced0ba4f6c0fd Mon Sep 17 00:00:00 2001 From: nehc <934298133@qq.com> Date: Thu, 31 Jul 2025 17:20:09 +0800 Subject: [PATCH 3/8] =?UTF-8?q?feat(@vben/web-antd):=20erp-stock-in=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=85=B6=E5=AE=83=E5=85=A5=E5=BA=93=E5=8D=95?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增其它入库单列表页面 - 实现其它入库单的创建、编辑和删除功能 - 添加产品清单管理功能 - 集成供应商、产品和仓库的选择接口 - 优化表格展示和搜索功能 --- apps/web-antd/src/api/erp/stock/in/index.ts | 23 +- .../web-antd/src/api/erp/stock/stock/index.ts | 8 +- apps/web-antd/src/views/erp/stock/in/data.ts | 338 ++++++++++++++++ .../web-antd/src/views/erp/stock/in/index.vue | 201 +++++++++- .../erp/stock/in/modules/StockInItemForm.vue | 368 ++++++++++++++++++ .../src/views/erp/stock/in/modules/form.vue | 252 ++++++++++++ 6 files changed, 1167 insertions(+), 23 deletions(-) create mode 100644 apps/web-antd/src/views/erp/stock/in/data.ts create mode 100644 apps/web-antd/src/views/erp/stock/in/modules/StockInItemForm.vue create mode 100644 apps/web-antd/src/views/erp/stock/in/modules/form.vue diff --git a/apps/web-antd/src/api/erp/stock/in/index.ts b/apps/web-antd/src/api/erp/stock/in/index.ts index 119398bc3..8fe9bafd4 100644 --- a/apps/web-antd/src/api/erp/stock/in/index.ts +++ b/apps/web-antd/src/api/erp/stock/in/index.ts @@ -2,17 +2,38 @@ import type { PageParam, PageResult } from '@vben/request'; import { requestClient } from '#/api/request'; -namespace ErpStockInApi { +export namespace ErpStockInApi { /** 其它入库单信息 */ export interface StockIn { id?: number; // 入库编号 no: string; // 入库单号 supplierId: number; // 供应商编号 + supplierName?: string; // 供应商名称 inTime: Date; // 入库时间 totalCount: number; // 合计数量 totalPrice: number; // 合计金额,单位:元 status: number; // 状态 remark: string; // 备注 + fileUrl?: string; // 附件 + productNames?: string; // 产品信息 + creatorName?: string; // 创建人 + items?: StockInItem[]; // 入库产品清单 + } + + /** 其它入库单产品信息 */ + export interface StockInItem { + id?: number; // 编号 + warehouseId: number; // 仓库编号 + productId: number; // 产品编号 + productName?: string; // 产品名称 + productUnitId?: number; // 产品单位编号 + productUnitName?: string; // 产品单位名称 + productBarCode?: string; // 产品条码 + count: number; // 数量 + productPrice: number; // 产品单价 + totalPrice: number; // 总价 + stockCount?: number; // 库存数量 + remark?: string; // 备注 } /** 其它入库单分页查询参数 */ diff --git a/apps/web-antd/src/api/erp/stock/stock/index.ts b/apps/web-antd/src/api/erp/stock/stock/index.ts index fa4cfaddb..3ef12dff6 100644 --- a/apps/web-antd/src/api/erp/stock/stock/index.ts +++ b/apps/web-antd/src/api/erp/stock/stock/index.ts @@ -54,9 +54,13 @@ export function getStockByProductAndWarehouse( /** * 获得产品库存数量 */ -export function getStockCount(productId: number) { +export function getStockCount(productId: number, warehouseId?: number) { + const params: any = { productId }; + if (warehouseId !== undefined) { + params.warehouseId = warehouseId; + } return requestClient.get('/erp/stock/get-count', { - params: { productId }, + params, }); } diff --git a/apps/web-antd/src/views/erp/stock/in/data.ts b/apps/web-antd/src/views/erp/stock/in/data.ts new file mode 100644 index 000000000..2086066ff --- /dev/null +++ b/apps/web-antd/src/views/erp/stock/in/data.ts @@ -0,0 +1,338 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { erpPriceInputFormatter } from '@vben/utils'; + +import { getSupplierSimpleList } from '#/api/erp/purchase/supplier'; +import { getSimpleUserList } from '#/api/system/user'; +import { DICT_TYPE, getDictOptions } from '#/utils'; + +/** 表单的配置项 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + componentProps: { + style: { display: 'none' }, + }, + fieldName: 'id', + label: 'ID', + hideLabel: true, + formItemClass: 'hidden', + }, + { + component: 'Input', + componentProps: { + placeholder: '系统自动生成', + disabled: true, + }, + fieldName: 'no', + label: '入库单号', + }, + { + component: 'ApiSelect', + componentProps: { + placeholder: '请选择供应商', + allowClear: true, + showSearch: true, + api: getSupplierSimpleList, + fieldNames: { + label: 'name', + value: 'id', + }, + }, + fieldName: 'supplierId', + label: '供应商', + }, + { + component: 'DatePicker', + componentProps: { + placeholder: '选择入库时间', + showTime: true, + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + style: { width: '100%' }, + }, + fieldName: 'inTime', + label: '入库时间', + rules: 'required', + }, + { + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + autoSize: { minRows: 2, maxRows: 4 }, + class: 'w-full', + }, + fieldName: 'remark', + label: '备注', + formItemClass: 'col-span-3', + }, + { + component: 'FileUpload', + componentProps: { + maxNumber: 1, + maxSize: 10, + accept: [ + 'pdf', + 'doc', + 'docx', + 'xls', + 'xlsx', + 'txt', + 'jpg', + 'jpeg', + 'png', + ], + showDescription: true, + }, + fieldName: 'fileUrl', + label: '附件', + formItemClass: 'col-span-3', + }, + { + fieldName: 'product', + label: '产品清单', + component: 'Input', + formItemClass: 'col-span-3', + }, + { + component: 'InputNumber', + componentProps: { + placeholder: '合计数量', + precision: 2, + disabled: true, + style: { width: '100%' }, + }, + fieldName: 'totalCount', + label: '合计数量', + }, + { + component: 'InputNumber', + componentProps: { + placeholder: '合计金额', + precision: 2, + formatter: erpPriceInputFormatter, + disabled: true, + style: { width: '100%' }, + }, + fieldName: 'totalPrice', + label: '合计金额', + }, + ]; +} + +/** 入库产品清单表格列定义 */ +export function useStockInItemTableColumns(): VxeTableGridOptions['columns'] { + return [ + { type: 'seq', title: '序号', minWidth: 50, fixed: 'left' }, + { + field: 'warehouseId', + title: '仓库名称', + minWidth: 150, + slots: { default: 'warehouseId' }, + }, + { + field: 'productId', + title: '产品名称', + minWidth: 200, + slots: { default: 'productId' }, + }, + { + field: 'stockCount', + title: '库存', + minWidth: 100, + }, + { + field: 'productBarCode', + title: '条码', + minWidth: 120, + }, + { + field: 'productUnitName', + title: '单位', + minWidth: 80, + }, + { + field: 'count', + title: '数量', + minWidth: 120, + slots: { default: 'count' }, + }, + { + field: 'productPrice', + title: '产品单价', + minWidth: 120, + slots: { default: 'productPrice' }, + }, + { + field: 'totalPrice', + title: '金额', + minWidth: 120, + formatter: 'formatAmount2', + }, + { + field: 'remark', + title: '备注', + minWidth: 150, + slots: { default: 'remark' }, + }, + { + title: '操作', + width: 50, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '入库单号', + component: 'Input', + componentProps: { + placeholder: '请输入入库单号', + allowClear: true, + }, + }, + { + fieldName: 'supplierId', + label: '供应商', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择供应商', + allowClear: true, + showSearch: true, + api: getSupplierSimpleList, + labelField: 'name', + valueField: 'id', + filterOption: false, + }, + }, + { + fieldName: 'inTime', + label: '入库时间', + component: 'RangePicker', + componentProps: { + placeholder: ['开始日期', '结束日期'], + showTime: true, + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'YYYY-MM-DD HH:mm:ss', + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + placeholder: '请选择状态', + allowClear: true, + options: getDictOptions(DICT_TYPE.ERP_AUDIT_STATUS, 'number'), + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Input', + componentProps: { + placeholder: '请输入备注', + allowClear: true, + }, + }, + { + fieldName: 'creator', + label: '创建人', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择创建人', + allowClear: true, + showSearch: true, + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + filterOption: false, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + fixed: 'left', + }, + { + field: 'no', + title: '入库单号', + minWidth: 180, + }, + { + field: 'productNames', + title: '产品信息', + minWidth: 200, + showOverflow: 'tooltip', + }, + { + field: 'supplierName', + title: '供应商', + width: 120, + }, + { + field: 'inTime', + title: '入库时间', + width: 180, + cellRender: { + name: 'CellDateTime', + }, + }, + { + field: 'creatorName', + title: '创建人', + width: 100, + }, + { + field: 'totalCount', + title: '数量', + width: 100, + cellRender: { + name: 'CellAmount', + props: { + digits: 2, + }, + }, + }, + { + field: 'totalPrice', + title: '金额', + width: 120, + cellRender: { + name: 'CellAmount', + props: { + digits: 2, + }, + }, + }, + { + field: 'status', + title: '状态', + width: 90, + fixed: 'right', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.ERP_AUDIT_STATUS }, + }, + }, + { + title: '操作', + width: 220, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-antd/src/views/erp/stock/in/index.vue b/apps/web-antd/src/views/erp/stock/in/index.vue index ae06852cb..641c4347d 100644 --- a/apps/web-antd/src/views/erp/stock/in/index.vue +++ b/apps/web-antd/src/views/erp/stock/in/index.vue @@ -1,34 +1,195 @@ diff --git a/apps/web-antd/src/views/erp/stock/in/modules/StockInItemForm.vue b/apps/web-antd/src/views/erp/stock/in/modules/StockInItemForm.vue new file mode 100644 index 000000000..d2ba3f195 --- /dev/null +++ b/apps/web-antd/src/views/erp/stock/in/modules/StockInItemForm.vue @@ -0,0 +1,368 @@ + + + diff --git a/apps/web-antd/src/views/erp/stock/in/modules/form.vue b/apps/web-antd/src/views/erp/stock/in/modules/form.vue new file mode 100644 index 000000000..108ef2600 --- /dev/null +++ b/apps/web-antd/src/views/erp/stock/in/modules/form.vue @@ -0,0 +1,252 @@ + + + -- Gitee From 3afd9577137f3df0e0059bbe7521dce357b32819 Mon Sep 17 00:00:00 2001 From: nehc <934298133@qq.com> Date: Fri, 1 Aug 2025 16:11:05 +0800 Subject: [PATCH 4/8] =?UTF-8?q?feat(@vben/web-antd):=20erp-stock-in=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=BA=93=E5=AD=98=E5=85=A5=E5=BA=93=E6=A8=A1?= =?UTF-8?q?=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 为表格列设置 minWidth 以优化布局 - 使用 Popconfirm组件替代 Modal 确认框 - 通过 message 组件展示操作结果 - 优化删除和审核操作的处理流程 - 引入 useVbenModal 优化表单弹窗 --- apps/web-antd/src/views/erp/stock/in/data.ts | 14 +-- .../web-antd/src/views/erp/stock/in/index.vue | 95 ++++++++++++------- .../erp/stock/in/modules/StockInItemForm.vue | 5 +- 3 files changed, 71 insertions(+), 43 deletions(-) diff --git a/apps/web-antd/src/views/erp/stock/in/data.ts b/apps/web-antd/src/views/erp/stock/in/data.ts index 2086066ff..bd54761d7 100644 --- a/apps/web-antd/src/views/erp/stock/in/data.ts +++ b/apps/web-antd/src/views/erp/stock/in/data.ts @@ -281,12 +281,12 @@ export function useGridColumns(): VxeTableGridOptions['columns'] { { field: 'supplierName', title: '供应商', - width: 120, + minWidth: 120, }, { field: 'inTime', title: '入库时间', - width: 180, + minWidth: 180, cellRender: { name: 'CellDateTime', }, @@ -294,12 +294,12 @@ export function useGridColumns(): VxeTableGridOptions['columns'] { { field: 'creatorName', title: '创建人', - width: 100, + minWidth: 100, }, { field: 'totalCount', title: '数量', - width: 100, + minWidth: 100, cellRender: { name: 'CellAmount', props: { @@ -310,7 +310,7 @@ export function useGridColumns(): VxeTableGridOptions['columns'] { { field: 'totalPrice', title: '金额', - width: 120, + minWidth: 120, cellRender: { name: 'CellAmount', props: { @@ -321,7 +321,7 @@ export function useGridColumns(): VxeTableGridOptions['columns'] { { field: 'status', title: '状态', - width: 90, + minWidth: 90, fixed: 'right', cellRender: { name: 'CellDict', @@ -330,7 +330,7 @@ export function useGridColumns(): VxeTableGridOptions['columns'] { }, { title: '操作', - width: 220, + width: 300, fixed: 'right', slots: { default: 'actions' }, }, diff --git a/apps/web-antd/src/views/erp/stock/in/index.vue b/apps/web-antd/src/views/erp/stock/in/index.vue index 641c4347d..8bb4c15d8 100644 --- a/apps/web-antd/src/views/erp/stock/in/index.vue +++ b/apps/web-antd/src/views/erp/stock/in/index.vue @@ -2,12 +2,10 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { ErpStockInApi } from '#/api/erp/stock/in'; -import { ref } from 'vue'; - -import { DocAlert, Page } from '@vben/common-ui'; +import { DocAlert, Page, useVbenModal } from '@vben/common-ui'; import { downloadFileFromBlobPart } from '@vben/utils'; -import { message, Modal } from 'ant-design-vue'; +import { message } from 'ant-design-vue'; import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; import { @@ -24,7 +22,10 @@ import StockInForm from './modules/form.vue'; /** 其它入库单管理 */ defineOptions({ name: 'ErpStockIn' }); -const formRef = ref(); +const [FormModal, formModalApi] = useVbenModal({ + connectedComponent: StockInForm, + destroyOnClose: true, +}); /** 刷新表格 */ function onRefresh() { @@ -39,34 +40,46 @@ async function handleExport() { /** 新增/编辑/详情 */ function openForm(type: string, id?: number) { - formRef.value?.modalApi.open({ type, id }); + formModalApi.setData({ type, id }).open(); } /** 删除 */ -function handleDelete(ids: any[]) { - Modal.confirm({ - title: '系统提示', - content: `是否确认删除编号为 ${ids.join(',')} 的其它入库单?`, - onOk: async () => { - await deleteStockIn(ids); - message.success('删除成功'); - onRefresh(); - }, +async function handleDelete(ids: any[]) { + const hideLoading = message.loading({ + content: '删除中...', + duration: 0, + key: 'action_process_msg', }); + try { + await deleteStockIn(ids); + message.success({ + content: '删除成功', + key: 'action_process_msg', + }); + onRefresh(); + } finally { + hideLoading(); + } } /** 审核/反审核 */ -function handleUpdateStatus(id: any, status: number) { +async function handleUpdateStatus(id: any, status: number) { const statusText = status === 20 ? '审核' : '反审核'; - Modal.confirm({ - title: '系统提示', - content: `确认要${statusText}该入库单吗?`, - onOk: async () => { - await updateStockInStatus({ id, status }); - message.success(`${statusText}成功`); - onRefresh(); - }, + const hideLoading = message.loading({ + content: `${statusText}中...`, + duration: 0, + key: 'action_process_msg', }); + try { + await updateStockInStatus({ id, status }); + message.success({ + content: `${statusText}成功`, + key: 'action_process_msg', + }); + onRefresh(); + } finally { + hideLoading(); + } } const [Grid, gridApi] = useVbenVxeGrid({ @@ -135,13 +148,16 @@ const [Grid, gridApi] = useVbenVxeGrid({ danger: true, icon: ACTION_ICON.DELETE, auth: ['erp:stock-in:delete'], - onClick: () => { - const checkboxRecords = gridApi.grid.getCheckboxRecords(); - if (checkboxRecords.length === 0) { - message.warning('请选择要删除的数据'); - return; - } - handleDelete(checkboxRecords.map((item) => item.id)); + popConfirm: { + title: '是否删除所选中数据?', + confirm: () => { + const checkboxRecords = gridApi.grid.getCheckboxRecords(); + if (checkboxRecords.length === 0) { + message.warning('请选择要删除的数据'); + return; + } + handleDelete(checkboxRecords.map((item) => item.id)); + }, }, }, ]" @@ -168,21 +184,30 @@ const [Grid, gridApi] = useVbenVxeGrid({ type: 'primary', auth: ['erp:stock-in:update'], ifShow: row.status === 10, - onClick: () => handleUpdateStatus(row.id, 20), + popConfirm: { + title: '确认要审核该入库单吗?', + confirm: () => handleUpdateStatus(row.id, 20), + }, }, { label: '反审核', danger: true, auth: ['erp:stock-in:update'], ifShow: row.status === 20, - onClick: () => handleUpdateStatus(row.id, 10), + popConfirm: { + title: '确认要反审核该入库单吗?', + confirm: () => handleUpdateStatus(row.id, 10), + }, }, { label: '删除', danger: true, auth: ['erp:stock-in:delete'], ifShow: row.status === 10, - onClick: () => handleDelete([row.id]), + popConfirm: { + title: '确认要删除该入库单吗?', + confirm: () => handleDelete([row.id]), + }, }, ]" /> @@ -190,6 +215,6 @@ const [Grid, gridApi] = useVbenVxeGrid({ - + diff --git a/apps/web-antd/src/views/erp/stock/in/modules/StockInItemForm.vue b/apps/web-antd/src/views/erp/stock/in/modules/StockInItemForm.vue index d2ba3f195..159e4e4a5 100644 --- a/apps/web-antd/src/views/erp/stock/in/modules/StockInItemForm.vue +++ b/apps/web-antd/src/views/erp/stock/in/modules/StockInItemForm.vue @@ -358,7 +358,10 @@ defineExpose({ label: '删除', type: 'link', danger: true, - onClick: () => handleDelete(row), + popConfirm: { + title: '确认删除该产品吗?', + confirm: handleDelete.bind(null, row), + }, }, ]" /> -- Gitee From 1433a0980d99daf6b1d9cc751ea94a224d095cfd Mon Sep 17 00:00:00 2001 From: nehc <934298133@qq.com> Date: Fri, 1 Aug 2025 17:35:56 +0800 Subject: [PATCH 5/8] =?UTF-8?q?feat(@vben/web-antd):=20erp-stock-in=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=85=A5=E5=BA=93=E5=8D=95=E4=BA=A7=E5=93=81?= =?UTF-8?q?=E6=B8=85=E5=8D=95=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除了 totalCount 和 totalPrice 的计算逻辑 - 调整了添加产品的按钮位置 - 为表格底部的单元格添加了自定义样式 - 简化了组件的 props 接口 --- apps/web-antd/src/views/erp/stock/in/data.ts | 47 -------------- .../erp/stock/in/modules/StockInItemForm.vue | 65 +++++++------------ .../src/views/erp/stock/in/modules/form.vue | 24 ++----- 3 files changed, 28 insertions(+), 108 deletions(-) diff --git a/apps/web-antd/src/views/erp/stock/in/data.ts b/apps/web-antd/src/views/erp/stock/in/data.ts index bd54761d7..7111cae9c 100644 --- a/apps/web-antd/src/views/erp/stock/in/data.ts +++ b/apps/web-antd/src/views/erp/stock/in/data.ts @@ -1,8 +1,6 @@ import type { VbenFormSchema } from '#/adapter/form'; import type { VxeTableGridOptions } from '#/adapter/vxe-table'; -import { erpPriceInputFormatter } from '@vben/utils'; - import { getSupplierSimpleList } from '#/api/erp/purchase/supplier'; import { getSimpleUserList } from '#/api/system/user'; import { DICT_TYPE, getDictOptions } from '#/utils'; @@ -96,29 +94,6 @@ export function useFormSchema(): VbenFormSchema[] { component: 'Input', formItemClass: 'col-span-3', }, - { - component: 'InputNumber', - componentProps: { - placeholder: '合计数量', - precision: 2, - disabled: true, - style: { width: '100%' }, - }, - fieldName: 'totalCount', - label: '合计数量', - }, - { - component: 'InputNumber', - componentProps: { - placeholder: '合计金额', - precision: 2, - formatter: erpPriceInputFormatter, - disabled: true, - style: { width: '100%' }, - }, - fieldName: 'totalPrice', - label: '合计金额', - }, ]; } @@ -296,28 +271,6 @@ export function useGridColumns(): VxeTableGridOptions['columns'] { title: '创建人', minWidth: 100, }, - { - field: 'totalCount', - title: '数量', - minWidth: 100, - cellRender: { - name: 'CellAmount', - props: { - digits: 2, - }, - }, - }, - { - field: 'totalPrice', - title: '金额', - minWidth: 120, - cellRender: { - name: 'CellAmount', - props: { - digits: 2, - }, - }, - }, { field: 'status', title: '状态', diff --git a/apps/web-antd/src/views/erp/stock/in/modules/StockInItemForm.vue b/apps/web-antd/src/views/erp/stock/in/modules/StockInItemForm.vue index 159e4e4a5..fd5f10a44 100644 --- a/apps/web-antd/src/views/erp/stock/in/modules/StockInItemForm.vue +++ b/apps/web-antd/src/views/erp/stock/in/modules/StockInItemForm.vue @@ -19,11 +19,7 @@ const props = withDefaults(defineProps(), { disabled: false, }); -const emit = defineEmits([ - 'update:items', - 'update:total-count', - 'update:total-price', -]); +const emit = defineEmits(['update:items']); interface Props { items?: ErpStockInApi.StockInItem[]; @@ -58,6 +54,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ enabled: false, }, showFooter: true, + footerCellClassName: 'stock-in-footer-cell', footerMethod: ({ columns }) => { const footers: any[][] = []; const sums = getSummaries(); @@ -96,31 +93,6 @@ watch( }, ); -/** 计算 totalCount、totalPrice */ -watch( - () => tableData.value, - () => { - if (!tableData.value || tableData.value.length === 0) { - emit('update:total-count', 0); - emit('update:total-price', 0); - return; - } - const totalCount = tableData.value.reduce( - (prev, curr) => prev + (curr.count || 0), - 0, - ); - const totalPrice = tableData.value.reduce( - (prev, curr) => prev + (curr.totalPrice || 0), - 0, - ); - - // 发送计算结果给父组件 - emit('update:total-count', totalCount); - emit('update:total-price', totalPrice); - }, - { deep: true }, -); - /** 初始化 */ onMounted(async () => { productOptions.value = await getProductSimpleList(); @@ -260,23 +232,14 @@ function init(items: ErpStockInApi.StockInItem[]) { defineExpose({ validate, init, + handleAdd, }); + + + + diff --git a/apps/web-antd/src/views/erp/stock/in/modules/form.vue b/apps/web-antd/src/views/erp/stock/in/modules/form.vue index 108ef2600..2f09d5215 100644 --- a/apps/web-antd/src/views/erp/stock/in/modules/form.vue +++ b/apps/web-antd/src/views/erp/stock/in/modules/form.vue @@ -49,24 +49,6 @@ const handleUpdateItems = (items: ErpStockInApi.StockInItem[]) => { } }; -const handleUpdateTotalCount = (totalCount: number) => { - if (formData.value) { - formData.value.totalCount = totalCount; - formApi.setValues({ - totalCount: formData.value.totalCount, - }); - } -}; - -const handleUpdateTotalPrice = (totalPrice: number) => { - if (formData.value) { - formData.value.totalPrice = totalPrice; - formApi.setValues({ - totalPrice: formData.value.totalPrice, - }); - } -}; - /** * 创建或更新其它入库单 */ @@ -145,6 +127,10 @@ const [Modal, modalApi] = useVbenModal({ if (itemFormInstance && typeof itemFormInstance.init === 'function') { itemFormInstance.init([]); } + // 如果是新增,自动添加一行 + if (formType.value === 'create' && itemFormInstance) { + itemFormInstance.handleAdd(); + } return; } @@ -209,8 +195,6 @@ defineExpose({ modalApi, handleUpdateStatus }); :items="formData?.items ?? []" :disabled="formType === 'detail'" @update:items="handleUpdateItems" - @update:total-count="handleUpdateTotalCount" - @update:total-price="handleUpdateTotalPrice" /> -- Gitee From 9d80b9fc7147a16483775925e27d778554010395 Mon Sep 17 00:00:00 2001 From: nehc <934298133@qq.com> Date: Fri, 1 Aug 2025 18:22:51 +0800 Subject: [PATCH 6/8] =?UTF-8?q?feat(@vben/web-antd):=20erp-stock-in=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=85=A5=E5=BA=93=E5=8D=95=E4=BA=A7=E5=93=81?= =?UTF-8?q?=E6=B8=85=E5=8D=95=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web-antd/src/views/erp/stock/in/index.vue | 8 ++--- .../erp/stock/in/modules/StockInItemForm.vue | 26 ++++---------- .../src/views/erp/stock/in/modules/form.vue | 34 ------------------- 3 files changed, 10 insertions(+), 58 deletions(-) diff --git a/apps/web-antd/src/views/erp/stock/in/index.vue b/apps/web-antd/src/views/erp/stock/in/index.vue index 8bb4c15d8..55891fa95 100644 --- a/apps/web-antd/src/views/erp/stock/in/index.vue +++ b/apps/web-antd/src/views/erp/stock/in/index.vue @@ -169,19 +169,19 @@ const [Grid, gridApi] = useVbenVxeGrid({ :actions="[ { label: '详情', + icon: ACTION_ICON.VIEW, auth: ['erp:stock-in:query'], onClick: () => openForm('detail', row.id), }, { label: '编辑', - type: 'primary', auth: ['erp:stock-in:update'], - ifShow: row.status === 10, + icon: ACTION_ICON.EDIT, + disabled: row.status !== 10, onClick: () => openForm('update', row.id), }, { label: '审核', - type: 'primary', auth: ['erp:stock-in:update'], ifShow: row.status === 10, popConfirm: { @@ -203,7 +203,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ label: '删除', danger: true, auth: ['erp:stock-in:delete'], - ifShow: row.status === 10, + disabled: row.status !== 10, popConfirm: { title: '确认要删除该入库单吗?', confirm: () => handleDelete([row.id]), diff --git a/apps/web-antd/src/views/erp/stock/in/modules/StockInItemForm.vue b/apps/web-antd/src/views/erp/stock/in/modules/StockInItemForm.vue index fd5f10a44..b35ff3146 100644 --- a/apps/web-antd/src/views/erp/stock/in/modules/StockInItemForm.vue +++ b/apps/web-antd/src/views/erp/stock/in/modules/StockInItemForm.vue @@ -246,41 +246,27 @@ defineExpose({ - - - -- Gitee From 5f56b1473357597d1ec8bcc669cb7a33df5843de Mon Sep 17 00:00:00 2001 From: nehc <934298133@qq.com> Date: Sat, 2 Aug 2025 21:21:51 +0800 Subject: [PATCH 7/8] =?UTF-8?q?feat(@vben/web-antd):=20=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 isValidating 状态管理,用于控制验证过程 - 在表格列定义中增加验证错误样式 - 实现必填字段错误提示功能 - 优化表格渲染逻辑,确保验证错误及时显示 - 新增相关 CSS 样式,定义验证错误的视觉效果 --- apps/web-antd/src/views/erp/stock/in/data.ts | 19 +++++++++++++- .../erp/stock/in/modules/StockInItemForm.vue | 24 ++++++++++++++++- .../effects/plugins/src/vxe-table/style.css | 26 +++++++++++++++++++ 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/apps/web-antd/src/views/erp/stock/in/data.ts b/apps/web-antd/src/views/erp/stock/in/data.ts index 7111cae9c..ad981befd 100644 --- a/apps/web-antd/src/views/erp/stock/in/data.ts +++ b/apps/web-antd/src/views/erp/stock/in/data.ts @@ -98,7 +98,9 @@ export function useFormSchema(): VbenFormSchema[] { } /** 入库产品清单表格列定义 */ -export function useStockInItemTableColumns(): VxeTableGridOptions['columns'] { +export function useStockInItemTableColumns( + isValidating?: any, +): VxeTableGridOptions['columns'] { return [ { type: 'seq', title: '序号', minWidth: 50, fixed: 'left' }, { @@ -106,12 +108,22 @@ export function useStockInItemTableColumns(): VxeTableGridOptions['columns'] { title: '仓库名称', minWidth: 150, slots: { default: 'warehouseId' }, + className: ({ row }: { row: any }) => { + return isValidating?.value && !row.warehouseId + ? 'required-field-error' + : ''; + }, }, { field: 'productId', title: '产品名称', minWidth: 200, slots: { default: 'productId' }, + className: ({ row }: { row: any }) => { + return isValidating?.value && !row.productId + ? 'required-field-error' + : ''; + }, }, { field: 'stockCount', @@ -133,6 +145,11 @@ export function useStockInItemTableColumns(): VxeTableGridOptions['columns'] { title: '数量', minWidth: 120, slots: { default: 'count' }, + className: ({ row }: { row: any }) => { + return isValidating?.value && (!row.count || row.count <= 0) + ? 'required-field-error' + : ''; + }, }, { field: 'productPrice', diff --git a/apps/web-antd/src/views/erp/stock/in/modules/StockInItemForm.vue b/apps/web-antd/src/views/erp/stock/in/modules/StockInItemForm.vue index b35ff3146..c1275a33c 100644 --- a/apps/web-antd/src/views/erp/stock/in/modules/StockInItemForm.vue +++ b/apps/web-antd/src/views/erp/stock/in/modules/StockInItemForm.vue @@ -29,6 +29,7 @@ interface Props { const tableData = ref([]); const productOptions = ref([]); const warehouseOptions = ref([]); +const isValidating = ref(false); /** 表格配置 */ const [Grid, gridApi] = useVbenVxeGrid({ @@ -37,7 +38,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ trigger: 'click', mode: 'cell', }, - columns: useStockInItemTableColumns(), + columns: useStockInItemTableColumns(isValidating), data: tableData.value, border: true, showOverflow: true, @@ -116,6 +117,10 @@ function handleAdd() { tableData.value.push(newRow); gridApi.grid.insertAt(newRow, -1); emit('update:items', [...tableData.value]); + // 触发表格重新渲染以更新cellClassName + nextTick(() => { + gridApi.grid.refreshColumn(); + }); } function handleDelete(row: ErpStockInApi.StockInItem) { @@ -182,6 +187,10 @@ function handleUpdateValue(row: any) { tableData.value[index] = row; } emit('update:items', [...tableData.value]); + // 触发表格重新渲染以更新cellClassName + nextTick(() => { + gridApi.grid.refreshColumn(); + }); } const getSummaries = (): { @@ -200,6 +209,13 @@ const getSummaries = (): { /** 验证表单 */ function validate(): Promise { return new Promise((resolve) => { + isValidating.value = true; + + // 触发表格重新渲染以显示验证错误 + nextTick(() => { + gridApi.grid.refreshColumn(); + }); + // 验证是否有产品清单 if (!tableData.value || tableData.value.length === 0) { resolve(false); @@ -219,6 +235,12 @@ function validate(): Promise { } } + // 验证通过,清除验证状态 + isValidating.value = false; + nextTick(() => { + gridApi.grid.refreshColumn(); + }); + resolve(true); }); } diff --git a/packages/effects/plugins/src/vxe-table/style.css b/packages/effects/plugins/src/vxe-table/style.css index 5b47fa2cf..152fcf219 100644 --- a/packages/effects/plugins/src/vxe-table/style.css +++ b/packages/effects/plugins/src/vxe-table/style.css @@ -115,3 +115,29 @@ .vxe-grid--layout-body-content-wrapper { overflow: hidden; } + +/* 必填字段错误样式 */ +.vxe-table .required-field-error::after { + position: absolute; + top: -1px; + right: -1px; + z-index: 10; + padding: 1px 4px; + font-size: 10px; + line-height: 1; + color: white; + content: '必填'; + background-color: #ff4d4f; + border-radius: 0 0 0 4px; +} + +/* 必填字段内的输入框样式 */ +.vxe-table .required-field-error .ant-select, +.vxe-table .required-field-error .ant-input-number, +.vxe-table .required-field-error .ant-input { + border-color: #ff4d4f !important; +} + +.vxe-table .required-field-error .ant-select .ant-select-selector { + border-color: #ff4d4f !important; +} -- Gitee From c64be886b4e6b964a86f826b255963ede6e5e163 Mon Sep 17 00:00:00 2001 From: nehc <934298133@qq.com> Date: Sat, 2 Aug 2025 23:28:59 +0800 Subject: [PATCH 8/8] =?UTF-8?q?feat(@vben/web-antd):=20vxe-table)=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E8=A1=A8=E5=8D=95=E9=AA=8C=E8=AF=81=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 vxe-table.ts 中添加 createRequiredValidation函数 - 在 data.ts 中使用 createRequiredValidation 替代原有的 className 函数 - 在 vxe-table 插件中添加 validation 相关的工具函数 - 优化表格列的验证逻辑,提高代码复用性和可维护性 --- apps/web-antd/src/adapter/vxe-table.ts | 3 +- apps/web-antd/src/views/erp/stock/in/data.ts | 19 ++---- .../effects/plugins/src/vxe-table/index.ts | 3 +- .../plugins/src/vxe-table/validation.ts | 61 +++++++++++++++++++ 4 files changed, 69 insertions(+), 17 deletions(-) create mode 100644 packages/effects/plugins/src/vxe-table/validation.ts diff --git a/apps/web-antd/src/adapter/vxe-table.ts b/apps/web-antd/src/adapter/vxe-table.ts index 69f855503..e28a6ae1d 100644 --- a/apps/web-antd/src/adapter/vxe-table.ts +++ b/apps/web-antd/src/adapter/vxe-table.ts @@ -7,6 +7,7 @@ import { IconifyIcon } from '@vben/icons'; import { $te } from '@vben/locales'; import { AsyncComponents, + createRequiredValidation, setupVbenVxeTable, useVbenVxeGrid, } from '@vben/plugins/vxe-table'; @@ -354,7 +355,7 @@ setupVbenVxeTable({ useVbenForm, }); -export { useVbenVxeGrid }; +export { createRequiredValidation, useVbenVxeGrid }; const [VxeTable, VxeColumn, VxeToolbar] = AsyncComponents; export { VxeColumn, VxeTable, VxeToolbar }; diff --git a/apps/web-antd/src/views/erp/stock/in/data.ts b/apps/web-antd/src/views/erp/stock/in/data.ts index ad981befd..68b667fc9 100644 --- a/apps/web-antd/src/views/erp/stock/in/data.ts +++ b/apps/web-antd/src/views/erp/stock/in/data.ts @@ -1,6 +1,7 @@ import type { VbenFormSchema } from '#/adapter/form'; import type { VxeTableGridOptions } from '#/adapter/vxe-table'; +import { createRequiredValidation } from '#/adapter/vxe-table'; import { getSupplierSimpleList } from '#/api/erp/purchase/supplier'; import { getSimpleUserList } from '#/api/system/user'; import { DICT_TYPE, getDictOptions } from '#/utils'; @@ -108,22 +109,14 @@ export function useStockInItemTableColumns( title: '仓库名称', minWidth: 150, slots: { default: 'warehouseId' }, - className: ({ row }: { row: any }) => { - return isValidating?.value && !row.warehouseId - ? 'required-field-error' - : ''; - }, + className: createRequiredValidation(isValidating, 'warehouseId'), }, { field: 'productId', title: '产品名称', minWidth: 200, slots: { default: 'productId' }, - className: ({ row }: { row: any }) => { - return isValidating?.value && !row.productId - ? 'required-field-error' - : ''; - }, + className: createRequiredValidation(isValidating, 'productId'), }, { field: 'stockCount', @@ -145,11 +138,7 @@ export function useStockInItemTableColumns( title: '数量', minWidth: 120, slots: { default: 'count' }, - className: ({ row }: { row: any }) => { - return isValidating?.value && (!row.count || row.count <= 0) - ? 'required-field-error' - : ''; - }, + className: createRequiredValidation(isValidating, 'count'), }, { field: 'productPrice', diff --git a/packages/effects/plugins/src/vxe-table/index.ts b/packages/effects/plugins/src/vxe-table/index.ts index 70f4cfa5c..8cc12bef7 100644 --- a/packages/effects/plugins/src/vxe-table/index.ts +++ b/packages/effects/plugins/src/vxe-table/index.ts @@ -1,8 +1,9 @@ export { AsyncComponents, setupVbenVxeTable } from './init'; export type { VxeTableGridOptions } from './types'; export * from './use-vxe-grid'; - export { default as VbenVxeGrid } from './use-vxe-grid.vue'; + +export * from './validation'; export type { VxeGridListeners, VxeGridProps, diff --git a/packages/effects/plugins/src/vxe-table/validation.ts b/packages/effects/plugins/src/vxe-table/validation.ts new file mode 100644 index 000000000..487f24107 --- /dev/null +++ b/packages/effects/plugins/src/vxe-table/validation.ts @@ -0,0 +1,61 @@ +/** + * 创建验证类名的工具函数 + * @param isValidating 验证状态 + * @param fieldName 字段名 + * @param validationRules 验证规则,可以是字符串或自定义函数 + * @returns 返回 className 函数 + */ +function createValidationClassName( + isValidating: any, + fieldName: string, + validationRules: ((row: any) => boolean) | string, +) { + return ({ row }: { row: any }) => { + if (!isValidating?.value) return ''; + + let isValid = true; + if (typeof validationRules === 'string') { + // 处理简单的验证规则 + if (validationRules === 'required') { + isValid = + fieldName === 'count' + ? row[fieldName] && row[fieldName] > 0 + : !!row[fieldName]; + } + } else if (typeof validationRules === 'function') { + // 处理自定义验证函数 + isValid = validationRules(row); + } + + return isValid ? '' : 'required-field-error'; + }; +} + +/** + * 创建必填字段验证 + * @param isValidating 验证状态 + * @param fieldName 字段名 + * @returns 返回 className 函数 + */ +function createRequiredValidation(isValidating: any, fieldName: string) { + return createValidationClassName(isValidating, fieldName, 'required'); +} + +/** + * 创建自定义验证 + * @param isValidating 验证状态 + * @param validationFn 自定义验证函数 + * @returns 返回 className 函数 + */ +function createCustomValidation( + isValidating: any, + validationFn: (row: any) => boolean, +) { + return createValidationClassName(isValidating, '', validationFn); +} + +export { + createCustomValidation, + createRequiredValidation, + createValidationClassName, +}; -- Gitee