Files
video-gen/video-gen-app/src/store/useAppStore.ts
T

223 lines
7.2 KiB
TypeScript

import { create } from 'zustand';
import type { Project, GenerationRecord, OptimizeParams, OptimizeResult, Industry, MediaReference } from '../types';
import * as api from '../api';
import { useAuthStore } from './useAuthStore';
const emptyRecordsPage = (): api.GenerationRecordPageListOut => ({
page: 1,
pageSize: 10,
total: 0,
items: [],
});
interface AppState {
projects: Project[];
records: api.GenerationRecordPageListOut;
loading: boolean;
// 生成配置状态 - 页面跳转时保留,刷新时重置
mediaType: string;
countType: string;
generationCount: number;
selectedRatio: string;
selectedResolution: string;
width: number;
height: number;
videoDuration: number;
videoAspectRatio: string;
videoResolution: string;
engineOptions: {
ratios: string[];
resolutions: string[];
durations: number[];
};
enginesele: any;
inputValue: string;
currentMedia: MediaReference[];
fetchProjects: () => Promise<void>;
createProject: (name: string, industry: Industry) => Promise<Project>;
deleteProject: (id: string) => Promise<void>;
fetchRecords: (params?: api.GetRecordsPageParams) => Promise<void>;
optimizePrompt: (projectId: string, params: OptimizeParams) => Promise<OptimizeResult>;
generateVideo: (recordId: string) => Promise<GenerationRecord>;
retryGeneration: (recordId: string) => Promise<GenerationRecord>;
updateRecordReferences: (recordId: string, references: MediaReference[]) => void;
// 生成配置状态更新方法
setMediaType: (mediaType: string) => void;
setCountType: (countType: string) => void;
setGenerationCount: (generationCount: number) => void;
setImageSettings: (ratio: string, resolution: string, width: number, height: number) => void;
setVideoSettings: (duration: number, aspectRatio: string, resolution: string) => void;
setEngineOptions: (options: { ratios: string[]; resolutions: string[]; durations: number[] }) => void;
// 单独的 setter 方法
setSelectedRatio: (ratio: string) => void;
setSelectedResolution: (resolution: string) => void;
setWidth: (width: number) => void;
setHeight: (height: number) => void;
setVideoDuration: (duration: number) => void;
setVideoAspectRatio: (aspectRatio: string) => void;
setVideoResolution: (resolution: string) => void;
setEnginesele: (enginesele: any) => void;
setInputValue: (inputValue: string) => void;
setCurrentMedia: (currentMedia: MediaReference[]) => void;
resetGenerationConfig: () => void;
}
export const useAppStore = create<AppState>((set, get) => ({
projects: [],
records: emptyRecordsPage(),
loading: false,
// 生成配置状态初始值
mediaType: 'video',
countType: '请选择',
generationCount: 1,
selectedRatio: '1:1',
selectedResolution: '2K',
width: 2048,
height: 2048,
videoDuration: 5,
videoAspectRatio: '9:16',
videoResolution: '720p',
engineOptions: {
ratios: ['16:9', '4:3', '1:1', '3:4', '9:16', '21:9'],
resolutions: ['480p', '720p', '1080p'],
durations: [5, 8, 10, 12, 15],
},
enginesele: [],
inputValue: '',
currentMedia: [],
fetchProjects: async () => {
set({ loading: true });
try {
const projects = await api.getProjects();
set({ projects, loading: false });
} catch {
set({ loading: false });
}
},
createProject: async (name, industry) => {
const project = await api.createProject(name, industry);
set({ projects: [project, ...get().projects] });
return project;
},
deleteProject: async (id) => {
await api.deleteProject(id);
set({ projects: get().projects.filter((p) => p.id !== id) });
},
fetchRecords: async (params = {}) => {
set({ loading: true });
try {
const records = await api.getRecordsPage(params);
set({ records, loading: false });
} catch {
set({ loading: false });
}
},
optimizePrompt: async (projectId, params) => {
const result = await api.optimizePrompt(projectId, params);
try { await useAuthStore.getState().checkAuth(); } catch { /* */ }
const currentRecords = get().records;
const existingIndex = currentRecords.items.findIndex((item) => item.id === result.record.id);
const nextItems = existingIndex >= 0
? currentRecords.items.map((item) => item.id === result.record.id ? result.record : item)
: [result.record, ...currentRecords.items];
set({
records: {
...currentRecords,
total: existingIndex >= 0 ? currentRecords.total : currentRecords.total + 1,
items: nextItems,
},
});
return result;
},
generateVideo: async (recordId) => {
const record = await api.generateVideo(recordId);
try { await useAuthStore.getState().checkAuth(); } catch { /* */ }
const currentRecords = get().records;
set({
records: {
...currentRecords,
items: currentRecords.items.map((r) => (r.id === recordId ? record : r)),
},
});
return record;
},
retryGeneration: async (recordId) => {
const record = await api.retryGeneration(recordId);
try { await useAuthStore.getState().checkAuth(); } catch { /* */ }
const currentRecords = get().records;
set({
records: {
...currentRecords,
items: currentRecords.items.map((r) => (r.id === recordId ? record : r)),
},
});
return record;
},
updateRecordReferences: (recordId, references) => {
const currentRecords = get().records;
set({
records: {
...currentRecords,
items: currentRecords.items.map((r) => (r.id === recordId ? { ...r, references } : r)),
},
});
},
// 生成配置状态更新方法
setMediaType: (mediaType) => set({ mediaType }),
setCountType: (countType) => set({ countType }),
setGenerationCount: (generationCount) => set({ generationCount }),
setImageSettings: (ratio, resolution, width, height) =>
set({ selectedRatio: ratio, selectedResolution: resolution, width, height }),
setVideoSettings: (duration, aspectRatio, resolution) =>
set({ videoDuration: duration, videoAspectRatio: aspectRatio, videoResolution: resolution }),
setEngineOptions: (options) => set({ engineOptions: options }),
// 单独的 setter 方法
setSelectedRatio: (ratio) => set({ selectedRatio: ratio }),
setSelectedResolution: (resolution) => set({ selectedResolution: resolution }),
setWidth: (width) => set({ width }),
setHeight: (height) => set({ height }),
setVideoDuration: (duration) => set({ videoDuration: duration }),
setVideoAspectRatio: (aspectRatio) => set({ videoAspectRatio: aspectRatio }),
setVideoResolution: (resolution) => set({ videoResolution: resolution }),
setEnginesele: (enginesele) => set({ enginesele }),
setInputValue: (inputValue) => set({ inputValue }),
setCurrentMedia: (currentMedia) => set({ currentMedia }),
resetGenerationConfig: () => set({
mediaType: 'image',
countType: '请选择',
generationCount: 1,
selectedRatio: '1:1',
selectedResolution: '2K',
width: 2048,
height: 2048,
videoDuration: 5,
videoAspectRatio: '9:16',
videoResolution: '720p',
engineOptions: {
ratios: ['16:9', '4:3', '1:1', '3:4', '9:16', '21:9'],
resolutions: ['480p', '720p', '1080p'],
durations: [5, 8, 10, 12, 15],
},
enginesele: [],
inputValue: '',
currentMedia: [],
}),
}));