""" 会员订阅体系管理 API(管理员) """ from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.orm import Session from ...database import get_db, SessionLocal from ...models import MembershipPlan, MembershipSubscription, User, RiskRule from ...auth import get_current_admin from ...middleware.log_service import LogService import uuid from datetime import datetime router = APIRouter() # ============================================================ # 会员计划 CRUD # ============================================================ @router.get("/plans") async def get_plans( admin_user=Depends(get_current_admin), db: Session = Depends(get_db), ): """获取会员计划列表""" plans = db.query(MembershipPlan).order_by(MembershipPlan.level).all() return [ { "id": p.id, "name": p.name, "level": p.level, "duration_type": p.duration_type, "price": float(p.price) if p.price else 0, "daily_free_tokens": p.daily_free_tokens, "features": p.features, "free_app_ids": p.free_app_ids, "free_model_ids": p.free_model_ids, "is_active": p.is_active, "created_at": p.created_at.isoformat() if p.created_at else None, "updated_at": p.updated_at.isoformat() if p.updated_at else None, } for p in plans ] @router.post("/plans") async def create_plan( name: str, level: int, duration_type: str, price: float, daily_free_tokens: int = 0, features: list = None, free_app_ids: list = None, free_model_ids: list = None, is_active: bool = True, admin_user=Depends(get_current_admin), db: Session = Depends(get_db), ): """创建会员计划""" plan = MembershipPlan( id=str(uuid.uuid4()), name=name, level=level, duration_type=duration_type, price=price, daily_free_tokens=daily_free_tokens, features=features, free_app_ids=free_app_ids, free_model_ids=free_model_ids, is_active=is_active, ) db.add(plan) db.commit() LogService.log_audit( admin_id=admin_user.id, admin_name=admin_user.username, action="create_membership_plan", target_type="membership_plan", target_id=plan.id, detail=f"创建会员计划 {name}", ) return {"message": "会员计划已创建", "id": plan.id} @router.put("/plans/{id}") async def update_plan( id: str, name: str = None, level: int = None, duration_type: str = None, price: float = None, daily_free_tokens: int = None, features: list = None, free_app_ids: list = None, free_model_ids: list = None, is_active: bool = None, admin_user=Depends(get_current_admin), db: Session = Depends(get_db), ): """更新会员计划""" plan = db.query(MembershipPlan).filter(MembershipPlan.id == id).first() if not plan: raise HTTPException(status_code=404, detail="会员计划不存在") if name is not None: plan.name = name if level is not None: plan.level = level if duration_type is not None: plan.duration_type = duration_type if price is not None: plan.price = price if daily_free_tokens is not None: plan.daily_free_tokens = daily_free_tokens if features is not None: plan.features = features if free_app_ids is not None: plan.free_app_ids = free_app_ids if free_model_ids is not None: plan.free_model_ids = free_model_ids if is_active is not None: plan.is_active = is_active plan.updated_at = datetime.now() db.commit() LogService.log_audit( admin_id=admin_user.id, admin_name=admin_user.username, action="update_membership_plan", target_type="membership_plan", target_id=id, detail=f"更新会员计划 {plan.name}", ) return {"message": "会员计划已更新"} @router.delete("/plans/{id}") async def delete_plan( id: str, admin_user=Depends(get_current_admin), db: Session = Depends(get_db), ): """删除会员计划""" plan = db.query(MembershipPlan).filter(MembershipPlan.id == id).first() if not plan: raise HTTPException(status_code=404, detail="会员计划不存在") db.delete(plan) db.commit() LogService.log_audit( admin_id=admin_user.id, admin_name=admin_user.username, action="delete_membership_plan", target_type="membership_plan", target_id=id, detail=f"删除会员计划 {plan.name}", ) return {"message": "会员计划已删除"} # ============================================================ # 用户订阅管理 # ============================================================ @router.get("/subscriptions") async def get_subscriptions( user_id: str = Query(None), status: str = Query(None, description="订阅状态: active/expired/downgraded"), page: int = Query(1, ge=1), page_size: int = Query(20, ge=1, le=100), admin_user=Depends(get_current_admin), db: Session = Depends(get_db), ): """获取所有用户订阅列表""" query = db.query(MembershipSubscription) if user_id: query = query.filter(MembershipSubscription.user_id == user_id) if status: query = query.filter(MembershipSubscription.status == status) total = query.count() subscriptions = query.order_by( MembershipSubscription.created_at.desc() ).offset((page - 1) * page_size).limit(page_size).all() return { "total": total, "page": page, "page_size": page_size, "items": [ { "id": s.id, "user_id": s.user_id, "plan_id": s.plan_id, "order_id": s.order_id, "start_at": s.start_at.isoformat() if s.start_at else None, "end_at": s.end_at.isoformat() if s.end_at else None, "auto_renew": s.auto_renew, "status": s.status, "created_at": s.created_at.isoformat() if s.created_at else None, } for s in subscriptions ], } # ============================================================ # 自动化规则(风控) # ============================================================ @router.get("/automation-rules") async def get_automation_rules( admin_user=Depends(get_current_admin), db: Session = Depends(get_db), ): """获取自动化规则配置""" rules = db.query(RiskRule).order_by(RiskRule.created_at.desc()).all() if not rules: # 返回默认规则 return { "rules": [], "defaults": { "max_login_attempts": 5, "token_usage_threshold_per_hour": 1000000, "token_usage_threshold_per_day": 10000000, "concurrent_sessions_limit": 5, }, } return { "rules": [ { "id": r.id, "name": r.name, "type": r.type, "threshold": r.threshold, "duration": r.duration, "is_enabled": r.is_enabled, "created_at": r.created_at.isoformat() if r.created_at else None, "updated_at": r.updated_at.isoformat() if r.updated_at else None, } for r in rules ], "defaults": { "max_login_attempts": 5, "token_usage_threshold_per_hour": 1000000, "token_usage_threshold_per_day": 10000000, "concurrent_sessions_limit": 5, }, }