tianfeng_task_modules/api/task_param_api.py

171 lines
5.5 KiB
Python
Raw Normal View History

2025-03-18 18:34:03 +08:00
"""
任务参数API
包含任务输入参数相关的API接口
"""
from typing import Dict, Any, List, Optional
from fastapi import APIRouter, HTTPException, Depends, Query, Path, Request
from pydantic import BaseModel, Field
from config.task_config import (
TaskInputParamConfig,
TaskInputParamType,
SystemParamKey
)
from services.task_param_service import TaskParamService
from core.exceptions import TianfengTaskError
from api.models import (
ApiResponse, TaskInputParamModel, TaskInputParamsUpdateRequest
)
import logging
import json
# 创建日志记录器
logger = logging.getLogger(__name__)
# 创建路由器
router = APIRouter(tags=["任务参数管理"])
# 创建服务实例
task_param_service = TaskParamService()
@router.get("/task/input-params/fields", response_model=ApiResponse)
async def get_task_param_types():
"""获取任务输入参数表单字段定义"""
try:
# 从配置中获取表单字段定义
form_fields = TaskInputParamConfig.get_input_params_form_fields()
return {
"code": 200,
"message": "获取任务输入参数表单字段定义成功",
"data": {
"form_fields": form_fields
}
}
except Exception as e:
raise HTTPException(status_code=500, detail=f"获取任务输入参数表单字段定义失败: {str(e)}")
@router.get("/task/{task_id}/input-params", response_model=ApiResponse)
async def get_task_input_params(
task_id: str = Path(..., description="任务ID"),
instance_id: str = Query(None, description="任务实例ID不传则使用最新实例")
):
"""
获取任务输入参数配置
返回任务输入参数的配置信息包括系统默认参数和用户自定义参数
"""
try:
# 使用任务参数服务获取参数
params, found_instance_id = task_param_service.get_task_input_params(task_id, instance_id)
return {
"code": 200,
"message": "获取任务输入参数成功",
"data": {
"task_id": task_id,
"instance_id": found_instance_id,
"params": params
}
}
except Exception as e:
raise HTTPException(status_code=500, detail=f"获取任务输入参数失败: {str(e)}")
def safe_process_default_value(param_dict: Dict[str, Any]) -> None:
"""
安全处理参数的default_value值确保其是JSON可序列化的
Args:
param_dict: 参数字典将被原地修改
"""
# 如果没有default_value键不处理
if "default_value" not in param_dict:
return
default_value = param_dict["default_value"]
param_type = param_dict.get("param_type", "")
# None值保持不变
if default_value is None:
return
# 只对json和array类型做特殊处理
if param_type not in ["json", "array"]:
return
# 如果已经是字符串尝试解析为JSON对象
if isinstance(default_value, str):
try:
param_dict["default_value"] = json.loads(default_value)
except json.JSONDecodeError:
# 解析失败保持原字符串
pass
@router.post("/task/{task_id}/input-params", response_model=ApiResponse)
async def update_task_input_params(
task_id: str = Path(..., description="任务ID"),
request: List[TaskInputParamModel] = None,
instance_id: str = Query(None, description="任务实例ID不传则使用最新实例或创建新实例")
):
"""
更新任务输入参数配置
批量保存用户自定义的任务输入参数配置只有点击"完成"按钮后才会生效
请求示例:
```json
[
{
"param_name": "robotId",
"label": "机器人ID",
"param_type": "string",
"required": true,
"default_value": "",
"description": "执行任务的机器人ID"
},
{
"param_name": "timeout",
"label": "超时时间",
"param_type": "integer",
"required": false,
"default_value": 3600,
"description": "任务执行的超时时间(秒)"
}
]
```
"""
try:
# 将Pydantic模型转换为字典列表并安全处理default_value
params = []
for param in request:
param_dict = param.dict(exclude_none=True)
safe_process_default_value(param_dict)
params.append(param_dict)
# 使用任务参数服务更新参数
updated_count, found_instance_id, has_changes = task_param_service.update_task_input_params(task_id, params, instance_id)
# 根据是否有变动返回不同的消息
message = "更新任务输入参数成功" if has_changes else "任务输入参数无变动"
return {
"code": 200,
"message": message,
"data": {
"task_id": task_id,
"instance_id": found_instance_id,
"updated_params_count": updated_count,
"has_changes": has_changes
}
}
except ValueError as e:
return {
"code": 400,
"message": str(e),
"data": None
}
except Exception as e:
import traceback
error_detail = f"更新任务输入参数失败: {str(e)}\n{traceback.format_exc()}"
raise HTTPException(status_code=500, detail=error_detail)