fix: 同步视频项目积分余额
This commit is contained in:
@@ -221,6 +221,12 @@ export function App() {
|
||||
if (data) setUnreadCount(data.unread_count);
|
||||
}, []);
|
||||
|
||||
// 仅同步顶栏余额:异步 AI 任务在成功结算后调用,避免为一个数字重拉整站数据。
|
||||
const refreshBilling = useCallback(async () => {
|
||||
const summary = await api.billingSummary().catch(() => null);
|
||||
if (summary) setBilling(summary);
|
||||
}, []);
|
||||
|
||||
// 自由创作自行管理长视频轮询;任务终态后只需同步顶栏依赖的两项全局数据,
|
||||
// 不必像通用 action 一样重拉商品、项目和素材列表。
|
||||
const refreshFreeCreateShell = useCallback(() => {
|
||||
@@ -413,8 +419,11 @@ export function App() {
|
||||
if (next && next.id === activeProjectIdRef.current) {
|
||||
// 视频生成动辄数分钟,多数 5s 轮次状态没变 —— 内容一致时跳过 setState,避免整棵管线每 5 秒空重渲染。
|
||||
setProjectDetail((prev) => (prev && JSON.stringify(prev) === JSON.stringify(next) ? prev : next));
|
||||
// 仅在本轮在途片段实际完成时同步余额;失败不产生真实扣费,不刷新。
|
||||
const charged = active.some((segment) => next.video_segments.find((item) => item.id === segment.id)?.status === "succeeded");
|
||||
if (charged) void refreshBilling();
|
||||
}
|
||||
}, [activeProjectId]);
|
||||
}, [activeProjectId, refreshBilling]);
|
||||
|
||||
// 静默轮询故事板分镜生成(对标 pollVideosQuiet):有 queued/running 的场就驱动后端出图并刷新,不占全局 loading、不弹 toast。
|
||||
// 这样单场重跑不会把别的场按钮也锁住——生成在后台跑,UI 只按每场自身状态转圈。
|
||||
@@ -432,8 +441,11 @@ export function App() {
|
||||
const next = await api.project(activeProjectId).catch(() => null);
|
||||
if (next && next.id === activeProjectIdRef.current) {
|
||||
setProjectDetail((prev) => (prev && JSON.stringify(prev) === JSON.stringify(next) ? prev : next));
|
||||
// 分镜图成功落库时后端同时结算积分;只在成功终态刷新顶栏余额。
|
||||
const charged = active.some((shot) => next.storyboard_shots?.find((item) => item.id === shot.id)?.status === "succeeded");
|
||||
if (charged) void refreshBilling();
|
||||
}
|
||||
}, [activeProjectId]);
|
||||
}, [activeProjectId, refreshBilling]);
|
||||
|
||||
// 静默刷新导出任务状态(进入拼接页 / 导出后回填成片),不弹 toast。
|
||||
const refreshExport = useCallback(async () => {
|
||||
@@ -679,13 +691,13 @@ export function App() {
|
||||
const { assets, error } = await pollAiTasks([taskId]);
|
||||
// 只刷新当前项目详情(新出的图就在 base_asset_groups 里),不再整页全量 loadData ——
|
||||
// 后者十几个 setState 触发全 PipelinePage 大重渲染,所有背景图被重新赋值 → "每次生成全页图重载"。
|
||||
// 余额受出图扣费影响,单独轻量刷新一下即可,不必连带把 products/projects/全部 assets/通知都重拉。
|
||||
// 成功出图已完成真实扣费,单独轻量同步顶栏余额即可,不必连带重拉其他全局数据。
|
||||
await refreshProjectDetail();
|
||||
api.billingSummary().then((b) => b && setBilling(b)).catch(() => {});
|
||||
if (assets.length === 0) {
|
||||
setNotice({ type: "error", text: error || "生成超时,稍后可在资产里查看" });
|
||||
return null;
|
||||
}
|
||||
await refreshBilling();
|
||||
setNotice({ type: "success", text: okText });
|
||||
return assets[0].id;
|
||||
}
|
||||
@@ -1100,6 +1112,7 @@ export function App() {
|
||||
exportResult={exportResult}
|
||||
onRefreshExport={refreshExport}
|
||||
onRefreshProject={refreshProjectDetail}
|
||||
onRefreshBilling={refreshBilling}
|
||||
onUploadVideoSegment={(segmentId, file) => action(() => api.uploadVideoSegment(pipelineProject.id, segmentId, file), "视频已上传")}
|
||||
onUploadBgm={(file, volume) => action(() => api.uploadBgm(pipelineProject.id, file, volume), "BGM 已上传")}
|
||||
onSaveTimeline={(payload) => action(() => api.saveTimeline(pipelineProject.id, payload), "草稿已保存")}
|
||||
|
||||
Reference in New Issue
Block a user