From 53371aabcd2244d3e5a9750392a3e31077d22c4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E9=B1=BC=E5=BC=80=E5=8F=91?= Date: Sat, 23 May 2026 10:59:47 +0800 Subject: [PATCH] =?UTF-8?q?feat(image):=20=E5=B0=81=E9=9D=A2=E5=BD=A2?= =?UTF-8?q?=E8=B1=A1=E6=8A=A0=E5=9B=BE=E5=A2=9E=E5=8A=A0=E7=A7=AF=E5=88=86?= =?UTF-8?q?=E6=B6=88=E8=80=97=EF=BC=88=E6=AF=8F=E6=AC=A1=2010=20=E7=A7=AF?= =?UTF-8?q?=E5=88=86=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - config/points-config.yaml: 添加 cover_avatar: 10 固定积分 - point_service.py: _CATEGORY_MAP 添加 cover_avatar → 封面形象 - image.py: remove_background 接口前置余额检查 + 后置扣费 - CoverAvatarLibrary.tsx: 上传弹窗显示积分提示,余额不足友好提示 --- python-api/app/api/v1/image.py | 27 +++++++++++++++- python-api/app/services/point_service.py | 1 + python-api/config/points-config.yaml | 3 ++ .../ContentManagement/CoverAvatarLibrary.tsx | 32 ++++++++++++------- 4 files changed, 51 insertions(+), 12 deletions(-) diff --git a/python-api/app/api/v1/image.py b/python-api/app/api/v1/image.py index 1bd5bc6..253dc28 100644 --- a/python-api/app/api/v1/image.py +++ b/python-api/app/api/v1/image.py @@ -7,17 +7,20 @@ import io import logging +import time import uuid from pathlib import Path import httpx from fastapi import APIRouter, Depends, File, HTTPException, Request, UploadFile from pydantic import BaseModel, Field +from sqlalchemy.ext.asyncio import AsyncSession -from app.api.deps import get_current_user +from app.api.deps import get_current_user, get_db from app.config import get_settings from app.models.user import User from app.schemas.common import ApiResponse, success_response +from app.services import point_service as ps from app.services.qiniu_service import get_qiniu_service from app.services.volcengine_mediakit_service import VolcengineMediakitService from app.utils.file_validation import check_upload_file @@ -163,12 +166,23 @@ async def remove_background( req: RemoveBackgroundRequest, current_user: User = Depends(get_current_user), mediakit_service: VolcengineMediakitService = Depends(get_mediakit_service), + db: AsyncSession = Depends(get_db), ) -> ApiResponse[RemoveBackgroundResponse]: """ AI 抠图(火山引擎 MediaKit) 移除图片背景,返回透明背景图片 URL。 + 每次调用消耗 10 积分。 """ + # 前置积分检查 + required_points = ps._calculate_cost("cover_avatar") + check = await ps.check_balance(db, current_user.id, required_points) + if not check["sufficient"]: + raise HTTPException( + status_code=402, + detail=f"积分不足,需要 {required_points} 积分,当前余额 {check['balance']}", + ) + try: logger.info( f"[RemoveBackground] 开始抠图: image_url={req.image_url[:80]}..., scene={req.scene}" @@ -216,6 +230,17 @@ async def remove_background( logger.info(f"[RemoveBackground] 结果已转存七牛云: {qiniu_url[:80]}...") + # 后置扣费(服务已调用成功) + await ps.consume( + db, + user_id=current_user.id, + points=required_points, + source_type="cover_avatar", + source_id=f"cover_avatar_{current_user.id}_{int(time.time() * 1000)}", + description="【封面形象抠图】", + ) + await db.commit() + return success_response( data=RemoveBackgroundResponse(url=qiniu_url), message="抠图成功", diff --git a/python-api/app/services/point_service.py b/python-api/app/services/point_service.py index 9820020..0e5d79e 100644 --- a/python-api/app/services/point_service.py +++ b/python-api/app/services/point_service.py @@ -329,6 +329,7 @@ _CATEGORY_MAP: dict[str, str] = { "compose": "压制成片", "subtitle_burn": "字幕烧录", "cover_design": "封面设计", + "cover_avatar": "封面形象", "wxpay": "充值", "compensation": "充值", "invite": "充值", diff --git a/python-api/config/points-config.yaml b/python-api/config/points-config.yaml index fefc61d..6e4c736 100644 --- a/python-api/config/points-config.yaml +++ b/python-api/config/points-config.yaml @@ -29,6 +29,9 @@ fixed_costs: # 封面设计:根据视频内容自动生成封面图 cover_design: 5 + # 封面形象:上传人物照片 AI 抠图生成透明背景形象 + cover_avatar: 10 + # 压制成片:将多个素材片段合并为最终视频(FFmpeg 拼接) compose: 5 diff --git a/tauri-app/src/pages/ContentManagement/CoverAvatarLibrary.tsx b/tauri-app/src/pages/ContentManagement/CoverAvatarLibrary.tsx index f1dfa3c..1bcd4c1 100644 --- a/tauri-app/src/pages/ContentManagement/CoverAvatarLibrary.tsx +++ b/tauri-app/src/pages/ContentManagement/CoverAvatarLibrary.tsx @@ -103,8 +103,13 @@ export default function CoverAvatarLibrary() { toast.success(`「${avatar.name}」已保存`); } catch (err) { const msg = err instanceof Error ? err.message : '上传失败'; - progress.error(msg); - toast.error(msg); + if (msg.includes('积分不足')) { + progress.error('积分不足'); + toast.error('积分不足,每次上传封面形象消耗 10 积分,请先充值'); + } else { + progress.error(msg); + toast.error(msg); + } } setUploadName(''); @@ -256,15 +261,20 @@ export default function CoverAvatarLibrary() { -
- - +
+ + 每次上传消耗 10 积分 + +
+ + +