Files
beige/backend/app/core/config.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

82 lines
3.1 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.
"""
app/core/config.py — 环境变量加载 + 启动校验
必填项缺失则启动失败,不静默。
"""
import os
from functools import lru_cache
from pydantic import field_validator
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
# ── 必填(缺失启动保护)───────────────────────────
FERNET_KEY: str
JWT_SECRET: str
DATABASE_URL: str
MONGO_URI: str
REDIS_URL: str
# ── AI 提供商(不写死默认,可配置)──────────────────
IMAGE_PROVIDER_PRIMARY: str = "gpt"
IMAGE_PROVIDER_FALLBACK: str = "gemini"
IMAGE_API_BASE: str = ""
IMAGE_MODEL: str = "gpt-image-2"
MODEL_IMAGE: str = "gpt-image-2" # 别名,与 IMAGE_MODEL 同义
MODEL_TEXT: str = "claude-opus-4-8"
MODEL_VISION: str = "" # 视觉模型verify_real_image 脚本用)
CLAUDE_API_URL: str = ""
GEMINI_API_URL: str = ""
# ── 多 Provider Key各人自录测试/真实出图脚本用)──
APIPORTS_BASE_URL: str = ""
APIPORTS_KEY: str = ""
CODEPROXY_BASE_URL: str = ""
CODEPROXY_KEY: str = ""
# ── 应用配置 ──────────────────────────────────────
APP_ENV: str = "development"
JWT_EXPIRE_MINUTES: int = 60 * 24 * 7 # 7天
CELERY_BROKER_URL: str = ""
CELERY_RESULT_BACKEND: str = ""
# ── 并发限制(可配置,不写死)─────────────────────
# 倩倩姐红线:每用户并发上限 5 个任务(客户侧实际跑几个再观察调整)。
MAX_CONCURRENT_TASKS_PER_USER: int = 5
# ── 文件存储路径 ──────────────────────────────────
UPLOAD_BASE_PATH: str = "uploads/packages"
# StaticFiles 实际服务的绝对目录(与 main.py app.mount("/uploads", .../uploads) 一致)。
# 容器内 main.py 在 /app/main.py故 uploads 绝对根 = /app/uploads。
# 所有写盘/读盘统一锚定此根,避免 api(cwd=/app) 与 worker(cwd=/) 相对路径解析不一致。
UPLOAD_ABS_ROOT: str = "/app/uploads"
model_config = {"env_file": ".env", "case_sensitive": True, "extra": "ignore"}
@field_validator("FERNET_KEY")
@classmethod
def fernet_key_not_empty(cls, v: str) -> str:
if not v or len(v) < 32:
raise ValueError("FERNET_KEY must be set and at least 32 chars")
return v
@field_validator("JWT_SECRET")
@classmethod
def jwt_secret_not_empty(cls, v: str) -> str:
if not v or len(v) < 32:
raise ValueError("JWT_SECRET must be at least 32 characters")
return v
def celery_broker(self) -> str:
return self.CELERY_BROKER_URL or self.REDIS_URL
def celery_backend(self) -> str:
return self.CELERY_RESULT_BACKEND or self.REDIS_URL
@lru_cache()
def get_settings() -> Settings:
"""单例配置,启动时校验一次。"""
return Settings()