diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..0f826be
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,112 @@
+# EditorConfig is awesome:http://EditorConfig.org
+# https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference
+
+# top-most EditorConfig file
+root = true
+
+# Don't use tabs for indentation.
+[*]
+indent_style = space
+# (Please don't specify an indent_size here; that has too many unintended consequences.)
+
+# Code files
+[*.{cs,csx,vb,vbx}]
+indent_size = 4
+insert_final_newline = false
+charset = utf-8-bom
+end_of_line = crlf
+
+# Xml project files
+[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}]
+indent_size = 2
+
+# Xml config files
+[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
+indent_size = 2
+
+# JSON files
+[*.json]
+indent_size = 2
+
+# Dotnet code style settings:
+[*.{cs,vb}]
+# Sort using and Import directives with System.* appearing first
+dotnet_sort_system_directives_first = true
+
+csharp_indent_case_contents = true
+csharp_indent_switch_labels = true
+csharp_indent_labels = flush_left
+
+#csharp_space_after_cast = true
+#csharp_space_after_keywords_in_control_flow_statements = true
+#csharp_space_between_method_declaration_parameter_list_parentheses = true
+#csharp_space_between_method_call_parameter_list_parentheses = true
+#csharp_space_between_parentheses = control_flow_statements, type_casts
+
+# 单行放置代码
+csharp_preserve_single_line_statements = true
+csharp_preserve_single_line_blocks = true
+
+# Avoid "this." and "Me." if not necessary
+dotnet_style_qualification_for_field = false:warning
+dotnet_style_qualification_for_property = false:warning
+dotnet_style_qualification_for_method = false:warning
+dotnet_style_qualification_for_event = false:warning
+
+# Use language keywords instead of framework type names for type references
+dotnet_style_predefined_type_for_locals_parameters_members = false:suggestion
+dotnet_style_predefined_type_for_member_access = false:suggestion
+#dotnet_style_require_accessibility_modifiers = for_non_interface_members:none/always:suggestion
+
+# Suggest more modern language features when available
+dotnet_style_object_initializer = true:suggestion
+dotnet_style_collection_initializer = true:suggestion
+dotnet_style_coalesce_expression = true:suggestion
+dotnet_style_null_propagation = true:suggestion
+dotnet_style_explicit_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
+
+# CSharp code style settings:
+[*.cs]
+# Prefer "var" everywhere
+csharp_style_var_for_built_in_types = true:warning
+csharp_style_var_when_type_is_apparent = true:warning
+csharp_style_var_elsewhere = true:warning
+
+# Prefer method-like constructs to have a block body
+csharp_style_expression_bodied_methods = when_on_single_line:suggestion
+csharp_style_expression_bodied_constructors = when_on_single_line:suggestion
+csharp_style_expression_bodied_operators = when_on_single_line:suggestion
+
+# Prefer property-like constructs to have an expression-body
+csharp_style_expression_bodied_properties = true:suggestion
+csharp_style_expression_bodied_indexers = true:suggestion
+#csharp_style_expression_bodied_accessors = true:suggestion
+
+# Suggest more modern language features when available
+csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
+csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
+csharp_style_inlined_variable_declaration = true:suggestion
+
+csharp_prefer_simple_default_expression = true:suggestion
+csharp_style_deconstructed_variable_declaration = true:suggestion
+csharp_style_pattern_local_over_anonymous_function = true:suggestion
+
+csharp_style_throw_expression = true:suggestion
+csharp_style_conditional_delegate_call = true:suggestion
+
+# 单行不需要大括号
+csharp_prefer_braces = false:suggestion
+
+# Newline settings
+csharp_new_line_before_open_brace = all
+csharp_new_line_before_else = true
+csharp_new_line_before_catch = true
+csharp_new_line_before_finally = true
+csharp_new_line_before_members_in_object_initializers = true
+csharp_new_line_before_members_in_anonymous_types = true
+csharp_new_line_between_query_expression_clauses = true
+
+[*.md]
+trim_trailing_whitespace = false
\ No newline at end of file
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
new file mode 100644
index 0000000..3c5b1dd
--- /dev/null
+++ b/.github/copilot-instructions.md
@@ -0,0 +1,406 @@
+# NewLife Copilot 协作指令
+
+本说明适用于新生命团队(NewLife)及其全部开源/衍生项目,规范 Copilot 及类似智能助手在 C#/.NET 项目中的协作行为。
+
+> 目标:把"每次请求必须携带的通用规则"控制在可接受体积;组件/业务专项流程放在 `.github/instructions/`,按需读取。
+
+---
+
+## 1. 核心原则
+
+| 原则 | 说明 |
+|------|------|
+| **提效** | 减少机械样板,聚焦业务/核心算法 |
+| **一致** | 风格、结构、命名、API 行为稳定 |
+| **可控** | 限制改动影响面,可审计,兼容友好 |
+| **可靠** | 先检索再生成,不虚构,不破坏现有合约 |
+| **主动** | 发现问题主动修复,不回避合理优化 |
+
+---
+
+## 2. 适用范围
+
+- 含 NewLife 组件或衍生的全部 C#/.NET 仓库
+- 不含纯前端/非 .NET/市场文案
+- 存在本文件 → 必须遵循
+
+---
+
+## 3. 组件专用指令索引(按需加载)
+
+以下专用指令**仅在相关任务时**才需要读取,避免每次请求都携带大段流程/示例。
+
+### 3.1 XCode / Cube(数据库 & Web 快速开发)
+
+当任务涉及以下任一信号时,请**先搜索并检查当前仓库** `.github/instructions/xcode.instructions.md` **是否存在**,若存在则读取并遵循:
+
+- 需求包含:XCode/Cube/魔方/实体生成/模型 XML/数据类库/数据库 CRUD/Controller 生成/`xcodetool`/`xcode` 命令
+- 解决方案/项目中出现:`NewLife.XCode` 包引用
+- 存在:`Model.xml`、`*.xcode.xml`、`*.Data.csproj`(或项目名以 `.Data` 结尾)
+- 代码出现命名空间/类型:`XCode.*`、`Entity`(XCode 实体基类)、XCode 相关特性/接口
+- **用户提到修改任意 `.xml` 文件**(如 `member.xml`、`area.xml` 等配置文件),应**主动搜索** `xcode.instructions.md` 判断是否需要引入
+
+**主动检测策略**:当用户提及 XML 文件修改时,即使未明确提到 XCode 关键字,也应先用 `file_search` 搜索 `xcode.instructions.md`,若存在则读取,以确定该 XML 文件是否属于 XCode/Cube 体系。
+
+未满足以上条件时,**不要**引入 XCode/Cube 初始化流程,避免干扰其它仓库的常规开发。
+
+---
+
+## 4. 工作流
+
+```
+需求分类 → 检索 → 评估 → 设计 → 实施 → 验证 → 说明
+```
+
+1. **需求分类**:功能/修复/性能/重构/文档
+2. **检索**:相关类型、目录、方法、已有扩展/工具(**优先复用**)
+3. **评估**:是否公共 API?是否性能热点?**是否存在潜在问题?**
+4. **设计**:列出改动点 + 兼容/降级策略
+5. **实施**:
+ - 完成用户请求的核心任务
+ - **顺带修复**发现的明显缺陷(资源泄漏、空引用、逻辑错误)
+ - **顺带优化**可简化的重复代码
+ - 保留原注释与结构,除非注释本身有误
+6. **验证**:
+ - 代码变更:必须编译通过;运行相关单元测试(未找到需说明)
+ - 仅文档变更(未修改任何代码文件):可跳过编译与单元测试
+7. **说明**:变更摘要/影响范围/风险点
+
+### 4.1 主动优化原则
+
+当用户请求分析或优化代码时,**应主动**:
+
+| 类型 | 行动 |
+|------|------|
+| **架构梳理** | 梳理代码架构并进行重构,让代码结构更清晰易懂 |
+| **语法现代化** | 使用最新的 C# 语法来简化代码,提升可读性 |
+| **缺陷修复** | 资源泄漏、空引用风险、并发问题、逻辑错误 → 直接修复,让代码更健壮 |
+| **性能优化** | 无用分配、重复计算、可池化资源 → 通过缓存减少耗时的重复计算 |
+| **代码简化** | 重复代码提取、冗余判断合并、现代语法替换 → 在不影响可读性前提下简化 |
+| **注释完善** | 补充类、接口、属性、方法头部的注释,以及方法内部重要代码的注释 |
+| **架构参考** | 参考网络上同类功能的优秀架构,给出架构调整建议 |
+
+**架构调整策略**:
+- **改动较小**:直接调整,完成后说明变更内容
+- **改动较大**:先列出调整方案,询问用户意见,待确认后再修改
+
+**不应过度保守**:
+- ❌ 仅添加注释而忽略明显的代码问题
+- ❌ 发现资源泄漏却不修复
+- ❌ 看到重复代码却不提取
+- ❌ 用户要求优化时只做表面工作
+
+**保持谨慎的场景**:
+- 公共 API 签名变更 → 需说明兼容性影响
+- 性能关键路径 → 需有依据或说明推理
+- 大范围重构 → 需先与用户确认范围
+
+### 4.2 防御性注释规则
+
+在旧有代码中,经常可以看到**被注释掉的代码**,这些注释代码前面通常带有说明文字。
+
+**这些是防御性注释**:
+- 记录了过去曾经踩过的坑
+- 目的是告诉后来人不要按照注释代码去写,否则会有问题
+- **禁止删除此类防御性注释**,用于警示后人
+
+**识别特征**:
+```csharp
+// 曾经尝试过 xxx 方案,但会导致 yyy 问题
+// var result = DoSomethingWrong();
+
+// 不要使用 xxx,否则会造成 yyy
+// await client.SendAsync(data);
+
+// 这里不能用 xxx,因为 yyy
+// stream.Flush();
+```
+
+**处理原则**:
+- ✅ 保留这类带说明的注释代码
+- ✅ 可以补充更详细的说明,解释为什么不能这样做
+- ❌ 不要删除这类防御性注释
+- ❌ 不要尝试"恢复"这些被注释的代码
+
+---
+
+## 5. 编码规范
+
+### 5.1 基础规范
+
+| 项目 | 规范 |
+|------|------|
+| 语言版本 | `<LangVersion>latest</LangVersion>`,所有目标框架均使用最新 C# 语法 |
+| 命名空间 | file-scoped namespace |
+| 类型名 | **必须**使用 .NET 正式名 `String`/`Int32`/`Boolean` 等,避免 `string`/`int`/`bool` |
+| 兼容性 | 代码需兼容 .NET 4.5+;**禁止**使用 `ArgumentNullException.ThrowIfNull`,改用 `if (value == null) throw new ArgumentNullException(nameof(value));` |
+| 单文件 | 每文件一个主要公共类型;较大平台差异使用 `partial` |
+
+### 5.2 命名规范
+
+| 成员类型 | 命名规则 | 示例 |
+|---------|---------|------|
+| 类型/公共成员 | PascalCase | `UserService`、`GetName()` |
+| 参数/局部变量 | camelCase | `userName`、`count` |
+| 私有字段(实例/静态) | `_camelCase` | `_cache`、`_instance` |
+| 属性/方法(实例/静态) | PascalCase | `Name`、`Default`、`Create()` |
+| 扩展方法类 | `xxxHelper` 或 `xxxExtensions` | `StringHelper`、`CollectionExtensions` |
+
+### 5.3 代码风格
+
+```csharp
+// ✅ 单行 if:单语句且整行不过长时同行
+if (value == null) return;
+if (key == null) throw new ArgumentNullException(nameof(key));
+
+// ✅ 单行 if:语句较长时另起一行
+if (value == null)
+ throw new ArgumentNullException(nameof(value), "Value cannot be null");
+
+// ✅ 多分支单语句:不加花括号
+if (count > 0)
+ DoSomething();
+else
+ DoOther();
+
+// ✅ 循环必须保留花括号(即使单语句)
+foreach (var item in list)
+{
+ Process(item);
+}
+```
+
+### 5.4 Region 组织结构
+
+较长的类使用 `#region` 分段组织,顺序为:`属性` → `静态`(如有)→ `构造` → `方法` → `辅助`(如有)→ `日志`。
+
+**日志 Region 规则**:
+- 类代码中如果带有 `ILog Log { get; set; }` 和 `WriteLog` 方法
+- **必须放在类代码的最后**
+- **必须用名为"日志"的 region 包裹**
+- 不要放在"辅助" region 中,应单独作为"日志" region
+
+### 5.5 现代 C# 语法
+
+优先使用最新语法(switch 表达式、模式匹配、目标类型 `new`、record 等),即使目标框架是 net45。
+
+### 5.6 集合表达式
+
+优先使用集合表达式 `[]` 初始化集合:`List<String> Tags { get; set; } = [];`
+
+### 5.7 Null 条件运算符
+
+优先使用 `?.` / `??` 简化空值检查:`span?.AppendTag("test");` `var name = user?.Profile?.Name ?? "";`
+
+---
+
+## 6. 多目标框架
+
+NewLife 支持 `net45` 到 `net10`,常用条件符号:`NETFRAMEWORK`、`NETSTANDARD2_0`、`NETCOREAPP`、`NET5_0_OR_GREATER`、`NET6_0_OR_GREATER`、`NET8_0_OR_GREATER`。
+
+新增 API 时需评估各框架兼容性,必要时提供降级实现。
+
+---
+
+## 7. 文档注释
+
+| 规则 | 说明 |
+|------|------|
+| `<summary>` | **必须同一行闭合**,简短描述方法用途 |
+| `<param>` | **必须为每个参数添加**,无论方法可见性如何 |
+| `<returns>` | 有返回值时必须添加 |
+| `<remarks>` | 复杂方法可增加详细说明(可多行) |
+| 覆盖范围 | `public`/`protected` 成员必须注释;`private`/`internal` 建议添加 |
+| `[Obsolete]` | 必须包含迁移建议 |
+
+**正确示例**:`/// <summary>获取名称</summary>` `/// <param name="id">编号</param>`
+
+**禁止**:`<summary>` 拆成多行;缺少 `<param>`;有参数但无 param 标签。
+
+---
+
+## 8. 异步与性能
+
+| 规范 | 说明 |
+|------|------|
+| 方法命名 | 异步方法后缀 `Async` |
+| ConfigureAwait | 库内部默认 `ConfigureAwait(false)` |
+| 高频路径 | 优先对象池/`ArrayPool<T>`/`Span`,避免多余分配 |
+| 反射/Linq | 仅用于非热点路径;热点使用手写循环/缓存 |
+| 池化资源 | 明确获取/归还;异常分支不遗失归还 |
+
+**内置工具优先**:`Pool.StringBuilder`、`Runtime.TickCount64`、`ToInt()`/`ToBoolean()` 等扩展方法。
+
+---
+
+## 9. 日志与追踪
+
+规则:若类包含 `ILog Log` 与 `WriteLog`,必须放在类末尾,并用名为"日志"的 `#region` 包裹;关键过程可使用 `Tracer?.NewSpan()` 埋点。
+
+---
+
+## 10. 错误处理
+
+- **精准异常类型**:`ArgumentNullException`/`InvalidOperationException` 等
+- **参数校验**:空/越界/格式
+- **TryXxx 模式**:不用异常作常规分支
+- **类型转换**:优先使用 `ToInt()`/`ToBoolean()` 等扩展方法
+- **对外异常**:不暴露内部实现/路径
+
+---
+
+## 11. 测试规范
+
+| 项目 | 规范 |
+|------|------|
+| 框架 | xUnit |
+| 命名 | `{ClassName}Tests` |
+| 描述 | `[DisplayName("中文描述意图")]` |
+| IO | 使用临时目录;端口用 0/随机 |
+| 覆盖 | 正常/边界/异常/并发(必要时) |
+
+### 测试执行策略
+
+1. 优先检索 `{ClassName}` 引用,若落入测试项目则运行
+2. 未命中则查找 `{ClassName}Tests.cs`
+3. **未发现相关测试需明确说明**,不自动创建测试项目
+
+---
+
+## 12. NuGet 发布规范
+
+| 类型 | 命名规则 | 示例 |
+|------|---------|------|
+| 正式版 | `{主版本}.{子版本}.{年}.{月日}` | `11.9.2025.0701` |
+| 测试版 | `{主版本}.{子版本}.{年}.{月日}-beta{时分}` | `11.9.2025.0701-beta0906` |
+
+- **正式版**:每月月初发布
+- **测试版**:提交代码到 GitHub 时自动发布
+
+---
+
+## 13. Markdown 文档规范
+
+| 项目 | 规范 |
+|------|------|
+| 文件编码 | **必须** UTF-8,**禁止** GB2312/GBK/UTF-8 BOM |
+| 默认存放 | 代码库根目录下的 `Doc` 目录 |
+| 文件命名 | 优先**中文文件名**,简洁描述内容 |
+
+**注意**:已有文件**必须先读取**再增量修改,**禁止直接覆盖**。
+
+---
+
+## 14. Copilot 行为守则
+
+### 必须
+
+- 简体中文回复
+- 输出前检索现有实现,**禁止重复造轮子**
+- 先列方案再实现
+- 标记不确定上下文为"需查看文件"
+- **发现明显缺陷时主动修复**(资源泄漏、空引用、逻辑错误)
+- **用户要求优化时深入分析**,不做表面工作
+
+### 鼓励
+
+- 提取重复代码为公共方法
+- 简化冗余的条件判断
+- 使用现代 C# 语法改进可读性
+- 补充缺失的资源释放逻辑
+- 修正错误或过时的注释
+
+### 禁止
+
+- 虚构 API/文件/类型
+- 伪造测试结果/性能数据
+- 擅自删除公共/受保护成员
+- 擅自删除已有代码注释(除非注释本身错误)
+- **删除防御性注释**(带说明的注释代码,记录历史踩坑经验)
+- 仅删除空白行制造"格式优化"提交
+- 删除循环体的花括号
+- 将 `<summary>` 拆成多行
+- 将 `String`/`Int32` 改为 `string`/`int`
+- 新增外部依赖(除非说明理由并给出权衡)
+- 在热点路径添加未缓存反射/复杂 Linq
+- 输出敏感凭据/内部地址
+- **发现问题却视而不见**
+- **用户要求优化时仅做注释/测试等表面工作**
+
+---
+
+## 15. 变更说明模板
+
+提交或答复需包含:
+
+```markdown
+## 概述
+做了什么 / 为什么
+
+## 影响
+- 公共 API:是/否
+- 性能影响:无/有(说明)
+
+## 兼容性
+降级策略 / 条件编译点
+
+## 风险
+潜在回归 / 性能开销
+
+## 后续
+是否补测试 / 文档
+```
+
+---
+
+## 16. 术语说明
+
+| 术语 | 定义 |
+|------|------|
+| **热点路径** | 经性能分析或高频调用栈确认的关键执行段 |
+| **基线** | 变更前的功能/性能参考数据 |
+| **顺带修复** | 在完成主任务过程中,修复发现的相关问题 |
+| **防御性注释** | 被注释掉的代码,前面带有说明,记录历史踩坑经验,用于警示后人 |
+
+---
+
+## 17. 代码优化检查清单
+
+当进行代码优化时,按以下清单逐项检查:
+
+### 架构与结构
+- [ ] 代码架构是否清晰?是否需要重构?
+- [ ] 类的职责是否单一?是否需要拆分?
+- [ ] 是否有重复代码可以提取为公共方法?
+- [ ] Region 组织是否符合规范(属性→静态→构造→方法→辅助→日志)?
+
+### 语法现代化
+- [ ] 是否可以使用更简洁的 C# 语法?(switch 表达式、模式匹配等)
+- [ ] 集合初始化是否使用了集合表达式 `[]`?
+- [ ] 是否可以使用 null 条件运算符 `?.` 简化代码?
+
+### 健壮性
+- [ ] 是否存在空引用风险?
+- [ ] 资源是否正确释放?(IDisposable、流、连接等)
+- [ ] 异常处理是否完善?
+- [ ] 并发场景是否线程安全?
+
+### 性能
+- [ ] 是否存在可以缓存的重复计算?
+- [ ] 是否有不必要的对象分配?
+- [ ] 热点路径是否避免了反射和复杂 Linq?
+- [ ] 是否使用了对象池/ArrayPool 等池化技术?
+
+### 注释与文档
+- [ ] 类、接口是否有 `<summary>` 注释?
+- [ ] 公共方法是否有完整的参数和返回值注释?
+- [ ] 方法内重要逻辑是否有注释说明?
+- [ ] 防御性注释是否保留?
+
+### 日志
+- [ ] `ILog Log` 和 `WriteLog` 是否放在类的最后?
+- [ ] 是否用名为"日志"的 region 包裹?
+
+---
+
+(完)
diff --git a/.github/instructions/xcode.instructions.md b/.github/instructions/xcode.instructions.md
new file mode 100644
index 0000000..dcd5984
--- /dev/null
+++ b/.github/instructions/xcode.instructions.md
@@ -0,0 +1,506 @@
+# XCode 协作指令
+
+本指令面向新生命团队(NewLife)开源数据中间件 XCode,帮助 Copilot 在 .NET 项目中正确使用 XCode 进行数据建模和实体操作。
+
+---
+
+## 1. XCode 定位与边界
+
+### 1.1 技术栈定位
+
+```
+NewLife.Core(基础库)
+ ↓
+ NewLife.XCode(数据中间件)← 本指令
+ ↓
+ NewLife.Cube(Web 快速开发框架)→ cube.instructions.md
+```
+
+### 1.2 职责边界
+
+| 层级 | 职责 | 指令文件 |
+|------|------|---------|
+| **NewLife.Core** | 基础扩展、日志、缓存、网络等 | `copilot-instructions.md` |
+| **NewLife.XCode** | 数据建模、ORM、实体增删改查、数据库操作 | 本指令 |
+| **NewLife.Cube** | Web 管理后台、控制器、视图、权限 | `cube.instructions.md` |
+
+### 1.3 本指令覆盖范围
+
+**包含**:
+- 数据模型设计(Model.xml)
+- 实体类生成与使用
+- 数据库 CRUD 操作
+- 项目初始化与 XCode 接入
+
+**不包含**(由 cube.instructions.md 负责):
+- Web 控制器逻辑
+- 视图与前端交互
+- 权限管理配置
+- 魔方区域深度定制
+
+---
+
+## 2. 使用场景与快速入口
+
+### 2.1 场景一:已有项目接入 XCode
+
+1. 引入 NuGet 包:`dotnet add package NewLife.XCode`
+2. 创建或编辑 `Model.xml` 进行数据建模
+3. 执行 `xcode` 命令生成实体类
+4. 在业务代码中使用实体类进行数据操作
+
+### 2.2 场景二:从零创建新项目
+
+1. 安装模板:`dotnet new install NewLife.Templates`
+2. 创建数据类库:`dotnet new xcode -n {系统名}.Data`
+3. 创建应用项目:
+ - Web 应用:`dotnet new cube -n {系统名}Web`
+ - 控制台应用:`dotnet new nconsole -n {系统名}App`
+4. 编辑 `Model.xml` 进行数据建模
+5. 执行 `xcode` 生成实体类
+
+### 2.3 核心工作流
+
+```
+理解业务需求 → 数据建模(Model.xml) → 生成实体类(xcode) → 编写业务代码
+```
+
+**关键点**:无论哪种场景,核心都是 **充分理解业务需求,在 Model.xml 中设计合理的数据表结构**。
+
+---
+
+## 3. 环境准备
+
+### 3.1 前置要求
+
+```powershell
+# 检查 .NET SDK(要求 8.0+)
+dotnet --version
+
+# 安装全局工具 xcodetool
+dotnet tool install xcodetool -g
+```
+
+### 3.2 模板版本检查
+
+NewLife.Templates 模板会持续更新,使用前需检查版本:
+
+```powershell
+# 查看模板详情
+dotnet new details NewLife.Templates
+```
+
+**判定规则**:输出包含类似 `包版本: 1.1.2025.820-beta1836`
+- 其中 `1.1.2025.820` 表示 v1.1,发布日期为 2025-08-20
+- **要求**:发布日期需 > 2025-08-01(即严格晚于 2025-08-01)
+
+```powershell
+# 若未安装或版本过旧,执行安装/更新
+dotnet new install NewLife.Templates
+```
+
+> **强约束**:仅当未安装或发布日期 ≤ 2025-08-01 时才执行安装;否则保持现状,避免无谓变更。
+
+### 3.3 模板说明
+
+| 模板 | 命令 | 用途 |
+|------|------|------|
+| `xcode` | `dotnet new xcode -n Name.Data` | 数据类库项目 |
+| `cube` | `dotnet new cube -n NameWeb` | Web 管理后台 |
+| `nconsole` | `dotnet new nconsole -n NameApp` | 控制台应用 |
+
+---
+
+## 4. Model.xml 完整参考
+
+### 4.1 文件结构
+
+```xml
+<?xml version="1.0" encoding="utf-8"?>
+<EntityModel xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
+ xs:schemaLocation="https://newlifex.com https://newlifex.com/Model202509.xsd"
+ xmlns="https://newlifex.com/Model202509.xsd">
+ <Option>
+ <!-- 全局配置 -->
+ </Option>
+ <Tables>
+ <Table>
+ <Columns>
+ <Column />
+ </Columns>
+ <Indexes>
+ <Index />
+ </Indexes>
+ </Table>
+ </Tables>
+</EntityModel>
+```
+
+### 4.2 Option 配置项
+
+| 配置项 | 说明 | 示例 |
+|--------|------|------|
+| `Namespace` | 命名空间 | `Zero.Data` |
+| `ConnName` | 数据库连接名 | `Zero` |
+| `Output` | 实体类输出目录 | `.\` |
+| `BaseClass` | 实体基类 | `Entity` |
+| `ChineseFileName` | 使用中文文件名 | `True` |
+| `Nullable` | 生成可空引用类型 | `True` |
+| `HasIModel` | 实现 IModel 接口 | `True` |
+| `ModelClass` | 模型类模板 | `{name}Model` |
+| `ModelsOutput` | 模型类输出目录 | `.\Models\` |
+| `ModelInterface` | 模型接口模板 | `I{name}` |
+| `InterfacesOutput` | 接口输出目录 | `.\Interfaces\` |
+| `NameFormat` | 命名格式 | `Default`/`Upper`/`Lower`/`Underline` |
+| `DisplayName` | 魔方区域显示名 | `订单管理` |
+| `CubeOutput` | 魔方控制器输出目录 | `../../Web/Areas/Order` |
+
+### 4.3 Table 属性
+
+| 属性 | 说明 | 示例 |
+|------|------|------|
+| `Name` | 实体类名 | `User` |
+| `TableName` | 数据库表名(可选,默认同 Name) | `sys_user` |
+| `Description` | 表说明 | `用户。用户账号信息` |
+| `ConnName` | 独立连接名(覆盖全局) | `Log` |
+| `BaseType` | 基类(支持实体继承) | `EntityBase` |
+| `InsertOnly` | 仅插入模式(日志表优化) | `True` |
+| `IsView` | 视图标识 | `True` |
+
+### 4.4 Column 属性完整参考
+
+#### 基础属性
+
+| 属性 | 说明 | 示例 |
+|------|------|------|
+| `Name` | 属性名 | `UserName` |
+| `ColumnName` | 数据库列名(可选) | `user_name` |
+| `DataType` | 数据类型 | `Int32`/`Int64`/`String`/`DateTime`/`Boolean`/`Double`/`Decimal` |
+| `Description` | 字段说明 | `用户名。登录账号` |
+| `Length` | 字符串长度 | `50`/`200`/`-1`(大文本) |
+| `Precision` | 数值精度 | `18` |
+| `Scale` | 小数位数 | `2` |
+
+#### 主键与标识
+
+| 属性 | 说明 | 示例 |
+|------|------|------|
+| `PrimaryKey` | 主键 | `True` |
+| `Identity` | 自增标识 | `True` |
+| `Master` | 主字段(业务主要字段) | `True` |
+
+#### 约束与默认值
+
+| 属性 | 说明 | 示例 |
+|------|------|------|
+| `Nullable` | 允许空 | `False` |
+| `DefaultValue` | 默认值 | `0`/`''`/`getdate()` |
+
+#### 映射关系(Map)
+
+格式:`表名@主键@显示字段@属性名`
+
+| 格式 | 说明 | 示例 |
+|------|------|------|
+| `Table@Id@Name` | 基本映射(三段) | `Role@Id@Name` |
+| `Table@Id@Name@RoleName` | 指定属性名(四段) | `Role@Id@Name@RoleName` |
+| `NS.Table@Id@Path@AreaPath` | 完整命名空间 | `XCode.Membership.Area@Id@Path@AreaPath` |
+
+#### 元素类型(ItemType)
+
+用于魔方前端渲染和数据验证:
+
+| ItemType | 说明 |
+|----------|------|
+| `image` | 图片上传 |
+| `file` | 文件上传 |
+| `mail` | 邮箱格式 |
+| `mobile` | 手机号格式 |
+| `url` | URL 链接 |
+| `TimeSpan` | 时间间隔(秒转可读格式) |
+| `GMK` | 字节数转 GB/MB/KB |
+| `html` | HTML 富文本 |
+| `code` | 代码编辑器 |
+| `json` | JSON 编辑器 |
+
+#### 显示选项(ShowIn)
+
+控制字段在魔方各区域的显示,支持三种语法:
+
+**语法一:具名列表(推荐)**
+```
+ShowIn="List,Search" # List和Search显示
+ShowIn="-EditForm,-Detail" # 编辑表单和详情隐藏
+ShowIn="All,-Detail" # 全部显示,详情隐藏
+ShowIn="None,Search,Add" # 全部隐藏,搜索和添加显示
+```
+
+区域别名:`List(L)`、`Detail(D)`、`AddForm(Add/A)`、`EditForm(Edit/E)`、`Search(S)`、`Form(F)`(同时控制 Add 和 Edit)
+
+**语法二:管道分隔**
+```
+ShowIn="Y|Y|N||A" # List=显示|Detail=显示|Add=隐藏|Edit=自动|Search=自动
+```
+
+**语法三:5字符掩码**
+```
+ShowIn="11110" # 1=显示, 0=隐藏, A/?/-=自动
+```
+
+#### 分表字段(DataScale)
+
+| 值 | 说明 |
+|----|------|
+| `time` | 大数据单表的时间字段(用于雪花 ID) |
+| `timeShard:yyMMdd` | 分表字段,按日期格式分表 |
+
+#### 其他属性
+
+| 属性 | 说明 | 示例 |
+|------|------|------|
+| `Type` | 枚举类型 | `XCode.Membership.SexKinds` |
+| `Category` | 表单分组 | `登录信息`/`扩展` |
+| `Attribute` | 额外特性 | `XmlIgnore, IgnoreDataMember` |
+| `Model` | 是否包含在模型类中 | `False` |
+| `RawType` | 原始数据库类型 | `varchar(50)` |
+
+### 4.5 Index 属性
+
+| 属性 | 说明 | 示例 |
+|------|------|------|
+| `Columns` | 索引列(逗号分隔) | `Name`/`Category,CreateTime` |
+| `Unique` | 唯一索引 | `True` |
+
+### 4.6 完整示例
+
+```xml
+<?xml version="1.0" encoding="utf-8"?>
+<EntityModel xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
+ xs:schemaLocation="https://newlifex.com https://newlifex.com/Model202509.xsd"
+ xmlns="https://newlifex.com/Model202509.xsd">
+ <Option>
+ <Namespace>Order.Data</Namespace>
+ <ConnName>Order</ConnName>
+ <Output>.\</Output>
+ <ChineseFileName>True</ChineseFileName>
+ <Nullable>True</Nullable>
+ <HasIModel>True</HasIModel>
+ <DisplayName>订单管理</DisplayName>
+ <CubeOutput>../../OrderWeb/Areas/Order</CubeOutput>
+ </Option>
+ <Tables>
+ <Table Name="Order" Description="订单。电商订单主表">
+ <Columns>
+ <Column Name="Id" DataType="Int64" PrimaryKey="True" DataScale="time" Description="编号" />
+ <Column Name="OrderNo" DataType="String" Master="True" Length="50" Nullable="False" Description="订单号" />
+ <Column Name="UserId" DataType="Int32" Map="User@Id@Name" Description="用户" />
+ <Column Name="Status" DataType="Int32" Type="Order.Data.OrderStatus" Description="状态" />
+ <Column Name="TotalAmount" DataType="Decimal" Precision="18" Scale="2" Description="总金额" />
+ <Column Name="Remark" DataType="String" Length="500" Description="备注" Category="扩展" />
+ <Column Name="CreateUser" DataType="String" Description="创建者" Model="False" Category="扩展" />
+ <Column Name="CreateTime" DataType="DateTime" Nullable="False" Description="创建时间" Category="扩展" />
+ <Column Name="UpdateTime" DataType="DateTime" Description="更新时间" Model="False" Category="扩展" />
+ </Columns>
+ <Indexes>
+ <Index Columns="OrderNo" Unique="True" />
+ <Index Columns="UserId" />
+ <Index Columns="Status,CreateTime" />
+ </Indexes>
+ </Table>
+ </Tables>
+</EntityModel>
+```
+
+---
+
+## 5. 实体类操作指南
+
+### 5.1 基础 CRUD
+
+```csharp
+// 新增
+var entity = new User { Name = "test", Password = "123456" };
+entity.Insert();
+
+// 查询单个
+var user = User.FindByKey(1);
+var user = User.Find(User._.Name == "test");
+
+// 查询列表
+var list = User.FindAll();
+var list = User.FindAll(User._.Status == 1, User._.Id.Desc(), null, 0, 10);
+
+// 更新
+user.Name = "newName";
+user.Update();
+
+// 删除
+user.Delete();
+
+// 保存(自动判断 Insert/Update)
+entity.Save();
+```
+
+### 5.2 高级查询
+
+```csharp
+// 分页查询
+var page = new PageParameter { PageIndex = 1, PageSize = 20 };
+var list = User.FindAll(User._.Status == 1, page);
+
+// 条件组合
+var where = new WhereExpression();
+where &= User._.Status == 1;
+where &= User._.CreateTime >= DateTime.Today;
+if (!key.IsNullOrEmpty()) where &= User._.Name.Contains(key);
+var list = User.FindAll(where, page);
+
+// 统计
+var count = User.FindCount(User._.Status == 1);
+
+// 查询最大/最小值
+var maxId = User.FindMax(User._.Id, null);
+```
+
+### 5.3 批量操作
+
+```csharp
+// 批量插入
+var list = new List<User>();
+list.Insert();
+
+// 批量更新
+User.Update(User._.Status == 2, User._.Status == 1);
+
+// 批量删除
+User.Delete(User._.Status == 0);
+```
+
+### 5.4 异步操作
+
+```csharp
+var user = await User.FindAsync(User._.Id == 1);
+var list = await User.FindAllAsync(User._.Status == 1, page);
+await entity.InsertAsync();
+await entity.SaveAsync(); // 异步保存,用于日志等高频写入
+```
+
+### 5.5 缓存查询
+
+```csharp
+// 实体缓存(适用于小表)
+var list = User.FindAllWithCache();
+
+// 单对象缓存(按主键)
+var user = User.FindByKeyWithCache(1);
+```
+
+---
+
+## 6. 多模块项目结构
+
+对于复杂业务系统,建议按模块组织:
+
+```
+Zero.Data/
+├── Order/ # 订单模块
+│ ├── Order.xml # 订单模型
+│ ├── 订单.cs
+│ └── 订单明细.cs
+├── Product/ # 商品模块
+│ ├── Product.xml # 商品模型
+│ ├── 商品.cs
+│ └── 分类.cs
+└── Member/ # 会员模块
+ ├── Member.xml # 会员模型
+ └── 会员.cs
+```
+
+每个模块目录内有独立的 `*.xml` 模型文件,在各自目录执行 `xcode` 命令生成实体类。
+
+---
+
+## 7. xcode 命令参考
+
+```powershell
+# 在模型文件所在目录执行(自动查找所有 *.xml)
+xcode
+
+# 指定模型文件
+xcode Model.xml
+xcode Order.xml
+```
+
+**执行效果**:
+1. 读取 XML 模型文件
+2. 生成实体类(`*.cs`)
+3. 生成模型类(如配置了 `ModelClass`)
+4. 生成接口(如配置了 `ModelInterface`)
+5. 生成数据字典(`*.htm`)
+6. 生成魔方控制器(如配置了 `CubeOutput`)
+
+---
+
+## 8. 常见问题
+
+### 8.1 模型文件命名
+
+- 默认:`Model.xml`
+- 推荐:`{系统英文名}.xml` 或 `{模块名}.xml`
+- 复杂项目:每个模块目录一个模型文件
+
+### 8.2 实体类生成位置
+
+- 实体类生成在 `xcode` 命令执行目录
+- 可通过 `Output` 配置项指定输出目录
+- 魔方控制器通过 `CubeOutput` 指定
+
+### 8.3 数据库连接
+
+在应用配置文件中配置连接字符串:
+
+```json
+{
+ "ConnectionStrings": {
+ "Order": "Server=.;Database=Order;Uid=sa;Pwd=xxx"
+ }
+}
+```
+
+连接名对应 Model.xml 中的 `ConnName`。
+
+---
+
+## 9. 与 Cube 的协作
+
+当需要生成 Web 管理界面时:
+
+1. 在 Model.xml 中配置 `CubeOutput` 指向 Web 项目的 Areas 目录
+2. 配置 `DisplayName` 作为魔方区域名称
+3. 执行 `xcode` 自动生成控制器
+4. 深度定制请参考 `cube.instructions.md`
+
+---
+
+## 10. Copilot 行为指引
+
+### 10.1 数据建模时
+
+1. **充分理解业务**:在设计表结构前,确保理解业务场景和数据关系
+2. **合理设计主键**:
+ - 普通表:`Int32` 自增主键
+ - 大数据表:`Int64` + `DataScale="time"`(雪花 ID)
+3. **必要的索引**:为查询条件字段添加索引
+4. **字段长度**:String 类型必须指定合理的 `Length`
+
+### 10.2 生成代码时
+
+1. 确保在正确目录执行 `xcode`
+2. 生成后检查编译是否通过
+3. 如需修改生成的代码,应修改 Model.xml 后重新生成
+
+### 10.3 边界意识
+
+- 数据模型和实体操作 → 本指令
+- Web 控制器和界面 → `cube.instructions.md`
+- 基础编码规范 → `copilot-instructions.md`
diff --git a/.github/workflows/publish-beta.yml b/.github/workflows/publish-beta.yml
new file mode 100644
index 0000000..d591c90
--- /dev/null
+++ b/.github/workflows/publish-beta.yml
@@ -0,0 +1,32 @@
+name: publish-beta
+
+on:
+ push:
+ branches: [ master ]
+ paths:
+ - 'NewLife.WeiXin/**'
+ workflow_dispatch:
+
+jobs:
+ build-publish:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Setup dotNET
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: |
+ 6.x
+ 7.x
+ 8.x
+ 9.x
+ 10.x
+ - name: Build
+ run: |
+ dotnet pack --version-suffix $(date "+%Y.%m%d-beta%H%M") -c Release -o out NewLife.WeiXin/NewLife.WeiXin.csproj
+ dotnet pack --version-suffix $(date "+%Y.%m%d-beta%H%M") -c Release -o out NewLife.WeiXinWeb/NewLife.WeiXinWeb.csproj
+ - name: Publish
+ run: |
+ dotnet nuget push ./out/*.nupkg --skip-duplicate --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.nugetKey }}
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
new file mode 100644
index 0000000..09693ee
--- /dev/null
+++ b/.github/workflows/publish.yml
@@ -0,0 +1,30 @@
+name: publish
+
+on:
+ push:
+ tags: [ v* ]
+ workflow_dispatch:
+
+jobs:
+ build-publish:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Setup dotNET
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: |
+ 6.x
+ 7.x
+ 8.x
+ 9.x
+ 10.x
+ - name: Build
+ run: |
+ dotnet pack --version-suffix $(date "+%Y.%m%d") -c Release -o out NewLife.WeiXin/NewLife.WeiXin.csproj
+ dotnet pack --version-suffix $(date "+%Y.%m%d") -c Release -o out NewLife.WeiXinWeb/NewLife.WeiXinWeb.csproj
+ - name: Publish
+ run: |
+ dotnet nuget push ./out/*.nupkg --skip-duplicate --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.nugetKey }}
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 0000000..d5eb09b
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,31 @@
+name: test
+
+on:
+ push:
+ branches: [ '*' ]
+ pull_request:
+ branches: [ '*' ]
+ workflow_dispatch:
+
+jobs:
+ build-publish:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Setup dotNET
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: |
+ 6.x
+ 7.x
+ 8.x
+ 9.x
+ 10.x
+ - name: Build
+ run: |
+ dotnet build -c Release
+ - name: Test
+ run: |
+ dotnet test -c Release XUnitTest/XUnitTest.csproj
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..72bf59c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,26 @@
+################################################################################
+# 此 .gitignore 文件已由 Microsoft(R) Visual Studio 自动创建。
+################################################################################
+
+/.vs
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+build/
+bld/
+[Bb]in/
+[Oo]bj/
+/packages
+*.user
+/Data
+/Log
+*.log
+*.htm
+*.nuspec
+*.nupkg
+/BinTest
+/BinUnitTest
+/NewLife.WeiXinWeb/Locations/Config
diff --git a/Doc/leaf.png b/Doc/leaf.png
new file mode 100644
index 0000000..cb15e89
Binary files /dev/null and b/Doc/leaf.png differ
diff --git a/Doc/newlife.snk b/Doc/newlife.snk
new file mode 100644
index 0000000..31ae707
Binary files /dev/null and b/Doc/newlife.snk differ
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..f3d40f6
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2018 新生命开发团队
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/NewLife.WeiXin.sln b/NewLife.WeiXin.sln
new file mode 100644
index 0000000..f82d24e
--- /dev/null
+++ b/NewLife.WeiXin.sln
@@ -0,0 +1,52 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.32112.339
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Test\Test.csproj", "{582E00A2-4FA4-41DC-84AD-EE264A9FF4D8}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XUnitTest", "XUnitTest\XUnitTest.csproj", "{08A39462-0531-45AB-ACBB-03F62AF4400F}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{719C113A-6804-4150-8473-BF889F06DFD6}"
+ ProjectSection(SolutionItems) = preProject
+ .editorconfig = .editorconfig
+ .github\workflows\publish-beta.yml = .github\workflows\publish-beta.yml
+ .github\workflows\publish.yml = .github\workflows\publish.yml
+ Readme.MD = Readme.MD
+ .github\workflows\test.yml = .github\workflows\test.yml
+ EndProjectSection
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NewLife.WeiXin", "NewLife.WeiXin\NewLife.WeiXin.csproj", "{9C7D96F5-136F-4FBD-8D58-18105263D041}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NewLife.WeiXinWeb", "NewLife.WeiXinWeb\NewLife.WeiXinWeb.csproj", "{393023C1-CCC2-40E3-AE4B-2AA6B4A20BC1}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {582E00A2-4FA4-41DC-84AD-EE264A9FF4D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {582E00A2-4FA4-41DC-84AD-EE264A9FF4D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {582E00A2-4FA4-41DC-84AD-EE264A9FF4D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {582E00A2-4FA4-41DC-84AD-EE264A9FF4D8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {08A39462-0531-45AB-ACBB-03F62AF4400F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {08A39462-0531-45AB-ACBB-03F62AF4400F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {08A39462-0531-45AB-ACBB-03F62AF4400F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {08A39462-0531-45AB-ACBB-03F62AF4400F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9C7D96F5-136F-4FBD-8D58-18105263D041}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9C7D96F5-136F-4FBD-8D58-18105263D041}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9C7D96F5-136F-4FBD-8D58-18105263D041}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9C7D96F5-136F-4FBD-8D58-18105263D041}.Release|Any CPU.Build.0 = Release|Any CPU
+ {393023C1-CCC2-40E3-AE4B-2AA6B4A20BC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {393023C1-CCC2-40E3-AE4B-2AA6B4A20BC1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {393023C1-CCC2-40E3-AE4B-2AA6B4A20BC1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {393023C1-CCC2-40E3-AE4B-2AA6B4A20BC1}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {323831A1-A95B-40AB-B9AD-36A0BC10C2CB}
+ EndGlobalSection
+EndGlobal
diff --git a/NewLife.WeiXin/NewLife.WeiXin.csproj b/NewLife.WeiXin/NewLife.WeiXin.csproj
new file mode 100644
index 0000000..b01edf8
--- /dev/null
+++ b/NewLife.WeiXin/NewLife.WeiXin.csproj
@@ -0,0 +1,59 @@
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <TargetFrameworks>net45;net461;netstandard2.0;netstandard2.1</TargetFrameworks>
+ <AssemblyTitle>微信对接库</AssemblyTitle>
+ <Description>微信对接库</Description>
+ <Company>新生命开发团队</Company>
+ <Copyright>©2002-2026 新生命开发团队</Copyright>
+ <VersionPrefix>1.0</VersionPrefix>
+ <VersionSuffix>$([System.DateTime]::Now.ToString(`yyyy.MMdd`))</VersionSuffix>
+ <Version>$(VersionPrefix).$(VersionSuffix)</Version>
+ <FileVersion>$(Version)</FileVersion>
+ <AssemblyVersion>$(VersionPrefix).*</AssemblyVersion>
+ <Deterministic>false</Deterministic>
+ <OutputPath>..\Bin</OutputPath>
+ <GenerateDocumentationFile>True</GenerateDocumentationFile>
+ <LangVersion>latest</LangVersion>
+ <ImplicitUsings>enable</ImplicitUsings>
+ <Nullable>enable</Nullable>
+ <SignAssembly>True</SignAssembly>
+ <AssemblyOriginatorKeyFile>..\Doc\newlife.snk</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <PackageId>$(AssemblyName)</PackageId>
+ <Authors>$(Company)</Authors>
+ <PackageProjectUrl>https://newlifex.com/core</PackageProjectUrl>
+ <PackageIcon>leaf.png</PackageIcon>
+ <RepositoryUrl>https://github.com/NewLifeX/NewLife.WeiXin</RepositoryUrl>
+ <RepositoryType>git</RepositoryType>
+ <PackageTags>新生命团队;X组件;NewLife;$(AssemblyName)</PackageTags>
+ <PackageReleaseNotes></PackageReleaseNotes>
+ <PackageLicenseExpression>MIT</PackageLicenseExpression>
+ <PublishRepositoryUrl>true</PublishRepositoryUrl>
+ <EmbedUntrackedSources>true</EmbedUntrackedSources>
+ <IncludeSymbols>true</IncludeSymbols>
+ <SymbolPackageFormat>snupkg</SymbolPackageFormat>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <Compile Remove="IpHelper.cs" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Microsoft.SourceLink.GitHub" Version="10.0.103">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageReference Include="NewLife.Core" Version="11.11.2026.201" />
+ <PackageReference Include="NewLife.Stardust" Version="3.7.2026.201" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <Content Include="..\Doc\leaf.png" Link="leaf.png" PackagePath="\" />
+ </ItemGroup>
+
+</Project>
diff --git a/NewLife.WeiXin/WeiXinFactory.cs b/NewLife.WeiXin/WeiXinFactory.cs
new file mode 100644
index 0000000..4c8a54e
--- /dev/null
+++ b/NewLife.WeiXin/WeiXinFactory.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace NewLife.WeiXin;
+
+internal class WeiXinFactory
+{
+}
diff --git a/NewLife.WeiXinWeb/appsettings.Development.json b/NewLife.WeiXinWeb/appsettings.Development.json
new file mode 100644
index 0000000..770d3e9
--- /dev/null
+++ b/NewLife.WeiXinWeb/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "DetailedErrors": true,
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/NewLife.WeiXinWeb/appsettings.json b/NewLife.WeiXinWeb/appsettings.json
new file mode 100644
index 0000000..da92fac
--- /dev/null
+++ b/NewLife.WeiXinWeb/appsettings.json
@@ -0,0 +1,18 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "AllowedHosts": "*",
+ "ConnectionStrings": {
+ "WeiXin": "Data Source=..\\Data\\WeiXin.db;showsql=false;Provider=Sqlite",
+
+ //"Location_MySql": "server=.;database=gps;user=gps;password=gps;Provider=MySql",
+ //"Membership_MySql": "server=.;database=gps;user=gps;password=gps;Provider=MySql",
+
+ "Cube": "MapTo=Membership",
+ "Log": "MapTo=Membership"
+ }
+}
diff --git a/NewLife.WeiXinWeb/MapSetting.cs b/NewLife.WeiXinWeb/MapSetting.cs
new file mode 100644
index 0000000..b833715
--- /dev/null
+++ b/NewLife.WeiXinWeb/MapSetting.cs
@@ -0,0 +1,48 @@
+using System.ComponentModel;
+using NewLife.Configuration;
+using XCode.Configuration;
+
+namespace IoTWeb;
+
+/// <summary>地址配置</summary>
+[Config("Map")]
+public class MapSetting : Config<MapSetting>
+{
+ #region 静态
+ static MapSetting() => Provider = new DbConfigProvider { UserId = 0, Category = "Map" };
+ #endregion
+
+ #region 属性
+ /// <summary>启用地图。默认true</summary>
+ [Description("启用地图。默认true")]
+ public Boolean Enable { get; set; } = true;
+
+ /// <summary>地图提供者。默认NewLife</summary>
+ [Description("地图提供者。默认NewLife")]
+ public String MapProvider { get; set; } = "NewLife";
+
+ /// <summary>Js地图密钥。浏览器端密钥</summary>
+ [Description("Js地图密钥。浏览器端密钥")]
+ public String JsKey { get; set; }
+
+ /// <summary>地图服务密钥。WebService密钥</summary>
+ [Description("地图服务密钥。WebService密钥")]
+ public String ServiceKey { get; set; }
+
+ /// <summary>地图中心城市。默认西安</summary>
+ [Description("地图中心城市。默认西安")]
+ public String CenterCity { get; set; } = "西安";
+
+ /// <summary>缩放等级。默认6看全国,17最小</summary>
+ [Description("缩放等级。默认6看全国,17最小")]
+ public Int32 ZoomLevel { get; set; } = 6;
+
+ /// <summary>卫星图。默认false</summary>
+ [Description("卫星图。默认false")]
+ public Boolean Earth { get; set; }
+
+ /// <summary>缓存天数。更新数据库记录的时间,默认30天</summary>
+ [Description("缓存天数。更新数据库记录的时间,默认30天")]
+ public Int32 CacheDays { get; set; } = 30;
+ #endregion
+}
\ No newline at end of file
diff --git a/NewLife.WeiXinWeb/NewLife.WeiXinWeb.csproj b/NewLife.WeiXinWeb/NewLife.WeiXinWeb.csproj
new file mode 100644
index 0000000..f9d4bf6
--- /dev/null
+++ b/NewLife.WeiXinWeb/NewLife.WeiXinWeb.csproj
@@ -0,0 +1,30 @@
+<Project Sdk="Microsoft.NET.Sdk.Web">
+
+ <PropertyGroup>
+ <TargetFrameworks>net6.0;net8.0;net10.0</TargetFrameworks>
+ <AssemblyTitle>微信Api</AssemblyTitle>
+ <Description>微信Api接口</Description>
+ <Company>新生命开发团队</Company>
+ <Copyright>©2002-2026 新生命开发团队</Copyright>
+ <VersionPrefix>1.0</VersionPrefix>
+ <VersionSuffix>$([System.DateTime]::Now.ToString(`yyyy.MMdd`))</VersionSuffix>
+ <Version>$(VersionPrefix).$(VersionSuffix)</Version>
+ <FileVersion>$(Version)</FileVersion>
+ <AssemblyVersion>$(VersionPrefix).*</AssemblyVersion>
+ <Deterministic>false</Deterministic>
+ <OutputPath>..\Bin\NewLife.WeiXinWeb</OutputPath>
+ <ImplicitUsings>enable</ImplicitUsings>
+ <LangVersion>latest</LangVersion>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageReference Include="NewLife.Cube.Core" Version="6.9.2026.201" />
+ <PackageReference Include="NewLife.Stardust.Extensions" Version="3.7.2026.201" />
+ <PackageReference Include="NewLife.XCode" Version="11.24.2026.201" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\NewLife.WeiXin\NewLife.WeiXin.csproj" />
+ </ItemGroup>
+
+</Project>
diff --git a/NewLife.WeiXinWeb/Program.cs b/NewLife.WeiXinWeb/Program.cs
new file mode 100644
index 0000000..af8835b
--- /dev/null
+++ b/NewLife.WeiXinWeb/Program.cs
@@ -0,0 +1,58 @@
+using NewLife.Cube;
+using NewLife.Log;
+using XCode;
+
+// 日志输出到控制台,并拦截全局异常
+XTrace.UseConsole();
+
+var builder = WebApplication.CreateBuilder(args);
+var services = builder.Services;
+
+// 配置星尘。借助StarAgent,或者读取配置文件 config/star.config 中的服务器地址、应用标识、密钥
+var star = services.AddStardust(null);
+
+// 初始配置
+var set = NewLife.Setting.Current;
+if (set.IsNew)
+{
+ set.DataPath = "../Data";
+ set.Save();
+}
+
+_ = EntityFactory.InitAllAsync();
+
+//services.AddSingleton<MapService>();
+
+// Add services to the container.
+builder.Services.AddRazorPages();
+
+// 引入魔方
+services.AddCube();
+
+var app = builder.Build();
+
+// Configure the HTTP request pipeline.
+if (!app.Environment.IsDevelopment())
+{
+ app.UseExceptionHandler("/Error");
+ // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
+ app.UseHsts();
+}
+
+app.UseHttpsRedirection();
+app.UseStaticFiles();
+
+app.UseRouting();
+
+app.UseAuthorization();
+
+app.UseCube(app.Environment);
+
+app.MapControllerRoute(
+ name: "default",
+ pattern: "{controller=CubeHome}/{action=Index}/{id?}");
+
+// 启用星尘注册中心,向注册中心注册服务,服务消费者将自动更新服务端地址列表
+app.RegisterService("NewLife.WeiXin", null, app.Environment.EnvironmentName);
+
+app.Run();
diff --git a/NewLife.WeiXinWeb/Properties/launchSettings.json b/NewLife.WeiXinWeb/Properties/launchSettings.json
new file mode 100644
index 0000000..ed1eb77
--- /dev/null
+++ b/NewLife.WeiXinWeb/Properties/launchSettings.json
@@ -0,0 +1,13 @@
+{
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "http://localhost:5122",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/Readme.MD b/Readme.MD
new file mode 100644
index 0000000..4024bc9
--- /dev/null
+++ b/Readme.MD
@@ -0,0 +1,229 @@
+# NewLife.WeiXin - 地图组件库
+
+
+
+
+
+
+
+地图组件库
+
+源码: https://github.com/NewLifeX/NewLife.WeiXin
+Nuget:`NewLife.WeiXin`
+
+## 功能特性
+- 统一接口 IMap,屏蔽百度 / 高德 / 腾讯 / 天地图 / 企业自建(NewLifeMap) 差异
+- 地理编码(地址→坐标)/ 逆地理编码(坐标→地址)
+- 路径距离/驾车时间(不同厂商策略参数差异已抽象)
+- 行政区划查询(高德)
+- POI / 语义信息融合,自动补充地址组件
+- IP 定位(百度)
+- 多 Key 轮询与自动熔断 + 定时恢复(内置限流/失效关键字识别)
+- 坐标系互转:WGS84 / GCJ02 / BD09(内置常用转换公式)及厂商在线批量转换(百度特殊 from/to 映射)
+- 可选抛出异常 `ThrowException`,便于上层统一处理
+- 多目标框架:net45 / net461 / netstandard2.0 / netstandard2.1(兼容老项目与现代 .NET)
+- 强命名签名,适合反射与插件体系
+- Stardust 注册中心集成(`NewLifeMap` 提供者)支持服务发现与多实例地址自动刷新
+
+## 安装
+```bash
+# 稳定版
+ dotnet add package NewLife.WeiXin
+# 预览版(带日期)
+ dotnet add package NewLife.WeiXin --prerelease
+```
+
+## 快速开始
+```csharp
+using NewLife.WeiXin;
+using NewLife.Data;
+
+// 选择一个具体地图提供者(BaiduMap / AMap / TencentMap / TianDiMap / NewLifeMap)
+var map = new BaiduMap { AppKey = "<BAIDU_AK>" }; // 多个 key 用逗号分隔
+
+// 1. 正向地理编码:地址 -> 坐标
+var geo = await map.GetGeoAsync("北京市海淀区上地十街10号", city: "北京", coordtype: "bd09ll", formatAddress: true);
+Console.WriteLine($"Point: {geo?.Location} 语义:{geo?.Title}");
+
+// 2. 逆地理编码:坐标 -> 地址
+var addr = await map.GetReverseGeoAsync(new GeoPoint(116.30815, 40.056885), "bd09ll");
+Console.WriteLine(addr?.Address);
+
+// 3. 距离(驾车)
+var d = await map.GetDistanceAsync(new GeoPoint(116.30815, 40.056885), new GeoPoint(116.39745, 39.909187), "bd09ll");
+Console.WriteLine($"Distance={d?.Distance}m Duration={d?.Duration}s");
+
+// 4. 坐标转换(离线公式)
+var list = await map.ConvertAsync(new List<GeoPoint> { new(116.30815, 40.056885) }, from: "wgs84", to: "bd09");
+Console.WriteLine(list[0]);
+```
+> 坐标系需使用球面坐标(经纬度),输出为 BD09 坐标系的点。
+
+## 通过工厂动态创建
+```csharp
+var m1 = Map.Create("Baidu"); // 自动匹配 *Map 后缀
+var m2 = Map.Create("AMap"); // 高德
+var m3 = Map.Create("NewLifeMap");
+```
+> `AppKey` 在实例化后设置;多个 key 以逗号分隔,内部轮询使用。
+
+## 提供者说明
+| 提供者 | 类名 | 主要能力 | 备注 |
+| ------ | ---- | -------- | ---- |
+| 百度地图 | `BaiduMap` | 地理/逆地理/距离/POI检索/IP定位/坐标转换(在线+离线) | `KeyName=ak` |
+| 高德地图 | `AMap` | 地理/逆地理/距离/行政区划/坐标转换(离线) | `KeyName=key` |
+| 腾讯地图 | `TencentMap` | (若实现) 地理/逆地理/距离 | 同模式 |
+| 天地图 | `TianDiMap` | (若实现) 地理/逆地理 | |
+| 新生命地图平台 | `NewLifeMap` | 企业聚合接口(后端微服务统一封装) | 通过 Stardust 服务发现 |
+
+`TencentMap.cs` / `TianDiMap.cs` 若为空或未实现,可按 AMap/BaiduMap 模式扩展。
+
+## NewLifeMap & 星尘集成
+```csharp
+// 方式1:直接指定服务端
+var map = new NewLifeMap("http://mapapi.company.local") { AppKey = "<KEY>" };
+
+// 方式2:依赖注入 + Stardust Registry 自动解析地址
+services.AddSingleton<IMap, NewLifeMap>();
+// NewLifeMap(IServiceProvider) 构造函数中会尝试:IRegistry -> StarFactory
+```
+当后端 NewLife.WeiXinWeb 节点列表变化时,绑定的 `ApiHttpClient` 会自动更新,可在多副本/蓝绿发布中无感切换。
+
+## AppKey 多 Key 轮询与熔断
+- 传入 `AppKey="k1,k2,k3"`
+- 每次请求递增索引取余
+- 若响应命中无效关键字(如:`TOO_FREQUENT`, `LIMIT`, `INVALID` 等),调用 `RemoveKey()` 将其暂时下线
+- 下线 key 会放入 `_pendingKeys`,定时器到期后自动恢复
+- 恢复时间策略:当前实现为调用处自行传入(例如 1 小时)
+
+## 坐标系说明
+| 名称 | 说明 | 常见厂商 |
+| ---- | ---- | -------- |
+| WGS84 | 国际通用 GPS | 设备原始定位 |
+| GCJ02 | 国测局加偏 | 高德 / 腾讯 / 绝大多数国内在线地图 |
+| BD09 | 百度加偏 | 百度 |
+
+调用示例:
+```csharp
+var rs = await map.ConvertAsync(new [] { new GeoPoint(lng, lat) }, from:"wgs84", to:"gcj02");
+```
+百度在线转换需要 from/to 索引值,本库已封装。
+
+## 常用 API 一览
+```csharp
+Task<GeoAddress?> GetGeoAsync(string address, string? city=null, string? coordtype=null, bool formatAddress=false);
+Task<GeoAddress?> GetReverseGeoAsync(GeoPoint point, string? coordtype);
+Task<Driving?> GetDistanceAsync(GeoPoint origin, GeoPoint destination, string? coordtype, int type=0);
+Task<IList<GeoPoint>> ConvertAsync(IList<GeoPoint> points, string from, string to);
+```
+扩展(BaiduMap / AMap 特有):
+```csharp
+Task<GeoAddress?> PlaceSearchAsync(...); // BaiduMap POI / 区域检索
+Task<IList<GeoArea>> GetAreaAsync(...); // AMap 行政区划
+Task<IDictionary<string, object?>> IpLocationAsync(...); // BaiduMap IP 定位
+```
+
+## 错误处理
+- 默认:接口返回非成功状态不会抛异常,方法返回 null
+- 设置 `map.ThrowException = true;` 后抛出 `Exception`,便于外层统一捕获
+- 最近一次请求调试信息:`LastUrl` / `LastString` / `LastResult` / `LastKey`
+
+## 扩展一个新地图提供者步骤
+1. 新建类 `XXXMap : Map, IMap`
+2. 设置 `Server` / `KeyName`
+3. 重写 `InvokeAsync<T>` 解析该厂商统一返回结构 & 错误码
+4. 实现 `GetGeoAsync` / `GetReverseGeoAsync` / 其它所需能力
+5. 若有专属限流/失效特征,重写 `IsValidKey` 返回 true 触发临时下线
+6. 提交单元测试覆盖主要功能与边界
+
+## 单元测试
+仓库包含 `XUnitTest` 工程:
+- `*MapTests`:针对不同提供者的编码/逆编码测试
+- 请将真实 Key 放入本地用户机密或环境变量,不要提交到仓库
+
+运行:
+```bash
+dotnet test -c Release
+```
+
+## 构建
+```bash
+dotnet build -c Release
+```
+输出(多框架编译)位于 `Bin/`。
+
+## Roadmap / TODO
+- [ ] 补全 `TencentMap` / `TianDiMap` 具体实现(若仍为空)
+- [ ] 为 `NewLifeMap` 聚合平台补充正向地理编码与距离计算接口
+- [ ] 增加并发限速(令牌桶)可选适配,避免密钥整体封禁
+- [ ] 添加 Benchmark 基准对比(批量坐标转换)
+- [ ] 丰富故障统计 / Metrics(成功率、平均耗时、Key 命中率)
+
+## 版本策略
+主版本 = 兼容性变更;次版本 = 新功能;修订号 = 修复 / 优化。`VersionSuffix` 带日期,便于快速定位构建。
+
+## 贡献
+欢迎 Issue / PR:Bug、性能优化、支持更多地图、补充文档与测试。提交前请阅读 `.github/copilot-instructions.md` 以保持代码风格一致。
+
+## 许可证
+MIT,保留版权声明即可自由使用于商业 / 开源项目。
+
+---
+
+## NewLifeMap
+地图提供者NewLifeMap指向内置MapApi地图接口平台,屏蔽各家接口差异,支持自定义修改。
+NewLifeMap 可明文制定服务端地址,也可以借助依赖注入自动从星尘注册中心获取。
+
+## 新生命项目矩阵
+各项目默认支持net9.0/netstandard2.1/netstandard2.0/net4.62/net4.5,旧版(2024.0801)支持net4.0/net2.0
+
+| 项目 | 年份 | 说明 |
+| :--------------------------------------------------------------: | :---: | ------------------------------------------------------------------------------------------- |
+| 基础组件 | | 支撑其它中间件以及产品项目 |
+| [NewLife.Core](https://github.com/NewLifeX/X) | 2002 | 核心库,日志、配置、缓存、网络、序列化、APM性能追踪 |
+| [NewLife.XCode](https://github.com/NewLifeX/NewLife.XCode) | 2005 | 大数据中间件,单表百亿级,MySql/SQLite/SqlServer/Oracle/PostgreSql/达梦,自动分表,读写分离 |
+| [NewLife.Net](https://github.com/NewLifeX/NewLife.Net) | 2005 | 网络库,单机千万级吞吐率(2266万tps),单机百万级连接(400万Tcp长连接) |
+| [NewLife.Remoting](https://github.com/NewLifeX/NewLife.Remoting) | 2011 | 协议通信库,提供CS应用通信框架,支持Http/RPC通信框架,高吞吐,物联网设备低开销易接入 |
+| [NewLife.Cube](https://github.com/NewLifeX/NewLife.Cube) | 2010 | 魔方快速开发平台,集成了用户权限、SSO登录、OAuth服务端等,单表100亿级项目验证 |
+| [NewLife.Agent](https://github.com/NewLifeX/NewLife.Agent) | 2008 | 服务管理组件,把应用安装成为操作系统守护进程,Windows服务、Linux的Systemd |
+| [NewLife.Zero](https://github.com/NewLifeX/NewLife.Zero) | 2020 | Zero零代脚手架,基于NewLife组件生态的项目模板NewLife.Templates,Web、WebApi、Service |
+| 中间件 | | 对接知名中间件平台 |
+| [NewLife.Redis](https://github.com/NewLifeX/NewLife.Redis) | 2017 | Redis客户端,微秒级延迟,百万级吞吐,丰富的消息队列,百亿级数据量项目验证 |
+| [NewLife.RocketMQ](https://github.com/NewLifeX/NewLife.RocketMQ) | 2018 | RocketMQ纯托管客户端,支持Apache RocketMQ和阿里云消息队列,十亿级项目验 |
+| [NewLife.MQTT](https://github.com/NewLifeX/NewLife.MQTT) | 2019 | 物联网消息协议,MqttClient/MqttServer,客户端支持阿里云物联网 |
+| [NewLife.IoT](https://github.com/NewLifeX/NewLife.IoT) | 2022 | IoT标准库,定义物联网领域的各种通信协议标准规范 |
+| [NewLife.Modbus](https://github.com/NewLifeX/NewLife.Modbus) | 2022 | ModbusTcp/ModbusRTU/ModbusASCII,基于IoT标准库实现,支持ZeroIoT平台和IoTEdge网关 |
+| [NewLife.Siemens](https://github.com/NewLifeX/NewLife.Siemens) | 2022 | 西门子PLC协议,基于IoT标准库实现,支持IoT平台和IoTEdge |
+| [NewLife.WeiXin](https://github.com/NewLifeX/NewLife.WeiXin) | 2022 | 地图组件库,封装百度地图、高德地图、腾讯地图、天地图 |
+| [NewLife.Audio](https://github.com/NewLifeX/NewLife.Audio) | 2023 | 音频编解码库,PCM/ADPCMA/G711A/G722U/WAV/AAC |
+| 产品平台 | | 产品平台级,编译部署即用,个性化自定义 |
+| [Stardust](https://github.com/NewLifeX/Stardust) | 2018 | 星尘,分布式服务平台,节点管理、APM监控中心、配置中心、注册中心、发布中心 |
+| [AntJob](https://github.com/NewLifeX/AntJob) | 2019 | 蚂蚁调度,分布式大数据计算平台(实时/离线),蚂蚁搬家分片思想,万亿级数据量项目验证 |
+| [NewLife.ERP](https://github.com/NewLifeX/NewLife.ERP) | 2021 | 企业ERP,产品管理、客户管理、销售管理、供应商管理 |
+| [CrazyCoder](https://github.com/NewLifeX/XCoder) | 2006 | 码神工具,众多开发者工具,网络、串口、加解密、正则表达式、Modbus、MQTT |
+| [EasyIO](https://github.com/NewLifeX/EasyIO) | 2023 | 简易文件存储,支持分布式系统中文件集中存储。 |
+| [XProxy](https://github.com/NewLifeX/XProxy) | 2005 | 产品级反向代理,NAT代理、Http代理 |
+| [HttpMeter](https://github.com/NewLifeX/HttpMeter) | 2022 | Http压力测试工具 |
+| [GitCandy](https://github.com/NewLifeX/GitCandy) | 2015 | Git源代码管理系统 |
+| [SmartOS](https://github.com/NewLifeX/SmartOS) | 2014 | 嵌入式操作系统,完全独立自主,支持ARM Cortex-M芯片架构 |
+| [SmartA2](https://github.com/NewLifeX/SmartA2) | 2019 | 嵌入式工业计算机,物联网边缘网关,高性能.NET8主机,应用于工业、农业、交通、医疗 |
+| FIoT物联网平台 | 2020 | 物联网整体解决方案,建筑、环保、农业,软硬件及大数据分析一体化,单机十万级点位项目验证 |
+| UWB高精度室内定位 | 2020 | 厘米级(10~20cm)高精度室内定位,软硬件一体化,与其它系统联动,大型展厅项目验证 |
+
+
+
+## 新生命开发团队
+
+
+新生命团队(NewLife)成立于2002年,是新时代物联网行业解决方案提供者,致力于提供软硬件应用方案咨询、系统架构规划与开发服务。
+团队主导的80多个开源项目已被广泛应用于各行业,Nuget累计下载量高达400余万次。
+团队开发的大数据中间件NewLife.XCode、蚂蚁调度计算平台AntJob、星尘分布式平台Stardust、缓存队列组件NewLife.Redis以及物联网平台FIoT,均成功应用于电力、高校、互联网、电信、交通、物流、工控、医疗、文博等行业,为客户提供了大量先进、可靠、安全、高质量、易扩展的产品和系统集成服务。
+
+我们将不断通过服务的持续改进,成为客户长期信赖的合作伙伴,通过不断的创新和发展,成为国内优秀的IoT服务供应商。
+
+`新生命团队始于2002年,部分开源项目具有20年以上漫长历史,源码库保留有2010年以来所有修改记录`
+网站:https://newlifex.com
+开源:https://github.com/newlifex
+QQ群:1600800/1600838
+微信公众号:
+
diff --git a/Test/Program.cs b/Test/Program.cs
new file mode 100644
index 0000000..9ecb7a8
--- /dev/null
+++ b/Test/Program.cs
@@ -0,0 +1,28 @@
+using NewLife.Log;
+
+namespace Test
+{
+ class Program
+ {
+ static void Main(String[] args)
+ {
+ XTrace.UseConsole();
+
+ try
+ {
+ Test1();
+ }
+ catch (Exception ex)
+ {
+ XTrace.WriteException(ex);
+ }
+
+ Console.WriteLine("OK!");
+ Console.ReadKey();
+ }
+
+ static async void Test1()
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/Test/Properties/PublishProfiles/FolderProfile.pubxml b/Test/Properties/PublishProfiles/FolderProfile.pubxml
new file mode 100644
index 0000000..3c0e917
--- /dev/null
+++ b/Test/Properties/PublishProfiles/FolderProfile.pubxml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+https://go.microsoft.com/fwlink/?LinkID=208121.
+-->
+<Project>
+ <PropertyGroup>
+ <Configuration>Release</Configuration>
+ <Platform>Any CPU</Platform>
+ <PublishDir>..\Bin\Test\publish\</PublishDir>
+ <PublishProtocol>FileSystem</PublishProtocol>
+ </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/Test/Test.csproj b/Test/Test.csproj
new file mode 100644
index 0000000..884fee5
--- /dev/null
+++ b/Test/Test.csproj
@@ -0,0 +1,23 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <TargetFramework>net10.0</TargetFramework>
+ <OutputPath>..\Bin\Test</OutputPath>
+ <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
+ <ImplicitUsings>enable</ImplicitUsings>
+ <LangVersion>latest</LangVersion>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageReference Include="NewLife.Core" Version="11.11.2026.201" />
+ <PackageReference Include="NewLife.Stardust.Extensions" Version="3.7.2026.201" />
+ <PackageReference Include="NewLife.XCode" Version="11.24.2026.201" />
+ <PackageReference Include="xunit.assert" Version="2.9.3" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\NewLife.WeiXin\NewLife.WeiXin.csproj" />
+ </ItemGroup>
+
+</Project>
diff --git a/XUnitTest/BasicTest.cs b/XUnitTest/BasicTest.cs
new file mode 100644
index 0000000..fc3553e
--- /dev/null
+++ b/XUnitTest/BasicTest.cs
@@ -0,0 +1,11 @@
+using Xunit;
+
+namespace XUnitTest;
+
+public class BasicTest
+{
+ [Fact]
+ public async void ConvertAsync()
+ {
+ }
+}
\ No newline at end of file
diff --git a/XUnitTest/XUnitTest.csproj b/XUnitTest/XUnitTest.csproj
new file mode 100644
index 0000000..3c73cb5
--- /dev/null
+++ b/XUnitTest/XUnitTest.csproj
@@ -0,0 +1,26 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFramework>net10.0</TargetFramework>
+ <OutputPath>..\Bin\UnitTest</OutputPath>
+
+ <IsPackable>false</IsPackable>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.3" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
+ <PackageReference Include="NewLife.Core" Version="11.11.2026.201" />
+ <PackageReference Include="NewLife.UnitTest" Version="1.1.2026.102" />
+ <PackageReference Include="xunit" Version="2.9.3" />
+ <PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\NewLife.WeiXin\NewLife.WeiXin.csproj" />
+ </ItemGroup>
+
+</Project>