You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

147 lines
4.9 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// ============================================================================
// 【文件说明】TreeSelect.cs - 树形选择器 DTO
// ============================================================================
// 这是一个用于前端树形选择器的数据传输对象。
//
// 【业务场景】
// 前端需要展示树形选择器(如配置类型选择),数据格式要求:
// {
// "id": 1,
// "label": "产品配置",
// "children": [
// { "id": 11, "label": "硬件产品", "children": [] },
// { "id": 12, "label": "软件产品", "children": [] }
// ]
// }
//
// 这个类就是把数据库的树形实体转换成前端需要的格式。
// ============================================================================
namespace Admin.NET.Plugin.HwPortal;
/// <summary>
/// 树形选择器 DTO。
/// <para>
/// 【用途说明】
/// 用于前端树形选择器组件,如:
/// - Element UI 的 el-tree-select
/// - Ant Design 的 TreeSelect
///
/// 标准的树形选择器数据格式:
/// - id节点唯一标识
/// - label节点显示文本
/// - children子节点列表
/// </para>
/// <para>
/// 【与 Java 若依的对比】
/// 若依框架也有类似的 TreeSelect 类:
/// public class TreeSelect {
/// private Long id;
/// private String label;
/// private List&lt;TreeSelect&gt; children;
/// }
///
/// 完全相同的设计,因为这是前端组件的标准数据格式。
/// </para>
/// </summary>
public class TreeSelect
{
/// <summary>
/// 默认构造函数。
/// <para>
/// 【C# 语法知识点 - 构造函数】
/// public TreeSelect() { }
///
/// 无参构造函数用于:
/// 1. 反序列化时创建对象JSON 反序列化需要无参构造函数)
/// 2. 创建空对象后手动赋值
/// </para>
/// </summary>
public TreeSelect()
{
}
/// <summary>
/// 从配置类型实体创建树形选择器节点。
/// <para>
/// 【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);
/// </para>
/// <para>
/// 【递归构建子节点】
/// 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 + 转换构造函数让递归变得非常简洁。
/// </para>
/// </summary>
/// <param name="portalConfigType">配置类型实体</param>
public TreeSelect(HwPortalConfigType portalConfigType)
{
// Id 和 Label 是树形选择器的标准字段。
Id = portalConfigType.ConfigTypeId;
Label = portalConfigType.ConfigTypeName;
// 【递归构建子节点】
// 对每个子节点递归调用构造函数,自动构建整个子树。
Children = portalConfigType.Children.Select(u => new TreeSelect(u)).ToList();
}
/// <summary>
/// 节点唯一标识。
/// </summary>
public long? Id { get; set; }
/// <summary>
/// 节点显示文本。
/// </summary>
public string Label { get; set; }
/// <summary>
/// 子节点列表。
/// <para>
/// 【集合初始化】
/// = new() 是 C# 9.0 的"目标类型 new"语法。
/// 等价于 = new List&lt;TreeSelect&gt;()。
///
/// 为什么初始化为空列表?
/// 1. 避免 null 引用异常
/// 2. 叶子节点不需要特殊处理Children.Count = 0
/// </para>
/// </summary>
public List<TreeSelect> Children { get; set; } = new();
}