学校报告

This commit is contained in:
tanglong 2025-06-26 17:36:12 +08:00
parent 0f5bc328c2
commit 2791faef42
57 changed files with 2951 additions and 16 deletions

View File

@ -0,0 +1,40 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using YD_AllHeartRates.Api.Entitys;
using YD_AllHeartRates.Api.Services.Impl;
using YD_AllHeartRates.Api.Services.Interface;
using YD_AllHeartRates.Commons.Dto.LargeScreen;
namespace YD_AllHeartRates.Api.Controllers
{
/// <summary>
/// 报告
/// </summary>
[ApiVersion("1.0")]
[AllowAnonymous]
public class HeartRateReportController : ControllerBase
{
private readonly IHeartRateReportService _rateReportService;
/// <summary>
/// HeartRateReportController
/// </summary>
/// <param name="rateReportService"></param>
public HeartRateReportController(IHeartRateReportService rateReportService)
{
_rateReportService = rateReportService;
}
/// <summary>
/// 学校心率报告
/// </summary>
/// <returns></returns>
[HttpGet(nameof(SchoolHeartRateReport))]
public async Task<SchoolHeartRateReportDataDto> SchoolHeartRateReport(DateTime scoreTime)
{
var res = await _rateReportService.SchoolHeartRateReport(scoreTime);
return res;
}
}
}

View File

@ -9,7 +9,7 @@ using YD_AllHeartRates.Commons.Dto.LargeScreen;
namespace YD_AllHeartRates.Api.Controllers
{
/// <summary>
/// 芯未
/// 大屏
/// </summary>
[ApiVersion("1.0")]
[AllowAnonymous]
@ -33,7 +33,7 @@ namespace YD_AllHeartRates.Api.Controllers
}
/// <summary>
/// 学校信息
/// 实时数据
/// </summary>
/// <returns></returns>
[HttpGet(nameof(HeartRateData))]

View File

@ -0,0 +1,150 @@

using AutoMapper;
using Microsoft.EntityFrameworkCore;
using System.Drawing;
using YD_AllHeartRates.Api.Context;
using YD_AllHeartRates.Api.Services.Interface;
using YD_AllHeartRates.Api.SmartSportsEntitys;
using YD_AllHeartRates.Commons.Dto;
using YD_AllHeartRates.Commons.Dto.LargeScreen;
using YD_AllHeartRates.Commons.Utils;
namespace YD_AllHeartRates.Api.Services.Impl
{
/// <summary>
/// 服务实现
/// </summary>
public class HeartRateReportService : IHeartRateReportService
{
public SmartSportsContext _sportsContext;
public UserContext _userContext;
/// <summary>
/// 构造
/// </summary>
public HeartRateReportService(SmartSportsContext sportsContext, UserContext userContext)
{
_sportsContext = sportsContext;
_userContext = userContext;
}
/// <summary>
/// 学校心率报告
/// </summary>
/// <returns></returns>
public async Task<SchoolHeartRateReportDataDto> SchoolHeartRateReport(DateTime scoreTime)
{
var schoolCode = "202501060001";
DateTime dayStart = scoreTime.Date; // 自动为 00:00:00
DateTime dayEnd = scoreTime.Date.AddDays(1).AddSeconds(-1); // 23:59:59
var res = new SchoolHeartRateReportDataDto();
var gradeList = await (
from g in _sportsContext.Grade
join a in _sportsContext.SchoolAssocGrade on g.Id equals a.GradeId
where a.SchoolCode == schoolCode
select new GradeListDto()
{
GradeId = g.Id,
GradeName = g.GradeName,
}).OrderBy(x => x.GradeId).ToListAsync();
var studentCount = await (
from s in _sportsContext.Student
join c in _sportsContext.Class
on s.ClassId equals c.Id
where s.SchoolCode == schoolCode
select new
{
s.StudentNo,
s.Sex,
c.GradeId
}).ToListAsync();
res.GradeCount = gradeList.Count;
res.MaleCount = studentCount.Where(x => x.Sex == 1).Count();
res.FemaleCount = studentCount.Where(x => x.Sex == 2).Count();
res.StartEndTime = scoreTime.ToString();
var data = await _userContext.HeartRateData.Where(x => x.SchoolCode == schoolCode && x.ScoreTime > dayStart && x.ScoreTime <= dayEnd).ToListAsync();
res.OnlineDevicesCount = data.GroupBy(x => x.StudentNo).Count();
res.AvgHeartRate = (int)data.Average(x => x.Value);
// 先筛选达标学生及对应性别
var durationsByStudent = data
.Where(x => x.Strength >= 50)
.GroupBy(x => new { x.StudentNo, x.Sex })
.ToDictionary(
g => g.Key,
g => g.Select(x => x.ScoreTime).ToList().CalculateDuration()
);
res.AvgDuration = (int)durationsByStudent.Values.DefaultIfEmpty(0).Average();
// 统计男女达标人数
int maleQualified = durationsByStudent.Count(kv => kv.Key.Sex == 1 && kv.Value >= 7200);
int femaleQualified = durationsByStudent.Count(kv => kv.Key.Sex == 2 && kv.Value >= 7200);
res.ReachCount = maleQualified + femaleQualified;
res.NotReachCount = res.StudentCount - res.ReachCount;
var hourlyAvg = data
.Where(x => x.ScoreTime.Hour >= 8 && x.ScoreTime.Hour <= 16)
.GroupBy(x => x.ScoreTime.Hour)
.OrderBy(g => g.Key)
.ToDictionary(
g => g.Key,
g => (int)Math.Round(g.Average(x => x.Value))
);
var chartData = new ChartDataDto();
for (int hour = 8; hour <= 16; hour++)
{
chartData.AxisX.Add($"{hour:00}:00");
if (hourlyAvg.TryGetValue(hour, out int avg))
chartData.AxisY.Add(avg);
else
chartData.AxisY.Add(0);
}
res.HeartRateTrend = chartData;
foreach (var item in gradeList)
{
res.GradeList.Add(new GradeListDto()
{
GradeId = item.GradeId,
GradeName = item.GradeName,
StudentCount = studentCount.Where(x => x.GradeId == item.GradeId).Count(),
MaleReachCount = maleQualified,
FemaleReachCount = femaleQualified,
ReachRate = (int)((double)res.ReachCount / res.StudentCount * 100)
});
}
return res;
}
public Task<GradeHeartRateReportDataDto> GradeHeartRateReport(int gradeId)
{
throw new NotImplementedException();
}
public Task<ClassHeartRateReportDataDto> ClassHeartRateReport(int classId)
{
throw new NotImplementedException();
}
public Task<StudentHeartRateReportDataDto> StudentHeartRateReport(string studentNo)
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,36 @@
using Microsoft.AspNetCore.Mvc;
using YD_AllHeartRates.Commons.Dto.LargeScreen;
namespace YD_AllHeartRates.Api.Services.Interface
{
/// <summary>
/// 服务接口
/// </summary>
public interface IHeartRateReportService
{
/// <summary>
/// 学校心率报告
/// </summary>
/// <returns></returns>
Task<SchoolHeartRateReportDataDto> SchoolHeartRateReport(DateTime scoreTime);
/// <summary>
/// 年级心率报告
/// </summary>
/// <returns></returns>
Task<GradeHeartRateReportDataDto> GradeHeartRateReport(int gradeId);
/// <summary>
/// 班级心率报告
/// </summary>
/// <returns></returns>
Task<ClassHeartRateReportDataDto> ClassHeartRateReport(int classId);
/// <summary>
/// 学生心率报告
/// </summary>
/// <param name="studentNo"></param>
/// <returns></returns>
Task<StudentHeartRateReportDataDto> StudentHeartRateReport(string studentNo);
}
}

View File

@ -77,6 +77,7 @@ namespace YD_AllHeartRates.Api
services.AddSingleton<JwtHelper>();
services.AddScoped<ILargeScreenService, LargeScreenService>();
services.AddScoped<IHeartRateReportService, HeartRateReportService>();
//services.AddScoped<ICaching, MemoryCaching>();
services.AddSession();

View File

@ -14,9 +14,26 @@
用户服务上下文
</summary>
</member>
<member name="T:YD_AllHeartRates.Api.Controllers.HeartRateReportController">
<summary>
报告
</summary>
</member>
<member name="M:YD_AllHeartRates.Api.Controllers.HeartRateReportController.#ctor(YD_AllHeartRates.Api.Services.Interface.IHeartRateReportService)">
<summary>
HeartRateReportController
</summary>
<param name="rateReportService"></param>
</member>
<member name="M:YD_AllHeartRates.Api.Controllers.HeartRateReportController.SchoolHeartRateReport(System.DateTime)">
<summary>
学校心率报告
</summary>
<returns></returns>
</member>
<member name="T:YD_AllHeartRates.Api.Controllers.LargeScreenController">
<summary>
芯未
大屏
</summary>
</member>
<member name="M:YD_AllHeartRates.Api.Controllers.LargeScreenController.SchoolInfo">
@ -27,7 +44,7 @@
</member>
<member name="M:YD_AllHeartRates.Api.Controllers.LargeScreenController.HeartRateData(System.Int32)">
<summary>
学校信息
实时数据
</summary>
<returns></returns>
</member>
@ -340,6 +357,22 @@
<param name="stoppingToken"></param>
<returns></returns>
</member>
<member name="T:YD_AllHeartRates.Api.Services.Impl.HeartRateReportService">
<summary>
服务实现
</summary>
</member>
<member name="M:YD_AllHeartRates.Api.Services.Impl.HeartRateReportService.#ctor(YD_AllHeartRates.Api.Context.SmartSportsContext,YD_AllHeartRates.Api.Context.UserContext)">
<summary>
构造
</summary>
</member>
<member name="M:YD_AllHeartRates.Api.Services.Impl.HeartRateReportService.SchoolHeartRateReport(System.DateTime)">
<summary>
学校心率报告
</summary>
<returns></returns>
</member>
<member name="T:YD_AllHeartRates.Api.Services.Impl.LargeScreenService">
<summary>
服务实现
@ -362,6 +395,36 @@
</summary>
<returns></returns>
</member>
<member name="T:YD_AllHeartRates.Api.Services.Interface.IHeartRateReportService">
<summary>
服务接口
</summary>
</member>
<member name="M:YD_AllHeartRates.Api.Services.Interface.IHeartRateReportService.SchoolHeartRateReport(System.DateTime)">
<summary>
学校心率报告
</summary>
<returns></returns>
</member>
<member name="M:YD_AllHeartRates.Api.Services.Interface.IHeartRateReportService.GradeHeartRateReport(System.Int32)">
<summary>
年级心率报告
</summary>
<returns></returns>
</member>
<member name="M:YD_AllHeartRates.Api.Services.Interface.IHeartRateReportService.ClassHeartRateReport(System.Int32)">
<summary>
班级心率报告
</summary>
<returns></returns>
</member>
<member name="M:YD_AllHeartRates.Api.Services.Interface.IHeartRateReportService.StudentHeartRateReport(System.String)">
<summary>
学生心率报告
</summary>
<param name="studentNo"></param>
<returns></returns>
</member>
<member name="T:YD_AllHeartRates.Api.Services.Interface.ILargeScreenService">
<summary>
服务接口

View File

@ -25,6 +25,32 @@
}
]
},
{
"ContainingType": "YD_AllHeartRates.Api.Controllers.HeartRateReportController",
"Method": "SchoolHeartRateReport",
"RelativePath": "SchoolHeartRateReport",
"HttpMethod": "GET",
"IsController": true,
"Order": 0,
"Parameters": [
{
"Name": "scoreTime",
"Type": "System.DateTime",
"IsRequired": false
}
],
"ReturnTypes": [
{
"Type": "YD_AllHeartRates.Commons.Dto.LargeScreen.SchoolHeartRateReportDataDto",
"MediaTypes": [
"text/plain",
"application/json",
"text/json"
],
"StatusCode": 200
}
]
},
{
"ContainingType": "YD_AllHeartRates.Api.Controllers.LargeScreenController",
"Method": "SchoolInfo",

View File

@ -6,6 +6,46 @@
"version": "v1"
},
"paths": {
"/SchoolHeartRateReport": {
"get": {
"tags": [
"HeartRateReport"
],
"summary": "学校心率报告",
"parameters": [
{
"name": "scoreTime",
"in": "query",
"schema": {
"type": "string",
"format": "date-time"
}
}
],
"responses": {
"200": {
"description": "Success",
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/SchoolHeartRateReportDataDto"
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/SchoolHeartRateReportDataDto"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/SchoolHeartRateReportDataDto"
}
}
}
}
}
}
},
"/SchoolInfo": {
"get": {
"tags": [
@ -41,7 +81,7 @@
"tags": [
"LargeScreen"
],
"summary": "学校信息",
"summary": "实时数据",
"parameters": [
{
"name": "classId",
@ -79,6 +119,27 @@
},
"components": {
"schemas": {
"ChartDataDto": {
"type": "object",
"properties": {
"axisX": {
"type": "array",
"items": {
"type": "string"
},
"nullable": true
},
"axisY": {
"type": "array",
"items": {
"type": "integer",
"format": "int32"
},
"nullable": true
}
},
"additionalProperties": false
},
"Classes": {
"type": "object",
"properties": {
@ -93,6 +154,41 @@
},
"additionalProperties": false
},
"GradeListDto": {
"type": "object",
"properties": {
"gradeId": {
"type": "integer",
"format": "int32"
},
"gradeName": {
"type": "string",
"nullable": true
},
"studentCount": {
"type": "integer",
"format": "int32"
},
"reachCount": {
"type": "integer",
"format": "int32",
"readOnly": true
},
"maleReachCount": {
"type": "integer",
"format": "int32"
},
"femaleReachCount": {
"type": "integer",
"format": "int32"
},
"reachRate": {
"type": "integer",
"format": "int32"
}
},
"additionalProperties": false
},
"Grades": {
"type": "object",
"properties": {
@ -192,6 +288,67 @@
},
"additionalProperties": false
},
"SchoolHeartRateReportDataDto": {
"type": "object",
"properties": {
"maleCount": {
"type": "integer",
"format": "int32"
},
"femaleCount": {
"type": "integer",
"format": "int32"
},
"studentCount": {
"type": "integer",
"format": "int32",
"readOnly": true
},
"startEndTime": {
"type": "string",
"nullable": true
},
"onlineDevicesCount": {
"type": "integer",
"format": "int32"
},
"avgDuration": {
"type": "integer",
"format": "int32"
},
"avgHeartRate": {
"type": "integer",
"format": "int32"
},
"reachCount": {
"type": "integer",
"format": "int32"
},
"notReachCount": {
"type": "integer",
"format": "int32"
},
"reachRate": {
"type": "integer",
"format": "int32"
},
"heartRateTrend": {
"$ref": "#/components/schemas/ChartDataDto"
},
"gradeCount": {
"type": "integer",
"format": "int32"
},
"gradeList": {
"type": "array",
"items": {
"$ref": "#/components/schemas/GradeListDto"
},
"nullable": true
}
},
"additionalProperties": false
},
"StudentDto": {
"type": "object",
"properties": {
@ -242,9 +399,13 @@
}
],
"tags": [
{
"name": "HeartRateReport",
"description": "报告"
},
{
"name": "LargeScreen",
"description": "芯未"
"description": "大屏"
}
]
}

View File

@ -1 +1 @@
c7f0ddbd
e7651be4

View File

@ -1 +1 @@
lQIT0uczD+KFhAyrl+a5QgH3jaWQpy4w8iyOREdwyPs=WWmIfOUbyYPYdKFHlVpzo+vbEnfIsJNTTcG8+oWdtSc=
jLqsk4XuQmQ5DfZ+cctApIvaUAmBnRmKgk1eSFdB5yM=WWmIfOUbyYPYdKFHlVpzo+vbEnfIsJNTTcG8+oWdtSc=

View File

@ -14,7 +14,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("YD_AllHeartRates.Api")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+6c6387f1c71b4c0e273004c66b7ccf24d7236bab")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+0f5bc328c2c65c18843580575b6b612b42a8da0d")]
[assembly: System.Reflection.AssemblyProductAttribute("YD_AllHeartRates.Api")]
[assembly: System.Reflection.AssemblyTitleAttribute("YD_AllHeartRates.Api")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

View File

@ -1 +1 @@
384acc3bf9bdbee510bed4ebf7e611e3cebca635622b84e51bcf6d2bb409f57e
2a20b93dbb377ccd2f581a9f243b1792e8d3809491b50e7150205d5be404b225

View File

@ -1 +1 @@
19ffe668de0d92ec5040af47b3d893fc785172a3222eed5f3a3ec8b1c37c20d5
2afe5fdfbca71c7fbcee5ddf076974907b96c40560261af04a2a747084082ddf

View File

@ -14,9 +14,26 @@
用户服务上下文
</summary>
</member>
<member name="T:YD_AllHeartRates.Api.Controllers.HeartRateReportController">
<summary>
报告
</summary>
</member>
<member name="M:YD_AllHeartRates.Api.Controllers.HeartRateReportController.#ctor(YD_AllHeartRates.Api.Services.Interface.IHeartRateReportService)">
<summary>
HeartRateReportController
</summary>
<param name="rateReportService"></param>
</member>
<member name="M:YD_AllHeartRates.Api.Controllers.HeartRateReportController.SchoolHeartRateReport(System.DateTime)">
<summary>
学校心率报告
</summary>
<returns></returns>
</member>
<member name="T:YD_AllHeartRates.Api.Controllers.LargeScreenController">
<summary>
芯未
大屏
</summary>
</member>
<member name="M:YD_AllHeartRates.Api.Controllers.LargeScreenController.SchoolInfo">
@ -27,7 +44,7 @@
</member>
<member name="M:YD_AllHeartRates.Api.Controllers.LargeScreenController.HeartRateData(System.Int32)">
<summary>
学校信息
实时数据
</summary>
<returns></returns>
</member>
@ -340,6 +357,22 @@
<param name="stoppingToken"></param>
<returns></returns>
</member>
<member name="T:YD_AllHeartRates.Api.Services.Impl.HeartRateReportService">
<summary>
服务实现
</summary>
</member>
<member name="M:YD_AllHeartRates.Api.Services.Impl.HeartRateReportService.#ctor(YD_AllHeartRates.Api.Context.SmartSportsContext,YD_AllHeartRates.Api.Context.UserContext)">
<summary>
构造
</summary>
</member>
<member name="M:YD_AllHeartRates.Api.Services.Impl.HeartRateReportService.SchoolHeartRateReport(System.DateTime)">
<summary>
学校心率报告
</summary>
<returns></returns>
</member>
<member name="T:YD_AllHeartRates.Api.Services.Impl.LargeScreenService">
<summary>
服务实现
@ -362,6 +395,36 @@
</summary>
<returns></returns>
</member>
<member name="T:YD_AllHeartRates.Api.Services.Interface.IHeartRateReportService">
<summary>
服务接口
</summary>
</member>
<member name="M:YD_AllHeartRates.Api.Services.Interface.IHeartRateReportService.SchoolHeartRateReport(System.DateTime)">
<summary>
学校心率报告
</summary>
<returns></returns>
</member>
<member name="M:YD_AllHeartRates.Api.Services.Interface.IHeartRateReportService.GradeHeartRateReport(System.Int32)">
<summary>
年级心率报告
</summary>
<returns></returns>
</member>
<member name="M:YD_AllHeartRates.Api.Services.Interface.IHeartRateReportService.ClassHeartRateReport(System.Int32)">
<summary>
班级心率报告
</summary>
<returns></returns>
</member>
<member name="M:YD_AllHeartRates.Api.Services.Interface.IHeartRateReportService.StudentHeartRateReport(System.String)">
<summary>
学生心率报告
</summary>
<param name="studentNo"></param>
<returns></returns>
</member>
<member name="T:YD_AllHeartRates.Api.Services.Interface.ILargeScreenService">
<summary>
服务接口

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YD_AllHeartRates.Commons.Dto
{
/// <summary>
/// 通用图表Dto
/// </summary>
public class ChartDataDto
{
/// <summary>
/// 横轴
/// </summary>
public List<string> AxisX { get; set; } = new List<string>();
/// <summary>
/// 纵轴
/// </summary>
public List<int> AxisY { get; set; } = new List<int>();
}
}

View File

@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YD_AllHeartRates.Commons.Dto.LargeScreen
{
/// <summary>
/// 班级心率报告
/// </summary>
public class ClassHeartRateReportDataDto : HeartRateReportDataDto
{
/// <summary>
/// 年级名称
/// </summary>
public string GradeName { get; set; }
/// <summary>
/// 班级名称
/// </summary>
public string ClassName { get; set; }
/// <summary>
/// 教师名称
/// </summary>
public string TeacherName { get; set; }
/// <summary>
/// 学生列表
/// </summary>
public List<StudentListDto> StudentListDto { get; set; } = new List<StudentListDto>();
}
/// <summary>
/// 学生列表
/// </summary>
public class StudentListDto
{
/// <summary>
/// 学号
/// </summary>
public string StudentNo { get; set; }
/// <summary>
/// 学生姓名
/// </summary>
public string StudentName { get; set; }
/// <summary>
/// 性别
/// </summary>
public int Sex { get; set; }
/// <summary>
/// 年龄
/// </summary>
public int Age { get; set; }
/// <summary>
/// 是否达标
/// </summary>
public bool IsReach { get; set; }
/// <summary>
/// 运动时长
/// </summary>
public int Duration { get; set; }
}
}

View File

@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YD_AllHeartRates.Commons.Dto.LargeScreen
{
/// <summary>
/// 年级心率报告
/// </summary>
public class GradeHeartRateReportDataDto : HeartRateReportDataDto
{
/// <summary>
/// 年级名称
/// </summary>
public string GradeName { get; set; }
/// <summary>
/// 班级数量
/// </summary>
public int ClassCount { get; set; }
/// <summary>
/// 班级列表
/// </summary>
public List<ClassListDto> ClassListDto { get; set; } = new List<ClassListDto>();
}
/// <summary>
/// 班级列表
/// </summary>
public class ClassListDto
{
/// <summary>
/// 班级Id
/// </summary>
public int ClassId { get; set; }
/// <summary>
/// 班级名称
/// </summary>
public string ClassName { get; set; }
/// <summary>
/// 教师名称
/// </summary>
public string TeacherName { get; set; }
/// <summary>
/// 学生人数
/// </summary>
public int StudentCount { get; set; }
/// <summary>
/// 达标人数
/// </summary>
public int ReachCount => MaleReachCount + FemaleReachCount;
/// <summary>
/// 男达标人数
/// </summary>
public int MaleReachCount { get; set; }
/// <summary>
/// 女达标人数
/// </summary>
public int FemaleReachCount { get; set; }
/// <summary>
/// 达标率
/// </summary>
public int ReachRate { get; set; }
}
}

View File

@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YD_AllHeartRates.Commons.Dto.LargeScreen
{
/// <summary>
/// 心率报告
/// </summary>
public class HeartRateReportDataDto
{
/// <summary>
/// 男生数量
/// </summary>
public int MaleCount { get; set; }
/// <summary>
/// 女生数量
/// </summary>
public int FemaleCount { get; set; }
/// <summary>
/// 学生总数(男+女)
/// </summary>
public int StudentCount => MaleCount + FemaleCount;
/// <summary>
/// 开始结束时间
/// </summary>
public string StartEndTime { get; set; }
/// <summary>
/// 在线设备数量
/// </summary>
public int OnlineDevicesCount { get; set; }
/// <summary>
/// 平均时长
/// </summary>
public int AvgDuration { get; set; }
/// <summary>
/// 平均心率
/// </summary>
public int AvgHeartRate { get; set; }
/// <summary>
/// 达标人数
/// </summary>
public int ReachCount { get; set; }
/// <summary>
/// 未达标人数
/// </summary>
public int NotReachCount { get; set; }
/// <summary>
/// 达标率
/// </summary>
public int ReachRate { get; set; }
/// <summary>
/// 心率变化趋势
/// </summary>
public ChartDataDto HeartRateTrend { get; set; } = new ChartDataDto();
}
}

View File

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YD_AllHeartRates.Commons.Dto.LargeScreen
{
/// <summary>
/// 学校心率报告
/// </summary>
public class SchoolHeartRateReportDataDto : HeartRateReportDataDto
{
/// <summary>
/// 年级数量
/// </summary>
public int GradeCount { get; set; }
/// <summary>
/// 年级列表
/// </summary>
public List<GradeListDto> GradeList { get; set; } = new List<GradeListDto>();
}
/// <summary>
/// 年级列表
/// </summary>
public class GradeListDto
{
/// <summary>
/// 年级Id
/// </summary>
public int GradeId { get; set; }
/// <summary>
/// 年级名称
/// </summary>
public string GradeName { get; set; }
/// <summary>
/// 学生人数
/// </summary>
public int StudentCount { get; set; }
/// <summary>
/// 达标人数
/// </summary>
public int ReachCount => MaleReachCount + FemaleReachCount;
/// <summary>
/// 男达标人数
/// </summary>
public int MaleReachCount { get; set; }
/// <summary>
/// 女达标人数
/// </summary>
public int FemaleReachCount { get; set; }
/// <summary>
/// 达标率
/// </summary>
public int ReachRate { get; set; }
}
}

View File

@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YD_AllHeartRates.Commons.Dto.LargeScreen
{
/// <summary>
/// 学生心率报告
/// </summary>
public class StudentHeartRateReportDataDto
{
/// <summary>
/// 年级名称
/// </summary>
public string GradeName { get; set; }
/// <summary>
/// 班级名称
/// </summary>
public string ClassName { get; set; }
/// <summary>
/// 学号
/// </summary>
public string StudentNo { get; set; }
/// <summary>
/// 学生姓名
/// </summary>
public string StudentName { get; set; }
/// <summary>
/// 性别
/// </summary>
public int Sex { get; set; }
/// <summary>
/// 年龄
/// </summary>
public int Age { get; set; }
/// <summary>
/// 头像
/// </summary>
public string Photo { get; set; }
/// <summary>
/// 是否达标
/// </summary>
public bool IsReach { get; set; }
/// <summary>
/// 设备状态
/// </summary>
public int DeviceStatus { get; set; }
/// <summary>
/// 心率变化趋势
/// </summary>
public ChartDataDto HeartRateTrend { get; set; } = new ChartDataDto();
}
}

View File

@ -143,5 +143,28 @@ namespace YD_AllHeartRates.Commons.Utils
_ => "低分"
};
}
/// <summary>
/// 计算连续时间点的累计时长默认最大间隔为10秒
/// </summary>
/// <param name="times">时间集合,已满足条件</param>
/// <param name="maxGapSeconds">允许的最大时间间隔</param>
/// <returns>累计持续时间(秒)</returns>
public static double CalculateDuration(this List<DateTime> times, int maxGapSeconds = 10)
{
if (times == null || times.Count < 2)
return 0;
var ordered = times.OrderBy(t => t).ToList();
double totalSeconds = 0;
for (int i = 1; i < ordered.Count; i++)
{
var gap = (ordered[i] - ordered[i - 1]).TotalSeconds;
if (gap <= maxGapSeconds)
totalSeconds += gap;
}
return totalSeconds;
}
}
}

View File

@ -14,7 +14,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("YD_AllHeartRates.Commons")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+6c6387f1c71b4c0e273004c66b7ccf24d7236bab")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+0f5bc328c2c65c18843580575b6b612b42a8da0d")]
[assembly: System.Reflection.AssemblyProductAttribute("YD_AllHeartRates.Commons")]
[assembly: System.Reflection.AssemblyTitleAttribute("YD_AllHeartRates.Commons")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

View File

@ -1 +1 @@
eb4edf26362979121ce0ee9daa7630250f32a8e25a56849f087f5de4d4f480a8
30eb45cd8144c9402f66a0ca54a34955f926020f1f5adb1a33d44ecc46b81951

View File

@ -1 +1 @@
f356e4cbcc366b982b4d810c7f9fed5d109a3fb07963b994a35ccf0d76509742
6f8dc75bfdccba527e69d224fb7a7ca6af608d0e72c7fcd462583c85f8c30f66