feat(flow): 添加动态API路由支持通过流程code执行
refactor(engine): 优化节点执行耗时记录 fix(db): 修正结果模式获取逻辑忽略connection.mode style(i18n): 统一节点描述和输出模式选项的国际化 test(flow): 新增测试流程定义文件 refactor(react): 简化开发环境日志降噪处理
This commit is contained in:
60
backend/src/routes/dynamic_api.rs
Normal file
60
backend/src/routes/dynamic_api.rs
Normal file
@ -0,0 +1,60 @@
|
||||
use axum::{Router, routing::post, extract::{State, Path}, Json};
|
||||
use crate::{db::Db, response::ApiResponse, services::flow_service, error::AppError};
|
||||
use serde_json::Value;
|
||||
use tracing::{info, error};
|
||||
|
||||
pub fn router() -> Router<Db> {
|
||||
Router::new()
|
||||
.route("/dynamic/{flow_code}", post(execute_flow))
|
||||
}
|
||||
|
||||
async fn execute_flow(
|
||||
State(db): State<Db>,
|
||||
Path(flow_code): Path<String>,
|
||||
Json(payload): Json<Value>
|
||||
) -> Result<Json<ApiResponse<Value>>, AppError> {
|
||||
info!(target = "udmin", "dynamic_api.execute_flow: start flow_code={}", flow_code);
|
||||
|
||||
// 1. 通过code查询流程
|
||||
let flow_doc = match flow_service::get_by_code(&db, &flow_code).await {
|
||||
Ok(doc) => doc,
|
||||
Err(e) => {
|
||||
error!(target = "udmin", error = ?e, "dynamic_api.execute_flow: flow not found flow_code={}", flow_code);
|
||||
return Err(flow_service::ae(e));
|
||||
}
|
||||
};
|
||||
|
||||
// 2. 执行流程
|
||||
let flow_id = flow_doc.id.clone();
|
||||
info!(target = "udmin", "dynamic_api.execute_flow: found flow id={} for code={}", flow_id, flow_code);
|
||||
|
||||
match flow_service::run(&db, &flow_id, flow_service::RunReq { input: payload }, Some((0, "接口".to_string()))).await {
|
||||
Ok(result) => {
|
||||
info!(target = "udmin", "dynamic_api.execute_flow: execution successful flow_code={}", flow_code);
|
||||
// 仅返回上下文中的 http_resp / http_response,如果不存在则返回空对象 {}
|
||||
let ctx = result.ctx;
|
||||
let data = match ctx {
|
||||
Value::Object(mut map) => {
|
||||
if let Some(v) = map.remove("http_resp") {
|
||||
v
|
||||
} else if let Some(v) = map.remove("http_response") {
|
||||
v
|
||||
} else {
|
||||
Value::Object(serde_json::Map::new())
|
||||
}
|
||||
}
|
||||
_ => Value::Object(serde_json::Map::new()),
|
||||
};
|
||||
Ok(Json(ApiResponse::ok(data)))
|
||||
},
|
||||
Err(e) => {
|
||||
error!(target = "udmin", error = ?e, "dynamic_api.execute_flow: execution failed flow_code={}", flow_code);
|
||||
let mut full = e.to_string();
|
||||
for cause in e.chain().skip(1) {
|
||||
full.push_str(" | ");
|
||||
full.push_str(&cause.to_string());
|
||||
}
|
||||
Err(AppError::InternalMsg(full))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,13 @@
|
||||
pub mod auth;
|
||||
pub mod users;
|
||||
pub mod roles;
|
||||
pub mod menus;
|
||||
pub mod departments;
|
||||
pub mod logs;
|
||||
// 新增岗位
|
||||
pub mod positions;
|
||||
pub mod menus;
|
||||
pub mod logs;
|
||||
pub mod flows;
|
||||
pub mod flow_run_logs;
|
||||
pub mod dynamic_api;
|
||||
|
||||
use axum::Router;
|
||||
use crate::db::Db;
|
||||
@ -23,4 +23,5 @@ pub fn api_router() -> Router<Db> {
|
||||
.merge(flows::router())
|
||||
.merge(positions::router())
|
||||
.merge(flow_run_logs::router())
|
||||
.merge(dynamic_api::router())
|
||||
}
|
||||
Reference in New Issue
Block a user