| | |
| | | using FlexJobApi.Core; |
| | | using FlexJobApi.Core.Models.ElectronSignServer.Common; |
| | | using FlexJobApi.Core.Models.ElectronSignServer.Contracts; |
| | | using FlexJobApi.Core.Models.ElectronSignServer.PersonalUserReals; |
| | | using FlexJobApi.Core.Models.ElectronSignServer.Users; |
| | | using Furion; |
| | | using Furion.DatabaseAccessor; |
| | | using Furion.DataValidation; |
| | | using Furion.DistributedIDGenerator; |
| | | using Furion.FriendlyException; |
| | | using Furion.HttpRemote; |
| | | using Mapster; |
| | | using MediatR; |
| | | using Microsoft.AspNetCore.Components.Forms; |
| | | using Microsoft.EntityFrameworkCore; |
| | | using MiniExcelLibs; |
| | | using NetTopologySuite.Index.HPRtree; |
| | |
| | | using System.Text; |
| | | using System.Text.RegularExpressions; |
| | | using System.Threading.Tasks; |
| | | using static System.Runtime.InteropServices.JavaScript.JSType; |
| | | |
| | | namespace FlexJobApi.UserServer.Application |
| | | { |
| | |
| | | /// 灵工命令处理器 |
| | | /// </summary> |
| | | public class EnterpriseEmployeesCommandHandler( |
| | | IRepository<EnterpriseEmployee> rep |
| | | SmsUtils smsUtils, |
| | | WxmpUtils wxmpUtils, |
| | | IMediator mediator, |
| | | IRepository<EnterpriseEmployee> rep, |
| | | IRepository<User> repUser, |
| | | IRepository<Enterprise> repEnterprise, |
| | | IRepository<EnterpriseEmployeeContract> repEnterpriseEmployeeContract, |
| | | IRepository<ElectronSignSetting> repElectronSignSetting, |
| | | IRepository<ContractTemplate> repContractTemplate, |
| | | IRepository<EnterpriseCost> repEnterpriseCost, |
| | | IRepository<TaskInfoUser> repTaskInfoUser, |
| | | IRepository<CodeUrl> repCodeUrl |
| | | ) : |
| | | IRequestHandler<ImportEnterpriseEmployeesCommand, ImportEnterpriseEmployeesCommandResult>, |
| | | IRequestHandler<EditEnterpriseEmployeeCommand, Guid> |
| | | IRequestHandler<EditEnterpriseEmployeeCommand, Guid>, |
| | | IRequestHandler<InviteElectronSignCommand, int>, |
| | | IRequestHandler<PersonalUserElectronSignCommand, PersonalUserElectronSignCommandResult>, |
| | | IRequestHandler<EnterpriseUserElectronSignCommand, EnterpriseUserElectronSignCommandResult>, |
| | | IRequestHandler<StopElectronSignCommand, int>, |
| | | IRequestHandler<SendInviteElectronSignSmsCommand, int> |
| | | { |
| | | private readonly SmsUtils smsUtils = smsUtils; |
| | | private readonly WxmpUtils wxmpUtils = wxmpUtils; |
| | | private readonly IMediator mediator = mediator; |
| | | private readonly IRepository<EnterpriseEmployee> rep = rep; |
| | | private readonly IRepository<User> repUser = repUser; |
| | | private readonly IRepository<Enterprise> repEnterprise = repEnterprise; |
| | | private readonly IRepository<EnterpriseEmployeeContract> repEnterpriseEmployeeContract = repEnterpriseEmployeeContract; |
| | | private readonly IRepository<ElectronSignSetting> repElectronSignSetting = repElectronSignSetting; |
| | | private readonly IRepository<ContractTemplate> repContractTemplate = repContractTemplate; |
| | | private readonly IRepository<EnterpriseCost> repEnterpriseCost = repEnterpriseCost; |
| | | private readonly IRepository<TaskInfoUser> repTaskInfoUser = repTaskInfoUser; |
| | | private readonly IRepository<CodeUrl> repCodeUrl = repCodeUrl; |
| | | |
| | | /// <summary> |
| | | /// 导入灵工信息 |
| | |
| | | var identities = models.DistinctSelect(it => it.Identity); |
| | | var enterpriseEmployees = await rep.AsQueryable() |
| | | .Where(it => it.EnterpriseId == logier.EnterpriseId && identities.Contains(it.Identity)) |
| | | .ToListAsync(); |
| | | var userIds = enterpriseEmployees.DistinctSelect(it => it.UserId.HasValue, it => it.UserId!.Value); |
| | | var users = await repUser.AsQueryable() |
| | | .Where(it => userIds.Contains(it.Id)) |
| | | .ToListAsync(); |
| | | var successList = new List<ImportEnterpriseEmployeesCommandModel>(); |
| | | foreach (var model in models) |
| | |
| | | } |
| | | else |
| | | { |
| | | var canUpdate = true; |
| | | if (enterpriseEmployee.UserId.HasValue) |
| | | { |
| | | errors.Add("该灵工已报名无法修改信息"); |
| | | var user = users.FirstOrDefault(it => it.Id == enterpriseEmployee.UserId.Value)!; |
| | | if (user.IsReal == true) |
| | | { |
| | | canUpdate = false; |
| | | errors.Add("已实名无法修改信息"); |
| | | } |
| | | else |
| | | { |
| | | user.Name = model.Name; |
| | | user.ContactPhoneNumber = model.ContactPhoneNumber; |
| | | user.Identity = model.Identity; |
| | | user.Gender = model.Gender; |
| | | user.Birthday = model.Birthday; |
| | | user.Age = model.Age; |
| | | await repUser.UpdateAsync(user); |
| | | } |
| | | } |
| | | else |
| | | if (canUpdate) |
| | | { |
| | | enterpriseEmployee.Name = model.Name; |
| | | enterpriseEmployee.ContactPhoneNumber = model.ContactPhoneNumber; |
| | |
| | | } |
| | | } |
| | | } |
| | | if (errors.IsNotNull()) |
| | | else |
| | | { |
| | | var error = model.Adapt<ImportEnterpriseEmployeesCommandResultError>(); |
| | | error.ErrorMessage = errors.SplitJoin(","); |
| | |
| | | /// <param name="request"></param> |
| | | /// <param name="cancellationToken"></param> |
| | | /// <returns></returns> |
| | | public Task<Guid> Handle(EditEnterpriseEmployeeCommand request, CancellationToken cancellationToken) |
| | | public async Task<Guid> Handle(EditEnterpriseEmployeeCommand request, CancellationToken cancellationToken) |
| | | { |
| | | var logier = JwtUtils.GetCurrentLogier(); |
| | | return request.SaveData<EnterpriseEmployee, EditEnterpriseEmployeeCommand>( |
| | | var entity = await request.SaveData<EnterpriseEmployee, EditEnterpriseEmployeeCommand>( |
| | | q => q.Where(it => it.EnterpriseId == logier.EnterpriseId), |
| | | it => it.EnterpriseId == logier.EnterpriseId && it.Id != request.Id && it.Identity == request.Identity, |
| | | (entity) => |
| | | (entity) => |
| | | { |
| | | if (request.Id.HasValue && entity.UserId.HasValue) |
| | | { |
| | | throw Oops.Oh(EnumErrorCodeType.s510, "该灵工已报名无法修改信息"); |
| | | var user = repUser.AsQueryable().FirstOrDefault(it => it.Id == entity.UserId.Value); |
| | | if (user!.IsReal == true) |
| | | { |
| | | throw Oops.Oh(EnumErrorCodeType.s510, "已实名无法修改信息"); |
| | | } |
| | | else |
| | | { |
| | | user.Name = request.Name; |
| | | user.ContactPhoneNumber = request.ContactPhoneNumber; |
| | | user.Identity = request.Identity; |
| | | user.Birthday = request.Identity.GetBirthday(); |
| | | user.Gender = request.Gender; |
| | | user.Age = request.Age; |
| | | repUser.Update(user); |
| | | } |
| | | } |
| | | request.Adapt(entity); |
| | | }, |
| | | cancellationToken); |
| | | return entity.Id; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 邀请灵工签约 |
| | | /// </summary> |
| | | /// <param name="request"></param> |
| | | /// <param name="cancellationToken"></param> |
| | | /// <returns></returns> |
| | | public async Task<int> Handle(InviteElectronSignCommand request, CancellationToken cancellationToken) |
| | | { |
| | | var logier = JwtUtils.GetCurrentLogier(); |
| | | |
| | | await mediator.Send(new CheckContractTemplateCommand |
| | | { |
| | | Id = request.ContractTemplateId |
| | | }, cancellationToken); |
| | | |
| | | var entities = await rep.AsQueryable() |
| | | .Where(it => it.EnterpriseId == logier.EnterpriseId && request.Ids.Contains(it.Id)) |
| | | .ToListAsync(); |
| | | foreach (var id in request.Ids) |
| | | { |
| | | var entity = entities.FirstOrDefault(it => it.Id == id); |
| | | if (entity == null) throw Oops.Oh(EnumErrorCodeType.s404, "灵工"); |
| | | if (entity.UserSignContractStatus == EnumTaskUserSignContractStatus.Wait) throw Oops.Oh(EnumErrorCodeType.s400, $"已邀请{entity.Name}"); |
| | | if (entity.UserSignContractStatus == EnumTaskUserSignContractStatus.Pass) throw Oops.Oh(EnumErrorCodeType.s400, $"已签约{entity.Name}"); |
| | | entity.ContractTemplateId = request.ContractTemplateId; |
| | | entity.UserSignContractStatus = EnumTaskUserSignContractStatus.Wait; |
| | | entity.UserSignContractTime = null; |
| | | entity.EnterpriseSignContractStatus = null; |
| | | entity.EnterpriseSignContractTime = null; |
| | | entity.ContractCode = $"{DateTime.Now:yyyyMMddHHmmss}{new Random(IDGen.NextID().GetHashCode()).Next(1000, 9999)}"; |
| | | entity.ContractUrl = null; |
| | | var contract = new EnterpriseEmployeeContract |
| | | { |
| | | EnterpriseEmployeeId = entity.Id, |
| | | ContractTemplateId = entity.ContractTemplateId, |
| | | ContractCode = entity.ContractCode, |
| | | UserSignContractStatus = entity.UserSignContractStatus, |
| | | }; |
| | | await repEnterpriseEmployeeContract.InsertAsync(contract); |
| | | //await mediator.Send(new SaveEnterpriseCostCommand |
| | | //{ |
| | | // EnterpriseId = logier.EnterpriseId!.Value, |
| | | // ContractTemplateId = request.ContractTemplateId, |
| | | // EnterpriseEmployeeContractId = contract.Id, |
| | | // Type = EnumEnterpriseCostType.ElectronSign |
| | | //}); |
| | | await rep.UpdateAsync(entity); |
| | | } |
| | | return entities.Count; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 发送邀请签约短信 |
| | | /// </summary> |
| | | /// <param name="request"></param> |
| | | /// <param name="cancellationToken"></param> |
| | | /// <returns></returns> |
| | | public async Task<int> Handle(SendInviteElectronSignSmsCommand request, CancellationToken cancellationToken) |
| | | { |
| | | var logier = JwtUtils.GetCurrentLogier(); |
| | | var entities = await rep.AsQueryable() |
| | | .Include(it => it.Enterprise) |
| | | .Include(it => it.ContractTemplate) |
| | | .Where(it => |
| | | it.EnterpriseId == logier.EnterpriseId |
| | | && request.Ids.Contains(it.Id) |
| | | && it.UserSignContractStatus == EnumTaskUserSignContractStatus.Wait) |
| | | .ToListAsync(); |
| | | foreach (var entity in entities) |
| | | { |
| | | var codeUrl = new SaveCodeUrlCommand |
| | | { |
| | | Scene = EnumCodeUrlScene.InviteElectronSign, |
| | | ParamValue1 = entity.Id.ToString(), |
| | | ExpiredTime = DateTime.Now.AddMonths(1) |
| | | }; |
| | | var code = await mediator.Send(codeUrl); |
| | | await smsUtils.Send(new SendSmsModel |
| | | { |
| | | PhoneNumber = entity.ContactPhoneNumber, |
| | | TemplateCode = EnumSmsTemplateCode.InviteElectronSign, |
| | | }, |
| | | new |
| | | { |
| | | name = entity.Enterprise.EnterpriseName, |
| | | code = code |
| | | }); |
| | | } |
| | | return entities.Count; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 个人用户签约 |
| | | /// </summary> |
| | | /// <param name="request"></param> |
| | | /// <param name="cancellationToken"></param> |
| | | /// <returns></returns> |
| | | public async Task<PersonalUserElectronSignCommandResult> Handle(PersonalUserElectronSignCommand request, CancellationToken cancellationToken) |
| | | { |
| | | if (request.Id == null) |
| | | { |
| | | if (request.SmsCode.IsNotNull()) |
| | | { |
| | | var codeUrl = await mediator.Send(new GetCodeUrlQuery |
| | | { |
| | | Code = request.SmsCode, |
| | | Scene = EnumCodeUrlScene.InviteElectronSign |
| | | }); |
| | | request.Id = codeUrl.ParamValue1.ToGuid()!; |
| | | } |
| | | else |
| | | { |
| | | throw Oops.Oh(EnumErrorCodeType.s400, "请填写灵工Id或短信编号"); |
| | | } |
| | | } |
| | | var entity = await rep.AsQueryable() |
| | | .Include(it => it.Enterprise) |
| | | .Include(it => it.ContractTemplate).ThenInclude(it => it.Values) |
| | | .Where(it => it.Id == request.Id) |
| | | .FirstOrDefaultAsync(); |
| | | if (entity == null) throw Oops.Oh(EnumErrorCodeType.s510, "未报名该企业"); |
| | | if (entity.UserSignContractStatus == null) throw Oops.Oh(EnumErrorCodeType.s510, "企业未发起签约"); |
| | | if (entity.UserSignContractStatus == EnumTaskUserSignContractStatus.Pass) throw Oops.Oh(EnumErrorCodeType.s510, "已签约"); |
| | | if (entity.UserSignContractStatus == EnumTaskUserSignContractStatus.Refuse) throw Oops.Oh(EnumErrorCodeType.s510, "已拒签"); |
| | | if (entity.UserSignContractStatus == EnumTaskUserSignContractStatus.Stop) throw Oops.Oh(EnumErrorCodeType.s510, "已终止"); |
| | | var contract = await repEnterpriseEmployeeContract.AsQueryable() |
| | | .OrderByDescending(it => it.CreatedTime) |
| | | .Where(it => it.EnterpriseEmployeeId == request.Id) |
| | | .FirstOrDefaultAsync(); |
| | | if (contract == null) throw Oops.Oh(EnumErrorCodeType.s404, "合同"); |
| | | var user = await repUser.AsQueryable().AsNoTracking() |
| | | .Include(it => it.UserAuth) |
| | | .Where(it => it.Id == entity.UserId) |
| | | .FirstOrDefaultAsync(); |
| | | if (user == null) throw Oops.Oh(EnumErrorCodeType.s404, "用户"); |
| | | if (entity.ContractTemplate.Access == EnumElectronSignAccess.BestSign && !user.IsReal) throw Oops.Oh(EnumErrorCodeType.s510, "请先实名"); |
| | | var result = await new SendContractInput |
| | | { |
| | | OutContractId = contract.Id.ToString(), |
| | | TemplateId = entity.ContractTemplate.ElectronSignContractTemplateId!.Value, |
| | | Title = entity.ContractTemplate.Name, |
| | | OutUserId = entity.UserId.ToString(), |
| | | Values = entity.ContractTemplate.Values |
| | | .Where(it => it.UserType == EnumUserType.Personal) |
| | | .Select(it => |
| | | { |
| | | string? value = null; |
| | | switch (it.BindProperty) |
| | | { |
| | | case "Name": |
| | | value = user.UserAuth.Name; |
| | | break; |
| | | case "PhoneNumber": |
| | | value = user.ContactPhoneNumber; |
| | | break; |
| | | case "Identity": |
| | | value = user.UserAuth.Identity; |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | return new SendContractInputValue |
| | | { |
| | | Name = it.Name, |
| | | Value = value |
| | | }; |
| | | }) |
| | | .ToList(), |
| | | UserCount = 2 |
| | | }.SendHttpAsync<SendContractInput, ElectronSignServerResult<SendContractOutput>>(EnumResourceHttpProvider.ElectronSignServerCustomer); |
| | | if (result?.Success != true) |
| | | { |
| | | throw Oops.Oh(EnumErrorCodeType.s510, result?.Message ?? "签约失败"); |
| | | } |
| | | var model = result.Result.Adapt<PersonalUserElectronSignCommandResult>(); |
| | | model.SignContractLongUrl = model.SignContractLongUrl |
| | | .Replace("https://openapi.bestsign.info:443", "https://wx115.bestsign.info") |
| | | .Replace("https://openapi.bestsign.cn:443", "https://wx115.bestsign.cn"); |
| | | |
| | | if (request.SmsCode.IsNull() && entity.ContractTemplate.Access == EnumElectronSignAccess.AlipaySign) |
| | | { |
| | | var codeUrl = new SaveCodeUrlCommand |
| | | { |
| | | Scene = EnumCodeUrlScene.ElectronSignUrl, |
| | | Url = model.SignContractLongUrl, |
| | | ExpiredTime = DateTime.Now.AddMonths(1) |
| | | }; |
| | | var code = await mediator.Send(codeUrl); |
| | | await smsUtils.Send(new SendSmsModel |
| | | { |
| | | PhoneNumber = entity.ContactPhoneNumber, |
| | | TemplateCode = EnumSmsTemplateCode.ElectronSignUrl, |
| | | }, |
| | | new |
| | | { |
| | | name = entity.Enterprise.EnterpriseName, |
| | | code = code |
| | | }); |
| | | } |
| | | |
| | | return model; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 企业用户签约 |
| | | /// </summary> |
| | | /// <param name="request"></param> |
| | | /// <param name="cancellationToken"></param> |
| | | /// <returns></returns> |
| | | public async Task<EnterpriseUserElectronSignCommandResult> Handle(EnterpriseUserElectronSignCommand request, CancellationToken cancellationToken) |
| | | { |
| | | var logier = JwtUtils.GetCurrentLogier(); |
| | | var entity = await rep.AsQueryable() |
| | | .Include(it => it.ContractTemplate).ThenInclude(it => it.Values) |
| | | .Where(it => it.EnterpriseId == logier.EnterpriseId && it.Id == request.Id) |
| | | .FirstOrDefaultAsync(); |
| | | if (entity == null) throw Oops.Oh(EnumErrorCodeType.s510, "灵工不存在"); |
| | | if (entity.UserSignContractStatus == null) throw Oops.Oh(EnumErrorCodeType.s510, "未邀请签约"); |
| | | if (entity.UserSignContractStatus == EnumTaskUserSignContractStatus.Wait) throw Oops.Oh(EnumErrorCodeType.s510, "请先等待灵工签约完成"); |
| | | if (entity.UserSignContractStatus == EnumTaskUserSignContractStatus.Refuse) throw Oops.Oh(EnumErrorCodeType.s510, "已拒签"); |
| | | if (entity.UserSignContractStatus == EnumTaskUserSignContractStatus.Stop) throw Oops.Oh(EnumErrorCodeType.s510, "已终止"); |
| | | var contract = await repEnterpriseEmployeeContract.AsQueryable() |
| | | .OrderByDescending(it => it.CreatedTime) |
| | | .Where(it => it.EnterpriseEmployeeId == request.Id) |
| | | .FirstOrDefaultAsync(); |
| | | if (contract == null) throw Oops.Oh(EnumErrorCodeType.s404, "合同"); |
| | | var enterprise = await repEnterprise.AsQueryable().AsNoTracking() |
| | | .Include(it => it.EnterpriseAuth) |
| | | .Where(it => it.Id == logier.EnterpriseId) |
| | | .FirstOrDefaultAsync(); |
| | | if (enterprise == null) throw Oops.Oh(EnumErrorCodeType.s404, "企业"); |
| | | if (entity.ContractTemplate.Access == EnumElectronSignAccess.BestSign && !enterprise.IsReal) throw Oops.Oh(EnumErrorCodeType.s510, "请先实名"); |
| | | var result = await new SendContractInput |
| | | { |
| | | OutContractId = contract.Id.ToString(), |
| | | TemplateId = entity.ContractTemplate.ElectronSignContractTemplateId!.Value, |
| | | Title = entity.ContractTemplate.Name, |
| | | OutUserId = logier.EnterpriseId.ToString(), |
| | | Values = entity.ContractTemplate.Values |
| | | .Where(it => it.UserType == EnumUserType.Enterprise) |
| | | .Select(it => new SendContractInputValue |
| | | { |
| | | Name = it.Name, |
| | | }) |
| | | .ToList(), |
| | | UserCount = 2 |
| | | }.SendHttpAsync<SendContractInput, ElectronSignServerResult<SendContractOutput>>(EnumResourceHttpProvider.ElectronSignServerCustomer); |
| | | if (result?.Success != true) |
| | | { |
| | | throw Oops.Oh(EnumErrorCodeType.s510, result?.Message ?? "签约失败"); |
| | | } |
| | | var model = result.Result.Adapt<EnterpriseUserElectronSignCommandResult>(); |
| | | model.SignContractLongUrl = model.SignContractLongUrl |
| | | .Replace("https://openapi.bestsign.info:443", "https://wx115.bestsign.info") |
| | | .Replace("https://openapi.bestsign.cn:443", "https://wx115.bestsign.cn"); |
| | | |
| | | if (entity.ContractTemplate.Access == EnumElectronSignAccess.AlipaySign) |
| | | { |
| | | var codeUrl = new SaveCodeUrlCommand |
| | | { |
| | | Scene = EnumCodeUrlScene.ElectronSignUrl, |
| | | Url = model.SignContractLongUrl, |
| | | ExpiredTime = DateTime.Now.AddMonths(1) |
| | | }; |
| | | var code = await mediator.Send(codeUrl); |
| | | await smsUtils.Send(new SendSmsModel |
| | | { |
| | | PhoneNumber = entity.Enterprise.ContactPhoneNumber, |
| | | TemplateCode = EnumSmsTemplateCode.ElectronSignUrl, |
| | | }, |
| | | new |
| | | { |
| | | name = entity.Name, |
| | | code = code |
| | | }); |
| | | } |
| | | |
| | | return model; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 灵工解约 |
| | | /// </summary> |
| | | /// <param name="request"></param> |
| | | /// <param name="cancellationToken"></param> |
| | | /// <returns></returns> |
| | | public async Task<int> Handle(StopElectronSignCommand request, CancellationToken cancellationToken) |
| | | { |
| | | var logier = JwtUtils.GetCurrentLogier(); |
| | | var entities = await rep.AsQueryable() |
| | | .Include(it => it.Contracts) |
| | | .Where(it => it.EnterpriseId == logier.EnterpriseId && request.Ids.Contains(it.Id)) |
| | | .ToListAsync(); |
| | | foreach (var id in request.Ids) |
| | | { |
| | | var entity = entities.FirstOrDefault(it => it.Id == id); |
| | | if (entity == null) throw Oops.Oh(EnumErrorCodeType.s404, "灵工"); |
| | | if (entity.UserSignContractStatus != EnumTaskUserSignContractStatus.Pass) throw Oops.Oh(EnumErrorCodeType.s400, $"未签约{entity.Name}"); |
| | | entity.UserSignContractStatus = EnumTaskUserSignContractStatus.Stop; |
| | | entity.EnterpriseSignContractStatus = EnumTaskUserSignContractStatus.Stop; |
| | | await rep.UpdateAsync(entity); |
| | | |
| | | var contract = entity.Contracts |
| | | .OrderByDescending(it => it.CreatedTime) |
| | | .FirstOrDefault(); |
| | | if (contract == null) throw Oops.Oh(EnumErrorCodeType.s404, $"与{entity.Name}的合同"); |
| | | contract.UserSignContractStatus = EnumTaskUserSignContractStatus.Stop; |
| | | contract.EnterpriseSignContractStatus = EnumTaskUserSignContractStatus.Stop; |
| | | await repEnterpriseEmployeeContract.UpdateAsync(contract); |
| | | } |
| | | |
| | | var taskUsers = await repTaskInfoUser.AsQueryable() |
| | | .Where(it => |
| | | it.HireStatus == EnumTaskUserHireStatus.Pass |
| | | && request.Ids.Contains(it.EnterpriseEmployeeId)) |
| | | .ToListAsync(); |
| | | if (taskUsers.IsNotNull()) |
| | | { |
| | | foreach (var taskUser in taskUsers) |
| | | { |
| | | taskUser.HireStatus = EnumTaskUserHireStatus.Wait; |
| | | } |
| | | await repTaskInfoUser.UpdateAsync(taskUsers); |
| | | } |
| | | |
| | | return entities.Count; |
| | | } |
| | | |
| | | } |
| | | } |