fix: PMC 图片工作台 — 去多余toast + 费用预估对齐实扣

PMC#23 删除批次后仍弹「图片已生成」:
- 生图成功不再弹全局 toast(批次卡已就地显示结果),也就不会在「生成中删掉该批次」后
  延迟弹出让人误以为删了又生成。

PMC#20 费用预估跟实扣有差别:
- 预估由写死的 ¥0.1/¥0.3/¥0.5 改为按「当前选的生图模型」真实 unit_price 计算
  (后端 estimate_cost=unit_price,如 gpt-image-2=¥2),预估与实扣一致。
- ModelConfig 序列化本就含 unit_price,前端类型补上并据此计算。

附注(同批已在早前提交内生效):PMC#5/#10 多批各自续轮询、PMC#8 并发重跑、
PMC#14/#15/#22 生成后自动滚动+清输入。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
zyc
2026-06-27 17:15:04 +08:00
co-authored by Claude Opus 4.8
parent 00e606a6a6
commit e6e3c48524
3 changed files with 15 additions and 3 deletions
+3 -1
View File
@@ -523,8 +523,10 @@ export function App() {
const res = await pollImageTasks(payload.mode, ids);
// 回传后端归属/新建的对话 id,供工作室把它登记进左栏会话列表并设为 active
return { ...res, conversation_id };
// successText 留空:工作台的批次卡已就地显示出图结果(生成中→已完成),全局右下角「图片已生成」toast 多余,
// 且会在「生成中删掉该批次」后才弹出来,让人以为删了又生成(PMC#23)。靠批次卡反馈即可。
// concurrent:生图支持多批并行,不占全局单飞锁(否则并发重跑被拒成 null→标失败,PMC#8)
}, "图片已生成", { concurrent: true });
}, "", { concurrent: true });
}
// 轮询一批已提交的生图任务直到全部出图/超时;每出一张就回写本地,刷新后可恢复。
+11 -2
View File
@@ -703,6 +703,15 @@ export function ImageWorkbenchPage({
}
const imageModels = modelConfigs.filter((model) => model.capability.includes("image"));
// 每张图实扣单价:取「当前选的生图模型」的 unit_price(火山/gpt-image),没匹配上用第一个图像模型,
// 再兜底 ¥2(后端 estimate_cost=unit_price,默认模型 gpt-image-2=¥2)。前端预估据此算,和后端实扣一致(PMC#20)。
const perImagePrice = (() => {
const want = genModel === "gpt-image" ? "gpt-image" : genModel === "volcano" ? "seedream" : genModel;
const m = imageModels.find((x) => x.name.toLowerCase().includes(want)) || imageModels[0];
const p = Number(m?.unit_price);
return Number.isFinite(p) && p > 0 ? p : 2;
})();
const estimateFee = (n: number) => `¥${(n * perImagePrice).toFixed(2)}`;
/* 模特卡数据来源:期2 改为「模特库」(顶级实体,引用其形象图当上身图参考)。
映射 ModelEntity→Asset 形:id=形象图资产 id(选中即作 model_id 参考图),metadata 记 model_entity_id 溯源。
@@ -1581,7 +1590,7 @@ export function ImageWorkbenchPage({
onSelect={setCount}
/>
<span className="right-meta">
<span className="val">¥{(candidateCount * 0.1).toFixed(2)}</span>
<span className="val">{estimateFee(candidateCount)}</span>
</span>
<button className="send-btn" type="button" onClick={runGenerate} disabled={!canGenerate} title="生成">
<ArrowRight size={15} />
@@ -1958,7 +1967,7 @@ export function ImageWorkbenchPage({
{/* 行31:并发提交——有批次在跑时仍可再次提交,只在提交瞬间不重复触发 */}
<button className="btn btn-primary" type="button" onClick={runGenerate} disabled={!canGenerate}>
<WandSparkles size={13} />
( ¥{(candidateCount * (mode === "model" ? 0.3 : 0.5)).toFixed(2)})
( {estimateFee(candidateCount)})
</button>
{/* YYX#9:去掉生成按钮下方那行说明文字 */}
</div>
+1
View File
@@ -525,6 +525,7 @@ export type ModelConfig = {
display_name: string;
capability: string;
status: string;
unit_price?: string; // 单位价(每张图/每次调用),前端据此算「预估扣费」与后端实扣一致(PMC#20)
};
export type AITask = {