feat(*): 短剧创作工作台 - 完善章节分镜、资产管理、技能运行与生成任务恢复

This commit is contained in:
ddCat
2026-08-29 23:34:46 +08:00
parent 4f07daae9e
commit 2f6832f99c
113 changed files with 7016 additions and 723 deletions

View File

@@ -2,7 +2,7 @@ import { create } from "zustand";
import { persist, type PersistStorage, type StorageValue } from "zustand/middleware";
import { nanoid } from "nanoid";
import { parseAssetStorageDocument, rebaseAssetSnapshot, serializeAssetStorageDocument, type AssetStorageDocument } from "@/lib/asset-storage-revision";
import { normalizeAssetRecord, parseAssetStorageDocument, rebaseAssetSnapshot, serializeAssetStorageDocument, type AssetStorageDocument } from "@/lib/asset-storage-revision";
import { parseCanvasStorageDocument } from "@/lib/canvas/canvas-storage-revision";
import { localForageStorageForScope } from "@/lib/localforage-storage";
import { getActiveUserScope } from "@/lib/user-scope";
@@ -144,7 +144,7 @@ function trackAssetOperation<T>(operation: Promise<T>) {
function persistAssetState(name: string, value: StorageValue<AssetStore>) {
const scope = getActiveUserScope();
const nextAssets = value.state.assets;
const nextAssets = value.state.assets.map(normalizeAssetRecord);
const queued = queuedAssetPersists.get(scope);
const observed = observedAssetPersists.get(scope);
const baseAssets = assetMemoryStates.get(scope)?.assets ?? observed?.assets ?? [];
@@ -230,6 +230,7 @@ const assetStorage: PersistStorage<AssetStore> = {
};
async function normalizePersistedAsset(asset: Asset): Promise<Asset> {
asset = normalizeAssetRecord(asset);
const storageKey = "data" in asset && asset.data && "storageKey" in asset.data ? asset.data.storageKey : undefined;
const resourceId = resourceIdFromStorageKey(storageKey);
if (resourceId) {
@@ -269,7 +270,7 @@ export const useAssetStore = create<AssetStore>()(
addAsset: (asset) => {
const now = new Date().toISOString();
const id = nanoid();
set((state) => ({ assets: [{ ...asset, id, createdAt: now, updatedAt: now } as Asset, ...state.assets] }));
set((state) => ({ assets: [normalizeAssetRecord({ ...asset, id, createdAt: now, updatedAt: now } as Asset), ...state.assets] }));
return id;
},
addGenerationAsset: (effectKey, asset, signal) => {
@@ -287,13 +288,13 @@ export const useAssetStore = create<AssetStore>()(
assetId: id,
createAsset: () => {
const now = new Date().toISOString();
return {
return normalizeAssetRecord({
...asset,
id,
createdAt: now,
updatedAt: now,
metadata: { ...asset.metadata, generationEffectKey: effectKey },
} as Asset;
} as Asset);
},
updateAssets: (updater) => {
withAssetStorePersistenceSuppressed(() => {
@@ -353,7 +354,7 @@ export const useAssetStore = create<AssetStore>()(
},
updateAsset: (id, patch) =>
set((state) => ({
assets: state.assets.map((asset) => (asset.id === id ? ({ ...asset, ...patch, updatedAt: new Date().toISOString() } as Asset) : asset)),
assets: state.assets.map((asset) => (asset.id === id ? normalizeAssetRecord({ ...asset, ...patch, updatedAt: new Date().toISOString() } as Asset) : asset)),
})),
removeAsset: async (id) => {
let remainingAssets: Asset[] = [];
@@ -369,7 +370,7 @@ export const useAssetStore = create<AssetStore>()(
if (!removedAsset || (!collectImageStorageKeys(removedAsset).size && !collectMediaStorageKeys(removedAsset).size)) return;
await get().cleanupImages({ assets: remainingAssets });
},
replaceAssets: (assets) => set({ assets }),
replaceAssets: (assets) => set({ assets: assets.map(normalizeAssetRecord) }),
cleanupImages: async (extra) => {
const scope = getActiveUserScope();
const frozenExtraImageKeys = collectImageStorageKeys(extra);