using System.Linq.Expressions; using JNPF.Common.Configuration; using JNPF.Common.Const; using JNPF.Common.Core.Manager; using JNPF.Common.Core.Manager.Files; using JNPF.Common.Dtos.OAuth; using JNPF.Common.Enums; using JNPF.Common.Extension; using JNPF.Common.Filter; using JNPF.Common.Helper; using JNPF.Common.Manager; using JNPF.Common.Models.NPOI; using JNPF.Common.Models.User; using JNPF.Common.Options; using JNPF.Common.Security; using JNPF.DatabaseAccessor; using JNPF.DataEncryption; using JNPF.DependencyInjection; using JNPF.DynamicApiController; using JNPF.Extras.DatabaseAccessor.SqlSugar.Models; using JNPF.FriendlyException; using JNPF.RemoteRequest.Extensions; using JNPF.Systems.Entitys.Dto.Organize; using JNPF.Systems.Entitys.Dto.Role; using JNPF.Systems.Entitys.Dto.SysConfig; using JNPF.Systems.Entitys.Dto.User; using JNPF.Systems.Entitys.Dto.UserRelation; using JNPF.Systems.Entitys.Enum; using JNPF.Systems.Entitys.Model.Permission.User; using JNPF.Systems.Entitys.Permission; using JNPF.Systems.Entitys.System; using JNPF.Systems.Interfaces.Permission; using JNPF.Systems.Interfaces.System; using Mapster; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.CodeAnalysis; using Microsoft.Extensions.Options; using SqlSugar; namespace JNPF.Systems; /// /// 业务实现:用户信息. /// [ApiDescriptionSettings(Tag = "Permission", Name = "Users", Order = 163)] [Route("api/permission/[controller]")] public class UsersService : IUsersService, IDynamicApiController, ITransient { /// /// 配置文档. /// private readonly OauthOptions _oauthOptions = App.GetConfig("OAuth", true); /// /// 服务基础仓储. /// private readonly ISqlSugarRepository _repository; // 用户表仓储 /// /// 机构表服务. /// private readonly IOrganizeService _organizeService; /// /// 用户关系表服务. /// private readonly IUserRelationService _userRelationService; /// /// 系统配置服务. /// private readonly ISysConfigService _sysConfigService; /// /// 第三方同步服务. /// private readonly ISynThirdInfoService _synThirdInfoService; /// /// 文件服务. /// private readonly IFileManager _fileManager; /// /// 缓存管理. /// private readonly ICacheManager _cacheManager; /// /// 用户管理. /// private readonly IUserManager _userManager; /// /// SqlSugarClient客户端. /// private SqlSugarScope _sqlSugarClient; /// /// 多租户配置选项. /// private readonly TenantOptions _tenant; /// /// 初始化一个类型的新实例. /// public UsersService( ISqlSugarRepository userRepository, IOrganizeService organizeService, IUserRelationService userRelationService, ISysConfigService sysConfigService, ISynThirdInfoService synThirdInfoService, ICacheManager cacheManager, IFileManager fileService, ISqlSugarClient sqlSugarClient, IOptions tenantOptions, IUserManager userManager) { _repository = userRepository; _organizeService = organizeService; _userRelationService = userRelationService; _sysConfigService = sysConfigService; _userManager = userManager; _cacheManager = cacheManager; _synThirdInfoService = synThirdInfoService; _fileManager = fileService; _tenant = tenantOptions.Value; _sqlSugarClient = (SqlSugarScope)sqlSugarClient; } #region GET /// /// 获取列表. /// /// 参数. /// [HttpGet("")] public async Task GetList([FromQuery] UserListQuery input) { // 获取分级管理组织 var dataScope = _userManager.DataScope.Where(x => x.Select).Select(x => x.organizeId).Distinct().ToList(); PageInputBase? pageInput = input.Adapt(); // 处理组织树 名称 List? orgTreeNameList = _organizeService.GetOrgListTreeName(); #region 获取组织层级 List? childOrgIds = new List(); if (input.organizeId.IsNotEmptyOrNull()) { childOrgIds.Add(input.organizeId); // 根据组织Id 获取所有子组织Id集合 childOrgIds.AddRange(_repository.AsSugarClient().Queryable().ToChildList(x => x.ParentId, input.organizeId).Select(x => x.Id).ToList()); childOrgIds = childOrgIds.Distinct().ToList(); } #endregion // 获取配置文件 账号锁定类型 SysConfigEntity? config = await _repository.AsSugarClient().Queryable().Where(x => x.Key.Equals("lockType") && x.Category.Equals("SysConfig")).FirstAsync(); ErrorStrategy configLockType = (ErrorStrategy)Enum.Parse(typeof(ErrorStrategy), config?.Value); SqlSugarPagedList? data = new SqlSugarPagedList(); data = await _repository.AsSugarClient().Queryable((a, b) => new JoinQueryInfos(JoinType.Left, b.Id == a.UserId)) .Where((a, b) => b.DeleteMark == null && !b.Account.Equals("admin")) .WhereIF(childOrgIds.Any(), (a, b) => childOrgIds.Contains(a.ObjectId)) .WhereIF(!pageInput.keyword.IsNullOrEmpty(), (a, b) => b.Account.Contains(pageInput.keyword) || b.RealName.Contains(pageInput.keyword)) .WhereIF(!_userManager.IsAdministrator, (a, b) => dataScope.Contains(a.ObjectId)) .OrderBy((a, b) => b.SortCode).OrderBy((a, b) => b.CreatorTime, OrderByType.Desc).OrderBy((a, b) => b.LastModifyTime, OrderByType.Desc) .GroupBy((a, b) => new { b.Id, b.Account, b.RealName, b.CreatorTime, b.LastModifyTime, b.Gender, b.MobilePhone, b.SortCode, b.EnabledMark, b.UnLockTime }) .Select((a, b) => new UserListOutput { id = b.Id, account = b.Account, realName = b.RealName, headIcon = SqlFunc.Subqueryable().Where(e => e.Id == b.Id).Select(u => SqlFunc.MergeString("/api/File/Image/userAvatar/", u.HeadIcon)), creatorTime = b.CreatorTime, gender = b.Gender, mobilePhone = b.MobilePhone, sortCode = b.SortCode, enabledMark = SqlFunc.IIF(configLockType == ErrorStrategy.Delay && b.EnabledMark == 2 && b.UnLockTime < DateTime.Now, 1, b.EnabledMark) }).ToPagedListAsync(input.currentPage, input.pageSize); #region 处理 用户 多组织 List? orgUserIdAll = await _repository.AsSugarClient().Queryable() .Where(x => data.list.Select(u => u.id).Contains(x.UserId)).ToListAsync(); foreach (UserListOutput? item in data.list) { // 获取用户组织集合 item.organizeList = orgUserIdAll.Where(x => x.UserId == item.id).Select(x => x.ObjectId).ToList(); item.organize = string.Join(" ; ", orgTreeNameList.Where(x => item.organizeList.Contains(x.Id)).Select(x => x.Description)); } #endregion return PageResult.SqlSugarPageResult(data); } /// /// 获取全部用户. /// /// [HttpGet("All")] public async Task GetUserAllList() { return await _repository.AsSugarClient().Queryable((a, b) => new JoinQueryInfos(JoinType.Left, b.Id == SqlFunc.ToString(a.OrganizeId))) .Where(p => p.EnabledMark == 1 && p.DeleteMark == null).OrderBy(p => p.SortCode) .Select((a, b) => new UserListAllOutput { id = a.Id, account = a.Account, realName = a.RealName, headIcon = SqlFunc.MergeString("/api/File/Image/userAvatar/", a.HeadIcon), gender = a.Gender, department = b.FullName, sortCode = a.SortCode, quickQuery = a.QuickQuery, }).ToListAsync(); } /// /// 获取用户数据分页 根据角色Id. /// /// [HttpGet("getUsersByRoleId")] public async Task GetUsersByRoleId([FromQuery] RoleListInput input) { RoleEntity? roleInfo = await _repository.AsSugarClient().Queryable().Where(x => x.Id == input.roleId).FirstAsync(); // 查询全部用户 (全局角色) if (roleInfo.GlobalMark == 1) { SqlSugarPagedList? list = await _repository.AsQueryable() .WhereIF(!input.keyword.IsNullOrEmpty(), a => a.Account.Contains(input.keyword) || a.RealName.Contains(input.keyword)) .Where(p => p.EnabledMark == 1 && p.DeleteMark == null).OrderBy(p => p.SortCode) .Select(a => new UserListAllOutput { id = a.Id, account = a.Account, realName = a.RealName, gender = a.Gender, sortCode = a.SortCode, quickQuery = a.QuickQuery }).ToPagedListAsync(input.currentPage, input.pageSize); return PageResult.SqlSugarPageResult(list); } // 查询角色 所属 所有组织 用户 else { // 查询角色 所有所属组织 List? orgList = await _repository.AsSugarClient().Queryable().Where(x => x.ObjectType == "Role" && x.ObjectId == roleInfo.Id).Select(x => x.OrganizeId).ToListAsync(); List? userIdList = await _repository.AsSugarClient().Queryable().Where(x => x.ObjectType == "Organize" && orgList.Contains(x.ObjectId)).Select(x => x.UserId).Distinct().ToListAsync(); SqlSugarPagedList? list = await _repository.AsQueryable() .Where(a => userIdList.Contains(a.Id)) .Where(p => p.EnabledMark == 1 && p.DeleteMark == null).OrderBy(p => p.SortCode) .WhereIF(!input.keyword.IsNullOrEmpty(), a => a.Account.Contains(input.keyword) || a.RealName.Contains(input.keyword)) .Select(a => new UserListAllOutput { id = a.Id, account = a.Account, realName = a.RealName, gender = a.Gender, sortCode = a.SortCode, quickQuery = a.QuickQuery, }).ToPagedListAsync(input.currentPage, input.pageSize); return PageResult.SqlSugarPageResult(list); } } /// /// 获取用户数据 根据角色所属组织. /// /// [HttpGet("GetUsersByRoleOrgId")] public async Task GetUsersByRoleOrgId([FromQuery] RoleListInput input) { RoleEntity? roleInfo = await _repository.AsSugarClient().Queryable().Where(x => x.Id == input.roleId).FirstAsync(); input.organizeId = input.organizeId == null ? "0" : input.organizeId; // 获取角色所属组织集合 List? orgList = await _repository.AsSugarClient().Queryable().Where(x => x.ObjectType == "Role" && x.ObjectId == roleInfo.Id).Select(x => x.OrganizeId).ToListAsync(); List? output = new List(); if (input.organizeId.Equals("0")) { if (input.keyword.IsNotEmptyOrNull()) { // 获取角色所属组织 成员id var res = await _repository.AsSugarClient().Queryable((a, b) => new JoinQueryInfos(JoinType.Left, b.UserId == a.Id)) .Where((a, b) => b.ObjectType == "Organize" && orgList.Contains(b.ObjectId)).Where((a, b) => a.EnabledMark == 1 && a.DeleteMark == null) .Where((a, b) => a.RealName.Contains(input.keyword) || a.Account.Contains(input.keyword)) .GroupBy((a, b) => new { a.Id, a.RealName, a.Account, a.EnabledMark }) .Select((a, b) => new { id = a.Id, fullName = SqlFunc.MergeString(a.RealName, "/", a.Account), enabledMark = a.EnabledMark, type = "user", icon = "icon-ym icon-ym-tree-user2", hasChildren = false, isLeaf = true }).ToListAsync(); output.AddRange(res.Adapt>()); } else { List? allOrg = _organizeService.GetOrgListTreeName(); List? data = await _repository.AsSugarClient().Queryable() .Where(o => orgList.Contains(o.Id) && o.DeleteMark == null && o.EnabledMark == 1) .OrderBy(o => o.SortCode).ToListAsync(); foreach (OrganizeEntity? o in data) { if (o.OrganizeIdTree.IsNullOrEmpty()) o.OrganizeIdTree = o.Id; if (!data.Where(x => x.Id != o.Id && o.OrganizeIdTree.Contains(x.OrganizeIdTree)).Any()) { output.Add(new OrganizeMemberListOutput { id = o.Id, fullName = allOrg.FirstOrDefault(x => x.Id.Equals(o.Id))?.Description, enabledMark = o.EnabledMark, type = o.Category, icon = "icon-ym icon-ym-tree-organization3", hasChildren = true, isLeaf = false }); } } } } else { List? allOrg = await _repository.AsSugarClient().Queryable().Where(o => o.DeleteMark == null && o.EnabledMark == 1).OrderBy(o => o.ParentId).ToListAsync(); var res = await _repository.AsSugarClient().Queryable((a, b) => new JoinQueryInfos(JoinType.Left, b.UserId == a.Id)) .Where((a, b) => b.ObjectType == "Organize" && b.ObjectId == input.organizeId).Where((a, b) => a.EnabledMark == 1 && a.DeleteMark == null) .GroupBy((a, b) => new { a.Id, a.RealName, a.Account, a.EnabledMark }) .Select((a, b) => new { id = a.Id, fullName = SqlFunc.MergeString(a.RealName, "/", a.Account), enabledMark = a.EnabledMark, type = "user", icon = "icon-ym icon-ym-tree-user2", hasChildren = false, isLeaf = true }).ToListAsync(); output.AddRange(res.Adapt>()); var departmentList = await _repository.AsSugarClient().Queryable().Where(o => o.OrganizeIdTree.Contains(input.organizeId) && orgList.Contains(o.Id)).ToListAsync(); var orgTreeNameList = _organizeService.GetOrgListTreeName(); departmentList.OrderBy(x => x.OrganizeIdTree.Length).ToList().ForEach(o => { o.FullName = orgTreeNameList.FirstOrDefault(x => x.Id.Equals(o.Id)).Description; if (o.Id != input.organizeId && !output.Any(x => o.FullName.Contains(x.fullName))) { var pName = string.Empty; if (!departmentList.Any(x => x.Id == o.ParentId)) pName = orgTreeNameList.FirstOrDefault(x => x.Id.Equals(input.organizeId)).Description; else pName = orgTreeNameList.FirstOrDefault(x => x.Id.Equals(o.ParentId)).Description; output.Add(new OrganizeMemberListOutput() { id = o.Id, fullName = o.FullName.Replace(pName + "/", string.Empty), enabledMark = o.EnabledMark, type = o.Category, icon = o.Category.Equals("company") ? "icon-ym icon-ym-tree-organization3" : "icon-ym icon-ym-tree-department1", hasChildren = true, isLeaf = false }); } }); } return output; } /// /// 获取IM用户列表. /// /// [HttpGet("ImUser")] public async Task GetImUserList([FromQuery] PageInputBase input) { SqlSugarPagedList? list = await _repository.AsSugarClient().Queryable((a, b) => new JoinQueryInfos(JoinType.Left, b.Id == SqlFunc.ToString(a.OrganizeId))) .WhereIF(!input.keyword.IsNullOrEmpty(), a => a.Account.Contains(input.keyword) || a.RealName.Contains(input.keyword)) .Where(a => a.Id != _userManager.UserId && a.EnabledMark == 1 && a.DeleteMark == null).OrderBy(a => a.SortCode) .Select((a, b) => new IMUserListOutput { id = a.Id, account = a.Account, realName = a.RealName, headIcon = SqlFunc.MergeString("/api/File/Image/userAvatar/", a.HeadIcon), department = b.FullName, }).ToPagedListAsync(input.currentPage, input.pageSize); return PageResult.SqlSugarPageResult(list); } /// /// 获取下拉框(公司+部门+用户). /// /// [HttpGet("Selector")] public async Task GetSelector() { List? organizeList = await _organizeService.GetListAsync(); List? userList = await _repository.AsQueryable().Where(t => t.EnabledMark == 1 && t.DeleteMark == null).OrderBy(u => u.SortCode).OrderBy(a => a.CreatorTime, OrderByType.Desc).ToListAsync(); List? organizeTreeList = organizeList.Adapt>(); List? treeList = userList.Adapt>(); treeList = treeList.Concat(organizeTreeList).ToList(); return new { list = treeList.OrderBy(x => x.sortCode).ToList().ToTree("-1") }; } /// /// 获取信息. /// /// 主键. /// [HttpGet("{id}")] public async Task GetInfo(string id) { UserEntity? entity = await _repository.GetFirstAsync(u => u.Id == id); SysConfigEntity? config = await _repository.AsSugarClient().Queryable().Where(x => x.Key.Equals("lockType") && x.Category.Equals("SysConfig")).FirstAsync(); string? configLockType = config?.Value; entity.EnabledMark = configLockType.IsNotEmptyOrNull() && configLockType == "2" && entity.EnabledMark == 2 && entity.UnLockTime < DateTime.Now ? 1 : entity.EnabledMark; UserInfoOutput? output = entity.Adapt(); if (output.headIcon == "/api/File/Image/userAvatar/") output.headIcon = string.Empty; if (entity != null) { List? allRelationList = await _userRelationService.GetListByUserId(id); var relationIds = allRelationList.Where(x => x.ObjectType == "Organize" || x.ObjectType == "Position").Select(x => new { x.ObjectId, x.ObjectType }).ToList(); List? oList = await _repository.AsSugarClient().Queryable().Where(x => relationIds.Where(x => x.ObjectType == "Organize").Select(x => x.ObjectId).Contains(x.Id)).ToListAsync(); output.organizeIdTree = new List>(); oList.ForEach(item => { if (item.OrganizeIdTree.IsNotEmptyOrNull()) output.organizeIdTree.Add(item.OrganizeIdTree.Split(",").ToList()); }); output.organizeId = string.Join(",", relationIds.Where(x => x.ObjectType == "Organize").Select(x => x.ObjectId)); output.positionId = string.Join(",", relationIds.Where(x => x.ObjectType == "Position").Select(x => x.ObjectId)); } return output; } /// /// 获取当前用户所属机构下属成员. /// /// 参数. /// [HttpGet("getOrganization")] public async Task GetOrganizeMember([FromQuery] UserListQuery input) { if (input.organizeId.IsNotEmptyOrNull() && input.organizeId != "0") input.organizeId = input.organizeId.Split(",").LastOrDefault(); else input.organizeId = _userManager.User.OrganizeId; // 获取所属组织的所有成员 List? userList = await _repository.AsSugarClient().Queryable() .Where(x => x.ObjectType == "Organize").ToListAsync(); var res = await _repository.AsQueryable() .WhereIF(!input.keyword.IsNullOrEmpty(), u => u.Account.Contains(input.keyword) || u.RealName.Contains(input.keyword)) .Where(u => u.EnabledMark == 1 && u.DeleteMark == null && userList.Where(x => x.ObjectId == input.organizeId).Select(x => x.UserId).Contains(u.Id)).OrderBy(o => o.SortCode) .Select(u => new OrganizeMemberListOutput { id = u.Id, fullName = SqlFunc.MergeString(u.RealName, "/", u.Account), enabledMark = u.EnabledMark, icon = "icon-ym icon-ym-tree-user2", headIcon = SqlFunc.MergeString("/api/File/Image/userAvatar/", u.HeadIcon), isLeaf = true, hasChildren = false, type = "user", }).ToListAsync(); if (res.Any()) { var orgList = _organizeService.GetOrgListTreeName(); // 处理组织树 res.ForEach(item => { var oids = userList.Where(x => x.UserId.Equals(item.id)).Select(x => x.ObjectId).ToList(); var oTree = orgList.Where(x => oids.Contains(x.Id)).Select(x => x.Description).ToList(); item.organize = string.Join(",", oTree); }); } return res; } #endregion #region POST /// /// 根据用户Id List 获取当前用户Id. /// /// [HttpPost("getDefaultCurrentValueUserId")] public async Task GetDefaultCurrentValueUserId([FromBody] GetDefaultCurrentValueInput input) { if ((input.UserIds == null || !input.UserIds.Any()) && (input.DepartIds == null || !input.DepartIds.Any()) && (input.PositionIds == null || !input.PositionIds.Any()) && (input.RoleIds == null || !input.RoleIds.Any()) && (input.GroupIds == null || !input.GroupIds.Any())) return new { userId = _userManager.UserId }; var userRelationList = _repository.AsSugarClient().Queryable().Select(x => new UserRelationEntity() { UserId = x.UserId, ObjectId = x.ObjectId }).ToList(); var userIdList = userRelationList.Where(x => input.UserIds.Contains(x.UserId) || input.DepartIds.Contains(x.ObjectId) || input.PositionIds.Contains(x.ObjectId) || input.RoleIds.Contains(x.ObjectId) || input.GroupIds.Contains(x.ObjectId)).Select(x => x.UserId).ToList(); if (userIdList.Contains(_userManager.UserId)) return new { userId = _userManager.UserId }; else return new { userId = string.Empty }; } /// /// 获取. /// /// [HttpPost("GetUserList")] public async Task GetUserList([FromBody] UserRelationInput input) { var data = await _repository.AsQueryable().Where(it => it.EnabledMark > 0 && it.DeleteMark == null) .Where(it => input.userId.Contains(it.Id)) .Select(it => new OrganizeMemberListOutput() { id = it.Id, fullName = SqlFunc.MergeString(it.RealName, "/", it.Account), headIcon = SqlFunc.MergeString("/api/File/Image/userAvatar/", it.HeadIcon), enabledMark = it.EnabledMark, }).ToListAsync(); data = data.OrderBy(x => input.userId.IndexOf(x.id)).ToList(); if (data.Any()) { var orgList = _organizeService.GetOrgListTreeName(); // 获取 所属组织的所有成员 List? userList = await _repository.AsSugarClient().Queryable() .Where(x => x.ObjectType == "Organize" && data.Select(x => x.id).Contains(x.UserId)).ToListAsync(); // 处理组织树 data.ForEach(item => { var oids = userList.Where(x => x.UserId.Equals(item.id)).Select(x => x.ObjectId).ToList(); var oTree = orgList.Where(x => oids.Contains(x.Id)).Select(x => x.Description).ToList(); item.organize = string.Join(",", oTree); //item.type = org.fullName; }); } return new { list = data }; } /// /// 获取机构成员列表. /// /// 机构ID. /// 参数. /// [HttpPost("ImUser/Selector/{organizeId}")] public async Task GetOrganizeMemberList(string organizeId, [FromBody] PageInputBase input) { List? output = new List(); var orgList = _organizeService.GetOrgListTreeName(); if (!input.keyword.IsNullOrEmpty()) { var outList = await _repository.AsQueryable() .WhereIF(!input.keyword.IsNullOrEmpty(), u => u.Account.Contains(input.keyword) || u.RealName.Contains(input.keyword)) .Where(u => u.EnabledMark > 0 && u.DeleteMark == null).OrderBy(o => o.SortCode) .Select(u => new OrganizeMemberListOutput { id = u.Id, fullName = SqlFunc.MergeString(u.RealName, "/", u.Account), enabledMark = SqlFunc.IIF(u.EnabledMark == 2 && u.UnLockTime < DateTime.Now, 1, u.EnabledMark), icon = "icon-ym icon-ym-tree-user2", headIcon = SqlFunc.MergeString("/api/File/Image/userAvatar/", u.HeadIcon), isLeaf = true, hasChildren = false, type = "user", }).ToPagedListAsync(input.currentPage, input.pageSize); if (outList.list.Any()) { // 获取 所属组织的所有成员 List? userList = await _repository.AsSugarClient().Queryable() .Where(x => x.ObjectType == "Organize" && outList.list.Select(x => x.id).Contains(x.UserId)).ToListAsync(); // 处理组织树 outList.list.Where(x => x.type.Equals("user")).ToList().ForEach(item => { var oids = userList.Where(x => x.UserId.Equals(item.id)).Select(x => x.ObjectId).ToList(); var oTree = orgList.Where(x => oids.Contains(x.Id)).Select(x => x.Description).ToList(); item.organize = string.Join(",", oTree); }); } return PageResult.SqlSugarPageResult(outList); } else { var pOrganize = orgList.FirstOrDefault(x => x.Id.Equals(organizeId)); output = await _organizeService.GetOrganizeMemberList(organizeId); if (pOrganize != null) output.ForEach(item => item.fullName = item.fullName.Replace(pOrganize.FullName + "/", string.Empty)); } if (output.Any()) { // 获取 所属组织的所有成员 List? userList = await _repository.AsSugarClient().Queryable() .Where(x => x.ObjectType == "Organize" && output.Select(x => x.id).Contains(x.UserId)).ToListAsync(); // 处理组织树 output.Where(x => x.type.Equals("user")).ToList().ForEach(item => { var oids = userList.Where(x => x.UserId.Equals(item.id)).Select(x => x.ObjectId).ToList(); var oTree = orgList.Where(x => oids.Contains(x.Id)).Select(x => x.Description).ToList(); item.organize = string.Join(",", oTree); }); } return new { list = output }; } /// /// 获取下拉框 根据权限. /// /// [HttpPost("GetListByAuthorize/{organizeId}")] public async Task GetListByAuthorize(string organizeId, [FromBody] KeywordInput input) { List? output = new List(); if (!input.keyword.IsNullOrEmpty()) { output = await _repository.AsQueryable() .WhereIF(!input.keyword.IsNullOrEmpty(), u => u.Account.Contains(input.keyword) || u.RealName.Contains(input.keyword)) .Where(u => u.EnabledMark > 0 && u.DeleteMark == null).OrderBy(o => o.SortCode) .Select(u => new OrganizeMemberListOutput { id = u.Id, fullName = SqlFunc.MergeString(u.RealName, "/", u.Account), enabledMark = SqlFunc.IIF(u.EnabledMark == 2 && u.UnLockTime < DateTime.Now, 1, u.EnabledMark), icon = "icon-ym icon-ym-tree-user2", headIcon = SqlFunc.MergeString("/api/File/Image/userAvatar/", u.HeadIcon), isLeaf = true, hasChildren = false, type = "user", }).Take(50).ToListAsync(); } else { output = await GetOrganizeMemberList(organizeId); } if (output.Any()) { var orgList = _organizeService.GetOrgListTreeName(); // 获取所属组织的所有成员 List? userList = await _repository.AsSugarClient().Queryable() .Where(x => x.ObjectType == "Organize" && output.Select(x => x.id).Contains(x.UserId)).ToListAsync(); // 处理组织树 output.Where(x => x.type.Equals("user")).ToList().ForEach(item => { var oids = userList.Where(x => x.UserId.Equals(item.id)).Select(x => x.ObjectId).ToList(); var oTree = orgList.Where(x => oids.Contains(x.Id)).Select(x => x.Description).ToList(); item.organize = string.Join(",", oTree); }); } return new { list = output.DistinctBy(x => x.id).ToList() }; } /// /// 获取当前用户下属成员. /// /// 参数. /// [HttpPost("getSubordinates")] public async Task GetSubordinate([FromBody] KeywordInput input) { var res = await _repository.AsQueryable() .WhereIF(!input.keyword.IsNullOrEmpty(), u => u.Account.Contains(input.keyword) || u.RealName.Contains(input.keyword)) .Where(u => u.EnabledMark == 1 && u.DeleteMark == null && u.ManagerId == _userManager.UserId).OrderBy(o => o.SortCode) .Select(u => new OrganizeMemberListOutput { id = u.Id, fullName = SqlFunc.MergeString(u.RealName, "/", u.Account), enabledMark = u.EnabledMark, icon = "icon-ym icon-ym-tree-user2", headIcon = SqlFunc.MergeString("/api/File/Image/userAvatar/", u.HeadIcon), isLeaf = true, hasChildren = false, type = "user", }).ToListAsync(); // ��ȡ������֯�����г�Ա List? userList = await _repository.AsSugarClient().Queryable() .Where(x => res.Select(xx => xx.id).Contains(x.UserId)).ToListAsync(); if (res.Any()) { var orgList = _organizeService.GetOrgListTreeName(); // ������֯�� res.ForEach(item => { var oids = userList.Where(x => x.UserId.Equals(item.id)).Select(x => x.ObjectId).ToList(); var oTree = orgList.Where(x => oids.Contains(x.Id)).Select(x => x.Description).ToList(); item.organize = string.Join(",", oTree); }); } return res; } /// /// 获取当前用户所属机构下属成员. /// /// 参数. /// [HttpGet("GetUsersByPositionId")] public async Task GetUsersByPositionId([FromQuery] UserListQuery input) { List? outData = new List(); UserEntity? user = _userManager.User; // 获取岗位所属组织信息 OrganizeMemberListOutput? orgInfo = await _repository.AsSugarClient().Queryable((a, b) => new JoinQueryInfos(JoinType.Left, b.Id == SqlFunc.ToString(a.OrganizeId) && b.EnabledMark == 1 && b.DeleteMark == null)) .Where((a, b) => a.Id == input.positionId).Select((a, b) => new OrganizeMemberListOutput { id = b.Id, fullName = b.FullName, enabledMark = b.EnabledMark, type = b.Category, parentId = "0", organize = b.Id, icon = b.Category.Equals("company") ? "icon-ym icon-ym-tree-organization3" : "icon-ym icon-ym-tree-department1", hasChildren = true, isLeaf = false }).FirstAsync(); // 处理组织树 if (orgInfo.organize.IsNotEmptyOrNull()) { var orgList = _organizeService.GetOrgListTreeName(); orgInfo.fullName = orgList.FirstOrDefault(x => x.Id.Equals(orgInfo.organize))?.Description; } outData.Add(orgInfo); // 获取岗位所属组织的所有成员 List? userData = await _repository.AsSugarClient().Queryable((a, b) => new JoinQueryInfos(JoinType.Left, b.Id == SqlFunc.ToString(a.UserId))) .Where((a, b) => a.ObjectType == "Organize" && a.ObjectId == orgInfo.id && b.EnabledMark == 1 && b.DeleteMark == null) .WhereIF(!input.keyword.IsNullOrEmpty(), (a, b) => b.Account.Contains(input.keyword) || b.RealName.Contains(input.keyword)) .Select((a, b) => new OrganizeMemberListOutput { id = b.Id, parentId = orgInfo.id, fullName = SqlFunc.MergeString(b.RealName, "/", b.Account), enabledMark = b.EnabledMark, icon = "icon-ym icon-ym-tree-user2", headIcon = SqlFunc.MergeString("/api/File/Image/userAvatar/", b.HeadIcon), isLeaf = true, hasChildren = false, type = "user" }).ToListAsync(); outData.AddRange(userData); return outData.ToTree("0"); } /// /// 通过部门、岗位、用户、角色、分组id获取用户列表. /// /// 参数. /// [HttpPost("UserCondition")] public async Task UserCondition([FromBody] UserConditionInput input) { SqlSugarPagedList? data = new SqlSugarPagedList(); if (input.departIds == null) input.departIds = new List(); if (input.positionIds != null) input.departIds.AddRange(input.positionIds); if (input.roleIds != null) input.departIds.AddRange(input.roleIds); if (input.groupIds != null) input.departIds.AddRange(input.groupIds); if (!input.departIds.Any()) return PageResult.SqlSugarPageResult(data); var ids = await _repository.AsSugarClient().Queryable((a, b) => new JoinQueryInfos(JoinType.Left, b.Id == a.UserId)) .Where((a, b) => b.DeleteMark == null) .WhereIF(input.departIds.Any() || input.userIds.Any(), (a, b) => input.departIds.Contains(a.ObjectId) || input.userIds.Contains(b.Id)) .WhereIF(input.pagination.keyword.IsNotEmptyOrNull(), (a, b) => b.Account.Contains(input.pagination.keyword) || b.RealName.Contains(input.pagination.keyword)) .Select((a, b) => b.Id).Distinct().ToListAsync(); data = await _repository.AsQueryable().Where(x => ids.Contains(x.Id)).Select(x => new UserListOutput() { id = x.Id, organizeId = x.OrganizeId, account = x.Account, fullName = SqlFunc.MergeString(x.RealName, "/", x.Account), headIcon = SqlFunc.MergeString("/api/File/Image/userAvatar/", x.HeadIcon), gender = x.Gender, mobilePhone = x.MobilePhone }).ToPagedListAsync(input.pagination.currentPage, input.pagination.pageSize); if (data.list.Any()) { var orgList = _organizeService.GetOrgListTreeName(); // 获取所属组织的所有成员 List? userList = await _repository.AsSugarClient().Queryable() .Where(x => x.ObjectType == "Organize" && data.list.Select(x => x.id).Contains(x.UserId)).ToListAsync(); // 处理组织树 data.list.ToList().ForEach(item => { var oids = userList.Where(x => x.UserId.Equals(item.id)).Select(x => x.ObjectId).ToList(); var oTree = orgList.Where(x => oids.Contains(x.Id)).Select(x => x.Description).ToList(); item.organize = string.Join(",", oTree); }); } return PageResult.SqlSugarPageResult(data); } /// /// 获取选中组织、岗位、角色、分组、用户基本信息. /// /// 参数. /// [HttpPost("GetSelectedList")] public async Task GetSelectedList([FromBody] UserSelectedInput input) { if (input.userId == null) return new { list = new List() }; var objIds = new List(); input.userId.Where(x => x.IsNotEmptyOrNull()).ToList().ForEach(item => objIds.Add(item.Split("--").First())); var orgInfoList = _organizeService.GetOrgListTreeName(); var orgList = orgInfoList.Where(x => objIds.Contains(x.Id)).ToList(); var posList = await _repository.AsSugarClient().Queryable().Where(x => objIds.Contains(x.Id)).Select(x => new { x.Id, x.OrganizeId, x.FullName }).ToListAsync(); var roleList = await _repository.AsSugarClient().Queryable().Where(x => objIds.Contains(x.Id)).Select(x => new { x.Id, x.FullName, x.GlobalMark }).ToListAsync(); var groupList = await _repository.AsSugarClient().Queryable().Where(x => objIds.Contains(x.Id)).Select(x => new { x.Id, x.FullName }).ToListAsync(); var userList = await _repository.AsSugarClient().Queryable().Where(x => objIds.Contains(x.Id)).Select(x => new { x.Id, x.RealName, x.Account, x.HeadIcon }).ToListAsync(); var resList = new List(); orgList.ForEach(item => { resList.Add(new UserSelectedOutput() { id = item.Id, fullName = item.FullName, type = item.Category, icon = item.Category.Equals("company") ? "icon-ym icon-ym-tree-organization3" : "icon-ym icon-ym-tree-department1", organize = item.Description, organizeIds = new List { item.OrganizeIdTree }, }); }); posList.ForEach(item => { resList.Add(new UserSelectedOutput() { id = item.Id, fullName = item.FullName, type = "position", icon = "icon-ym icon-ym-tree-position1", organize = orgInfoList.Find(x => x.Id.Equals(item.OrganizeId)).Description, organizeIds = new List { orgInfoList.Find(x => x.Id.Equals(item.OrganizeId)).OrganizeIdTree }, }); }); var roleOrgList = await _repository.AsSugarClient().Queryable().Where(x => roleList.Select(xx => xx.Id).Contains(x.ObjectId)).Select(x => new { x.ObjectId, x.OrganizeId }).ToListAsync(); roleList.ForEach(item => { resList.Add(new UserSelectedOutput() { id = item.Id, fullName = item.FullName, type = "role", organize = SqlFunc.IIF(item.GlobalMark == 1, "", string.Join(",", orgInfoList.Where(o => roleOrgList.Where(x => x.ObjectId.Equals(item.Id)).Select(x => x.OrganizeId).Contains(o.Id)).Select(x => x.Description))), icon = "icon-ym icon-ym-generator-role", organizeIds = orgInfoList.Where(o => roleOrgList.Where(x => x.ObjectId.Equals(item.Id)).Select(x => x.OrganizeId).Contains(o.Id)).Select(x => x.OrganizeIdTree).ToList(), }); }); groupList.ForEach(item => { resList.Add(new UserSelectedOutput() { id = item.Id, fullName = item.FullName, type = "group", icon = "icon-ym icon-ym-generator-group1" }); }); var userOrgList = await _repository.AsSugarClient().Queryable().Where(x => userList.Select(xx => xx.Id).Contains(x.UserId) && x.ObjectType.Equals("Organize")).Select(x => new { x.ObjectId, x.UserId }).ToListAsync(); userList.ForEach(item => { resList.Add(new UserSelectedOutput() { id = item.Id, fullName = item.RealName + "/" + item.Account, type = "user", icon = "icon-ym icon-ym-tree-user2", headIcon = "/api/File/Image/userAvatar/" + item.HeadIcon, organize = string.Join(",", orgInfoList.Where(o => userOrgList.Where(x => x.UserId.Equals(item.Id)).Select(x => x.ObjectId).Contains(o.Id)).Select(x => x.Description)), organizeIds = orgInfoList.Where(o => userOrgList.Where(x => x.UserId.Equals(item.Id)).Select(x => x.ObjectId).Contains(o.Id)).Select(x => x.OrganizeIdTree).ToList(), }); }); return new { list = resList.OrderBy(x => objIds.IndexOf(x.id)) }; } /// /// 获取用户基本信息. /// /// 参数. /// [HttpPost("GetSelectedUserList")] public async Task GetSelectedUserList([FromBody] UserSelectedInput input) { var userId = new List(); input.userId.ForEach(item => userId.Add(item.Split("--").First())); var orgInfoList = _organizeService.GetOrgListTreeName(); var relIdList = await _repository.AsSugarClient().Queryable().Where(x => userId.Contains(x.ObjectId)).Select(x => new { x.UserId, x.ObjectId, x.ObjectType }).Distinct().ToListAsync(); var userIdList = relIdList.Where(x => !x.ObjectType.Equals("Organize")).Select(x => x.UserId).ToList(); // 子组织 var childOrgIdList = new List(); relIdList.Where(x => x.ObjectType.Equals("Organize")).Select(x => x.ObjectId).ToList().ForEach(item => childOrgIdList.AddRange(orgInfoList.Where(x => x.OrganizeIdTree.Contains(item)).Select(x => x.Id))); userIdList.AddRange(await _repository.AsSugarClient().Queryable().Where(x => childOrgIdList.Contains(x.ObjectId) && x.ObjectType.Equals("Organize")).Select(x => x.UserId).ToListAsync()); userIdList.AddRange(userId); var userOrgList = await _repository.AsSugarClient().Queryable().Where(x => userIdList.Contains(x.UserId) && x.ObjectType.Equals("Organize")).Select(x => new { x.ObjectId, x.UserId }).ToListAsync(); var userInfoList = await _repository.AsSugarClient().Queryable().Where(x => userIdList.Contains(x.Id) && x.DeleteMark == null && x.EnabledMark > 0) .WhereIF(input.pagination.keyword.IsNotEmptyOrNull(), x => x.RealName.Contains(input.pagination.keyword) || x.Account.Contains(input.pagination.keyword)) .Select(x => new UserSelectedOutput { fullName = SqlFunc.MergeString(x.RealName, "/", x.Account), icon = "icon-ym icon-ym-tree-user2", headIcon = SqlFunc.MergeString("/api/File/Image/userAvatar/", x.HeadIcon), id = x.Id, type = "user", gender = x.Gender, mobilePhone = x.MobilePhone }).ToPagedListAsync(input.pagination.currentPage, input.pagination.pageSize); userInfoList.list.ToList().ForEach(item => { item.organize = string.Join(",", orgInfoList.Where(o => userOrgList.Where(x => x.UserId.Equals(item.id)).Select(x => x.ObjectId).Contains(o.Id)).Select(x => x.Description)); item.organizeIds = orgInfoList.Where(o => userOrgList.Where(x => x.UserId.Equals(item.id)).Select(x => x.ObjectId).Contains(o.Id)).Select(x => x.OrganizeIdTree).ToList(); }); return PageResult.SqlSugarPageResult(userInfoList); } /// /// 新建. /// /// 参数. /// [HttpPost("")] public async Task Create([FromBody] UserCrInput input) { var orgids = input.organizeId.Split(','); if (!_userManager.DataScope.Any(it => orgids.Contains(it.organizeId) && it.Add) && !_userManager.IsAdministrator) throw Oops.Oh(ErrorCode.D1013); if (await _repository.IsAnyAsync(u => u.Account == input.account && u.DeleteMark == null)) throw Oops.Oh(ErrorCode.D1003); UserEntity? entity = input.Adapt(); #region 用户表单 entity.IsAdministrator = 0; entity.EntryDate = input.entryDate.IsNullOrEmpty() ? DateTime.Now : input.entryDate; entity.Birthday = input.birthday.IsNullOrEmpty() ? DateTime.Now : input.birthday; entity.QuickQuery = PinyinHelper.PinyinString(input.realName); entity.Secretkey = Guid.NewGuid().ToString(); entity.Password = MD5Encryption.Encrypt(MD5Encryption.Encrypt(CommonConst.DEFAULTPASSWORD) + entity.Secretkey); string? headIcon = input.headIcon.Split('/').ToList().Last(); if (string.IsNullOrEmpty(headIcon)) headIcon = "001.png"; entity.HeadIcon = headIcon; #region 多组织 优先选择有权限组织 // 多组织 string[]? orgList = entity.OrganizeId.Split(","); entity.OrganizeId = string.Empty; foreach (string? item in orgList) { List? roleList = await _userManager.GetUserOrgRoleIds(entity.RoleId, item); // 如果该组织下有角色并且有角色权限 则为默认组织 if (roleList.Any() && _repository.AsSugarClient().Queryable().Where(x => x.ObjectType == "Role" && x.ItemType == "module" && roleList.Contains(x.ObjectId)).Any()) { // 多 组织 默认 entity.OrganizeId = item; break; } } // 如果所选组织下都没有角色或者没有角色权限 默认取第一个 if (entity.OrganizeId.IsNullOrEmpty()) entity.OrganizeId = input.organizeId.Split(",").FirstOrDefault(); #endregion string[]? positionIds = entity.PositionId?.Split(","); List? pIdList = await _repository.AsSugarClient().Queryable().Where(x => x.OrganizeId == entity.OrganizeId && positionIds.Contains(x.Id)).Select(x => x.Id).ToListAsync(); entity.PositionId = pIdList.FirstOrDefault(); // 多 岗位 默认取当前组织第一个 // 获取有菜单的系统 默认系统 var userRoleIds = input.roleId.Split(","); var sysList = await _repository.AsSugarClient().Queryable().Where(x => x.ObjectType == "Role" && userRoleIds.Contains(x.ObjectId)) .Where(x => x.ItemType == "module" || x.ItemType == "system").ToListAsync(); var menuList = await _repository.AsSugarClient().Queryable() .Where(x => sysList.Where(xx => xx.ItemType.Equals("system")).Select(xx => xx.ItemId).Contains(x.SystemId)).ToListAsync(); entity.SystemId = menuList.Where(x => sysList.Where(xx => xx.ItemType.Equals("module")).Select(xx => xx.ItemId).Contains(x.Id)).FirstOrDefault()?.SystemId; #endregion try { // 新增用户记录 await _repository.AsInsertable(entity).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync(); // 将临时文件迁移至正式文件 FileHelper.MoveFile(Path.Combine(FileVariable.TemporaryFilePath, headIcon), Path.Combine(FileVariable.UserAvatarFilePath, headIcon)); List? userRelationList = new List(); userRelationList.AddRange(_userRelationService.CreateUserRelation(entity.Id, input.roleId, "Role")); userRelationList.AddRange(_userRelationService.CreateUserRelation(entity.Id, input.positionId, "Position")); userRelationList.AddRange(_userRelationService.CreateUserRelation(entity.Id, input.organizeId, "Organize")); userRelationList.AddRange(_userRelationService.CreateUserRelation(entity.Id, input.groupId, "Group")); if (userRelationList.Count > 0) await _userRelationService.Create(userRelationList); // 批量新增用户关系 #region 第三方同步 try { SysConfigOutput? sysConfig = await _sysConfigService.GetInfo(); List? userList = new List(); userList.Add(entity); if (sysConfig.dingSynIsSynUser) await _synThirdInfoService.SynUser(2, 3, sysConfig, userList); if (sysConfig.qyhIsSynUser) await _synThirdInfoService.SynUser(1, 3, sysConfig, userList); } catch (Exception) { } #endregion // 单点登录同步 await syncUserInfo(entity, "create", _userManager.TenantId); } catch (Exception) { throw Oops.Bah(ErrorCode.D5001); } } /// /// 删除. /// /// 主键. /// [HttpDelete("{id}")] public async Task Delete(string id) { UserEntity? entity = await _repository.GetFirstAsync(u => u.Id == id && u.DeleteMark == null); // 所属组织 分级权限验证 List? orgIdList = await _repository.AsSugarClient().Queryable().Where(x => x.UserId == id && x.ObjectType == "Organize").Select(x => x.ObjectId).ToListAsync(); if (!_userManager.DataScope.Any(it => orgIdList.Contains(it.organizeId) && it.Delete) && !_userManager.IsAdministrator) throw Oops.Oh(ErrorCode.D1013); if (await _organizeService.GetIsManagerByUserId(id)) throw Oops.Oh(ErrorCode.D2003); _ = entity ?? throw Oops.Oh(ErrorCode.D5002); if (entity.IsAdministrator == (int)AccountType.Administrator) throw Oops.Oh(ErrorCode.D1014); if (entity.Id == _userManager.UserId) throw Oops.Oh(ErrorCode.D1001); entity.DeleteTime = DateTime.Now; entity.DeleteMark = 1; entity.DeleteUserId = _userManager.UserId; // 用户软删除 await _repository.AsUpdateable(entity).UpdateColumns(it => new { it.DeleteTime, it.DeleteMark, it.DeleteUserId }).ExecuteCommandAsync(); // 直接删除用户关系表相关相关数据 await _userRelationService.Delete(id); #region 第三方同步 try { SysConfigOutput? sysConfig = await _sysConfigService.GetInfo(); if (sysConfig.dingSynIsSynUser) await _synThirdInfoService.DelSynData(2, 3, sysConfig, id); if (sysConfig.qyhIsSynUser) await _synThirdInfoService.DelSynData(1, 3, sysConfig, id); } catch (Exception) { } #endregion // 单点登录同步 await syncUserInfo(entity, "delete", _userManager.TenantId); } /// /// 更新. /// /// 主键. /// 参数. /// [HttpPut("{id}")] public async Task Update(string id, [FromBody] UserUpInput input) { UserEntity? oldUserEntity = await _repository.GetFirstAsync(it => it.Id == id); input.roleId = input.roleId == null ? string.Empty : input.roleId; // 超级管理员 只有 admin 账号才有变更权限 if (_userManager.UserId != oldUserEntity.Id && oldUserEntity.IsAdministrator == 1 && _userManager.Account != "admin") throw Oops.Oh(ErrorCode.D1033); // 超级管理员不能禁用 if (oldUserEntity.IsAdministrator.Equals(1) && input.enabledMark.Equals(0)) throw Oops.Oh(ErrorCode.D1015); // 旧数据 List? orgIdList = await _repository.AsSugarClient().Queryable().Where(x => x.UserId == id && x.ObjectType == "Organize").Select(x => x.ObjectId).ToListAsync(); if (!_userManager.DataScope.Any(it => orgIdList.Contains(it.organizeId) && it.Edit) && !_userManager.IsAdministrator) throw Oops.Oh(ErrorCode.D1013); // 新数据 var orgids = input.organizeId.Split(','); if (!_userManager.DataScope.Any(it => orgids.Contains(it.organizeId) && it.Edit) && !_userManager.IsAdministrator) throw Oops.Oh(ErrorCode.D1013); // 排除自己并且判断与其他是否相同 if (await _repository.IsAnyAsync(u => u.Account == input.account && u.DeleteMark == null && u.Id != id)) throw Oops.Oh(ErrorCode.D1003); if (id == input.managerId) throw Oops.Oh(ErrorCode.D1021); // 直属主管的上级不能为自己的下属 if (await GetIsMyStaff(id, input.managerId, 10)) throw Oops.Oh(ErrorCode.D1026); UserEntity? entity = input.Adapt(); entity.QuickQuery = PinyinHelper.PinyinString(input.realName); string? headIcon = input.headIcon.Split('/').ToList().Last(); entity.HeadIcon = headIcon; entity.LastModifyTime = DateTime.Now; entity.LastModifyUserId = _userManager.UserId; if (entity.EnabledMark == 2) entity.UnLockTime = null; #region 多组织 优先选择有权限组织 // 多 组织 string[]? orgList = entity.OrganizeId.Split(","); entity.OrganizeId = string.Empty; if (orgList.Contains(oldUserEntity.OrganizeId)) { List? roleList = await _userManager.GetUserOrgRoleIds(entity.RoleId, oldUserEntity.OrganizeId); // 如果该组织下有角色并且有角色权限 则为默认组织 if (roleList.Any() && _repository.AsSugarClient().Queryable().Where(x => x.ObjectType == "Role" && x.ItemType == "module" && roleList.Contains(x.ObjectId)).Any()) entity.OrganizeId = oldUserEntity.OrganizeId; // 多 组织 默认 } if (entity.OrganizeId.IsNullOrEmpty()) { foreach (string? item in orgList) { List? roleList = await _userManager.GetUserOrgRoleIds(entity.RoleId, item); // 如果该组织下有角色并且有角色权限 则为默认组织 if (roleList.Any() && _repository.AsSugarClient().Queryable().Where(x => x.ObjectType == "Role" && x.ItemType == "module" && roleList.Contains(x.ObjectId)).Any()) { // 多 组织 默认 entity.OrganizeId = item; break; } } } // 如果所选组织下都没有角色或者没有角色权限 默认取第一个 if (entity.OrganizeId.IsNullOrEmpty()) entity.OrganizeId = input.organizeId.Split(",").FirstOrDefault(); #endregion // 获取有菜单的系统 默认系统 var userRoleIds = input.roleId.Split(","); var sysList = await _repository.AsSugarClient().Queryable().Where(x => x.ObjectType == "Role" && userRoleIds.Contains(x.ObjectId)) .Where(x => x.ItemType == "module" || x.ItemType == "system").ToListAsync(); var menuList = await _repository.AsSugarClient().Queryable() .Where(x => sysList.Where(xx => xx.ItemType.Equals("system")).Select(xx => xx.ItemId).Contains(x.SystemId)).ToListAsync(); if (menuList.Any() && !menuList.Any(x => x.SystemId.Equals(oldUserEntity.SystemId))) entity.SystemId = menuList.Where(x => sysList.Where(xx => xx.ItemType.Equals("module")).Select(xx => xx.ItemId).Contains(x.Id)).FirstOrDefault()?.SystemId; else entity.SystemId = oldUserEntity.SystemId; // 获取默认组织下的岗位 string[]? positionIds = entity.PositionId?.Split(","); List? pIdList = await _repository.AsSugarClient().Queryable().Where(x => x.OrganizeId == entity.OrganizeId && positionIds.Contains(x.Id)).Select(x => x.Id).ToListAsync(); if (entity.PositionId.IsNotEmptyOrNull() && pIdList.Contains(oldUserEntity.PositionId)) entity.PositionId = oldUserEntity.PositionId; else entity.PositionId = pIdList.FirstOrDefault(); // 多 岗位 默认取第一个 try { // 更新用户记录 int newEntity = await _repository.AsUpdateable(entity).UpdateColumns(it => new { it.Account, it.RealName, it.QuickQuery, it.Gender, it.Email, it.OrganizeId, it.ManagerId, it.PositionId, it.RoleId, it.SortCode, it.EnabledMark, it.Description, it.HeadIcon, it.Nation, it.NativePlace, it.EntryDate, it.CertificatesType, it.CertificatesNumber, it.Education, it.UrgentContacts, it.UrgentTelePhone, it.PostalAddress, it.MobilePhone, it.Birthday, it.TelePhone, it.Landline, it.UnLockTime, it.GroupId, it.LastModifyTime, it.SystemId, it.LastModifyUserId }).ExecuteCommandAsync(); // 将临时文件迁移至正式文件 FileHelper.MoveFile(Path.Combine(FileVariable.TemporaryFilePath, headIcon), Path.Combine(FileVariable.UserAvatarFilePath, headIcon)); // 直接删除用户关系表相关相关数据 await _userRelationService.Delete(id); List? userRelationList = new List(); userRelationList.AddRange(_userRelationService.CreateUserRelation(id, entity.RoleId, "Role")); userRelationList.AddRange(_userRelationService.CreateUserRelation(id, input.positionId, "Position")); userRelationList.AddRange(_userRelationService.CreateUserRelation(id, input.organizeId, "Organize")); userRelationList.AddRange(_userRelationService.CreateUserRelation(id, input.groupId, "Group")); if (userRelationList.Count > 0) await _userRelationService.Create(userRelationList); // 批量新增用户关系 // 如果是改成禁止或者锁定状态,该用户立即退出登录 if (input.enabledMark == 0 || input.enabledMark == 2) { Scoped.Create((_, scope) => { var services = scope.ServiceProvider; var _onlineuser = App.GetService(services); _onlineuser.ForcedOffline(entity.Id); }); } } catch (Exception) { FileHelper.MoveFile(Path.Combine(FileVariable.UserAvatarFilePath, headIcon), Path.Combine(FileVariable.TemporaryFilePath, headIcon)); throw Oops.Oh(ErrorCode.D5004); } #region 第三方同步 try { SysConfigOutput? sysConfig = await _sysConfigService.GetInfo(); List? userList = new List(); userList.Add(entity); if (sysConfig.dingSynIsSynUser) await _synThirdInfoService.SynUser(2, 3, sysConfig, userList); if (sysConfig.qyhIsSynUser) await _synThirdInfoService.SynUser(1, 3, sysConfig, userList); } catch (Exception) { } #endregion // 单点登录同步 await syncUserInfo(entity, "update", _userManager.TenantId); } /// /// 更新状态. /// /// 主键. /// [HttpPut("{id}/Actions/State")] public async Task UpdateState(string id) { UserEntity? entity = await _repository.GetFirstAsync(it => it.Id == id); if (!_userManager.DataScope.Any(it => it.organizeId == entity.OrganizeId && it.Edit == true) && !_userManager.IsAdministrator) throw Oops.Oh(ErrorCode.D1013); if (!await _repository.IsAnyAsync(u => u.Id == id && u.DeleteMark == null)) throw Oops.Oh(ErrorCode.D1002); int isOk = await _repository.AsUpdateable().SetColumns(it => new UserEntity() { EnabledMark = SqlFunc.IIF(it.EnabledMark == 1, 0, 1), LastModifyUserId = _userManager.UserId, LastModifyTime = SqlFunc.GetDate() }).Where(it => it.Id == id).ExecuteCommandAsync(); if (!(isOk > 0)) throw Oops.Oh(ErrorCode.D5005); } /// /// 重置密码. /// /// 主键. /// 参数. /// [HttpPost("{id}/Actions/ResetPassword")] public async Task ResetPassword(string id, [FromBody] UserResetPasswordInput input) { UserEntity? entity = await _repository.GetFirstAsync(u => u.Id == id && u.DeleteMark == null); // 所属组织 分级权限验证 List? orgIdList = await _repository.AsSugarClient().Queryable().Where(x => x.UserId == id && x.ObjectType == "Organize").Select(x => x.ObjectId).ToListAsync(); if (!_userManager.DataScope.Any(it => orgIdList.Contains(it.organizeId) && it.Edit) && !_userManager.IsAdministrator) throw Oops.Oh(ErrorCode.D1013); if (!input.userPassword.Equals(input.validatePassword)) throw Oops.Oh(ErrorCode.D5006); _ = entity ?? throw Oops.Oh(ErrorCode.D1002); string? password = MD5Encryption.Encrypt(input.userPassword + entity.Secretkey); int isOk = await _repository.AsUpdateable().SetColumns(it => new UserEntity() { Password = password, ChangePasswordDate = SqlFunc.GetDate(), LastModifyUserId = _userManager.UserId, LastModifyTime = SqlFunc.GetDate() }).Where(it => it.Id == id).ExecuteCommandAsync(); if (!(isOk > 0)) throw Oops.Oh(ErrorCode.D5005); // 单点登录同步 entity.Password = input.userPassword; await syncUserInfo(entity, "modifyPassword", _userManager.TenantId); } /// /// 解除锁定. /// /// 主键. /// [HttpPut("{id}/Actions/Unlock")] public async Task Unlock(string id) { UserEntity? entity = await _repository.GetFirstAsync(u => u.Id == id && u.DeleteMark == null); if (!_userManager.DataScope.Any(it => it.organizeId == entity.OrganizeId && it.Edit) && !_userManager.IsAdministrator) throw Oops.Oh(ErrorCode.D1013); int isOk = await _repository.AsUpdateable().SetColumns(it => new UserEntity() { LockMark = 0, // 解锁 LogErrorCount = 0, // 解锁 EnabledMark = 1, // 解锁 UnLockTime = DateTime.Now, // 取消解锁时间 LastModifyUserId = _userManager.UserId, LastModifyTime = SqlFunc.GetDate() }).Where(it => it.Id == id).ExecuteCommandAsync(); if (!(isOk > 0)) throw Oops.Oh(ErrorCode.D5005); } /// /// 导出Excel. /// /// /// [HttpGet("ExportExcel")] public async Task ExportExcel([FromQuery] UserExportDataInput input) { // 用户信息列表 List? userList = new List(); ISugarQueryable? sqlQuery = _repository.AsSugarClient().Queryable((a, b) => new JoinQueryInfos(JoinType.Left, b.Id == SqlFunc.ToString(a.OrganizeId))) .WhereIF(!string.IsNullOrWhiteSpace(input.organizeId), a => a.OrganizeId == input.organizeId) // 组织机构 .WhereIF(!input.keyword.IsNullOrEmpty(), a => a.Account.Contains(input.keyword) || a.RealName.Contains(input.keyword)) .Where(a => a.DeleteMark == null) .OrderBy(a => a.SortCode).OrderBy(a => a.CreatorTime, OrderByType.Desc) .Select(a => new UserListImportDataInput() { id = a.Id, account = a.Account, realName = a.RealName, birthday = SqlFunc.ToString(a.Birthday), certificatesNumber = a.CertificatesNumber, managerId = SqlFunc.Subqueryable().Where(e => e.Id == a.ManagerId).Select(u => SqlFunc.MergeString(u.RealName, "/", u.Account)), organizeId = a.OrganizeId, // 组织结构 positionId = a.PositionId, // 岗位 roleId = a.RoleId, // 多角色 certificatesType = SqlFunc.Subqueryable().Where(d => d.DictionaryTypeId == "7866376d5f694d4d851c7164bd00ebfc" && d.Id == a.CertificatesType).Select(b => b.FullName), education = SqlFunc.Subqueryable().Where(d => d.DictionaryTypeId == "6a6d6fb541b742fbae7e8888528baa16" && d.Id == a.Education).Select(b => b.FullName), gender = SqlFunc.Subqueryable().Where(d => d.DictionaryTypeId == "963255a34ea64a2584c5d1ba269c1fe6" && d.EnCode == SqlFunc.ToString(a.Gender)).Select(b => b.FullName), nation = SqlFunc.Subqueryable().Where(d => d.DictionaryTypeId == "b6cd65a763fa45eb9fe98e5057693e40" && d.Id == a.Nation).Select(b => b.FullName), description = a.Description, entryDate = SqlFunc.ToString(a.EntryDate), email = a.Email, enabledMark = SqlFunc.IF(a.EnabledMark.Equals(0)).Return("禁用").ElseIF(a.EnabledMark.Equals(1)).Return("正常").End("锁定"), mobilePhone = a.MobilePhone, nativePlace = a.NativePlace, postalAddress = a.PostalAddress, telePhone = a.TelePhone, urgentContacts = a.UrgentContacts, urgentTelePhone = a.UrgentTelePhone, landline = a.Landline, sortCode = a.SortCode.ToString() }); if (input.dataType == "0") userList = await sqlQuery.ToPageListAsync(input.currentPage, input.pageSize); else userList = await sqlQuery.ToListAsync(); userList.ForEach(item => { if (item.birthday.IsNotEmptyOrNull()) item.birthday = Convert.ToDateTime(item.birthday).ToString("yyyy-MM-dd HH:mm:ss"); if (item.entryDate.IsNotEmptyOrNull()) item.entryDate = Convert.ToDateTime(item.entryDate).ToString("yyyy-MM-dd HH:mm:ss"); }); List? olist = await _repository.AsSugarClient().Queryable().Where(it => it.EnabledMark == 1 && it.DeleteMark == null).OrderBy(a => a.CreatorTime, OrderByType.Asc).ToListAsync(); // 获取所有组织 List? plist = await _repository.AsSugarClient().Queryable().Where(it => it.EnabledMark == 1 && it.DeleteMark == null).ToListAsync(); // 获取所有岗位 List? rlist = await _repository.AsSugarClient().Queryable().Where(it => it.EnabledMark == 1 && it.DeleteMark == null).ToListAsync(); // 获取所有角色 // 转换 组织结构 和 岗位(多岗位) foreach (UserListImportDataInput? item in userList) { // 获取用户组织关联数据 List? orgRelList = await _repository.AsSugarClient().Queryable().Where(x => x.ObjectType == "Organize" && x.UserId == item.id).Select(x => x.ObjectId).ToListAsync(); if (orgRelList.Any()) { List? oentityList = olist.Where(x => orgRelList.Contains(x.Id)).ToList(); if (oentityList.Any()) { List? userOrgList = new List(); oentityList.ForEach(oentity => { List? oidList = oentity.OrganizeIdTree?.Split(',').ToList(); if (oidList != null) { List? oNameList = olist.Where(x => oidList.Contains(x.Id)).Select(x => x.FullName).ToList(); userOrgList.Add(string.Join("/", oNameList)); } else { List? oNameList = new List(); oNameList.Add(oentity.FullName); // 递归获取上级组织 GetOrganizeParentName(olist, oentity.ParentId, oNameList); userOrgList.Add(string.Join("/", oNameList)); } }); item.organizeId = string.Join(";", userOrgList); } } else { item.organizeId = string.Empty; } // 获取用户岗位关联 List? posRelList = await _repository.AsSugarClient().Queryable().Where(x => x.ObjectType == "Position" && x.UserId == item.id).Select(x => x.ObjectId).ToListAsync(); if (posRelList.Any()) item.positionId = string.Join(";", plist.Where(x => posRelList.Contains(x.Id)).Select(x => x.FullName + "/" + x.EnCode).ToList()); else item.positionId = string.Empty; // 角色 if (item.roleId.IsNotEmptyOrNull()) { List? ridList = item.roleId.Split(',').ToList(); item.roleId = string.Join(";", rlist.Where(x => ridList.Contains(x.Id)).Select(x => x.FullName).ToList()); } } ExcelConfig excelconfig = new ExcelConfig(); excelconfig.FileName = string.Format("{0:yyyy-MM-dd}_用户信息.xls", DateTime.Now); excelconfig.HeadFont = "微软雅黑"; excelconfig.HeadPoint = 10; excelconfig.IsAllSizeColumn = true; excelconfig.ColumnModel = new List(); foreach (KeyValuePair item in GetUserInfoFieldToTitle(input.selectKey.Split(',').ToList())) { string? column = item.Key; string? excelColumn = item.Value; excelconfig.ColumnModel.Add(new ExcelColumnModel() { Column = column, ExcelColumn = excelColumn }); } string? addPath = Path.Combine(FileVariable.TemporaryFilePath, excelconfig.FileName); var fs = ExcelExportHelper.ExportMemoryStream(userList, excelconfig); var flag = await _fileManager.UploadFileByType(fs, FileVariable.TemporaryFilePath, excelconfig.FileName); if (flag) { fs.Flush(); fs.Close(); } _cacheManager.Set(excelconfig.FileName, string.Empty); return new { name = excelconfig.FileName, url = "/api/file/Download?encryption=" + DESCEncryption.Encrypt(_userManager.UserId + "|" + excelconfig.FileName + "|" + addPath, "JNPF") }; } /// /// 模板下载. /// /// [HttpGet("TemplateDownload")] public dynamic TemplateDownload() { // 初始化 一条空数据 List? dataList = new List() { new UserListImportDataInput() { } }; ExcelConfig excelconfig = new ExcelConfig(); excelconfig.FileName = "用户信息导入模板.xls"; excelconfig.HeadFont = "微软雅黑"; excelconfig.HeadPoint = 10; excelconfig.IsAllSizeColumn = true; excelconfig.ColumnModel = new List(); foreach (KeyValuePair item in GetUserInfoFieldToTitle()) { string? column = item.Key; string? excelColumn = item.Value; excelconfig.ColumnModel.Add(new ExcelColumnModel() { Column = column, ExcelColumn = excelColumn }); } string? addPath = Path.Combine(FileVariable.TemporaryFilePath, excelconfig.FileName); ExcelExportHelper.Export(dataList, excelconfig, addPath); _cacheManager.Set(excelconfig.FileName, string.Empty); return new { name = excelconfig.FileName, url = "/api/file/Download?encryption=" + DESCEncryption.Encrypt(_userManager.UserId + "|" + excelconfig.FileName + "|" + addPath, "JNPF") }; } /// /// 上传文件. /// /// /// [HttpPost("Uploader")] public async Task Uploader(IFormFile file) { var _filePath = _fileManager.GetPathByType(string.Empty); var _fileName = DateTime.Now.ToString("yyyyMMdd") + "_" + SnowflakeIdHelper.NextId() + Path.GetExtension(file.FileName); var stream = file.OpenReadStream(); await _fileManager.UploadFileByType(stream, _filePath, _fileName); return new { name = _fileName, url = string.Format("/api/File/Image/{0}/{1}", string.Empty, _fileName) }; } /// /// 导入预览. /// /// [HttpGet("ImportPreview")] public dynamic ImportPreview(string fileName) { try { Dictionary? FileEncode = GetUserInfoFieldToTitle(); string? filePath = FileVariable.TemporaryFilePath; string? savePath = Path.Combine(filePath, fileName); // 得到数据 global::System.Data.DataTable? excelData = ExcelImportHelper.ToDataTable(savePath); foreach (object? item in excelData.Columns) { excelData.Columns[item.ToString()].ColumnName = FileEncode.Where(x => x.Value == item.ToString()).FirstOrDefault().Key; } if (excelData.Rows.Count > 0) excelData.Rows.RemoveAt(0); // 返回结果 return new { dataRow = excelData }; } catch (Exception e) { throw Oops.Oh(ErrorCode.D1801); } } /// /// 导出错误报告. /// /// /// [HttpPost("ExportExceptionData")] [UnitOfWork] public async Task ExportExceptionData([FromBody] UserImportDataInput list) { object[]? res = await ImportUserData(list.list); // 错误数据 List? errorlist = res.Last() as List; ExcelConfig excelconfig = new ExcelConfig(); excelconfig.FileName = "用户导入错误报告.xls"; excelconfig.HeadFont = "微软雅黑"; excelconfig.HeadPoint = 10; excelconfig.IsAllSizeColumn = true; excelconfig.ColumnModel = new List(); foreach (KeyValuePair item in GetUserInfoFieldToTitle()) { string? column = item.Key; string? excelColumn = item.Value; excelconfig.ColumnModel.Add(new ExcelColumnModel() { Column = column, ExcelColumn = excelColumn }); } string? addPath = Path.Combine(FileVariable.TemporaryFilePath, excelconfig.FileName); ExcelExportHelper.Export(errorlist, excelconfig, addPath); _cacheManager.Set(excelconfig.FileName, string.Empty); return new { name = excelconfig.FileName, url = "/api/file/Download?encryption=" + DESCEncryption.Encrypt(_userManager.UserId + "|" + excelconfig.FileName + "|" + addPath, "JNPF") }; } /// /// 导入数据. /// /// /// [HttpPost("ImportData")] [UnitOfWork] public async Task ImportData([FromBody] UserImportDataInput list) { object[]? res = await ImportUserData(list.list); List? addlist = res.First() as List; List? errorlist = res.Last() as List; return new UserImportResultOutput() { snum = addlist.Count, fnum = errorlist.Count, failResult = errorlist, resultType = errorlist.Count < 1 ? 0 : 1 }; } #endregion #region PublicMethod /// /// 获取用户信息 根据用户ID. /// /// 用户ID /// [NonAction] public UserEntity GetInfoByUserId(string userId) { return _repository.GetFirst(u => u.Id == userId && u.DeleteMark == null); } /// /// 获取用户信息 根据用户ID. /// /// 用户ID. /// [NonAction] public async Task GetInfoByUserIdAsync(string userId) { return await _repository.GetFirstAsync(u => u.Id == userId && u.DeleteMark == null); } /// /// 获取用户列表. /// /// [NonAction] public async Task> GetList() { return await _repository.AsQueryable().Where(u => u.DeleteMark == null).ToListAsync(); } /// /// 获取用户信息 根据用户账户. /// /// 用户账户. /// [NonAction] public async Task GetInfoByAccount(string account) { return await _repository.GetFirstAsync(u => u.Account == account && u.DeleteMark == null); } /// /// 获取用户信息 根据登录信息. /// /// 用户账户. /// 用户密码. /// [NonAction] public async Task GetInfoByLogin(string account, string password) { return await _repository.GetFirstAsync(u => u.Account == account && u.Password == password && u.DeleteMark == null); } /// /// 根据用户姓名获取用户ID. /// /// 用户姓名. /// [NonAction] public async Task GetUserIdByRealName(string realName) { return (await _repository.GetFirstAsync(u => u.RealName == realName && u.DeleteMark == null)).Id; } /// /// 获取用户名. /// /// 用户id. /// 是否显示账号. /// [NonAction] public async Task GetUserName(string userId, bool isAccount = true) { UserEntity? entity = await _repository.GetFirstAsync(x => x.Id == userId && x.DeleteMark == null); if (entity.IsNullOrEmpty()) return string.Empty; return isAccount ? entity.RealName + "/" + entity.Account : entity.RealName; } /// /// 获取当前用户岗位信息. /// /// /// [NonAction] public async Task> GetPosition(string PositionIds) { string[]? ids = PositionIds.Split(","); return await _repository.AsSugarClient().Queryable().In(it => it.Id, ids).Select(it => new PositionInfoModel { id = it.Id, name = it.FullName }).ToListAsync(); } /// /// 表达式获取用户. /// /// /// [NonAction] public async Task GetUserByExp(Expression> expression) { return await _repository.GetFirstAsync(expression); } /// /// 表达式获取用户列表. /// /// /// [NonAction] public async Task> GetUserListByExp(Expression> expression) { return await _repository.AsQueryable().Where(expression).ToListAsync(); } /// /// 表达式获取指定字段的用户列表. /// /// where 条件表达式. /// select 选择字段表达式. /// [NonAction] public async Task> GetUserListByExp(Expression> expression, Expression> select) { return await _repository.AsQueryable().Where(expression).Select(select).ToListAsync(); } #endregion #region PrivateMethod /// /// 获取集合中的组织 树,根据上级ID. /// /// 组织 集合. /// 上级ID. /// 返回. /// private List GetOrganizeParentName(List list, string parentId, List addList) { OrganizeEntity? entity = list.Find(x => x.Id == parentId); if (entity.ParentId != "-1") GetOrganizeParentName(list, entity.ParentId, addList); else addList.Add(entity.FullName); return addList; } /// /// 是否我的下属. /// /// 当前用户. /// 主管ID. /// 层级. /// private async Task GetIsMyStaff(string userId, string managerId, int tier) { bool isMyStaff = false; if (tier <= 0) return true; string? superiorUserId = (await _repository.GetFirstAsync(it => it.Id.Equals(managerId) && it.DeleteMark == null))?.ManagerId; if (superiorUserId == null) { isMyStaff = false; } else if (userId == superiorUserId) { isMyStaff = true; } else { tier--; isMyStaff = await GetIsMyStaff(userId, superiorUserId, tier); } return isMyStaff; } /// /// 用户信息 字段对应 列名称. /// /// private Dictionary GetUserInfoFieldToTitle(List fields = null) { Dictionary? res = new Dictionary(); res.Add("account", "账户"); res.Add("realName", "姓名"); res.Add("gender", "性别"); res.Add("email", "电子邮箱"); res.Add("organizeId", "所属组织"); res.Add("managerId", "直属主管"); res.Add("positionId", "岗位"); res.Add("roleId", "角色"); res.Add("sortCode", "排序"); res.Add("enabledMark", "状态"); res.Add("description", "说明"); res.Add("nation", "民族"); res.Add("nativePlace", "籍贯"); res.Add("entryDate", "入职时间"); res.Add("certificatesType", "证件类型"); res.Add("certificatesNumber", "证件号码"); res.Add("education", "文化程度"); res.Add("birthday", "出生年月"); res.Add("telePhone", "办公电话"); res.Add("landline", "办公座机"); res.Add("mobilePhone", "手机号码"); res.Add("urgentContacts", "紧急联系"); res.Add("urgentTelePhone", "紧急电话"); res.Add("postalAddress", "通讯地址"); if (fields == null || !fields.Any()) return res; Dictionary? result = new Dictionary(); foreach (KeyValuePair item in res) { if (fields.Contains(item.Key)) result.Add(item.Key, item.Value); } return result; } /// /// 导入用户数据函数. /// /// list. /// [成功列表,失败列表]. private async Task ImportUserData(List list) { List userInputList = list; #region 初步排除错误数据 if (userInputList == null || userInputList.Count() < 1) throw Oops.Oh(ErrorCode.D5019); // 必填字段验证 (账号,姓名,性别,所属组织) List? errorList = userInputList .Where(x => !x.account.IsNotEmptyOrNull() || !x.realName.IsNotEmptyOrNull() || !x.gender.IsNotEmptyOrNull() || !x.organizeId.IsNotEmptyOrNull()).ToList(); // 上传重复的账号 userInputList.ForEach(item => { if (userInputList.Count(x => x.account == item.account) > 1) { var errorItems = userInputList.Where(x => x.account == item.account).ToList(); errorItems.Remove(errorItems.First()); errorList.AddRange(errorItems); } }); errorList = errorList.Distinct().ToList(); userInputList = userInputList.Except(errorList).ToList(); // 用户账号 (匹配直属主管 和 验证重复账号) List? _userRepositoryList = await _repository.AsQueryable().Where(it => it.DeleteMark == null).ToListAsync(); // 已存在的账号 List? repeat = _userRepositoryList.Where(u => userInputList.Select(x => x.account).Contains(u.Account)).ToList(); // 已存在的账号 列入 错误列表 if (repeat.Any()) errorList.AddRange(userInputList.Where(u => repeat.Select(x => x.Account).Contains(u.account))); userInputList = userInputList.Except(errorList).ToList(); #endregion List? userList = new List(); #region 预处理关联表数据 // 组织机构 List? _organizeServiceList = await _organizeService.GetListAsync(); Dictionary? organizeDic = new Dictionary(); _organizeServiceList.ForEach(item => { if (item.OrganizeIdTree.IsNullOrEmpty()) item.OrganizeIdTree = item.Id; var orgNameList = new List(); item.OrganizeIdTree.Split(",").ToList().ForEach(it => { var org = _organizeServiceList.Find(x => x.Id == it); if (org != null) orgNameList.Add(org.FullName); }); organizeDic.Add(item.Id, string.Join("/", orgNameList)); }); List? _positionRepositoryList = await _repository.AsSugarClient().Queryable().Where(x => x.DeleteMark == null).ToListAsync(); // 岗位 List? _roleRepositoryList = await _repository.AsSugarClient().Queryable().Where(x => x.DeleteMark == null).ToListAsync(); // 角色 DictionaryTypeEntity? typeEntity = await _repository.AsSugarClient().Queryable().Where(x => (x.Id == "963255a34ea64a2584c5d1ba269c1fe6" || x.EnCode == "963255a34ea64a2584c5d1ba269c1fe6") && x.DeleteMark == null).FirstAsync(); List? _genderList = await _repository.AsSugarClient().Queryable().Where(d => d.DictionaryTypeId == typeEntity.Id && d.DeleteMark == null).ToListAsync(); // 性别 typeEntity = await _repository.AsSugarClient().Queryable().Where(x => (x.Id == "b6cd65a763fa45eb9fe98e5057693e40" || x.EnCode == "b6cd65a763fa45eb9fe98e5057693e40") && x.DeleteMark == null).FirstAsync(); List? _nationList = await _repository.AsSugarClient().Queryable().Where(d => d.DictionaryTypeId == typeEntity.Id && d.DeleteMark == null).ToListAsync(); // 民族 typeEntity = await _repository.AsSugarClient().Queryable().Where(x => (x.Id == "7866376d5f694d4d851c7164bd00ebfc" || x.EnCode == "7866376d5f694d4d851c7164bd00ebfc") && x.DeleteMark == null).FirstAsync(); List? certificateTypeList = await _repository.AsSugarClient().Queryable().Where(d => d.DictionaryTypeId == typeEntity.Id && d.DeleteMark == null).ToListAsync(); // 证件类型 typeEntity = await _repository.AsSugarClient().Queryable().Where(x => (x.Id == "6a6d6fb541b742fbae7e8888528baa16" || x.EnCode == "6a6d6fb541b742fbae7e8888528baa16") && x.DeleteMark == null).FirstAsync(); List? educationList = await _repository.AsSugarClient().Queryable().Where(d => d.DictionaryTypeId == typeEntity.Id && d.DeleteMark == null).ToListAsync(); // 文化程度 #endregion // 用户关系数据 List? userRelationList = new List(); foreach (UserListImportDataInput? item in userInputList) { List? orgIds = new List(); // 多组织 , 号隔开 List? posIds = new List(); // 多岗位 , 号隔开 UserEntity? uentity = new UserEntity(); uentity.Id = SnowflakeIdHelper.NextId(); if (string.IsNullOrEmpty(uentity.HeadIcon)) uentity.HeadIcon = "001.png"; uentity.Secretkey = Guid.NewGuid().ToString(); uentity.Password = MD5Encryption.Encrypt(MD5Encryption.Encrypt(CommonConst.DEFAULTPASSWORD) + uentity.Secretkey); // 初始化密码 uentity.ManagerId = _userRepositoryList.Find(x => x.Account == item.managerId?.Split('/').LastOrDefault())?.Id; // 寻找主管 // 寻找角色 if (item.roleId.IsNotEmptyOrNull() && item.roleId.Split(";").Any()) uentity.RoleId = string.Join(",", _roleRepositoryList.Where(r => item.roleId.Split(";").Contains(r.FullName)).Select(x => x.Id).ToList()); // 寻找组织 string[]? userOidList = item.organizeId.Split(";"); if (userOidList.Any()) { foreach (string? oinfo in userOidList) { if (organizeDic.ContainsValue(oinfo)) orgIds.Add(organizeDic.Where(x => x.Value == oinfo).FirstOrDefault().Key); } } else { // 如果未找到组织,列入错误列表 errorList.Add(item); continue; } // 如果未找到组织,列入错误列表 if (!orgIds.Any()) { errorList.Add(item); continue; } // 寻找岗位 item.positionId?.Split(';').ToList().ForEach(it => { string[]? pinfo = it.Split("/"); string? pid = _positionRepositoryList.Find(x => x.FullName == pinfo.FirstOrDefault() && x.EnCode == pinfo.LastOrDefault())?.Id; if (pid.IsNotEmptyOrNull()) posIds.Add(pid); // 多岗位 }); // 性别 if (_genderList.Find(x => x.FullName == item.gender) != null) uentity.Gender = _genderList.Find(x => x.FullName == item.gender).EnCode.ParseToInt(); else uentity.Gender = _genderList.Find(x => x.FullName == "保密").EnCode.ParseToInt(); uentity.Nation = _nationList.Find(x => x.FullName == item.nation)?.Id; // 民族 uentity.Education = educationList.Find(x => x.FullName == item.education)?.Id; // 文化程度 uentity.CertificatesType = certificateTypeList.Find(x => x.FullName == item.certificatesType)?.Id; // 证件类型 uentity.Account = item.account; uentity.Birthday = item.birthday.IsNotEmptyOrNull() ? item.birthday.ParseToDateTime() : null; uentity.CertificatesNumber = item.certificatesNumber; uentity.CreatorUserId = _userManager.UserId; uentity.CreatorTime = DateTime.Now; uentity.Description = item.description; uentity.Email = item.email; switch (item.enabledMark) { case "禁用": uentity.EnabledMark = 0; break; case "正常": uentity.EnabledMark = 1; break; case "锁定": default: uentity.EnabledMark = 2; break; } uentity.EntryDate = item.entryDate.IsNotEmptyOrNull() ? item.entryDate.ParseToDateTime() : null; uentity.Landline = item.landline; uentity.MobilePhone = item.mobilePhone; uentity.NativePlace = item.nativePlace; uentity.PostalAddress = item.postalAddress; uentity.RealName = item.realName; uentity.SortCode = item.sortCode.ParseToInt(); uentity.TelePhone = item.telePhone; uentity.UrgentContacts = item.urgentContacts; uentity.UrgentTelePhone = item.urgentTelePhone; #region 多组织 优先选择有权限组织 uentity.OrganizeId = string.Empty; foreach (string? it in orgIds) { List? UserRoleList = await _userManager.GetUserOrgRoleIds(uentity.RoleId, it); // 如果该组织下有角色并且有角色权限 则为默认组织 if (UserRoleList.Any() && _repository.AsSugarClient().Queryable().Where(x => x.ObjectType == "Role" && x.ItemType == "module" && UserRoleList.Contains(x.ObjectId)).Any()) { uentity.OrganizeId = it; // 多 组织 默认 break; } } if (uentity.OrganizeId.IsNullOrEmpty()) // 如果所选组织下都没有角色或者没有角色权限 默认取第一个 uentity.OrganizeId = orgIds.FirstOrDefault(); #endregion // 岗位多组织 匹配 var opIds = await _repository.AsSugarClient().Queryable().Where(x => x.DeleteMark == null && orgIds.Contains(x.OrganizeId)).Select(x => x.Id).ToListAsync(); posIds = opIds.Intersect(posIds).ToList(); if (uentity.OrganizeId.IsNotEmptyOrNull()) { List? roleList = _userRelationService.CreateUserRelation(uentity.Id, uentity.RoleId, "Role"); // 角色关系 List? positionList = _userRelationService.CreateUserRelation(uentity.Id, string.Join(",", posIds), "Position"); // 岗位关系 List? organizeList = _userRelationService.CreateUserRelation(uentity.Id, string.Join(",", orgIds), "Organize"); // 组织关系 userRelationList.AddRange(positionList); userRelationList.AddRange(roleList); userRelationList.AddRange(organizeList); } userList.Add(uentity); } if (userList.Any()) { try { // 新增用户记录 UserEntity? newEntity = await _repository.AsInsertable(userList).CallEntityMethod(m => m.Create()).ExecuteReturnEntityAsync(); // 批量新增用户关系 if (userRelationList.Count > 0) await _userRelationService.Create(userRelationList); } catch (Exception) { errorList.AddRange(userInputList); userInputList = new List(); } } return new object[] { userList, errorList }; } /// /// 获取机构成员列表. /// /// 机构ID. /// [NonAction] public async Task> GetOrganizeMemberList(string organizeId) { // 获取分级管理组织 var dataScope = _repository.AsSugarClient().Queryable() .Where(it => SqlFunc.ToString(it.UserId) == _userManager.UserId && it.DeleteMark == null) .Where(it => it.ThisLayerSelect.Equals(1) || it.SubLayerSelect.Equals(1) || it.ThisLayerAdd.Equals(1) || it.SubLayerAdd.Equals(1) || it.ThisLayerDelete.Equals(1) || it.SubLayerDelete.Equals(1) || it.ThisLayerEdit.Equals(1) || it.SubLayerEdit.Equals(1)).ToList(); var thisLayer = dataScope.Where(it => it.ThisLayerSelect.Equals(1) || it.ThisLayerAdd.Equals(1) || it.ThisLayerDelete.Equals(1) || it.ThisLayerEdit.Equals(1)).ToList(); var subLayer = dataScope.Where(it => it.SubLayerSelect.Equals(1) || it.SubLayerAdd.Equals(1) || it.SubLayerDelete.Equals(1) || it.SubLayerEdit.Equals(1)).ToList(); List? output = new List(); if (organizeId.Equals("0")) { List? data = await _repository.AsSugarClient().Queryable().Where(o => o.DeleteMark == null && o.EnabledMark == 1) .WhereIF(thisLayer.Any(), x => thisLayer.Select(x => x.OrganizeId).Contains(x.Id)) .WhereIF(!thisLayer.Any(), x => thisLayer.Select(x => x.OrganizeId).Contains(x.Id)).OrderBy(o => o.SortCode).ToListAsync(); if (subLayer.Any()) { subLayer.ForEach(item => { var itemRes = _repository.AsSugarClient().Queryable().Where(o => o.DeleteMark == null && o.EnabledMark == 1) .Where(x => x.OrganizeIdTree.Contains(item.OrganizeId) && !x.Id.Equals(item.OrganizeId)).OrderBy(o => o.SortCode).ToList(); data.AddRange(itemRes); }); } data.ForEach(o => { output.Add(new OrganizeMemberListOutput { id = o.Id, fullName = o.FullName, enabledMark = o.EnabledMark, type = o.Category, icon = o.Category.Equals("company") ? "icon-ym icon-ym-tree-organization3" : "icon-ym icon-ym-tree-department1", organizeIdTree = o.OrganizeIdTree, hasChildren = true, isLeaf = false }); }); } else { var userRelationList = await _repository.AsSugarClient().Queryable().Where(x => x.ObjectType.Equals("Organize") && x.ObjectId.Equals(organizeId)).Select(x => x.UserId).ToListAsync(); List? userList = await _repository.AsSugarClient().Queryable() .Where(u => userRelationList.Contains(u.Id) && u.EnabledMark > 0 && u.DeleteMark == null).OrderBy(o => o.SortCode).ToListAsync(); userList.ForEach(u => { output.Add(new OrganizeMemberListOutput() { id = u.Id, fullName = u.RealName + "/" + u.Account, enabledMark = u.EnabledMark, type = "user", icon = "icon-ym icon-ym-tree-user2", headIcon = "/api/File/Image/userAvatar/" + u.HeadIcon, hasChildren = false, isLeaf = true }); }); List? departmentList = await _repository.AsSugarClient().Queryable().Where(o => o.DeleteMark == null && o.EnabledMark == 1) .Where(x => x.ParentId.Equals(organizeId)) .WhereIF(thisLayer.Any(), x => thisLayer.Select(x => x.OrganizeId).Contains(x.Id)) .WhereIF(!thisLayer.Any(), x => thisLayer.Select(x => x.OrganizeId).Contains(x.Id)).OrderBy(o => o.SortCode).ToListAsync(); if (subLayer.Any()) { subLayer.ForEach(item => { var itemRes = _repository.AsSugarClient().Queryable().Where(o => o.DeleteMark == null && o.EnabledMark == 1) .Where(x => x.OrganizeIdTree.Contains(item.OrganizeId) && !x.Id.Equals(item.OrganizeId)).OrderBy(o => o.SortCode).ToList(); departmentList.AddRange(itemRes); }); } departmentList.ForEach(o => { output.Add(new OrganizeMemberListOutput() { id = o.Id, fullName = o.FullName, enabledMark = o.EnabledMark, type = o.Category, icon = o.Category.Equals("company") ? "icon-ym icon-ym-tree-organization3" : "icon-ym icon-ym-tree-department1", hasChildren = true, organizeIdTree = o.OrganizeIdTree, isLeaf = false }); }); } if (!organizeId.Equals("0")) output.RemoveAll(x => x.id.Equals(organizeId)); // 获取组织树 var orgTree = _organizeService.GetOrgListTreeName(); // 组织断层处理 output.Where(x => x.parentId != "-1" && x.organizeIdTree.IsNotEmptyOrNull()).ToList().ForEach(item => { item.fullName = orgTree.Find(x => x.Id.Equals(item.id)).Description; if (!output.Any(x => x.id.Equals(item.parentId))) { var pItem = output.Where(x => x.organizeIdTree.IsNotEmptyOrNull() && x.id != item.id && item.organizeIdTree.Contains(x.organizeIdTree)).FirstOrDefault(); if (pItem != null) { item.parentId = pItem.id; item.fullName = item.fullName.Replace(pItem.fullName + "/", string.Empty); } else { item.parentId = "-1"; } } else { var pItem = output.Find(x => x.id.Equals(item.parentId)); item.fullName = item.fullName.Replace(pItem.fullName + "/", string.Empty); } }); output.RemoveAll(x => x.type != "user" && x.parentId != "-1"); if (!organizeId.Equals("0")) { var pOrgTreeName = orgTree.Find(x => x.Id.Equals(organizeId)).Description; output.ForEach(item => item.fullName = item.fullName.Replace(pOrgTreeName + "/", string.Empty)); } return output; } #endregion #region 单点登录 数据同步 /// /// 同步数据导maxkey. /// /// /// /// public async Task syncUserInfo(UserEntity userEntity, string method, string tenantId) { try { if (_oauthOptions.Enabled) { var userName = string.Format("{0}:{1}", _oauthOptions.Pull.UserName, _oauthOptions.Pull.Password).ToBase64String(); // http调用结果 HttpResponse execute = null; var map = parse(userEntity); tenantId = tenantId != null && tenantId.Length > 0 ? tenantId : "1"; if (tenantId.Equals("default")) tenantId = "1"; map.Add("instId", tenantId); // 得到userId // String username = userEntity.get("id") != null && userEntity.get("id").toString().length() > 0 ? userEntity.get("id").toString() : null; Dictionary jsonObject = null; var resString = string.Empty; var headers = new Dictionary(); headers.Add("Authorization", _oauthOptions.Pull.CredentialType + " " + userName); if (method.Equals("create")) { resString = await (_oauthOptions.Pull.CreateRestAddress + "?appId=" + _oauthOptions.Pull.UserName).SetHeaders(headers).SetBody(map).PostAsStringAsync(); } else if (method.Equals("update")) { resString = await (_oauthOptions.Pull.ReplaceRestAddress + "?appId=" + _oauthOptions.Pull.UserName).SetHeaders(headers).SetBody(map).PutAsStringAsync(); } else if (method.Equals("delete")) { resString = await (_oauthOptions.Pull.DeleteRestAddress + "?appId=" + _oauthOptions.Pull.UserName).SetHeaders(headers).SetBody(map).DeleteAsStringAsync(); } else if (method.Equals("modifyPassword")) { resString = await (_oauthOptions.Pull.ChangePasswordRestAddress + "?appId=" + _oauthOptions.Pull.UserName).SetHeaders(headers).SetBody(map).PostAsStringAsync(); } // else if (method.Equals("modifyPassword")) { // jsonObject = HttpUtil.httpRequest(_oauthOptions.Pull.getGetRestAddress() + username // , "GET" // , null, _oauthOptions.Pull.getCredentialType() + " " + _oauthOptions.Pull.getUserName() + "Og==" + _oauthOptions.Pull.getPassword() // , null); // } } } catch (Exception e) { } } private Dictionary parse(UserEntity userEntity) { var map = new Dictionary(); // map.Add("id", userEntity.get("id")); map.Add("username", userEntity.Account); map.Add("password", userEntity.Password); map.Add("mobile", userEntity.MobilePhone); map.Add("email", userEntity.Email); map.Add("gender", (int)userEntity.Gender == 1 ? 2 : 1); map.Add("createdBy", userEntity.CreatorUserId); map.Add("createdDate", userEntity.CreatorTime); map.Add("modifiedBy", userEntity.LastModifyUserId); map.Add("modifiedDate", userEntity.LastModifyTime); map.Add("displayName", userEntity.RealName); // map.Add("managerId", userEntity.get("managerId")); // map.Add("departmentId", userEntity.get("organizeId")); map.Add("loginCount", userEntity.LogSuccessCount); map.Add("badPasswordCount", userEntity.LogErrorCount); map.Add("lastLoginIp", userEntity.LastLogIP); map.Add("lastLoginTime", userEntity.LastLogTime); map.Add("status", userEntity.EnabledMark != null ? (userEntity.EnabledMark == 1 ? 1 : 4) : 4); return map; } /// /// 根据单点服务端消息 同步用户信息到数据库. /// /// [NonAction] public async Task Receive(string message) { bool isSuccess; var map = new Dictionary(); try { var mqMessage = message.ToObject(); // 转成用户实体类 var userInfo = mqMessage.content.ToObject(); var userEntity = new UserEntity(); userEntity.Id = userInfo.id; userEntity.Account = userInfo.username; userEntity.MobilePhone = userInfo.mobile; userEntity.Email = userInfo.email; userEntity.Gender = userInfo.gender; userEntity.CreatorTime = userInfo.createdDate.IsNullOrWhiteSpace() ? null : userInfo.createdDate?.ParseToLong().TimeStampToDateTime(); userEntity.CreatorUserId = userInfo.createdBy; userEntity.LastModifyUserId = userInfo.modifiedBy; userEntity.LastModifyTime = userInfo.modifiedDate.IsNullOrWhiteSpace() ? null : userInfo.modifiedDate?.ParseToLong().TimeStampToDateTime(); userEntity.RealName = userInfo.displayName; userEntity.LogSuccessCount = userInfo.loginCount; userEntity.LogErrorCount = userInfo.badPasswordCount; userEntity.LastLogIP = userInfo.lastLoginIp; userEntity.LastLogTime = userInfo.lastLoginTime.IsNullOrWhiteSpace() ? null : userInfo.lastLoginTime?.ParseToLong().TimeStampToDateTime(); userEntity.EnabledMark = userInfo.status == 1 ? 1 : 0; userEntity.HeadIcon = "001.png"; if (_tenant.MultiTenancy) { ConnectionConfigOptions options = new ConnectionConfigOptions(); var interFace = string.Format("{0}{1}", _tenant.MultiTenancyDBInterFace, userInfo.instId); var response = interFace.GetAsStringAsync().Result; var result = response.ToObject>(); if (result.code != 200) { throw Oops.Oh(result.msg); } else if (result.data.dotnet == null && result.data.linkList == null) { throw Oops.Oh(ErrorCode.D1025); } else { if (result.data.linkList == null || result.data.linkList?.Count == 0) { options = JNPFTenantExtensions.GetLinkToOrdinary(userInfo.instId, result.data.dotnet); } else if (result.data.dotnet == null) { options = JNPFTenantExtensions.GetLinkToCustom(userInfo.instId, result.data.linkList); } } if (!"default".Equals(userInfo.instId) && _tenant.MultiTenancyType.Equals("COLUMN")) { _sqlSugarClient.QueryFilter.AddTableFilter(it => it.TenantId == userInfo.instId); } else { _sqlSugarClient.AddConnection(JNPFTenantExtensions.GetConfig(options)); _sqlSugarClient.ChangeDatabase(userInfo.instId); } } isSuccess = await process(userEntity, mqMessage.actionType, userInfo.instId); } catch (Exception e) { // _logger.error("同步用户失败", e); isSuccess = false; } if (!isSuccess) { // _logger.info("消息消费失败:" + message); } else { // _logger.debug("同步用户信息, {}", JSONObject.toJSONString(map)); } return isSuccess; } /// /// 保存到数据库处理逻辑. /// /// /// /// private async Task process(UserEntity entity, string actionType, string instId) { if (actionType.Equals("CREATE_ACTION")) { if (_sqlSugarClient.Queryable().Any(x => x.Account.Equals(entity.Account) && x.DeleteMark == null)) return true; entity.Secretkey = Guid.NewGuid().ToString(); entity.Password = MD5Encryption.Encrypt(MD5Encryption.Encrypt(CommonConst.DEFAULTPASSWORD) + entity.Secretkey); UserRelationEntity? entityRelation = new UserRelationEntity(); entityRelation.Id = SnowflakeIdHelper.NextId(); entityRelation.ObjectType = "Organize"; entityRelation.ObjectId = _sqlSugarClient.Queryable().First(x => x.ParentId.Equals("-1")).Id; entityRelation.SortCode = 0; entityRelation.UserId = entity.Id; entityRelation.CreatorTime = DateTime.Now; entityRelation.CreatorUserId = entity.CreatorUserId; _sqlSugarClient.Insertable(entityRelation).ExecuteCommand(); // 批量新增用户关系 // 新增用户记录 return await _sqlSugarClient.Insertable(entity).CallEntityMethod(m => m.Create()).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandAsync() > 0; } else if (actionType.Equals("UPDATE_ACTION")) { var oldEntity = await _sqlSugarClient.Queryable().FirstAsync(x => x.Account.Equals(entity.Account) && x.DeleteMark == null); entity.Id = oldEntity.Id; return await _sqlSugarClient.Updateable(entity).CallEntityMethod(m => m.LastModify()).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync() > 0; } else if (actionType.Equals("DELETE_ACTION")) { var oldEntity = await _sqlSugarClient.Queryable().FirstAsync(x => x.Account.Equals(entity.Account) && x.DeleteMark == null); oldEntity.EnabledMark = 0; // 同步删除用户 只能 该状态为 : 禁用 return await _sqlSugarClient.Updateable(oldEntity).CallEntityMethod(m => m.LastModify()).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync() > 0; } else if (actionType.Equals("PASSWORD_ACTION")) { return await _sqlSugarClient.Updateable().SetColumns(it => new UserEntity() { Password = entity.Password, ChangePasswordDate = SqlFunc.GetDate(), LastModifyUserId = _userManager.UserId, LastModifyTime = SqlFunc.GetDate() }).Where(it => it.Id == entity.Id).ExecuteCommandAsync() > 0; } else { //_logger.info("Other Action , will sikp it ..."); } return true; } #endregion }