diff --git a/.trae/rules/project_rules.md b/.trae/rules/project_rules.md index 20d08f4..9565e3d 100644 --- a/.trae/rules/project_rules.md +++ b/.trae/rules/project_rules.md @@ -1,152 +1,60 @@ -# Rust 代码风格规范(用于 AI 生成代码规则) +# Rust 复杂文件代码规范顺序(紧凑版) -## 1. 基础风格 +1. **文件说明** + - 使用 `//!` 模块文档注释,描述文件或模块作用。 + - 必须位于文件最顶部。 -* 使用 **Rust 2021 edition**。 -* 缩进统一 **4 空格**,不使用 Tab。 -* 每行代码长度建议不超过 **100 字符**。 -* **花括号风格**: +2. **版权声明(可选)** + - 如果项目需要版权信息,放在文档注释之后。 - ```rust - fn example() { - // good - } - ``` -* 表达式尽量简洁,必要时换行,参数链式调用时 **缩进对齐**。 +3. **外部依赖和模块引入(use)** + - 所有 `use` 必须放在文件顶部,不能出现在中间或底部。 + - 引入顺序:标准库 -> 当前 crate 模块 -> 父模块 -> 第三方库 + - 每一类之间空 1 行,同一类内部按字母序排列 + - 所有 `use` **不允许**添加注释说明分组 + - 紧凑要求:单行导入尽量合并,不要强行拆成多行 ---- +4. **子模块声明(mod)** + - 写在所有 `use` 之后 + - `pub mod`、`mod` 都在这里集中声明 -## 2. 模块与导入 +5. **常量定义(const / static)** + - 必须在类型定义之前 + - 命名使用 `SCREAMING_SNAKE_CASE` + - 紧凑要求:值较短时保持单行,不要拆行 -* 模块顶部导入,按以下顺序分组,组间空一行: +6. **类型别名(type)** + - 放在常量之后、结构体之前 - 1. **标准库 (`std::..`)** - 2. **第三方库 (`chrono`, `sea_orm`, `tokio` 等)** - 3. **本地 crate (`crate::..`)** -* 统一使用 **显式导入**,禁止 `use super::*` 或 `use crate::*`。 -* 相同模块导入合并: +7. **结构体定义(struct)** + - 放在文件的类型区域开头 + - 所有 `struct` 必须集中写在这里,不允许与 `impl` 穿插 + - 紧凑要求:字段数量不多时保持单行;字段多时每行一个 - ```rust - use sea_orm::{EntityTrait, QueryFilter, ColumnTrait}; - ``` +8. **枚举定义(enum)** + - 紧随结构体之后,集中定义所有枚举类型 + - 紧凑要求:简单枚举保持单行,复杂枚举多行 ---- +9. **联合体定义(union)** + - 如果需要,放在枚举之后 -## 3. 命名规则 +10. **Trait 定义** + - 紧跟在所有数据类型(struct/enum/union)之后 -* **模块 / 文件名**:`snake_case` -* **函数 / 变量名**:`snake_case` -* **结构体 / 枚举名**:`PascalCase` -* **常量**:`UPPER_CASE` -* **DTO/请求体/响应体**后缀:`Doc` / `Req` / `Resp` +11. **实现块(impl Struct)** + - 必须放在类型定义和 Trait 定义之后 + - 内部方法顺序:构造函数 -> 公共方法 -> 私有方法 + - 紧凑要求:函数体内调用链、元组、match 分支若能在一行内写清楚,则保持单行 -示例: +12. **Trait 实现(impl Trait for Struct)** + - 紧跟对应的 `impl Struct` 之后 + - 不要与其他类型的实现混在一起 -```rust -pub struct ScheduleJobDoc { .. } -pub struct CreateReq { .. } -pub struct PageResp { .. } -``` +13. **自由函数(fn,不属于任何 impl)** + - 文件中独立函数放在最后 + - 按功能分组,可以用注释分隔 + - 紧凑要求:参数少的函数调用保持单行 ---- - -## 4. 文档与注释 - -* 每个 **模块** 顶部使用 `//!` 写模块职责说明。 -* 每个 **公开函数** 必须有 `///` 注释,简述用途与主要逻辑。 -* 内部复杂逻辑使用 `//` 单行注释解释。 -* 中文注释优先,避免英文缩写晦涩难懂。 - -示例: - -```rust -/// 创建任务: -/// - 校验 cron 表达式 -/// - 校验唯一性 -/// - 入库后注册调度器 -pub async fn create(..) -> Result<..> { .. } -``` - ---- - -## 5. 错误处理 - -* 错误类型统一用 **自定义错误枚举**(如 `AppError`)。 -* 不直接 `unwrap()` / `expect()`,统一返回 `Result`。 -* 错误信息应清晰且面向用户,内部日志保留技术细节。 - ---- - -## 6. 日志规范 - -* 使用 `tracing` 库,必须带 `target`。 -* 统一格式:`模块.操作.状态` -* 日志字段使用 `key = %value` 或 `key = ?value`,避免拼接字符串。 - -示例: - -```rust -info!(target = "udmin", id = %job_id, enabled = %enabled, "schedule_jobs.update.persisted"); -error!(target = "udmin", id = %job_id, error = %e, "schedule_jobs.run.failed"); -``` - ---- - -## 7. 异步与数据库 - -* 使用 `async fn`,返回 `Result`。 -* SeaORM 查询使用链式写法,**按字段过滤**时一行一个 filter。 -* 分页/排序明确写出,不隐式。 - -示例: - -```rust -let jobs = schedule_job::Entity::find() - .filter(schedule_job::Column::Enabled.eq(true)) - .order_by_desc(schedule_job::Column::UpdatedAt) - .paginate(db, page_size); -``` - ---- - -## 8. 结构体组织 - -* DTO / 请求体 / 响应体 放在模块前部。 -* Service 函数按生命周期顺序:`list → create → update → remove → init`。 -* 工具函数(如 `build_executor_for_job`、`now_fixed_offset`)放在模块最后。 - ---- - -## 9. 闭包与异步执行器 - -* 使用 `Arc::new(move || { Box::pin(async move { .. }) })` 形式。 -* 避免重复 clone,大对象提前 clone 一次再 move 进闭包。 -* 返回 `Pin + Send>>`。 - ---- - -## 10. 时间与 ID - -* 时间统一用 `chrono::Utc::now().with_timezone(&FixedOffset::east_opt(0).unwrap())`,可封装成 `now_fixed_offset()`。 -* ID 统一使用 `id: Set(crate::utils::generate_id())`。 - ---- - -## 11. 统一返回体 - -* 分页接口统一返回 `PageResp`。 -* 单条数据返回 DTO(如 `ScheduleJobDoc`)。 -* 删除接口返回 `Result<(), AppError>`。 - ---- - -## 12. 代码整洁性 - -* 避免嵌套过深,必要时提前 `return`。 -* 冗余 clone 使用 `.clone()` 仅在必须时。 -* 枚举 / match 分支完整,必要时加 `_ => {}` 显式忽略。 - ---- - -⚡ 总结: -生成的代码必须 **简洁、清晰、分组有序、日志一致、错误优雅**,看起来像经验丰富的 Rust 高手写的生产级代码。 +14. **测试模块(#[cfg(test)] mod tests)** + - 永远放在文件最末尾 + - 仅用于单元测试代码 \ No newline at end of file diff --git a/backend/src/flow/engine.rs b/backend/src/flow/engine.rs index 43c0c50..85afe88 100644 --- a/backend/src/flow/engine.rs +++ b/backend/src/flow/engine.rs @@ -76,7 +76,7 @@ thread_local! { static RHIA_ENGINE: RefCell = RefCell::new({ let mut eng = Engine::new(); // 限制执行步数,防止复杂表达式消耗过多计算资源 - eng.set_max_operations(100_000); + eng.set_max_operations(10_000_000); // 严格变量模式,避免拼写错误导致静默为 null eng.set_strict_variables(true); // 注册常用工具函数 diff --git a/backend/src/flow/executors/variable.rs b/backend/src/flow/executors/variable.rs index 797977f..42c4b82 100644 --- a/backend/src/flow/executors/variable.rs +++ b/backend/src/flow/executors/variable.rs @@ -54,8 +54,11 @@ fn resolve_assign_value(ctx: &Value, v: &Value) -> Value { return resolve_assign_value(ctx, &ref_json); } } - // ctx[...] / ctx. 前缀 -> 表达式求值 - return eval_rhai_expr_json(s_trim, ctx).unwrap_or_else(|_| V::Null); + // 仅当以 ctx[ 或 ctx. 前缀时才进行表达式求值;否则保留原字符串常量 + if s_trim.starts_with("ctx[") || s_trim.starts_with("ctx.") { + return eval_rhai_expr_json(s_trim, ctx).unwrap_or_else(|_| V::Null); + } + return V::String(s.to_string()); } v.get("content").cloned().unwrap_or(V::Null) }