From 5ed75adf5871f93c682eabe15cf03718734665fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=98=BF=E8=8F=9C=20Cai?= Date: Mon, 10 Nov 2025 15:39:02 +0800 Subject: [PATCH 1/4] fix(form): add `success` validation type to `setValidateMessage` --- packages/components/common.ts | 6 +- packages/components/form/form-item.tsx | 85 +++++++++++++++----------- packages/components/form/form.en-US.md | 2 +- packages/components/form/form.md | 2 +- packages/components/form/type.ts | 4 +- 5 files changed, 57 insertions(+), 42 deletions(-) diff --git a/packages/components/common.ts b/packages/components/common.ts index 2a381a710f..b593c98fe9 100644 --- a/packages/components/common.ts +++ b/packages/components/common.ts @@ -41,9 +41,6 @@ export interface UploadDisplayDragEvents { export type ImageEvent = Event; -/** - * 通用全局类型 - * */ export type PlainObject = { [key: string]: any }; export type OptionData = { @@ -63,6 +60,9 @@ export type TreeOptionData = { content?: string | TNode; } & PlainObject; +/** + * 通用全局类型 + * */ export type SizeEnum = 'small' | 'medium' | 'large'; export type ShapeEnum = 'circle' | 'round'; diff --git a/packages/components/form/form-item.tsx b/packages/components/form/form-item.tsx index 50f446d724..2b7761d0ae 100644 --- a/packages/components/form/form-item.tsx +++ b/packages/components/form/form-item.tsx @@ -1,3 +1,19 @@ +import { + cloneDeep, + isArray, + isBoolean, + isNil, + isNumber, + isString, + get as lodashGet, + set as lodashSet, +} from 'lodash-es'; +import { + GlobalIconType, + CheckCircleFilledIcon as TdCheckCircleFilledIcon, + CloseCircleFilledIcon as TdCloseCircleFilledIcon, + ErrorCircleFilledIcon as TdErrorCircleFilledIcon, +} from 'tdesign-icons-vue-next'; import { computed, defineComponent, @@ -12,34 +28,7 @@ import { VNode, watch, } from 'vue'; -import { - CheckCircleFilledIcon as TdCheckCircleFilledIcon, - CloseCircleFilledIcon as TdCloseCircleFilledIcon, - ErrorCircleFilledIcon as TdErrorCircleFilledIcon, - GlobalIconType, -} from 'tdesign-icons-vue-next'; -import { - isNil, - isArray, - isNumber, - isString, - isBoolean, - cloneDeep, - get as lodashGet, - set as lodashSet, -} from 'lodash-es'; -import { validate } from './utils/form-model'; -import { - AllValidateResult, - Data, - FormErrorMessage, - FormItemValidateMessage, - FormRule, - ValidateTriggerType, - ValueType, -} from './type'; -import props from './form-item-props'; import { AnalysisValidateResult, ErrorListType, @@ -50,10 +39,21 @@ import { useCLASSNAMES, ValidateStatus, } from './consts'; +import props from './form-item-props'; +import { + AllValidateResult, + Data, + FormErrorMessage, + FormItemValidateMessage, + FormRule, + ValidateTriggerType, + ValueType, +} from './type'; +import { validate } from './utils/form-model'; -import { useConfig, useTNodeJSX, useGlobalIcon, usePrefixClass } from '@tdesign/shared-hooks'; -import { getFormItemClassName } from './utils'; import { template } from '@tdesign/common-js/utils/stringTemplate'; +import { useConfig, useGlobalIcon, usePrefixClass, useTNodeJSX } from '@tdesign/shared-hooks'; +import { getFormItemClassName } from './utils'; export type FormItemValidateResult = { [key in keyof T]: boolean | AllValidateResult[] }; @@ -164,7 +164,7 @@ export default defineComponent({ /** Suffix Icon END */ /** Content Style */ - const errorClasses = computed(() => { + const statusClasses = computed(() => { if (!showErrorMessage.value) return ''; if (verifyStatus.value === ValidateStatus.SUCCESS) { return props.successBorder @@ -176,7 +176,7 @@ export default defineComponent({ if (props.status) return statusClass.value; return type === 'error' ? CLASS_NAMES.value.error : CLASS_NAMES.value.warning; }); - const contentClasses = computed(() => [CLASS_NAMES.value.controls, errorClasses.value]); + const contentClasses = computed(() => [CLASS_NAMES.value.controls, statusClasses.value]); const contentStyle = computed(() => { let contentStyle = {}; if (labelWidth.value && labelAlign.value !== 'top') { @@ -322,13 +322,28 @@ export default defineComponent({ }; const setValidateMessage = (validateMessage: FormItemValidateMessage[]) => { - if (!validateMessage && !isArray(validateMessage)) return; + if (!validateMessage || !isArray(validateMessage)) return; + errorList.value = []; + successList.value = []; if (validateMessage.length === 0) { - errorList.value = []; verifyStatus.value = ValidateStatus.SUCCESS; + return; } - errorList.value = validateMessage.map((item) => ({ ...item, result: false })); - verifyStatus.value = ValidateStatus.FAIL; + const errors = validateMessage.filter( + (item) => item.type === 'error' || item.type === 'warning', + ) as FormItemValidateMessage[]; + const successes = validateMessage.filter((item) => item.type === 'success') as FormItemValidateMessage[]; + errorList.value = errors.map((item) => ({ + message: item.message, + type: item.type as 'error' | 'warning', + result: false, + })); + successList.value = successes.map((item) => ({ + message: item.message, + type: item.type as 'success', + result: true, + })); + verifyStatus.value = errors.length > 0 ? ValidateStatus.FAIL : ValidateStatus.SUCCESS; }; const value = computed(() => form?.data && lodashGet(form?.data, props.name)); diff --git a/packages/components/form/form.en-US.md b/packages/components/form/form.en-US.md index d15bfd4f0d..deb04dc42c 100644 --- a/packages/components/form/form.en-US.md +++ b/packages/components/form/form.en-US.md @@ -42,7 +42,7 @@ name | params | return | description -- | -- | -- | -- clearValidate | `(fields?: Array)` | \- | required reset | `(params?: FormResetParams)` | \- | required。[see more ts definition](https://github.com/Tencent/tdesign-vue-next/blob/develop/packages/components/form/type.ts)。
`interface FormResetParams { type?: 'initial' \| 'empty'; fields?: Array }`
-setValidateMessage | `(message: FormValidateMessage)` | \- | required。[see more ts definition](https://github.com/Tencent/tdesign-vue-next/blob/develop/packages/components/form/type.ts)。
`type FormValidateMessage = { [field in keyof FormData]: FormItemValidateMessage[] }`

`interface FormItemValidateMessage { type: 'warning' \| 'error'; message: string }`
+setValidateMessage | `(message: FormValidateMessage)` | \- | required。Sets custom validation results, such as directly displaying remote validation messages. Note: This method must be called after the component is mounted. `FormData` refers to the generic type of form data。[see more ts definition](https://github.com/Tencent/tdesign-vue-next/blob/develop/packages/components/form/type.ts)。
`type FormValidateMessage = { [field in keyof FormData]: FormItemValidateMessage[] }`

`interface FormItemValidateMessage { type: 'warning' \| 'error' \| 'success'; message: string }`
submit | `(params?: { showErrorMessage?: boolean })` | \- | required validate | `(params?: FormValidateParams)` | `Promise>` | required。[see more ts definition](https://github.com/Tencent/tdesign-vue-next/blob/develop/packages/components/form/type.ts)。
`interface FormValidateParams { fields?: Array; showErrorMessage?: boolean; trigger?: ValidateTriggerType }`

`type ValidateTriggerType = 'blur' \| 'change' \| 'submit' \| 'all'`
validateOnly | `(params?: Pick)` | `Promise>` | required diff --git a/packages/components/form/form.md b/packages/components/form/form.md index 0f9c978c05..df907c3551 100644 --- a/packages/components/form/form.md +++ b/packages/components/form/form.md @@ -44,7 +44,7 @@ validate | `(result: ValidateResultContext)` | 校验结束后触发 -- | -- | -- | -- clearValidate | `(fields?: Array)` | \- | 必需。清空校验结果。可使用 fields 指定清除部分字段的校验结果,fields 值为空则表示清除所有字段校验结果。清除邮箱校验结果示例:`clearValidate(['email'])` reset | `(params?: FormResetParams)` | \- | 必需。重置表单,表单里面没有重置按钮`