using MyHomePage.Api.Models.Entities;
namespace MyHomePage.Api.Models.Dtos;
/// 分类输出 DTO(包含二级子项)
public class CategoryDto
{
public int Id { get; set; }
public int ParentId { get; set; }
public string Name { get; set; } = string.Empty;
public string? Icon { get; set; }
public int Sort { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
public List Children { get; set; } = new();
///
/// 把扁平的 Category 实体集合构建为树形 DTO 列表。
/// 规则:parentId == 0 → 顶级;其余 → 挂到对应父分类的 Children 下。
/// 若父分类在当前集合中不存在(孤儿),降级为顶级。
/// 子项按 Sort, Id 升序排列。
///
public static List BuildTree(IEnumerable entities)
{
var list = entities
.Select(c => new CategoryDto
{
Id = c.Id,
ParentId = c.ParentId,
Name = c.Name,
Icon = c.Icon,
Sort = c.Sort,
CreatedAt = c.CreatedAt,
UpdatedAt = c.UpdatedAt
})
.ToList();
return BuildTreeFromFlat(list);
}
///
/// 把扁平的 DTO 集合构建为树形 DTO 列表(按 Id 重新组织父子关系)。
///
public static List BuildTreeFromFlat(IEnumerable flat)
{
var all = flat.ToList();
var byId = all.ToDictionary(d => d.Id);
var roots = new List();
// 重置所有 Children(防止调用方传入了预填的 Children 造成重复)
foreach (var d in all) d.Children = new List();
foreach (var d in all.OrderBy(x => x.Sort).ThenBy(x => x.Id))
{
if (d.ParentId == 0 || !byId.TryGetValue(d.ParentId, out var parent))
{
// 顶级 OR 孤儿(父分类不存在)→ 降级为顶级
roots.Add(d);
}
else
{
parent.Children.Add(d);
}
}
// 给每个父分类的 children 排序
foreach (var r in roots)
{
r.Children = r.Children.OrderBy(x => x.Sort).ThenBy(x => x.Id).ToList();
}
return roots;
}
}
/// 分类创建/更新入参
public class CategoryUpsertRequest
{
public int? Id { get; set; }
public int ParentId { get; set; }
public string Name { get; set; } = string.Empty;
public string? Icon { get; set; }
public int Sort { get; set; }
}