338 lines
12 KiB
Python
338 lines
12 KiB
Python
"""
|
||
主播信息管理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
|