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
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;
|
|
}
|
|
}
|
|
}
|