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.
1134 lines
57 KiB
1134 lines
57 KiB
using ATS.NonCustodial.Application.Base; |
|
using ATS.NonCustodial.Application.Contracts.Interfaces.Admins.AppDictionaries; |
|
using ATS.NonCustodial.Application.Contracts.Interfaces.Admins.AppDictionaries.Output; |
|
using ATS.NonCustodial.Application.Contracts.Interfaces.Admins.User; |
|
using ATS.NonCustodial.Application.Contracts.Interfaces.Business.AppCaseManagements.AppCaseManagement; |
|
using ATS.NonCustodial.Application.Contracts.Interfaces.Business.AppCaseManagements.AppCaseManagement.Input; |
|
using ATS.NonCustodial.Application.Contracts.Interfaces.Business.AppCaseManagements.AppCaseManagement.Output; |
|
using ATS.NonCustodial.Application.Contracts.Interfaces.Business.AppCommonFences; |
|
using ATS.NonCustodial.Application.Contracts.Interfaces.Business.AppCommonFences.Output; |
|
using ATS.NonCustodial.Application.Contracts.Interfaces.Business.AppEarlyWarnings; |
|
using ATS.NonCustodial.Application.Contracts.Interfaces.Business.AppEarlyWarnings.Input; |
|
using ATS.NonCustodial.Application.Contracts.Interfaces.Business.AppEarlyWarnings.Output; |
|
using ATS.NonCustodial.Application.Contracts.Interfaces.Business.Apps.Output; |
|
using ATS.NonCustodial.Application.Contracts.Interfaces.Business.IM.Notifies; |
|
using ATS.NonCustodial.Application.Contracts.Interfaces.Business.PunchRecordServices.Input; |
|
using ATS.NonCustodial.Application.Impl.Business.IM; |
|
using ATS.NonCustodial.Domain.Entities.Business; |
|
using ATS.NonCustodial.Domain.Entities.Business.CaseManagements; |
|
using ATS.NonCustodial.Domain.Entities.Business.EarlyWarning; |
|
using ATS.NonCustodial.Domain.Entities.Business.IM; |
|
using ATS.NonCustodial.Domain.Shared.AggRootEntities.Dtos; |
|
using ATS.NonCustodial.Domain.Shared.Enums; |
|
using ATS.NonCustodial.Domain.Shared.OrmRepositories.Basic.EfCore; |
|
using ATS.NonCustodial.DynamicApi; |
|
using ATS.NonCustodial.DynamicApi.Attributes; |
|
using ATS.NonCustodial.Shared.Common.Dtos; |
|
using ATS.NonCustodial.Shared.Common.Enums; |
|
using ATS.NonCustodial.Shared.Common.UnifiedResults; |
|
using ATS.NonCustodial.Shared.Extensions; |
|
using ATS.NonCustodial.Shared.Helpers; |
|
using AutoMapper.QueryableExtensions; |
|
using Castle.Components.DictionaryAdapter; |
|
using Microsoft.AspNetCore.Authorization; |
|
using Microsoft.AspNetCore.Mvc; |
|
using Microsoft.AspNetCore.SignalR; |
|
using Microsoft.EntityFrameworkCore; |
|
using Newtonsoft.Json; |
|
using System.Net; |
|
using System.Text; |
|
using Yitter.IdGenerator; |
|
|
|
namespace ATS.NonCustodial.Application.Impl.Business |
|
{ |
|
/// <summary> |
|
/// 预警提醒管理(实时) |
|
/// </summary> |
|
/// Author:mxg |
|
/// CreatedTimed:2022-06-05 11:30 PM |
|
/// <remarks> |
|
/// 1、【脱离监管区域】被监管人触发电子围栏,会发送预警并记录违规。 |
|
/// 2、【同案人员地点靠近】被监管人靠近同案其他成员的距离小于案件接近等级,会发送预警并记录违规。 |
|
/// 3、【未打卡】被监管人未按照要求打卡,每次会触发一次违规。在被监管人在非休息时间内打卡时间间隔超过设置的间隔,则需要进行预警,提示XXX未打卡。 |
|
/// 4、【脱离监管区域、未打卡、未学习、同案人员地点靠近、失联】监管人在移动端手动给该监管人进行告警,记录一次违规。 |
|
/// 5、【设备拆除】手环中有一个数据为是否被拆除,如果为是的话,则会触发拆除的预警违规。 |
|
/// 总共的类型为:脱离监管区域、同案人员地点靠近、未打卡、未学习、设备拆除 |
|
/// </remarks> |
|
[DynamicApi(Area = "admin")] |
|
public class AppEarlyWarningService : AdminCommonService, IAppEarlyWarningService, IDynamicApi |
|
{ |
|
#region Identity |
|
|
|
private readonly IHubContext<NonCustodialHub> _hubContext; |
|
private readonly IEfRepository<AppEarlyWarning, long> _appEarlyWarningRepository; |
|
private readonly IEfRepository<AppEarlyWarningPushResult, long> _appEarlyWarningPushResultRepository; |
|
|
|
|
|
private readonly IEfRepository<AppDeviceManagement, long> _appDeviceManagementRepository; |
|
private readonly IEfRepository<AppEarlyWarningViewStatistics, long> _appEarlyWarningViewStatisticsRepository; |
|
private readonly IAppCommonFenceService _appCommonFenceService; |
|
private readonly IEfRepository<AppBusinessApplication, long> _appBusinessApplicationRepository; |
|
private readonly IClientNotifyService _clientNotifyService; |
|
private readonly IEfRepository<AppEarlyWarningRule, long> _appEarlyWarningRuleRepository; |
|
private readonly IAppCaseManagementService _appCaseManagementService; |
|
private readonly IUserService _userService; |
|
|
|
/// <summary> |
|
/// |
|
/// </summary> |
|
/// <param name="appEarlyWarningRepository"></param> |
|
/// <param name="hubContext"></param> |
|
/// <param name="appCaseManagementRepository"></param> |
|
/// <param name="appCaseSupervisorRepository"></param> |
|
/// <param name="appSupervisedPersonRepository"></param> |
|
/// <param name="userService"></param> |
|
/// <param name="appDictionaryService"></param> |
|
/// <param name="appDeviceManagementRepository"></param> |
|
/// <param name="appSessionInformationRepository"></param> |
|
/// <param name="appCommonFenceService"></param> |
|
public AppEarlyWarningService(IEfRepository<AppEarlyWarning, long> appEarlyWarningRepository, |
|
IEfRepository<AppEarlyWarningPushResult, long> appEarlyWarningPushResultRepository, |
|
IHubContext<NonCustodialHub> hubContext, |
|
IEfRepository<AppCaseManagement, long> appCaseManagementRepository, |
|
IEfRepository<AppCaseSupervisor, long> appCaseSupervisorRepository, |
|
IEfRepository<AppCaseSupervisedPerson, long> appSupervisedPersonRepository, |
|
IUserService userService, |
|
IAppDictionaryService appDictionaryService, |
|
IEfRepository<AppDeviceManagement, long> appDeviceManagementRepository, |
|
IEfRepository<AppSessionInformation, long> appSessionInformationRepository, |
|
IAppCommonFenceService appCommonFenceService, |
|
|
|
IAppCaseManagementService appCaseManagementService, |
|
IEfRepository<AppBusinessApplication, long> appBusinessApplicationRepository, |
|
IEfRepository<AppSupervisedPersonRealTimeLocation, long> appSupervisedPersonRealTimeLocationRepository, |
|
IClientNotifyService clientNotifyService, |
|
IEfRepository<AppEarlyWarningViewStatistics, long> appEarlyWarningViewStatisticsRepository, |
|
IEfRepository<AppEarlyWarningRule, long> appEarlyWarningRuleRepository) |
|
: base( |
|
appCaseManagementRepository, |
|
appCaseSupervisorRepository, |
|
appSupervisedPersonRepository, |
|
userService, |
|
appDictionaryService, |
|
appSupervisedPersonRealTimeLocationRepository |
|
) |
|
{ |
|
_appEarlyWarningRepository = appEarlyWarningRepository; |
|
_appEarlyWarningPushResultRepository = appEarlyWarningPushResultRepository; |
|
_hubContext = hubContext; |
|
_appDeviceManagementRepository = appDeviceManagementRepository; |
|
_appEarlyWarningViewStatisticsRepository = appEarlyWarningViewStatisticsRepository; |
|
_appCommonFenceService = appCommonFenceService; |
|
_appBusinessApplicationRepository = appBusinessApplicationRepository; |
|
_clientNotifyService = clientNotifyService; |
|
_appEarlyWarningRuleRepository = appEarlyWarningRuleRepository; |
|
_appCaseManagementService = appCaseManagementService; |
|
_userService = userService; |
|
} |
|
|
|
#endregion Identity |
|
|
|
/// <summary> |
|
/// 手动添加预警信息[比如:监管人App聊天窗口调用] |
|
/// </summary> |
|
/// <returns></returns> |
|
/// <remarks> |
|
/// ###### 手动触发 |
|
/// 通过移动端监管人APP给被监管人手动录入预警的类型数据 |
|
/// </remarks> |
|
public async Task<IResultOutput> ManualAddEarlyWarning(EarlyWarningAddInput input) |
|
{ |
|
//[获取当前[被监管挂人员]的案件 |
|
var caseInfo = await base.GetCaseInfoBySupervisedPersonId(input.SupervisedPersonId); |
|
if (caseInfo == null) return ResultOutput.NotOk($"当前被监管人:{input.SupervisedPersonId}不存在正在进行的案件!"); |
|
|
|
//字典 |
|
var dictionaryGetOutput = await _appDictionaryService.GetDicByDicId(input.EarlyWarningTypeId); |
|
|
|
//公共逻辑 |
|
return await EarlyWarningCommLogic(caseInfo, dictionaryGetOutput, null, input.address == null ? "" : input.address); |
|
} |
|
|
|
/// <summary> |
|
/// 新增预计信息 |
|
/// </summary> |
|
/// <param name="input"></param> |
|
/// <returns></returns> |
|
public async Task<IResultOutput> AddAsync(AppEarlyWarningAddInput input) => |
|
await base.AddAsync(input, _appEarlyWarningRepository); |
|
|
|
/// <summary> |
|
/// 批量新增预计信息 |
|
/// </summary> |
|
/// <param name="input"></param> |
|
/// <returns></returns> |
|
public async Task<IResultOutput> BatchAddAsync(List<AppEarlyWarningAddInput> input) |
|
{ |
|
List<AppEarlyWarningViewStatistics> earlyWarningView = new EditableList<AppEarlyWarningViewStatistics>(); |
|
|
|
var spIds = input.Select(w => w.SupervisedPersonId).ToList(); |
|
var admins = (await _userService.GetAllAdminUserIds()).Select(w => new KeyValueDto() |
|
{ |
|
Id = w.Id, |
|
Value = w.UserName, |
|
Text = w.UserName |
|
}).ToList(); |
|
var superviseList = (await base.GetSuperviseListByUserId(spIds)).Select(w => new KeyValueDto() |
|
{ |
|
Id = w.SupervisedId, |
|
Value = w.SupervisedName, |
|
Text = w.SupervisedName |
|
}).ToList(); |
|
|
|
foreach (var addInput in input) |
|
{ |
|
//管理员 |
|
earlyWarningView.AddRange(await AddEarlyWithViews(addInput, admins)); |
|
//监管人 |
|
earlyWarningView.AddRange(await AddEarlyWithViews(addInput, superviseList)); |
|
//被监管人自己 |
|
earlyWarningView.AddRange(await AddEarlyWithViews(addInput, new EditableList<KeyValueDto>() |
|
{ |
|
new KeyValueDto() |
|
{ |
|
Id = addInput.SupervisedPersonId, |
|
Text = addInput.SupervisedPersonName, |
|
Value = addInput.SupervisedPersonName |
|
} |
|
})); |
|
} |
|
|
|
//入库 |
|
await base.AddAsync(input, _appEarlyWarningRepository); |
|
await _appEarlyWarningViewStatisticsRepository.InsertAsync(earlyWarningView); |
|
|
|
return ResultOutput.Ok(); |
|
} |
|
/// <summary> |
|
/// 批量新增推送结果 |
|
/// </summary> |
|
/// <param name="input"></param> |
|
/// <returns></returns> |
|
public async Task<IResultOutput> BatchAddPushResultAsync(List<AppEarlyWarningPushResultAddInput> input) |
|
{ |
|
foreach (var item in input) |
|
{ |
|
// item.WarningId = item.Id; |
|
item.Id = null; |
|
} |
|
//入库 |
|
await base.AddAsync(input, _appEarlyWarningPushResultRepository); |
|
return ResultOutput.Ok(); |
|
} |
|
/// <summary> |
|
/// 根据预计类型枚举和设备唯一标识符新增预警信息 |
|
/// </summary> |
|
/// <param name="input"></param> |
|
/// <returns></returns> |
|
/// <remarks> |
|
/// ###### 设备触发 |
|
/// 设备触发设备拆除的预警情况,不需要token鉴权,只需要一个设备唯一码即可 |
|
/// </remarks> |
|
[AllowAnonymous] |
|
public async Task<IResultOutput> AddEarlyWarning(AddEarlyWarningInput input) |
|
{ |
|
//查找设备 |
|
var device = |
|
await _appDeviceManagementRepository.FindAsync(w => w.UniqueIdentifier == input.UniqueIdentifier); |
|
if (device == null) return ResultOutput.NotOk($"当前设备:{input.UniqueIdentifier}不存在!"); |
|
|
|
//[获取当前[被监管挂人员]的案件 |
|
var caseInfo = await base.GetCaseInfoBySupervisedPersonId(device.SupervisedPersonId); |
|
if (caseInfo == null) return ResultOutput.NotOk($"当前设备标识符:{input.UniqueIdentifier}绑定的被监管人不存在!"); |
|
|
|
//处理预警类型 |
|
var dictionaryGetOutput = input.EarlyWarningType switch |
|
{ |
|
EarlyWarningTypeEnum.EquipmentRemoval => await base.GetDictionariesOutput("early_warning_type", |
|
"equipmentremoval"), |
|
_ => throw new ArgumentOutOfRangeException() |
|
}; |
|
|
|
if (dictionaryGetOutput == null) |
|
return ResultOutput.NotOk($"当前预警类型:{input.EarlyWarningType.ToDescription()}不存在字典中,请联系管理员添加"); |
|
|
|
//公共逻辑 |
|
return await EarlyWarningCommLogic(caseInfo, dictionaryGetOutput, device); |
|
} |
|
|
|
/// <summary> |
|
/// 查询列表 |
|
/// </summary> |
|
/// <param name="input"></param> |
|
/// <returns></returns> |
|
[HttpPost] |
|
[AllowAnonymous] |
|
public async Task<IResultOutput> GetPageAsync(AppEarlyWarningGetPageInput input) |
|
{ |
|
//获取当前用户权限下的案件ids |
|
var limits = User.limits; |
|
var selectLimits = await _appCaseSupervisorRepository.AsQueryable(false, true) |
|
.Where(w => limits.Contains(w.UnitId.ToString())) |
|
.ToListAsync(); |
|
var caseIdList = selectLimits.Select(w => w.CaseId).Distinct().ToList(); |
|
|
|
|
|
var express = await GetExpression(input, _appEarlyWarningRepository.AsQueryable(false, true)); |
|
// 先应用案件ID过滤条件 |
|
express = express.Where(w => caseIdList.Contains(w.CaseId)); |
|
// 然后再获取分页数据 |
|
return await base.GetEntityAddPageAsync<AppEarlyWarning, AppEarlyWarningGetPageInput, AppEarlyWarningListDto>(input, express); |
|
} |
|
|
|
/// <summary> |
|
/// 越界预警统计查询 |
|
/// </summary> |
|
/// <param name="input"></param> |
|
/// <returns></returns> |
|
[HttpPost] |
|
public async Task<IResultOutput> GetCrossborderStatisticsAsync(AppEarlyWarningGetPageInput input) |
|
{ //获取当前用户权限下的案件ids |
|
var limits = User.limits; |
|
var selectLimits = await _appCaseSupervisorRepository.AsQueryable(false, true) |
|
.Where(w => limits.Contains(w.UnitId.ToString())) |
|
.ToListAsync(); |
|
var caseIds = selectLimits.Select(w => w.CaseId).Distinct().ToList(); |
|
|
|
var express = await GetExpression(input, _appEarlyWarningRepository.AsQueryable(false, true)); |
|
var grudlist = express.Where(p=> caseIds.Contains(p.CaseId)) |
|
.WhereIf(input.supname.NotNull(), w => w.SupervisedPersonName.Contains(input.supname)) |
|
.GroupBy(q => new { q.CaseId, q.CaseName, q.SupervisedPersonId, q.SupervisedPersonName }).Select(q => new { q.Key.CaseId, q.Key.CaseName, q.Key.SupervisedPersonName, q.Key.SupervisedPersonId, Count = q.ToList().Count() }).Skip((input.PageIndex - 1) * input.PageSize).Take(input.PageSize); |
|
//var SupervisedPersonIds = grudlist.Select(q => q.SupervisedPersonId); |
|
// var grudlistcunot = express.Where(q => SupervisedPersonIds.Contains(q.SupervisedPersonId)).ToList(); |
|
return ResultOutput.Ok(new { TotalCount = express.Where(p => caseIds.Contains(p.CaseId)).GroupBy(q => new { q.CaseId, q.CaseName, q.SupervisedPersonId, q.SupervisedPersonName }).Count(), grudlist }); |
|
} |
|
|
|
|
|
|
|
|
|
/// <summary> |
|
/// 设备上传经纬度时候,验证 |
|
/// </summary> |
|
/// <returns></returns> |
|
/// <remarks> |
|
/// ###### 设备上传经纬度时候,验证 |
|
/// a)是否脱离监管区域,监管区域以案件设置的围栏为准,这里需要注意一下,如果通过了跨区域的申请,在这个时间内,不做预警触发 |
|
/// b)同案人员地点靠经,如果存在2个以上的人员(包括2个),依据最近一次经纬度进行校验,范围为案件申请里面的接近等级 |
|
/// </remarks> |
|
[AllowAnonymous] |
|
public async Task<IResultOutput> ValidWithLatitudeAndLongitude(ValidWithLatitudeAndLongitudeInput input) |
|
{ |
|
//查找设备 |
|
var device = await _appDeviceManagementRepository.FindAsync(w => w.UniqueIdentifier == input.UniqueIdentifier); |
|
if (device == null) return ResultOutput.NotOk($"当前设备:{input.UniqueIdentifier}不存在!"); |
|
if (device.DataStatus != DataStatusEnum.Normal) return ResultOutput.Ok(); |
|
|
|
//[获取当前[被监管挂人员]的案件 |
|
var caseInfo = await base.GetCaseInfoBySupervisedPersonId(device.SupervisedPersonId); |
|
return caseInfo == null |
|
? ResultOutput.NotOk($"当前设备标识符:{input.UniqueIdentifier}绑定的被监管人不存在!") |
|
: caseInfo.ApprovalStatus != ApprovalStatusEnum.PassReview |
|
? ResultOutput.Ok() |
|
: await ValidWithLatitudeAndLongitudeCommonLogic(caseInfo, input.Longitude, input.Latitude); |
|
} |
|
|
|
/// <summary> |
|
/// 设备上传经纬度时候,验证 |
|
/// </summary> |
|
/// <returns></returns> |
|
/// <remarks> |
|
/// ###### 设备上传经纬度时候,验证 |
|
/// a)是否脱离监管区域,监管区域以案件设置的围栏为准,这里需要注意一下,如果通过了跨区域的申请,在这个时间内,不做预警触发 |
|
/// b)同案人员地点靠经,如果存在2个以上的人员(包括2个),依据最近一次经纬度进行校验,范围为案件申请里面的接近等级 |
|
/// </remarks> |
|
public async Task<IResultOutput> ValidWithLatitudeAndLongitude(ValidWithLatitudeAndLongitudeByIdInput input) |
|
{ |
|
//[获取当前[被监管挂人员]的案件 |
|
var caseInfo = await base.GetCaseInfoBySupervisedPersonId(input.SupervisedPersonId); |
|
if (caseInfo == null) return ResultOutput.NotOk($"当前设备标识符:{input.SupervisedPersonId}绑定的被监管人不存在!"); |
|
if (caseInfo.ApprovalStatus != ApprovalStatusEnum.PassReview) return ResultOutput.Ok(); |
|
|
|
//如果当前设备绑定的设备被禁用 |
|
var deviceBind = await _appDeviceManagementRepository.FindAsync(w => w.SupervisedPersonId == caseInfo.SupervisedPersonId); |
|
return deviceBind != null && deviceBind.DataStatus != DataStatusEnum.Normal |
|
? ResultOutput.Ok() |
|
: await ValidWithLatitudeAndLongitudeCommonLogic(caseInfo, input.Longitude, input.Latitude, true); |
|
} |
|
|
|
/// <summary> |
|
/// 批量设置是否查阅状态 |
|
/// </summary> |
|
/// <param name="input"></param> |
|
/// <returns></returns> |
|
[HttpPost] |
|
public async Task<IResultOutput> BatchSetCheckStatus(SetCheckStatusInput input) |
|
{ |
|
if (_user?.Id > 0 || !input.Ids.Any()) return ResultOutput.Ok(); |
|
|
|
//查询记录(根据公告Id和订阅者ID(被监管人Id)) |
|
var earlyWarnings = await _appEarlyWarningViewStatisticsRepository |
|
.Where(w => input.Ids.Contains(w.AppEarlyWarningId) && w.SubscriberId == User.Id) |
|
.ToListAsync(); |
|
|
|
earlyWarnings.ForEach(item => |
|
{ |
|
//如果已经是已读了就直接返回 |
|
if (item.CheckStatus == CheckStatusEnum.Checked) return; |
|
|
|
item!.CheckStatus = input.CheckStatus; |
|
item.CheckTime = input.CheckStatus == CheckStatusEnum.Checked ? DateTime.Now : null; |
|
}); |
|
|
|
//批量修改 |
|
await _appEarlyWarningViewStatisticsRepository.UpdateAsync(earlyWarnings); |
|
return ResultOutput.Ok(); |
|
} |
|
|
|
/// <summary> |
|
/// 业务工作台==>最新5条预警 |
|
/// </summary> |
|
/// <returns></returns> |
|
public async Task<IResultOutput> EarlyWarningBusinessWorkbench() |
|
{ |
|
//获取当前用户权限下的案件ids |
|
var limits = User.limits; |
|
var selectLimits = await _appCaseSupervisorRepository.AsQueryable(false, true) |
|
.Where(w => limits.Contains(w.UnitId.ToString())) |
|
.ToListAsync(); |
|
var caseIdList = selectLimits.Select(w => w.CaseId).Distinct().ToList(); |
|
var caseIds = await (await base.GetCurrentUserCaseListAsync()).Where(w=> w.AppCaseManagement!=null&&caseIdList.Contains(w.AppCaseManagement.Id)).Select(w => w.AppCaseManagement.Id).ToListAsync(); |
|
|
|
|
|
var dataList = await _appEarlyWarningRepository.AsQueryable(false, true) |
|
.Where(w => caseIds.Contains(w.CaseId)) |
|
.OrderByDescending(w => w.CreatedTime) |
|
.Skip(0) |
|
.Take(5) |
|
.ProjectTo<AppEarlyWarningListDto>(Mapper.ConfigurationProvider) |
|
.ToListAsync(); |
|
|
|
var dictIds = dataList.Select(w => w.EarlyWarningTypeId).ToList(); |
|
var dataDict = await _appDictionaryService.GetDicByDicIds(new BatchIdsInput() |
|
{ |
|
Ids = dictIds |
|
}); |
|
|
|
foreach (var listDto in dataList) |
|
{ |
|
listDto.EarlyWarningTypeName = dataDict.FirstOrDefault(w => w.Id == listDto.EarlyWarningTypeId)?.Name; |
|
} |
|
|
|
return ResultOutput.Ok(dataList); |
|
} |
|
|
|
#region Private |
|
|
|
/// <summary> |
|
/// 查询实时预警条件 |
|
/// </summary> |
|
/// <param name="pageInput"></param> |
|
/// <param name="query"></param> |
|
/// <returns></returns> |
|
private async Task<IQueryable<AppEarlyWarning>> GetExpression(AppEarlyWarningGetPageInput pageInput, IQueryable<AppEarlyWarning?> query) |
|
{ |
|
var limits = User.limits; |
|
var IsAdmin = User.IsAdmin; |
|
var selectLimits = await _appCaseSupervisorRepository.AsQueryable(false, true) |
|
.WhereIf((!IsAdmin),w => limits.Contains(w.UnitId.ToString())) |
|
.ToListAsync(); |
|
var caseIds = selectLimits.Select(w => w.CaseId).Distinct().ToList(); |
|
//var caseIds = await (await base.GetCurrentUserCaseListAsync()).Select(w => w.AppCaseManagement.Id).ToListAsync(); |
|
|
|
query = query.Where(w => caseIds.Contains(w.CaseId)) |
|
.WhereIf(pageInput.KeyWord.NotNull(), w => w.Title.Contains(pageInput.KeyWord) || w.CaseName.Contains(pageInput.KeyWord)) |
|
.WhereIf(pageInput.casename.NotNull(), w => w.CaseName.Contains(pageInput.casename)) |
|
.WhereIf(pageInput.EarlyWarningTypeId.Any(), a => pageInput.EarlyWarningTypeId.Contains(a.EarlyWarningTypeId)) |
|
.WhereIf(pageInput.UserSearch != null, p => p.SupervisedPersonId == pageInput.UserSearch!.ModifiedUserId); |
|
|
|
var express = base.GetEntityAddExpression<AppEarlyWarning, AppEarlyWarningGetPageInput, long>(pageInput, query); |
|
|
|
return express; |
|
} |
|
|
|
/// <summary> |
|
/// 添加预警信息公告逻辑发给当前被监管人、管理员、监管人 |
|
/// </summary> |
|
/// <param name="caseInfo"></param> |
|
/// <param name="dictionaryGetOutput"></param> |
|
/// <param name="device"></param> |
|
/// <returns></returns> |
|
/// <remarks> |
|
/// 1、如果出现跨区域预警第一次预警后 后面将不在预警 等到回到区域后 再次跨区域 才会出现 |
|
/// 2、同案件范围接近报警 也同上 出现第一次后 直到不在出现后 再次出现才报警,如果一直报警 仅为1次 |
|
/// </remarks> |
|
private async Task<IResultOutput> EarlyWarningCommLogic(GetCaseInfoBySupervisedPersonIdOutput caseInfo, DictionaryGetOutput dictionaryGetOutput, AppDeviceManagement? device = null, string address = "") |
|
{ |
|
//Builder AppEarlyWarning |
|
var entity = await _appEarlyWarningRepository.InsertAsync(new AppEarlyWarning(YitIdHelper.NextId()) |
|
{ |
|
CaseId = caseInfo.CaseId, |
|
CaseName = caseInfo.CaseName, |
|
Title = dictionaryGetOutput?.Name, |
|
Content = dictionaryGetOutput?.Name + address, |
|
SupervisedPersonId = caseInfo.SupervisedPersonId, |
|
SupervisedPersonName = caseInfo.SupervisedPersonName, |
|
EarlyWarningTypeId = dictionaryGetOutput?.Id, |
|
EarlyWarningTypeName = dictionaryGetOutput?.Name, |
|
DeviceId = device?.Id, |
|
DeviceName = device?.Name, |
|
UniqueIdentifier = device?.UniqueIdentifier |
|
}); |
|
|
|
var earlyWarningView = await base.GetEarlyWarningRecord(new EditableList<AppEarlyWarningAddInput>() |
|
{ |
|
new AppEarlyWarningAddInput(entity.Id) |
|
{ |
|
EarlyWarningTypeId = entity.EarlyWarningTypeId, |
|
CaseId = entity.CaseId, |
|
Content = entity.Content, |
|
Title = entity.Title, |
|
SupervisedPersonId = entity.SupervisedPersonId, |
|
SupervisedPersonName = entity.SupervisedPersonName |
|
} |
|
}); |
|
|
|
await _appEarlyWarningViewStatisticsRepository.InsertAsync(earlyWarningView); |
|
|
|
//通知 |
|
await _clientNotifyService.RealTimeWarningToPc(new RealTimeWarningToPcInput() |
|
{ |
|
AppRemindListDtos = new EditableList<AppRemindListDto>() |
|
{ |
|
new AppRemindListDto() |
|
{ |
|
Title = entity.Title, |
|
Id = entity.Id, |
|
Content = entity.Content, |
|
CaseId = entity.CaseId, |
|
CreatedTime = entity.CreatedTime |
|
}, |
|
}, |
|
SubscriberIds = earlyWarningView.Select(w => w.SubscriberId).ToList() |
|
}); |
|
|
|
return ResultOutput.Ok(); |
|
} |
|
|
|
/// <summary> |
|
/// 校验当前被监管人位置公共方法 |
|
/// </summary> |
|
/// <param name="caseInfo"></param> |
|
/// <param name="longitude"></param> |
|
/// <param name="latitude"></param> |
|
/// <param name="isFromPunchRecord">是否来自打卡(打卡的话就不需要判断上一次是否来自围栏内)</param> |
|
/// <returns></returns> |
|
private async Task<IResultOutput> ValidWithLatitudeAndLongitudeCommonLogic(GetCaseInfoBySupervisedPersonIdOutput caseInfo, decimal longitude, decimal latitude, bool isFromPunchRecord = false) |
|
{ |
|
if (!caseInfo.ElectricFenceId.HasValue) return ResultOutput.Ok(); |
|
|
|
//[1]跨域申请 |
|
var commonFence = (IResultOutput<AppCommonFenceGetDto>)await _appCommonFenceService.GetAsync(caseInfo.ElectricFenceId.Value); |
|
var points = commonFence.Data.Path.StrToLatLngList(); |
|
|
|
await LeaveArea(caseInfo, longitude, latitude, points, isFromPunchRecord); |
|
|
|
//[2]同案人员地点靠近 |
|
await InvestigatorsApproach(caseInfo, longitude, latitude, points, isFromPunchRecord); |
|
|
|
//[3] |
|
await Getpoi(caseInfo, longitude, latitude, isFromPunchRecord); |
|
|
|
return ResultOutput.Ok(); |
|
} |
|
/// <summary> |
|
/// 校验当前被监管人位置公共方法 多个监控区域 |
|
/// </summary> |
|
/// <param name="caseInfo"></param> |
|
/// <param name="longitude"></param> |
|
/// <param name="latitude"></param> |
|
/// <param name="isFromPunchRecord"></param> |
|
/// <returns></returns> |
|
private async Task<IResultOutput> ValidWithLatitudeAndLongitudeCommonLogic1(GetCaseInfoBySupervisedPersonIdOutput caseInfo, decimal longitude, decimal latitude, bool isFromPunchRecord = false) |
|
{ |
|
if (!caseInfo.ElectricFenceId.HasValue) return ResultOutput.Ok(); |
|
await LeaveArea1(caseInfo, longitude, latitude, isFromPunchRecord); |
|
|
|
//[2]同案人员地点靠近 |
|
//await InvestigatorsApproach(caseInfo, longitude, latitude, points, isFromPunchRecord); |
|
return ResultOutput.Ok(); |
|
} |
|
|
|
/// <summary> |
|
/// 处理预警规则(True需要) |
|
/// </summary> |
|
/// <param name="caseInfo"></param> |
|
/// <param name="dictionaryGet"></param> |
|
/// <param name="longitude"></param> |
|
/// <param name="latitude"></param> |
|
/// <param name="bmapPoints"></param> |
|
/// <param name="isFromPunchRecord"></param> |
|
/// <returns></returns> |
|
private async Task<bool> IsNeedToEarlyWarning(GetCaseInfoBySupervisedPersonIdOutput caseInfo, DictionaryGetOutput dictionaryGet, decimal longitude, decimal latitude, BmapPoint[] bmapPoints, bool isFromPunchRecord = false) |
|
{ |
|
var earlyWarningRule = await _appEarlyWarningRuleRepository.FindAsync(w => |
|
w.EarlyWarningTypeId == dictionaryGet.Id && |
|
w.SupervisedPersonId == caseInfo.SupervisedPersonId && |
|
w.CaseId == caseInfo.CaseId); |
|
|
|
//判断点是否在多边形内(基本思路是用交点法)(true:在围栏内,false:在围栏外) |
|
var isPointInPolygon = GraphUtils.IsPointInPolygon(new BmapPoint(longitude, latitude), bmapPoints); |
|
|
|
//上一次是否在圈内(只针对定位) |
|
var lastIsPointInPolygon = earlyWarningRule?.LastIsPointInPolygon ?? false; |
|
|
|
if (earlyWarningRule == null) |
|
{ |
|
await _appEarlyWarningRuleRepository.InsertAsync(new AppEarlyWarningRule(YitIdHelper.NextId()) |
|
{ |
|
CaseId = caseInfo.CaseId, |
|
CaseName = caseInfo.CaseName, |
|
SupervisedPersonId = caseInfo.SupervisedPersonId, |
|
SupervisedPersonName = caseInfo.SupervisedPersonName, |
|
EarlyWarningTypeId = dictionaryGet.Id, |
|
EarlyWarningTypeName = dictionaryGet.Name, |
|
LastIsPointInPolygon = isPointInPolygon |
|
}); |
|
} |
|
else |
|
{ |
|
earlyWarningRule.LastIsPointInPolygon = isPointInPolygon; |
|
|
|
//跟新上一次是否实在围栏内 |
|
await _appEarlyWarningRuleRepository.UpdateAsync(earlyWarningRule, UpdatingProps<AppEarlyWarningRule>(x => x.LastIsPointInPolygon)!); |
|
} |
|
|
|
//如果来自打卡直接返回 |
|
if (isFromPunchRecord) return !isPointInPolygon; |
|
else |
|
{ |
|
//预警条件:上一次在圈内且现在在圈外,如果第一次都在外面那么也需要预警 |
|
return earlyWarningRule == null && !isPointInPolygon ? true : lastIsPointInPolygon && !isPointInPolygon; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// 处理预警规则(True需要) 多个监控区域 |
|
/// </summary> |
|
/// <param name="caseInfo"></param> |
|
/// <param name="dictionaryGet"></param> |
|
/// <param name="longitude"></param> |
|
/// <param name="latitude"></param> |
|
/// <param name="bmapPoints"></param> |
|
/// <param name="isFromPunchRecord"></param> |
|
/// <returns></returns> |
|
private async Task<bool> IsNeedToEarlyWarning1(GetCaseInfoBySupervisedPersonIdOutput caseInfo, DictionaryGetOutput dictionaryGet, decimal longitude, decimal latitude, bool isFromPunchRecord = false) |
|
{ |
|
var earlyWarningRule = await _appEarlyWarningRuleRepository.FindAsync(w => |
|
w.EarlyWarningTypeId == dictionaryGet.Id && |
|
w.SupervisedPersonId == caseInfo.SupervisedPersonId && |
|
w.CaseId == caseInfo.CaseId); |
|
//循环监控区域 |
|
var isPointInPolygon = false; |
|
foreach (var item in caseInfo.ElectricFenceId.Value.ToString().Split(",")) |
|
{ |
|
//[1]跨域申请 |
|
var commonFence = (IResultOutput<AppCommonFenceGetDto>)await _appCommonFenceService.GetAsync(caseInfo.ElectricFenceId.Value); |
|
var bmap = commonFence.Data.Path.StrToLatLngList();//转换字符串二维数组经纬度 |
|
//判断点是否在多边形内(基本思路是用交点法)(true:在围栏内,false:在围栏外) |
|
isPointInPolygon = GraphUtils.IsPointInPolygon(new BmapPoint(longitude, latitude), bmap); |
|
if (isPointInPolygon) break; |
|
} |
|
//上一次是否在圈内(只针对定位) |
|
var lastIsPointInPolygon = earlyWarningRule?.LastIsPointInPolygon ?? false; |
|
|
|
if (earlyWarningRule == null) |
|
{ |
|
await _appEarlyWarningRuleRepository.InsertAsync(new AppEarlyWarningRule(YitIdHelper.NextId()) |
|
{ |
|
CaseId = caseInfo.CaseId, |
|
CaseName = caseInfo.CaseName, |
|
SupervisedPersonId = caseInfo.SupervisedPersonId, |
|
SupervisedPersonName = caseInfo.SupervisedPersonName, |
|
EarlyWarningTypeId = dictionaryGet.Id, |
|
EarlyWarningTypeName = dictionaryGet.Name, |
|
LastIsPointInPolygon = isPointInPolygon |
|
}); |
|
} |
|
else |
|
{ |
|
earlyWarningRule.LastIsPointInPolygon = isPointInPolygon; |
|
|
|
//跟新上一次是否实在围栏内 |
|
await _appEarlyWarningRuleRepository.UpdateAsync(earlyWarningRule, UpdatingProps<AppEarlyWarningRule>(x => x.LastIsPointInPolygon)!); |
|
} |
|
|
|
//如果来自打卡直接返回 |
|
if (isFromPunchRecord) return !isPointInPolygon; |
|
else |
|
{ |
|
//预警条件:上一次在圈内且现在在圈外,如果第一次都在外面那么也需要预警 |
|
return earlyWarningRule == null && !isPointInPolygon ? true : lastIsPointInPolygon && !isPointInPolygon; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// 处理同案件人员靠近 |
|
/// </summary> |
|
/// <param name="caseInfo"></param> |
|
/// <param name="longitude"></param> |
|
/// <param name="latitude"></param> |
|
/// <param name="bmapPoints"></param> |
|
/// <param name="isFromPunchRecord"></param> |
|
/// <returns></returns> |
|
private async Task InvestigatorsApproach(GetCaseInfoBySupervisedPersonIdOutput caseInfo, decimal longitude, decimal latitude, BmapPoint[] bmapPoints, bool isFromPunchRecord) |
|
{ |
|
var allInProcessCase = await base._appCaseManagementRepository.AsQueryable(false, true) |
|
.Where(w => w.CaseProgress != CaseProgressEnum.Pending && w.CaseProgress != CaseProgressEnum.Closed && w.Id == caseInfo.CaseId) |
|
.Select(w => w.Id) |
|
.ToListAsync(); |
|
|
|
//当前被监管人定位信息 |
|
var currentSpLocation = await _appSupervisedPersonRealTimeLocationRepository |
|
.AsQueryable(false, true) |
|
.Where(w => allInProcessCase.Contains(w.CaseId) && w.SupervisedPersonId != caseInfo.SupervisedPersonId) |
|
.Select(w => new |
|
{ |
|
w.SupervisedPersonId, |
|
w.SupervisedPersonName, |
|
w.Latitude, |
|
w.Longitude, |
|
w.CreatedTime |
|
}).ToListAsync(); |
|
|
|
var ita = await base.GetDictionariesOutput("early_warning_type", "InvestigatorsApproach"); |
|
|
|
//规则:设置了接近等级(米)、当前等位信息、需要预警 |
|
if (caseInfo.ProximityLevel == default || !currentSpLocation.Any() && !await IsNeedToEarlyWarning(caseInfo, ita, longitude, latitude, bmapPoints, isFromPunchRecord)) return; |
|
{ |
|
foreach (var tempDistinct in currentSpLocation.Select(item => GraphUtils.GetDistance(longitude, latitude, item.Longitude, item.Latitude))) |
|
{ |
|
//出了电子围栏,添加一条预计信息 |
|
if (tempDistinct > (decimal)caseInfo.ProximityLevel || ita == null) continue; |
|
_ = await ManualAddEarlyWarning(new EarlyWarningAddInput() |
|
{ |
|
EarlyWarningTypeId = ita.Id, |
|
SupervisedPersonId = caseInfo.SupervisedPersonId |
|
}); |
|
|
|
break; |
|
} |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// 处理脱离围栏 |
|
/// </summary> |
|
/// <param name="caseInfo"></param> |
|
/// <param name="longitude"></param> |
|
/// <param name="latitude"></param> |
|
/// <param name="bmapPoints"></param> |
|
/// <param name="isFromPunchRecord"></param> |
|
/// <returns></returns> |
|
private async Task LeaveArea(GetCaseInfoBySupervisedPersonIdOutput caseInfo, decimal longitude, decimal latitude, BmapPoint[] bmapPoints, bool isFromPunchRecord) |
|
{ |
|
//是否脱离监管区域、判断当前监管人是否申请了跨域 |
|
var dtNow = DateTime.Now; |
|
|
|
//跨域申请字典 |
|
var df = await base.GetDictionariesOutput("application_type", "df"); |
|
|
|
//被监管人职位字典 |
|
var spBusApp = await _appBusinessApplicationRepository.AsQueryable(false, true) |
|
.Where(w => |
|
df != null && |
|
w.SupervisedPersonId == caseInfo.SupervisedPersonId && |
|
dtNow >= w.ActiveTimePeriodBegin && dtNow <= w.ActiveTimePeriodEnd && |
|
w.AuditStatus == AuditStatusEnum.Pass && |
|
w.ApplicationTypeId == df.Id |
|
).ToListAsync(); |
|
|
|
//只有有电子围栏且当前时间段没有跨域申请的才判断 |
|
var dic = await base.GetDictionariesOutput("early_warning_type", "LeaveArea"); |
|
|
|
//出了电子围栏,添加一条预计信息 |
|
if (caseInfo.ElectricFenceId.HasValue && !spBusApp.Any() && dic != null && await IsNeedToEarlyWarning(caseInfo, dic, longitude, latitude, bmapPoints, isFromPunchRecord)) |
|
{ |
|
_ = await ManualAddEarlyWarning(new EarlyWarningAddInput() |
|
{ |
|
EarlyWarningTypeId = dic.Id, |
|
SupervisedPersonId = caseInfo.SupervisedPersonId |
|
}); |
|
} |
|
} |
|
/// <summary> |
|
/// 处理脱离围栏---多个监管区域 |
|
/// </summary> |
|
/// <param name="caseInfo"></param> |
|
/// <param name="longitude"></param> |
|
/// <param name="latitude"></param> |
|
/// <param name="bmapPoints"></param> |
|
/// <param name="isFromPunchRecord"></param> |
|
/// <returns></returns> |
|
private async Task LeaveArea1(GetCaseInfoBySupervisedPersonIdOutput caseInfo, decimal longitude, decimal latitude, bool isFromPunchRecord) |
|
{ |
|
//是否脱离监管区域、判断当前监管人是否申请了跨域 |
|
var dtNow = DateTime.Now; |
|
|
|
//跨域申请字典 |
|
var df = await base.GetDictionariesOutput("application_type", "df"); |
|
|
|
//被监管人职位字典 |
|
var spBusApp = await _appBusinessApplicationRepository.AsQueryable(false, true) |
|
.Where(w => |
|
df != null && |
|
w.SupervisedPersonId == caseInfo.SupervisedPersonId && |
|
dtNow >= w.ActiveTimePeriodBegin && dtNow <= w.ActiveTimePeriodEnd && |
|
w.AuditStatus == AuditStatusEnum.Pass && |
|
w.ApplicationTypeId == df.Id |
|
).ToListAsync(); |
|
|
|
//只有有电子围栏且当前时间段没有跨域申请的才判断 |
|
var dic = await base.GetDictionariesOutput("early_warning_type", "LeaveArea"); |
|
|
|
//出了电子围栏,添加一条预计信息 |
|
if (caseInfo.ElectricFenceId.HasValue && !spBusApp.Any() && dic != null && await IsNeedToEarlyWarning1(caseInfo, dic, longitude, latitude, isFromPunchRecord)) |
|
{ |
|
_ = await ManualAddEarlyWarning(new EarlyWarningAddInput() |
|
{ |
|
EarlyWarningTypeId = dic.Id, |
|
SupervisedPersonId = caseInfo.SupervisedPersonId |
|
}); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// 进入未经许可场所 |
|
/// </summary> |
|
/// <param name="caseInfo"></param> |
|
/// <param name="longitude"></param> |
|
/// <param name="latitude"></param> |
|
/// <param name="bmapPoints"></param> |
|
/// <param name="isFromPunchRecord"></param> |
|
/// <returns></returns> |
|
private async Task<bool> Unlicensed(GetCaseInfoBySupervisedPersonIdOutput caseInfo, string name) |
|
{ |
|
//停留未许可场所预警 |
|
var Unlicensed = await base.GetDictionariesOutput("early_warning_type", "Unlicensed"); |
|
|
|
var earlyWarningRule = await _appEarlyWarningRuleRepository.FindAsync(w => |
|
w.EarlyWarningTypeId == Unlicensed.Id && |
|
w.SupervisedPersonId == caseInfo.SupervisedPersonId && |
|
w.CaseId == caseInfo.CaseId); |
|
var isPointInPolygon = false; |
|
if (earlyWarningRule == null) |
|
{ |
|
//LastIsPointInPolygon=true当前被监管人在未经允许的地方 false不在未经允许的地方 |
|
await _appEarlyWarningRuleRepository.InsertAsync(new AppEarlyWarningRule(YitIdHelper.NextId()) |
|
{ |
|
CaseId = caseInfo.CaseId, |
|
CaseName = caseInfo.CaseName, |
|
SupervisedPersonId = caseInfo.SupervisedPersonId, |
|
SupervisedPersonName = caseInfo.SupervisedPersonName, |
|
EarlyWarningTypeId = Unlicensed.Id, |
|
EarlyWarningTypeName = Unlicensed.Name + $"+{name}", |
|
LastIsPointInPolygon = false |
|
}); |
|
} |
|
else |
|
{ |
|
if (!earlyWarningRule.EarlyWarningTypeName.Contains(name)) |
|
{ |
|
earlyWarningRule.EarlyWarningTypeName = Unlicensed.Name + $"+{name}"; |
|
//更新上一次是否是在该地方停留 |
|
await _appEarlyWarningRuleRepository.UpdateAsync(earlyWarningRule, UpdatingProps<AppEarlyWarningRule>(x => x.LastIsPointInPolygon)!); |
|
} |
|
else |
|
{ |
|
earlyWarningRule.EarlyWarningTypeName = Unlicensed.Name + $"+{name}"; |
|
isPointInPolygon = true; |
|
} |
|
} |
|
return isPointInPolygon; |
|
} |
|
|
|
/// <summary> |
|
/// 添加预警和查看预警方法 |
|
/// </summary> |
|
/// <param name="addInput"></param> |
|
/// <param name="dtos"></param> |
|
/// <returns></returns> |
|
private async Task<List<AppEarlyWarningViewStatistics>> AddEarlyWithViews(AppEarlyWarningAddInput addInput, List<KeyValueDto> dtos) |
|
{ |
|
return dtos.Select(w => new AppEarlyWarningViewStatistics(YitIdHelper.NextId()) |
|
{ |
|
SupervisedName = w.Value, |
|
SubscriberId = w.Id, |
|
CaseId = addInput.CaseId, |
|
AppEarlyWarningId = addInput.Id ?? default |
|
}).ToList(); |
|
} |
|
|
|
/// <summary> |
|
/// 通过经纬度 获取poi |
|
/// </summary> |
|
/// <returns></returns> |
|
/// <remarks> |
|
/// </remarks> |
|
public async Task Getpoi(GetCaseInfoBySupervisedPersonIdOutput caseInfo, decimal longitude, decimal latitude, bool isFromPunchRecord) |
|
{ |
|
if (!string.IsNullOrEmpty(caseInfo.poitypename) && caseInfo.radius > 0 && caseInfo.rice > 0) |
|
{ |
|
//未许可场所预警 |
|
var Unlicensedtype = await base.GetDictionariesOutput("early_warning_type", "Unlicensed"); |
|
//通过字典获取地图key 密钥 |
|
var key = await base.GetDictionariesOutput("map_key", "map_key"); |
|
if (key == null) return; |
|
//获取被监管人当前位置的周边位置 |
|
var url = $"https://restapi.amap.com/v3/place/around?key={key.Value}&location={longitude},{latitude}&keywords={caseInfo.poitypename.Replace(",", "|")}&radius={caseInfo.radius}&offset=1000&page=1&extensions=all"; |
|
string requestString = ""; |
|
try |
|
{ |
|
Encoding myEncoding = Encoding.UTF8; |
|
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest; |
|
request.Method = "GET"; |
|
request.ContentType = "text/plain"; |
|
HttpWebResponse response = (HttpWebResponse)request.GetResponse(); |
|
StreamReader responseStream = new StreamReader(response.GetResponseStream(), myEncoding); |
|
requestString = responseStream.ReadToEnd(); |
|
var da = JsonConvert.DeserializeObject<dynamic>(requestString);//对象集合 requestString |
|
if (da.info == "OK") |
|
{ |
|
//判断当前人所在位置是否存在未经许可长时间停留 |
|
List<suggestion> list = JsonConvert.DeserializeObject<List<suggestion>>(da.pois + ""); |
|
var dalist = list.Where(q => q.distance.ToInt() <= caseInfo.rice); |
|
var name = dalist.OrderBy(q => q.distance.ToInt()).First()?.name; |
|
//长时间停留在未经许可的地方,添加一条预计信息 |
|
if (await Unlicensed(caseInfo, name)) |
|
{ |
|
_ = await ManualAddEarlyWarning(new EarlyWarningAddInput() |
|
{ |
|
EarlyWarningTypeId = Unlicensedtype.Id, |
|
SupervisedPersonId = caseInfo.SupervisedPersonId, |
|
address = name |
|
}); |
|
} |
|
} |
|
response.Close(); |
|
responseStream.Close(); |
|
} |
|
catch (Exception) |
|
{ |
|
} |
|
} |
|
} |
|
#endregion Private |
|
|
|
/// <summary> |
|
/// 根据时间范围查询预警信息 |
|
/// </summary> |
|
/// <param name="input"></param> |
|
/// <returns></returns> |
|
[HttpPost] |
|
public async Task<IResultOutput> GetEarlyWarningByTimeRangeAsync(AppEarlyWarningTimeRangeInput input) |
|
{ |
|
// 1. 验证时间范围不能为空 |
|
if (input.TimeSearch == null || input.TimeSearch.BeginTime == null || input.TimeSearch.EndTime == null) |
|
{ |
|
return ResultOutput.NotOk("开始时间和结束时间不能为空"); |
|
} |
|
// 2. 确保开始时间不晚于结束时间 |
|
if (input.TimeSearch.BeginTime > input.TimeSearch.EndTime) |
|
{ |
|
return ResultOutput.NotOk("开始时间不能晚于结束时间"); |
|
} |
|
|
|
// 3. 验证时间范围不能超过半年(183天) |
|
TimeSpan timeDiff = input.TimeSearch.EndTime.Value - input.TimeSearch.BeginTime.Value; |
|
if (timeDiff.TotalDays > 183) |
|
{ |
|
return ResultOutput.NotOk("查询时间范围不能超过半年"); |
|
} |
|
|
|
// 4. 获取当前用户有权限的案件ID列表 |
|
var caseIds = await (await base.GetCurrentUserCaseListAsync()).Select(w => w.AppCaseManagement.Id).ToListAsync(); |
|
|
|
// 5. 构建查询表达式 |
|
var beginTime = input.TimeSearch.BeginTime.Value; |
|
var endTime = input.TimeSearch.EndTime.Value; |
|
var query = _appEarlyWarningRepository.AsQueryable(false, true) |
|
.Where(w => caseIds.Contains(w.CaseId)) |
|
.Where(w => w.CreatedTime >= beginTime && w.CreatedTime <= endTime); |
|
|
|
// 6. 获取总数 |
|
var total = query.Count(); |
|
|
|
// 7. 分页查询 |
|
var items = await query |
|
.OrderByDescending(w => w.CreatedTime) |
|
.ProjectTo<AppEarlyWarningPushDto>(Mapper.ConfigurationProvider) |
|
.ToListAsync(); |
|
|
|
|
|
//8 补全监管人、监管人id、监管人手机号 |
|
var caseIdList = items.Select(w => w.CaseId).Distinct().ToList(); |
|
//9 根据案件ID查询监管人(可能多条) |
|
var dataCaseSupervise = await _appCaseManagementService.GetSupervisedPageAsync(new GetSuperviseorPage() { Ids = caseIdList }); |
|
//10 构建「案件ID → 该案件的所有监管人列表」的映射 |
|
var caseSupervisorMap = dataCaseSupervise |
|
.GroupBy(x => x.CaseId) // 按案件ID分组 |
|
.ToDictionary(g => g.Key, g => g.ToList()); // 分组结果转字典 |
|
|
|
var supervisorIdList = dataCaseSupervise.Select(w => w.SupervisorId).Distinct().ToList(); |
|
//11 根据监管人ID查询电话 |
|
var user = await _userService.GetAllByConditionAsync(new BatchIdsInput() { Ids = supervisorIdList }); |
|
//12 构建「监管人ID → 电话」的映射 |
|
var supervisorPhoneMap = user |
|
.ToDictionary(u => u.Id, u => u.Phone); // 监管人ID为Key,电话为Value |
|
// 生成新的案件列表(每个案件对应所有监管人) |
|
var newItems = new List<AppEarlyWarningPushDto>(); |
|
//13 脱离区域申请 |
|
var Unlicensedtype = await base.GetDictionariesOutput("early_warning_type", "LeaveAreaApplication"); |
|
//循环插入预警信息 |
|
foreach (var item in items) |
|
{ |
|
var caseId = item.CaseId; |
|
|
|
// 若该案件有监管人,遍历所有监管人生成新项 |
|
if (caseSupervisorMap.TryGetValue(caseId, out var supervisors)) |
|
{ |
|
foreach (var supervisor in supervisors) |
|
{ |
|
// 复制原案件信息(可通过 AutoMapper 简化,见下文) |
|
var newItem = new AppEarlyWarningPushDto(); |
|
newItem.Id = item.Id; |
|
newItem.CaseId = item.CaseId; |
|
newItem.CaseName = item.CaseName; |
|
newItem.Content = item.Content; |
|
newItem.UniqueIdentifier = item.UniqueIdentifier; |
|
newItem.DeviceId = item.DeviceId; |
|
newItem.DeviceName = item.DeviceName; |
|
newItem.EarlyWarningTypeId = item.EarlyWarningTypeId; |
|
newItem.EarlyWarningTypeName = item.EarlyWarningTypeName; |
|
newItem.Title = item.Title; |
|
newItem.CreatedTime = item.CreatedTime; |
|
newItem.SupervisedPersonId = item.SupervisedPersonId; |
|
newItem.SupervisedPersonName = item.SupervisedPersonName; |
|
// 填充监管人字段 |
|
newItem.SupervisorName = supervisor.SupervisorName; |
|
newItem.SupervisorId = supervisor.SupervisorId; |
|
newItem.BeginTime = beginTime; |
|
newItem.EndTime = endTime; |
|
// 从电话映射中获取监管人电话(处理空值) |
|
newItem.Phone = supervisorPhoneMap.TryGetValue(supervisor.SupervisorId, out var phone) |
|
? phone |
|
: string.Empty; |
|
//判断是否已经推送过 |
|
var pushList = await _appEarlyWarningPushResultRepository.AsQueryable(false, true) |
|
.Where(w => w.WarningId == newItem.Id && w.SupervisorId == supervisor.SupervisorId) |
|
.ProjectTo<AppEarlyWarningPushResultAddInput>(Mapper.ConfigurationProvider) |
|
.ToListAsync() |
|
.ConfigureAwait(false); |
|
|
|
newItem.PushFlag = pushList.Count > 0 ? "1" : "0"; |
|
newItems.Add(newItem); |
|
} |
|
} |
|
} |
|
//14 获取未处理的申请信息 |
|
var spBusApplication = await _appBusinessApplicationRepository.AsQueryable(false, true).Where(w => w.AuditStatus == AuditStatusEnum.PendingReview).ToListAsync(); |
|
if (spBusApplication.Count > 0) |
|
{ |
|
//8 补全监管人、监管人id、监管人手机号 |
|
var busCaseIdList = spBusApplication.Select(w => w.CaseId).Distinct().ToList(); |
|
//根据案件ID查询监管人(可能多条) |
|
dataCaseSupervise.Clear(); |
|
dataCaseSupervise = await _appCaseManagementService.GetSupervisedPageAsync(new GetSuperviseorPage() { Ids = busCaseIdList }); |
|
// 构建「案件ID → 该案件的所有监管人列表」的映射 |
|
caseSupervisorMap.Clear(); |
|
caseSupervisorMap = dataCaseSupervise |
|
.GroupBy(x => x.CaseId) // 按案件ID分组 |
|
.ToDictionary(g => g.Key, g => g.ToList()); // 分组结果转字典 |
|
supervisorIdList.Clear(); |
|
supervisorIdList = dataCaseSupervise.Select(w => w.SupervisorId).Distinct().ToList(); |
|
// 根据监管人ID查询电话 |
|
user.Clear(); |
|
user = await _userService.GetAllByConditionAsync(new BatchIdsInput() { Ids = supervisorIdList }); |
|
// 构建「监管人ID → 电话」的映射 |
|
supervisorPhoneMap.Clear(); |
|
supervisorPhoneMap = user |
|
.ToDictionary(u => u.Id, u => u.Phone); // 监管人ID为Key,电话为Value |
|
// 生成新的案件列表(每个案件对应所有监管人) |
|
|
|
|
|
foreach (var item in spBusApplication) |
|
{ |
|
var caseId = item.CaseId; |
|
// 若该案件有监管人,遍历所有监管人生成新项 |
|
if (caseSupervisorMap.TryGetValue(caseId, out var supervisors)) |
|
{ |
|
foreach (var supervisor in supervisors) |
|
{ |
|
// 复制原案件信息(可通过 AutoMapper 简化,见下文) |
|
var newItem = new AppEarlyWarningPushDto(); |
|
newItem.SupervisedPersonId = item.SupervisedPersonId; |
|
newItem.SupervisedPersonName = item.SupervisedPersonName; |
|
newItem.Content = item.ApplicationDescription; |
|
newItem.EarlyWarningTypeId = Unlicensedtype.Id; |
|
newItem.CaseId = item.CaseId; |
|
newItem.CreatedTime = item.CreatedTime; |
|
newItem.Id = item.Id; |
|
// 填充监管人字段 |
|
newItem.SupervisorName = supervisor.SupervisorName; |
|
newItem.SupervisorId = supervisor.SupervisorId; |
|
newItem.BeginTime = beginTime; |
|
newItem.EndTime = endTime; |
|
// 从电话映射中获取监管人电话(处理空值) |
|
newItem.Phone = supervisorPhoneMap.TryGetValue(supervisor.SupervisorId, out var phone) |
|
? phone |
|
: string.Empty; |
|
//判断是否已经推送过 |
|
var pushList = await _appEarlyWarningPushResultRepository.AsQueryable(false, true) |
|
.Where(w => w.WarningId == item.Id && w.SupervisorId == supervisor.SupervisorId) |
|
.ProjectTo<AppEarlyWarningPushResultAddInput>(Mapper.ConfigurationProvider) |
|
.ToListAsync() |
|
.ConfigureAwait(false); |
|
|
|
newItem.PushFlag = pushList.Count > 0 ? "1" : "0"; |
|
newItems.Add(newItem); |
|
} |
|
} |
|
} |
|
} |
|
//15 补充预警类型名称 |
|
var dictIds = newItems.Select(w => w.EarlyWarningTypeId).ToList(); |
|
var dataDict = await _appDictionaryService.GetDicByDicIds(new BatchIdsInput() { Ids = dictIds }); |
|
|
|
foreach (var item in newItems) |
|
{ |
|
item.EarlyWarningTypeName = dataDict.FirstOrDefault(w => w.Id == item.EarlyWarningTypeId)?.Name; |
|
} |
|
return ResultOutput.Ok(new PagedList<AppEarlyWarningPushDto>() |
|
{ |
|
Data = newItems, |
|
TotalCount = newItems.Count, // 展开后的总记录数 |
|
PageIndex = input.PageIndex, |
|
PageSize = input.PageSize |
|
}); |
|
} |
|
|
|
} |
|
/// <summary> |
|
/// poi model |
|
/// </summary> |
|
public class suggestion |
|
{ |
|
//类型 |
|
public string type { set; get; } |
|
//名称 |
|
public string name { set; get; } |
|
//详细地址 |
|
public string address { set; get; } |
|
//距离 |
|
public string distance { set; get; } |
|
} |
|
} |