一个关于多层级排序的问题
比如我们在设计架构的时候,或者权限,菜单的时候一般有多层级的概念,这个时候要排序就有点困难了!这里引入另外一个字段,然后按照自己的层级进行排序!
/// <summary> /// 添加一个权限列表 ///</summary> /// <param name="input"></param> /// <returns></returns> [HttpPost] public async Task<RoleInfoDto> CreateItemAsync(RoleInfoAddDto input) { //做排重处理 var find = _dbContext.RoleInfo.Where(x => x.Model == input.Model && x.Role == input.Role).Any(); if (find) { throw new DataSupperException("已经存在这样的权限,无法重复添加"); } var info = ObjectMapper.Map<RoleInfoAddDto, RoleInfo>(input); info.IsEnable = true;//添加自定义 _dbContext.Add(info); info.SortStr = info.Sort.ToString().PadLeft(_persize, '0') + "0".PadLeft((_maxlevel - 1) * _persize, '0'); await _dbContext.SaveChangesAsync(); if (input.FatherId != 0) { var father = _dbContext.RoleInfo.Where(x => x.Id == input.FatherId).AsNoTracking().FirstOrDefault(); if (father != null && father != default) { info.FatherStr = $"{father.FatherStr}{info.Id},"; info.Level = (father.Level + 1); info.FatherId = father.Id; info.RootId = father.RootId != 0 ? father.RootId : father.Id; BuildSortStr(info, father); } else { input.FatherId = 0; } } if (input.FatherId == 0) { info.FatherStr = $"{info.Id},"; info.RootId = info.Id; } await _dbContext.SaveChangesAsync(); var backinfo = ObjectMapper.Map<RoleInfo, RoleInfoDto>(info); return backinfo; } /// <summary> /// 更新一个权限列表 ///</summary> /// <param name="input"></param> /// <returns></returns> [HttpPost] public async Task<RoleInfoDto> UpdateItemAsync(RoleInfoUpdateDto input) { var find = _dbContext.RoleInfo.Where(x => x.Id != input.Id && x.Model == input.Model && x.Role == input.Role).Select(x => x.Id).FirstOrDefault(); if (find != 0) { throw new DataSupperException($"数据重复,权限的模块和权限值的组合不能重复! {input.Model}-{input.Role}"); } var info = await _dbContext.RoleInfo.Where(x => x.Id == input.Id).FirstOrDefaultAsync(); if (info == null || info == default) { throw new DataSupperException("需要查询的信息不存在"); } var old_father_str = info.FatherStr; var _chat_level = info.Level; ObjectMapper.Map<RoleInfoUpdateDto, RoleInfo>(input, info); if (info.FatherId != 0) { var father = _dbContext.RoleInfo.Where(x => x.Id == info.FatherId).AsNoTracking().FirstOrDefault(); if (father != null && father != default) { info.Level = father.Level + 1; info.FatherStr = $"{father.FatherStr}{info.Id},"; info.RootId = father.RootId; BuildSortStr(info, father); } else { info.FatherId = 0; info.FatherStr = $"{info.Id},"; info.Level = 0; info.RootId = info.Id; BuildSortStr(info, null); } } else { info.FatherId = 0; info.FatherStr = $"{info.Id},"; info.Level = 0; info.RootId = info.Id; BuildSortStr(info, null); } _chat_level = _chat_level - (info.Level); if (old_father_str != info.FatherStr) { var suns = _dbContext.RoleInfo.Where(x => x.Id != info.Id && x.FatherStr.StartsWith(old_father_str)).ToList(); if (suns != null && suns.Count > 0) { foreach (var item in suns) { item.FatherStr = item.FatherStr.Replace(old_father_str, info.FatherStr); item.Level = item.Level + _chat_level; item.RootId = info.RootId; BuildFootSortStr(item, info); } } } var backinfo = ObjectMapper.Map<RoleInfo, RoleInfoDto>(info); await _dbContext.SaveChangesAsync(); return backinfo; } /// <summary> /// 每层最大支持的排序位数 5表示00000 /// </summary> private const int _persize = 3; /// <summary> /// 最大层级个数,从0开始 比如4就是 0 1 2 3 /// </summary> private const int _maxlevel = 4; /// <summary> /// 基于父级和当前自己的排序信息,构建对应的排序字符串 /// </summary> /// <param name="_info"></param> /// <param name="_father"></param> private void BuildSortStr(RoleInfo _info, RoleInfo _father) { if (_info.Level < _maxlevel) { if (_father == null) { _info.SortStr = _info.Sort.ToString().PadLeft(_persize, '0') + "0".PadLeft(_persize * (_maxlevel - 1), '0'); } else { if (!string.IsNullOrEmpty(_father.SortStr)) { _info.SortStr = _father.SortStr.Substring(0, (_father.Level + 1) * _persize) + _info.Sort.ToString().PadLeft(_persize, '0'); //补充尾巴 if (_info.Level < (_maxlevel - 1)) { _info.SortStr += "0".PadLeft(_persize * (_maxlevel - 1 - _info.Level), '0'); } } } } } /// <summary> /// 上级或者祖籍变更的替换,自己之后的不变,中间层级也不变 /// </summary> /// <param name="_info"></param> /// <param name="_father">是自己的上级或者祖级</param> private void BuildFootSortStr(RoleInfo _info, RoleInfo _father) { var _old_sort_str = _info.SortStr; _info.SortStr = _father.SortStr.Substring(0, (_father.Level + 1) * _persize); _info.SortStr += _old_sort_str.Substring((_father.Level + 1) * _persize); }
按照代码的意思,就是创建类似000000000000这样的,每个level各自管控自己的,然后基于这个排序!