会员积分改版V4 | 修复历史素材云兼容BUG | build app/admin

This commit is contained in:
2026-08-11 10:27:06 +08:00
parent 392b9f4117
commit ba32d6f55e
8 changed files with 810 additions and 804 deletions
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -28,7 +28,7 @@
}
})();
</script>
<script type="module" crossorigin src="/assets/index-D-7FxsJd.js"></script>
<script type="module" crossorigin src="/assets/index-C0AXQCDm.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-D3fwIbOp.css">
</head>
<body>
+1 -1
View File
@@ -1 +1 @@
{"root":["./src/app.tsx","./src/env.d.ts","./src/main.tsx","./src/api/client.ts","./src/api/crypto.ts","./src/api/index.ts","./src/components/preresultdisplay.tsx","./src/components/quotaadjustmodal.tsx","./src/components/generation/generationtaskresourcegrid.tsx","./src/pages/adminapikeys.tsx","./src/pages/adminapimodelpricings.tsx","./src/pages/adminapiusage.tsx","./src/pages/adminauthoriz.tsx","./src/pages/adminconsume.tsx","./src/pages/admincontactrequests.tsx","./src/pages/admincreditratios.tsx","./src/pages/admincreditrecords.tsx","./src/pages/admindashboard.tsx","./src/pages/admingenerationairecords.tsx","./src/pages/admingenerationrecords.tsx","./src/pages/adminhomematerials.tsx","./src/pages/adminhotopeningreplicationdetail.tsx","./src/pages/adminhotopeningreplications.tsx","./src/pages/adminimageengines.tsx","./src/pages/adminindustries.tsx","./src/pages/admininvoices.tsx","./src/pages/adminlayout.tsx","./src/pages/adminloginpage.tsx","./src/pages/adminmateriallist.tsx","./src/pages/adminmenuconfig.tsx","./src/pages/adminmodels.tsx","./src/pages/adminnotificationmanager.tsx","./src/pages/adminoauthlist.tsx","./src/pages/adminoauthapplist.tsx","./src/pages/adminoperationlogs.tsx","./src/pages/adminpaymentconfig.tsx","./src/pages/adminpaymentstats.tsx","./src/pages/adminplatform.tsx","./src/pages/adminpretesttemplates.tsx","./src/pages/adminprivateportraitprojects.tsx","./src/pages/adminrechargepackages.tsx","./src/pages/adminreplicationprojectdetail.tsx","./src/pages/adminsettings.tsx","./src/pages/adminshotreplications.tsx","./src/pages/adminshottasksetdetail.tsx","./src/pages/adminteams.tsx","./src/pages/adminusers.tsx","./src/pages/adminvideoengines.tsx","./src/pages/adminvideopromptschemaconfig.tsx","./src/pages/adminvideoupscale.tsx","./src/pages/adminreplication/components/jsoncollapse.tsx","./src/pages/adminreplication/components/mediapreview.tsx","./src/pages/adminreplication/components/statustag.tsx","./src/pages/adminreplication/components/videopromptschemaviewer.tsx","./src/pages/homematerials/homematerialassettable.tsx","./src/pages/homematerials/homematerialcategorypanel.tsx","./src/pages/homematerials/homematerialuploadmodal.tsx","./src/pages/homematerials/mediareferenceseditor.tsx","./src/pages/homematerials/watermarkeditor.tsx","./src/pages/homematerials/watermarklibrarymodal.tsx","./src/pages/homematerials/watermarkpreview.tsx","./src/store/index.ts","./src/types/index.ts","./src/types/xlsx-js-style.d.ts","./src/utils/clipboard.ts","./src/utils/excelexport.ts","./src/utils/formatdate.ts","./src/utils/generationtaskstatus.ts","./src/utils/resourceurl.ts","./src/utils/shotreplicatestatus.ts","./src/utils/videopromptschema.ts"],"version":"6.0.3"}
{"root":["./src/app.tsx","./src/env.d.ts","./src/main.tsx","./src/api/client.ts","./src/api/crypto.ts","./src/api/index.ts","./src/components/preresultdisplay.tsx","./src/components/quotaadjustmodal.tsx","./src/components/generation/generationtaskresourcegrid.tsx","./src/pages/adminapikeys.tsx","./src/pages/adminapimodelpricings.tsx","./src/pages/adminapiusage.tsx","./src/pages/adminauthoriz.tsx","./src/pages/adminconsume.tsx","./src/pages/admincontactrequests.tsx","./src/pages/admincreditproducts.tsx","./src/pages/admincreditratios.tsx","./src/pages/admincreditrecords.tsx","./src/pages/admindashboard.tsx","./src/pages/admingenerationairecords.tsx","./src/pages/admingenerationrecords.tsx","./src/pages/adminhomematerials.tsx","./src/pages/adminhotopeningreplicationdetail.tsx","./src/pages/adminhotopeningreplications.tsx","./src/pages/adminimageengines.tsx","./src/pages/adminindustries.tsx","./src/pages/admininvoices.tsx","./src/pages/adminlayout.tsx","./src/pages/adminllmbillingexecutions.tsx","./src/pages/adminllmbillingpolicies.tsx","./src/pages/adminloginpage.tsx","./src/pages/adminmateriallist.tsx","./src/pages/adminmenuconfig.tsx","./src/pages/adminmodels.tsx","./src/pages/adminnotificationmanager.tsx","./src/pages/adminoauthlist.tsx","./src/pages/adminoauthapplist.tsx","./src/pages/adminoperationlogs.tsx","./src/pages/adminpaymentconfig.tsx","./src/pages/adminpaymentstats.tsx","./src/pages/adminplatform.tsx","./src/pages/adminpretesttemplates.tsx","./src/pages/adminprivateportraitprojects.tsx","./src/pages/adminrechargepackages.tsx","./src/pages/adminreplicationprojectdetail.tsx","./src/pages/adminsettings.tsx","./src/pages/adminshotreplications.tsx","./src/pages/adminshottasksetdetail.tsx","./src/pages/adminteams.tsx","./src/pages/adminusers.tsx","./src/pages/adminvideoengines.tsx","./src/pages/adminvideopromptschemaconfig.tsx","./src/pages/adminvideoupscale.tsx","./src/pages/adminreplication/components/jsoncollapse.tsx","./src/pages/adminreplication/components/mediapreview.tsx","./src/pages/adminreplication/components/statustag.tsx","./src/pages/adminreplication/components/videopromptschemaviewer.tsx","./src/pages/homematerials/homematerialassettable.tsx","./src/pages/homematerials/homematerialcategorypanel.tsx","./src/pages/homematerials/homematerialuploadmodal.tsx","./src/pages/homematerials/mediareferenceseditor.tsx","./src/pages/homematerials/watermarkeditor.tsx","./src/pages/homematerials/watermarklibrarymodal.tsx","./src/pages/homematerials/watermarkpreview.tsx","./src/store/index.ts","./src/types/index.ts","./src/types/xlsx-js-style.d.ts","./src/utils/clipboard.ts","./src/utils/excelexport.ts","./src/utils/formatdate.ts","./src/utils/generationtaskstatus.ts","./src/utils/resourceurl.ts","./src/utils/shotreplicatestatus.ts","./src/utils/videopromptschema.ts"],"version":"6.0.3"}
+7 -3
View File
@@ -18,9 +18,13 @@ class UploadResourceModuleEnum(StrEnum):
class UploadResourceTypeEnum(StrEnum):
"""上传资源类型。"""
IMAGE = "Image"
VIDEO = "Video"
AUDIO = "Audio"
IMAGE = "image"
VIDEO = "video"
AUDIO = "audio"
F_IMAGE = "Image"
F_VIDEO = "Video"
F_AUDIO = "Audio"
SHOT_SEGMENT = "shot_segment"
PDF = "pdf"
FILE = "file"
@@ -64,20 +64,20 @@ class DownloadedAsset(NamedTuple):
def _max_bytes(asset_type: str) -> int:
return VP_V3_VIDEO_MAX_BYTES if asset_type == UploadResourceTypeEnum.VIDEO.value else VP_V3_IMAGE_MAX_BYTES
return VP_V3_VIDEO_MAX_BYTES if asset_type == UploadResourceTypeEnum.F_VIDEO.value else VP_V3_IMAGE_MAX_BYTES
def _allowed_mime_set(asset_type: str) -> set[str]:
return VIDEO_MIME_ALLOWED if asset_type == UploadResourceTypeEnum.VIDEO.value else IMAGE_MIME_ALLOWED
return VIDEO_MIME_ALLOWED if asset_type == UploadResourceTypeEnum.F_VIDEO.value else IMAGE_MIME_ALLOWED
def _safe_ext(filename: str, asset_type: str) -> str:
ext = (os.path.splitext(filename or "")[1].lower().lstrip(".") or "").strip()
allowed = VIDEO_EXT_ALLOWED if asset_type == UploadResourceTypeEnum.VIDEO.value else IMAGE_EXT_ALLOWED
allowed = VIDEO_EXT_ALLOWED if asset_type == UploadResourceTypeEnum.F_VIDEO.value else IMAGE_EXT_ALLOWED
if ext and ext in allowed:
return ext
# fallback
return "mp4" if asset_type == UploadResourceTypeEnum.VIDEO.value else "png"
return "mp4" if asset_type == UploadResourceTypeEnum.F_VIDEO.value else "png"
def _get_ffprobe_bin() -> str:
@@ -150,7 +150,7 @@ def _build_destination(*, api_key_id: str, asset_type: str, original_filename: s
month = f"{now.month:02d}"
day = f"{now.day:02d}"
sub_type = "videos" if asset_type == UploadResourceTypeEnum.VIDEO.value else "images"
sub_type = "videos" if asset_type == UploadResourceTypeEnum.F_VIDEO.value else "images"
rel_dir = Path("api") / "private_portrait_virtual" / sub_type / year / month / day
filename = f"vp_v3_{safe_uuid}.{ext}"
@@ -198,7 +198,7 @@ def _guess_ext_from_mime(mime: str | None, asset_type: str) -> str | None:
if not mime:
return None
# 按 asset_type 优先匹配
allowed_exts = VIDEO_EXT_ALLOWED if asset_type == UploadResourceTypeEnum.VIDEO.value else IMAGE_EXT_ALLOWED
allowed_exts = VIDEO_EXT_ALLOWED if asset_type == UploadResourceTypeEnum.F_VIDEO.value else IMAGE_EXT_ALLOWED
guesses = mimetypes.guess_all_extensions(mime.strip().lower()) or []
for g in guesses:
ext = g.lower().lstrip(".")
@@ -232,7 +232,7 @@ async def upload_asset_file(
- 落盘到 /uploads/images|videos/vp_v3/{api_key_id_short}/{yyyy}/{mm}/{dd}/
- 返回 url + 虚拟 resource_idhash 形式)
"""
if asset_type not in {UploadResourceTypeEnum.IMAGE.value, UploadResourceTypeEnum.VIDEO.value}:
if asset_type not in {UploadResourceTypeEnum.F_IMAGE.value, UploadResourceTypeEnum.F_VIDEO.value}:
raise HTTPException(status_code=400, detail="虚拟素材上传仅支持图片或视频")
max_size = _max_bytes(asset_type)
@@ -317,7 +317,7 @@ async def download_url_to_local(
- 下载一半失败 → 清理临时文件,不留下半截
- 视频可选探测 ffprobe,失败不抛错(调用方自行用 payload.video_duration
"""
if asset_type not in {UploadResourceTypeEnum.IMAGE.value, UploadResourceTypeEnum.VIDEO.value}:
if asset_type not in {UploadResourceTypeEnum.F_IMAGE.value, UploadResourceTypeEnum.F_VIDEO.value}:
raise HTTPException(status_code=400, detail="虚拟素材仅支持图片或视频")
# URL 合法性
@@ -465,7 +465,7 @@ async def download_url_to_local(
# --- 第二步:视频可选 ffprobe 探测时长 ---
duration: float | None = None
if asset_type == UploadResourceTypeEnum.VIDEO.value:
if asset_type == UploadResourceTypeEnum.F_VIDEO.value:
duration = _probe_duration_optional(Path(temp_path))
# --- 第三步:落到最终目录(与 _build_destination 一致的目录结构/权限) ---
@@ -483,7 +483,7 @@ async def download_url_to_local(
if not mime:
mime, _ = mimetypes.guess_type(final_filename)
if not mime:
mime = "image/png" if asset_type == UploadResourceTypeEnum.IMAGE.value else "video/mp4"
mime = "image/png" if asset_type == UploadResourceTypeEnum.F_IMAGE.value else "video/mp4"
suggested_name: str | None = None
try:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -27,7 +27,7 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet" />
<title>民众智创</title>
<script type="module" crossorigin src="/assets/index-C_heyhPf.js"></script>
<script type="module" crossorigin src="/assets/index-Bni9FiTX.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DtYH0-uL.css">
</head>
<body>