using Furion.DatabaseAccessor; using Furion.DataEncryption; using Furion.DependencyInjection; using Furion.DynamicApiController; using Furion.FriendlyException; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Newtonsoft.Json; using Senparc.Weixin.WxOpen.Helpers; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Threading.Tasks; using Znyc.Dispatching.Application.Dto.Input; using Znyc.Dispatching.Core; using Znyc.Dispatching.Core.Entitys; using Znyc.Dispatching.Core.Extension; using Znyc.Dispatching.WeChat.Core.CommonService.TemplateMessage.WxOpen; namespace Znyc.Dispatching.Application { /// /// 用户服务 /// [ApiDescriptionSettings(Name = "user", Order = 10)] public class UserService : IUserService, IDynamicApiController, ITransient { private readonly ICacheService _cacheService; private readonly SmsProviderOptions _smsProviderOptions; private readonly IUserManager _userManager; private readonly WeixinSettingOptions _weixinSettingOptions; private readonly IWxUserRelationService _wxUserRelationService; private readonly IRoleMenuService _roleMenuService; private readonly ILogger _logger; private readonly IRepository _repository; private readonly IRepository _companyRepository; private readonly IRepository _employeeRepository; private readonly IRepository _userRoleRepository; private readonly IRepository _vehiclePersonRepository; private readonly IRepository workPlaceRepository; private readonly IRepository _projectPersonRepository; private readonly IRepository wrokPlaceEmployee; public UserService( IUserManager userManager, ICacheService cacheService, IRepository companyRepository, IRepository repository, IRepository employeeRepository, IRepository userRoleRepository, IOptions smsProviderOptions, IWxUserRelationService wxUserRelationService, IRoleMenuService roleMenuService, IOptions weixinSettingOptions, ILogger logger, IRepository vehiclePersonRepository, IRepository workPlaceRepository, IRepository wrokPlaceEmployee, IRepository projectPersonRepository) { _repository = repository; _userManager = userManager; _cacheService = cacheService; _companyRepository = companyRepository; _employeeRepository = employeeRepository; _smsProviderOptions = smsProviderOptions.Value; _weixinSettingOptions = weixinSettingOptions.Value; _userRoleRepository = userRoleRepository; _wxUserRelationService = wxUserRelationService; _roleMenuService = roleMenuService; _logger = logger; _vehiclePersonRepository = vehiclePersonRepository; _projectPersonRepository = projectPersonRepository; this.workPlaceRepository = workPlaceRepository; this.wrokPlaceEmployee = wrokPlaceEmployee; } /// /// 个人资料 /// /// [HttpGet] [Route("api/v1/user")] public async Task GetUserAsync() { var userOutput = await _cacheService.GetUserAsync(_userManager.UserId); if (userOutput.IsNull()) { var user = await _repository.Where(x => x.Id == _userManager.UserId).Select(x => new { x.Id, x.UserName, x.Phone, x.AvatarUrl }).FirstOrDefaultAsync(); var employeeList = await _employeeRepository.Where(x => x.UserId == user.Id && x.Status == (int)CommonStatusEnum.ENABLE).ToListAsync(); var cIds = employeeList.Select(x => x.CompanyId).ToArray(); //有管理员优先登陆管理员 if (employeeList.Any(x => x.RoleId == (int)RoleStatusEnum.Administrator)) { cIds = employeeList.Where(x => x.RoleId == (long)RoleStatusEnum.Administrator).Select(x => x.CompanyId).ToArray(); } var company = await _companyRepository.Where(x => cIds.Contains(x.Id) && x.Status == (int)CommonStatusEnum.ENABLE).Select(x => new { x.Id, x.CompanyName }).FirstOrDefaultAsync(); var employee = employeeList.Where(x => x.CompanyId == company.Id).Select(x => new { x.RoleId, x.RoleName, x.CompanyId, x.UserId, x.EmployeeName, x.IsDefault }).FirstOrDefault(); userOutput = new UserOutput { Id = user.Id, AvatarUrl = user.AvatarUrl, UserName = employee.EmployeeName, RoleId = employee.RoleId, RoleName = employee.RoleName, CompanyId = employee.CompanyId, CompanyName = company.CompanyName, Phone = user.Phone }; await _cacheService.SetUserAsync(userOutput); } return userOutput; } /// /// 邀请用户注册并登陆 /// /// /// [HttpPost] [AllowAnonymous] [UnitOfWork] [Route("api/v1/user/register")] public async Task RegisterUserAsync(UserAddInput input) { User userEntity = new User(); var jsCode2JsonResult = await SnsApi.JsCode2JsonAsync(_weixinSettingOptions.WxOpenAppId, _weixinSettingOptions.WxOpenAppSecret, input.DecryptPhoneAddInput.JsCode); if (jsCode2JsonResult.IsNull()) { throw Oops.Bah("jsCode2JsonResult为空"); } var company = await _companyRepository.FindOrDefaultAsync(input.CompanyId); if (company.IsNull()) throw Oops.Bah("公司不存在"); if (company.Status == (int)CommonStatusEnum.REVIEW) { throw Oops.Bah("您注册公司正在审核中,请稍等").StatusCode(4012); } if (company.Status == (int)CommonStatusEnum.DISABLE) { throw Oops.Bah("公司已被停用,请联系管理员"); } var user = await _repository.FirstOrDefaultAsync(x => x.OpenId == jsCode2JsonResult.openid); var employee = new Employee(); if (user.IsNull()) { //解密电话 string phone = " "; if (input.DecryptPhoneAddInput.EncryptedData.IsNotNull() && input.DecryptPhoneAddInput.Iv.IsNotNull()) { try { var rijndael = new RijndaelManaged { BlockSize = 128, Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 }; var encryptedData = Convert.FromBase64String(input.DecryptPhoneAddInput.EncryptedData); var key = Convert.FromBase64String(jsCode2JsonResult.session_key);//第一步获取到的session_key var iv = Convert.FromBase64String(input.DecryptPhoneAddInput.Iv); var decryptor = rijndael.CreateDecryptor(key, iv); using (var msDecrypt = new MemoryStream(encryptedData)) { using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) { using (var srDecrypt = new StreamReader(csDecrypt)) { var plaintext = srDecrypt.ReadToEnd(); var json = Newtonsoft.Json.JsonConvert.DeserializeObject(plaintext); var phoneNumber = json.phoneNumber; var purePhoneNumber = json.purePhoneNumber; //至此,成功获取到手机号 phone = Convert.ToString(purePhoneNumber); } } } } catch (Exception ex) { Console.WriteLine($"RegisterUserAsync:{ex.Message}"); _logger.LogError(ex.StackTrace); } } //用户 var userEntityTask = await _repository.InsertNowAsync(new User { OpenId = jsCode2JsonResult.openid, UserName = input.UserName, AvatarUrl = input.AvatarUrl, Phone = phone, Status = CommonStatusEnum.ENABLE }); userEntity = userEntityTask.Entity; var isDefault = input.RoleId == (int)RoleStatusEnum.Outside ? false : true; //员工 var employeeEntity = await _employeeRepository.InsertNowAsync(new Employee { UserId = userEntity.Id, AvatarUrl = input.AvatarUrl, EmployeeName = input.UserName, EmployeePhone = phone, CompanyId = input.CompanyId, RoleId = input.RoleId, RoleName = typeof(RoleStatusEnum).GetDescription(input.RoleId.ObjToInt()), IsDefault = isDefault, Status = (int)CommonStatusEnum.ENABLE }); //清除员工列表Cache await _cacheService.RemoveEmployeeListAsync(input.CompanyId); //用户中间表 await _wxUserRelationService.AddOrUpdateAsync(userEntity.Id, jsCode2JsonResult.openid, jsCode2JsonResult.unionid); user = userEntity; employee = employeeEntity.Entity; } else { userEntity = user; employee = await _employeeRepository.Where(x => x.UserId == userEntity.Id && x.Status == (int)CommonStatusEnum.ENABLE && x.CompanyId == input.CompanyId).FirstOrDefaultAsync(); if (employee.IsNull()) { var employeenew = new Employee { UserId = userEntity.Id, AvatarUrl = input.AvatarUrl, EmployeeName = input.UserName, EmployeePhone = userEntity.Phone, CompanyId = input.CompanyId, RoleId = input.RoleId, RoleName = typeof(RoleStatusEnum).GetDescription((int)input.RoleId), IsDefault = true, Status = (int)CommonStatusEnum.ENABLE }; Console.WriteLine($"{JsonConvert.SerializeObject(employeenew)}"); var isDefault = input.RoleId == (int)RoleStatusEnum.Outside ? false : true; //员工 var employeeEntity = await _employeeRepository.InsertNowAsync(new Employee { UserId = userEntity.Id, AvatarUrl = input.AvatarUrl, EmployeeName = input.UserName, EmployeePhone = userEntity.Phone, CompanyId = input.CompanyId, RoleId = input.RoleId, RoleName = typeof(RoleStatusEnum).GetDescription(input.RoleId.ObjToInt()), IsDefault = isDefault, Status = (int)CommonStatusEnum.ENABLE }); employee = employeeEntity.Entity; company = new Company() { Id = input.CompanyId }; } } // 工地方 if(input.RoleId == 1009) { await this.wrokPlaceEmployee.InsertAsync(new WorkPlaceEmployee() { UserId = userEntity.Id, CreatedTime = DateTime.Now, IsDeleted= false, }); } // 生成 token string accessToken = JWTEncryption.Encrypt(new Dictionary { {ClaimConst.CLAINM_USERID, user.Id}, {ClaimConst.CLAINM_COMPANYID, company.Id}, {ClaimConst.CLAINM_ROLEID, employee.RoleId}, {ClaimConst.CLAINM_USERNAME, user.UserName}, {ClaimConst.CLAINM_SUPERADMIN,new long[] { (long)RoleStatusEnum.Administrator, (long)RoleStatusEnum.Scheduling,(long)RoleStatusEnum.CarCaptain }.Contains(employee.RoleId) } }); //RedisToken await _cacheService.SetTokenAsync(user.Id, accessToken); await _cacheService.RemoveEmployeeListAsync(input.CompanyId); LoginOutput loginOutput = new LoginOutput() { Token = accessToken, Menus = await _roleMenuService.GetRoleMenuListByIdAsync(employee.RoleId) }; switch (employee.RoleId) { case (long)RoleStatusEnum.Administrator: case (long)RoleStatusEnum.Scheduling: case (long)RoleStatusEnum.CarCaptain: case (long)RoleStatusEnum.Salesman: case (long)RoleStatusEnum.Financial: case (long)RoleStatusEnum.WareHouse: case (long)RoleStatusEnum.PartTimeSalesman: loginOutput.Url = CommonConst.DEFAULT_SUPERADMIN_INDEX; break; case (long)RoleStatusEnum.CrewMembers: case (long)RoleStatusEnum.ProjectPerson: loginOutput.Url = CommonConst.DEFAULT_DRIVER_INDEX; break; case (long)RoleStatusEnum.Outside: loginOutput.Url = CommonConst.DEFAULT_OUTSIDE_INDEX; break; default: loginOutput.Url = CommonConst.DEFAULT_DRIVER_INDEX; break; } return loginOutput; } /// /// 修改用户信息 /// /// /// [HttpPut] [Route("api/v1/user")] public async Task UpdateAsync(UserUpdateInput input) { var user = await _repository.FirstOrDefaultAsync(x => x.Id == input.Id); if (user.IsNull()) { throw Oops.Oh("用户不存在"); } var repeatPhone = await _repository.DetachedEntities.FirstOrDefaultAsync(x => x.Id != input.Id && x.Phone == input.Phone); if (repeatPhone.IsNotNull()) { throw Oops.Bah("电话已存在"); } user.Phone = input.Phone; user.UserName = input.UserName; user.AvatarUrl = CommonConst.Prefix_AvataUrl + input.AvatarUrl[(input.AvatarUrl.LastIndexOf("/") + 1)..]; await _repository.UpdateNowAsync(user); //更新当前用户下所有角色姓名 var employees =await _employeeRepository.Where(x => x.UserId == user.Id).ToListAsync(); foreach (var employee in employees) { if (employee.IsNotNull()) { employee.EmployeePhone = input.Phone; employee.EmployeeName = input.UserName; employee.AvatarUrl = CommonConst.Prefix_AvataUrl + input.AvatarUrl[(input.AvatarUrl.LastIndexOf("/") + 1)..]; await _employeeRepository.UpdateNowAsync(employee); await _cacheService.RemoveEmployeeAsync(employee.Id); await _cacheService.RemoveEmployeeListAsync(employee.CompanyId); } } await _cacheService.RemoveUserAsync(user.Id); //同步车组人员表 var vehiclePersons = await _vehiclePersonRepository.Where(x => x.IsDeleted == false && x.UserId == input.Id).ToListAsync(); foreach (var item in vehiclePersons) { item.UserName = input.UserName; item.UserPhone = input.Phone; await _vehiclePersonRepository.UpdateNowAsync(item); //删除车组人员Cache await _cacheService.RemoveVehiclePersonAsync(item.VehicleId); } //同步工程联系人表 var projectPersons = await _projectPersonRepository.Where(x => x.IsDeleted == false && x.ProjectPersonId == input.Id).ToListAsync(); foreach (var item in projectPersons) { item.ProjectPersonName = input.UserName; item.ProjectPersonPhone = input.Phone; await _projectPersonRepository.UpdateNowAsync(item); //清除工程信息Cache await _cacheService.RemoveProjectAsync(item.ProjectId); //清除工程列表信息Cache await _cacheService.RemoveProjectListAsync(_userManager.CompanyId); } } /// /// 更新用户信息 /// /// /// /// [HttpPut] [AllowAnonymous] public async Task UpdateAsync(string openId, string account) { //var user = await _repository.FirstOrDefaultAsync(x => x.Account == account); //if (user.IsNotNull()) //{ // user.OpenId = openId; // await _repository.UpdateNowAsync(user); //} } /// /// 解密电话号码 /// /// /// [HttpPost] [AllowAnonymous] [Route("api/v1/decryptphone")] public async Task DecryptPhoneNumber([FromBody] DecryptPhoneAddInput decryptPhone) { var jsCode2JsonResult = await SnsApi.JsCode2JsonAsync(_weixinSettingOptions.WxOpenAppId, _weixinSettingOptions.WxOpenAppSecret, decryptPhone.JsCode); if (jsCode2JsonResult.IsNull()) { throw Oops.Oh("jsCode2JsonResult为空!"); } string phone = ""; if (decryptPhone.EncryptedData.IsNotNull() && decryptPhone.Iv.IsNotNull()) { var phoneNumber = EncryptHelper.DecryptPhoneNumberBySessionKey(jsCode2JsonResult.session_key, decryptPhone.EncryptedData, decryptPhone.Iv); if (phoneNumber.IsNull()) { phone = phoneNumber.purePhoneNumber; } } return phone; } } }