feat(deploy): fix docker deployment and add backend i18n

- Docker Deployment Fixes:
  - Switch base images to docker.m.daocloud.io to resolve registry 401 errors
  - Add Postgres and Redis services to docker-compose.traefik.yml
  - Fix frontend build: replace missing icons (Globe->Location, Chart->TrendCharts)
  - Fix frontend build: resolve pnpm CI/TTY issues and frozen lockfile errors
  - Add missing backend dependencies (sqlalchemy, psycopg2, redis-py, celery, docker-py) in pixi.toml
  - Ensure database tables are created on startup (lifespan event)

- Backend Internationalization (i18n):
  - Add backend/app/core/i18n.py for locale handling
  - Update API endpoints (jobs, tasks, uploads, results) to return localized messages
  - Support 'Accept-Language' header (en/zh)

- Documentation:
  - Update DOCKER_DEPLOYMENT.md with new architecture and troubleshooting
  - Update AGENTS.md with latest stack details and deployment steps
  - Update @fix_plan.md status

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
zly
2026-01-14 12:38:54 +08:00
parent c0f2de02ca
commit 9835b6e341
32 changed files with 1924 additions and 231 deletions

View File

@@ -15,6 +15,15 @@ class JobStatus(str, enum.Enum):
FAILED = "failed" # 执行失败
class StepStatus(str, enum.Enum):
"""步骤状态"""
PENDING = "PENDING"
RUNNING = "RUNNING"
SUCCESS = "SUCCESS"
FAILED = "FAILED"
SKIPPED = "SKIPPED"
class Job(Base):
__tablename__ = "jobs"
@@ -48,3 +57,36 @@ class Job(Base):
started_at = Column(DateTime(timezone=True), nullable=True)
completed_at = Column(DateTime(timezone=True), nullable=True)
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
class Step(Base):
"""任务步骤"""
__tablename__ = "job_steps"
id = Column(Integer, primary_key=True, index=True)
job_id = Column(String, index=True) # ForeignKey("jobs.id") - simplified for SQLite/No-Relation
step_id = Column(String) # digger, shoter, etc.
name = Column(String)
status = Column(Enum(StepStatus), default=StepStatus.PENDING)
start_at = Column(DateTime(timezone=True), nullable=True)
end_at = Column(DateTime(timezone=True), nullable=True)
duration_ms = Column(Integer, nullable=True)
summary = Column(Text, nullable=True)
error = Column(Text, nullable=True)
class JobLog(Base):
"""任务日志"""
__tablename__ = "job_logs"
id = Column(Integer, primary_key=True, index=True)
job_id = Column(String, index=True)
step_id = Column(String, nullable=True)
level = Column(String, default="INFO")
message = Column(Text)
timestamp = Column(DateTime(timezone=True), server_default=func.now())
seq = Column(Integer, default=0)