Squashed commit of the following:

commit 528cdd51c05d26437f0b23f415e06311b667e9f7
Author: liguoyang <Ligy.97@foxmail.com>
Date:   Wed Apr 17 15:37:30 2024 +0800

    feat 访客预约

commit e73a3fcd9307f86aba2c39578495c03cde1d41f9
Author: liguoyang <Ligy.97@foxmail.com>
Date:   Tue Apr 16 16:15:16 2024 +0800

    feat 业务curd

commit b98b6e2764fea875866e11f790f388ccf3c234b5
Merge: a3dcec3 965e84b
Author: liguoyang <Ligy.97@foxmail.com>
Date:   Tue Apr 16 14:56:30 2024 +0800

    Merge branch 'feat-visitorAppointments' of https://git.dlhis.com/liguoyang/jinko.yikatong into feat-visitorAppointments

commit a3dcec30e1289fbb09de8f85009d3931d971337a
Author: liguoyang <Ligy.97@foxmail.com>
Date:   Fri Apr 12 17:57:49 2024 +0800

    fix appsettings

commit 766fbec0c45a3852a75a7a37686b885ac3b0a77a
Author: liguoyang <Ligy.97@foxmail.com>
Date:   Fri Apr 12 17:37:01 2024 +0800

    add dockerfile

commit 86731d41fee97ba073065ed1b807987760a371a7
Author: liguoyang <Ligy.97@foxmail.com>
Date:   Sun Apr 14 20:11:56 2024 +0800

    fix 测试websocket链接

commit 1301b126a9ba9a7d97cf45967cf2915e1169c505
Author: liguoyang <Ligy.97@foxmail.com>
Date:   Fri Apr 12 17:57:49 2024 +0800

    fix appsettings

commit 081f3a67896c67891c3f80edde82a440b8736851
Author: liguoyang <Ligy.97@foxmail.com>
Date:   Fri Apr 12 17:37:01 2024 +0800

    add dockerfile

commit 271b6c5898b5732a35ccfa0629ce89442ac49143
Author: liguoyang <Ligy.97@foxmail.com>
Date:   Fri Apr 12 17:34:26 2024 +0800

    test 提交测试代码

commit 965e84b6f3b7f925f8021c9b996cce961b896dea
Merge: 578eb6a 6a6fad1
Author: liguoyang <Ligy.97@foxmail.com>
Date:   Mon Apr 15 17:06:45 2024 +0800

    Merge branch 'feat-visitorAppointments' of https://git.dlhis.com/liguoyang/jinko.yikatong into feat-visitorAppointments

commit 578eb6afbd96f0bfe4aaf8058fd4743309c74d62
Author: liguoyang <Ligy.97@foxmail.com>
Date:   Sun Apr 14 20:11:56 2024 +0800

    fix 测试websocket链接

commit 114511f1daea64b7dbf9c3c38b73e28b6d0301e6
Author: liguoyang <Ligy.97@foxmail.com>
Date:   Fri Apr 12 17:57:49 2024 +0800

    fix appsettings

commit 5eacfa8af8087eade8553266a12a2cf42305716b
Author: liguoyang <Ligy.97@foxmail.com>
Date:   Fri Apr 12 17:37:01 2024 +0800

    add dockerfile

commit b2ffff1f099be343d89690014d05cb859776acbb
Author: liguoyang <Ligy.97@foxmail.com>
Date:   Fri Apr 12 17:34:26 2024 +0800

    test 提交测试代码

commit 6a6fad1d1b8772eebf5df12cd74cfd5c955ff560
Author: liguoyang <Ligy.97@foxmail.com>
Date:   Sun Apr 14 20:11:56 2024 +0800

    fix 测试websocket链接

commit 9ce3c4d6f63957c175d65370d9a6b80e10f4254f
Author: liguoyang <Ligy.97@foxmail.com>
Date:   Fri Apr 12 17:57:49 2024 +0800

    fix appsettings

commit c637fd89850cf289d7da457c6c6f47354b5beed3
Author: liguoyang <Ligy.97@foxmail.com>
Date:   Fri Apr 12 17:37:01 2024 +0800

    add dockerfile

commit 58c39815b1c45a99aea0caf503fcb1365c957f03
Author: liguoyang <Ligy.97@foxmail.com>
Date:   Fri Apr 12 17:34:26 2024 +0800

    test 提交测试代码
This commit is contained in:
2024-04-17 15:38:25 +08:00
parent 4b6d29291f
commit f8d1997ddd
68 changed files with 2086 additions and 412 deletions

View File

@@ -0,0 +1,25 @@
using Dlhis.Entity.Device.Enums;
namespace Dlhis.ScheduledTask.TaskAssignment.Dto;
public class TaskDto
{
public long TaskId { get; set; }
public long? UserId { get; set; }
public DeviceTaskEnumType Type { get; set; }
public string DeviceUniqueNo { get; set; }
public string DeviceConnectionInfo { get; set; }
public string Brand { get; set; }
public string FuncStr { get; set; }
public string UserNo { get; set; }
public string UserCode { get; set; }
public string UserName { get; set; }
public string DepartmentNo { get; set; }
public string DepartmentName { get; set; }
public string CardNo { get; set; }
public int Version { get; set; }
public DeviceTaskStatusEnumType Status { get; set; }
}

View File

@@ -13,6 +13,7 @@ using Newtonsoft.Json.Linq;
using Kurisu.Core.CustomClass;
using Kurisu.AspNetCore;
using Kurisu.AspNetCore.Utils;
using Dlhis.ScheduledTask.TaskAssignment.Dto;
namespace Dlhis.ScheduledTask.TaskAssignment.Services.Implements;
@@ -21,248 +22,158 @@ public class AssignmentService : IAssignmentService
private readonly IDbContext _dbContext;
private readonly IDataProtectionProvider _dataProtectionProvider;
private readonly FaceUrlOptions _faceUrlOptions;
private readonly ILogger<AssignmentService> _logger;
public AssignmentService(IDbContext dbContext,
IDataProtectionProvider dataProtectionProvider,
IOptions<FaceUrlOptions> options,
ILogger<AssignmentService> logger)
IOptions<FaceUrlOptions> options)
{
_dbContext = dbContext;
_dataProtectionProvider = dataProtectionProvider;
_faceUrlOptions = options.Value;
_logger = logger;
}
public async Task<List<DeviceTaskToDeviceByDeviceResponse>> DeviceGetTasksAsync(DeviceTaskGetRequest request)
{
////获取心跳设备 todo
//var key = "heardbeat-devices";
//var heartbeatDeviceNos = (await _redisCache.ListRangeAsync(key))?.Select(x => x.ToString()).ToList();
var data = await GetDataAsync(request);
if (data.IsEmpty()) return new List<DeviceTaskToDeviceByDeviceResponse>();
var data = await CommonHelper.RetryAsync(async () =>
{
var page = await _dbContext.Queryable<DeviceTaskEntity>()
.LeftJoin<DeviceEntity>((deviceTask, deivce) => deviceTask.DeviceUniqueNo == deivce.UniqueNo)
.LeftJoin<DeviceTemplateEntity>((deviceTask, deivce, deivceTamplate) => deivceTamplate.Code == deivce.TemplateCode)
.LeftJoin<GainfoEntity>((deviceTask, deivce, deivceTamplate, ga) => deviceTask.UserNo == ga.No)
.LeftJoin<GainfoLeaveEntity>((deviceTask, deivce, deivceTamplate, ga, galeave) => deviceTask.UserNo == galeave.No)
.LeftJoin<DepartmentEntity>((deviceTask, deivce, deivceTamplate, ga, galeave, department) => department.No == ga.DepartmentNo)
.WhereIF(request.Brand.IsPresent(), (deviceTask, deivce, deivceTamplate) => deivceTamplate.Brand == request.Brand)
.WhereIF(request.DeviceUniqueNo.IsPresent(), (deviceTask, deivce) => deviceTask.DeviceUniqueNo == request.DeviceUniqueNo)
.WhereIF(request.Types.IsPresent(), deviceTask => request.Types.Contains(deviceTask.Type))
.WhereIF(!request.IsProcess, deviceTask => deviceTask.Status == DeviceTaskStatusEnumType.Wait)
.WhereIF(request.IsProcess, deviceTask => deviceTask.Status == DeviceTaskStatusEnumType.Process
&& SqlFunc.DateDiff(DateType.Minute, deviceTask.ModifiedTime, DateTime.Now) > 30)
//.Where(deviceTask => heartbeatDeviceNos.Contains(deviceTask.DeviceUniqueNo))
.OrderBy(deviceTask => new { Priority = SqlFunc.Desc(deviceTask.Priority), deviceTask.CreateTime })
.Select((deviceTask, deivce, deivceTamplate, ga, galeave, department) => new
{
UserId = SqlFunc.IsNull(SqlFunc.IsNull(deviceTask.UserId, ga.Id), galeave.IdentityUserId),
TaskId = deviceTask.Id,
deviceTask.Type,
deviceTask.DeviceUniqueNo,
DeviceConnectionInfo = deivce.ConnectionInfo,
deivceTamplate.Brand,
FuncStr = deivce.Funcs.ToString(),
deviceTask.UserNo,
UserCode = SqlFunc.IsNull(ga.Code, galeave.Code),
UserName = SqlFunc.IsNull(ga.Name, galeave.Name),
ga.DepartmentNo,
DepartmentName = department.Name,
ga.CardNo,
deviceTask.Version
})
.ToPageListAsync(request);
if (!page.Data.Any())
{
return page.Data;
}
var taskIdVs = page.Data.Select(x => new { x.TaskId, x.Version }).ToList();
var where = LinqExpressionExtensions.False<DeviceTaskEntity>();
taskIdVs.ForEach(p =>
{
where = where.Or(x => x.Id == p.TaskId && x.Version == p.Version && x.Status != DeviceTaskStatusEnumType.Success);
});
var effecet = await _dbContext.Updateable<DeviceTaskEntity>()
.SetColumns(x => x.Version == x.Version + 1)
.SetColumns(x => x.Status == DeviceTaskStatusEnumType.Process)
.SetColumns(x => x.ModifiedTime == DateTime.Now)
.Where(where)
.ExecuteCommandAsync();
(taskIdVs.Count != effecet).ThrowIfTrue("获取任务失败");
return page.Data;
}, 5);
if (!data.Any())
{
return new List<DeviceTaskToDeviceByDeviceResponse>();
}
Dictionary<string, DateTime?> deviceUploadInfos = null;
if (data.Any(x => x.Type == DeviceTaskEnumType.UploadRecord))
{
var deviceNos = data.Select(x => x.DeviceUniqueNo).Distinct();
deviceUploadInfos = new Dictionary<string, DateTime?>(deviceNos.Count());
var logInfos = await _dbContext.Queryable<DeviceUploadLogEntity>().Select(it => new
{
RowNumber = SqlFunc.RowNumber(SqlFunc.Desc(it.Id), it.DeviceUniqueNo),
it.DeviceUniqueNo,
it.RaiseDateTime
})
.MergeTable()
.Where(it => it.RowNumber == 1)
.ToListAsync();
foreach (var item in deviceNos)
{
var logInfo = logInfos.FirstOrDefault(x => x.DeviceUniqueNo == item);
deviceUploadInfos.Add(item, logInfo?.RaiseDateTime);
}
}
var deviceUploadInfos = await GetDeviceUploadRecordInfosAsync(data);
var timeLimitedDataProtector = _dataProtectionProvider
.CreateProtector("down:face")
.ToTimeLimitedDataProtector();
return data.GroupBy(x => new { x.Brand, x.DeviceUniqueNo, x.DeviceConnectionInfo, x.FuncStr })
.Select(x =>
{
var b = x.Key.Brand;
var d = x.Key.DeviceUniqueNo;
var dc = x.Key.DeviceConnectionInfo ?? "{}";
var func = x.Key.FuncStr ?? "[]";
.Select(x =>
{
var b = x.Key.Brand;
var d = x.Key.DeviceUniqueNo;
var dc = x.Key.DeviceConnectionInfo ?? "{}";
var func = x.Key.FuncStr ?? "[]";
var jobj = new JObject
{
{ "connectionInfo", JToken.Parse(dc) },
{ "function", JArray.Parse(func) }
};
var jobj = new JObject
{
{ "connectionInfo", JToken.Parse(dc) },
{ "function", JArray.Parse(func) }
};
return new DeviceTaskToDeviceByDeviceResponse
{
Brand = b,
DeviceUniqueNo = d,
DeviceInfo = jobj,
Tasks = x.AsEnumerable().Select(item =>
{
var key = $"face:{item.UserCode}";
var token = item.Type == DeviceTaskEnumType.Delete
? string.Empty
: timeLimitedDataProtector.Protect(key, TimeSpan.FromSeconds(_faceUrlOptions.Limit));
return new DeviceTaskToDeviceByDeviceResponse
{
Brand = b,
DeviceUniqueNo = d,
DeviceInfo = jobj,
Tasks = x.Select(item =>
{
var key = $"face:{item.UserCode}";
var token = item.Type == DeviceTaskEnumType.Delete
? string.Empty
: timeLimitedDataProtector.Protect(key, TimeSpan.FromSeconds(_faceUrlOptions.Limit));
var dto = new TaskCombineDto
{
TaskId = item.TaskId,
Type = item.Type,
};
var dto = new TaskCombineDto
{
TaskId = item.TaskId,
Type = item.Type,
};
switch (dto.Type)
{
case DeviceTaskEnumType.Add:
case DeviceTaskEnumType.Delete:
case DeviceTaskEnumType.Update:
{
dto.Info = new UserToDeviceResponse
{
UserId = item.UserId.Value,
UserNo = item.UserNo,
UserCode = item.UserCode,
UserName = item.UserName,
DepartmentNo = item.DepartmentNo,
DepartmentName = item.DepartmentName,
CardNo = item.Type == DeviceTaskEnumType.Delete ? string.Empty : item.CardNo,
Face = item.Type == DeviceTaskEnumType.Delete ? string.Empty : _faceUrlOptions.Url + token,//下发才附带照片信息
ValidDatePeriod = new DatePeriod
{
Start = DateOnly.FromDateTime(DateTime.Now.AddDays(-1)),
End = DateOnly.FromDateTime(DateTime.Now.AddYears(20)),
},
TimePeriods = new List<int> { 1 },
Doors = new List<int> { 1 },
Schedule = 1
};
}
break;
case DeviceTaskEnumType.TimePeriodAdd:
case DeviceTaskEnumType.TimePeriodDelete:
{
dto.Info = new TimePeriodToDeviceResponse
{
Id = 1,
Name = "小白领",
Enable = true,
Sections = new List<TimePeriodWeekDaySection>()
{
new()
{
DayOfWeek= DayOfWeek.Monday,
TimePeriods = new List<TimePeriod>()
{
new()
{
Start = TimeOnly.Parse("08:00:00"),
End = TimeOnly.Parse("17:30:00"),
},
}
}
}
};
}
break;
case DeviceTaskEnumType.ScheduleAdd:
case DeviceTaskEnumType.ScheduleDelete:
{
dto.Info = new ScheduleToDeviceResponse
{
Id = 1,
Enable = true,
Name = "计划的一部分",
Schedules = new List<ScheduleDto>
{
new()
{
Name = "国庆节",
DateTimePeriod = new DateTimePeriod
switch (dto.Type)
{
case DeviceTaskEnumType.Add:
case DeviceTaskEnumType.Delete:
case DeviceTaskEnumType.Update:
{
dto.Info = new UserToDeviceResponse
{
UserId = item.UserId.HasValue ? item.UserId.Value : 0,
UserNo = item.UserNo,
UserCode = item.UserCode,
UserName = item.UserName,
DepartmentNo = item.DepartmentNo,
DepartmentName = item.DepartmentName,
CardNo = item.Type == DeviceTaskEnumType.Delete ? string.Empty : item.CardNo,
Face = item.Type == DeviceTaskEnumType.Delete ? string.Empty : _faceUrlOptions.Url + token,//下发才附带照片信息
ValidDatePeriod = new DatePeriod
{
Start = DateOnly.FromDateTime(DateTime.Now.AddDays(-1)),
End = DateOnly.FromDateTime(DateTime.Now.AddYears(20)),
},
TimePeriods = new List<int> { 1 },
Doors = new List<int> { 1 },
Schedule = 1
};
}
break;
case DeviceTaskEnumType.TimePeriodAdd:
case DeviceTaskEnumType.TimePeriodDelete:
{
dto.Info = new TimePeriodToDeviceResponse
{
Id = 1,
Name = "小白领",
Enable = true,
Sections = new List<TimePeriodWeekDaySection>()
{
new()
{
DayOfWeek= DayOfWeek.Monday,
TimePeriods = new List<TimePeriod>()
{
Start = new DateTime(2024,10,1),
End = new DateTime(2024,10,7)
new()
{
Start = TimeOnly.Parse("08:00:00"),
End = TimeOnly.Parse("17:30:00"),
},
}
}
}
};
}
break;
}
}
};
}
break;
case DeviceTaskEnumType.ScheduleAdd:
case DeviceTaskEnumType.ScheduleDelete:
{
dto.Info = new ScheduleToDeviceResponse
{
Id = 1,
Enable = true,
Name = "计划的一部分",
Schedules = new List<ScheduleDto>
{
new()
{
Name = "国庆节",
DateTimePeriod = new DateTimePeriod
{
Start = new DateTime(2024,10,1),
End = new DateTime(2024,10,7)
}
}
}
};
}
break;
case DeviceTaskEnumType.UploadRecord:
{
dto.Info = new UploadRecordToDeviceResponse
{
DateTimePeriod = new DateTimePeriod
{
Start = deviceUploadInfos[d] ?? DateTime.Now,
End = DateTime.Now.AddDays(1)
}
};
}
break;
default:
break;
}
case DeviceTaskEnumType.UploadRecord:
{
dto.Info = new UploadRecordToDeviceResponse
{
DateTimePeriod = new DateTimePeriod
{
Start = deviceUploadInfos[d] ?? DateTime.Now,
End = DateTime.Now.AddDays(1)
}
};
}
break;
default:
break;
}
return dto;
return dto;
}).ToList()
};
}).ToList()
};
}).ToList();
}).ToList();
}
/// <summary>
@@ -314,4 +225,101 @@ public class AssignmentService : IAssignmentService
await _dbContext.UpdateAsync(deviceTasks);
}
//**************************************************** help method **************************************************
private async Task<List<TaskDto>> GetDataAsync(DeviceTaskGetRequest request)
{
var data = await CommonHelper.RetryAsync(async () =>
{
var page = await _dbContext.Queryable<DeviceTaskEntity>()
.LeftJoin<DeviceEntity>((deviceTask, deivce) => deviceTask.DeviceUniqueNo == deivce.UniqueNo)
.LeftJoin<DeviceTemplateEntity>((deviceTask, deivce, deivceTamplate) => deivceTamplate.Code == deivce.TemplateCode)
.LeftJoin<GainfoEntity>((deviceTask, deivce, deivceTamplate, ga) => deviceTask.UserNo == ga.No)
.LeftJoin<GainfoLeaveEntity>((deviceTask, deivce, deivceTamplate, ga, galeave) => deviceTask.UserNo == galeave.No)
.LeftJoin<DepartmentEntity>((deviceTask, deivce, deivceTamplate, ga, galeave, department) => department.No == ga.DepartmentNo)
.LeftJoin<GainfoExternalEntity>((deviceTask, deivce, deivceTamplate, ga, galeave, department, gainfoEx) => deviceTask.UserNo == gainfoEx.No)
.WhereIF(!request.IsProcess, deviceTask => deviceTask.Status == DeviceTaskStatusEnumType.Wait)
.WhereIF(request.IsProcess, deviceTask => deviceTask.Status == DeviceTaskStatusEnumType.Process
&& SqlFunc.DateDiff(DateType.Minute, deviceTask.ModifiedTime, DateTime.Now) > 30)
.WhereIF(request.DeviceUniqueNo.IsPresent(), (deviceTask, deivce) => deviceTask.DeviceUniqueNo == request.DeviceUniqueNo)
.WhereIF(request.Types.IsPresent(), deviceTask => request.Types.Contains(deviceTask.Type))
.WhereIF(request.Brand.IsPresent(), (deviceTask, deivce, deivceTamplate) => deivceTamplate.Brand == request.Brand)
.OrderBy(deviceTask => new { Priority = SqlFunc.Desc(deviceTask.Priority), deviceTask.CreateTime })
.Select((deviceTask, deivce, deivceTamplate, ga, galeave, department, gainfoEx) => new TaskDto
{
UserId = SqlFunc.IsNull(SqlFunc.IsNull(deviceTask.UserId, ga.Id), galeave.IdentityUserId),
TaskId = deviceTask.Id,
Type = deviceTask.Type,
DeviceUniqueNo = deviceTask.DeviceUniqueNo,
DeviceConnectionInfo = deivce.ConnectionInfo,
Brand = deivceTamplate.Brand,
FuncStr = deivce.Funcs.ToString(),
UserNo = deviceTask.UserNo,
UserCode = SqlFunc.IsNull(SqlFunc.IsNull(ga.Code, galeave.Code), gainfoEx.Code),
UserName = SqlFunc.IsNull(SqlFunc.IsNull(ga.Name, galeave.Name), gainfoEx.Name),
DepartmentNo = ga.DepartmentNo,
DepartmentName = department.Name,
CardNo = ga.CardNo,
Version = deviceTask.Version,
Status = deviceTask.Status
})
.ToPageListAsync(request);
if (!page.Data.Any())
{
return page.Data;
}
//var taskIdVs = page.Data.Select(x => new { x.TaskId, x.Version, x.Status }).ToList();
//var where = LinqExpressionExtensions.False<DeviceTaskEntity>();
//taskIdVs.ForEach(p =>
//{
// where = where.Or(x => x.Id == p.TaskId && x.Version == p.Version && x.Status == p.Status);
//});
//var effecet = await _dbContext.Updateable<DeviceTaskEntity>()
// .SetColumns(x => x.Version == x.Version + 1)
// .SetColumns(x => x.Status == DeviceTaskStatusEnumType.Process)
// .SetColumns(x => x.ModifiedTime == DateTime.Now)
// .Where(where)
// .ExecuteCommandAsync();
//(taskIdVs.Count != effecet).ThrowIfTrue("获取任务失败");
return page.Data;
}, 5);
return data;
}
private async Task<Dictionary<string, DateTime?>> GetDeviceUploadRecordInfosAsync(List<TaskDto> data)
{
if (data.Any(x => x.Type == DeviceTaskEnumType.UploadRecord))
{
var deviceNos = data.Select(x => x.DeviceUniqueNo).Distinct();
var result = new Dictionary<string, DateTime?>(deviceNos.Count());
//日志数据最后一条
var logInfos = await _dbContext.Queryable<DeviceUploadLogEntity>().Select(it => new
{
RowNumber = SqlFunc.RowNumber(SqlFunc.Desc(it.Id), it.DeviceUniqueNo),
it.DeviceUniqueNo,
it.RaiseDateTime
})
.MergeTable()
.Where(it => it.RowNumber == 1)
.ToListAsync();
foreach (var item in deviceNos)
{
var logInfo = logInfos.FirstOrDefault(x => x.DeviceUniqueNo == item);
result.Add(item, logInfo?.RaiseDateTime);
}
}
return new Dictionary<string, DateTime?>();
}
}