This commit is contained in:
tanglong 2026-03-16 10:33:46 +08:00
parent 3fb2268bb0
commit 1666169397
25 changed files with 143 additions and 135 deletions

View File

@ -1,6 +0,0 @@
C:\Users\tangl\Desktop\Git\YD_AllHeartRates.Api\YD_AllHeartRates.Api\Fakes\YD_AllHeartRates.Commons.fakes : warning : 无法为 YD_AllHeartRates.Commons.Dto.ResponseMsg 生成存根: 类型没有对程序集可见的构造函数。构造函数本身或参数可能不可见。。
C:\Users\tangl\Desktop\Git\YD_AllHeartRates.Api\YD_AllHeartRates.Api\Fakes\YD_AllHeartRates.Commons.fakes : warning : 无法为 YD_AllHeartRates.Commons.MemoryCaches.MemoryCacheSetup 生成存根: 类型没有对程序集可见的构造函数。构造函数本身或参数可能不可见。。
C:\Users\tangl\Desktop\Git\YD_AllHeartRates.Api\YD_AllHeartRates.Api\Fakes\YD_AllHeartRates.Commons.fakes : warning : 无法为 YD_AllHeartRates.Commons.Middlewares.SystemExceptionApplicationBuilderExtensions 生成存根: 类型没有对程序集可见的构造函数。构造函数本身或参数可能不可见。。
C:\Users\tangl\Desktop\Git\YD_AllHeartRates.Api\YD_AllHeartRates.Api\Fakes\YD_AllHeartRates.Commons.fakes : warning : 无法为 YD_AllHeartRates.Commons.Utils.Util 生成存根: 类型没有对程序集可见的构造函数。构造函数本身或参数可能不可见。。
C:\Users\tangl\Desktop\Git\YD_AllHeartRates.Api\YD_AllHeartRates.Api\Fakes\YD_AllHeartRates.Commons.fakes : warning : 正在跳过 method System.Int32 YD_AllHeartRates.Commons.Utils.Util.GetRank(!!0 score),method System.Int32 YD_AllHeartRates.Commons.Utils.Util.GetRank(!!0 score) unstubbable: 无法同时指定类约束和 "class" 或 "struct" 约束
C:\Users\tangl\Desktop\Git\YD_AllHeartRates.Api\YD_AllHeartRates.Api\Fakes\YD_AllHeartRates.Commons.fakes : warning : 正在跳过 method System.String YD_AllHeartRates.Commons.Utils.Util.GetRankStr(!!0 score),method System.String YD_AllHeartRates.Commons.Utils.Util.GetRankStr(!!0 score) unstubbable: 无法同时指定类约束和 "class" 或 "struct" 约束

View File

@ -1,4 +1,5 @@
using Newtonsoft.Json; using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using System; using System;
using YD_AllHeartRates.Api.Context; using YD_AllHeartRates.Api.Context;
using YD_AllHeartRates.Api.Entitys; using YD_AllHeartRates.Api.Entitys;
@ -30,34 +31,34 @@ namespace YD_AllHeartRates.Api.Middlewares
"方欣玥", "方欣玥",
"宫恩佑", "宫恩佑",
"郭依诺", "郭依诺",
"黄子熙", //"黄子熙",
"计永安", //"计永安",
"蒋圣煊", //"蒋圣煊",
"李锦娴", //"李锦娴",
"李语汐", //"李语汐",
"李梓皓", //"李梓皓",
"刘家耀", //"刘家耀",
"龙正柏瑀", //"龙正柏瑀",
"罗昕", //"罗昕",
"聂新淼", //"聂新淼",
"彭禹凡", //"彭禹凡",
"宋皓晨", //"宋皓晨",
"孙海翔", //"孙海翔",
"唐瀚宇", //"唐瀚宇",
"陶柔紫若", //"陶柔紫若",
"万欣怡", //"万欣怡",
"王心语", //"王心语",
"王梓皓", //"王梓皓",
"王梓煜", //"王梓煜",
"徐子琪", //"徐子琪",
"许穆晨", //"许穆晨",
"杨温馨", //"杨温馨",
"杨子墨", //"杨子墨",
"袁洛霏", //"袁洛霏",
"张宸溪", //"张宸溪",
"张羽曦", //"张羽曦",
"赵昊辰", //"赵昊辰",
"周舒洋" //"周舒洋"
}; };
private static string[] ZhengDa = new string[] private static string[] ZhengDa = new string[]
@ -72,30 +73,30 @@ namespace YD_AllHeartRates.Api.Middlewares
"朱灏辰", "朱灏辰",
"王叡之", "王叡之",
"施梓俊", "施梓俊",
"龚怡豪", //"龚怡豪",
"张子赫", //"张子赫",
"仇泽宇", //"仇泽宇",
"陈歆蕾", //"陈歆蕾",
"朱旖文", //"朱旖文",
"郭笑笑", //"郭笑笑",
"陈瑾萱", //"陈瑾萱",
"蔡乐妮", //"蔡乐妮",
"侯熙琰", //"侯熙琰",
"龚思涵", //"龚思涵",
"朱瑾萱", //"朱瑾萱",
"宋依涵", //"宋依涵",
"顾渝尧", //"顾渝尧",
"张赛文", //"张赛文",
"沈美夕", //"沈美夕",
"吴佳凤", //"吴佳凤",
"蒋添依", //"蒋添依",
"茅苹苹", //"茅苹苹",
"李腾宇", //"李腾宇",
"林少熙", //"林少熙",
"史梓晨", //"史梓晨",
"丁文洁", //"丁文洁",
"董利妍", //"董利妍",
"朱紫芸" //"朱紫芸"
}; };
private readonly List<StudentCacheInfo> _students = new(); private readonly List<StudentCacheInfo> _students = new();
@ -175,7 +176,7 @@ namespace YD_AllHeartRates.Api.Middlewares
} }
public Task StartAsync(CancellationToken cancellationToken) public Task StartAsync(CancellationToken cancellationToken)
{ {
// 每分钟检查一次时间,看是否在8-16点并整点执行 // 每分钟检查一次时间,看是否在8-16点并整点执行
_timer = new Timer(async _ => await DoWork(), null, TimeSpan.Zero, TimeSpan.FromMinutes(1)); _timer = new Timer(async _ => await DoWork(), null, TimeSpan.Zero, TimeSpan.FromMinutes(1));
return Task.CompletedTask; return Task.CompletedTask;
@ -185,60 +186,69 @@ namespace YD_AllHeartRates.Api.Middlewares
{ {
var now = DateTime.Now; var now = DateTime.Now;
var heartRateDatas = new List<HeartRateData>(); // 每天 8:30 ~ 18:30 每小时30分执行
if (now.Hour < 8 || now.Hour > 18 || now.Minute != 23)
return;
// 每天 8:30 ~ 18:30,每小时的第 30 分钟执行 var startTime = now.AddHours(-1);
if (now.Hour >= 8 && now.Hour <= 18 && now.Minute == 30) var endTime = now;
Console.WriteLine($"[{now}] 开始统计心率数据 {startTime} ~ {endTime}");
try
{ {
var random = new Random(); // 1 查询1小时心率数据,并按分钟计算平均值
var list = await _userContext.HeartRateData
.Where(x => x.SchoolCode == AppSettings.SchoolCode && x.ScoreTime >= startTime && x.ScoreTime <= endTime)
.GroupBy(x => new
{
x.StudentNo,
Minute = new DateTime(
x.ScoreTime.Year,
x.ScoreTime.Month,
x.ScoreTime.Day,
x.ScoreTime.Hour,
x.ScoreTime.Minute,
0)
})
.Select(g => new
{
g.Key.StudentNo,
Minute = g.Key.Minute,
AvgValue = g.Average(x => x.Value),
AvgInstant = g.Average(x => x.InstantValue)
})
.ToListAsync();
// 2 按学生分组(提高查找效率)
var groups = list
.GroupBy(x => x.StudentNo)
.ToDictionary(
x => x.Key,
x => x.OrderBy(t => t.Minute).ToList()
);
var data = new List<StudentData>(); var data = new List<StudentData>();
// 3 生成推送数据
for (int i = 0; i < _students.Count; i++) for (int i = 0; i < _students.Count; i++)
{ {
var stu = _students[i]; // 学生完整信息(含学校/班级/姓名/EduId) var stu = _students[i];
var hdsjList = new List<HeartRateRecordDto>();
// 从当前时间往前推 59 分钟 if (!groups.TryGetValue(stu.EduId, out var stuData))
var recordTime = now.AddMinutes(-59); continue;
for (int j = 0; j < 60; j++) var hdsjList = stuData.Select(x => new HeartRateRecordDto
{ {
var xl = random.Next(70, 111); SJSJ = x.Minute.ToString("yyyy-MM-dd HH:mm:ss"),
var jxxl = random.Next(60, 91); XL = (int)Math.Round(x.AvgValue),
hdsjList.Add(new HeartRateRecordDto JXXL = (int)Math.Round(x.AvgInstant)
{ }).ToList();
SJSJ = recordTime.ToString("yyyy-MM-dd HH:mm:ss"),
XL = xl,
JXXL = jxxl
});
recordTime = recordTime.AddMinutes(1); // 间隔 1 分钟 // 保证每个学生60条数据
if (hdsjList.Count == 0)
continue;
heartRateDatas.Add(new HeartRateData()
{
SchoolCode = stu.School,
Area = "本部",
Code = stu.EduId,
GradeName = stu.Grade,
ClassName = stu.ClassName,
GradeId = 1,
ClassId = 1,
StudentName = stu.Name,
Sex = 0,
Consumption = 0,
CreateTime = now,
UploadTime = now,
Value = xl,
InstantValue = jxxl,
ScoreTime = recordTime,
MotionDuration = 0,
Strength = 0,
QuantityOfElectricity = 0,
StudentNo = stu.EduId
});
}
// SBID = 设备编号(按顺序递增)
var student = new StudentData var student = new StudentData
{ {
SBID = (i + 1).ToString("D2"), SBID = (i + 1).ToString("D2"),
@ -249,32 +259,26 @@ namespace YD_AllHeartRates.Api.Middlewares
data.Add(student); data.Add(student);
Console.WriteLine( Console.WriteLine(
$"生成数据 → {stu.School}-{stu.Grade}-{stu.ClassName}-{stu.Name} | EduId:{stu.EduId}"); $"生成数据 → {stu.School}-{stu.Grade}-{stu.ClassName}-{stu.Name} | EduId:{stu.EduId} | {hdsjList.Count}条");
} }
try // 4 推送数据
if (data.Count > 0)
{ {
var res = await _dataPushService.SportsRoutineReport(data); var res = await _dataPushService.SportsRoutineReport(data);
Console.WriteLine($"[{DateTime.Now}] HeartRate job code:{res?.code} msg:{res?.msg}");
}
catch (Exception ex)
{
Console.WriteLine($"[{DateTime.Now}] HeartRate job msg:{ex.Message}");
}
try
{
await _userContext.HeartRateData.AddRangeAsync(heartRateDatas);
await _userContext.SaveChangesAsync();
Console.WriteLine($"[{DateTime.Now}] HeartRate Add:{heartRateDatas.Count}");
Console.WriteLine(
$"[{DateTime.Now}] HeartRate job code:{res?.code} msg:{res?.msg} 学生数:{data.Count}");
} }
catch (Exception ex) else
{ {
Console.WriteLine($"[{DateTime.Now}] HeartRate Add:{ex.Message}"); Console.WriteLine($"[{DateTime.Now}] 无心率数据需要推送");
} }
} }
catch (Exception ex)
{
Console.WriteLine($"[{DateTime.Now}] HeartRate job error:{ex.Message}");
}
} }
public Task StopAsync(CancellationToken cancellationToken) public Task StopAsync(CancellationToken cancellationToken)

View File

@ -83,7 +83,7 @@ namespace YD_AllHeartRates.Api
// ③ 后台批量写库服务 // ③ 后台批量写库服务
services.AddHostedService<MqttBackgroundService>(); services.AddHostedService<MqttBackgroundService>();
//services.AddHostedService<SportsRoutineReportJob>(); services.AddHostedService<SportsRoutineReportJob>();
services.AddSingleton<JwtHelper>(); services.AddSingleton<JwtHelper>();

View File

@ -14,10 +14,10 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("YD_AllHeartRates.Api")] [assembly: System.Reflection.AssemblyCompanyAttribute("YD_AllHeartRates.Api")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+6050a80567dfcfd8b1a4733dae47b778e8de45f0")] [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+3fb2268bb010dba28589cdc7a4186a566f598d0c")]
[assembly: System.Reflection.AssemblyProductAttribute("YD_AllHeartRates.Api")] [assembly: System.Reflection.AssemblyProductAttribute("YD_AllHeartRates.Api")]
[assembly: System.Reflection.AssemblyTitleAttribute("YD_AllHeartRates.Api")] [assembly: System.Reflection.AssemblyTitleAttribute("YD_AllHeartRates.Api")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
// 由 MSBuild WriteCodeFragment 类生成。 // Generated by the MSBuild WriteCodeFragment class.

View File

@ -1 +1 @@
6f0aadcb399a9fd745412b4579ef39629db7a4eb635e1e89bcf37d38de54ae14 45bbed3a25c19fc3e72e316405f040c6cd1751d64f9cada8b42789394000df94

View File

@ -16,5 +16,5 @@ using System.Reflection;
[assembly: Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartAttribute("YD_AllHeartRates.Commons")] [assembly: Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartAttribute("YD_AllHeartRates.Commons")]
[assembly: Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartAttribute("YD_AllHeartRates.Commons.1.0.0.0.Fakes")] [assembly: Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartAttribute("YD_AllHeartRates.Commons.1.0.0.0.Fakes")]
// 由 MSBuild WriteCodeFragment 类生成。 // Generated by the MSBuild WriteCodeFragment class.

View File

@ -31,6 +31,7 @@
}, },
"frameworks": { "frameworks": {
"net6.0": { "net6.0": {
"framework": "net6.0",
"targetAlias": "net6.0", "targetAlias": "net6.0",
"projectReferences": { "projectReferences": {
"C:\\Users\\tangl\\Desktop\\Git\\YD_AllHeartRates.Api\\YD_AllHeartRates.Commons\\YD_AllHeartRates.Commons.csproj": { "C:\\Users\\tangl\\Desktop\\Git\\YD_AllHeartRates.Api\\YD_AllHeartRates.Commons\\YD_AllHeartRates.Commons.csproj": {
@ -53,6 +54,7 @@
}, },
"frameworks": { "frameworks": {
"net6.0": { "net6.0": {
"framework": "net6.0",
"targetAlias": "net6.0", "targetAlias": "net6.0",
"dependencies": { "dependencies": {
"AutoMapper.Collection": { "AutoMapper.Collection": {
@ -143,7 +145,7 @@
"privateAssets": "all" "privateAssets": "all"
} }
}, },
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.200-preview.0.26103.119\\RuntimeIdentifierGraph.json" "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.200\\RuntimeIdentifierGraph.json"
} }
} }
}, },
@ -174,6 +176,7 @@
}, },
"frameworks": { "frameworks": {
"net6.0": { "net6.0": {
"framework": "net6.0",
"targetAlias": "net6.0", "targetAlias": "net6.0",
"projectReferences": {} "projectReferences": {}
} }
@ -192,6 +195,7 @@
}, },
"frameworks": { "frameworks": {
"net6.0": { "net6.0": {
"framework": "net6.0",
"targetAlias": "net6.0", "targetAlias": "net6.0",
"dependencies": { "dependencies": {
"Aliyun.OSS.SDK.NetCore": { "Aliyun.OSS.SDK.NetCore": {
@ -235,7 +239,7 @@
"privateAssets": "all" "privateAssets": "all"
} }
}, },
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.200-preview.0.26103.119\\RuntimeIdentifierGraph.json" "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.200\\RuntimeIdentifierGraph.json"
} }
} }
} }

View File

@ -7228,6 +7228,7 @@
}, },
"frameworks": { "frameworks": {
"net6.0": { "net6.0": {
"framework": "net6.0",
"targetAlias": "net6.0", "targetAlias": "net6.0",
"projectReferences": { "projectReferences": {
"C:\\Users\\tangl\\Desktop\\Git\\YD_AllHeartRates.Api\\YD_AllHeartRates.Commons\\YD_AllHeartRates.Commons.csproj": { "C:\\Users\\tangl\\Desktop\\Git\\YD_AllHeartRates.Api\\YD_AllHeartRates.Commons\\YD_AllHeartRates.Commons.csproj": {
@ -7250,6 +7251,7 @@
}, },
"frameworks": { "frameworks": {
"net6.0": { "net6.0": {
"framework": "net6.0",
"targetAlias": "net6.0", "targetAlias": "net6.0",
"dependencies": { "dependencies": {
"AutoMapper.Collection": { "AutoMapper.Collection": {
@ -7340,7 +7342,7 @@
"privateAssets": "all" "privateAssets": "all"
} }
}, },
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.200-preview.0.26103.119\\RuntimeIdentifierGraph.json" "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.200\\RuntimeIdentifierGraph.json"
} }
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"version": 2, "version": 2,
"dgSpecHash": "EFwpte+qrlo=", "dgSpecHash": "TABP7rZDE8o=",
"success": true, "success": true,
"projectFilePath": "C:\\Users\\tangl\\Desktop\\Git\\YD_AllHeartRates.Api\\YD_AllHeartRates.Api\\YD_AllHeartRates.Api.csproj", "projectFilePath": "C:\\Users\\tangl\\Desktop\\Git\\YD_AllHeartRates.Api\\YD_AllHeartRates.Api\\YD_AllHeartRates.Api.csproj",
"expectedPackageFiles": [ "expectedPackageFiles": [

View File

@ -14,10 +14,10 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("YD_AllHeartRates.Commons")] [assembly: System.Reflection.AssemblyCompanyAttribute("YD_AllHeartRates.Commons")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+a3011552e4a905ce05e14a8ff0c44dca1c3ceeb3")] [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+3fb2268bb010dba28589cdc7a4186a566f598d0c")]
[assembly: System.Reflection.AssemblyProductAttribute("YD_AllHeartRates.Commons")] [assembly: System.Reflection.AssemblyProductAttribute("YD_AllHeartRates.Commons")]
[assembly: System.Reflection.AssemblyTitleAttribute("YD_AllHeartRates.Commons")] [assembly: System.Reflection.AssemblyTitleAttribute("YD_AllHeartRates.Commons")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
// 由 MSBuild WriteCodeFragment 类生成。 // Generated by the MSBuild WriteCodeFragment class.

View File

@ -1 +1 @@
9449a9877321fe5de1ea0a820503de509581ed5d7e64230fef9c2bbcf92c1a53 570bf2cb94f3c5895254f5e1e956aeef4ad74c2361b0fe7de273549fbb278f22

View File

@ -31,6 +31,7 @@
}, },
"frameworks": { "frameworks": {
"net6.0": { "net6.0": {
"framework": "net6.0",
"targetAlias": "net6.0", "targetAlias": "net6.0",
"projectReferences": {} "projectReferences": {}
} }
@ -49,6 +50,7 @@
}, },
"frameworks": { "frameworks": {
"net6.0": { "net6.0": {
"framework": "net6.0",
"targetAlias": "net6.0", "targetAlias": "net6.0",
"dependencies": { "dependencies": {
"Aliyun.OSS.SDK.NetCore": { "Aliyun.OSS.SDK.NetCore": {
@ -92,7 +94,7 @@
"privateAssets": "all" "privateAssets": "all"
} }
}, },
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.200-preview.0.26103.119\\RuntimeIdentifierGraph.json" "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.200\\RuntimeIdentifierGraph.json"
} }
} }
} }

View File

@ -993,6 +993,7 @@
}, },
"frameworks": { "frameworks": {
"net6.0": { "net6.0": {
"framework": "net6.0",
"targetAlias": "net6.0", "targetAlias": "net6.0",
"projectReferences": {} "projectReferences": {}
} }
@ -1011,6 +1012,7 @@
}, },
"frameworks": { "frameworks": {
"net6.0": { "net6.0": {
"framework": "net6.0",
"targetAlias": "net6.0", "targetAlias": "net6.0",
"dependencies": { "dependencies": {
"Aliyun.OSS.SDK.NetCore": { "Aliyun.OSS.SDK.NetCore": {
@ -1054,7 +1056,7 @@
"privateAssets": "all" "privateAssets": "all"
} }
}, },
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.200-preview.0.26103.119\\RuntimeIdentifierGraph.json" "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.200\\RuntimeIdentifierGraph.json"
} }
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"version": 2, "version": 2,
"dgSpecHash": "l9MQglnqMP4=", "dgSpecHash": "R9lcaqHMGy8=",
"success": true, "success": true,
"projectFilePath": "C:\\Users\\tangl\\Desktop\\Git\\YD_AllHeartRates.Api\\YD_AllHeartRates.Commons\\YD_AllHeartRates.Commons.csproj", "projectFilePath": "C:\\Users\\tangl\\Desktop\\Git\\YD_AllHeartRates.Api\\YD_AllHeartRates.Commons\\YD_AllHeartRates.Commons.csproj",
"expectedPackageFiles": [ "expectedPackageFiles": [