""" 任务参数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)