using MyHomePage.Api.Common; using MyHomePage.Api.Models.Dtos; using MyHomePage.Api.Models.Entities; using SqlSugar; namespace MyHomePage.Api.Services; /// public class CategoryService : ICategoryService { private readonly ISqlSugarClient _db; private readonly SyncLogHelper _sync; public CategoryService(ISqlSugarClient db, SyncLogHelper sync) { _db = db; _sync = sync; } /// public async Task> GetTreeAsync() { var all = await _db.Queryable() .OrderBy(c => c.Sort) .OrderBy(c => c.Id) .ToListAsync(); return CategoryDto.BuildTree(all); } /// public async Task GetByIdAsync(int id) { var entity = await _db.Queryable().InSingleAsync(id); return entity is null ? null : ToDto(entity); } /// public async Task CreateAsync(CategoryUpsertRequest request) { Validate(request); var now = DateTime.UtcNow; var entity = new Category { ParentId = request.ParentId, Name = request.Name.Trim(), Icon = request.Icon, Sort = request.Sort, CreatedAt = now, UpdatedAt = now }; entity.Id = await _db.Insertable(entity).ExecuteReturnIdentityAsync(); await _sync.WriteAsync("category", entity.Id, "create"); return ToDto(entity); } /// public async Task UpdateAsync(int id, CategoryUpsertRequest request) { Validate(request); var entity = await _db.Queryable().InSingleAsync(id) ?? throw new BusinessException("分类不存在", 404); entity.ParentId = request.ParentId; entity.Name = request.Name.Trim(); entity.Icon = request.Icon; entity.Sort = request.Sort; entity.UpdatedAt = DateTime.UtcNow; await _db.Updateable(entity).ExecuteCommandAsync(); await _sync.WriteAsync("category", id, "update"); return ToDto(entity); } /// public async Task DeleteAsync(int id) { var entity = await _db.Queryable().InSingleAsync(id) ?? throw new BusinessException("分类不存在", 404); // 如果是父分类,先检查是否有子分类 / 链接 if (entity.ParentId == 0) { var hasChildren = await _db.Queryable().AnyAsync(c => c.ParentId == id); if (hasChildren) throw new BusinessException("请先删除子分类", 400); } var hasBookmarks = await _db.Queryable().AnyAsync(b => b.CategoryId == id && !b.IsDeleted); if (hasBookmarks) throw new BusinessException("该分类下仍有链接,请先删除链接", 400); await _db.Deleteable(id).ExecuteCommandAsync(); await _sync.WriteAsync("category", id, "delete"); } /// 校验入参 private static void Validate(CategoryUpsertRequest req) { if (string.IsNullOrWhiteSpace(req.Name)) throw new BusinessException("分类名称不能为空", 400); if (req.Name.Length > 64) throw new BusinessException("分类名称不能超过 64 字符", 400); } private static CategoryDto ToDto(Category c) => new() { Id = c.Id, ParentId = c.ParentId, Name = c.Name, Icon = c.Icon, Sort = c.Sort, CreatedAt = c.CreatedAt, UpdatedAt = c.UpdatedAt }; }