223 lines
7.2 KiB
TypeScript
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: [],
|
|
}),
|
|
}));
|