8920a337e0
- 前端
- topics.html: 恢复结构并修复Vue初始化问题
- 调整创作按钮逻辑:仅已发布选题禁用
- 修正API端点与payload格式(generate/optimizer/publishing使用topic_ids数组)
- 移除ElementPlus图标模块依赖,使用全局构建
- admin.html: 回退至Options API版本,解决this上下文错误
- 后端
- 注册/api/generate/run路由
- 简化generate逻辑:允许非已发布选题重创作,更新状态为“待审查”
- 统一logs查询接口支持query参数
- 修复admin用户管理字段引用
- 系统概览返回{ stats }结构
- 静态资源整理
- 删除冗余element-plus-icons、重复CSS/JS、图标文件
- 正确放置Vue和ElementPlus全局文件
- 数据库与数据
- 补充30个案例
- 更新选题状态与初始数据
验证:所有页面可访问,API认证与端点正常工作。
189 lines
5.7 KiB
Python
189 lines
5.7 KiB
Python
# 宇之然内容创作平台 - 选题管理API
|
|
|
|
from pydantic import BaseModel
|
|
from datetime import datetime
|
|
from fastapi import APIRouter, Depends, HTTPException, status, Query
|
|
from sqlalchemy.orm import Session
|
|
from typing import List, Optional
|
|
import json
|
|
|
|
from core.security import get_current_admin_user, create_audit_log
|
|
from app.database import get_db
|
|
from app.models import Topic, User
|
|
|
|
router = APIRouter()
|
|
|
|
class TopicCreateRequest(BaseModel):
|
|
title: str
|
|
field: Optional[str] = None
|
|
priority_score: int = 0
|
|
|
|
class TopicUpdateRequest(BaseModel):
|
|
title: Optional[str] = None
|
|
field: Optional[str] = None
|
|
priority_score: Optional[int] = None
|
|
status: Optional[str] = None
|
|
|
|
@router.get("", response_model=List[dict])
|
|
async def get_topics(
|
|
status: Optional[str] = Query(None),
|
|
page: int = Query(1, ge=1),
|
|
size: int = Query(20, ge=1, le=100),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""获取选题列表"""
|
|
query = db.query(Topic)
|
|
|
|
# 状态筛选
|
|
if status:
|
|
query = query.filter(Topic.status == status)
|
|
|
|
# 分页
|
|
offset = (page - 1) * size
|
|
topics = query.offset(offset).limit(size).all()
|
|
|
|
# 转换为字典格式
|
|
result = []
|
|
for topic in topics:
|
|
result.append({
|
|
"id": topic.id,
|
|
"title": topic.title,
|
|
"field": topic.field,
|
|
"priority_score": topic.priority_score,
|
|
"status": topic.status,
|
|
"compliance_score": topic.compliance_score,
|
|
"created_at": topic.created_at.isoformat() if topic.created_at else None,
|
|
"updated_at": topic.updated_at.isoformat() if topic.updated_at else None,
|
|
"generated_at": topic.generated_at.isoformat() if topic.generated_at else None,
|
|
"published_at": topic.published_at.isoformat() if topic.published_at else None,
|
|
"platform_urls": topic.platform_urls
|
|
})
|
|
|
|
return result
|
|
|
|
@router.post("/", response_model=dict)
|
|
async def create_topic(
|
|
topic_data: TopicCreateRequest,
|
|
current_user: User = Depends(get_current_admin_user),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""创建新选题(管理员功能)"""
|
|
new_topic = Topic(
|
|
title=topic_data.title,
|
|
field=topic_data.field,
|
|
priority_score=topic_data.priority_score,
|
|
status="待处理"
|
|
)
|
|
db.add(new_topic)
|
|
db.commit()
|
|
db.refresh(new_topic)
|
|
|
|
# 记录审计日志
|
|
create_audit_log(
|
|
db=db,
|
|
user_id=current_user.id,
|
|
action="create_topic",
|
|
resource_type="topic",
|
|
resource_id=new_topic.id,
|
|
details=f"标题: {topic_data.title}"
|
|
)
|
|
|
|
return {
|
|
"id": new_topic.id,
|
|
"title": new_topic.title,
|
|
"status": new_topic.status,
|
|
"created_at": new_topic.created_at.isoformat() if new_topic.created_at else None
|
|
}
|
|
|
|
@router.put("/{topic_id}", response_model=dict)
|
|
async def update_topic(
|
|
topic_id: int,
|
|
topic_data: TopicUpdateRequest,
|
|
current_user: User = Depends(get_current_admin_user),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""更新选题信息(管理员功能)"""
|
|
topic = db.query(Topic).filter(Topic.id == topic_id).first()
|
|
if not topic:
|
|
raise HTTPException(status_code=404, detail="选题不存在")
|
|
|
|
# 更新字段
|
|
if topic_data.title is not None:
|
|
topic.title = topic_data.title
|
|
if topic_data.field is not None:
|
|
topic.field = topic_data.field
|
|
if topic_data.priority_score is not None:
|
|
topic.priority_score = topic_data.priority_score
|
|
if topic_data.status is not None:
|
|
topic.status = topic_data.status
|
|
|
|
topic.updated_at = datetime.utcnow()
|
|
db.commit()
|
|
db.refresh(topic)
|
|
|
|
# 记录审计日志
|
|
create_audit_log(
|
|
db=db,
|
|
user_id=current_user.id,
|
|
action="update_topic",
|
|
resource_type="topic",
|
|
resource_id=topic_id,
|
|
details=f"状态更新为: {topic_data.status}"
|
|
)
|
|
|
|
return {
|
|
"id": topic.id,
|
|
"title": topic.title,
|
|
"status": topic.status,
|
|
"updated_at": topic.updated_at.isoformat() if topic.updated_at else None
|
|
}
|
|
|
|
@router.delete("/{topic_id}")
|
|
async def delete_topic(
|
|
topic_id: str,
|
|
current_user: User = Depends(get_current_admin_user),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""删除选题(管理员功能)"""
|
|
topic = db.query(Topic).filter(Topic.id == topic_id).first()
|
|
if not topic:
|
|
raise HTTPException(status_code=404, detail="选题不存在")
|
|
|
|
db.delete(topic)
|
|
db.commit()
|
|
|
|
# 记录审计日志
|
|
create_audit_log(
|
|
db=db,
|
|
user_id=current_user.id,
|
|
action="delete_topic",
|
|
resource_type="topic",
|
|
resource_id=topic_id,
|
|
details="选题已删除"
|
|
)
|
|
|
|
return {"message": "选题已成功删除"}
|
|
|
|
@router.get("/{topic_id}", response_model=dict)
|
|
async def get_topic(
|
|
topic_id: int,
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""获取单个选题详情"""
|
|
topic = db.query(Topic).filter(Topic.id == topic_id).first()
|
|
if not topic:
|
|
raise HTTPException(status_code=404, detail="选题不存在")
|
|
|
|
return {
|
|
"id": topic.id,
|
|
"title": topic.title,
|
|
"field": topic.field,
|
|
"priority_score": topic.priority_score,
|
|
"status": topic.status,
|
|
"compliance_score": topic.compliance_score,
|
|
"created_at": topic.created_at.isoformat() if topic.created_at else None,
|
|
"updated_at": topic.updated_at.isoformat() if topic.updated_at else None,
|
|
"generated_at": topic.generated_at.isoformat() if topic.generated_at else None,
|
|
"published_at": topic.published_at.isoformat() if topic.published_at else None,
|
|
"platform_urls": topic.platform_urls
|
|
} |