|
-
- //
-
-
-
-
-
-
-
-
- namespace SafeCampus.System;
-
- /// <summary>
- /// <inheritdoc cref="IMenuService"/>
- /// </summary>
- public class MenuService : DbRepository<SysResource>, IMenuService
- {
- private readonly ILogger<MenuService> _logger;
- private readonly IResourceService _resourceService;
- private readonly IRelationService _relationService;
-
- public MenuService(ILogger<MenuService> logger, IResourceService resourceService, IRelationService relationService)
- {
- _logger = logger;
- _resourceService = resourceService;
- _relationService = relationService;
- }
-
- /// <inheritdoc/>
- public List<SysResource> ConstructMenuTrees(List<SysResource> resourceList, long? parentId = 0)
- {
- //找下级资源ID列表
- var resources = resourceList.Where(it => it.ParentId == parentId).OrderBy(it => it.SortCode).ToList();
- if (resources.Count > 0)//如果数量大于0
- {
- var data = new List<SysResource>();
- foreach (var item in resources)//遍历资源
- {
- item.Children = ConstructMenuTrees(resourceList, item.Id);//添加子节点
- data.Add(item);//添加到列表
- }
- return data;//返回结果
- }
- return new List<SysResource>();
- }
-
- /// <inheritdoc />
- public async Task<List<SysResource>> Tree(MenuTreeInput input, bool showDisabled = true)
- {
- //获取所有菜单
- var sysResources = await _resourceService.GetListByCategory(CateGoryConst.RESOURCE_MENU);
- sysResources = sysResources.WhereIF(input.Module != null, it => it.Module.Value == input.Module.Value)//根据模块查找
- .WhereIF(!showDisabled, it => it.Status == CommonStatusConst.ENABLE)//是否显示禁用的
- .WhereIF(!string.IsNullOrEmpty(input.SearchKey), it => it.Title == input.SearchKey)//根据关键字查找
- .ToList();
- //构建菜单树
- var tree = ConstructMenuTrees(sysResources);
- return tree;
- }
-
- /// <inheritdoc />
- public async Task<List<SysResource>> ShortcutTree(List<SysResource> sysResources = null)
- {
- if (sysResources == null)
- //获取所有菜单
- sysResources = (await _resourceService.GetAllModuleAndMenuAndSpaList())
- .Where(it => it.Status == CommonStatusConst.ENABLE).ToList();
- // //获取所有单页
- // var sysSpas = (await _resourceService.GetConfigsByCategory(CateGoryConst.RESOURCE_SPA))
- // .Where(it => it.Status == CommonStatusConst.ENABLE).ToList();
- sysResources.ForEach(it =>
- {
- if (it.MenuType == SysResourceConst.CATALOG)
- it.ParentId = it.Module.Value;//目录的父级ID设置为模块ID
- });
-
- //构建菜单树
- var tree = ConstructMenuTrees(sysResources, null);
- //将单页的排前面根据排序码排序
- tree = tree.OrderByDescending(it => it.Category == CateGoryConst.RESOURCE_SPA).ThenBy(it => it.SortCode).ToList();
- return tree;
- }
-
- /// <inheritdoc />
- public async Task Add(MenuAddInput input)
- {
- await CheckInput(input);//检查参数
- var sysResource = input.Adapt<SysResource>();//实体转换
-
- if (await InsertAsync(sysResource))//插入数据
- await _resourceService.RefreshCache(CateGoryConst.RESOURCE_MENU);//刷新菜单缓存
- }
-
- /// <inheritdoc />
- public async Task Edit(MenuEditInput input)
- {
- var resource = await CheckInput(input);//检查参数
- var sysResource = input.Adapt<SysResource>();//实体转换
- var updatePath = resource.Path != input.Path;//是否更新路径
- var permissions = new List<SysRelation>();
- if (updatePath)
- {
- //获取所有角色和用户的权限关系
- var rolePermissions = await _relationService.GetRelationByCategory(CateGoryConst.RELATION_SYS_ROLE_HAS_PERMISSION);
- var userPermissions = await _relationService.GetRelationByCategory(CateGoryConst.RELATION_SYS_USER_HAS_PERMISSION);
- //找到所有匹配的权限
- rolePermissions = rolePermissions.Where(it => it.TargetId.Contains(resource.Path)).ToList();
- userPermissions = userPermissions.Where(it => it.TargetId.Contains(resource.Path)).ToList();
- //更新路径
- rolePermissions.ForEach(it => it.TargetId = it.TargetId.Replace(resource.Path, input.Path));
- userPermissions.ForEach(it => it.TargetId = it.TargetId.Replace(resource.Path, input.Path));
- //添加到权限列表
- permissions.AddRange(rolePermissions);
- permissions.AddRange(userPermissions);
- }
- //事务
- var result = await Tenant.UseTranAsync(async () =>
- {
- await UpdateAsync(sysResource);//更新数据
- if (permissions.Count > 0)//如果权限列表大于0就更新
- {
- await Context.Updateable(permissions)
- .ExecuteCommandAsync();//更新关系表
- }
- });
- if (result.IsSuccess)//如果成功了
- {
- await _resourceService.RefreshCache(CateGoryConst.RESOURCE_MENU);//刷新菜单缓存
- //刷新关系表缓存
- if (updatePath)
- {
- await _relationService.RefreshCache(CateGoryConst.RELATION_SYS_ROLE_HAS_PERMISSION);
- await _relationService.RefreshCache(CateGoryConst.RELATION_SYS_USER_HAS_PERMISSION);
- }
- }
- }
-
- /// <inheritdoc />
- public async Task Delete(BaseIdListInput input)
- {
- //获取所有ID
- var ids = input.Ids;
- if (ids.Count > 0)
- {
- //获取所有菜单和按钮
- var resourceList = await _resourceService.GetListAsync(new List<string> { CateGoryConst.RESOURCE_MENU, CateGoryConst.RESOURCE_BUTTON });
- //找到要删除的菜单
- var sysResources = resourceList.Where(it => ids.Contains(it.Id)).ToList();
- //查找内置菜单
- var system = sysResources.Where(it => it.Code == SysResourceConst.SYSTEM).FirstOrDefault();
- if (system != null)
- throw Oops.Bah($"不可删除系统菜单:{system.Title}");
- //需要删除的资源ID列表
- var resourceIds = new List<long>();
- //遍历菜单列表
- sysResources.ForEach(it =>
- {
- //获取菜单所有子节点
- var child = _resourceService.GetChildListById(resourceList, it.Id, false);
- //将子节点ID添加到删除资源ID列表
- resourceIds.AddRange(child.Select(it => it.Id).ToList());
- resourceIds.Add(it.Id);//添加到删除资源ID列表
- });
- ids.AddRange(resourceIds);//添加到删除ID列表
- //事务
- var result = await Tenant.UseTranAsync(async () =>
- {
- await DeleteByIdsAsync(ids.Cast<object>().ToArray());//删除菜单和按钮
- await Context.Deleteable<SysRelation>()//关系表删除对应SYS_ROLE_HAS_RESOURCE
- .Where(it => it.Category == CateGoryConst.RELATION_SYS_ROLE_HAS_RESOURCE && resourceIds.Contains(SqlFunc.ToInt64(it.TargetId)))
- .ExecuteCommandAsync();
- });
- if (result.IsSuccess)//如果成功了
- {
- await _resourceService.RefreshCache(CateGoryConst.RESOURCE_MENU);//资源表菜单刷新缓存
- await _resourceService.RefreshCache(CateGoryConst.RESOURCE_BUTTON);//资源表按钮刷新缓存
- await _relationService.RefreshCache(CateGoryConst.RELATION_SYS_ROLE_HAS_RESOURCE);//关系表刷新缓存
- }
- else
- {
- //写日志
- _logger.LogError(result.ErrorMessage, result.ErrorException);
- throw Oops.Oh(ErrorCodeEnum.A0002);
- }
- }
- }
-
- /// <inheritdoc />
- public async Task<SysResource> Detail(BaseIdInput input)
- {
- var sysResources = await _resourceService.GetListByCategory(CateGoryConst.RESOURCE_MENU);
- var resource = sysResources.Where(it => it.Id == input.Id).FirstOrDefault();
- return resource;
- }
-
- /// <inheritdoc />
- public async Task ChangeModule(MenuChangeModuleInput input)
- {
- var sysResource = await Detail(new BaseIdInput { Id = input.Id });
- if (sysResource != null)
- {
- if (sysResource.Module == input.Module)//如果模块ID没变直接返回
- return;
- if (sysResource.ParentId != 0)
- throw Oops.Bah("非顶级菜单不可修改所属模块");
- //获取所有菜单和模块
- var resourceList = await _resourceService.GetListAsync(new List<string> { CateGoryConst.RESOURCE_MENU, CateGoryConst.RESOURCE_MODULE });
- if (!resourceList.Any(it => it.Category == CateGoryConst.RESOURCE_MODULE && it.Id == input.Module.Value))
- throw Oops.Bah("不存在的模块");
- //获取所有菜单
- var menuList = resourceList.Where(it => it.Category == CateGoryConst.RESOURCE_MENU).ToList();
- //获取需要改变模块菜单的所有子菜单
- var childList = _resourceService.GetChildListById(menuList, input.Id);
- childList.ForEach(it => it.Module = input.Module);
- //更新数据
- await UpdateRangeAsync(childList);
- //刷新菜单缓存
- await _resourceService.RefreshCache(CateGoryConst.RESOURCE_MENU);
- }
- }
-
- #region 方法
-
- /// <summary>
- /// 检查输入参数
- /// </summary>
- /// <param name="sysResource"></param>
- private async Task<SysResource> CheckInput(SysResource sysResource)
- {
- //获取所有菜单列表
- var menList = await _resourceService.GetListByCategory(CateGoryConst.RESOURCE_MENU);
- //判断是否有同级且同名的菜单
- if (menList.Any(it => it.ParentId == sysResource.ParentId && it.Title == sysResource.Title && it.Id != sysResource.Id))
- throw Oops.Bah($"存在重复的菜单名称:{sysResource.Title}");
- if (sysResource.ParentId != 0)
- {
- //获取父级,判断父级ID正不正确
- var parent = menList.Where(it => it.Id == sysResource.ParentId).FirstOrDefault();
- if (parent != null)
- {
- if (parent.Module != sysResource.Module)//如果父级的模块和当前模块不一样
- throw Oops.Bah("模块与上级菜单不一致");
- if (parent.Id == sysResource.Id)
- throw Oops.Bah("上级菜单不能选择自己");
- }
- else
- {
- throw Oops.Bah($"上级菜单不存在:{sysResource.ParentId}");
- }
- }
- //如果ID大于0表示编辑
- if (sysResource.Id > 0)
- {
- var resource = menList.Where(it => it.Id == sysResource.Id).FirstOrDefault();
- if (resource == null)
- throw Oops.Bah($"菜单不存在:{sysResource.Id}");
- return resource;
- }
- return null;
- }
-
- #endregion 方法
- }
|