feat: 视频生成使用系统素材时每个额外收取 2 积分

This commit is contained in:
小鱼开发
2026-05-22 09:40:23 +08:00
parent 497e65d86d
commit 574874c856
2 changed files with 34 additions and 18 deletions
@@ -378,7 +378,14 @@ export function useVideoGeneration({
};
});
}
const actualVideoPoints = Math.ceil(totalAudioDuration) * videoMultiplier;
const baseVideoPoints = Math.ceil(totalAudioDuration) * videoMultiplier;
// 系统素材额外收费:每个空镜使用的系统素材额外 2 积分
const systemMaterialCount = shots.filter((s: ScriptShot) => {
if (s.type !== 'empty_shot') return false;
const matched = materialMatchMap[String(s.id)];
return matched && (matched.url.startsWith('http://') || matched.url.startsWith('https://'));
}).length;
const actualVideoPoints = baseVideoPoints + systemMaterialCount * 2;
await pointsApi.consumePoints({
points: actualVideoPoints,
sourceType: 'video',
+26 -17
View File
@@ -60,23 +60,6 @@ export default function VideoGeneration() {
const dubbingAudioDuration = useProjectStore(state => state.dubbingAudioDuration);
// 视频生成积分:统一用完整配音音频时长作为唯一口径(与后端预检、实际扣费保持一致)
const estimatedVideoPoints = useMemo(() => {
// 优先使用已保存的配音音频实际时长,确保预估 = 实际扣费
if (dubbingAudioDuration && dubbingAudioDuration > 0) {
return Math.ceil(dubbingAudioDuration) * videoMultiplier;
}
// 降级:按分镜 actualDuration 累加(配音后已更新)
const totalDur = shots.reduce((sum, shot) => {
if (shot.actualDuration && shot.actualDuration > 0) {
return sum + shot.actualDuration;
}
const durStr = typeof shot.duration === 'string' ? shot.duration : '5s';
return sum + parseFloat(durStr.replace(/[^0-9.]/g, '') || '0');
}, 0);
return Math.ceil(totalDur) * videoMultiplier;
}, [shots, videoMultiplier, dubbingAudioDuration]);
const [activeScene, setActiveScene] = useState<number>(1);
// 控制右侧预览区显示完整视频还是镜头素材
@@ -149,6 +132,32 @@ export default function VideoGeneration() {
setMaterialMatchMap,
} = useEmptyShotMaterials(shots, projectId);
// 视频生成积分:统一用完整配音音频时长作为唯一口径(与后端预检、实际扣费保持一致)
const estimatedVideoPoints = useMemo(() => {
// 优先使用已保存的配音音频实际时长,确保预估 = 实际扣费
let basePoints = 0;
if (dubbingAudioDuration && dubbingAudioDuration > 0) {
basePoints = Math.ceil(dubbingAudioDuration) * videoMultiplier;
} else {
// 降级:按分镜 actualDuration 累加(配音后已更新)
const totalDur = shots.reduce((sum, shot) => {
if (shot.actualDuration && shot.actualDuration > 0) {
return sum + shot.actualDuration;
}
const durStr = typeof shot.duration === 'string' ? shot.duration : '5s';
return sum + parseFloat(durStr.replace(/[^0-9.]/g, '') || '0');
}, 0);
basePoints = Math.ceil(totalDur) * videoMultiplier;
}
// 系统素材额外收费:每个空镜使用的系统素材额外 2 积分
const systemMaterialCount = shots.filter((s) => {
if (s.type !== 'empty_shot') return false;
const matched = materialMatchMap[String(s.id)];
return matched && (matched.url.startsWith('http://') || matched.url.startsWith('https://'));
}).length;
return basePoints + systemMaterialCount * 2;
}, [shots, videoMultiplier, dubbingAudioDuration, materialMatchMap]);
// 同步 activeScene 与 shots 数据
useEffect(() => {
if (shots.length > 0 && !shots.find((s) => Number(s.id) === activeScene)) {