fix: 消除积分预检硬编码,统一使用 getRule() 动态读取
CoverDesign: 预检 COVER_POINTS=2 → getRule('cover_design')?.points || 2
SubtitleBurning: 预检 SUBTITLE_POINTS=2 → getRule('subtitle_burn')?.points || 2
VideoCompose: 预检 COMPOSE_POINTS=5 → getRule('compose')?.points || 5
确保预检口径与扣费口径一致,避免后端规则调整后出现余额误判
This commit is contained in:
@@ -248,10 +248,10 @@ export default function CoverDesign() {
|
||||
if (!projectId) {return;}
|
||||
if (!config.mainTitle.trim()) {return;}
|
||||
|
||||
const COVER_POINTS = 2;
|
||||
const coverPoints = usePointStore.getState().getRule('cover_design')?.points || 2;
|
||||
await fetchBalance();
|
||||
const currentBalance = usePointStore.getState().balance;
|
||||
if (currentBalance < COVER_POINTS) {
|
||||
if (currentBalance < coverPoints) {
|
||||
setShowPointsModal(true);
|
||||
return;
|
||||
}
|
||||
@@ -636,39 +636,41 @@ export default function CoverDesign() {
|
||||
onClick={handleGenerate}
|
||||
style={{ flex: 1 }}
|
||||
>
|
||||
{isDesigning ? '生成中...' : `重新生成(${usePointStore.getState().getRule('cover_design')?.points || 2}积分)`}
|
||||
{isDesigning
|
||||
? '生成中...'
|
||||
: coverPath
|
||||
? `重新生成(${usePointStore.getState().getRule('cover_design')?.points || 2}积分)`
|
||||
: `生成封面(${usePointStore.getState().getRule('cover_design')?.points || 2}积分)`}
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-secondary"
|
||||
onClick={async () => {
|
||||
if (!coverPath) {
|
||||
toast.info('请先生成封面');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const filename = coverPath.split(/[\\/]/).pop() || 'cover.png';
|
||||
const targetPath = await save({
|
||||
defaultPath: filename,
|
||||
filters: [{ name: '图片', extensions: ['png'] }],
|
||||
});
|
||||
if (!targetPath) {return;}
|
||||
const res = await invoke<{ code: number; data?: string; message: string }>('export_product', {
|
||||
sourcePath: coverPath,
|
||||
targetPath,
|
||||
});
|
||||
if (res.code === 200) {
|
||||
toast.success('封面导出成功');
|
||||
} else {
|
||||
toast.error(res.message || '导出失败');
|
||||
{coverPath && (
|
||||
<button
|
||||
className="btn btn-secondary"
|
||||
onClick={async () => {
|
||||
try {
|
||||
const filename = coverPath.split(/[\\/]/).pop() || 'cover.png';
|
||||
const targetPath = await save({
|
||||
defaultPath: filename,
|
||||
filters: [{ name: '图片', extensions: ['png'] }],
|
||||
});
|
||||
if (!targetPath) {return;}
|
||||
const res = await invoke<{ code: number; data?: string; message: string }>('export_product', {
|
||||
sourcePath: coverPath,
|
||||
targetPath,
|
||||
});
|
||||
if (res.code === 200) {
|
||||
toast.success('封面导出成功');
|
||||
} else {
|
||||
toast.error(res.message || '导出失败');
|
||||
}
|
||||
} catch (e) {
|
||||
toast.error('导出失败');
|
||||
}
|
||||
} catch (e) {
|
||||
toast.error('导出失败');
|
||||
}
|
||||
}}
|
||||
style={{ flex: 1 }}
|
||||
>
|
||||
导出封面
|
||||
</button>
|
||||
}}
|
||||
style={{ flex: 1 }}
|
||||
>
|
||||
导出封面
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -333,11 +333,11 @@ export default function SubtitleBurning() {
|
||||
return;
|
||||
}
|
||||
|
||||
// 积分预检:字幕烧录固定消耗 2 积分
|
||||
const SUBTITLE_POINTS = 2;
|
||||
// 积分预检:字幕烧录
|
||||
const subtitlePoints = usePointStore.getState().getRule('subtitle_burn')?.points || 2;
|
||||
await fetchBalance();
|
||||
const currentBalance = usePointStore.getState().balance;
|
||||
if (currentBalance < SUBTITLE_POINTS) {
|
||||
if (currentBalance < subtitlePoints) {
|
||||
setShowPointsModal(true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -217,11 +217,11 @@ export default function VideoCompose() {
|
||||
return;
|
||||
}
|
||||
|
||||
// 前置积分检查:压制成片固定消耗 5 积分
|
||||
const COMPOSE_POINTS = 5;
|
||||
// 前置积分检查:压制成片
|
||||
const composePoints = usePointStore.getState().getRule('compose')?.points || 5;
|
||||
await fetchBalance();
|
||||
const currentBalance = usePointStore.getState().balance;
|
||||
if (currentBalance < COMPOSE_POINTS) {
|
||||
if (currentBalance < composePoints) {
|
||||
setShowPointsModal(true);
|
||||
return;
|
||||
}
|
||||
@@ -266,11 +266,13 @@ export default function VideoCompose() {
|
||||
useProgressStore.getState().update('正在混合背景音乐...');
|
||||
const bgmFullPath = bgmMusicPath;
|
||||
const mixRes = await invoke<{ code: number; data?: string; message: string }>('mix_bgm_to_video', {
|
||||
videoPath: result,
|
||||
bgmPath: bgmFullPath,
|
||||
outputPath: result,
|
||||
videoVolume: 1.0,
|
||||
bgmVolume: (bgmVolume ?? 0.25),
|
||||
args: {
|
||||
videoPath: result,
|
||||
bgmPath: bgmFullPath,
|
||||
outputPath: result,
|
||||
videoVolume: 1.0,
|
||||
bgmVolume: (bgmVolume ?? 0.25),
|
||||
},
|
||||
});
|
||||
if (mixRes.code !== 200) {
|
||||
console.warn('BGM 混合失败,使用无 BGM 版本:', mixRes.message);
|
||||
|
||||
Reference in New Issue
Block a user