Files
qihuaiflow/backend/python/app/api/admin/services.py
T
qyyfw 78ff261b5a 初始提交: Qihu-AIFlow v2.0.1 完整项目
- 前端 React+TypeScript (源码+构建产物)
- 后端 Python FastAPI
- 数据库迁移 001-015
- Docker部署配置
- 微信ClawBot API频道绑定
- 项目文档 README.md
2026-07-02 14:40:46 +08:00

454 lines
15 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(管理员)
四大类服务: app_custom / platform_proxy / data_custom / private_project
"""
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session
from pydantic import BaseModel
from typing import Optional, List
from ...database import get_db
from ...models import ValueAddedService, CustomServiceOrder, CustomServiceRequest, MarketApp, User
from ...auth import get_current_admin
from ...middleware.log_service import LogService
import uuid
import json
from datetime import datetime
router = APIRouter()
class CreateServiceRequest(BaseModel):
name: str
service_type: str
description: Optional[str] = None
price: float = 0
features: Optional[str] = None
status: str = "active"
assigned_agent_id: Optional[str] = None
class UpdateServiceRequest(BaseModel):
name: Optional[str] = None
price: Optional[float] = None
service_type: Optional[str] = None
description: Optional[str] = None
features: Optional[str] = None
status: Optional[str] = None
assigned_agent_id: Optional[str] = None
# 服务类型映射
SERVICE_TYPE_MAP = {
"app_custom": "应用定制服务",
"platform_proxy": "平台代理申请",
"data_custom": "数据定制服务",
"private_project": "私有化项目服务",
}
# ============================================================
# 增值服务 CRUD
# ============================================================
@router.get("/")
async def get_services(
service_type: str = Query(None, description="服务类型筛选: app_custom/platform_proxy/data_custom/private_project"),
status: str = Query(None, description="状态筛选: active/inactive/deleted"),
admin_user=Depends(get_current_admin),
db: Session = Depends(get_db),
):
"""获取增值服务列表"""
import logging
logger = logging.getLogger(__name__)
logger.info(f"Admin {admin_user.username} requested services list: type={service_type}, status={status}")
query = db.query(ValueAddedService).filter(ValueAddedService.status != "deleted")
if service_type:
query = query.filter(ValueAddedService.type == service_type)
if status:
query = query.filter(ValueAddedService.status == status)
services = query.order_by(ValueAddedService.created_at.desc()).all()
result = []
for s in services:
result.append({
"id": s.id,
"name": s.name,
"description": s.description,
"price": float(s.price) if s.price else 0,
"type": s.type,
"type_name": SERVICE_TYPE_MAP.get(s.type, s.type),
"features": s.features or [],
"status": s.status,
"assigned_agent_id": s.assigned_agent_id,
"created_at": s.created_at.isoformat() if s.created_at else None,
"updated_at": s.updated_at.isoformat() if s.updated_at else None,
})
return result
@router.post("/")
async def create_service(
req: CreateServiceRequest,
admin_user=Depends(get_current_admin),
db: Session = Depends(get_db),
):
"""创建增值服务"""
import logging
logger = logging.getLogger(__name__)
if req.service_type not in SERVICE_TYPE_MAP:
raise HTTPException(status_code=400, detail=f"无效的服务类型,可选值:{', '.join(SERVICE_TYPE_MAP.keys())}")
features_json = None
if req.features:
try:
features_json = json.loads(req.features) if isinstance(req.features, str) else req.features
except (json.JSONDecodeError, TypeError):
features_json = [req.features]
service = ValueAddedService(
id=str(uuid.uuid4()),
name=req.name,
description=req.description,
price=req.price,
type=req.service_type,
features=features_json,
status=req.status,
assigned_agent_id=req.assigned_agent_id,
)
db.add(service)
db.commit()
db.refresh(service)
logger.info(f"Admin {admin_user.username} created service: {service.id} - {req.name}")
LogService.log_audit(
admin_id=admin_user.id,
admin_name=admin_user.username,
action="create_service",
target_type="value_added_service",
target_id=service.id,
detail=f"创建增值服务 {req.name}(类型: {SERVICE_TYPE_MAP.get(req.service_type)})",
)
return {"message": "增值服务已创建", "id": service.id}
@router.put("/{id}")
async def update_service(
id: str,
req: UpdateServiceRequest,
admin_user=Depends(get_current_admin),
db: Session = Depends(get_db),
):
"""更新增值服务"""
import logging
logger = logging.getLogger(__name__)
service = db.query(ValueAddedService).filter(ValueAddedService.id == id).first()
if not service:
raise HTTPException(status_code=404, detail="增值服务不存在")
if req.name is not None:
service.name = req.name
if req.price is not None:
service.price = req.price
if req.service_type is not None:
if req.service_type not in SERVICE_TYPE_MAP:
raise HTTPException(status_code=400, detail=f"无效的服务类型")
service.type = req.service_type
if req.description is not None:
service.description = req.description
if req.features is not None:
try:
service.features = json.loads(req.features) if isinstance(req.features, str) else req.features
except (json.JSONDecodeError, TypeError):
service.features = [req.features]
if req.status is not None:
service.status = req.status
if req.assigned_agent_id is not None:
service.assigned_agent_id = req.assigned_agent_id
service.updated_at = datetime.now()
db.commit()
logger.info(f"Admin {admin_user.username} updated service: {id}")
LogService.log_audit(
admin_id=admin_user.id,
admin_name=admin_user.username,
action="update_service",
target_type="value_added_service",
target_id=id,
detail=f"更新增值服务 {service.name}",
)
return {"message": "增值服务已更新"}
@router.delete("/{id}")
async def delete_service(
id: str,
admin_user=Depends(get_current_admin),
db: Session = Depends(get_db),
):
"""逻辑删除增值服务(设置为 deleted 状态,保留数据记录)"""
import logging
logger = logging.getLogger(__name__)
service = db.query(ValueAddedService).filter(ValueAddedService.id == id).first()
if not service:
raise HTTPException(status_code=404, detail="增值服务不存在")
if service.status == "deleted":
raise HTTPException(status_code=400, detail="该增值服务已被删除")
logger.info(f"Admin {admin_user.username} soft-deleting service: {id} - {service.name}")
service.status = "deleted"
service.updated_at = datetime.now()
db.commit()
LogService.log_audit(
admin_id=admin_user.id,
admin_name=admin_user.username,
action="delete_service",
target_type="value_added_service",
target_id=id,
detail=f"逻辑删除增值服务 {service.name}",
)
return {"message": "增值服务已删除(逻辑删除)"}
# ============================================================
# 定制服务工单管理 (CustomServiceRequest)
# ============================================================
@router.get("/custom-requests")
async def get_custom_requests(
request_type: str = Query(None, description="工单类型: data_custom/private_project/platform_proxy"),
status: str = Query(None, description="状态: pending/processing/completed/rejected"),
admin_user=Depends(get_current_admin),
db: Session = Depends(get_db),
):
"""获取定制服务工单列表"""
import logging
logger = logging.getLogger(__name__)
logger.info(f"Admin {admin_user.username} requested custom requests: type={request_type}, status={status}")
query = db.query(CustomServiceRequest)
if request_type:
query = query.filter(CustomServiceRequest.request_type == request_type)
if status:
query = query.filter(CustomServiceRequest.status == status)
requests = query.order_by(CustomServiceRequest.created_at.desc()).all()
result = []
for r in requests:
# 查询用户名
user = db.query(User).filter(User.id == r.user_id).first()
# 查询服务名
service = db.query(ValueAddedService).filter(ValueAddedService.id == r.service_id).first()
result.append({
"id": r.id,
"user_id": r.user_id,
"username": user.username if user else "未知用户",
"service_id": r.service_id,
"service_name": service.name if service else "未知服务",
"request_type": r.request_type,
"request_type_name": SERVICE_TYPE_MAP.get(r.request_type, r.request_type),
"title": r.title,
"description": r.description,
"requirements": r.requirements or {},
"status": r.status,
"assigned_agent_id": r.assigned_agent_id,
"created_at": r.created_at.isoformat() if r.created_at else None,
"updated_at": r.updated_at.isoformat() if r.updated_at else None,
})
return result
@router.put("/custom-requests/{id}")
async def update_custom_request(
id: str,
status: str = None,
assigned_agent_id: str = None,
admin_user=Depends(get_current_admin),
db: Session = Depends(get_db),
):
"""更新定制服务工单(分配Agent / 标记完成)"""
import logging
logger = logging.getLogger(__name__)
req = db.query(CustomServiceRequest).filter(CustomServiceRequest.id == id).first()
if not req:
raise HTTPException(status_code=404, detail="工单不存在")
if status is not None:
if status not in ("pending", "processing", "completed", "rejected"):
raise HTTPException(status_code=400, detail="无效的状态值")
req.status = status
if assigned_agent_id is not None:
req.assigned_agent_id = assigned_agent_id
req.updated_at = datetime.now()
db.commit()
logger.info(f"Admin {admin_user.username} updated custom request: {id}, status={status}, agent={assigned_agent_id}")
LogService.log_audit(
admin_id=admin_user.id,
admin_name=admin_user.username,
action="update_custom_request",
target_type="custom_service_request",
target_id=id,
detail=f"更新工单状态: {status}, 分配Agent: {assigned_agent_id}",
)
return {"message": "工单已更新"}
# ============================================================
# 定制服务订单管理 (CustomServiceOrder - 保留兼容)
# ============================================================
@router.get("/custom-orders")
async def get_custom_orders(
status: str = Query(None, description="状态筛选"),
admin_user=Depends(get_current_admin),
db: Session = Depends(get_db),
):
"""获取定制服务订单列表"""
query = db.query(CustomServiceOrder)
if status:
query = query.filter(CustomServiceOrder.status == status)
orders = query.order_by(CustomServiceOrder.created_at.desc()).all()
result = []
for o in orders:
user = db.query(User).filter(User.id == o.user_id).first()
result.append({
"id": o.id,
"user_id": o.user_id,
"username": user.username if user else "未知用户",
"service_id": o.service_id,
"service_type": o.service_type,
"description": o.description,
"status": o.status,
"price": float(o.price) if o.price else 0,
"order_id": o.order_id,
"created_at": o.created_at.isoformat() if o.created_at else None,
"updated_at": o.updated_at.isoformat() if o.updated_at else None,
})
return result
@router.put("/custom-orders/{id}")
async def update_custom_order(
id: str,
status: str = None,
price: float = None,
admin_user=Depends(get_current_admin),
db: Session = Depends(get_db),
):
"""更新定制服务订单状态"""
import logging
logger = logging.getLogger(__name__)
order = db.query(CustomServiceOrder).filter(CustomServiceOrder.id == id).first()
if not order:
raise HTTPException(status_code=404, detail="定制服务订单不存在")
if status is not None:
order.status = status
if price is not None:
order.price = price
order.updated_at = datetime.now()
db.commit()
logger.info(f"Admin {admin_user.username} updated custom order: {id}, status={status}")
LogService.log_audit(
admin_id=admin_user.id,
admin_name=admin_user.username,
action="update_custom_order",
target_type="custom_service_order",
target_id=id,
detail=f"更新定制服务订单状态为 {status}",
)
return {"message": "定制服务订单已更新"}
# ============================================================
# Agent 配置(为应用定制服务绑定市场Agent)
# ============================================================
@router.get("/agents")
async def get_available_agents(
admin_user=Depends(get_current_admin),
db: Session = Depends(get_db),
):
"""获取可用的市场Agent列表(用于绑定到应用定制服务)"""
from sqlalchemy import or_
agents = db.query(MarketApp).filter(
MarketApp.type == "agent",
or_(MarketApp.status == "published", MarketApp.status == "active")
).all()
result = []
for a in agents:
result.append({
"id": a.id,
"name": a.name,
"description": a.description,
"publisher_name": a.publisher_name,
})
return result
@router.put("/{id}/agent")
async def assign_agent_to_service(
id: str,
agent_id: str,
admin_user=Depends(get_current_admin),
db: Session = Depends(get_db),
):
"""为应用定制服务绑定Agent"""
import logging
logger = logging.getLogger(__name__)
service = db.query(ValueAddedService).filter(ValueAddedService.id == id).first()
if not service:
raise HTTPException(status_code=404, detail="增值服务不存在")
# 验证agent存在
agent = db.query(MarketApp).filter(
MarketApp.id == agent_id,
MarketApp.type == "agent"
).first()
if not agent:
raise HTTPException(status_code=404, detail="Agent不存在")
service.assigned_agent_id = agent_id
service.updated_at = datetime.now()
db.commit()
logger.info(f"Admin {admin_user.username} assigned agent {agent_id} to service {id}")
LogService.log_audit(
admin_id=admin_user.id,
admin_name=admin_user.username,
action="assign_agent",
target_type="value_added_service",
target_id=id,
detail=f"为服务 {service.name} 绑定Agent: {agent.name}",
)
return {"message": "Agent绑定成功", "agent_name": agent.name}