From 2a21018544d63e96e2794ac35b3c3399cda86782 Mon Sep 17 00:00:00 2001 From: zly Date: Fri, 29 May 2026 11:02:43 +0800 Subject: [PATCH] =?UTF-8?q?feat(componentList):=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E8=A1=A8=E5=8D=95=E6=A0=A1=E9=AA=8C=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../componentList/addApiModal.tsx | 18 ++- .../componentList/editableTable.tsx | 114 +++++++++++++++--- 2 files changed, 113 insertions(+), 19 deletions(-) diff --git a/src/pages/componentDevelopment/componentList/addApiModal.tsx b/src/pages/componentDevelopment/componentList/addApiModal.tsx index 35334ce..7247996 100644 --- a/src/pages/componentDevelopment/componentList/addApiModal.tsx +++ b/src/pages/componentDevelopment/componentList/addApiModal.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect } from 'react'; import { Modal, Form, Input, Message } from '@arco-design/web-react'; -import EditableTable from '@/pages/componentDevelopment/componentList/editableTable'; +import EditableTable, { validateEditableTableData } from '@/pages/componentDevelopment/componentList/editableTable'; import { updateComponentDesign } from '@/api/componentDevelopProcess'; const FormItem = Form.Item; @@ -18,10 +18,12 @@ const AddApiModal = ({ const [form] = Form.useForm(); const [parametersData, setParametersData] = useState([]); const [responsesData, setResponsesData] = useState([]); + const [showTableValidationErrors, setShowTableValidationErrors] = useState(false); // 当 visible 或 componentDesignProgress 变化时,设置表单初始值 useEffect(() => { if (visible && componentDesignProgress) { + setShowTableValidationErrors(false); // 设置表单字段值 form.setFieldsValue({ ident: componentDesignProgress.ident || '', @@ -51,6 +53,7 @@ const AddApiModal = ({ } } else if (visible) { + setShowTableValidationErrors(false); // 重置表单和表格数据 form.resetFields(); setParametersData([]); @@ -62,6 +65,15 @@ const AddApiModal = ({ try { await form.validate(); const formData = form.getFields(); + const parametersValidation = validateEditableTableData(parametersData); + const responsesValidation = validateEditableTableData(responsesData); + + if (!parametersValidation.valid || !responsesValidation.valid) { + setShowTableValidationErrors(true); + const firstError = parametersValidation.errors[0] || responsesValidation.errors[0]; + Message.error(firstError || '请检查参数填写是否正确'); + return; + } // 构造要提交的数据 const params = { @@ -170,6 +182,7 @@ const AddApiModal = ({ onDataUpdate={setParametersData} initialData={componentDesignProgress?.parameters || []} visible={visible} + showValidationErrors={showTableValidationErrors} /> @@ -177,6 +190,7 @@ const AddApiModal = ({ onDataUpdate={setResponsesData} initialData={componentDesignProgress?.responses || []} visible={visible} + showValidationErrors={showTableValidationErrors} /> @@ -184,4 +198,4 @@ const AddApiModal = ({ ); }; -export default AddApiModal; \ No newline at end of file +export default AddApiModal; diff --git a/src/pages/componentDevelopment/componentList/editableTable.tsx b/src/pages/componentDevelopment/componentList/editableTable.tsx index 916b361..ea91a89 100644 --- a/src/pages/componentDevelopment/componentList/editableTable.tsx +++ b/src/pages/componentDevelopment/componentList/editableTable.tsx @@ -22,20 +22,70 @@ const arrayTypeOptions = [ { label: 'OBJECT', value: 'OBJECT' } ]; -function EditableCell({ value, onChange, columnType, record, dataIndex }) { +const isEmptyValue = (value) => value === undefined || value === null || `${value}`.trim() === ''; + +const getFieldError = (record, dataIndex) => { + if (dataIndex === 'ident' && isEmptyValue(record.ident)) { + return '请输入名称'; + } + + if (dataIndex === 'type' && isEmptyValue(record.type)) { + return '请选择数据类型'; + } + + if (dataIndex === 'generic' && record.type === 'ARRAY' && isEmptyValue(record.generic)) { + return '请选择数组类型'; + } + + return ''; +}; + +export const validateEditableTableData = (tableData = []) => { + const errors = []; + + tableData.forEach((item, index) => { + const rowIndex = index + 1; + + if (isEmptyValue(item.ident)) { + errors.push(`第${rowIndex}行请输入名称`); + } + + if (isEmptyValue(item.type)) { + errors.push(`第${rowIndex}行请选择数据类型`); + } + + if (item.type === 'ARRAY' && isEmptyValue(item.generic)) { + errors.push(`第${rowIndex}行请选择数组类型`); + } + }); + + return { + valid: errors.length === 0, + errors + }; +}; + +function EditableCell({ value, onChange, columnType, record, dataIndex, showError, onBlur }) { const [error, setError] = useState(''); + const requiredError = getFieldError(record, dataIndex); + const mergedError = error || (showError ? requiredError : ''); // 对于数组类型字段的特殊处理 if (dataIndex === 'generic') { // 仅当数据类型为 ARRAY 时才可编辑 if (record.type === 'ARRAY') { return ( - + {mergedError &&
{mergedError}
} + ); } else { @@ -64,10 +114,11 @@ function EditableCell({ value, onChange, columnType, record, dataIndex }) { - {error &&
{error}
} + {mergedError &&
{mergedError}
} ); } @@ -76,6 +127,7 @@ function EditableCell({ value, onChange, columnType, record, dataIndex }) { ); @@ -83,20 +135,39 @@ function EditableCell({ value, onChange, columnType, record, dataIndex }) { if (columnType === 'select') { return ( - + {mergedError &&
{mergedError}
} + ); } return {value}; } -function EditableTable({ onDataUpdate, initialData = [], visible }) { +function EditableTable({ onDataUpdate, initialData = [], visible, showValidationErrors = false }) { const [data, setData] = useState([]); + const [touchedFields, setTouchedFields] = useState({}); + + const getFieldKey = (key, dataIndex) => `${key}-${dataIndex}`; + + const markFieldTouched = (key, dataIndex) => { + setTouchedFields(prev => ({ + ...prev, + [getFieldKey(key, dataIndex)]: true + })); + }; + + const shouldShowFieldError = (record, dataIndex) => { + return showValidationErrors || touchedFields[getFieldKey(record.key, dataIndex)]; + }; // 当初始数据变化时,更新表格数据 useEffect(() => { @@ -112,6 +183,7 @@ function EditableTable({ onDataUpdate, initialData = [], visible }) { useEffect(() => { if (!visible) setData([]); + if (!visible) setTouchedFields({}); }, [visible]); const handleValueChange = (key, dataIndex, value) => { @@ -144,6 +216,8 @@ function EditableTable({ onDataUpdate, initialData = [], visible }) { columnType="input" record={record} dataIndex="ident" + showError={shouldShowFieldError(record, 'ident')} + onBlur={() => markFieldTouched(record.key, 'ident')} /> ) }, @@ -157,6 +231,8 @@ function EditableTable({ onDataUpdate, initialData = [], visible }) { columnType="select" record={record} dataIndex="type" + showError={shouldShowFieldError(record, 'type')} + onBlur={() => markFieldTouched(record.key, 'type')} /> ) }, @@ -170,6 +246,8 @@ function EditableTable({ onDataUpdate, initialData = [], visible }) { columnType="select" record={record} dataIndex="generic" + showError={shouldShowFieldError(record, 'generic')} + onBlur={() => markFieldTouched(record.key, 'generic')} /> ) }, @@ -183,6 +261,8 @@ function EditableTable({ onDataUpdate, initialData = [], visible }) { columnType="input" record={record} dataIndex="desc" + showError={false} + onBlur={() => markFieldTouched(record.key, 'desc')} /> ) }, @@ -239,4 +319,4 @@ function EditableTable({ onDataUpdate, initialData = [], visible }) { ); } -export default EditableTable; \ No newline at end of file +export default EditableTable;