deep-risk/backend/app/api/v1/endpoints/streamer.py
2025-12-14 20:08:27 +08:00

338 lines
12 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
主播信息管理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