feat(@vben/web-antd): 验证样式
- 添加 isValidating 状态管理,用于控制验证过程 - 在表格列定义中增加验证错误样式 - 实现必填字段错误提示功能 - 优化表格渲染逻辑,确保验证错误及时显示 - 新增相关 CSS 样式,定义验证错误的视觉效果pull/188/head
parent
9d80b9fc71
commit
5f56b14733
|
@ -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',
|
||||||
|
|
|
@ -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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue