课堂报告

This commit is contained in:
tanglong 2025-06-11 11:45:53 +08:00
parent ff846fe72f
commit 345e1d0928
19 changed files with 1195 additions and 208 deletions

View File

@ -23,6 +23,10 @@ namespace YD_WeChatApplet.Context
public DbSet<Sys_User> Sys_User { get; set; }
public DbSet<Ai_Special> Ai_Special { get; set; }
public DbSet<Ai_ClassRoomRecord> Ai_ClassRoomRecord { get; set; }
public DbSet<Ai_ClassroomStudentRecord> Ai_ClassroomStudentRecord { get; set; }
public DbSet<Ai_FastJumpRopeData> Ai_FastJumpRopeData { get; set; }
public DbSet<Ai_HeartRateData> Ai_HeartRateData { get; set; }
public DbSet<G_Article> Article { get; set; }
public DbSet<Ai_SpecialAction> Ai_SpecialAction { get; set; }
public DbSet<Ai_SpecialLevel> Ai_SpecialLevel { get; set; }

View File

@ -1,6 +1,8 @@
using System.ComponentModel.Design;
using Microsoft.AspNetCore.Mvc;
using YD_WeChatApplet.Api.Services.Impl;
using YD_WeChatApplet.Commons.Dto;
using YD_WeChatApplet.Commons.Dto.ClassRoomRecord;
using YD_WeChatApplet.Commons.Dto.HomeWork;
using YD_WeChatApplet.Commons.Dto.Resource;
using YD_WeChatApplet.Commons.Dto.Teacher;
@ -93,5 +95,41 @@ namespace YD_WeChatApplet.Api.Controllers
return res;
}
/// <summary>
/// 课堂记录
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
[HttpGet("ClassRoomRecord")]
public async Task<PageDataDto<ClassRoomRecordPageDto>> ClassRoomRecord([FromQuery] ClassRoomRecordDto dto)
{
var res = await _teacherService.ClassRoomRecord(dto);
return res;
}
/// <summary>
/// 课堂详情
/// </summary>
/// <param name="classRoomId"></param>
/// <returns></returns>
[HttpGet("ClassRoomReportDetails")]
public async Task<ClassReportDetailsDto> ClassRoomReportDetails(int classRoomId)
{
var res = await _teacherService.ClassRoomReportDetails(classRoomId);
return res;
}
/// <summary>
/// 学员课堂报告
/// </summary>
/// <param name="classRoomId"></param>
/// <param name="studentNo"></param>
/// <returns></returns>
[HttpGet("StudentClassRoomReport")]
public async Task<StudentClassRoomReportDto> StudentClassRoomReport(int classRoomId, string studentNo)
{
var res = await _teacherService.StudentClassRoomReport(classRoomId, studentNo);
return res;
}
}
}

View File

@ -20,7 +20,6 @@ using YD_WeChatApplet.Commons.Dto.School;
using YD_WeChatApplet.Commons.Dto.SportsTest;
using YD_WeChatApplet.Commons.Dto.Teacher;
using YD_WeChatApplet.Commons.Enum;
using YD_WeChatApplet.Commons.MemoryCaches;
using YD_WeChatApplet.Commons.Utils;
using YD_WeChatApplet.Context;
using YD_WeChatApplet.Services;
@ -36,13 +35,11 @@ namespace YD_WeChatApplet.Api.Services.Impl
public UserContext _userContext;
public SmartSportsContext _sportsContext;
private readonly IMapper _mapper;
private readonly ICaching _caching;
public ClientSideService(UserContext userContext, SmartSportsContext sportsContext, IMapper mapper, ICaching caching)
public ClientSideService(UserContext userContext, SmartSportsContext sportsContext, IMapper mapper)
{
_userContext = userContext;
_sportsContext = sportsContext;
_mapper = mapper;
_caching = caching;
}
/// <summary>
@ -302,103 +299,6 @@ namespace YD_WeChatApplet.Api.Services.Impl
return res;
}
// 获取 access_token
public async Task<string> GetAccessTokenAsync()
{
var userId = UserLoginContext.Current.UserId;
var key = $"access_token_{userId}";
var token = _caching.Get(key).ToString();
if (!string.IsNullOrWhiteSpace(token))
{
return token;
}
// 2. 缓存不存在,请求微信接口
var url = $"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={AppSettings.WeChatQA.Appid}&secret={AppSettings.WeChatQA.Secret}";
var response = await HttpManager.HttpGetAsync(url, null);
dynamic data = JsonConvert.DeserializeObject(response);
if (data?.access_token != null)
{
token = data.access_token;
// 微信官方返回中有 expires_in一般是7200秒2小时
int expiresInSeconds = data.expires_in ?? 7200;
// 3. 写入缓存提前1分钟过期
_caching.Set(key, token, expiresInSeconds);
return token;
}
throw new Exception("获取 access_token 失败");
}
// 获取文章列表
public async Task<object> GetArticlesAsync(string accessToken, int offset, int count = 20)
{
var userId = UserLoginContext.Current.UserId;
var key = $"articles_{userId}_{offset}";
var articlesData = _caching.Get(key).ToString();
if (articlesData != null && articlesData.Count() > 0)
{
return articlesData;
}
//var url = $"https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token={accessToken}";
var url = $"https://api.weixin.qq.com/cgi-bin/freepublish/batchget?access_token={accessToken}";
var postData = JsonConvert.SerializeObject(new
{
//type = "news",
offset = offset,
count = count
});
var response = await HttpManager.HttpPostAsync(url, postData, "application/json");
// 解析并过滤掉content字段
dynamic data = JsonConvert.DeserializeObject(response);
if (data?.item != null)
{
var filteredItems = new List<object>();
foreach (var item in data.item)
{
if (item["update_time"] is JValue timeValue && timeValue.Type == JTokenType.Integer)
{
item["update_time"] = DateTimeOffset.FromUnixTimeSeconds((long)timeValue)
.ToString("yyyy-MM-dd HH:mm:ss");
}
foreach (var newitem in item.content.news_item)
{
filteredItems.Add(new
{
newitem.title,
newitem.author,
newitem.digest,
newitem.url,
newitem.thumb_url,
item.update_time
});
}
}
int expiresInSeconds = data.expires_in ?? 7200;
_caching.Set(key, filteredItems, expiresInSeconds);
return filteredItems;
}
throw new Exception("获取文章列表失败");
}
/// <summary>
/// 创建群组
/// </summary>

View File

@ -2,9 +2,12 @@
using System;
using System.Threading.Tasks;
using AutoMapper;
using CSRedis;
using Microsoft.EntityFrameworkCore;
using YD_WeChatApplet.Api.SmartSportsEntitys;
using YD_WeChatApplet.Api.Utilities;
using YD_WeChatApplet.Commons.Dto;
using YD_WeChatApplet.Commons.Dto.ClassRoomRecord;
using YD_WeChatApplet.Commons.Dto.HomeWork;
using YD_WeChatApplet.Commons.Dto.SportsTest;
using YD_WeChatApplet.Commons.Dto.Teacher;
@ -313,5 +316,225 @@ namespace YD_WeChatApplet.Services
res.ComprehensiveScore = totalScore.ToString("F0");
return res;
}
/// <summary>
/// 课堂记录
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
public async Task<PageDataDto<ClassRoomRecordPageDto>> ClassRoomRecord(ClassRoomRecordDto dto)
{
var res = new PageDataDto<ClassRoomRecordPageDto>();
if (string.IsNullOrWhiteSpace(dto.StudentNo))
{
var phoneNo = UserLoginContext.Current.PhoneNo;
var teacherId = await _sportsContext.Teacher.Where(x => x.TeacherPhoneNo == phoneNo).Select(x => x.Id).FirstOrDefaultAsync();
var query = from td in _sportsContext.Ai_ClassRoomRecord
where td.TeacherId == teacherId
select new ClassRoomRecordPageDto()
{
Id = td.Id,
ClassId = td.ClassId,
Name = td.Name,
StartingEndingTime = $"{(td.StartTime.HasValue ? td.StartTime.Value.ToString("yyyy-MM-dd HH:mm") : string.Empty)}{(td.EndTime.HasValue ? " - " + td.EndTime.Value.ToString("yyyy-MM-dd HH:mm") : string.Empty)}"
};
res.Total = await query.CountAsync();
var list = await query
.OrderByDescending(c => c.Id)
.Skip((dto.PageIndex - 1) * dto.PageSize)
.Take(dto.PageSize)
.ToListAsync();
res.Datas = list;
}
else
{
var query = from s in _sportsContext.Ai_ClassroomStudentRecord
join c in _sportsContext.Ai_ClassRoomRecord on s.ClassRoomRecordId equals c.Id
where s.StudentName == dto.StudentNo
select new ClassRoomRecordPageDto()
{
Id = c.Id,
ClassId = c.ClassId,
Name = c.Name,
StartingEndingTime = $"{(c.StartTime.HasValue ? c.StartTime.Value.ToString("yyyy-MM-dd HH:mm") : string.Empty)}{(c.EndTime.HasValue ? " - " + c.EndTime.Value.ToString("yyyy-MM-dd HH:mm") : string.Empty)}"
};
res.Total = await query.CountAsync();
var list = await query
.OrderByDescending(c => c.Id)
.Skip((dto.PageIndex - 1) * dto.PageSize)
.Take(dto.PageSize)
.ToListAsync();
res.Datas = list;
}
return res;
}
/// <summary>
/// 课堂详情
/// </summary>
/// <param name="classRoomId"></param>
/// <returns></returns>
public async Task<ClassReportDetailsDto> ClassRoomReportDetails(int classRoomId)
{
var res = new ClassReportDetailsDto();
var query = from hrd in _sportsContext.Ai_HeartRateData
where hrd.ClassRoomRecordId == classRoomId
select hrd;
var heartRateDataList = await query.ToListAsync();
if (heartRateDataList.Count == 0)
return res;
var classRoom = await _sportsContext.Ai_ClassRoomRecord.Include(x => x.ClassroomStudentRecord)
.Where(x => x.Id == classRoomId)
.FirstAsync();
var classRoomStudent = await _sportsContext.Ai_ClassroomStudentRecord
.Where(x => x.ClassRoomRecordId == classRoomId)
.ToListAsync();
res.MaxHR = (int)heartRateDataList.Max(x => x.Value);
res.MinHR = (int)heartRateDataList.Min(x => x.Value);
res.AvgHR = (int)heartRateDataList.Average(x => x.Value);
res.HighIntensity = heartRateDataList.Where(x => x.Strength > 50).Sum(x => x.MotionDuration);
var studentTrainingRecordList = classRoom.ClassroomStudentRecord.ToList();
List<StudentTrainingRecordDto> studentList = new List<StudentTrainingRecordDto>();
foreach (var item in studentTrainingRecordList)
{
var studentTrainingData = heartRateDataList.Where(x => x.StudentNo == item.StudentNo).ToList();
if (studentTrainingData.Count > 0)
{
var student = new StudentTrainingRecordDto()
{
StudentNo = item.StudentNo,
Age = item.Age,
Sex = item.Sex
};
student.StudentName = studentTrainingData[0].StudentName;
studentList.Add(student);
}
}
res.HeartRateTrend = GetHeartRateTrend(heartRateDataList);
res.StudentTrainingRecordList = studentList;
return res;
}
/// <summary>
/// 学员报告
/// </summary>
/// <param name="classRoomRecordId"></param>
/// <param name="studentNo"></param>
/// <returns></returns>
public async Task<StudentClassRoomReportDto> StudentClassRoomReport(int classRoomId, string studentNo)
{
var res = new StudentClassRoomReportDto();
var query = from hrd in _sportsContext.Ai_HeartRateData
where hrd.ClassRoomRecordId == classRoomId &&
hrd.StudentNo == studentNo
select hrd;
var heartRateDataList = await query.ToListAsync();
if (heartRateDataList.Count == 0)
return res;
var student = heartRateDataList[0];
res.MaxHR = (int)heartRateDataList.Max(x => x.Value);
res.MinHR = (int)heartRateDataList.Min(x => x.Value);
res.AvgHR = (int)heartRateDataList.Average(x => x.Value);
res.HighIntensity = heartRateDataList.Where(x => x.Strength > 50).Sum(x => x.MotionDuration);
var baseTime = await _sportsContext.Ai_HeartRateData.Where(x => x.ClassRoomRecordId == classRoomId).MinAsync(x => x.ScoreTime);
var heartRateWithMinutes = heartRateDataList
.Select(data => new
{
Data = data,
MinuteBucket = (int)(data.ScoreTime - baseTime).TotalMinutes
})
.ToList();
var maxMinute = heartRateWithMinutes.Max(x => x.MinuteBucket);
for (int minute = 0; minute <= maxMinute; minute++)
{
var minuteData = heartRateWithMinutes
.Where(x => x.MinuteBucket == minute)
.Select(x => x.Data)
.ToList();
if (minuteData.Any())
{
res.HeartRateTrend.AxisX.Add($"{minute + 1} 分钟");
res.HeartRateTrend.AxisY.Add((int)minuteData.Average(x => x.Value));
}
}
return res;
}
/// <summary>
/// 心率变化趋势
/// </summary>
/// <param name="heartRateDataList"></param>
/// <returns></returns>
public ChartDataDto GetHeartRateTrend(List<Ai_HeartRateData> heartRateDataList)
{
var result = new ChartDataDto();
if (heartRateDataList == null || !heartRateDataList.Any())
return result;
var baseTime = heartRateDataList.Min(x => x.ScoreTime);
var heartRateWithMinutes = heartRateDataList
.Select(data => new
{
Data = data,
MinuteBucket = (int)(data.ScoreTime - baseTime).TotalMinutes
})
.ToList();
var maxMinute = heartRateWithMinutes.Max(x => x.MinuteBucket);
for (int minute = 0; minute <= maxMinute; minute++)
{
var minuteData = heartRateWithMinutes
.Where(x => x.MinuteBucket == minute)
.Select(x => x.Data)
.ToList();
if (minuteData.Any())
{
result.AxisX.Add($"{minute + 1} 分钟");
result.AxisY.Add((int)minuteData.Average(x => x.Value));
}
}
return result;
}
}
}

View File

@ -19,7 +19,6 @@ using YD_WeChatApplet.Api.SmartSportsEntitys;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Authorization;
using System.Text.Json;
using YD_WeChatApplet.Commons.MemoryCaches;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using YD_WeChatApplet.Commons.Dto.ClientSide;
using System.Reflection;

View File

@ -3,6 +3,8 @@ using TGJ.NetworkFreight.SeckillAggregateServices.Pos.UserService;
using YD_WeChatApplet.Api;
using YD_WeChatApplet.Api.Entitys;
using YD_WeChatApplet.Commons;
using YD_WeChatApplet.Commons.Dto;
using YD_WeChatApplet.Commons.Dto.ClassRoomRecord;
using YD_WeChatApplet.Commons.Dto.HomeWork;
using YD_WeChatApplet.Commons.Dto.Teacher;
@ -48,5 +50,26 @@ namespace YD_WeChatApplet.Services
/// <param name="dto"></param>
/// <returns></returns>
Task<DataStatisticsDetailsDto> DataStatisticsDetails(DataStatisticsDetailsFilterDto dto);
/// <summary>
/// 课堂记录
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
Task<PageDataDto<ClassRoomRecordPageDto>> ClassRoomRecord(ClassRoomRecordDto dto);
/// <summary>
/// 课堂详情
/// </summary>
/// <param name="classRoomId"></param>
/// <returns></returns>
Task<ClassReportDetailsDto> ClassRoomReportDetails(int classRoomId);
/// <summary>
/// 学员课堂报告
/// </summary>
/// <param name="studentNo"></param>
/// <returns></returns>
Task<StudentClassRoomReportDto> StudentClassRoomReport(int classRoomId, string studentNo);
}
}

View File

@ -0,0 +1,183 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YD_WeChatApplet.Api.SmartSportsEntitys
{
[Table("Ai_ClassRoomRecord")]
public class Ai_ClassRoomRecord
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Display(Description = "主键Id")]
[Comment("Id")]
public int Id { get; set; }
/// <summary>
///学校Code
/// </summary>
[Display(Name = "学校Code")]
[Comment("学校Code")]
[Column(TypeName = "nvarchar(100)")]
public string SchoolCode { get; set; }
/// <summary>
/// AI设备的唯一编码
/// </summary>
[Display(Name = "AI设备的唯一编码")]
[Comment("AI设备的唯一编码")]
[Column(TypeName = "nvarchar(100)")]
public string Code { get; set; }
/// <summary>
/// 名称
/// </summary>
[Display(Name = "名称")]
[Comment("名称")]
[Column(TypeName = "nvarchar(200)")]
public string Name { get; set; }
/// <summary>
/// 年级编号
/// </summary>
[Display(Name = "年级编号")]
[Comment("年级编号")]
[Column(TypeName = "int")]
public int GradeId { get; set; }
/// <summary>
///班级Id
/// </summary>
[Display(Name = "班级Id")]
[Comment("班级Id")]
[Column(TypeName = "int")]
public int ClassId { get; set; }
/// <summary>
/// 年级名称
/// </summary>
[Display(Name = "年级名称")]
[Comment("年级名称")]
[Column(TypeName = "nvarchar(100)")]
public string GradeName { get; set; }
/// <summary>
/// 班级名称
/// </summary>
[Display(Name = "班级名称")]
[Comment("班级名称")]
[Column(TypeName = "nvarchar(100)")]
public string ClassName { get; set; }
/// <summary>
/// 训练模块枚举
/// </summary>
[Display(Name = "训练模块枚举")]
[Comment("训练模块枚举")]
[Column(TypeName = "int")]
public int TrainingModuleEnum { get; set; }
/// <summary>
/// 开始时间
/// </summary>
[Display(Name = "开始时间")]
[Comment("开始时间")]
[Column(TypeName = "datetime")]
public DateTime? StartTime { get; set; }
/// <summary>
/// 结束时间
/// </summary>
[Display(Name = "结束时间")]
[Comment("结束时间")]
[Column(TypeName = "datetime")]
public DateTime? EndTime { get; set; }
/// <summary>
///老师Id
/// </summary>
[Display(Name = "老师Id")]
[Comment("老师Id")]
[Column(TypeName = "int")]
public int TeacherId { get; set; }
/// <summary>
/// 老师姓名
/// </summary>
[Display(Name = "老师姓名")]
[Comment("老师姓名")]
[Column(TypeName = "nvarchar(200)")]
public string TeacherName { get; set; }
/// <summary>
/// 参与人数
/// </summary>
[Display(Name = "参与人数")]
[Comment("参与人数")]
[Column(TypeName = "int")]
public int ParticipateCount { get; set; }
/// <summary>
/// 班级下学生人数
/// </summary>
[Display(Name = "班级下学生人数")]
[Comment("班级下学生人数")]
[Column(TypeName = "int")]
public int StudentCount { get; set; }
/// <summary>
/// 缺勤人数
/// </summary>
[Display(Name = "缺勤人数")]
[Comment("缺勤人数")]
[Column(TypeName = "int")]
public int NoParticipateCount { get; set; }
/// <summary>
/// 新增人数
/// </summary>
[Display(Name = "新增人数")]
[Comment("新增人数")]
[Column(TypeName = "int")]
public int AddCount { get; set; }
/// <summary>
///备注
/// </summary>
[Display(Name = "备注")]
[Comment("备注")]
[Column(TypeName = "text")]
public string? Remarks { get; set; }
/// <summary>
/// 当前年份
/// </summary>
[Display(Name = "当前年份")]
[Comment("当前年份")]
[Column(TypeName = "int)")]
public int Year { get; set; }
/// <summary>
/// 学期
/// </summary>
[Display(Name = "学期")]
[Comment("学期")]
[Column(TypeName = "int)")]
public int Semester { get; set; }
/// <summary>
/// 是否显示
/// </summary>
[Display(Name = "是否显示")]
[Comment("是否显示")]
[Column(TypeName = "bit")]
[Editable(true)]
public bool IsDisplay { get; set; }
public List<Ai_ClassroomStudentRecord> ClassroomStudentRecord { get; set; }
}
}

View File

@ -0,0 +1,127 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YD_WeChatApplet.Api.SmartSportsEntitys
{
[Table("Ai_ClassroomStudentRecord")]
public class Ai_ClassroomStudentRecord
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Display(Description = "主键Id")]
[Comment("Id")]
public int Id { get; set; }
/// <summary>
///学校Code
/// </summary>
[Display(Name = "学校Code")]
[Comment("学校Code")]
[Column(TypeName = "nvarchar(100)")]
public string SchoolCode { get; set; }
/// <summary>
/// AI设备的唯一编码
/// </summary>
[Display(Name = "AI设备的唯一编码")]
[Comment("AI设备的唯一编码")]
[Column(TypeName = "nvarchar(100)")]
public string Code { get; set; }
/// <summary>
/// 课堂记录Id
/// </summary>
[Display(Name = "课堂记录Id")]
[Comment("课堂记录Id")]
[Column(TypeName = "int")]
public int ClassRoomRecordId { get; set; }
/// <summary>
/// 年级编号
/// </summary>
[Display(Name = "年级编号")]
[Comment("年级编号")]
[Column(TypeName = "int")]
public int GradeId { get; set; }
/// <summary>
///班级Id
/// </summary>
[Display(Name = "班级Id")]
[Comment("班级Id")]
[Column(TypeName = "int")]
public int ClassId { get; set; }
/// <summary>
/// 年级名称
/// </summary>
[Display(Name = "年级名称")]
[Comment("年级名称")]
[Column(TypeName = "nvarchar(100)")]
public string? GradeName { get; set; }
/// <summary>
/// 班级名称
/// </summary>
[Display(Name = "班级名称")]
[Comment("班级名称")]
[Column(TypeName = "nvarchar(100)")]
public string? ClassName { get; set; }
/// <summary>
///老师Id
/// </summary>
[Display(Name = "老师Id")]
[Comment("老师Id")]
[Column(TypeName = "int")]
public int TeacherId { get; set; }
/// <summary>
///学号
/// </summary>
[Display(Name = "学号")]
[Comment("学号")]
[Column(TypeName = "nvarchar(100)")]
public string StudentNo { get; set; }
/// <summary>
///姓名
/// </summary>
[Display(Name = "姓名")]
[Comment("姓名")]
[Column(TypeName = "nvarchar(100)")]
public string? StudentName { get; set; }
/// <summary>
///性别
/// </summary>
[Display(Name = "性别")]
[Comment("学校Co性别de")]
[Column(TypeName = "int")]
public int Sex { get; set; }
/// <summary>
///年龄
/// </summary>
[Display(Name = "年龄")]
[Comment("年龄")]
[Column(TypeName = "int")]
public int Age { get; set; }
/// <summary>
/// 是否显示
/// </summary>
[Display(Name = "是否显示")]
[Comment("是否显示")]
[Column(TypeName = "bit")]
[Editable(true)]
public bool IsDisplay { get; set; }
public Ai_ClassRoomRecord ClassRoomRecord { get; set; }
}
}

View File

@ -0,0 +1,230 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YD_WeChatApplet.Api.SmartSportsEntitys
{
[Table("Ai_FastJumpRopeData")]
public class Ai_FastJumpRopeData
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Display(Description = "主键Id")]
[Comment("Id")]
public int Id { get; set; }
/// <summary>
///学校Code
/// </summary>
[Display(Name = "学校Code")]
[Comment("学校Code")]
[Column(TypeName = "nvarchar(100)")]
public string SchoolCode { get; set; }
/// <summary>
/// AI设备的唯一编码
/// </summary>
[Display(Name = "AI设备的唯一编码")]
[Comment("AI设备的唯一编码")]
[Column(TypeName = "nvarchar(100)")]
public string Code { get; set; }
/// <summary>
/// 课堂记录Id
/// </summary>
[Display(Name = "课堂记录Id")]
[Comment("课堂记录Id")]
[Column(TypeName = "int")]
public int ClassRoomRecordId { get; set; }
/// <summary>
/// GroupId
/// </summary>
[Display(Name = "GroupId")]
[Comment("GroupId")]
[Column(TypeName = "nvarchar(100)")]
public string GroupId { get; set; }
/// <summary>
/// 设备上传成绩时唯一标识, 重复时服务端不保存数据
/// </summary>
[Display(Name = "设备上传成绩时唯一标识, 重复时服务端不保存数据")]
[Comment("设备上传成绩时唯一标识, 重复时服务端不保存数据")]
public long UniqueId { get; set; }
/// <summary>
/// 模式类型
/// </summary>
[Display(Name = "模式类型")]
[Comment("模式类型")]
[Column(TypeName = "int")]
public int ModeType { get; set; }
/// <summary>
/// 模式名称
/// </summary>
[Display(Name = "模式名称")]
[Comment("模式名称")]
[Column(TypeName = "nvarchar(100)")]
public string ModelName { get; set; }
/// <summary>
/// 年级编号
/// </summary>
[Display(Name = "年级编号")]
[Comment("年级编号")]
[Column(TypeName = "int")]
public int GradeId { get; set; }
/// <summary>
///班级Id
/// </summary>
[Display(Name = "班级Id")]
[Comment("班级Id")]
[Column(TypeName = "int")]
public int ClassId { get; set; }
/// <summary>
/// 年级名称
/// </summary>
[Display(Name = "年级名称")]
[Comment("年级名称")]
[Column(TypeName = "nvarchar(100)")]
public string GradeName { get; set; }
/// <summary>
/// 班级名称
/// </summary>
[Display(Name = "班级名称")]
[Comment("班级名称")]
[Column(TypeName = "nvarchar(100)")]
public string ClassName { get; set; }
/// <summary>
/// 测试人数
/// </summary>
[Display(Name = "测试人数")]
[Comment("测试人数")]
[Column(TypeName = "int")]
public int? StudentCount { get; set; }
/// <summary>
///老师Id
/// </summary>
[Display(Name = "老师Id")]
[Comment("老师Id")]
[Column(TypeName = "int")]
public int TeacherId { get; set; }
/// <summary>
/// 训练模块[[1:专项教学/2:测评考级/3:AI赛场/4:AI体测/5:速度跳绳]
/// </summary>
[Display(Name = "训练模块[[1:专项教学/2:测评考级/3:AI赛场/4:AI体测/5:速度跳绳]")]
[Comment("训练模块[[1:专项教学/2:测评考级/3:AI赛场/4:AI体测]/5:")]
[Column(TypeName = "int")]
public int TrainingModule { get; set; }
/// <summary>
/// 开始时间
/// </summary>
[Display(Name = "开始时间")]
[Comment("开始时间")]
[Column(TypeName = "datetime")]
public DateTime? StartTime { get; set; }
/// <summary>
/// 结束时间
/// </summary>
[Display(Name = "结束时间")]
[Comment("结束时间")]
[Column(TypeName = "datetime")]
public DateTime? EndTime { get; set; }
/// <summary>
///测试时间
/// </summary>
[Display(Name = "测试时间")]
[Comment("测试时间")]
[Column(TypeName = "datetime")]
[Editable(true)]
public DateTime ScoreTime { get; set; }
/// <summary>
///学号
/// </summary>
[Display(Name = "学号")]
[Comment("学号")]
[Column(TypeName = "nvarchar(100)")]
public string StudentNo { get; set; }
/// <summary>
///姓名
/// </summary>
[Display(Name = "姓名")]
[Comment("姓名")]
[Column(TypeName = "nvarchar(100)")]
public string StudentName { get; set; }
/// <summary>
///性别
/// </summary>
[Display(Name = "性别")]
[Comment("学校Co性别de")]
[Column(TypeName = "int")]
public int Sex { get; set; }
/// <summary>
///运动时长/分钟
/// </summary>
[Display(Name = "运动时长/秒")]
[Comment("运动时长/秒")]
[Column(TypeName = "int")]
public int? MotionDuration { get; set; }
/// <summary>
/// 训练成绩等级[1:优秀,2:良好,3:及格,4:不及格]
/// 心率项目[1:达标,2:未达标]
/// </summary>
[Display(Name = "训练成绩等级")]
[Comment("训练成绩等级")]
[Column(TypeName = "int")]
public int RankEnum { get; set; }
/// <summary>
/// 等级
/// </summary>
[Display(Name = "等级")]
[Comment("等级")]
[Column(TypeName = "nvarchar(100)")]
public string Rank { get; set; }
/// <summary>
///错误个数[敏捷:错误个数]
/// </summary>
[Display(Name = "错误个数")]
[Comment("错误个数")]
[Column(TypeName = "int")]
public int? ErrorNumber { get; set; }
/// <summary>
///正确个数[敏捷:正确个数]
/// </summary>
[Display(Name = "正确个数")]
[Comment("正确个数")]
[Column(TypeName = "int")]
public int? JumpValue { get; set; }
/// <summary>
/// 是否显示
/// </summary>
[Display(Name = "是否显示")]
[Comment("是否显示")]
[Column(TypeName = "bit")]
[Editable(true)]
public bool IsDisplay { get; set; }
}
}

View File

@ -0,0 +1,174 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YD_WeChatApplet.Api.SmartSportsEntitys
{
[Table("Ai_HeartRateData")]
public class Ai_HeartRateData
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Display(Description = "主键Id")]
[Comment("Id")]
public int Id { get; set; }
/// <summary>
///学校Code
/// </summary>
[Display(Name = "学校Code")]
[Comment("学校Code")]
[Column(TypeName = "nvarchar(100)")]
public string SchoolCode { get; set; }
/// <summary>
/// AI设备的唯一编码
/// </summary>
[Display(Name = "AI设备的唯一编码")]
[Comment("AI设备的唯一编码")]
[Column(TypeName = "nvarchar(100)")]
public string Code { get; set; }
/// <summary>
/// 课堂记录Id
/// </summary>
[Display(Name = "课堂记录Id")]
[Comment("课堂记录Id")]
[Column(TypeName = "int")]
public int ClassRoomRecordId { get; set; }
/// <summary>
/// 年级编号
/// </summary>
[Display(Name = "年级编号")]
[Comment("年级编号")]
[Column(TypeName = "int")]
public int GradeId { get; set; }
/// <summary>
///班级Id
/// </summary>
[Display(Name = "班级Id")]
[Comment("班级Id")]
[Column(TypeName = "int")]
public int ClassId { get; set; }
/// <summary>
/// 年级名称
/// </summary>
[Display(Name = "年级名称")]
[Comment("年级名称")]
[Column(TypeName = "nvarchar(100)")]
public string GradeName { get; set; }
/// <summary>
/// 班级名称
/// </summary>
[Display(Name = "班级名称")]
[Comment("班级名称")]
[Column(TypeName = "nvarchar(100)")]
public string ClassName { get; set; }
/// <summary>
/// 班级人数
/// </summary>
//[Display(Name = "班级人数")]
//[Comment("班级人数")]
//[Column(TypeName = "int")]
//public int StudentCount { get; set; }
/// <summary>
///老师Id
/// </summary>
[Display(Name = "老师Id")]
[Comment("老师Id")]
[Column(TypeName = "int")]
public int TeacherId { get; set; }
/// <summary>
///学号
/// </summary>
[Display(Name = "学号")]
[Comment("学号")]
[Column(TypeName = "nvarchar(100)")]
public string StudentNo { get; set; }
/// <summary>
///姓名
/// </summary>
[Display(Name = "姓名")]
[Comment("姓名")]
[Column(TypeName = "nvarchar(100)")]
public string StudentName { get; set; }
/// <summary>
///性别
/// </summary>
[Display(Name = "性别")]
[Comment("学校Co性别de")]
[Column(TypeName = "int")]
public int Sex { get; set; }
/// <summary>
///测试时间
/// </summary>
[Display(Name = "测试时间")]
[Comment("测试时间")]
[Column(TypeName = "datetime")]
[Editable(true)]
public DateTime ScoreTime { get; set; }
/// <summary>
///运动时长/分钟
/// </summary>
[Display(Name = "运动时长/分钟")]
[Comment("运动时长/分钟")]
[Column(TypeName = "int")]
public int MotionDuration { get; set; }
/// <summary>
///运动消耗
/// </summary>
[Display(Name = "运动消耗")]
[Comment("运动消耗")]
[Column(TypeName = "int")]
public int? Consumption { get; set; }
/// <summary>
///运动强度
/// </summary>
[Display(Name = "运动强度")]
[Comment("运动强度")]
[Column(TypeName = "double")]
public double Strength { get; set; }
/// <summary>
///心率
/// </summary>
[Display(Name = "心率")]
[Comment("心率")]
[Column(TypeName = "double")]
public double Value { get; set; }
/// <summary>
///备注
/// </summary>
[Display(Name = "备注")]
[Comment("备注")]
[Column(TypeName = "text")]
public string? Remarks { get; set; }
/// <summary>
/// 是否显示
/// </summary>
[Display(Name = "是否显示")]
[Comment("是否显示")]
[Column(TypeName = "bit")]
[Editable(true)]
public bool IsDisplay { get; set; }
}
}

View File

@ -8,7 +8,6 @@ using YD_WeChatApplet.Context;
using Microsoft.EntityFrameworkCore;
using YD_WeChatApplet.Services;
using YD_WeChatApplet.Commons.Filters;
using YD_WeChatApplet.Commons.MemoryCaches;
using YD_WeChatApplet.Commons.Users;
using Newtonsoft.Json.Serialization;
using Microsoft.AspNetCore.Authentication.JwtBearer;
@ -68,7 +67,6 @@ namespace YD_WeChatApplet
services.AddScoped<IUserPreferenceService, UserPreferenceService>();
services.AddScoped<IServerService, ServerService>();
services.AddScoped<ICaching, MemoryCaching>();
services.AddScoped<ICacheService, RedisCacheService>();
services.AddSession();
services.AddMemoryCache();
@ -281,13 +279,13 @@ namespace YD_WeChatApplet
//配置HttpContext
app.UseStaticHttpContext();
//app.UseSwagger();
//app.UseSwaggerUI(c =>
//{
// //2个下拉框选项 选择对应的文档
// c.SwaggerEndpoint("/swagger/v1/swagger.json", "YD_WeChatApplet.Api");
// c.RoutePrefix = "";
//});
app.UseSwagger();
app.UseSwaggerUI(c =>
{
//2个下拉框选项 选择对应的文档
c.SwaggerEndpoint("/swagger/v1/swagger.json", "YD_WeChatApplet.Api");
c.RoutePrefix = "";
});
app.UseRouting();
app.UseCors();

View File

@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YD_WeChatApplet.Commons.Dto.ClassRoomRecord
{
/// <summary>
/// 课堂详情
/// </summary>
public class ClassReportDetailsDto
{
/// <summary>
/// 最大心率
/// </summary>
public int MaxHR { get; set; }
/// <summary>
/// 最小心率
/// </summary>
public int MinHR { get; set; }
/// <summary>
/// 平均心率
/// </summary>
public int AvgHR { get; set; }
/// <summary>
/// 中高强度时长
/// </summary>
public int HighIntensity { get; set; }
/// <summary>
/// 学生运动记录
/// </summary>
public List<StudentTrainingRecordDto> StudentTrainingRecordList { get; set; } = new List<StudentTrainingRecordDto>();
/// <summary>
/// 心率变化趋势
/// </summary>
public ChartDataDto HeartRateTrend { get; set; } = new ChartDataDto();
}
/// <summary>
/// 学生训练记录
/// </summary>
public class StudentTrainingRecordDto
{
/// <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; }
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YD_WeChatApplet.Commons.Dto.ClassRoomRecord
{
/// <summary>
/// 课堂列表
/// </summary>
public class ClassRoomRecordDto : PageDto
{
/// <summary>
/// 学号
/// </summary>
public string StudentNo { get; set; }
}
}

View File

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YD_WeChatApplet.Commons.Dto.ClassRoomRecord
{
/// <summary>
/// 课堂记录
/// </summary>
public class ClassRoomRecordPageDto
{
/// <summary>
/// 课堂记录ID
/// </summary>
public int? Id { get; set; }
/// <summary>
///课堂名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 班级Id
/// </summary>
public int? ClassId { get; set; }
/// <summary>
/// 课程起止时间
/// </summary>
public string StartingEndingTime { get; set; }
}
}

View File

@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YD_WeChatApplet.Commons.Dto.ClassRoomRecord
{
/// <summary>
/// 学员课堂报告
/// </summary>
public class StudentClassRoomReportDto
{
/// <summary>
/// 最大心率
/// </summary>
public int MaxHR { get; set; }
/// <summary>
/// 最小心率
/// </summary>
public int MinHR { get; set; }
/// <summary>
/// 平均心率
/// </summary>
public int AvgHR { get; set; }
/// <summary>
/// 中高强度时长
/// </summary>
public int HighIntensity { get; set; }
/// <summary>
/// 跳绳记录
/// </summary>
public List<JumpRecordListDto> JumpRecordList { get; set; } = new List<JumpRecordListDto>();
/// <summary>
/// 心率变化趋势
/// </summary>
public ChartDataDto HeartRateTrend { get; set; } = new ChartDataDto();
}
public class JumpRecordListDto
{
/// <summary>
/// 跳绳类型
/// </summary>
public string JumpType { get; set; }
/// <summary>
/// 总个数
/// </summary>
public int TotalCount { get; set; }
/// <summary>
/// 总时长
/// </summary>
public int TotalDuration { get; set; }
}
}

View File

@ -1,21 +0,0 @@
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using System;
namespace YD_WeChatApplet.Commons.MemoryCaches
{
public static class MemoryCacheSetup
{
public static void AddMemoryCacheSetup(this IServiceCollection services)
{
if (services == null) throw new ArgumentNullException(nameof(services));
services.AddScoped<ICaching, MemoryCaching>();
services.AddScoped<IMemoryCache>(factory =>
{
var cache = new MemoryCache(new MemoryCacheOptions());
return cache;
});
}
}
}

View File

@ -1,23 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace YD_WeChatApplet.Commons.MemoryCaches
{
/// <summary>
/// 缓存接口
/// </summary>
public interface ICaching
{
object Get(string cacheKey);
void Set(string cacheKey, object cacheValue, int seconds);
void Set(string cacheKey, object cacheValue);
void Update(string cacheKey, object cacheValue, int seconds);
void Remove(string cacheKey);
}
}

View File

@ -1,52 +0,0 @@
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace YD_WeChatApplet.Commons.MemoryCaches
{
/// <summary>
/// 实例化缓存接口ICaching
/// </summary>
public class MemoryCaching : ICaching
{
private readonly IMemoryCache _cache;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="cache"></param>
public MemoryCaching(IMemoryCache cache)
{
_cache = cache;
}
public object Get(string cacheKey)
{
return _cache.Get(cacheKey);
}
public void Update(string cacheKey, object cacheValue, int seconds)
{
_cache.Remove(cacheKey);
_cache.Set(cacheKey, cacheValue, TimeSpan.FromSeconds(seconds));
}
public void Set(string cacheKey, object cacheValue, int seconds)
{
_cache.Set(cacheKey, cacheValue, TimeSpan.FromSeconds(seconds));
}
public void Set(string cacheKey, object cacheValue)
{
_cache.Set(cacheKey, cacheValue);
}
public void Remove(string cacheKey)
{
_cache.Remove(cacheKey);
}
}
}

View File

@ -12,7 +12,6 @@
<PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Formatters.Json" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.0" />
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.1.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.1.0" />
</ItemGroup>