2026-03-22 16:45:57 +08:00
|
|
|
|
import type { ChapterViewModel } from './types';
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 与后端 `CHAPTER_ORDER` / `CHAPTER_CATEGORIES` 顺序一致;对应 i18n `memoir.frameworkChapters.*`。
|
|
|
|
|
|
*/
|
|
|
|
|
|
export const FRAMEWORK_CHAPTER_KEYS = [
|
|
|
|
|
|
'chapter1',
|
|
|
|
|
|
'chapter2',
|
|
|
|
|
|
'chapter3',
|
|
|
|
|
|
'chapter4',
|
|
|
|
|
|
'chapter5',
|
|
|
|
|
|
'chapter6',
|
|
|
|
|
|
'chapter7',
|
|
|
|
|
|
'chapter8',
|
|
|
|
|
|
] as const;
|
|
|
|
|
|
|
|
|
|
|
|
export type FrameworkChapterKey = (typeof FRAMEWORK_CHAPTER_KEYS)[number];
|
|
|
|
|
|
|
2026-05-19 11:11:58 +08:00
|
|
|
|
/** 与后端 `CHAPTER_ORDER` 一致(用于占位章节缺省 category) */
|
|
|
|
|
|
export const CHAPTER_CATEGORY_BY_ORDER_INDEX = [
|
|
|
|
|
|
'childhood',
|
|
|
|
|
|
'education',
|
|
|
|
|
|
'career_early',
|
|
|
|
|
|
'career_achievement',
|
|
|
|
|
|
'career_challenge',
|
|
|
|
|
|
'family',
|
|
|
|
|
|
'beliefs',
|
|
|
|
|
|
'summary',
|
|
|
|
|
|
] as const;
|
|
|
|
|
|
|
2026-03-22 16:45:57 +08:00
|
|
|
|
export function buildFrameworkChapterPlaceholders(
|
|
|
|
|
|
tr: (key: string) => string,
|
|
|
|
|
|
): ChapterViewModel[] {
|
|
|
|
|
|
return FRAMEWORK_CHAPTER_KEYS.map((key, orderIndex) => ({
|
|
|
|
|
|
id: `framework:${key}`,
|
|
|
|
|
|
title: tr(`frameworkChapters.${key}`),
|
|
|
|
|
|
category: '',
|
|
|
|
|
|
orderIndex,
|
|
|
|
|
|
isEmpty: true,
|
|
|
|
|
|
isNew: false,
|
|
|
|
|
|
hasImages: false,
|
|
|
|
|
|
allImagesReady: false,
|
|
|
|
|
|
pendingImageCount: 0,
|
|
|
|
|
|
failedImageCount: 0,
|
|
|
|
|
|
coverImageUrl: null,
|
|
|
|
|
|
updatedAt: null,
|
|
|
|
|
|
wordCount: 0,
|
|
|
|
|
|
}));
|
|
|
|
|
|
}
|
2026-03-23 13:21:07 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 列表页始终展示 8 个框架槽位:已有章节用接口数据,其余槽位仍用框架占位(与「零章节」时一致)。
|
|
|
|
|
|
*/
|
|
|
|
|
|
export function mergeFrameworkChaptersWithFetched(
|
|
|
|
|
|
placeholders: ChapterViewModel[],
|
|
|
|
|
|
fetched: ChapterViewModel[],
|
|
|
|
|
|
): ChapterViewModel[] {
|
|
|
|
|
|
const byOrder = new Map<number, ChapterViewModel>();
|
|
|
|
|
|
for (const vm of fetched) {
|
|
|
|
|
|
byOrder.set(vm.orderIndex, vm);
|
|
|
|
|
|
}
|
|
|
|
|
|
return placeholders.map((p) => byOrder.get(p.orderIndex) ?? p);
|
|
|
|
|
|
}
|