// using SafeCampus.Core.Extension; namespace SafeCampus.System; /// /// /// public class SysUserService : DbRepository, ISysUserService { private readonly ILogger _logger; private readonly ISimpleCacheService _simpleCacheService; private readonly IRelationService _relationService; private readonly IResourceService _resourceService; private readonly ISysOrgService _sysOrgService; private readonly ISysRoleService _sysRoleService; private readonly IImportExportService _importExportService; private readonly ISysPositionService _sysPositionService; private readonly IDictService _dictService; private readonly IConfigService _configService; private readonly IBatchEditService _batchEditService; public SysUserService(ILogger logger, ISimpleCacheService simpleCacheService, IRelationService relationService, IResourceService resourceService, ISysOrgService orgService, ISysRoleService sysRoleService, IImportExportService importExportService, ISysPositionService sysPositionService, IDictService dictService, IConfigService configService, IBatchEditService updateBatchService) { _logger = logger; _simpleCacheService = simpleCacheService; _relationService = relationService; _resourceService = resourceService; _sysOrgService = orgService; _sysRoleService = sysRoleService; _importExportService = importExportService; _sysPositionService = sysPositionService; _dictService = dictService; _configService = configService; _batchEditService = updateBatchService; } #region 查询 /// public async Task GetUserAvatar(long userId) { //先从缓存拿 var avatar = _simpleCacheService.HashGetOne(SystemConst.CACHE_SYS_USER_AVATAR, userId.ToString()); if (string.IsNullOrEmpty(avatar)) { //单查获取用户头像 avatar = await GetFirstAsync(it => it.Id == userId, it => it.Avatar); if (!string.IsNullOrEmpty(avatar)) { //插入缓存 _simpleCacheService.HashAdd(SystemConst.CACHE_SYS_USER_AVATAR, userId.ToString(), avatar); } } return avatar; } /// public async Task GetUserByAccount(string account, long? tenantId = null) { var userId = await GetIdByAccount(account, tenantId);//获取用户ID if (userId != SafeCampusConst.ZERO) { var sysUser = await GetUserById(userId);//获取用户信息 if (sysUser.Account == account)//这里做了比较用来限制大小写 return sysUser; return null; } return null; } /// public async Task GetUserByPhone(string phone, long? tenantId = null) { var userId = await GetIdByPhone(phone, tenantId);//获取用户ID if (userId > 0) { return await GetUserById(userId);//获取用户信息 } return null; } /// public async Task GetIdByPhone(string phone, long? tenantId = null) { var orgIds = new List(); var key = SystemConst.CACHE_SYS_USER_PHONE; if (tenantId != null) { key += $":{tenantId}"; orgIds = await _sysOrgService.GetOrgChildIds(tenantId.Value);//获取下级机构 } //先从缓存拿 var userId = _simpleCacheService.HashGetOne(key, phone); if (userId == 0) { var sm4Phone = CryptogramUtil.Sm4Encrypt(phone);//SM4加密一下 //单查获取用户手机号对应的账号 userId = await Context.Queryable() .Where(it => it.Phone == sm4Phone) .WhereIF(orgIds.Count > 0, it => orgIds.Contains(it.OrgId)) .Select(it => it.Id) .FirstAsync(); if (userId > 0) { //插入缓存 _simpleCacheService.HashAdd(key, phone, userId); } } return userId; } /// public async Task GetUserById(long userId) { //先从缓存拿 var sysUser = _simpleCacheService.HashGetOne(SystemConst.CACHE_SYS_USER, userId.ToString()); if (sysUser == null) { sysUser = await GetUserFromDb(userId);//从数据库拿用户信息 } return sysUser; } /// public async Task GetUserById(long userId) { var user = await GetUserById(userId); return user.Adapt(); } /// public async Task GetIdByAccount(string account, long? tenantId = null) { var orgIds = new List(); var key = SystemConst.CACHE_SYS_USER_ACCOUNT; if (tenantId != null) { key += $":{tenantId}"; orgIds = await _sysOrgService.GetOrgChildIds(tenantId.Value);//获取下级机构 } //先从缓存拿 var userId = _simpleCacheService.HashGetOne(key, account); if (userId == 0) { //单查获取用户账号对应ID userId = await Context.Queryable() .Where(it => it.Account == account) .WhereIF(orgIds.Count > 0, it => orgIds.Contains(it.OrgId)) .Select(it => it.Id) .FirstAsync(); if (userId != 0) { //插入缓存 _simpleCacheService.HashAdd(key, account, userId); } } return userId; } /// public async Task> GetButtonCodeList(long userId) { var buttonCodeList = new List();//按钮ID集合 //获取用户资源集合 var resourceList = await _relationService.GetRelationListByObjectIdAndCategory(userId, CateGoryConst.RELATION_SYS_USER_HAS_RESOURCE); var buttonIdList = new List();//按钮ID集合 if (resourceList.Count == 0)//如果有表示用户单独授权了不走用户角色 { //获取用户角色关系集合 var roleList = await _relationService.GetRelationListByObjectIdAndCategory(userId, CateGoryConst.RELATION_SYS_USER_HAS_ROLE); var roleIdList = roleList.Select(x => x.TargetId.ToLong()).ToList();//角色ID列表 if (roleIdList.Count > 0)//如果该用户有角色 { resourceList = await _relationService.GetRelationListByObjectIdListAndCategory(roleIdList, CateGoryConst.RELATION_SYS_ROLE_HAS_RESOURCE);//获取资源集合 } } resourceList.ForEach(it => { if (!string.IsNullOrEmpty(it.ExtJson)) buttonIdList.AddRange(it.ExtJson.ToJsonEntity().ButtonInfo);//如果有按钮权限,将按钮ID放到buttonIdList }); if (buttonIdList.Count > 0) { buttonCodeList = await _resourceService.GetCodeByIds(buttonIdList, CateGoryConst.RESOURCE_BUTTON); } return buttonCodeList; } /// public async Task> GetPermissionListByUserId(long userId, long orgId) { var permissions = new List();//权限集合 var sysRelations = await _relationService.GetRelationListByObjectIdAndCategory(userId, CateGoryConst.RELATION_SYS_USER_HAS_PERMISSION);//根据用户ID获取用户权限 if (sysRelations.Count == 0)//如果有表示用户单独授权了不走用户角色 { var roleIdList = await _relationService.GetRelationListByObjectIdAndCategory(userId, CateGoryConst.RELATION_SYS_USER_HAS_ROLE);//根据用户ID获取角色ID if (roleIdList.Count > 0)//如果角色ID不为空 { //获取角色权限信息 sysRelations = await _relationService.GetRelationListByObjectIdListAndCategory(roleIdList.Select(it => it.TargetId.ToLong()).ToList(), CateGoryConst.RELATION_SYS_ROLE_HAS_PERMISSION); } } var relationGroup = sysRelations.GroupBy(it => it.TargetId).ToList();//根据目标ID,也就是接口名分组,因为存在一个用户多个角色 //遍历分组 foreach (var it in relationGroup) { var scopeSet = new HashSet();//定义不可重复列表 var relationList = it.ToList();//关系列表 var scopeCategory = CateGoryConst.SCOPE_SELF;//数据权限分类,默认为仅自己 //获取角色权限信息列表 var rolePermissions = relationList.Select(it => it.ExtJson.ToJsonEntity()).ToList(); if (rolePermissions.Any(role => role.ScopeCategory == CateGoryConst.SCOPE_ALL))//如果有全部 scopeCategory = CateGoryConst.SCOPE_ALL;//标记为全部 else if (rolePermissions.Any(role => role.ScopeCategory == CateGoryConst.SCOPE_ORG_CHILD))//如果有机构及以下机构 scopeCategory = CateGoryConst.SCOPE_ORG_CHILD;//标记为机构及以下机构 else if (rolePermissions.Any(role => role.ScopeCategory == CateGoryConst.SCOPE_ORG))//如果有仅自己机构 scopeCategory = CateGoryConst.SCOPE_ORG;//标记为仅自己机构 else if (rolePermissions.Any(role => role.ScopeCategory == CateGoryConst.SCOPE_ORG_DEFINE))//如果有自定义机构 { scopeCategory = CateGoryConst.SCOPE_ORG_DEFINE;//标记为仅自己 rolePermissions.ForEach(s => { scopeSet.AddRange(s.ScopeDefineOrgIdList);//添加自定义范围的机构ID }); } var dataScopes = scopeSet.ToList();//获取范围列表转列表 permissions.Add(new DataScope { ApiUrl = it.Key, ScopeCategory = scopeCategory, DataScopes = dataScopes });//将改URL的权限集合加入权限集合列表 } return permissions; } /// public async Task> Selector(UserSelectorInput input) { var orgIds = await _sysOrgService.GetOrgChildIds(input.OrgId);//获取下级机构 var result = await Context.Queryable() .WhereIF(input.OrgId > 0, u => orgIds.Contains(u.OrgId))//指定机构 .WhereIF(input.OrgIds != null, u => input.OrgIds.Contains(u.OrgId))//在指定机构列表查询 .WhereIF(input.PositionId > 0, u => u.PositionId == input.PositionId)//指定职位 .WhereIF(input.RoleId > 0, u => SqlFunc.Subqueryable() .Where(r => r.TargetId == input.RoleId.ToString() && r.ObjectId == u.Id && r.Category == CateGoryConst.RELATION_SYS_USER_HAS_ROLE) .Any())//指定角色 .WhereIF(!string.IsNullOrEmpty(input.Account), u => u.Account.Contains(input.Account))//根据关键字查询 .Select().ToPagedListAsync(input.PageNum, input.PageSize); return result; } /// public async Task> Page(UserPageInput input) { var query = await GetQuery(input);//获取查询条件 var pageInfo = await query.ToPagedListAsync(input.PageNum, input.PageSize);//分页 return pageInfo; } /// public async Task> List(UserPageInput input) { var query = await GetQuery(input);//获取查询条件 var list = await query.ToListAsync(); return list; } /// public async Task> OwnRole(BaseIdInput input) { var relations = await _relationService.GetRelationListByObjectIdAndCategory(input.Id, CateGoryConst.RELATION_SYS_USER_HAS_ROLE); var roleIds = relations.Select(it => it.TargetId.ToLong()).ToList(); var roleList = await Context.Queryable().Where(it => roleIds.Contains(it.Id)).Select().ToListAsync(); return roleList; } /// public async Task OwnResource(BaseIdInput input) { return await _sysRoleService.OwnResource(input, CateGoryConst.RELATION_SYS_USER_HAS_RESOURCE); } /// public async Task OwnPermission(BaseIdInput input) { var roleOwnPermission = new RoleOwnPermissionOutput { Id = input.Id };//定义结果集 var grantInfoList = new List();//已授权信息集合 //获取关系列表 var relations = await _relationService.GetRelationListByObjectIdAndCategory(input.Id, CateGoryConst.RELATION_SYS_USER_HAS_PERMISSION); //遍历关系表 relations.ForEach(it => { //将扩展信息转为实体 var relationPermission = it.ExtJson.ToJsonEntity(); grantInfoList.Add(relationPermission);//添加到已授权信息 }); roleOwnPermission.GrantInfoList = grantInfoList;//赋值已授权信息 return roleOwnPermission; } /// public async Task> UserPermissionTreeSelector(BaseIdInput input) { var permissionTreeSelectors = new List();//授权树结果集 //获取用户资源关系 var relationsRes = await _relationService.GetRelationByCategory(CateGoryConst.RELATION_SYS_USER_HAS_RESOURCE); var menuIds = relationsRes.Where(it => it.ObjectId == input.Id).Select(it => it.TargetId.ToLong()).ToList(); if (menuIds.Any()) { //获取菜单信息 var menus = await _resourceService.GetResourcesByIds(menuIds, CateGoryConst.RESOURCE_MENU); //获取权限授权树 var permissions = _resourceService.PermissionTreeSelector(menus.Select(it => it.Path).ToList()); if (permissions.Count > 0) { permissionTreeSelectors = permissions.Select(it => it.PermissionName).ToList();//返回授权树权限名称列表 } } return permissionTreeSelectors; } /// public async Task> GetUserListByIdList(IdListInput input) { var userList = await Context.Queryable().Where(it => input.IdList.Contains(it.Id)).Select().ToListAsync(); return userList; } /// public async Task Detail(BaseIdInput input) { var user = await GetUserById(input.Id); if (user != null) { user.Password = null;//清空密码 } return user; } #endregion 查询 #region 数据范围相关 /// public async Task?> GetLoginUserApiDataScope() { var userInfo = await GetUserById(UserManager.UserId);//获取用户信息 // 路由名称 var routeName = App.HttpContext.Request.Path.Value; //获取当前url的数据范围 var dataScope = userInfo.DataScopeList.Where(it => it.ApiUrl == routeName).FirstOrDefault(); if (dataScope != null) { //根据数据范围分类获取数据范围 //null:代表拥有全部数据权限 //[xx,xx]:代表拥有部分机构的权限 //[]:代表仅自己权限 switch (dataScope.ScopeCategory) { case CateGoryConst.SCOPE_ALL: return null; case CateGoryConst.SCOPE_ORG_CHILD: return userInfo.ScopeOrgChildList; case CateGoryConst.SCOPE_ORG: return new List { userInfo.OrgId }; case CateGoryConst.SCOPE_ORG_DEFINE: return dataScope.DataScopes; case CateGoryConst.SCOPE_SELF: return new List(); } } return new List(); } /// public async Task CheckApiDataScope(long? orgId, long? createUerId, string errMsg = "") { var hasPermission = true; //判断数据范围 var dataScope = await GetLoginUserApiDataScope(); if (dataScope is { Count: > 0 })//如果有机构 { if (orgId == null || !dataScope.Contains(orgId.Value))//判断机构id是否在数据范围 hasPermission = false; } else if (dataScope is { Count: 0 })// 表示仅自己 { if (createUerId != UserManager.UserId) hasPermission = false;//机构的创建人不是自己则报错 } //如果传了错误信息,直接抛出异常 if (!hasPermission && !string.IsNullOrEmpty(errMsg)) throw Oops.Bah(errMsg); return hasPermission; } public async Task CheckApiDataScope(List orgIds, List createUerIds, string errMsg = "") { var hasPermission = true; //判断数据范围 var dataScope = await GetLoginUserApiDataScope(); if (dataScope is { Count: > 0 })//如果有机构 { if (orgIds == null || !dataScope.ContainsAll(orgIds))//判断机构id列表是否全在数据范围 hasPermission = false; } else if (dataScope is { Count: 0 })// 表示仅自己 { if (createUerIds.Any(it => it != UserManager.UserId))//如果创建者id里有任何不是自己创建的机构 hasPermission = false; } //如果传了错误信息,直接抛出异常 if (!hasPermission && !string.IsNullOrEmpty(errMsg)) throw Oops.Bah(errMsg); return hasPermission; } #endregion #region 新增 /// public async Task Add(UserAddInput input) { await CheckInput(input);//检查参数 var sysUser = input.Adapt();//实体转换 //默认头像 sysUser.Avatar = AvatarUtil.GetNameImageBase64(sysUser.Name); //获取默认密码 sysUser.Password = await GetDefaultPassWord(true);//设置密码 sysUser.Status = CommonStatusConst.ENABLE;//默认状态 await InsertAsync(sysUser);//添加数据 } #endregion 新增 #region 编辑 /// public async Task Edit(UserEditInput input) { await CheckInput(input);//检查参数 var exist = await GetUserById(input.Id);//获取用户信息 if (exist != null) { var isSuperAdmin = exist.Account == SysRoleConst.SUPER_ADMIN;//判断是否有超管 if (isSuperAdmin && !UserManager.SuperAdmin) throw Oops.Bah("不可修改系统内置超管用户账号"); var name = exist.Name;//姓名 var sysUser = input.Adapt();//实体转换 if (name != input.Name) sysUser.Avatar = AvatarUtil.GetNameImageBase64(input.Name);//如果姓名改变了,重新生成头像 if (await Context.Updateable(sysUser).IgnoreColumns(it => new { //忽略更新字段 it.Password, it.LastLoginAddress, it.LastLoginDevice, it.LastLoginIp, it.LastLoginTime, it.LatestLoginAddress, it.LatestLoginDevice, it.LatestLoginIp, it.LatestLoginTime }).IgnoreColumnsIF(name == input.Name, it => it.Avatar).ExecuteCommandAsync() > 0 )//修改数据 { DeleteUserFromRedis(sysUser.Id);//删除用户缓存 //删除用户token缓存 _simpleCacheService.HashDel>(CacheConst.CACHE_USER_TOKEN, sysUser.Id.ToString()); } } } /// public async Task Edits(BatchEditInput input) { //获取参数字典 var data = await _batchEditService.GetUpdateBatchConfigDict(input.Code, input.Columns); if (data.Count > 0) { await Context.Updateable(data).Where(it => input.Ids.Contains(it.Id)).ExecuteCommandAsync(); } } /// public async Task DisableUser(BaseIdInput input) { var sysUser = await GetUserById(input.Id);//获取用户信息 if (sysUser != null) { var isSuperAdmin = sysUser.Account == SysRoleConst.SUPER_ADMIN;//判断是否有超管 if (isSuperAdmin) throw Oops.Bah("不可禁用系统内置超管用户账号"); CheckSelf(input.Id, SystemConst.DISABLE);//判断是不是自己 //设置状态为禁用 if (await UpdateSetColumnsTrueAsync(it => new SysUser { Status = CommonStatusConst.DISABLED }, it => it.Id == input.Id)) DeleteUserFromRedis(input.Id);//从缓存删除用户信息 } } /// public async Task EnableUser(BaseIdInput input) { CheckSelf(input.Id, SystemConst.ENABLE);//判断是不是自己 //设置状态为启用 if (await UpdateSetColumnsTrueAsync(it => new SysUser { Status = CommonStatusConst.ENABLE }, it => it.Id == input.Id)) DeleteUserFromRedis(input.Id);//从缓存删除用户信息 } /// public async Task ResetPassword(BaseIdInput input) { var password = await GetDefaultPassWord(true);//获取默认密码,这里不走Aop所以需要加密一下 //重置密码 if (await UpdateSetColumnsTrueAsync(it => new SysUser { Password = password }, it => it.Id == input.Id)) DeleteUserFromRedis(input.Id);//从缓存删除用户信息 } /// public async Task GrantRole(UserGrantRoleInput input) { var sysUser = await GetUserById(input.Id);//获取用户信息 if (sysUser != null) { var isSuperAdmin = sysUser.Account == SysRoleConst.SUPER_ADMIN;//判断是否有超管 if (isSuperAdmin) throw Oops.Bah("不能给超管分配角色"); CheckSelf(input.Id, SystemConst.GRANT_ROLE);//判断是不是自己 //给用户赋角色 await _relationService.SaveRelationBatch(CateGoryConst.RELATION_SYS_USER_HAS_ROLE, input.Id, input.RoleIdList.Select(it => it.ToString()).ToList(), null, true); DeleteUserFromRedis(input.Id);//从缓存删除用户信息 } } /// public async Task GrantResource(UserGrantResourceInput input) { var menuIds = input.GrantInfoList.Select(it => it.MenuId).ToList();//菜单ID var extJsons = input.GrantInfoList.Select(it => it.ToJson()).ToList();//拓展信息 var relationRoles = new List();//要添加的用户资源和授权关系表 var sysUser = await GetUserById(input.Id);//获取用户 if (sysUser != null) { #region 用户资源处理 //遍历角色列表 for (var i = 0; i < menuIds.Count; i++) { //将用户资源添加到列表 relationRoles.Add(new SysRelation { ObjectId = sysUser.Id, TargetId = menuIds[i].ToString(), Category = CateGoryConst.RELATION_SYS_USER_HAS_RESOURCE, ExtJson = extJsons == null ? null : extJsons[i] }); } #endregion 用户资源处理 #region 用户权限处理. var relationRolePer = new List();//要添加的用户有哪些权限列表 var defaultDataScope = input.DefaultDataScope;//获取默认数据范围 //获取菜单信息 var menus = await _resourceService.GetResourcesByIds(menuIds, CateGoryConst.RESOURCE_MENU); if (menus.Count > 0) { #region 用户模块关系 //获取我的模块信息Id列表 var moduleIds = menus.Select(it => it.Module.Value).Distinct().ToList(); moduleIds.ForEach(it => { //将角色资源添加到列表 relationRoles.Add(new SysRelation { ObjectId = sysUser.Id, TargetId = it.ToString(), Category = CateGoryConst.RELATION_SYS_USER_HAS_MODULE }); }); #endregion //获取权限授权树 var permissions = _resourceService.PermissionTreeSelector(menus.Select(it => it.Path).ToList()); permissions.ForEach(it => { //新建角色权限关系 relationRolePer.Add(new SysRelation { ObjectId = sysUser.Id, TargetId = it.ApiRoute, Category = CateGoryConst.RELATION_SYS_USER_HAS_PERMISSION, ExtJson = new RelationRolePermission { ApiUrl = it.ApiRoute, ScopeCategory = defaultDataScope.ScopeCategory, ScopeDefineOrgIdList = defaultDataScope.ScopeDefineOrgIdList }.ToJson() }); }); } relationRoles.AddRange(relationRolePer);//合并列表 #endregion 用户权限处理. #region 保存数据库 //事务 var result = await Tenant.UseTranAsync(async () => { var relationRep = ChangeRepository>();//切换仓储 await relationRep.DeleteAsync(it => it.ObjectId == sysUser.Id && (it.Category == CateGoryConst.RELATION_SYS_USER_HAS_PERMISSION || it.Category == CateGoryConst.RELATION_SYS_USER_HAS_RESOURCE) || it.Category == CateGoryConst.RELATION_SYS_USER_HAS_MODULE); await relationRep.InsertRangeAsync(relationRoles);//添加新的 }); if (result.IsSuccess)//如果成功了 { await _relationService.RefreshCache(CateGoryConst.RELATION_SYS_USER_HAS_PERMISSION);//刷新关系缓存 await _relationService.RefreshCache(CateGoryConst.RELATION_SYS_USER_HAS_RESOURCE);//刷新关系缓存 await _relationService.RefreshCache(CateGoryConst.RELATION_SYS_USER_HAS_MODULE);//刷新关系缓存 DeleteUserFromRedis(input.Id);//删除该用户缓存 } else { //写日志 _logger.LogError(result.ErrorMessage, result.ErrorException); throw Oops.Oh(ErrorCodeEnum.A0003); } #endregion 保存数据库 } } /// public async Task GrantPermission(GrantPermissionInput input) { var sysUser = await GetUserById(input.Id);//获取用户 if (sysUser != null) { var apiUrls = input.GrantInfoList.Select(it => it.ApiUrl).ToList();//apiurl列表 var extJsons = input.GrantInfoList.Select(it => it.ToJson()).ToList();//拓展信息 await _relationService.SaveRelationBatch(CateGoryConst.RELATION_SYS_USER_HAS_PERMISSION, input.Id, apiUrls, extJsons, true);//添加到数据库 DeleteUserFromRedis(input.Id); } } #endregion 编辑 #region 删除 /// public async Task Delete(BaseIdListInput input) { //获取所有ID var ids = input.Ids; if (ids.Count > 0) { var containsSuperAdmin = await IsAnyAsync(it => it.Account == SysRoleConst.SUPER_ADMIN && ids.Contains(it.Id));//判断是否有超管 if (containsSuperAdmin) throw Oops.Bah("不可删除系统内置超管用户"); if (ids.Contains(UserManager.UserId)) throw Oops.Bah("不可删除自己"); //定义删除的关系 var delRelations = new List { CateGoryConst.RELATION_SYS_USER_HAS_RESOURCE, CateGoryConst.RELATION_SYS_USER_HAS_PERMISSION, CateGoryConst.RELATION_SYS_USER_HAS_ROLE, CateGoryConst.RELATION_SYS_USER_HAS_MODULE, CateGoryConst.RELATION_SYS_USER_SCHEDULE_DATA, CateGoryConst.RELATION_SYS_USER_WORKBENCH_DATA }; //事务 var result = await Tenant.UseTranAsync(async () => { //清除该用户作为主管信息 await UpdateAsync(it => new SysUser { DirectorId = null }, it => ids.Contains(it.DirectorId.Value)); //删除用户 await DeleteByIdsAsync(ids.Cast().ToArray()); var relationRep = ChangeRepository>();//切换仓储 //删除关系表用户与资源关系,用户与权限关系,用户与角色关系 await relationRep.DeleteAsync(it => ids.Contains(it.ObjectId) && delRelations.Contains(it.Category)); var orgRep = ChangeRepository>();//切换仓储 //删除组织表主管信息 await orgRep.DeleteAsync(it => ids.Contains(it.DirectorId.Value)); }); if (result.IsSuccess)//如果成功了 { DeleteUserFromRedis(ids);//缓存删除用户 await _relationService.RefreshCache(CateGoryConst.RELATION_SYS_USER_HAS_ROLE);//关系表刷新SYS_USER_HAS_ROLE缓存 await _relationService.RefreshCache(CateGoryConst.RELATION_SYS_USER_HAS_RESOURCE);//关系表刷新SYS_USER_HAS_ROLE缓存 await _relationService.RefreshCache(CateGoryConst.RELATION_SYS_USER_HAS_PERMISSION);//关系表刷新SYS_USER_HAS_ROLE缓存 await _relationService.RefreshCache(CateGoryConst.RELATION_SYS_USER_HAS_MODULE);//关系表刷新RELATION_SYS_USER_HAS_MODULE缓存 await _relationService.RefreshCache(CateGoryConst.RELATION_SYS_USER_SCHEDULE_DATA);//关系表刷新RELATION_SYS_USER_SCHEDULE_DATA缓存 await _relationService.RefreshCache(CateGoryConst.RELATION_SYS_USER_WORKBENCH_DATA);//关系表刷新RELATION_SYS_USER_WORKBENCH_DATA缓存 // TODO 此处需要将这些用户踢下线,并永久注销这些用户 var idArray = ids.Select(it => it.ToString()).ToArray(); //从列表中删除 _simpleCacheService.HashDel>(CacheConst.CACHE_USER_TOKEN, idArray); } else { //写日志 _logger.LogError(result.ErrorMessage, result.ErrorException); throw Oops.Oh(ErrorCodeEnum.A0002); } } } /// public void DeleteUserFromRedis(long userId) { DeleteUserFromRedis(new List { userId }); } /// public void DeleteUserFromRedis(List ids) { var userIds = ids.Select(it => it.ToString()).ToArray();//id转string列表 var sysUsers = _simpleCacheService.HashGet(SystemConst.CACHE_SYS_USER, userIds);//获取用户列表 sysUsers = sysUsers.Where(it => it != null).ToList();//过滤掉不存在的 if (sysUsers.Count > 0) { var accounts = sysUsers.Select(it => it.Account).ToArray();//账号集合 var phones = sysUsers.Select(it => it.Phone).ToArray();//手机号集合 //删除用户信息 _simpleCacheService.HashDel(SystemConst.CACHE_SYS_USER, userIds); //删除用户头像信息 _simpleCacheService.HashDel(SystemConst.CACHE_SYS_USER_AVATAR, userIds); var userAccountKey = SystemConst.CACHE_SYS_USER_ACCOUNT; var userPhoneKey = SystemConst.CACHE_SYS_USER_PHONE; if (sysUsers.Any(it => it.TenantId != null))//如果有租户id不是空的表示是多租户模式 { var tenantIds = sysUsers.Where(it => it.TenantId != null).Select(it => it.TenantId.Value).Distinct().ToArray();//租户id列表 foreach (var tenantId in tenantIds) { userAccountKey = $"{userAccountKey}:{tenantId}"; userPhoneKey = $"{userPhoneKey}:{tenantId}"; //删除账号 _simpleCacheService.HashDel(userAccountKey, accounts); //删除手机 if (phones != null) _simpleCacheService.HashDel(userPhoneKey, phones); } } else { //删除账号 _simpleCacheService.HashDel(userAccountKey, accounts); //删除手机 if (phones != null) _simpleCacheService.HashDel(userPhoneKey, phones); } } } #endregion 删除 #region 导入导出 /// public async Task Template() { var templateName = "用户信息"; //var result = _importExportService.GenerateLocalTemplate(templateName); var result = await _importExportService.GenerateTemplate(templateName); return result; } /// public async Task> Preview(ImportPreviewInput input) { var importPreview = await _importExportService.GetImportPreview(input.File); importPreview.Data = await CheckImport(importPreview.Data);//检查导入数据 return importPreview; } /// public async Task> Import(ImportResultInput input) { var data = await CheckImport(input.Data, true);//检查数据格式 var result = _importExportService.GetImportResultPreview(data, out var importData); var sysUsers = importData.Adapt>();//转实体 await SetUserDefault(sysUsers);//设置默认值 await InsertOrBulkCopy(sysUsers);// 数据导入 return result; } /// public async Task Export(UserPageInput input) { var genTests = await List(input); var data = genTests.Adapt>();//转为Dto var result = await _importExportService.Export(data, "用户信息"); return result; } /// public async Task> CheckImport(List data, bool clearError = false) where T : SysUserImportInput { #region 校验要用到的数据 var accounts = data.Select(it => it.Account).ToList();//当前导入数据账号列表 var phones = data.Where(it => !string.IsNullOrEmpty(it.Phone)).Select(it => it.Phone).ToList();//当前导入数据手机号列表 var emails = data.Where(it => !string.IsNullOrEmpty(it.Email)).Select(it => it.Email).ToList();//当前导入数据邮箱列表 var sysUsers = await GetListAsync(it => true, it => new SysUser { Account = it.Account, Phone = it.Phone, Email = it.Email });//获取数据用户信息 var dbAccounts = sysUsers.Select(it => it.Account).ToList();//数据库账号列表 var dbPhones = sysUsers.Where(it => !string.IsNullOrEmpty(it.Phone)).Select(it => it.Phone).ToList();//数据库手机号列表 var dbEmails = sysUsers.Where(it => !string.IsNullOrEmpty(it.Email)).Select(it => it.Email).ToList();//邮箱账号列表 var sysOrgList = await _sysOrgService.GetListAsync(); var sysPositions = await _sysPositionService.GetListAsync(); var dictList = await _dictService.GetListAsync(); #endregion 校验要用到的数据 foreach (var item in data) { if (clearError)//如果需要清除错误 { item.ErrorInfo = new Dictionary(); item.HasError = false; } #region 校验账号 if (dbAccounts.Contains(item.Account)) item.ErrorInfo.Add(nameof(item.Account), $"系统已存在账号{item.Account}"); if (accounts.Where(u => u == item.Account).Count() > 1) item.ErrorInfo.Add(nameof(item.Account), "账号重复"); #endregion 校验账号 #region 校验手机号 if (!string.IsNullOrEmpty(item.Phone)) { if (dbPhones.Contains(item.Phone)) item.ErrorInfo.Add(nameof(item.Phone), $"系统已存在手机号{item.Phone}的用户"); if (phones.Where(u => u == item.Phone).Count() > 1) item.ErrorInfo.Add(nameof(item.Phone), "手机号重复"); } #endregion 校验手机号 #region 校验邮箱 if (!string.IsNullOrEmpty(item.Email)) { if (dbEmails.Contains(item.Email)) item.ErrorInfo.Add(nameof(item.Email), $"系统已存在邮箱{item.Email}"); if (emails.Where(u => u == item.Email).Count() > 1) item.ErrorInfo.Add(nameof(item.Email), "邮箱重复"); } #endregion 校验邮箱 #region 校验部门和职位 if (!string.IsNullOrEmpty(item.OrgName)) { var org = sysOrgList.Where(u => u.Names == item.OrgName).FirstOrDefault(); if (org != null) item.OrgId = org.Id;//赋值组织Id else item.ErrorInfo.Add(nameof(item.OrgName), $"部门{org}不存在"); } //校验职位 if (!string.IsNullOrEmpty(item.PositionName)) { if (string.IsNullOrEmpty(item.OrgName)) item.ErrorInfo.Add(nameof(item.PositionName), "请填写部门"); else { //根据部门ID和职位名判断是否有职位 var position = sysPositions.FirstOrDefault(u => u.OrgId == item.OrgId && u.Name == item.PositionName); if (position != null) item.PositionId = position.Id; else item.ErrorInfo.Add(nameof(item.PositionName), $"职位{item.PositionName}不存在"); } } #endregion 校验部门和职位 #region 校验性别等字典 var genders = await _dictService.GetValuesByDictValue(SysDictConst.GENDER, dictList); if (!genders.Contains(item.Gender)) item.ErrorInfo.Add(nameof(item.Gender), "性别只能是男和女"); if (!string.IsNullOrEmpty(item.Nation)) { var nations = await _dictService.GetValuesByDictValue(SysDictConst.NATION, dictList); if (!nations.Contains(item.Nation)) item.ErrorInfo.Add(nameof(item.Nation), "不存在的民族"); } if (!string.IsNullOrEmpty(item.IdCardType)) { var idCarTypes = await _dictService.GetValuesByDictValue(SysDictConst.ID_CARD_TYPE, dictList); if (!idCarTypes.Contains(item.IdCardType)) item.ErrorInfo.Add(nameof(item.IdCardType), "证件类型错误"); } if (!string.IsNullOrEmpty(item.CultureLevel)) { var cultureLevels = await _dictService.GetValuesByDictValue(SysDictConst.CULTURE_LEVEL, dictList); if (!cultureLevels.Contains(item.CultureLevel)) item.ErrorInfo.Add(nameof(item.CultureLevel), "文化程度有误"); } #endregion 校验性别等字典 if (item.ErrorInfo.Count > 0) item.HasError = true;//如果错误信息数量大于0则表示有错误 } data = data.OrderByDescending(it => it.HasError).ToList();//排序 return data; } /// public async Task SetUserDefault(List sysUsers) { var defaultPassword = await GetDefaultPassWord(true);//默认密码 //默认值赋值 sysUsers.ForEach(user => { user.Status = CommonStatusConst.ENABLE;//状态 user.Phone = CryptogramUtil.Sm4Encrypt(user.Phone);//手机号 user.Password = defaultPassword;//默认密码 user.Avatar = AvatarUtil.GetNameImageBase64(user.Name);//默认头像 }); } #endregion 导入导出 #region 方法 /// /// 获取默认密码 /// /// private async Task GetDefaultPassWord(bool isSm4 = false) { //获取默认密码 var defaultPassword = (await _configService.GetByConfigKey(CateGoryConst.CONFIG_PWD_POLICY, SysConfigConst.PWD_DEFAULT_PASSWORD)).ConfigValue; return isSm4 ? CryptogramUtil.Sm4Encrypt(defaultPassword) : defaultPassword;//判断是否需要加密 } /// /// 检查输入参数 /// /// private async Task CheckInput(SysUser sysUser) { var sysOrgList = await _sysOrgService.GetListAsync();//获取组织列表 var userOrg = sysOrgList.FirstOrDefault(it => it.Id == sysUser.OrgId); if (userOrg == null) throw Oops.Bah($"组织机构不存在"); //获取多租户配置 var isTenant = await _configService.IsTenant(); long? tenantId = null; if (isTenant) tenantId = await _sysOrgService.GetTenantIdByOrgId(sysUser.OrgId, sysOrgList); //判断账号重复,直接从缓存拿 var accountId = await GetIdByAccount(sysUser.Account, tenantId); if (accountId > 0 && accountId != sysUser.Id) throw Oops.Bah($"存在重复的账号:{sysUser.Account}"); //如果手机号不是空 if (!string.IsNullOrEmpty(sysUser.Phone)) { if (!sysUser.Phone.MatchPhoneNumber())//验证手机格式 throw Oops.Bah($"手机号码:{sysUser.Phone} 格式错误"); var phoneId = await GetIdByPhone(sysUser.Phone, tenantId); if (phoneId > 0 && sysUser.Id != phoneId)//判断重复 throw Oops.Bah($"存在重复的手机号:{sysUser.Phone}"); sysUser.Phone = CryptogramUtil.Sm4Encrypt(sysUser.Phone); } //如果邮箱不是空 if (!string.IsNullOrEmpty(sysUser.Email)) { var (isMatch, match) = sysUser.Email.MatchEmail();//验证邮箱格式 if (!isMatch) throw Oops.Bah($"邮箱:{sysUser.Email} 格式错误"); if (await IsAnyAsync(it => it.Email == sysUser.Email && it.Id != sysUser.Id)) throw Oops.Bah($"存在重复的邮箱:{sysUser.Email}"); } if (sysUser.DirectorId != null) { if (sysUser.DirectorId.Value == UserManager.UserId) throw Oops.Bah($"不能设置自己为主管"); } } /// /// 检查是否为自己 /// /// /// 操作名称 private void CheckSelf(long id, string operate) { if (id == UserManager.UserId)//如果是自己 { throw Oops.Bah($"禁止{operate}自己"); } } /// /// 根据日期计算年龄 /// /// /// public int GetAgeByBirthdate(DateTime birthdate) { var now = DateTime.Now; var age = now.Year - birthdate.Year; if (now.Month < birthdate.Month || now.Month == birthdate.Month && now.Day < birthdate.Day) { age--; } return age < 0 ? 0 : age; } /// /// 获取SqlSugar的ISugarQueryable /// /// /// private async Task> GetQuery(UserPageInput input) { var orgIds = await _sysOrgService.GetOrgChildIds(input.OrgId);//获取下级机构 var query = Context.Queryable().LeftJoin((u, o) => u.OrgId == o.Id).LeftJoin((u, o, p) => u.PositionId == p.Id) .WhereIF(input.OrgId > 0, u => orgIds.Contains(u.OrgId))//根据组织 .WhereIF(input.Expression != null, input.Expression?.ToExpression())//动态查询 .WhereIF(!string.IsNullOrEmpty(input.Status), u => u.Status == input.Status)//根据状态查询 .WhereIF(!string.IsNullOrEmpty(input.SearchKey), u => u.Name.Contains(input.SearchKey) || u.Account.Contains(input.SearchKey))//根据关键字查询 .OrderByIF(!string.IsNullOrEmpty(input.SortField), $"u.{input.SortField} {input.SortOrder}").OrderBy(u => u.Id)//排序 .OrderBy((u, o) => u.CreateTime)//排序 .Select((u, o, p) => new SysUser { Id = u.Id.SelectAll(), OrgName = o.Name, PositionName = p.Name, OrgNames = o.Names }).Mapper(u => { u.Password = null;//密码清空 u.Phone = CryptogramUtil.Sm4Decrypt(u.Phone);//手机号解密 }); return query; } /// /// 数据库获取用户信息 /// /// 用户ID /// private async Task GetUserFromDb(long userId) { var sysUser = await Context.Queryable().LeftJoin((u, o) => u.OrgId == o.Id)//连表 .LeftJoin((u, o, p) => u.PositionId == p.Id)//连表 .Where(u => u.Id == userId) .Select((u, o, p) => new SysUser { Id = u.Id.SelectAll(), OrgName = o.Name, OrgNames = o.Names, PositionName = p.Name, OrgAndPosIdList = o.ParentIdList }).FirstAsync(); if (sysUser != null) { sysUser.Password = CryptogramUtil.Sm4Decrypt(sysUser.Password);//解密密码 sysUser.Phone = CryptogramUtil.Sm4Decrypt(sysUser.Phone);//解密手机号 sysUser.OrgAndPosIdList.AddRange(sysUser.OrgId, sysUser.PositionId);//添加组织和职位Id if (sysUser.DirectorId != null) { sysUser.DirectorInfo = await GetUserById(sysUser.DirectorId.Value);//获取主管信息 } //获取按钮码 var buttonCodeList = await GetButtonCodeList(sysUser.Id); //获取数据权限 var dataScopeList = await GetPermissionListByUserId(sysUser.Id, sysUser.OrgId); //获取权限码 var permissionCodeList = dataScopeList.Select(it => it.ApiUrl).ToList(); //获取角色码 var roleCodeList = await _sysRoleService.GetRoleListByUserId(sysUser.Id); //权限码赋值 sysUser.ButtonCodeList = buttonCodeList; sysUser.RoleCodeList = roleCodeList.Select(it => it.Code).ToList(); sysUser.RoleIdList = roleCodeList.Select(it => it.Id).ToList(); sysUser.PermissionCodeList = permissionCodeList; sysUser.DataScopeList = dataScopeList; var sysOrgList = await _sysOrgService.GetListAsync(); var scopeOrgChildList = (await _sysOrgService.GetChildListById(sysUser.OrgId, true, sysOrgList)).Select(it => it.Id).ToList();//获取所属机构的下级机构Id列表 sysUser.ScopeOrgChildList = scopeOrgChildList; if (await _configService.IsTenant())//如果是多租户就获取用户的租户Id { var tenantId = await _sysOrgService.GetTenantIdByOrgId(sysUser.OrgId, sysOrgList); sysUser.TenantId = tenantId; } var moduleIds = await _relationService.GetUserModuleId(sysUser.RoleIdList, sysUser.Id);//获取模块ID列表 var modules = await _resourceService.GetResourcesByIds(moduleIds, CateGoryConst.RESOURCE_MODULE);//获取模块列表 sysUser.ModuleList = modules;//模块列表赋值给用户 //插入缓存 _simpleCacheService.HashAdd(SystemConst.CACHE_SYS_USER_AVATAR, sysUser.Id.ToString(), sysUser.Avatar); sysUser.Avatar = null;//头像清空,减少CACHE_SYS_USER的大小 _simpleCacheService.HashAdd(SystemConst.CACHE_SYS_USER, sysUser.Id.ToString(), sysUser); return sysUser; } return null; } #endregion 方法 }