Files
meijiaka-zy/tauri-app/src/utils/projectMeta.ts
T
小鱼开发 aa818b75a8 refactor: 脚本提示词体系重构 — 子类从目录改为单个文件
- 删除 system/bk/ 下所有旧提示词,平铺替换为 23 个新文件
- 文件名格式统一为: 文案——描述.txt
- 后端: _meta.json 扁平化,loader.py 新增 list_prompt_files() + load_prompt_file()
- 后端: API 从 subcategory 改为 filename,按指定文件读取
- 后端: categories 接口返回文件列表(label/desc/filename)供前端展示
- 前端: ScriptCreation 分类选择改为卡片网格,展示文案+描述
- 前端: 清理 subcategoryCode,统一改为 filename
- 前端: 字幕字号调整为 64/96/80px
2026-06-01 13:44:59 +08:00

178 lines
5.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 项目元数据工具函数
* ==================
*
* 封装 meta.json 的构建、合并、迁移逻辑。
* 新增字段时只需在 types/project.ts 的 ProjectMeta 中定义,
* 此处无需修改。
*/
import type { ProjectMeta, MetaOverrides } from '../types/project';
// ------------------------------------------------------------------
// 默认值配置(集中管理)
// ------------------------------------------------------------------
const DEFAULT_META_VALUES: Partial<ProjectMeta> = {
currentStep: 1,
voiceSpeed: 1.0,
voiceVolume: 0,
voicePitch: 0,
status: 'draft',
version: 1,
};
// ------------------------------------------------------------------
// 内部工具:判断值是否为 undefined(区分"未传"和"传了 undefined"
// ------------------------------------------------------------------
function hasOwn<K extends string>(obj: object, key: K): obj is Record<K, unknown> {
return Object.prototype.hasOwnProperty.call(obj, key);
}
// ------------------------------------------------------------------
// 构建项目标题
// ------------------------------------------------------------------
function buildTitle(topic: string | undefined, existingTitle?: string): string {
// 优先保留用户自定义的项目名称
if (existingTitle) {
return existingTitle;
}
const trimmed = topic?.trim();
if (trimmed) {
return trimmed;
}
return '未命名项目';
}
// ------------------------------------------------------------------
// 核心:通用元数据合并函数
// ------------------------------------------------------------------
/**
* 构建完整的 ProjectMeta 对象。
*
* 逻辑:
* 1. 将 existingMeta 与 overrides 合并(overrides 优先级高)
* 2. 计算系统字段(id, title, status, timestamps
* 3. 填充默认值
*
* @param projectId 项目 ID
* @param existing 磁盘上已有的 meta(可能为 null)
* @param overrides 前端传入的覆盖值
*/
export function buildProjectMeta(
projectId: string,
existing: Partial<ProjectMeta> | null,
overrides: MetaOverrides = {},
): ProjectMeta {
const now = Date.now();
// Step 1: 自动合并所有非系统字段
const merged: Partial<ProjectMeta> = { ...(existing || {}) };
for (const key of Object.keys(overrides) as Array<keyof MetaOverrides>) {
if (hasOwn(overrides, key)) {
(merged as Record<string, unknown>)[key] = overrides[key];
}
}
// Step 2: 计算系统字段
const topic = merged.topic;
const title = buildTitle(topic, merged.title);
// Step 3: 组装最终结果
return {
// 系统字段(不能被 overrides 覆盖)
id: projectId,
title,
status: (merged.status as 'draft' | 'published') || DEFAULT_META_VALUES.status!,
currentStep:
merged.currentStep ?? existing?.currentStep ?? DEFAULT_META_VALUES.currentStep!,
createdAt: existing?.createdAt || now,
updatedAt: now,
version:
(existing?.version || 0) >= 1 ? existing!.version : DEFAULT_META_VALUES.version,
// 自动展开所有持久化字段(包括用户覆盖的和已有磁盘数据)
...merged,
} as ProjectMeta;
}
// ------------------------------------------------------------------
// 数据迁移
// ------------------------------------------------------------------
/**
* 将旧版 meta.json 升级到新格式。
*
* 未来结构变更时在此添加迁移逻辑:
* if (version < 2) { ...v1→v2 迁移... }
*/
export function migrateMeta(raw: unknown): Partial<ProjectMeta> {
if (typeof raw !== 'object' || raw === null) {
return {};
}
const obj = raw as Record<string, unknown>;
const version = typeof obj.version === 'number' ? obj.version : 0;
if (version < 1) {
// v0 → v1: 添加 version 字段,其他保持不变
return { ...obj, version: 1 } as Partial<ProjectMeta>;
}
// 当前版本,无需迁移
return obj as Partial<ProjectMeta>;
}
// ------------------------------------------------------------------
// 空白 overrides — 用于切换项目时清空旧数据
// ------------------------------------------------------------------
/**
* 显式将所有业务字段设为 undefined,配合 Zustand setState 使用。
* 在 initProjectStore / createNewProject 中先展开此对象,再展开新项目的 meta,
* 确保旧项目的字段不会残留。
*
* 新增字段时必须在此补充,否则切换项目时旧值会残留。
*/
export const BLANK_META_OVERRIDES: MetaOverrides = {
topic: undefined,
categoryCode: undefined,
filename: undefined,
selectedVoiceId: undefined,
finalVideoPath: undefined,
finalVideoDuration: undefined,
coverPath: undefined,
coverConfig: undefined,
exportedAt: undefined,
composedVideoUrl: undefined,
composedVideoPath: undefined,
lipSyncTaskId: undefined,
lipSyncState: undefined,
lipSyncedVideoPath: undefined,
lipSyncedVideoUrl: undefined,
dubbingAudioUrl: undefined,
dubbingAudioPath: undefined,
dubbingAudioDuration: undefined,
avatarMaterialPath: undefined,
avatarMaterialName: undefined,
avatarMaterialDuration: undefined,
subtitleAlignment: undefined,
burnedVideoPath: undefined,
mainTitle: undefined,
subTitle: undefined,
mainTitlePreset: undefined,
subTitlePreset: undefined,
captionPreset: undefined,
userUploadedMaterials: undefined,
stepDirtyFlags: undefined,
bgmMusicId: undefined,
bgmMusicTitle: undefined,
bgmMusicPath: undefined,
bgmVolume: undefined,
};