SysRevelanceService.cs 10.2 KB
using Hh.Mes.Common.log;
using Hh.Mes.Pojo.System;
using Hh.Mes.POJO.Entity;
using Hh.Mes.POJO.EnumEntitys;
using Hh.Mes.POJO.Response;
using Hh.Mes.Service.Repository;
using Microsoft.Extensions.Caching.Distributed;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Hh.Mes.Service.WebService.Base
{
    /// <summary>
    /// 关联服务(用户角色、角色权限、用户权限、用户部门等等)
    /// </summary>
    public class SysRelevanceService : RepositorySqlSugar<SysRelevance>
    {
        private readonly IDistributedCache _cache;

        public SysRelevanceService(IDistributedCache cache)
        {
            _cache = cache;
        }

        /// <summary>
        /// 添加关联
        /// <para>比如给用户分配资源,那么firstId就是用户ID,secIds就是资源ID列表</para>
        /// </summary>
        /// <param name="type">关联的类型,如Define.XXX</param>
        public dynamic Assign(string type, int firstId, int[] secIds)
        {
            return Assign(type, secIds.ToLookup(u => firstId));
        }

        public dynamic Assign(string key, ILookup<int, int> idMaps)
        {
            return ExceptionsHelp.Instance.ExecuteT(() =>
            {
                var response = new Response();
                if (idMaps.Count == 0)
                {
                    return response.ResponseError("关联项ID不能为空!");
                }
                if (idMaps.Any(t => t.Count() == 0) || idMaps.Any(t => t.Any(x => x <= 0)))
                {
                    return response.ResponseError("被关联项ID都不能为空!,也不能小于0");
                }
                ClearRelevanceRedis(key, idMaps);
                //拼接新的实体列表
                List<SysRelevance> list = new List<SysRelevance>();
                foreach (var groupItem in idMaps)
                {
                    foreach (var item in groupItem)
                    {
                        var sysRelevance = new SysRelevance
                        {
                            RelKey = key,
                            FirstId = groupItem.Key,
                            SecondId = item,
                            CreateBy = sysWebUser?.Account,
                            CreateTime = DateTime.Now
                        };
                        list.Add(sysRelevance);
                    }
                }
                //先删除旧的关联
                foreach (var groupItem in idMaps)
                {
                    var secondIdList = groupItem.ToList();
                    //如果是取消 角色的模块、用户的模块,那么也要把模块下的元素给取消了,不然废弃数据越积越多。
                    if (key == Define.USERMODULE || key == Define.ROLEMODULE)
                    {
                        var elementIds = Context.Queryable<SysModuleElement>()
                                                .Where(t => secondIdList.Contains(t.ModuleId.Value))
                                                .Select(t => t.Id)
                                                .ToList();
                        //如果取消角色模块,就取消角色菜单。如果取消用户模块,就取消用户菜单。
                        var typeKey = key == Define.ROLEMODULE ? Define.ROLEELEMENT : Define.USERELEMENT;
                        //删除角色模块的菜单、用户模块的菜单
                        Context.Deleteable<SysRelevance>(t => t.RelKey == typeKey && t.FirstId == groupItem.Key && elementIds.Contains(t.SecondId.Value)).AddQueue();
                    }
                    Context.Deleteable<SysRelevance>(t => t.RelKey == key && t.FirstId == groupItem.Key && secondIdList.Contains(t.SecondId.Value)).AddQueue();
                }
                //新增关联
                Context.Insertable(list).AddQueue();

                //提交事务处理
                if (ExecuteQueues(Context) <= 0)
                {
                    return response.ResponseError(SystemVariable.dataActionError);
                }
                return response;
            });
        }

        /// <summary>
        /// 取消关联
        /// </summary>
        /// <param name="type">关联的类型,如Define.XXX</param>
        /// <param name="firstId">The first identifier.</param>
        /// <param name="secIds">The sec ids.</param>
        public dynamic UnAssign(string type, int firstId, int[] secIds)
        {
            return ExceptionsHelp.Instance.ExecuteT(() =>
            {
                var response = new Response();
                if (firstId <= 0)
                {
                    return response.ResponseError("关联项ID不能小于0");
                }
                if (secIds.Length == 0 || secIds.Any(t => t <= 0))
                {
                    return response.ResponseError("被关联项ID不能为空,也不能小于0");
                }

                var idMaps = secIds.ToLookup(u => firstId);
                ClearRelevanceRedis(type, idMaps);

                foreach (var groupItem in idMaps)
                {
                    var secondIdList = groupItem.ToList();
                    //如果是取消 角色的模块、用户的模块,那么也要把模块下的元素给取消了,不然废弃数据越积越多。
                    if (type == Define.USERMODULE || type == Define.ROLEMODULE)
                    {
                        var elementIds = Context.Queryable<SysModuleElement>()
                                                .Where(t => secondIdList.Contains(t.ModuleId.Value))
                                                .Select(t => t.Id)
                                                .ToList();
                        //如果取消角色模块,就取消角色菜单。如果取消用户模块,就取消用户菜单。
                        var typeKey = type == Define.ROLEMODULE ? Define.ROLEELEMENT : Define.USERELEMENT;
                        //删除角色模块的菜单、用户模块的菜单
                        Context.Deleteable<SysRelevance>(t => t.RelKey == typeKey && t.FirstId == groupItem.Key && elementIds.Contains(t.SecondId.Value)).AddQueue();
                    }
                    Context.Deleteable<SysRelevance>(t => t.RelKey == type && t.FirstId == groupItem.Key && secondIdList.Contains(t.SecondId.Value)).AddQueue();
                }

                if (ExecuteQueues(Context) < secIds.Length)
                {
                    if (type == Define.USERMODULE)
                    {
                        return response.ResponseError("部分模块取消失败!有部分模块是角色的模块,要去角色中取消,或是取消用户的角色!");
                    }
                    if (type == Define.USERELEMENT)
                    {
                        return response.ResponseError("部分菜单取消失败!有部分菜单是角色的菜单,要去角色中取消,或是取消用户的角色!");
                    }
                    return response.ResponseError(SystemVariable.dataActionError);
                }
                return response;
            });
        }


        /// <summary>
        /// 根据关联表的一个键获取另外键的值
        /// </summary>
        /// <param name="key">映射标识</param>
        /// <param name="returnSecondIds">返回的是否为映射表的第二列,如果不是则返回第一列</param>
        /// <param name="ids">已知的ID列表</param>
        /// <returns>List&lt;System.String&gt;.</returns>
        public dynamic Get(string key, bool returnSecondIds, params int[] ids)
        {
            return ExceptionsHelp.Instance.ExecuteT(() =>
            {
                var response = new Response<List<int>>();
                List<int> idlist = ids.ToList();
                if (returnSecondIds)
                {
                    response.Result = Context.Queryable<SysRelevance>()
                                             .Where(u => u.RelKey == key && idlist.Contains(u.FirstId.Value))
                                             .Select(u => u.SecondId.Value)
                                             .ToList();
                }
                else
                {
                    response.Result = Context.Queryable<SysRelevance>()
                                             .Where(u => u.RelKey == key && idlist.Contains(u.SecondId.Value))
                                             .Select(u => u.FirstId.Value)
                                             .ToList();
                }
                return response;
            });
        }

        /// <summary>
        /// 清除相关的用户、角色的redis授权缓存
        /// </summary>
        /// <param name="key">关联类型,Define枚举的值</param>
        /// <param name="idMaps">关系关联表,FirstId和SecondId的组合</param>
        private void ClearRelevanceRedis(string key, ILookup<int, int> idMaps)
        {
            #region 
            foreach (var groupItem in idMaps)
            {
                if (key.StartsWith("USER"))
                {
                    var account = Context.Queryable<SysUser>().Where(t => t.Id == groupItem.Key).Select(t => t.Account).First();
                    //清空对应的账户的redis授权缓存
                    _cache.Remove(account);
                }
                if (key.StartsWith("ROLE"))
                {
                    //根据角色找到对应的用户id
                    var userIdList = Context.Queryable<SysRelevance>()
                                            .Where(t => t.RelKey == Define.USERROLE && t.SecondId == groupItem.Key)
                                            .Select(t => t.FirstId).ToList();

                    //根据用户id找到用户账号
                    var accountList = Context.Queryable<SysUser>()
                                             .Where(t => userIdList.Contains(t.Id))
                                             .Select(t => t.Account).ToList();
                    //清空对应的账户的redis授权缓存
                    foreach (var item in accountList)
                    {
                        _cache.Remove(item);
                    }
                }
            }
            #endregion
        }
    }
}