|
|
|
|
|
// ============================================================================
|
|
|
|
|
|
// 【文件说明】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<TreeSelect> 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<TreeSelect>()。
|
|
|
|
|
|
///
|
|
|
|
|
|
/// 为什么初始化为空列表?
|
|
|
|
|
|
/// 1. 避免 null 引用异常
|
|
|
|
|
|
/// 2. 叶子节点不需要特殊处理(Children.Count = 0)
|
|
|
|
|
|
/// </para>
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public List<TreeSelect> Children { get; set; } = new();
|
|
|
|
|
|
}
|