You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

472 lines
20 KiB

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
{
/// <summary>
/// 用户服务
/// </summary>
[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<UserService> _logger;
private readonly IRepository<User> _repository;
private readonly IRepository<Company> _companyRepository;
private readonly IRepository<Employee> _employeeRepository;
private readonly IRepository<UserRole> _userRoleRepository;
private readonly IRepository<VehiclePerson> _vehiclePersonRepository;
private readonly IRepository<WorkPlace> workPlaceRepository;
private readonly IRepository<ProjectPerson> _projectPersonRepository;
private readonly IRepository<WorkPlaceEmployee> wrokPlaceEmployee;
public UserService(
IUserManager userManager,
ICacheService cacheService,
IRepository<Company> companyRepository,
IRepository<User> repository,
IRepository<Employee> employeeRepository,
IRepository<UserRole> userRoleRepository,
IOptions<SmsProviderOptions> smsProviderOptions,
IWxUserRelationService wxUserRelationService,
IRoleMenuService roleMenuService,
IOptions<WeixinSettingOptions> weixinSettingOptions,
ILogger<UserService> logger,
IRepository<VehiclePerson> vehiclePersonRepository,
IRepository<WorkPlace> workPlaceRepository,
IRepository<WorkPlaceEmployee> wrokPlaceEmployee,
IRepository<ProjectPerson> 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;
}
/// <summary>
/// 个人资料
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("api/v1/user")]
public async Task<UserOutput> 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;
}
/// <summary>
/// 邀请用户注册并登陆
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost]
[AllowAnonymous]
[UnitOfWork]
[Route("api/v1/user/register")]
public async Task<LoginOutput> 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<dynamic>(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<string, object>
{
{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;
}
/// <summary>
/// 修改用户信息
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[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);
}
}
/// <summary>
/// 更新用户信息
/// </summary>
/// <param name="openId"></param>
/// <param name="account"></param>
/// <returns></returns>
[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);
//}
}
/// <summary>
/// 解密电话号码
/// </summary>
/// <param name="decryptPhone"></param>
/// <returns></returns>
[HttpPost]
[AllowAnonymous]
[Route("api/v1/decryptphone")]
public async Task<string> 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;
}
}
}