feat():learning后台管理项目初始化
This commit is contained in:
124
scripts/invite_code_api.py
Normal file
124
scripts/invite_code_api.py
Normal file
@@ -0,0 +1,124 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
邀请码申请 API - 简洁版本
|
||||
|
||||
使用方法:
|
||||
1. 直接运行: ./scripts/run_invite_api.sh
|
||||
2. 或者: uv run scripts/invite_code_api.py
|
||||
3. 访问: POST http://localhost:8000/api/invite-code/apply
|
||||
|
||||
默认使用 AWS RDS 数据库(与 Go 项目共享)
|
||||
如需使用本地数据库,请设置环境变量或创建 scripts/.env 文件
|
||||
"""
|
||||
|
||||
import os
|
||||
from datetime import datetime, timezone
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from pydantic import BaseModel, EmailStr
|
||||
from sqlalchemy import create_engine, Column, Integer, String, DateTime, Text
|
||||
from sqlalchemy.orm import declarative_base, Session
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
|
||||
# 数据库配置 - 从环境变量读取(默认使用 AWS RDS 配置)
|
||||
DB_USER = os.getenv("DB_USER", "goalfymax_prod")
|
||||
DB_PASSWORD = os.getenv("DB_PASSWORD", "X6cQDaOLOifFBOMq")
|
||||
DB_HOST = os.getenv("DB_HOST", "goalfyagent-aurora-mysql-staging.cb2sq6y2mg93.us-west-2.rds.amazonaws.com")
|
||||
DB_PORT = os.getenv("DB_PORT", "3306")
|
||||
DB_NAME = os.getenv("DB_NAME", "goalfymax_prod")
|
||||
|
||||
DATABASE_URL = f"mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}?charset=utf8mb4"
|
||||
|
||||
Base = declarative_base()
|
||||
engine = create_engine(DATABASE_URL, echo=False, pool_pre_ping=True)
|
||||
|
||||
# 数据模型 - 与 Go 项目的 admin_invite_code_applications 表结构保持一致
|
||||
class InviteCodeApplication(Base):
|
||||
__tablename__ = "admin_invite_code_applications"
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||
email = Column(String(255), nullable=False, index=True)
|
||||
reason = Column(Text, nullable=True)
|
||||
language = Column(String(10), nullable=False, default="zh")
|
||||
status = Column(String(20), nullable=False, default="pending", index=True)
|
||||
created_at = Column(DateTime, nullable=False, default=lambda: datetime.now(timezone.utc))
|
||||
updated_at = Column(DateTime, nullable=False, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))
|
||||
|
||||
# 不自动创建表(使用 Go 项目已有的表结构)
|
||||
# Base.metadata.create_all(engine)
|
||||
|
||||
# FastAPI 应用
|
||||
app = FastAPI(title="邀请码申请 API")
|
||||
|
||||
# 请求/响应模型
|
||||
class ApplicationRequest(BaseModel):
|
||||
email: EmailStr
|
||||
reason: Optional[str] = None
|
||||
language: Optional[str] = "zh" # zh 或 en,默认 zh
|
||||
|
||||
class ApplicationResponse(BaseModel):
|
||||
id: int
|
||||
email: str
|
||||
reason: Optional[str]
|
||||
language: str
|
||||
status: str
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
class SuccessResponse(BaseModel):
|
||||
code: int = 0
|
||||
message: str
|
||||
data: ApplicationResponse
|
||||
|
||||
# API 端点
|
||||
@app.post("/api/invite-code/apply", response_model=SuccessResponse)
|
||||
async def submit_application(req: ApplicationRequest):
|
||||
"""提交邀请码申请"""
|
||||
|
||||
with Session(engine) as session:
|
||||
# 检查是否已有待处理或已通过的申请
|
||||
existing = session.query(InviteCodeApplication).filter(
|
||||
InviteCodeApplication.email == req.email,
|
||||
InviteCodeApplication.status.in_(["pending", "approved"])
|
||||
).first()
|
||||
|
||||
if existing:
|
||||
if existing.status == "pending":
|
||||
raise HTTPException(status_code=400, detail="您已经提交过申请,请等待审核")
|
||||
if existing.status == "approved":
|
||||
raise HTTPException(status_code=400, detail="您的申请已通过,请检查邮箱")
|
||||
|
||||
# 创建新申请
|
||||
language = req.language if req.language in ["zh", "en"] else "zh"
|
||||
application = InviteCodeApplication(
|
||||
email=req.email,
|
||||
reason=req.reason,
|
||||
language=language,
|
||||
status="pending"
|
||||
)
|
||||
|
||||
try:
|
||||
session.add(application)
|
||||
session.commit()
|
||||
session.refresh(application)
|
||||
|
||||
return SuccessResponse(
|
||||
message="申请已提交,我们将在1-2个工作日内处理您的申请",
|
||||
data=ApplicationResponse.model_validate(application)
|
||||
)
|
||||
except IntegrityError:
|
||||
session.rollback()
|
||||
raise HTTPException(status_code=500, detail="创建申请失败")
|
||||
|
||||
# 健康检查
|
||||
@app.get("/health")
|
||||
async def health_check():
|
||||
return {"status": "ok"}
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
uvicorn.run(app, host="0.0.0.0", port=8000)
|
||||
Reference in New Issue
Block a user