#!/usr/bin/env python3 """发布管理 API""" from fastapi import APIRouter, HTTPException, Depends, Request from pydantic import BaseModel from datetime import datetime, timezone, timedelta from typing import Optional, List from ..database import get_db from ..models import Topic, PublishRecord, User from sqlalchemy.orm import Session from .auth import get_current_admin, org_filter from ..core.audit_logger import audit_log router = APIRouter(prefix="/api/publishing", tags=["publishing"]) PLATFORM_LABELS = { "zhihu": "知乎", "wechat": "微信公众号", "xiaohongshu": "小红书" } class MultiPublishRequest(BaseModel): topic_id: str platforms: List[str] = ["zhihu", "wechat", "xiaohongshu"] class PublishResult(BaseModel): platform: str platform_label: str status: str error_msg: Optional[str] = None class MultiPublishResponse(BaseModel): ok: bool topic_id: str results: List[PublishResult] message: str @router.post("/create", response_model=MultiPublishResponse) async def create_publish_record( req: MultiPublishRequest, request: Request, db: Session = Depends(get_db), current_user: User = Depends(get_current_admin) ): """多平台发布选题(管理员)""" try: q = db.query(Topic).filter(Topic.id == req.topic_id) of = org_filter(current_user, Topic) if of is not True: q = q.filter(of) topic = q.first() if not topic: raise HTTPException(status_code=404, detail=f"选题 {req.topic_id} 不存在") if topic.status not in ('ready', '待发布'): raise HTTPException(status_code=400, detail=f"选题 {req.topic_id} 状态不是待发布(当前: {topic.status})") if not req.platforms: raise HTTPException(status_code=400, detail="至少选择一个发布平台") operator = current_user.username results = [] for platform in req.platforms: try: record = PublishRecord( topic_id=req.topic_id, platform=platform, action='publish', status='success', operator=operator, description=f"选题 {req.topic_id} 发布到 {PLATFORM_LABELS.get(platform, platform)}", org_id=topic.org_id ) db.add(record) results.append(PublishResult( platform=platform, platform_label=PLATFORM_LABELS.get(platform, platform), status='success' )) except Exception as e: results.append(PublishResult( platform=platform, platform_label=PLATFORM_LABELS.get(platform, platform), status='failed', error_msg=str(e) )) topic.status = '已发布' _now = datetime.now(timezone(timedelta(hours=8))) topic.updated_at = _now topic.published_at = _now.date() db.commit() db.expire_all() db.refresh(topic) audit_log( action="publish", user=current_user, resource_type="topic", resource_id=req.topic_id, details={"operator": operator, "platforms": req.platforms, "results": [r.model_dump() for r in results]}, ip_address=request.client.host if request.client else None, user_agent=request.headers.get("user-agent", ""), db=db ) success_count = sum(1 for r in results if r.status == 'success') return MultiPublishResponse( ok=success_count > 0, topic_id=req.topic_id, results=results, message=f"选题 {req.topic_id} 发布完成({success_count}/{len(results)} 平台成功)" ) except HTTPException: raise except Exception as e: db.rollback() raise HTTPException(status_code=500, detail=str(e))