sunpengfei
2025-08-07 b4943813a032976e0febdd7f22d8bcf084e331c5
FlexJobApi.User.Application/Menus/Commands/SaveMenuCommandHandler.cs
@@ -1,4 +1,5 @@
using FlexJobApi.Core;
using Consul;
using FlexJobApi.Core;
using Furion.DatabaseAccessor;
using Furion.DataValidation;
using Furion.FriendlyException;
@@ -29,35 +30,30 @@
        /// <inheritdoc/>
        public async Task<Guid> Handle(SaveMenuCommand request, CancellationToken cancellationToken)
        {
            if (request.Id.HasValue)
            {
                var entity = await rep.AsQueryable()
                    .Include(it => it.Childrens)
                    .FirstOrDefaultAsync(it => it.Id == request.Id, cancellationToken);
                if (entity == null) throw Oops.Oh(EnumErrorCodeType.s404, "菜单");
                if (entity.UserType != request.UserType) throw Oops.Oh(EnumErrorCodeType.s410, "用户类型");
                if (entity.ClientType != request.ClientType) throw Oops.Oh(EnumErrorCodeType.s410, "客户端类型");
                var path = await GetPathAsync(request.ParentId, request.Code, cancellationToken);
                if (await CheckExist(entity, request.ParentId, request.Code)) throw Oops.Oh(EnumErrorCodeType.s405, "菜单编号");
                await UpdateChildrensPath($"{entity.Path}/{entity.Code}", $"{path}/{request.Code}", cancellationToken);
                request.Adapt(entity);
                SaveChildrens(entity, request);
                await rep.UpdateAsync(entity);
                return entity.Id;
            }
            else
            {
                var entity = new Menu();
                request.Adapt(entity);
                entity.Path = await GetPathAsync(entity.ParentId, entity.Code, cancellationToken);
                if (await CheckExist(entity, request.ParentId, request.Code)) throw Oops.Oh(EnumErrorCodeType.s405, "菜单编号");
                SaveChildrens(entity, request);
                await rep.InsertAsync(entity);
                return entity.Id;
            }
            return await request.SaveData<Menu, SaveMenuCommand>(
                q => q.Include(it => it.Children),
                it =>
                    it.UserType == request.UserType
                    && it.ClientType == request.ClientType
                    && it.ParentId == request.ParentId
                    && it.Code == request.Code
                    && it.Id != request.Id,
                (entity) =>
                {
                    entity.Path = DbUtils.GetTreeDataPath<Menu>(request.ParentId, cancellationToken).Result;
                    if (request.Id.HasValue)
                    {
                        if (entity.UserType != request.UserType) throw Oops.Oh(EnumErrorCodeType.s410, "用户类型");
                        if (entity.ClientType != request.ClientType) throw Oops.Oh(EnumErrorCodeType.s410, "客户端类型");
                        DbUtils.UpdateTreeDataChildrenPath<DictionaryData>(
                           $"{entity.Path}/{entity.Code}/",
                           $"{entity.Path}/{request.Code}/",
                           cancellationToken).Wait();
                    }
                    request.Adapt(entity);
                    SaveChildrens(entity, request);
                },
                cancellationToken);
        }
        /// <summary>
@@ -71,7 +67,13 @@
            // 获取子集Id
            var childrenIds = GetRequestChildrenIds(request);
            // 删除子级
            entity.Childrens = entity.Childrens.Where(it => childrenIds.Contains(it.Id)).ToList();
            entity.Children = entity.Children
                .Where(it =>
                    it.Type == EnumMenuType.Menu
                    || it.Type == EnumMenuType.Page
                    || it.Type == EnumMenuType.Modal
                    || childrenIds.Contains(it.Id))
                .ToList();
            // 遍历分组
@@ -83,7 +85,7 @@
                    // 遍历按钮 添加或更新
                    foreach (var button in buttonLocation.Buttons)
                    {
                        var buttonEntity = entity.Childrens.FirstOrDefault(it => it.Id == button.Id);
                        var buttonEntity = entity.Children.FirstOrDefault(it => it.Id == button.Id);
                        if (buttonEntity == null)
                        {
                            if (button.Id.HasValue) throw Oops.Oh(EnumErrorCodeType.s404, $"当前分组{group.Group}-位置{buttonLocation.Location}-按钮{button.Code}");
@@ -92,8 +94,9 @@
                                UserType = entity.UserType,
                                ClientType = entity.ClientType,
                                Type = EnumMenuType.Button,
                                VisitLevel = entity.VisitLevel,
                            };
                            entity.Childrens.Add(buttonEntity);
                            entity.Children.Add(buttonEntity);
                        }
                        else if (buttonEntity.Type != EnumMenuType.Button) throw Oops.Oh(EnumErrorCodeType.s400, $"当前分组{group.Group}-字段{button.Code}并非一个按钮");
                        buttonEntity.Path = $"{entity.Path}{entity.Code}/";
@@ -106,7 +109,7 @@
                // 遍历字段 添加或更新
                foreach (var field in group.Fields)
                {
                    var fieldEntity = entity.Childrens.FirstOrDefault(it => it.Id == field.Id);
                    var fieldEntity = entity.Children.FirstOrDefault(it => it.Id == field.Id);
                    if (fieldEntity == null)
                    {
                        if (field.Id.HasValue) throw Oops.Oh(EnumErrorCodeType.s404, $"当前分组{group.Group}-字段{field.Code}");
@@ -115,8 +118,9 @@
                            UserType = entity.UserType,
                            ClientType = entity.ClientType,
                            Type = EnumMenuType.Field,
                            VisitLevel = entity.VisitLevel,
                        };
                        entity.Childrens.Add(fieldEntity);
                        entity.Children.Add(fieldEntity);
                    }
                    else if (fieldEntity.Type != EnumMenuType.Field) throw Oops.Oh(EnumErrorCodeType.s400, $"当前分组{group.Group}-位置{fieldEntity.Location}-按钮{fieldEntity.Code}并非一个字段");
                    fieldEntity.Path = $"{entity.Path}{entity.Code}/";
@@ -133,7 +137,7 @@
        /// <param name="entity"></param>
        private void CheckRepeatChildrens(Menu entity)
        {
            var repeats = entity.Childrens
            var repeats = entity.Children
                .GroupBy(it =>
                {
                    return it.Type == EnumMenuType.Button
@@ -164,75 +168,6 @@
                    g.Fields.Where(f => f.Id.HasValue).Select(f => f.Id!.Value)))
                .SelectMany(it => it)
                .ToList();
        }
        /// <summary>
        /// 校验菜单是否重复
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="parentId"></param>
        /// <param name="code"></param>
        /// <returns></returns>
        private async Task<bool> CheckExist(Menu entity, Guid? parentId, string code)
        {
            return await rep.AsQueryable().AsNoTracking()
                .AnyAsync(it =>
                    it.UserType == entity.UserType
                    && it.ClientType == entity.ClientType
                    && it.ParentId == parentId
                    && it.Code == code
                    && it.Id != entity.Id);
        }
        /// <summary>
        /// 获取地址
        /// </summary>
        /// <param name="parentId"></param>
        /// <param name="code"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        private async Task<string> GetPathAsync(Guid? parentId, string code, CancellationToken cancellationToken)
        {
            if (parentId.HasValue)
            {
                var parent = await rep.AsQueryable().AsNoTracking()
                    .Where(it => it.Id == parentId)
                    .Select(it => new
                    {
                        it.Path,
                        it.Code
                    })
                    .FirstOrDefaultAsync(cancellationToken);
                if (parent == null) throw Oops.Oh(EnumErrorCodeType.s404, "上级菜单");
                return $"{parent.Path}{parent.Code}/";
            }
            else
            {
                return "/";
            }
        }
        /// <summary>
        /// 更新下级菜单路径
        /// </summary>
        /// <param name="oldPath"></param>
        /// <param name="newPath"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        private async Task UpdateChildrensPath(string oldPath, string newPath, CancellationToken cancellationToken)
        {
            var models = await rep.AsQueryable()
                .Where(it => it.Path.StartsWith(oldPath))
                .Where(it => it.Type == EnumMenuType.Menu || it.Type == EnumMenuType.Page || it.Type == EnumMenuType.Modal)
                .ToListAsync(cancellationToken);
            if (models.IsNotNull())
            {
                foreach (var model in models)
                {
                    model.Path = model.Path.Replace(oldPath, newPath);
                }
                await rep.UpdateAsync(models);
            }
        }
    }
}