diff --git a/BasePlatformDotnet/Directory.Build.props b/BasePlatformDotnet/Directory.Build.props
index cbddf3c..7f4befe 100644
--- a/BasePlatformDotnet/Directory.Build.props
+++ b/BasePlatformDotnet/Directory.Build.props
@@ -10,8 +10,9 @@
false
true
- 1.0.0-preview.1
+ 1.0.0-preview.1:核对表 #6~#9/#12 未实调,先发预发布;实调通过再定 1.0.0
+ 1.0.0-preview.2:Yh.SchClass.OpenApi 新增 SchTree(/oapi/SchGroup/GetTeaTree 教师组树) -->
+ 1.0.0-preview.2
$(YhPlatformNetVersion)
yunhai-platform
yunhai
diff --git a/BasePlatformDotnet/src/Yh.SchClass.OpenApi/Model/TeaTreeVo.cs b/BasePlatformDotnet/src/Yh.SchClass.OpenApi/Model/TeaTreeVo.cs
new file mode 100644
index 0000000..68fe77a
--- /dev/null
+++ b/BasePlatformDotnet/src/Yh.SchClass.OpenApi/Model/TeaTreeVo.cs
@@ -0,0 +1,37 @@
+using System.Text.Json.Serialization;
+
+namespace Yh.SchClass.OpenApi.Model;
+
+///
+/// 学校教师组树节点视图对象(镜像 Java com.yunhai.bschclassmanage.model.oa.TeaTreeVO)。
+///
+/// Java 侧为 Lombok @Data + @JsonInclude(NON_NULL):教师叶子节点的
+/// children 为 null 会被省略;本客户端大小写不敏感反序列化,按 Java 字段原名锚定即可双向兼容。
+///
+///
+public class TeaTreeVo
+{
+ /// 节点 ID(学校/组为组中心 ID,教师为 teaId,未分组兜底节点为 -1)
+ [JsonPropertyName("id")] public int? Id { get; set; }
+
+ /// 节点名称
+ [JsonPropertyName("name")] public string? Name { get; set; }
+
+ /// 父节点 ID(根节点为 0)
+ [JsonPropertyName("pid")] public int? Pid { get; set; }
+
+ /// 排序号(组=组中心 sort,教师=0)
+ [JsonPropertyName("no")] public int? No { get; set; }
+
+ /// 节点类型(1=组节点,2=教师叶子)
+ [JsonPropertyName("type")] public int? Type { get; set; }
+
+ /// 是否父节点(组=true,教师=false)
+ [JsonPropertyName("isParent")] public bool? IsParent { get; set; }
+
+ /// 头像(Java 侧固定空串)
+ [JsonPropertyName("photo")] public string? Photo { get; set; }
+
+ /// 子节点(组节点保证非 null;教师叶子为 null)
+ [JsonPropertyName("children")] public List? Children { get; set; }
+}
diff --git a/BasePlatformDotnet/src/Yh.SchClass.OpenApi/SchClassSchTreeClient.cs b/BasePlatformDotnet/src/Yh.SchClass.OpenApi/SchClassSchTreeClient.cs
new file mode 100644
index 0000000..ee30945
--- /dev/null
+++ b/BasePlatformDotnet/src/Yh.SchClass.OpenApi/SchClassSchTreeClient.cs
@@ -0,0 +1,28 @@
+using Yh.SchClass.OpenApi.Model;
+
+namespace Yh.SchClass.OpenApi;
+
+///
+/// 学校教师组树客户端(镜像 Java SchGroupController,路径前缀 /oapi/SchGroup/)。
+///
+public class SchClassSchTreeClient : SchClassClientBase
+{
+ private const string Root = Prefix + "/SchGroup/";
+
+ public SchClassSchTreeClient(HttpClient httpClient, SchClassOpenApiOptions options)
+ : base(httpClient, options)
+ {
+ }
+
+ ///
+ /// 获取学校教师组树(GET /oapi/SchGroup/GetTeaTree)。
+ /// 返回单元素数组(根 = 学校节点,type=1),其下为教师组层级挂教师叶子(type=2)。
+ /// 与 至少提供一个(服务端 schId 优先),
+ /// 都缺时服务端返回空数组(本方法返回空列表,与 Java 行为一致)。
+ ///
+ /// 学校外部序列号(Java 参数名 SchSerID)。
+ /// 学校内部 ID(Java 参数名 schId,优先使用)。
+ public Task> GetTeaTreeAsync(string? schSerId = null, int? schId = null, CancellationToken ct = default)
+ => ResolveListAsync(HttpMethod.Get, Root + "GetTeaTree",
+ Params(("SchSerID", schSerId), ("schId", schId)), ct: ct);
+}
diff --git a/BasePlatformDotnet/tests/Yh.SchClass.OpenApi.Tests/SchClassSchTreeClientTests.cs b/BasePlatformDotnet/tests/Yh.SchClass.OpenApi.Tests/SchClassSchTreeClientTests.cs
new file mode 100644
index 0000000..f6457d6
--- /dev/null
+++ b/BasePlatformDotnet/tests/Yh.SchClass.OpenApi.Tests/SchClassSchTreeClientTests.cs
@@ -0,0 +1,101 @@
+namespace Yh.SchClass.OpenApi.Tests;
+
+/// SchTree(教师组树)端点契约与 反序列化。
+public class SchClassSchTreeClientTests
+{
+ private const string Root = "/oapi/SchGroup/";
+
+ [Fact]
+ public async Task SchGroup_GetTeaTree_路径与参数名对齐()
+ {
+ var handler = SchClassTestHost.Ok();
+ var api = SchClassTestHost.Api(handler);
+
+ // 双参数齐全:按 Java 参数原名 SchSerID / schId 提交
+ await api.SchTree.GetTeaTreeAsync("S1", 2);
+ SchClassTestHost.Verify(handler, HttpMethod.Get, Root + "GetTeaTree", "?SchSerID=S1&schId=2");
+
+ // 仅 schId(服务端优先使用)
+ await api.SchTree.GetTeaTreeAsync(null, 5);
+ SchClassTestHost.Verify(handler, HttpMethod.Get, Root + "GetTeaTree", "?schId=5");
+
+ // 仅 SchSerID
+ await api.SchTree.GetTeaTreeAsync("S9", null);
+ SchClassTestHost.Verify(handler, HttpMethod.Get, Root + "GetTeaTree", "?SchSerID=S9");
+
+ // 都缺:服务端返回 [](不抛异常)
+ await api.SchTree.GetTeaTreeAsync();
+ SchClassTestHost.Verify(handler, HttpMethod.Get, Root + "GetTeaTree", "");
+ }
+
+ [Fact]
+ public async Task TeaTreeVO_嵌套树按Java原名反序列化()
+ {
+ // 教师叶子节点无 children 字段(Java @JsonInclude(NON_NULL) 省略)
+ var handler = FakeHandler.Json(HttpStatusCode.OK, """
+ [{"id":10,"name":"第一中学","pid":0,"no":1,"type":1,"isParent":true,"photo":"",
+ "children":[
+ {"id":31,"name":"教师组","pid":10,"no":1,"type":1,"isParent":true,"photo":"",
+ "children":[
+ {"id":32,"name":"语文组","pid":31,"no":1,"type":1,"isParent":true,"photo":"",
+ "children":[
+ {"id":77,"name":"王老师","pid":32,"no":0,"type":2,"isParent":false,"photo":""}]},
+ {"id":99,"name":"李老师","pid":31,"no":0,"type":2,"isParent":false,"photo":""}]}]}]
+ """);
+
+ var tree = await SchClassTestHost.Api(handler).SchTree.GetTeaTreeAsync("S001", null);
+
+ Assert.Single(tree);
+ var sch = tree[0];
+ Assert.Equal(10, sch.Id);
+ Assert.Equal("第一中学", sch.Name);
+ Assert.Equal(0, sch.Pid);
+ Assert.Equal(1, sch.Type);
+ Assert.True(sch.IsParent);
+ Assert.Equal("", sch.Photo);
+
+ var teaGroup = Assert.Single(sch.Children!);
+ Assert.Equal(31, teaGroup.Id);
+ Assert.Equal("教师组", teaGroup.Name);
+ Assert.Equal(10, teaGroup.Pid);
+
+ Assert.Equal(2, teaGroup.Children!.Count);
+ var subject = teaGroup.Children[0];
+ Assert.Equal("语文组", subject.Name);
+ var tea = Assert.Single(subject.Children!);
+ Assert.Equal(77, tea.Id);
+ Assert.Equal("王老师", tea.Name);
+ Assert.Equal(32, tea.Pid);
+ Assert.Equal(0, tea.No);
+ Assert.Equal(2, tea.Type);
+ Assert.False(tea.IsParent);
+ Assert.Null(tea.Children);
+
+ var ungrouped = teaGroup.Children[1];
+ Assert.Equal(99, ungrouped.Id);
+ Assert.Equal("李老师", ungrouped.Name);
+ Assert.Null(ungrouped.Children);
+ }
+
+ [Fact]
+ public async Task GetTeaTree_两参数都缺时服务端空数组返回空列表()
+ {
+ var handler = FakeHandler.Json(HttpStatusCode.OK, "[]");
+
+ var tree = await SchClassTestHost.Api(handler).SchTree.GetTeaTreeAsync();
+
+ Assert.NotNull(tree);
+ Assert.Empty(tree);
+ }
+
+ [Fact]
+ public async Task GetTeaTree_服务端404时归一为空列表()
+ {
+ var handler = FakeHandler.Empty(HttpStatusCode.NotFound);
+
+ var tree = await SchClassTestHost.Api(handler).SchTree.GetTeaTreeAsync("S001", null);
+
+ Assert.NotNull(tree);
+ Assert.Empty(tree);
+ }
+}
diff --git a/yh-platform-dotnet建设方案v4.md b/yh-platform-dotnet建设方案v4.md
index 9ab204c..052c0a5 100644
--- a/yh-platform-dotnet建设方案v4.md
+++ b/yh-platform-dotnet建设方案v4.md
@@ -245,7 +245,7 @@ dotnet pack -c Release -o artifacts # 预期 4 包生成
| 模型契约 | ✅ 13 POCO ⇔ 权威快照双向对拍 |
| 双序列化器 | ✅ Newtonsoft(大小写不敏感)+ STJ Web 逐节点对拍 |
| pack 产物 | ✅ 5 包(含 Yh.SchClass.OpenApi)、双 TFM lib、依赖分组正确(本地验证) |
-| Nexus 发布 | ✅ 5 包 1.0.0-preview.1 已推送(2026-09-02);CI #643 全绿自动发布链路打通 |
+| Nexus 发布 | ✅ 5 包 1.0.0-preview.1 已推送(2026-09-02);CI #643 全绿自动发布链路打通;1.0.0-preview.2 增补 Yh.SchClass.OpenApi SchTree 教师组树(2026-09-08) |
| 真实环境实调 | ❌ 待 UserBase 测试环境(待 4.2,核对表 15 项中 11 过 4 待) |
| 消费方实际接入 | ❌ 未开始(待 4.3 指南 + 4.1 发布) |