feat: 支持皮肤包就地更新与新建即传

- 新增皮肤包更新接口,覆盖内容保持文件名不变,避免 APP 配置的主题引用失效
- 上传新皮肤后自动为空主题目录的证书选中该皮肤
- 新建 APP 保存后不关弹窗并回填 upload_key,可直接上传皮肤

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
shenlei
2026-07-29 15:14:08 +09:00
co-authored by Claude Opus 4.8
parent bb8a0afeac
commit 5014376b81
2 changed files with 78 additions and 3 deletions
+28 -1
View File
@@ -316,7 +316,7 @@ async def create_app(app: dict):
apps[new_id] = app
config["apps"] = apps
save_config(config)
return {"id": new_id, "message": "App 已创建"}
return {"id": new_id, "upload_key": app["upload_key"], "message": "App 已创建"}
@router.put("/apps/{app_id}")
@@ -410,6 +410,33 @@ async def upload_skin(upload_key: str, file: UploadFile = File(...)):
return {"message": "皮肤包上传成功", "name": file.filename}
@router.put("/skins/{upload_key}/{skin_name}")
async def replace_skin(upload_key: str, skin_name: str, file: UploadFile = File(...)):
"""替换已有皮肤包内容,保持原文件名不变。
APP 配置的 theme 通过文件名(去掉 .zip)引用皮肤包,若上传新文件名会新增一个皮肤而非更新,
导致原引用失效。此接口就地覆盖指定皮肤,确保被引用的皮肤可以更新。
"""
if not file.filename or not file.filename.lower().endswith(".zip"):
raise HTTPException(status_code=400, detail="仅支持 .zip 格式")
config = load_config()
app_id, _ = _find_app_by_upload_key(config, upload_key)
if not app_id:
raise HTTPException(status_code=404, detail="App 不存在")
app_skins_dir = SKINS_DIR / upload_key
skin_path = app_skins_dir / skin_name
if not skin_path.exists():
raise HTTPException(status_code=404, detail="皮肤包不存在")
content = await file.read()
with open(skin_path, "wb") as f:
f.write(content)
return {"message": "皮肤包已更新", "name": skin_name}
@router.delete("/skins/{upload_key}/{skin_name}")
async def delete_skin(upload_key: str, skin_name: str):
"""删除指定皮肤包"""