using Furion.DataEncryption; using Furion.DependencyInjection; using Furion.DynamicApiController; using Furion.FriendlyException; using Myshipping.Core.Entity; using Mapster; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using MiniExcelLibs; using SqlSugar; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using Yitter.IdGenerator; using Furion; using NPOI.HSSF.UserModel; using Myshipping.Core.Helper; using System.Web; using System.Text; using Furion.EventBus; using Microsoft.AspNetCore.Authorization; using Myshipping.Core.Const; namespace Myshipping.Core.Service; /// /// 用户服务 /// [ApiDescriptionSettings(Name = "User", Order = 150)] public class SysUserService : ISysUserService, IDynamicApiController, ITransient { private readonly SqlSugarRepository _sysUserRep; // 用户表仓储 private readonly ISysCacheService _sysCacheService; private readonly ISysConfigService _sysConfigService; private readonly ISysEmpService _sysEmpService; private readonly ISysUserDataScopeService _sysUserDataScopeService; private readonly ISysUserRoleService _sysUserRoleService; private readonly ISysEmpPosService _sysEmpPosService; private readonly IEventPublisher _publisher; private readonly ISysDataUserMenu _sysDataUserMenu; private readonly ISysRoleService _sysRoleService; public SysUserService(SqlSugarRepository sysUserRep, ISysCacheService sysCacheService, ISysEmpService sysEmpService, ISysUserDataScopeService sysUserDataScopeService, ISysUserRoleService sysUserRoleService, ISysConfigService sysConfigService, ISysEmpPosService sysEmpPosService, IEventPublisher publisher, ISysDataUserMenu sysDataUserMenu, ISysRoleService sysRoleService) { _sysUserRep = sysUserRep; _sysCacheService = sysCacheService; _sysEmpService = sysEmpService; _sysUserDataScopeService = sysUserDataScopeService; _sysUserRoleService = sysUserRoleService; _sysConfigService = sysConfigService; _sysEmpPosService = sysEmpPosService; _publisher = publisher; _sysDataUserMenu = sysDataUserMenu; _sysRoleService = sysRoleService; } /// /// 分页查询用户 /// /// /// [HttpGet("/sysUser/page")] public async Task QueryUserPageList([FromQuery] UserInput input) { var superAdmin = UserManager.IsSuperAdmin; var searchValue = input.SearchValue; var pid = input.SysEmpParam.OrgId; var users = await _sysUserRep.AsQueryable().InnerJoin((u, e) => u.Id == e.Id) .InnerJoin((u, e, o) => e.OrgId == o.Id) .InnerJoin((u, e, o, t) => u.TenantId == t.Id) .WhereIF(!string.IsNullOrWhiteSpace(searchValue), (u, e, o) => u.Account.Contains(input.SearchValue.Trim()) || u.Name.Contains(input.SearchValue.Trim()) || u.Phone.Contains(input.SearchValue.Trim())) .WhereIF(!string.IsNullOrWhiteSpace(pid), (u, e, o) => e.OrgId == long.Parse(pid) || o.Pids.Contains(pid.Trim())) .WhereIF(Enum.IsDefined(typeof(CommonStatus), input.SearchStatus), (u, e, o) => u.Status == input.SearchStatus) .Where((u, e, o) => u.AdminType == AdminType.None) .Select("u.*,t.Name As TenantName,o.name as orgName ").ToDataFilter("u", "Id", FilterType.User) .OrderBy(PageInputOrder.OrderBuilder(input.SortField, input.DescSort)). ToPagedListAsync(input.PageNo, input.PageSize); var empInfos = await _sysEmpService.GetEmpInfo(users.Items.Select(m => long.Parse(m.Id)).ToList()); foreach (var user in users.Items) { user.SysEmpInfo = empInfos.FirstOrDefault(m => m.Id == long.Parse(user.Id)); } return users.XnPagedResult(); } /// /// 增加用户 /// /// /// [HttpPost("/sysUser/add")] public async Task AddUser(AddUserInput input) { // 数据范围检查 CheckDataScope(input.SysEmpParam == null || string.IsNullOrEmpty(input.SysEmpParam.OrgId) ? 0 : long.Parse(input.SysEmpParam.OrgId)); var isExist = await _sysUserRep.AsQueryable().Filter(null, true).AnyAsync(u => u.Account == input.Account && u.IsDeleted == false); if (isExist) throw Oops.Oh(ErrorCode.D1003); var keyDES = App.GetOptions().DES; var user = input.Adapt(); user.AdminType = AdminType.None; user.Password = DESCEncryption.Encrypt(input.Password, keyDES); if (string.IsNullOrEmpty(user.Name)) user.Name = user.Account; if (string.IsNullOrEmpty(user.NickName)) user.NickName = user.Account; try { _sysUserRep.CurrentBeginTran(); var newUser = await _sysUserRep.InsertReturnEntityAsync(user); input.SysEmpParam.Id = newUser.Id.ToString(); // 增加员工信息 await _sysEmpService.AddOrUpdate(input.SysEmpParam); // 如果当前运行模式为和川,则进行一些初始化操作 if (App.Configuration["RunType"] == CommonConst.RUN_TYPE_HECHUAN) { // 绑定角色:普通员工 long? roleId = await _sysRoleService.GetRoleIdByRoleCode(CommonConst.ROLE_COMMON_EMPLOYEE); if (roleId != null) { await _sysUserRoleService.GrantRole(new UpdateUserInput() { Id = newUser.Id, GrantRoleIdList = new List() { (long)roleId } }); } // 授权"订舱台账"菜单的数据范围 var userMenuDto = new User.Dto.SysDataUserMenuDto() { UserId = newUser.Id, childrens = new List() { new(MenuConst.MenuBookingOrder, DataScopeType.DEPT_WITH_CHILD, true) } }; await _sysDataUserMenu.GrantData(userMenuDto); } _sysUserRep.CurrentCommitTran(); await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_USERSDATASCOPE); } catch (Exception) { _sysUserRep.CurrentRollbackTran(); throw; } } /// /// 删除用户 /// /// /// [HttpPost("/sysUser/delete")] public async Task DeleteUser(DeleteUserInput input) { var user = await _sysUserRep.FirstOrDefaultAsync(u => u.Id == input.Id); if (user.AdminType != AdminType.None) throw Oops.Oh(ErrorCode.D1014); if (user.Account == UserManager.Account) { throw Oops.Oh(ErrorCode.D1001); } // 数据范围检查 CheckDataScopeByUserId(input.Id); try { _sysUserRep.CurrentBeginTran(); // 直接删除用户 await _sysUserRep.AsUpdateable(new SysUser { IsDeleted = true }).UpdateColumns(user.FalseDeleteColumn()).Where(wh => wh.Id == user.Id).ExecuteCommandAsync(); // 删除员工及附属机构职位信息 await _sysEmpService.DeleteEmpInfoByUserId(user.Id); //删除该用户对应的用户-角色表关联信息 await _sysUserRoleService.DeleteUserRoleListByUserId(user.Id); //删除该用户对应的用户-数据范围表关联信息 await _sysUserDataScopeService.DeleteUserDataScopeListByUserId(user.Id); _sysUserRep.CurrentCommitTran(); await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_USERSDATASCOPE); } catch (Exception) { _sysUserRep.CurrentRollbackTran(); throw; } } /// /// 更新用户 /// /// /// [HttpPost("/sysUser/edit")] public async Task UpdateUser(UpdateUserInput input) { // 数据范围检查 CheckDataScopeByUserId(input.Id); // 排除自己并且判断与其他是否相同 var isExist = await _sysUserRep.AnyAsync(u => u.Account == input.Account && u.Id != input.Id); if (isExist) throw Oops.Oh(ErrorCode.D1003); var user = input.Adapt(); try { _sysUserRep.CurrentBeginTran(); await _sysUserRep.AsUpdateable(user).IgnoreColumns(it => new { it.Password, it.Status, it.AdminType, it.TenantId }).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync(); input.SysEmpParam.Id = user.Id.ToString(); // 更新员工及附属机构职位信息 await _sysEmpService.AddOrUpdate(input.SysEmpParam); _sysUserRep.CurrentCommitTran(); await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_USERSDATASCOPE); } catch (Exception) { _sysUserRep.CurrentRollbackTran(); throw; } } /// /// 查看用户 /// /// /// [HttpGet("/sysUser/detail")] public async Task GetUser([FromQuery] QueryUserInput input) { var user = await _sysUserRep.FirstOrDefaultAsync(u => u.Id == input.Id); var userDto = user.Adapt(); if (userDto != null) { userDto.SysEmpInfo = await _sysEmpService.GetEmpInfo(user.Id); } return userDto; } /// /// 修改用户状态 /// /// /// [HttpPost("/sysUser/changeStatus")] public async Task ChangeUserStatus(UpdateUserInput input) { var user = await _sysUserRep.FirstOrDefaultAsync(u => u.Id == input.Id); if (user.AdminType == AdminType.SuperAdmin) throw Oops.Oh(ErrorCode.D1015); if (!Enum.IsDefined(typeof(CommonStatus), input.Status)) throw Oops.Oh(ErrorCode.D3005); user.Status = input.Status; await _sysUserRep.AsUpdateable(user).ExecuteCommandAsync(); } /// /// 授权用户角色 /// /// /// [HttpPost("/sysUser/grantRole")] public async Task GrantUserRole(UpdateUserInput input) { // 数据范围检查 CheckDataScopeByUserId(input.Id); await _sysUserRoleService.GrantRole(input); } /// /// 授权用户数据范围 /// /// /// [HttpPost("/sysUser/grantData")] public async Task GrantUserData(UpdateUserInput input) { // 清除缓存 await _sysCacheService.DelAsync(CommonConst.CACHE_KEY_DATASCOPE + $"{input.Id}"); await _sysCacheService.DelAsync(CommonConst.CACHE_KEY_USERSDATASCOPE + $"{input.Id}"); // 数据范围检查 CheckDataScopeByUserId(input.Id); await _sysUserDataScopeService.GrantData(input); await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_USERSDATASCOPE); await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_DATASCOPE); } /// /// 更新用户信息 /// /// /// [HttpPost("/sysUser/updateInfo")] public async Task UpdateUserInfo(UpdateUserInput input) { var user = input.Adapt(); await _sysUserRep.AsUpdateable(user) .IgnoreColumns(it => new { it.AdminType, it.LastLoginTime, it.TenantId, it.CreatedUserId, it.DjyUserId, it.Account, it.Password, it.Status, it.IsDeleted, it.Name }) .ExecuteCommandAsync(); await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_USERSDATASCOPE); } /// /// 修改用户密码 /// /// /// [HttpPost("/sysUser/updatePwd")] public async Task UpdateUserPwd(ChangePasswordUserInput input) { var keyDES = App.GetOptions().DES; var user = await _sysUserRep.FirstOrDefaultAsync(u => u.Id == input.Id); if (DESCEncryption.Encrypt(input.Password, keyDES) != user.Password) throw Oops.Oh(ErrorCode.D1004); if (!PasswordCheckHelper.Check(input.NewPassword)) { throw Oops.Oh("密码强度不符合要求:需要8位以上的字母+数字+特殊符号"); } user.Password = DESCEncryption.Encrypt(input.NewPassword, keyDES); user.LastModifyPassword = DateTime.Now; await _sysUserRep.AsUpdateable(user).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync(); } /// /// 获取用户拥有角色 /// /// /// [HttpGet("/sysUser/ownRole")] public async Task GetUserOwnRole([FromQuery] QueryUserInput input) { return await _sysUserRoleService.GetUserRoleIdList(input.Id); } /// /// 获取用户拥有数据 /// /// /// [HttpGet("/sysUser/ownData")] public async Task GetUserOwnData([FromQuery] QueryUserInput input) { return await _sysUserDataScopeService.GetUserDataScopeIdList(input.Id); } /// /// 重置用户密码 /// /// /// [HttpPost("/sysUser/resetPwd")] public async Task ResetUserPwd(ResetPasswordUserInput input) { var keyDES = App.GetOptions().DES; var user = await _sysUserRep.FirstOrDefaultAsync(u => u.Id == input.Id); user.Password = DESCEncryption.Encrypt(input.NewPassword, keyDES); user.LastLoginTime = DateTime.Today.AddYears(-1); //让密码过期,需要用户登录时重新修改密码 await _sysUserRep.AsUpdateable(user).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync(); } /// /// 修改用户头像 /// /// /// [HttpPost("/sysUser/updateAvatar")] public async Task UpdateAvatar(UploadAvatarInput input) { var user = await _sysUserRep.FirstOrDefaultAsync(u => u.Id == input.Id); user.Avatar = input.Avatar.ToString(); await _sysUserRep.AsUpdateable(user).IgnoreColumns(it => new { it.AdminType }).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync(); } /// /// 获取用户选择器 /// /// /// [HttpGet("/sysUser/selector")] public async Task GetUserSelector([FromQuery] UserInput input) { return await _sysUserRep.AsQueryable() .WhereIF(!string.IsNullOrWhiteSpace(input.Name), u => (u.Name.Contains(input.Name.Trim()))) .Where(u => u.Status != CommonStatus.DELETED) .Where(u => u.AdminType != AdminType.SuperAdmin) .Select(u => new { u.Id, u.Name }).ToListAsync(); } /// /// 用户导出 /// /// [HttpGet("/sysUser/export")] public async Task ExportUser() { var excelwork = new HSSFWorkbook(); var sheet = excelwork.CreateSheet(); var fileName = string.Empty; //创建第一行表头 var srow = NpoiExcelExportHelper._.CreateRow(sheet, 0); srow.CreateCell(0).SetCellValue("账号"); srow.CreateCell(1).SetCellValue("姓名"); srow.CreateCell(2).SetCellValue("性别"); srow.CreateCell(3).SetCellValue("手机"); srow.CreateCell(4).SetCellValue("状态"); srow.CreateCell(5).SetCellValue("邮件"); var users = await _sysUserRep.AsQueryable().Filter(null, true).Where(x => x.TenantId == UserManager.TENANT_ID && x.IsDeleted == false).ToListAsync(); int i = 1; foreach (var item in users) { var row = NpoiExcelExportHelper._.CreateRow(sheet, i); row.CreateCell(0).SetCellValue(item.Account); row.CreateCell(1).SetCellValue(item.Name); row.CreateCell(2).SetCellValue(item.Sex == Gender.MALE ? "男" : item.Sex == Gender.FEMALE ? "女" : "未知"); row.CreateCell(3).SetCellValue(item.Phone); row.CreateCell(4).SetCellValue(item.Status == CommonStatus.ENABLE ? "正常" : item.Status == CommonStatus.DISABLE ? "停用" : "删除"); row.CreateCell(5).SetCellValue(item.Email); i++; } var fileFullPath = Path.Combine(App.WebHostEnvironment.WebRootPath, App.GetOptions().Path);//服务器路径 if (!Directory.Exists(fileFullPath)) { Directory.CreateDirectory(fileFullPath); } fileName = $"{UserManager.TENANT_NAME}_{DateTime.Now.Ticks}" + ".xls";//名称 var filestream = new FileStream(Path.Combine(fileFullPath, fileName), FileMode.OpenOrCreate, FileAccess.ReadWrite); excelwork.Write(filestream); filestream.Close(); filestream.Dispose(); var result = new FileStreamResult(new FileStream(Path.Combine(fileFullPath, fileName), FileMode.Open), "application/octet-stream") { FileDownloadName = fileName }; return result; } /// 用户导入 /// /// /// [HttpPost("/sysUser/import")] public async Task ImportUser(IFormFile file) { var path = Path.Combine(Path.GetTempPath(), $"{YitIdHelper.NextId()}.xlsx"); using (var stream = File.Create(path)) { await file.CopyToAsync(stream); } throw Oops.Oh("请自行完善入库操作"); //var rows = MiniExcel.Query(path); // 解析 //foreach (var row in rows) //{ // var a = row.A; // var b = row.B; // // 入库等操作 //} } /// /// 根据用户Id获取用户 /// /// /// [NonAction] public async Task GetUserById(long userId) { return await _sysUserRep.FirstOrDefaultAsync(u => u.Id == userId); } /// /// 将OAuth账号转换成账号 /// /// /// /// [NonAction] public async Task SaveAuthUserToUser(AuthUserInput authUser, UserInput sysUser) { var user = sysUser.Adapt(); user.AdminType = AdminType.None; // 非管理员 // oauth账号与系统账号判断 var isExist = await _sysUserRep.AnyAsync(u => u.Account == authUser.Username); user.Account = isExist ? authUser.Username + DateTime.Now.Ticks : authUser.Username; user.Name = user.NickName = authUser.Nickname; user.Email = authUser.Email; user.Sex = authUser.Gender; await _sysUserRep.InsertAsync(user); } /// /// 获取用户数据范围(机构Id集合)并缓存 /// /// /// [NonAction] public async Task> GetUserDataScopeIdList(long userId = 0) { userId = userId <= 0 ? UserManager.UserId : userId; var dataScopes = await _sysCacheService.GetDataScope(userId); // 先从缓存里面读取 if (dataScopes == null || dataScopes.Count < 1) { if (!UserManager.IsSuperAdmin && !UserManager.IsTenantAdmin) { var orgId = await _sysEmpService.GetEmpOrgId(userId); // 获取该用户对应的数据范围集合 var userDataScopeIdListForUser = await _sysUserDataScopeService.GetUserDataScopeIdList(userId); // 获取该用户的角色对应的数据范围集合 var userDataScopeIdListForRole = await _sysUserRoleService.GetUserRoleDataScopeIdList(userId, orgId); dataScopes = userDataScopeIdListForUser.Concat(userDataScopeIdListForRole).Distinct().ToList(); // 并集 } else { dataScopes = await _sysUserRep.Change().AsQueryable().Select(u => u.Id).ToListAsync(); } await _sysCacheService.SetDataScope(userId, dataScopes); // 缓存结果 } return dataScopes; } /// /// 检查普通用户数据范围 /// /// /// [NonAction] public async void CheckDataScope(long orgId) { // 如果当前用户不是超级管理员,则进行数据范围校验 if (!UserManager.IsSuperAdmin) { var dataScopes = await GetUserDataScopeIdList(UserManager.UserId); if (dataScopes == null || orgId <= 0 || !dataScopes.Contains(orgId)) throw Oops.Oh(ErrorCode.D1013); } } /// /// 获取用户数据范围(用户Id集合) /// /// [NonAction] public async Task> GetDataScopeIdUserList(long userId = 0) { userId = userId <= 0 ? UserManager.UserId : userId; var list = await _sysCacheService.GetUsersDataScope(userId); // 先从缓存里面读取 if (list == null || list.Count < 1) { var dataScopes = await GetUserDataScopeIdList(userId); list = (await _sysEmpService.HasOrgEmp(dataScopes)).Select(a => a.Id).ToList(); list.Add(userId); list = list.Distinct().ToList(); await _sysCacheService.SetUsersDataScope(userId, list); // 缓存结果 } return list; } /// /// 检查普通用户数据范围 /// /// /// [NonAction] public async void CheckDataScopeByUserId(long userId) { // 如果当前用户不是超级管理员,则进行数据范围校验 if (!UserManager.IsSuperAdmin) { var dataScopes = await GetDataScopeIdUserList(UserManager.UserId); if (dataScopes == null || userId <= 0 || !dataScopes.Contains(userId)) throw Oops.Oh(ErrorCode.D1013); } } /// /// 获取租户下的用户 /// /// 用户的代码、英文名或中文名 /// 默认0 获取当前用户,可不传 传租户id获取当前租户 /// [HttpGet("/sysUser/GetTenantUser")] public async Task> GetTenantUser(string name, long? tenantId = 0) { return await _sysUserRep.AsQueryable().Filter(null, true) .WhereIF(!string.IsNullOrWhiteSpace(name), x => x.UserCode.Contains(name) || x.EnName.Contains(name) || x.Name.Contains(name)) .WhereIF(tenantId == 0, x => x.TenantId == Convert.ToInt64(UserManager.TENANT_ID) && x.Status == CommonStatus.ENABLE && x.IsDeleted == false) .WhereIF(tenantId != 0, x => x.TenantId == tenantId) .OrderBy(x => x.Name).ToListAsync(); } [HttpGet("/sysUser/DecryptPassword")] public async Task DecryptPassword(long id) { if (UserManager.IsSuperAdmin) { var user = await _sysUserRep.AsQueryable().Filter(null, false).FirstAsync(u => u.Id == id); var keyDES = App.GetOptions().DES; var pwdDecrypt = DESCEncryption.Decrypt(user.Password, keyDES); return pwdDecrypt; } throw Oops.Bah("没有权限"); } /// /// 通过职位获取用户信息 /// /// /// 职位代码 PCDD-调度 /// 返回用户详情 [HttpGet("/sysUser/QueryUserByPos")] public async Task> QueryUserByPos([FromQuery] string name, [FromQuery] string pos) { if (string.IsNullOrWhiteSpace(pos)) Oops.Oh("没有权限"); var allList = await _sysEmpPosService.GetAllEmpByPos(new List { pos }); if (allList.Count > 0 && !string.IsNullOrWhiteSpace(name)) { allList = allList.Where(a => a.SysEmpName.Contains(name.Trim())).ToList(); } return allList; } /// /// 公司用户信息同步 /// /// [HttpPost("/sysUser/CompanyUserSync"), AllowAnonymous, ApiUser(ApiCode = "CompanyUserSync")] public async Task CompanyUserSync(MyshippingCompanyUserSyncDto dto) { if (dto.Type != "CompanyUserSync") { throw Oops.Bah($"类型有误:{dto.Type}"); } if (string.IsNullOrEmpty(dto.Company.CompId) || string.IsNullOrEmpty(dto.Company.CompName) || string.IsNullOrEmpty(dto.Company.AdminUser) || string.IsNullOrEmpty(dto.Company.AdminShowName) || string.IsNullOrEmpty(dto.Company.AdminUserEmail) || string.IsNullOrEmpty(dto.Company.AdminUserMobile) || string.IsNullOrEmpty(dto.Company.CompId)) { throw Oops.Bah($"公司信息不全。公司ID、名称、管理员ID、名称、手机、邮箱都不能为空"); } var cc = dto.Users.Where(x => string.IsNullOrEmpty(x.GID) || string.IsNullOrEmpty(x.CODENAME) || string.IsNullOrEmpty(x.SHOWNAME) || string.IsNullOrEmpty(x.EMAIL1) || string.IsNullOrEmpty(x.MOBILE)) .Count(); if (cc > 0) { throw Oops.Bah($"用户信息不全。用户ID、姓名、登录名、密码、手机、邮箱都不能为空"); } await _publisher.PublishAsync(new ChannelEventSource("CompanyUserSync:CompanyUser", dto.ToJsonString())); } /// /// 用户离职信息同步 /// /// [HttpPost("/sysUser/UserLeave"), AllowAnonymous, ApiUser(ApiCode = "CompanyUserSync")] public async Task UserLeave(MyshippingUserLeaveSyncDto dto) { if (dto.Type != "UserLeave") { throw Oops.Bah($"类型有误:{dto.Type}"); } if (string.IsNullOrEmpty(dto.CompId) || string.IsNullOrEmpty(dto.UserId)) { throw Oops.Bah($"信息不全。公司ID、用户ID都不能为空"); } await _publisher.PublishAsync(new ChannelEventSource("CompanyUserSync:UserLeave", dto.ToJsonString())); } }