a2736f722c
- 安装 zustand + react-router-dom 依赖 - 修复 Vite 代理配置,添加 /auth 路由转发 - 实现 API 封装层(client.ts 统一 fetch、auth.ts 真实调用) - 实现 mock 数据层(mock.ts 模拟 WebSocket 管线进度) - 实现 4 个 zustand stores(auth/project/task/generation) - 实现 5 个组件(StyleSelector/PromptEditor/GenerateForm/ProgressBar/AssetPreview) - 实现 5 个页面(Login/Register/Project/Generate/Result) - 实现路由含 ProtectedRoute 守卫 - 添加暗色主题全局样式 - 更新前端文档与 API 文档
83 lines
2.0 KiB
TypeScript
83 lines
2.0 KiB
TypeScript
import { create } from 'zustand'
|
|
import type { Asset, PipelineProgress, PipelineStage } from '../api/types'
|
|
import { submitGenerate } from '../api/generate'
|
|
import { createMockWebSocket } from '../api/mock'
|
|
|
|
type Status = 'idle' | 'submitting' | 'running' | 'completed' | 'failed'
|
|
|
|
interface GenerationState {
|
|
taskId: string | null
|
|
stage: PipelineStage | null
|
|
progress: number
|
|
status: Status
|
|
retryCount: number
|
|
rejectReason: string | null
|
|
assets: Asset[]
|
|
error: string | null
|
|
submit: (projectId: string, prompt: string, assetType: string) => Promise<void>
|
|
handleProgress: (msg: PipelineProgress) => void
|
|
reset: () => void
|
|
}
|
|
|
|
let cleanupWs: (() => void) | null = null
|
|
|
|
export const useGenerationStore = create<GenerationState>((set, get) => ({
|
|
taskId: null,
|
|
stage: null,
|
|
progress: 0,
|
|
status: 'idle',
|
|
retryCount: 0,
|
|
rejectReason: null,
|
|
assets: [],
|
|
error: null,
|
|
|
|
submit: async (projectId, prompt, assetType) => {
|
|
set({ status: 'submitting', error: null })
|
|
try {
|
|
const taskId = await submitGenerate(projectId, prompt, assetType)
|
|
set({ taskId, status: 'running', progress: 0 })
|
|
|
|
// 启动 mock WebSocket
|
|
cleanupWs = createMockWebSocket(
|
|
taskId,
|
|
(msg) => get().handleProgress(msg),
|
|
(assets) => {
|
|
set({ status: 'completed', assets, progress: 100 })
|
|
},
|
|
(error) => {
|
|
set({ status: 'failed', error })
|
|
}
|
|
)
|
|
} catch (err) {
|
|
set({ status: 'failed', error: (err as Error).message })
|
|
}
|
|
},
|
|
|
|
handleProgress: (msg) => {
|
|
set({
|
|
stage: msg.stage,
|
|
progress: msg.progress,
|
|
retryCount: msg.retryCount ?? get().retryCount,
|
|
rejectReason: msg.rejectReason ?? null,
|
|
})
|
|
if (msg.result?.assets) {
|
|
set({ assets: msg.result.assets })
|
|
}
|
|
},
|
|
|
|
reset: () => {
|
|
cleanupWs?.()
|
|
cleanupWs = null
|
|
set({
|
|
taskId: null,
|
|
stage: null,
|
|
progress: 0,
|
|
status: 'idle',
|
|
retryCount: 0,
|
|
rejectReason: null,
|
|
assets: [],
|
|
error: null,
|
|
})
|
|
},
|
|
}))
|