feat: 脚本执行平台功能
Some checks failed
continuous-integration/drone/push Build is failing

- 支持 Python 脚本定时执行(类似青龙面板)
- 内置 SDK:AI大模型、钉钉/企微通知、数据库查询、HTTP请求、变量存储
- 安全沙箱执行,禁用危险模块
- 前端脚本编辑器,支持测试执行
- SDK 文档查看
- 日志通过 TraceID 与 platform_logs 关联
This commit is contained in:
2026-01-28 11:45:02 +08:00
parent ed88099cf0
commit 644255891e
6 changed files with 1153 additions and 35 deletions

View File

@@ -69,26 +69,64 @@ async def execute_task(task_id: int):
result = db.execute(text("SELECT LAST_INSERT_ID() as id"))
log_id = result.scalar()
# 4. 调用 webhook
webhook_url = task["webhook_url"]
input_params = task["input_params"] or {}
# 生成 trace_id
trace_id = f"task_{task_id}_{datetime.now().strftime('%Y%m%d%H%M%S%f')}"
async with httpx.AsyncClient(timeout=300.0) as client:
response = await client.post(
webhook_url,
json=input_params,
headers={"Content-Type": "application/json"}
)
# 4. 根据执行类型分发
execution_type = task.get("execution_type", "webhook")
if execution_type == "script":
# 脚本执行模式
from .script_executor import execute_script as run_script
response_code = response.status_code
response_body = response.text[:5000] if response.text else "" # 限制存储长度
if response.is_success:
status = "success"
error_message = None
else:
script_content = task.get("script_content", "")
if not script_content:
status = "failed"
error_message = f"HTTP {response_code}"
error_message = "脚本内容为空"
response_code = None
response_body = ""
else:
script_result = await run_script(
task_id=task_id,
tenant_id=task["tenant_id"],
script_content=script_content,
trace_id=trace_id
)
if script_result.success:
status = "success"
error_message = None
else:
status = "failed"
error_message = script_result.error
response_code = None
response_body = script_result.output[:5000] if script_result.output else ""
# 添加日志到响应体
if script_result.logs:
response_body += "\n\n--- 执行日志 ---\n" + "\n".join(script_result.logs[-20:])
else:
# Webhook 执行模式
webhook_url = task["webhook_url"]
input_params = task["input_params"] or {}
async with httpx.AsyncClient(timeout=300.0) as client:
response = await client.post(
webhook_url,
json=input_params,
headers={"Content-Type": "application/json"}
)
response_code = response.status_code
response_body = response.text[:5000] if response.text else "" # 限制存储长度
if response.is_success:
status = "success"
error_message = None
else:
status = "failed"
error_message = f"HTTP {response_code}"
# 5. 更新执行日志
db.execute(