Files
beige/backend/main.py
yangqianqian 4bed7425a8 A8多套打包+M4归档+R5多图:存量功能备份
A8 多套交付包(packaging_task.py):
- 修复交付包只打第1条混乱note的bug,按ImageCandidate.strategy分A/B/C组
- 每组生独立note_0N夹(6图+文案.txt),同seq留最新去重,老数据兼容
- task74端到端验:3套各6图,独立agent7项交叉验证全过

M4 归档(tasks.py/exports.py/前端):
- list_tasks加date_from/date_to/product_id筛选+product_name批量填(防N+1)
- 新增exports.py:产品JSON导出+标杆CSV导出(UTF-8 BOM)
- 前端HistoryFilters日期/产品筛选+产品列+打回原因红banner
- response.py加raise_param_error;独立agent验A1/A2/A9通过

R5 产品多图(product_images.py/020迁移/前端):
- product_images表+5端点(上传/列/改场景/设主图/删图)
- 生图按ROLE_SCENE_PREFERENCE选对应场景图,回落primary
- 前端ProductImageManager多图画廊

R6 账号config拆页(settings/):
- 配置页按角色拆/settings(运营+组长+admin)+/config(仅admin)
- Key只显末4位不显余额(守红线)

核销表对齐真实代码状态:D1改稿框/M7裂变/E12评图分纠偏为已完成(曾漏回写)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 17:32:49 +08:00

103 lines
4.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
main.py — FastAPI 应用入口
统一响应包络 / 全局异常处理 / 健康检查 / 路由注册
"""
import logging
import os
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from fastapi.staticfiles import StaticFiles
from app.core.config import get_settings
from app.core.response import CloverHTTPException, ErrorCode
logger = logging.getLogger(__name__)
settings = get_settings()
def create_app() -> FastAPI:
app = FastAPI(
title="Clover API",
version="0.1.0",
docs_url="/docs" if settings.APP_ENV != "production" else None,
redoc_url=None,
)
# ── CORS ──────────────────────────────────────────
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # 生产环境收窄到前端域名
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# ── 全局异常处理(统一包络)──────────────────────
@app.exception_handler(CloverHTTPException)
async def clover_http_exception_handler(request: Request, exc: CloverHTTPException):
return JSONResponse(
status_code=exc.status_code,
content={"code": exc.biz_code, "message": exc.biz_message},
)
@app.exception_handler(Exception)
async def generic_exception_handler(request: Request, exc: Exception):
logger.error("Unhandled exception: %s %s%s", request.method, request.url, exc)
return JSONResponse(
status_code=500,
content={"code": ErrorCode.SERVER_ERROR, "message": "服务器内部错误"},
)
# ── 健康检查Docker 健康检查用)──────────────────
@app.get("/health")
async def health():
return {"status": "ok"}
# ── 路由注册(每个模块路由独立文件,这里汇总注册)─
_register_routers(app)
# ── 静态文件G4坑修复图片 /uploads 路由)──────
uploads_dir = os.path.join(os.path.dirname(__file__), "uploads")
os.makedirs(uploads_dir, exist_ok=True)
app.mount("/uploads", StaticFiles(directory=uploads_dir), name="uploads")
return app
def _register_routers(app: FastAPI) -> None:
from app.api.v1.auth import router as auth_router
from app.api.v1.api_keys import router as api_keys_router
from app.api.v1.products import router as products_router
from app.api.v1.product_images import router as product_images_router
from app.api.v1.benchmarks import router as benchmarks_router
from app.api.v1.tasks import router as tasks_router
from app.api.v1.task_actions import router as task_actions_router
from app.api.v1.review import router as review_router
from app.api.v1.delivery import router as delivery_router
from app.api.v1.stream import router as stream_router
from app.api.v1.workspaces import router as workspaces_router
from app.api.v1.fission import router as fission_router
from app.api.v1.exports import router as exports_router
prefix = "/api/v1"
app.include_router(auth_router, prefix=prefix)
app.include_router(api_keys_router, prefix=prefix)
# 导出 router 必须在 products_router 之前:否则 /products/export 被 /products/{product_id} 吞掉
app.include_router(exports_router, prefix=prefix)
app.include_router(products_router, prefix=prefix)
app.include_router(product_images_router, prefix=prefix)
app.include_router(benchmarks_router, prefix=prefix)
app.include_router(tasks_router, prefix=prefix)
app.include_router(task_actions_router, prefix=prefix)
app.include_router(review_router, prefix=prefix)
app.include_router(delivery_router, prefix=prefix)
app.include_router(stream_router, prefix=prefix)
app.include_router(workspaces_router, prefix=prefix)
app.include_router(fission_router, prefix=prefix)
app = create_app()