baseline: Clover 独立仓库首次基线提交
将 Clover 从上层产品包旧仓库中独立出来,建立专属版本控制。 当前状态=纵切片端到端已打通(登录→选品→出文出图→审核→下载包), M1文案质量去套路化已验收。此提交作为后续按核销清单逐条修复的基线。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
122
frontend/src/stores/generationStore.ts
Normal file
122
frontend/src/stores/generationStore.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* generationStore — SSE进度 / 图片候选 / 飞轮注入
|
||||
* image_candidate 无 batch 字段,所以 imageCandidates 平铺存储
|
||||
*/
|
||||
import { create } from 'zustand';
|
||||
import { SseConnectionStatus } from '@/lib/sse';
|
||||
import { TextCandidate, ImageCandidate } from '@/types/index';
|
||||
|
||||
interface FailedBatch {
|
||||
batch: string; // 图片角色名("hook"/"pain"等),对应 BE batch_failed.batch 字段
|
||||
reason: string;
|
||||
retryable: boolean;
|
||||
}
|
||||
|
||||
interface GenerationState {
|
||||
// 连接状态
|
||||
connectionStatus: SseConnectionStatus;
|
||||
reconnectAttempt: number;
|
||||
|
||||
// 文案生成进度
|
||||
textDone: number;
|
||||
textTotal: number;
|
||||
textCandidates: TextCandidate[];
|
||||
|
||||
// 图片生成进度(平铺,不分 batch — 契约无 batch 字段)
|
||||
imageDone: number;
|
||||
imageTotal: number;
|
||||
imageCandidates: ImageCandidate[];
|
||||
failedBatches: FailedBatch[];
|
||||
|
||||
// 飞轮注入(飞轮隐形,只显注入提示,无"训练AI"按钮)
|
||||
flywheelInjected: {
|
||||
recentPreference: string;
|
||||
rejectReasons: string[];
|
||||
} | null;
|
||||
|
||||
setConnectionStatus: (s: SseConnectionStatus, attempt?: number) => void;
|
||||
setTextProgress: (done: number, total: number) => void;
|
||||
addTextCandidate: (candidate: TextCandidate) => void;
|
||||
patchTextCandidateScore: (candidateId: number, score: TextCandidate['score']) => void;
|
||||
setImageProgress: (done: number, total: number) => void;
|
||||
addImageCandidate: (candidate: ImageCandidate) => void;
|
||||
markBatchFailed: (batch: string, reason: string, retryable: boolean) => void;
|
||||
setFlywheelInjected: (data: { recentPreference: string; rejectReasons: string[] }) => void;
|
||||
hydrateFromTask: (data: {
|
||||
textCandidates: TextCandidate[];
|
||||
imageCandidates: ImageCandidate[];
|
||||
}) => void;
|
||||
reset: () => void;
|
||||
}
|
||||
|
||||
export const useGenerationStore = create<GenerationState>((set) => ({
|
||||
connectionStatus: 'connecting',
|
||||
reconnectAttempt: 0,
|
||||
textDone: 0,
|
||||
textTotal: 0,
|
||||
textCandidates: [],
|
||||
imageDone: 0,
|
||||
imageTotal: 0,
|
||||
imageCandidates: [],
|
||||
failedBatches: [],
|
||||
flywheelInjected: null,
|
||||
|
||||
setConnectionStatus(s, attempt = 0) {
|
||||
set({ connectionStatus: s, reconnectAttempt: attempt });
|
||||
},
|
||||
|
||||
setTextProgress(done, total) {
|
||||
set({ textDone: done, textTotal: total });
|
||||
},
|
||||
|
||||
addTextCandidate(candidate) {
|
||||
set((s) => ({ textCandidates: [...s.textCandidates, candidate] }));
|
||||
},
|
||||
|
||||
patchTextCandidateScore(candidateId, score) {
|
||||
set((s) => ({
|
||||
textCandidates: s.textCandidates.map((tc) =>
|
||||
tc.candidate_id === candidateId ? { ...tc, score } : tc
|
||||
),
|
||||
}));
|
||||
},
|
||||
|
||||
setImageProgress(done, total) {
|
||||
set({ imageDone: done, imageTotal: total });
|
||||
},
|
||||
|
||||
addImageCandidate(candidate) {
|
||||
set((s) => ({ imageCandidates: [...s.imageCandidates, candidate] }));
|
||||
},
|
||||
|
||||
markBatchFailed(batch, reason, retryable) {
|
||||
set((s) => ({
|
||||
failedBatches: [...s.failedBatches, { batch, reason, retryable }],
|
||||
}));
|
||||
},
|
||||
|
||||
setFlywheelInjected(data) {
|
||||
set({ flywheelInjected: data });
|
||||
},
|
||||
|
||||
// 进入已完成/进行中任务时一次性回填(历史任务 SSE 不重放,必须主动拉接口)
|
||||
hydrateFromTask({ textCandidates, imageCandidates }) {
|
||||
set({
|
||||
textCandidates,
|
||||
textDone: textCandidates.length,
|
||||
textTotal: textCandidates.length || 0,
|
||||
imageCandidates,
|
||||
imageDone: imageCandidates.length,
|
||||
imageTotal: imageCandidates.length || 0,
|
||||
});
|
||||
},
|
||||
|
||||
reset() {
|
||||
set({
|
||||
connectionStatus: 'connecting', reconnectAttempt: 0,
|
||||
textDone: 0, textTotal: 0, textCandidates: [],
|
||||
imageDone: 0, imageTotal: 0, imageCandidates: [],
|
||||
failedBatches: [], flywheelInjected: null,
|
||||
});
|
||||
},
|
||||
}));
|
||||
Reference in New Issue
Block a user