// ============================================================================ // 【文件说明】TreeSelect.cs - 树形选择器 DTO // ============================================================================ // 这是一个用于前端树形选择器的数据传输对象。 // // 【业务场景】 // 前端需要展示树形选择器(如配置类型选择),数据格式要求: // { // "id": 1, // "label": "产品配置", // "children": [ // { "id": 11, "label": "硬件产品", "children": [] }, // { "id": 12, "label": "软件产品", "children": [] } // ] // } // // 这个类就是把数据库的树形实体转换成前端需要的格式。 // ============================================================================ namespace Admin.NET.Plugin.HwPortal; /// /// 树形选择器 DTO。 /// /// 【用途说明】 /// 用于前端树形选择器组件,如: /// - Element UI 的 el-tree-select /// - Ant Design 的 TreeSelect /// /// 标准的树形选择器数据格式: /// - id:节点唯一标识 /// - label:节点显示文本 /// - children:子节点列表 /// /// /// 【与 Java 若依的对比】 /// 若依框架也有类似的 TreeSelect 类: /// public class TreeSelect { /// private Long id; /// private String label; /// private List<TreeSelect> children; /// } /// /// 完全相同的设计,因为这是前端组件的标准数据格式。 /// /// public class TreeSelect { /// /// 默认构造函数。 /// /// 【C# 语法知识点 - 构造函数】 /// public TreeSelect() { } /// /// 无参构造函数用于: /// 1. 反序列化时创建对象(JSON 反序列化需要无参构造函数) /// 2. 创建空对象后手动赋值 /// /// public TreeSelect() { } /// /// 从配置类型实体创建树形选择器节点。 /// /// 【C# 语法知识点 - 转换构造函数】 /// public TreeSelect(HwPortalConfigType portalConfigType) /// /// 这是一个"转换构造函数",用于从一种类型转换成另一种类型。 /// /// 对比 Java: /// Java 通常用静态工厂方法或工具类: /// public static TreeSelect from(HwPortalConfigType entity) { /// TreeSelect select = new TreeSelect(); /// select.setId(entity.getConfigTypeId()); /// select.setLabel(entity.getConfigTypeName()); /// ... /// return select; /// } /// /// C# 的转换构造函数更直观,使用更方便: /// TreeSelect select = new TreeSelect(configType); /// /// /// 【递归构建子节点】 /// Children = portalConfigType.Children.Select(u => new TreeSelect(u)).ToList() /// /// 这是一行递归代码: /// 1. portalConfigType.Children 获取子节点列表 /// 2. .Select(u => new TreeSelect(u)) 对每个子节点创建 TreeSelect /// 3. 递归:创建子节点时,子节点又会创建孙节点... /// /// 对比 Java: /// Java 需要手写递归: /// private void buildChildren(HwPortalConfigType entity, TreeSelect select) { /// if (entity.getChildren() != null && !entity.getChildren().isEmpty()) { /// select.setChildren(entity.getChildren().stream() /// .map(child -> { /// TreeSelect childSelect = new TreeSelect(child); /// buildChildren(child, childSelect); /// return childSelect; /// }) /// .collect(Collectors.toList())); /// } /// } /// /// C# 的 LINQ + 转换构造函数让递归变得非常简洁。 /// /// /// 配置类型实体 public TreeSelect(HwPortalConfigType portalConfigType) { // Id 和 Label 是树形选择器的标准字段。 Id = portalConfigType.ConfigTypeId; Label = portalConfigType.ConfigTypeName; // 【递归构建子节点】 // 对每个子节点递归调用构造函数,自动构建整个子树。 Children = portalConfigType.Children.Select(u => new TreeSelect(u)).ToList(); } /// /// 节点唯一标识。 /// public long? Id { get; set; } /// /// 节点显示文本。 /// public string Label { get; set; } /// /// 子节点列表。 /// /// 【集合初始化】 /// = new() 是 C# 9.0 的"目标类型 new"语法。 /// 等价于 = new List<TreeSelect>()。 /// /// 为什么初始化为空列表? /// 1. 避免 null 引用异常 /// 2. 叶子节点不需要特殊处理(Children.Count = 0) /// /// public List Children { get; set; } = new(); }