feat: 支持创作入口公告配置
This commit is contained in:
@@ -36,9 +36,9 @@ const entryConfig = {
|
||||
visible: true,
|
||||
open: true,
|
||||
sortOrder: 10,
|
||||
categoryId: 'recent',
|
||||
categoryLabel: '最近创作',
|
||||
categorySortOrder: 10,
|
||||
categoryId: 'recommended',
|
||||
categoryLabel: '热门推荐',
|
||||
categorySortOrder: 20,
|
||||
updatedAtMicros: 1,
|
||||
},
|
||||
],
|
||||
|
||||
@@ -353,6 +353,7 @@ import type { PublishShareModalPayload } from '../common/publishShareModalModel'
|
||||
import { UnifiedModal } from '../common/UnifiedModal';
|
||||
import { resolveCreativeAgentTargetSelectionStage } from '../creative-agent/creativeAgentViewModel';
|
||||
import {
|
||||
buildCreationWorkShelfItems,
|
||||
type CreationWorkShelfItem,
|
||||
isPersistedBarkBattleDraftGenerating,
|
||||
isPersistedPuzzleDraftGenerating,
|
||||
@@ -2162,35 +2163,24 @@ function buildDraftCompletionDialogSource(
|
||||
return formatPlatformTaskCompletionSource('创作草稿', sourceId);
|
||||
}
|
||||
|
||||
/** 为恢复的小游戏草稿重建生成态,保留后端开始时间作为进度事实源。 */
|
||||
function createMiniGameDraftGenerationStateForRestoredDraft(
|
||||
kind: MiniGameDraftGenerationKind,
|
||||
metadata?: MiniGameDraftGenerationState['metadata'],
|
||||
startedAtMs = Date.now(),
|
||||
): MiniGameDraftGenerationState {
|
||||
return {
|
||||
...createMiniGameDraftGenerationState(kind),
|
||||
...createMiniGameDraftGenerationState(kind, startedAtMs),
|
||||
...(metadata ? { metadata } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
/** 清理生成态完成时间,避免返回生成页后继续沿用结束态计时。 */
|
||||
function rebaseMiniGameDraftGenerationStateForDisplay(
|
||||
state: MiniGameDraftGenerationState,
|
||||
): MiniGameDraftGenerationState {
|
||||
const rebasedStartedAtMs = Date.now();
|
||||
|
||||
if (state.kind === 'puzzle') {
|
||||
const puzzleAiRedraw = state.metadata?.puzzleAiRedraw;
|
||||
return {
|
||||
...state,
|
||||
startedAtMs: rebasedStartedAtMs,
|
||||
finishedAtMs: undefined,
|
||||
metadata:
|
||||
typeof puzzleAiRedraw === 'boolean' ? { puzzleAiRedraw } : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...state,
|
||||
startedAtMs: rebasedStartedAtMs,
|
||||
finishedAtMs: undefined,
|
||||
};
|
||||
}
|
||||
@@ -14920,6 +14910,19 @@ export function PlatformEntryFlowShellImpl({
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
platformBootstrap.platformTab === 'create' &&
|
||||
platformBootstrap.canReadProtectedData
|
||||
) {
|
||||
// 中文注释:底部加号创作入口的“最近创作”依赖 RPG works 摘要;
|
||||
// 失败草稿也必须随进入创作页刷新,不能只等草稿页刷新后才可见。
|
||||
void platformBootstrap.refreshCustomWorldWorks().catch((error) => {
|
||||
platformBootstrap.setPlatformError(
|
||||
resolveRpgCreationErrorMessage(error, '读取创作作品列表失败。'),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
(platformBootstrap.platformTab === 'create' ||
|
||||
selectionStage === 'platform') &&
|
||||
@@ -14942,6 +14945,8 @@ export function PlatformEntryFlowShellImpl({
|
||||
isVisualNovelCreationOpen,
|
||||
platformBootstrap.canReadProtectedData,
|
||||
platformBootstrap.platformTab,
|
||||
platformBootstrap.refreshCustomWorldWorks,
|
||||
platformBootstrap.setPlatformError,
|
||||
refreshBabyObjectMatchShelf,
|
||||
refreshBarkBattleShelf,
|
||||
refreshMatch3DShelf,
|
||||
@@ -14969,6 +14974,46 @@ export function PlatformEntryFlowShellImpl({
|
||||
selectionStage,
|
||||
]);
|
||||
|
||||
// 中文注释:最近创作必须由真实作品架/后端草稿摘要决定,不能混入本地生成中占位。
|
||||
const backendRecentCreationShelfItems = useMemo(
|
||||
() =>
|
||||
buildCreationWorkShelfItems({
|
||||
rpgItems: creationHubItems,
|
||||
rpgLibraryEntries: platformBootstrap.savedCustomWorldEntries,
|
||||
bigFishItems: isBigFishCreationVisible ? bigFishWorks : [],
|
||||
match3dItems: match3dWorks,
|
||||
squareHoleItems: isSquareHoleCreationVisible ? squareHoleWorks : [],
|
||||
jumpHopItems: isJumpHopCreationVisible ? jumpHopWorks : [],
|
||||
woodenFishItems: woodenFishWorks,
|
||||
puzzleItems: puzzleWorks,
|
||||
babyObjectMatchItems: isBabyObjectMatchVisible
|
||||
? babyObjectMatchDrafts
|
||||
: [],
|
||||
barkBattleItems: barkBattleWorks,
|
||||
visualNovelItems: isVisualNovelCreationOpen ? visualNovelWorks : [],
|
||||
getItemState: getCreationWorkShelfState,
|
||||
}),
|
||||
[
|
||||
barkBattleWorks,
|
||||
babyObjectMatchDrafts,
|
||||
bigFishWorks,
|
||||
creationHubItems,
|
||||
getCreationWorkShelfState,
|
||||
isBabyObjectMatchVisible,
|
||||
isBigFishCreationVisible,
|
||||
isJumpHopCreationVisible,
|
||||
isSquareHoleCreationVisible,
|
||||
isVisualNovelCreationOpen,
|
||||
jumpHopWorks,
|
||||
match3dWorks,
|
||||
platformBootstrap.savedCustomWorldEntries,
|
||||
puzzleWorks,
|
||||
squareHoleWorks,
|
||||
visualNovelWorks,
|
||||
woodenFishWorks,
|
||||
],
|
||||
);
|
||||
|
||||
const renderCreationHubContent = (
|
||||
mode: 'start-only' | 'works-only',
|
||||
fallbackLabel: string,
|
||||
@@ -15065,6 +15110,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
}
|
||||
entryConfig={creationEntryConfig}
|
||||
creationTypes={creationEntryTypes}
|
||||
recentWorkItems={backendRecentCreationShelfItems}
|
||||
onCreateType={handleCreationHubCreateType}
|
||||
getWorkState={getCreationWorkShelfState}
|
||||
onOpenShelfItem={(item) => {
|
||||
|
||||
@@ -306,7 +306,7 @@ test('groups visible platform creation types by backend category metadata', () =
|
||||
const groups = groupVisiblePlatformCreationTypes(cards);
|
||||
|
||||
expect(groups.map((group) => group.label)).toEqual([
|
||||
'最近创作',
|
||||
'热门推荐',
|
||||
'节日主题',
|
||||
]);
|
||||
expect(groups[0]?.items.map((item) => item.id)).toEqual([
|
||||
@@ -337,14 +337,14 @@ test('falls back when backend creation type category metadata is missing', () =>
|
||||
expect(cards[0]).toEqual(
|
||||
expect.objectContaining({
|
||||
id: 'legacy-entry',
|
||||
categoryId: 'recent',
|
||||
categoryLabel: '最近创作',
|
||||
categoryId: 'recommended',
|
||||
categoryLabel: '热门推荐',
|
||||
}),
|
||||
);
|
||||
expect(groupVisiblePlatformCreationTypes(cards)).toEqual([
|
||||
expect.objectContaining({
|
||||
id: 'recent',
|
||||
label: '最近创作',
|
||||
id: 'recommended',
|
||||
label: '热门推荐',
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -24,8 +24,9 @@ export type PlatformCreationTypeGroup = {
|
||||
items: PlatformCreationTypeCard[];
|
||||
};
|
||||
|
||||
const FALLBACK_CREATION_CATEGORY_ID = 'recent';
|
||||
const FALLBACK_CREATION_CATEGORY_LABEL = '最近创作';
|
||||
const RECENT_CREATION_CATEGORY_ID = 'recent';
|
||||
const FALLBACK_CREATION_CATEGORY_ID = 'recommended';
|
||||
const FALLBACK_CREATION_CATEGORY_LABEL = '热门推荐';
|
||||
|
||||
export function getVisiblePlatformCreationTypes(
|
||||
creationTypes: readonly PlatformCreationTypeCard[],
|
||||
@@ -55,16 +56,25 @@ export function isPlatformCreationTypeOpen(
|
||||
);
|
||||
}
|
||||
|
||||
/** 归一化模板分类 ID,历史 recent 分类会并入推荐分类。 */
|
||||
function normalizeCategoryId(value: string | null | undefined) {
|
||||
const normalized = typeof value === 'string' ? value.trim() : '';
|
||||
if (normalized === RECENT_CREATION_CATEGORY_ID) {
|
||||
return FALLBACK_CREATION_CATEGORY_ID;
|
||||
}
|
||||
return normalized || FALLBACK_CREATION_CATEGORY_ID;
|
||||
}
|
||||
|
||||
/** 归一化模板分类名,避免最近创作被误当作模板页签。 */
|
||||
function normalizeCategoryLabel(value: string | null | undefined) {
|
||||
const normalized = typeof value === 'string' ? value.trim() : '';
|
||||
if (normalized === '最近创作') {
|
||||
return FALLBACK_CREATION_CATEGORY_LABEL;
|
||||
}
|
||||
return normalized || FALLBACK_CREATION_CATEGORY_LABEL;
|
||||
}
|
||||
|
||||
/** 按玩法模板分类分组,旧 recent 分类不再作为模板页签展示。 */
|
||||
export function groupVisiblePlatformCreationTypes(
|
||||
creationTypes: readonly PlatformCreationTypeCard[],
|
||||
): PlatformCreationTypeGroup[] {
|
||||
|
||||
Reference in New Issue
Block a user