feat(@vben/web-antd): 验证样式

- 添加 isValidating 状态管理,用于控制验证过程
- 在表格列定义中增加验证错误样式
- 实现必填字段错误提示功能
- 优化表格渲染逻辑,确保验证错误及时显示
- 新增相关 CSS 样式,定义验证错误的视觉效果
pull/188/head
nehc 2025-08-02 21:21:51 +08:00
parent 9d80b9fc71
commit 5f56b14733
3 changed files with 67 additions and 2 deletions

View File

@ -98,7 +98,9 @@ export function useFormSchema(): VbenFormSchema[] {
} }
/** 入库产品清单表格列定义 */ /** 入库产品清单表格列定义 */
export function useStockInItemTableColumns(): VxeTableGridOptions['columns'] { export function useStockInItemTableColumns(
isValidating?: any,
): VxeTableGridOptions['columns'] {
return [ return [
{ type: 'seq', title: '序号', minWidth: 50, fixed: 'left' }, { type: 'seq', title: '序号', minWidth: 50, fixed: 'left' },
{ {
@ -106,12 +108,22 @@ export function useStockInItemTableColumns(): VxeTableGridOptions['columns'] {
title: '仓库名称', title: '仓库名称',
minWidth: 150, minWidth: 150,
slots: { default: 'warehouseId' }, slots: { default: 'warehouseId' },
className: ({ row }: { row: any }) => {
return isValidating?.value && !row.warehouseId
? 'required-field-error'
: '';
},
}, },
{ {
field: 'productId', field: 'productId',
title: '产品名称', title: '产品名称',
minWidth: 200, minWidth: 200,
slots: { default: 'productId' }, slots: { default: 'productId' },
className: ({ row }: { row: any }) => {
return isValidating?.value && !row.productId
? 'required-field-error'
: '';
},
}, },
{ {
field: 'stockCount', field: 'stockCount',
@ -133,6 +145,11 @@ export function useStockInItemTableColumns(): VxeTableGridOptions['columns'] {
title: '数量', title: '数量',
minWidth: 120, minWidth: 120,
slots: { default: 'count' }, slots: { default: 'count' },
className: ({ row }: { row: any }) => {
return isValidating?.value && (!row.count || row.count <= 0)
? 'required-field-error'
: '';
},
}, },
{ {
field: 'productPrice', field: 'productPrice',

View File

@ -29,6 +29,7 @@ interface Props {
const tableData = ref<ErpStockInApi.StockInItem[]>([]); const tableData = ref<ErpStockInApi.StockInItem[]>([]);
const productOptions = ref<any[]>([]); const productOptions = ref<any[]>([]);
const warehouseOptions = ref<any[]>([]); const warehouseOptions = ref<any[]>([]);
const isValidating = ref(false);
/** 表格配置 */ /** 表格配置 */
const [Grid, gridApi] = useVbenVxeGrid({ const [Grid, gridApi] = useVbenVxeGrid({
@ -37,7 +38,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
trigger: 'click', trigger: 'click',
mode: 'cell', mode: 'cell',
}, },
columns: useStockInItemTableColumns(), columns: useStockInItemTableColumns(isValidating),
data: tableData.value, data: tableData.value,
border: true, border: true,
showOverflow: true, showOverflow: true,
@ -116,6 +117,10 @@ function handleAdd() {
tableData.value.push(newRow); tableData.value.push(newRow);
gridApi.grid.insertAt(newRow, -1); gridApi.grid.insertAt(newRow, -1);
emit('update:items', [...tableData.value]); emit('update:items', [...tableData.value]);
// cellClassName
nextTick(() => {
gridApi.grid.refreshColumn();
});
} }
function handleDelete(row: ErpStockInApi.StockInItem) { function handleDelete(row: ErpStockInApi.StockInItem) {
@ -182,6 +187,10 @@ function handleUpdateValue(row: any) {
tableData.value[index] = row; tableData.value[index] = row;
} }
emit('update:items', [...tableData.value]); emit('update:items', [...tableData.value]);
// cellClassName
nextTick(() => {
gridApi.grid.refreshColumn();
});
} }
const getSummaries = (): { const getSummaries = (): {
@ -200,6 +209,13 @@ const getSummaries = (): {
/** 验证表单 */ /** 验证表单 */
function validate(): Promise<boolean> { function validate(): Promise<boolean> {
return new Promise((resolve) => { return new Promise((resolve) => {
isValidating.value = true;
//
nextTick(() => {
gridApi.grid.refreshColumn();
});
// //
if (!tableData.value || tableData.value.length === 0) { if (!tableData.value || tableData.value.length === 0) {
resolve(false); resolve(false);
@ -219,6 +235,12 @@ function validate(): Promise<boolean> {
} }
} }
//
isValidating.value = false;
nextTick(() => {
gridApi.grid.refreshColumn();
});
resolve(true); resolve(true);
}); });
} }

View File

@ -115,3 +115,29 @@
.vxe-grid--layout-body-content-wrapper { .vxe-grid--layout-body-content-wrapper {
overflow: hidden; 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;
}