# 基础节点与 C# 功能对应 SDK 1.6 新增 141 个内置基础节点,核心现有 164 个动作节点,另有 4 个系统触发器。基础节点在独立 Runner 执行,无需安装插件;通过“全部来源 → 内置节点”查找,也可搜索中文名称、能力 ID 或 C# 方法名,例如“文本拼接”“string concat”“Enumerable.Where”“Math.Round”“break”。 常量和变量支持[画布内类型编辑](typed-values.md):数组用加号逐项添加,对象逐字段添加,文本/数字/布尔使用对应控件。右侧属性和工作流变量使用同一编辑方式,无需为基础数据手工编写 JSON。 本次检索了仓库的 C# 源文件、现有核心调度与逻辑分支、插件能力清单和测试,再与 C# 运算符、语句、字符串及集合 API 对照。文件、HTTP、命令行、屏幕、企业微信等已有能力继续由对应插件提供。下表按自动化用途归类;编译器声明、访问修饰符和指针操作留在 C# 编辑器,避免把一个语言关键字机械地当作一个节点。 ## 分类 | 分类 | 核心动作数 | 主要内容 | |---|---:|---| | 文本操作 | 23 | 拼接、数组连接、拆分、长度、截取、替换、首尾空白、大小写、包含、前后缀、位置、填充、重复、按行拆分、Unicode 规范化、空文本、插入、删除、格式化、正则匹配/替换/转义 | | 数学运算 | 21 | 加减乘除、余数、最小/最大、乘方、绝对值、相反数、取整、符号、四舍五入、范围、随机、数学函数、数字格式化、数组统计、整数位运算 | | 比较与布尔 | 13 | 相等/不等/大小比较、与/或/异或/非、全部/任意、条件选择值 | | 数组与集合 | 26 | 组合、追加、前插、合并、读取、替换、插入、删除、截取、长度、包含、位置、反转、去重、排序、筛选、查找、字段投影、数字序列、展开、分批、配对、分组、并/交/差集 | | 对象与 JSON | 14 | 设置/删除/存在、字段名/值/键值对、数量、合并、选择字段、数组/键值对生成对象、深复制、任意 JSON 解析、可读 JSON 格式化 | | 变量与数据 | 11 | 原有变量写入、对象字段读取;新增文本/数字/布尔/对象/数组/null 常量,变量读取/删除/递增递减 | | 类型判断 | 4 | 读取 JSON 类型、类型判断、null 判断、null 回退 | | 类型转换 | 6 | 原有文本、数字、布尔、对象、数组转换与 JSON 序列化 | | 日期与时间 | 10 | 当前时间、解析、格式化、加减、时间差、组成、Unix 时间戳双向转换、时区、时间线比较 | | 编码与标识 | 10 | Base64、URL 参数、HTML、UTF-8 十六进制双向转换,摘要与 GUID | | 路径操作 | 4 | 拼接、组成、扩展名、绝对路径 | | 逻辑控制 | 15 | 原有条件、Switch、遍历、当前项、While、并行、汇合、异常处理;新增计数循环、重复、Do While、break、continue、throw、当前异常 | | 流程、代码、基础操作、日志操作 | 7 | 开始/结束/调用工作流、C#、延时、输出/导出日志 | 逐节点能力 ID、输入、输出和用途见[完整基础节点目录](basic-node-catalog.md)。节点属性及每个圆环的悬停提示也提供相应说明。画布卡片保留原有样式,节点库使用原生分类和系统强调色。 ## 先导入运行 在编辑器“文件 → 导入工作流”中选择以下任一包。导入后默认关闭自动触发,F5 手动运行;所有示例无需插件,仅显式日志节点输出内容。 | 模板 | 结果 | JSON 源文件 | |---|---|---| | [文本拼接](../samples/workflows/basic-text-concat.xfeworkflow) | 一行“你好,XFEWorkflow 🌚” | [JSON](../samples/workflows/basic-text-concat.json) | | [筛选联系人并拼接名称](../samples/workflows/basic-array-filter-join.xfeworkflow) | 按多个 ID 筛选 → 提取名称 → 连接文本,一行“张三 🌚、王五 👨‍👩‍👧‍👦” | [JSON](../samples/workflows/basic-array-filter-join.json) | | [计数循环与数学运算](../samples/workflows/basic-for-numbers.xfeworkflow) | 1、2、3 分别乘以 10,输出 10、20、30 | [JSON](../samples/workflows/basic-for-numbers.json) | | [连线条件循环](../samples/workflows/basic-while-wired-condition.xfeworkflow) | 每轮读取 counter 判断是否小于 3,递增并输出 1、2、3,返回 3 | [JSON](../samples/workflows/basic-while-wired-condition.json) | 模板来源为 [Generate-BasicNodeSamples.ps1](../tools/Generate-BasicNodeSamples.ps1),重复运行可重新生成对应 JSON 与 ZIP 包。ZIP 内的 workflow.json 与旁边的 JSON 源一致。 ## 文本与连线 “文本拼接”的 `left`、`right`、`separator` 均为文本输入,`value` 为文本输出;将 `value` 连到日志的 `message` 或通知的正文。没有连线的参数可以手动填写。多个值可先用“组合数组”形成数组,再使用“连接文本数组”;成员必须为文本,数字或对象先转换。 原消息、空白、换行、中文、表情和字面反斜杠保持原样。基础节点的字面参数不解析变量对象或表达式;日志和通知不会自动拼接或插值。“格式化文本”才明确使用 `{0}` 等格式参数,“正则替换”才明确使用分组替换。无需在消息里写变量表达式。 “文本长度”的 `length` 默认计算完整 Unicode 字符,“截取文本”、空分隔符“拆分文本”、插入/删除和填充按完整字符处理;家庭表情、肤色、旗帜与组合重音不会被从中间拆开。`utf16Length` 对应 C# string.Length;“查找文本位置”与正则的 index、length 使用 UTF-16 单元,可与截取节点的 `unit=utf16` 联用。文本/数组索引从 0 开始。 数字端口不能直连文本端口,通用字段输出需要显式转换。比较节点输出布尔,可直接连到“条件分支”的左值,比较选 `truthy`。多个比较结果可以用“布尔与/或”联动。条件选择值 `?:` 只选择已有数据,控制执行路径仍使用条件分支,避免误以为上游会短路执行。[端口规则](typed-ports.md)。 ## 对象与集合 读取字段沿用“读取对象字段”:`found` 区分缺失与存在的 null。数组读取和查找也输出 `found`;未找到的 index 为 -1,越界读取返回 null/false,修改或截取越界则报错。返回对象、数组均为新副本。 “筛选数组”可按 `path` 字段与 `right` 比较;`in`/`notIn` 的 right 是候选数组,适合多个联系人 ID。`path` 留空比较原项,支持点路径和 JSON Pointer。字段缺失视为 null。“提取数组字段”输出字段值数组,默认保留缺失项为 null,可选略过缺失;存在但为 null 的字段仍保留。比如: ```text 搜索缓存联系人.contacts → 筛选数组.items 筛选数组.value → 提取数组字段.items(path = displayName) 提取数组字段.value → 连接文本数组.items(separator = 、) 连接文本数组.value → 输出日志.message ``` 筛选结果也可连接“遍历集合”,在 body 中逐项处理。文本数组连接不接受数值或对象成员;缺失名称可先筛选,或逐项使用 null 回退。排序字段必须同为数字或同为文本,升序 null 排最前,排序稳定;去重及集合运算使用 JSON 深度相等,文本 ID 与数字不同,长 ID 不经过浮点转换。 对象设置/删除/选择字段使用顶层**完整字段名**,点与斜杠不会隐式变成路径。对象合并为浅合并,右侧是否覆盖同名字段可配置。读取嵌套字段继续使用路径读取节点。字段存在、null、空字符串、false、0 均分别保留;`??` 只在 null 时回退。所有查询均不会自动修改消息内容。 ## 循环、变量和异常 “计数循环”输入 start、count、step;count 必须为非负整数,body 当前项为 `start + index * step`。“重复执行”只需 count,当前项为从 0 开始的序号。两者 `results` 收集正常完成的 body 输出,count=0 不执行。continue 跳过的轮次与 break 中断的轮次不加入 results。 在 While 或 Do While 属性中选择“添加判断子图(每轮重算)”。condition 子图中用“读取变量 → 转换为数字 → 比较”构造判断,将布尔输出连到子图“结束”的 result。While 先判断,Do While 先执行至少一次;每轮重新运行判断子图。没有 condition 子图时保留原固定条件及旧绑定兼容。body 与 condition 的顺序变量共享;“当前循环项”可读取 body 的最近一层序号。循环有最大次数保护。 break/continue 只控制最近一层循环 body。嵌套循环退出后恢复外层当前项与 item/index 变量。并行子图可读取当前项,但不能用 break/continue 控制分支外的循环;并行分支自己的内层循环可以控制。独立子工作流和封装方法拥有独立作用域。 “读取变量”输出 value/found,“变量递增递减”不存在时从 0 开始,amount 为负数则递减;非数字报错。“删除变量”输出 removed。并行分支复制变量,不争写父作用域。使用这些节点即可通过连线完成计数,不需在文本里写绑定。 “抛出异常”由“异常处理”的 catch 子图捕获;“当前异常”只允许在 catch 中读取 message、nodeId、type。finally 在正常结束、异常和 break/continue 时执行;取消时不继续运行 finally。循环信号不重试、不交给普通 catch。结束节点结束当前子图或工作流,对应当前方法的 return。 F9 给选中节点设置断点;F5 运行/继续,F10 单步越过,F11 进入结构化子图。基础节点不输出开始、结束或遍历过程日志。[调试说明](debugging.md)。 ## 数学、日期与编码 普通数值计算使用 decimal 与固定小数点格式,0.1+0.2 为 0.3,除零和溢出报错;乘方及数学函数使用 double,非有限结果报错。位运算使用 Int64,移位 0~63。随机整数范围为 `[min,max)`。数字数组空集合 sum/count 为 0,average/min/max 为 null,通过通用端口输出。舍入可明确选择中点远离零或银行家舍入。 日期使用带偏移的 ISO 8601 文本和 Unix 秒/毫秒。解析无偏移日期按 UTC,格式和比较不依赖界面语言;时区转换明确选择 UTC、local 或时区 ID。时间差计算 end-start,可为负数;日期加减的年/月为整数。路径按 Runner 所在操作系统的 Path 规则处理,只改变文本,不移动或读取文件。 Base64、十六进制、摘要按 UTF-8 处理,解码无效 UTF-8 报错。URL 编码用于单个参数,解码保留字面的 `+`。JSON 解析显式产生结构化值;显示/导出继续完整保留中文、表情及必要的 JSON 转义。 新基础运算每次生成的数组最多 100,000 项,输入或输出文本最多 1,048,576 个 UTF-16 单元;正则单次匹配最多 2 秒。长操作检查取消,在 Runner 中执行。超过上限明确定位到节点,避免静默截断。 ## C# 语义对照 | 关键词/表达式 | 图形方式 | |---|---| | `string`、`+`、Concat/Join/Split/Substring/Replace/Trim | 文本常量、文本操作;类型转换为文本 | | `bool`、`true`、`false`、`&&`、`\|\|`、`!`、`^` | 布尔常量、比较与布尔;执行短路用条件分支 | | `int`、`long`、`float`、`double`、`decimal`、`+ - * / %` | 数字常量、数学运算、数字转换;图形 JSON Number 不保留 CLR 数字子类型 | | `&`、`\|`、`^`、`~`、`<<`、`>>` | 整数位运算;需要其他 CLR 整数宽度及 `>>>` 时用 C# 节点 | | `== != > >= < <=`、`?:`、`??`、`is null`、`is`、`typeof` | 比较、条件选择值、空值回退、空值/类型判断、读取值类型 | | `as`、显式强制转换、Parse | 类型判断后显式转换;失败定位节点 | | `const`、`null`、`new`、`var`、`=`、`+= -= ++ --` | 常量、组合数组/创建对象、读写变量、变量递增递减;`var` 由端口类型推断 | | `if else`、`switch case default` | 条件分支、多路选择 | | `for`、`foreach in`、`while`、`do while` | 计数循环、遍历集合、条件循环、先执行后判断循环 | | `break`、`continue`、`return` | 跳出循环、继续下一次、结束当前子图/工作流 | | `try catch finally throw` | 异常处理、当前异常、抛出异常 | | Where/Select/OrderBy/GroupBy/Distinct/Chunk/Zip/Union/Intersect/Except | 数组与集合;任意业务变换使用遍历 body 或 C# 节点 | | `async await`、`Task.WhenAll`、取消 | 所有能力异步执行,显式并行子图、停止/节点超时;异步代码可写在 C# 节点 | | `class struct record interface enum namespace`、`public private protected internal`、`static abstract virtual override sealed partial readonly required init` | 在 C# 工作流/插件 SDK 中声明类型与成员;节点本身对应方法,端口对应参数和返回值 | | `delegate event`、lambda、`yield`、`out ref params`、泛型约束/where | 插件动作/触发器和 C# 方法内使用;组合数据通过显式端口传递,避免跨进程共享 CLR 引用 | | `using`、`lock`、`checked unchecked`、`fixed unsafe stackalloc sizeof`、`goto`、预处理指令 | 在 C# 节点内部使用相应语言语义;图形执行采用结构化子图、受检 decimal、资源句柄与受控释放 | 原始 C# 保留全部语言能力;图形节点重点覆盖可连线、可调试的自动化操作。节点库的英文搜索名来自能力 ID 与描述,不要求用户记住 C# 语法。 ## C# 和插件调用 基础纯数据节点也可通过稳定能力 ID 调用,参数为已经得到的 JSON 值: ```csharp var text = await context.InvokeAsync("core.text.concat", new JsonObject { ["left"] = "你好,", ["right"] = "张三 🌚" }, cancellationToken); await context.LogAsync(text["value"]!.GetValue(), cancellationToken); ``` 结构化循环、变量和异常节点需要当前图的执行作用域,使用图形生成的 C# 或 `ExecuteGraphAsync`。封装图形插件时保留节点与连线,插件清单要求 SDK 1.6;已有兼容范围为 1.0~2.0 的插件仍可运行。没有增加插件实现 DLL 之间的引用。 ## 参考与检查依据 - [C# 关键字](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/)与[语句](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/statement-keywords) - [C# 运算符](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/) - [.NET String](https://learn.microsoft.com/en-us/dotnet/api/system.string?view=net-10.0)、[StringInfo](https://learn.microsoft.com/en-us/dotnet/api/system.globalization.stringinfo?view=net-10.0)与[Regex](https://learn.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regex?view=net-10.0) - [Enumerable 集合操作](https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable?view=net-10.0) 验收包含精确小数、边界和类型拒绝、中文与组合表情、JSON 字面值、稳定排序/去重、日期与编码、嵌套循环和 finally、取消、独立 Runner、JSON/ZIP 导入、生成 C# 及原生 WinUI 搜索/连线/F5。实际结果见[验收记录](acceptance.md)。