mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2026-08-07 13:29:21 +00:00
fix(form): 优化可选项校验建议文案并导出供 editor 复用
超过 20 个可选项时仅举例 5 个并标明总数,避免 AI 误以为仅有举例值合法;editor 侧复用 form 的统一实现。
This commit is contained in:
parent
efb637e72e
commit
0d1a17dce3
@ -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;
|
||||
|
||||
/**
|
||||
* 生成「请使用以下某一个值:xxx;xxx」形式的参考建议;无可选值时返回空字符串(不追加建议)。
|
||||
*/
|
||||
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 的参考建议。
|
||||
|
||||
@ -67,8 +67,11 @@ export {
|
||||
clearTypeMatchRules,
|
||||
deleteTypeMatchRule,
|
||||
getTypeMatchRule,
|
||||
MAX_SUGGESTION_OPTIONS,
|
||||
optionSuggestion,
|
||||
registerTypeMatchRule,
|
||||
registerTypeMatchRules,
|
||||
stringifyExampleValue,
|
||||
validateTypeMatch,
|
||||
} from './utils/typeMatch';
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
/**
|
||||
* 生成「请使用以下某一个值:xxx;xxx」形式的参考建议;无可选值时返回空字符串(不追加建议)。
|
||||
* 可选值超过 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(';')}`;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -196,14 +196,25 @@ describe('validateTypeMatch', () => {
|
||||
expect(validateTypeMatch(3, mForm, propsOf(config))).toBe('3 不在可选项中\n\n请使用以下某一个值:1;2');
|
||||
});
|
||||
|
||||
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(';')}`,
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user