修复精选提示词展示

精选卡片优先展示用户可见的生成输入

过滤系统内置和素材提取提示词

补充精选提示词外露回归测试
This commit is contained in:
2026-07-07 18:47:23 +08:00
parent 5888219c95
commit 862653c987
2 changed files with 176 additions and 10 deletions
@@ -260,6 +260,62 @@ describe('creationShowcaseModel', () => {
expect(items[1]?.cost).toBe('12泥点');
});
it('prefers user generation inputs over internal assembled prompts', () => {
const items = buildCreationShowcaseItems({
activeTab: 'all',
projectResources: [
createResource({
resourceId: 'character-1',
label: '角色主图',
assetKind: 'character',
prompt:
'【系统内置】完整拼接提示词:用户的角色设定,自动添加视角、构图和抠图背景规则。',
actualPrompt:
'【系统内置】真正发送给模型的完整提示词,包含更多模型约束。',
generationInputs: {
fields: [
{ title: '角色设定', value: '用户的角色设定' },
{ title: '抠图背景色', value: '暖浅桃色 #FFD6C2' },
{ title: 'model', value: 'gpt-image-2' },
],
references: [],
},
}),
],
});
expect(items).toHaveLength(1);
expect(items[0]?.prompt).toBe('用户的角色设定');
});
it('does not expose built-in extraction prompts as showcase descriptions', () => {
const items = buildCreationShowcaseItems({
activeTab: 'all',
projectResources: [
createResource({
resourceId: 'icon-sheet-1',
label: '图标素材图集',
assetKind: 'icon-spritesheet',
prompt: '【系统内置】固定素材提取提示词',
generationInputs: {
fields: [
{
title: '提取提示词',
value:
'仅提取被红色框框选的素材并整理成spritesheet,图集背景必须使用所选单一纯色抠图背景。',
},
{ title: 'model', value: 'gpt-image-2' },
],
references: [],
},
}),
],
});
expect(items).toHaveLength(1);
expect(items[0]?.prompt).toBe('-');
});
it('keeps unset category visible in all tab and out of concrete category tabs', () => {
const items = buildCreationShowcaseItems({
activeTab: 'all',
@@ -65,6 +65,38 @@ const SHOWCASE_AUTHOR_KEYS = [
'authorPublicUserCode',
] as const;
const USER_PROMPT_INPUT_TITLES = new Set(
[
'生成提示词',
'视频描述',
'prompt',
'sound',
'gpt_description_prompt',
'音效提示词',
'背景音乐提示词',
'角色设定',
'用户输入',
'素材描述',
'自定义规范提示词',
'修改要求',
'快速编辑提示词',
'重绘提示词',
'动作描述',
].map((title) => title.toLowerCase()),
);
const STRUCTURED_USER_INPUT_TITLES = new Set(
[
'玩法设定',
'美术风格',
'头身比',
'角色视角',
'游戏名',
'游戏分类',
'一句话描述游戏',
].map((title) => title.toLowerCase()),
);
export const SHOWCASE_TABS: Array<{ id: ShowcaseTabId; label: string }> = [
{ id: 'all', label: '全部' },
{ id: 'characters', label: '角色' },
@@ -89,6 +121,22 @@ function normalizeText(value: unknown) {
return typeof value === 'string' && value.trim() ? value.trim() : '';
}
function normalizeGenerationInputTitle(value: string) {
return value.trim().toLowerCase();
}
function isBuiltInPromptText(value: string) {
const trimmedValue = value.trim();
return (
trimmedValue.startsWith('【系统内置】') ||
trimmedValue.startsWith('【宣发素材类型】') ||
trimmedValue.startsWith('参考图1的图标素材规范') ||
trimmedValue.startsWith('生成玩法UI原型图') ||
trimmedValue.includes('仅提取被红色框框选的素材') ||
trimmedValue.includes('图集背景必须使用所选单一纯色抠图背景')
);
}
function normalizeNumber(value: unknown) {
if (typeof value === 'number' && Number.isFinite(value)) {
return value;
@@ -597,18 +645,80 @@ function getGroupsForTab(assets: EditorAssetSnapshot[], tab: ShowcaseTabId) {
return [];
}
function resolveAssetPrompt(asset: EditorAssetSnapshot) {
const directPrompt = asset.prompt?.trim() || asset.actualPrompt?.trim();
if (directPrompt) {
return directPrompt;
function resolveUserGenerationPrompt(asset: EditorAssetSnapshot) {
const fields = asset.generationInputs?.fields ?? [];
const promptField = fields.find((field) => {
const value = field.value.trim();
return (
value &&
USER_PROMPT_INPUT_TITLES.has(
normalizeGenerationInputTitle(field.title),
) &&
!isBuiltInPromptText(value)
);
});
const promptValue = promptField?.value.trim();
if (promptValue) {
return promptValue;
}
const generationFields = asset.generationInputs?.fields ?? [];
const firstPromptField =
generationFields.find((field) =>
/|||prompt/u.test(field.title),
) ?? generationFields[0];
return firstPromptField?.value?.trim() || UNKNOWN_META_VALUE;
const structuredLines = fields.flatMap((field) => {
if (
!STRUCTURED_USER_INPUT_TITLES.has(
normalizeGenerationInputTitle(field.title),
)
) {
return [];
}
const value = field.value.trim();
return value && !isBuiltInPromptText(value)
? [`${field.title.trim()}${value}`]
: [];
});
return structuredLines.join('\n');
}
function extractUserPromptFromAssembledPrompt(value: string) {
const trimmedValue = value.trim();
const sectionMatch =
trimmedValue.match(/\s*([\s\S]*?)(?=\n+|$)/u) ??
trimmedValue.match(/\s*([\s\S]*?)(?=\n+|$)/u);
const sectionValue = sectionMatch?.[1]?.trim();
if (sectionValue && !isBuiltInPromptText(sectionValue)) {
return sectionValue;
}
const roleSettingMatch = trimmedValue.match(
/(?:^|\n)[:]\s*([^\n]+)/u,
);
const roleSettingValue = roleSettingMatch?.[1]?.trim();
return roleSettingValue && !isBuiltInPromptText(roleSettingValue)
? roleSettingValue
: '';
}
function resolveAssetPrompt(asset: EditorAssetSnapshot) {
const userPrompt = resolveUserGenerationPrompt(asset);
if (userPrompt) {
return userPrompt;
}
for (const value of [asset.prompt, asset.actualPrompt]) {
const directPrompt = value?.trim() ?? '';
if (!directPrompt) {
continue;
}
const extractedPrompt = extractUserPromptFromAssembledPrompt(directPrompt);
if (extractedPrompt) {
return extractedPrompt;
}
if (!isBuiltInPromptText(directPrompt)) {
return directPrompt;
}
}
return UNKNOWN_META_VALUE;
}
function resolveGroupPrompt(assets: EditorAssetSnapshot[]) {