""" 主播信息管理API路由 """ from typing import Any, List, Optional from fastapi import APIRouter, Depends, HTTPException, Query, status from sqlalchemy import select, func, and_, or_ from sqlalchemy.ext.asyncio import AsyncSession from loguru import logger from app.database import get_async_session from app.models.streamer import StreamerInfo, McnAgency from app.schemas.streamer import ( StreamerCreate, StreamerUpdate, StreamerResponse, StreamerDetailResponse, StreamerListResponse, ) router = APIRouter() @router.get("", response_model=StreamerListResponse) async def list_streamers( page: int = Query(1, ge=1, description="页码"), size: int = Query(10, ge=1, le=100, description="每页数量"), streamer_id: str = Query(None, description="主播ID"), streamer_name: str = Query(None, description="主播名称"), entity_type: str = Query(None, description="主体类型"), status: str = Query(None, description="状态"), mcn_agency_id: int = Query(None, description="MCN机构ID"), db: AsyncSession = Depends(get_async_session), ): """ 获取主播列表(分页查询) """ logger.info(f"获取主播列表: page={page}, size={size}") # 构建查询 query = select( StreamerInfo, McnAgency.mcn_name.label("mcn_agency_name") ).join( McnAgency, StreamerInfo.mcn_agency_id == McnAgency.id, isouter=True ) # 添加过滤条件 conditions = [] if streamer_id: conditions.append(StreamerInfo.streamer_id.ilike(f"%{streamer_id}%")) if streamer_name: conditions.append(StreamerInfo.streamer_name.ilike(f"%{streamer_name}%")) if entity_type: conditions.append(StreamerInfo.entity_type == entity_type) if status: conditions.append(StreamerInfo.status == status) if mcn_agency_id: conditions.append(StreamerInfo.mcn_agency_id == mcn_agency_id) if conditions: query = query.where(and_(*conditions)) # 获取总数 count_query = select(func.count()).select_from(StreamerInfo) if conditions: count_query = count_query.where(and_(*conditions)) total_result = await db.execute(count_query) total = total_result.scalar() # 分页 query = query.offset((page - 1) * size).limit(size) # 执行查询 result = await db.execute(query) rows = result.all() # 转换为响应格式 records = [] for streamer, mcn_name in rows: record = { "id": streamer.id, "streamer_id": streamer.streamer_id, "streamer_name": streamer.streamer_name, "entity_type": streamer.entity_type, "phone_number": streamer.phone_number, "bank_account_no": streamer.bank_account_no, "bank_name": streamer.bank_name, "mcn_agency_id": streamer.mcn_agency_id, "mcn_agency_name": mcn_name, "status": streamer.status, "registration_date": streamer.registration_date.isoformat() if streamer.registration_date else None, "created_at": streamer.created_at.isoformat() if streamer.created_at else None, } records.append(record) return StreamerListResponse( records=records, total=total, page=page, size=size, ) @router.get("/{streamer_id}", response_model=StreamerDetailResponse) async def get_streamer(streamer_id: str, db: AsyncSession = Depends(get_async_session)): """ 根据ID获取主播详细信息 """ logger.info(f"获取主播详情: {streamer_id}") # 查询主播信息及MCN机构 query = select( StreamerInfo, McnAgency.mcn_name.label("mcn_agency_name") ).join( McnAgency, StreamerInfo.mcn_agency_id == McnAgency.id, isouter=True ).where( StreamerInfo.streamer_id == streamer_id ) result = await db.execute(query) row = result.first() if not row: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"主播不存在: {streamer_id}", ) streamer, mcn_name = row # 转换为响应格式 detail = { "id": streamer.id, "streamer_id": streamer.streamer_id, "streamer_name": streamer.streamer_name, "entity_type": streamer.entity_type, "phone_number": streamer.phone_number, "bank_account_no": streamer.bank_account_no, "bank_name": streamer.bank_name, "wechat_pay_account": streamer.wechat_pay_account, "alipay_account": streamer.alipay_account, "douyin_account": streamer.douyin_account, "mcn_agency_id": streamer.mcn_agency_id, "mcn_agency_name": mcn_name, "status": streamer.status, "registration_date": streamer.registration_date.isoformat() if streamer.registration_date else None, "created_at": streamer.created_at.isoformat() if streamer.created_at else None, # 详细信息 "id_card_no": streamer.id_card_no, "social_security_no": streamer.social_security_no, "unified_social_credit_code": streamer.unified_social_credit_code, "tax_registration_no": streamer.tax_registration_no, "legal_person_name": streamer.legal_person_name, "legal_person_id_card": streamer.legal_person_id_card, "registered_address": streamer.registered_address, "actual_address": streamer.actual_address, "kuaishou_account": streamer.kuaishou_account, "xiaohongshu_account": streamer.xiaohongshu_account, "weibo_account": streamer.weibo_account, "bilibili_account": streamer.bilibili_account, "streamer_certificate_no": streamer.streamer_certificate_no, "certificate_issuing_authority": streamer.certificate_issuing_authority, "certificate_issue_date": streamer.certificate_issue_date.isoformat() if streamer.certificate_issue_date else None, "certificate_expiry_date": streamer.certificate_expiry_date.isoformat() if streamer.certificate_expiry_date else None, "related_persons": streamer.related_persons, "updated_at": streamer.updated_at.isoformat() if streamer.updated_at else None, } return detail @router.post("", response_model=StreamerResponse, status_code=status.HTTP_201_CREATED) async def create_streamer(streamer: StreamerCreate, db: AsyncSession = Depends(get_async_session)): """ 创建新主播 """ logger.info(f"创建主播: {streamer.streamer_name}") # 生成主播ID query = select(func.count()).select_from(StreamerInfo) result = await db.execute(query) count = result.scalar() streamer_id = f"STR{2024}{(count + 1):06d}" # 创建新主播 new_streamer = StreamerInfo( streamer_id=streamer_id, streamer_name=streamer.streamer_name, entity_type=streamer.entity_type, phone_number=streamer.phone_number, bank_account_no=streamer.bank_account_no, bank_name=streamer.bank_name, wechat_pay_account=streamer.wechat_pay_account, alipay_account=streamer.alipay_account, douyin_account=streamer.douyin_account, mcn_agency_id=streamer.mcn_agency_id, status=streamer.status, registration_date=streamer.registration_date, id_card_no=streamer.id_card_no, social_security_no=streamer.social_security_no, unified_social_credit_code=streamer.unified_social_credit_code, tax_registration_no=streamer.tax_registration_no, legal_person_name=streamer.legal_person_name, legal_person_id_card=streamer.legal_person_id_card, registered_address=streamer.registered_address, actual_address=streamer.actual_address, kuaishou_account=streamer.kuaishou_account, xiaohongshu_account=streamer.xiaohongshu_account, weibo_account=streamer.weibo_account, bilibili_account=streamer.bilibili_account, streamer_certificate_no=streamer.streamer_certificate_no, certificate_issuing_authority=streamer.certificate_issuing_authority, certificate_issue_date=streamer.certificate_issue_date, certificate_expiry_date=streamer.certificate_expiry_date, related_persons=streamer.related_persons, ) db.add(new_streamer) await db.commit() await db.refresh(new_streamer) # 查询MCN机构名称 mcn_name = None if new_streamer.mcn_agency_id: result = await db.execute( select(McnAgency.mcn_name).where(McnAgency.id == new_streamer.mcn_agency_id) ) mcn_name = result.scalar() # 转换为响应格式 response = { "id": new_streamer.id, "streamer_id": new_streamer.streamer_id, "streamer_name": new_streamer.streamer_name, "entity_type": new_streamer.entity_type, "phone_number": new_streamer.phone_number, "bank_account_no": new_streamer.bank_account_no, "bank_name": new_streamer.bank_name, "wechat_pay_account": new_streamer.wechat_pay_account, "alipay_account": new_streamer.alipay_account, "douyin_account": new_streamer.douyin_account, "mcn_agency_id": new_streamer.mcn_agency_id, "mcn_agency_name": mcn_name, "status": new_streamer.status, "registration_date": new_streamer.registration_date, "created_at": new_streamer.created_at, } return response @router.put("/{streamer_id}", response_model=StreamerResponse) async def update_streamer( streamer_id: str, streamer_update: StreamerUpdate, db: AsyncSession = Depends(get_async_session), ): """ 修改主播信息 """ logger.info(f"修改主播: {streamer_id}") # 查询主播 query = select(StreamerInfo).where(StreamerInfo.streamer_id == streamer_id) result = await db.execute(query) streamer = result.scalar_one_or_none() if not streamer: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"主播不存在: {streamer_id}", ) # 更新字段 update_data = streamer_update.model_dump(exclude_unset=True) for key, value in update_data.items(): if hasattr(streamer, key): setattr(streamer, key, value) await db.commit() await db.refresh(streamer) # 查询MCN机构名称 mcn_name = None if streamer.mcn_agency_id: result = await db.execute( select(McnAgency.mcn_name).where(McnAgency.id == streamer.mcn_agency_id) ) mcn_name = result.scalar() # 转换为响应格式 response = { "id": streamer.id, "streamer_id": streamer.streamer_id, "streamer_name": streamer.streamer_name, "entity_type": streamer.entity_type, "phone_number": streamer.phone_number, "bank_account_no": streamer.bank_account_no, "bank_name": streamer.bank_name, "wechat_pay_account": streamer.wechat_pay_account, "alipay_account": streamer.alipay_account, "douyin_account": streamer.douyin_account, "mcn_agency_id": streamer.mcn_agency_id, "mcn_agency_name": mcn_name, "status": streamer.status, "registration_date": streamer.registration_date, "created_at": streamer.created_at, } return response @router.delete("/{streamer_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_streamer(streamer_id: str, db: AsyncSession = Depends(get_async_session)): """ 删除主播(软删除) """ logger.info(f"删除主播: {streamer_id}") # 查询主播 query = select(StreamerInfo).where(StreamerInfo.streamer_id == streamer_id) result = await db.execute(query) streamer = result.scalar_one_or_none() if not streamer: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"主播不存在: {streamer_id}", ) # 软删除(设置为inactive) streamer.status = "inactive" await db.commit() return None