fix(form): 优化可选项校验建议文案并导出供 editor 复用

超过 20 个可选项时仅举例 5 个并标明总数,避免 AI 误以为仅有举例值合法;editor 侧复用 form 的统一实现。
This commit is contained in:
roymondchen 2026-08-06 13:13:24 +08:00
parent efb637e72e
commit 0d1a17dce3
4 changed files with 33 additions and 41 deletions

View File

@ -20,7 +20,7 @@ import type { DataSourceFieldType, DataSourceSchema, Id } from '@tmagic/core';
import { NodeType } from '@tmagic/core';
import { appendValidateSuggestion } from '@tmagic/design';
import type { TypeMatchValidateContext, TypeMatchValidator } from '@tmagic/form';
import { validateTypeMatch } from '@tmagic/form';
import { MAX_SUGGESTION_OPTIONS, optionSuggestion, stringifyExampleValue, validateTypeMatch } from '@tmagic/form';
import {
DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX,
DATA_SOURCE_SET_DATA_METHOD_NAME,
@ -41,35 +41,9 @@ import {
numberOptions,
} from '@editor/utils/props';
/**
*
*/
const stringifyExampleValue = (value: any): string => {
if (typeof value === 'string') return `"${value}"`;
if (value === null || value === undefined) return String(value);
if (typeof value === 'object') {
try {
return JSON.stringify(value);
} catch {
return String(value);
}
}
return String(value);
};
// 参考建议中最多展示的可选值个数,超出以「等」省略。
const MAX_SUGGESTION_OPTIONS = 20;
/**
* 使xxxxxx
*/
const listSuggestion = (values: any[]): string => {
const list = values.filter((item) => typeof item !== 'undefined' && item !== null && item !== '');
if (!list.length) return '';
const shown = list.slice(0, MAX_SUGGESTION_OPTIONS).map(stringifyExampleValue);
const suffix = list.length > MAX_SUGGESTION_OPTIONS ? ' 等' : '';
return `请使用以下某一个值:${shown.join('')}${suffix}`;
};
/** 复用 form 的可选项建议文案;额外过滤 null / 空串,避免业务侧无效枚举污染提示。 */
const listSuggestion = (values: any[]): string =>
optionSuggestion(values.filter((item) => item !== null && item !== ''));
/**
* id

View File

@ -67,8 +67,11 @@ export {
clearTypeMatchRules,
deleteTypeMatchRule,
getTypeMatchRule,
MAX_SUGGESTION_OPTIONS,
optionSuggestion,
registerTypeMatchRule,
registerTypeMatchRules,
stringifyExampleValue,
validateTypeMatch,
} from './utils/typeMatch';

View File

@ -135,7 +135,7 @@ const TIMESTAMP_VALUE_FORMATS = new Set(['x', 'timestamp']);
/**
*
*/
const stringifyExampleValue = (value: any): string => {
export const stringifyExampleValue = (value: any): string => {
if (typeof value === 'string') return `"${value}"`;
if (value === null || value === undefined) return String(value);
if (typeof value === 'object') {
@ -148,19 +148,23 @@ const stringifyExampleValue = (value: any): string => {
return String(value);
};
// 参考建议中最多展示的可选值个数,超出以「等」省略。
const MAX_SUGGESTION_OPTIONS = 20;
/** 参考建议中可选值全量展示上限;超出时仅举例 EXAMPLE_SUGGESTION_COUNT 个并标明总数。 */
export const MAX_SUGGESTION_OPTIONS = 20;
const EXAMPLE_SUGGESTION_COUNT = 5;
/**
* 使xxxxxx
* MAX_SUGGESTION_OPTIONS
*
* MAX_SUGGESTION_OPTIONS EXAMPLE_SUGGESTION_COUNT AI
*/
const optionSuggestion = (optionValues: any[]): string => {
export const optionSuggestion = (optionValues: any[]): string => {
const values = optionValues.filter((item) => typeof item !== 'undefined');
if (!values.length) return '';
const shown = values.slice(0, MAX_SUGGESTION_OPTIONS).map(stringifyExampleValue);
const suffix = values.length > MAX_SUGGESTION_OPTIONS ? ' 等' : '';
return `请使用以下某一个值:${shown.join('')}${suffix}`;
const truncated = values.length > MAX_SUGGESTION_OPTIONS;
const shown = values.slice(0, truncated ? EXAMPLE_SUGGESTION_COUNT : values.length).map(stringifyExampleValue);
if (truncated) {
return `请从可选项中选用合法值(共 ${values.length} 个,例如:${shown.join('')}`;
}
return `请使用以下某一个值:${shown.join('')}`;
};
/**

View File

@ -196,14 +196,25 @@ describe('validateTypeMatch', () => {
expect(validateTypeMatch(3, mForm, propsOf(config))).toBe('3 不在可选项中\n\n请使用以下某一个值12');
});
test('可选项超过 20 个时建议仅展示前 20 个并以「等」省略', () => {
test('可选项超过 20 个时建议仅举例前 5 个并标明总数', () => {
const values = Array.from({ length: 21 }, (_, i) => i + 1);
const config = {
type: 'select',
options: values.map((v) => ({ text: `${v}`, value: v })),
};
expect(validateTypeMatch(99, mForm, propsOf(config))).toBe(
`99 不在可选项中\n\n请使用以下某一个值${values.slice(0, 20).join('')}`,
`99 不在可选项中\n\n请从可选项中选用合法值共 21 个,例如:${values.slice(0, 5).join('')}`,
);
});
test('可选项未超过 20 个时建议全部列举', () => {
const values = Array.from({ length: 20 }, (_, i) => i + 1);
const config = {
type: 'select',
options: values.map((v) => ({ text: `${v}`, value: v })),
};
expect(validateTypeMatch(99, mForm, propsOf(config))).toBe(
`99 不在可选项中\n\n请使用以下某一个值${values.join('')}`,
);
});