1419 lines
61 KiB
C#
1419 lines
61 KiB
C#
using AutoMapper;
|
||
using Castle.DynamicProxy.Generators;
|
||
using Microsoft.AspNetCore.Http;
|
||
using Microsoft.AspNetCore.Mvc;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using Microsoft.Extensions.DependencyInjection;
|
||
using Microsoft.ML;
|
||
using OfficeOpenXml.ConditionalFormatting;
|
||
using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
|
||
using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
|
||
using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
|
||
using SkiaSharp;
|
||
using StackExchange.Redis;
|
||
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using System.Diagnostics;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using VOL.Business.IServices;
|
||
using VOL.Business.IServices.Norm;
|
||
using VOL.Core.CacheManager;
|
||
using VOL.Core.Configuration;
|
||
using VOL.Core.Extensions;
|
||
using VOL.Core.Extensions.AutofacManager;
|
||
using VOL.Core.ManageUser;
|
||
using VOL.Core.Utilities;
|
||
using VOL.Entity.DomainModels;
|
||
using VOL.Entity.DomainModels.Business.People;
|
||
using VOL.Entity.Enum;
|
||
using VOL.Model;
|
||
using VOL.Model.Ai;
|
||
using VOL.Model.Norm.Request;
|
||
using VOL.Model.Norm.Response;
|
||
using VOL.Model.School.Response;
|
||
using VOL.System.IRepositories;
|
||
using VOL.System.Repositories;
|
||
using static Dapper.SqlMapper;
|
||
using static System.Formats.Asn1.AsnWriter;
|
||
|
||
namespace VOL.Business.Services
|
||
{
|
||
public class N_SportsTestResultService : IN_SportsTestResultService, IDependency
|
||
{
|
||
#region 初始化
|
||
private readonly IMapper _mapper;
|
||
private readonly ICacheService _cacheService;
|
||
private readonly ICacheQueryService _cacheQueryService;
|
||
private readonly IN_SportsTestResultRepository _sportsTestResultRepository;
|
||
private readonly IS_GradeRepository _gradeRepository;
|
||
private readonly IS_ClassRepository _classRepository;
|
||
private readonly IS_StudentRepository _studentRepository;
|
||
private readonly IN_HealthStandardsRepository _healthStandardsRepository;
|
||
private readonly IN_SportsTestCategoryRepository _sportsTestCategoryRepository;
|
||
//private readonly IG_ActivitiesRepository _activitiesRepository;
|
||
|
||
[ActivatorUtilitiesConstructor]
|
||
public N_SportsTestResultService(IMapper mapper,
|
||
ICacheService cacheService,
|
||
ICacheQueryService cacheQueryService,
|
||
IN_SportsTestResultRepository sportsTestResultRepository,
|
||
IS_GradeRepository gradeRepository,
|
||
IS_ClassRepository classRepository,
|
||
IS_StudentRepository studentRepository,
|
||
IN_HealthStandardsRepository healthStandardsRepository,
|
||
IN_SportsTestCategoryRepository sportsTestCategoryRepository
|
||
//IG_ActivitiesRepository activitiesRepository
|
||
)
|
||
{
|
||
_mapper = mapper;
|
||
_cacheService = cacheService;
|
||
_cacheQueryService = cacheQueryService;
|
||
_sportsTestResultRepository = sportsTestResultRepository;
|
||
_gradeRepository = gradeRepository;
|
||
_classRepository = classRepository;
|
||
_studentRepository = studentRepository;
|
||
_healthStandardsRepository = healthStandardsRepository;
|
||
|
||
_sportsTestCategoryRepository = sportsTestCategoryRepository;
|
||
//_activitiesRepository = activitiesRepository;
|
||
}
|
||
#endregion
|
||
|
||
/// <summary>
|
||
/// 导入学生体测成绩
|
||
/// </summary>
|
||
/// <param name="file"></param>
|
||
/// <returns></returns>
|
||
/// <exception cref="Exception"></exception>
|
||
public async Task ImportStudentsTestData(IFormFile file)
|
||
{
|
||
if (file == null || file.Length <= 0)
|
||
throw new Exception("操作失败");
|
||
|
||
List<ImportStudentsTestDataParam> dataObjects;
|
||
|
||
using (var fileStream = file.OpenReadStream())
|
||
{
|
||
dataObjects = Tool.ConvertExcelToList<ImportStudentsTestDataParam>(fileStream);
|
||
}
|
||
|
||
var studentNos = dataObjects.Select(x => x.StudentNo).Distinct().ToList();
|
||
|
||
// 用一个查询一次性获取所有学生信息
|
||
var students = await (from s in _studentRepository.DbContext.Set<S_Student>()
|
||
join c in _studentRepository.DbContext.Set<S_Class>() on s.ClassId equals c.Id
|
||
join g in _studentRepository.DbContext.Set<S_Grade>() on c.GradeId equals g.Id
|
||
where c.SchoolCode.Equals(UserContext.Current.TenantId)
|
||
select new
|
||
{
|
||
s.Id,
|
||
s.Age,
|
||
s.ClassId,
|
||
c.ClassName,
|
||
s.StudentName,
|
||
GradeId = g.Id,
|
||
g.GradeName,
|
||
s.Sex,
|
||
s.StudentNo
|
||
}).ToListAsync();
|
||
|
||
// 将学生信息存入字典,快速查找
|
||
var studentsDict = students.ToDictionary(x => x.StudentNo);
|
||
|
||
var entityList = new List<N_SportsTestValue>();
|
||
|
||
// 将时间变量移到外部,避免重复赋值
|
||
var timeNow = DateTime.Now;
|
||
|
||
foreach (var data in dataObjects)
|
||
{
|
||
if (!studentsDict.TryGetValue(data.StudentNo, out var student))
|
||
{
|
||
throw new Exception($"未找到此编号为{data.StudentNo}的学生");
|
||
}
|
||
|
||
// 为每个学生添加多条体测数据
|
||
if (data.BMIValue > 0)
|
||
entityList.Add(await AddEnumStudentsTestData(data, SportsTestItemType.BMI, student, timeNow));
|
||
|
||
if (data.Sit_And_ReachValue > 0)
|
||
entityList.Add(await AddEnumStudentsTestData(data, SportsTestItemType.Sit_And_Reach, student, timeNow));
|
||
|
||
if (data.VitalCapacityValue > 0)
|
||
entityList.Add(await AddEnumStudentsTestData(data, SportsTestItemType.VitalCapacity, student, timeNow));
|
||
|
||
if (data.MeterRun_50Value > 0)
|
||
entityList.Add(await AddEnumStudentsTestData(data, SportsTestItemType.MeterRun_50, student, timeNow));
|
||
|
||
if (data.OneMinuteJumpRopeValue > 0)
|
||
entityList.Add(await AddEnumStudentsTestData(data, SportsTestItemType.OneMinuteJumpRope, student, timeNow));
|
||
|
||
if (data.One_Minute_Sit_UpValue > 0)
|
||
entityList.Add(await AddEnumStudentsTestData(data, SportsTestItemType.One_Minute_Sit_Up, student, timeNow));
|
||
|
||
if (data.ShuttleRun_50x8Value > 0)
|
||
entityList.Add(await AddEnumStudentsTestData(data, SportsTestItemType.ShuttleRun_50x8, student, timeNow));
|
||
|
||
if (data.StandingLongJumpValue > 0)
|
||
entityList.Add(await AddEnumStudentsTestData(data, SportsTestItemType.StandingLongJump, student, timeNow));
|
||
|
||
if (data.MeterRun_800Value > 0)
|
||
entityList.Add(await AddEnumStudentsTestData(data, SportsTestItemType.MeterRun_800, student, timeNow));
|
||
|
||
if (data.MeterRun_1000Value > 0)
|
||
entityList.Add(await AddEnumStudentsTestData(data, SportsTestItemType.MeterRun_1000, student, timeNow));
|
||
|
||
if (data.Pull_UpValue > 0)
|
||
entityList.Add(await AddEnumStudentsTestData(data, SportsTestItemType.Pull_Up, student, timeNow));
|
||
}
|
||
|
||
// 批量添加数据
|
||
await _sportsTestResultRepository.AddRangeAsync(entityList);
|
||
|
||
// 一次性保存所有修改
|
||
await _sportsTestResultRepository.SaveChangesAsync();
|
||
}
|
||
|
||
public async Task<N_SportsTestValue> AddEnumStudentsTestData(ImportStudentsTestDataParam data, SportsTestItemType type, dynamic student, DateTime timeNow)
|
||
{
|
||
var entity = new N_SportsTestValue
|
||
{
|
||
TeacherId = 1,
|
||
DataSource = DataSource.IOT,
|
||
ScoreTime = timeNow,
|
||
GradeId = student.GradeId,
|
||
ClassId = student.ClassId,
|
||
GradeName = student.GradeName,
|
||
ClassName = student.ClassName,
|
||
SchoolCode = UserContext.Current.TenantId,
|
||
Sex = student.Sex,
|
||
StudentNo = data.StudentNo,
|
||
StudentName = student.StudentName,
|
||
Creator = UserContext.Current.UserId,
|
||
CreateDate = timeNow
|
||
};
|
||
int gradeId = student.GradeId;
|
||
SexType sexType = student.Sex;
|
||
|
||
string typeStr = type.ToString();
|
||
|
||
// 根据测试项目类型设置对应的值
|
||
if (type == SportsTestItemType.BMI)
|
||
{
|
||
entity.Value = data.BMIValue;
|
||
|
||
// 根据测试项目查找标准
|
||
var standard = await _healthStandardsRepository.FindFirstAsync(x =>
|
||
x.CategoryEnum.Equals(typeStr) &&
|
||
x.GradeId == gradeId &&
|
||
x.Sex == sexType &&
|
||
data.BMIValue >= x.MinValue &&
|
||
data.BMIValue < x.MaxValue
|
||
);
|
||
|
||
if (standard != null)
|
||
{
|
||
entity.Score = standard.Score;
|
||
entity.Rank = standard.Rank;
|
||
}
|
||
|
||
}
|
||
else if (type == SportsTestItemType.Sit_And_Reach)
|
||
{
|
||
entity.Value = data.Sit_And_ReachValue;
|
||
|
||
// 根据测试项目查找标准
|
||
var standard = await _healthStandardsRepository.FindFirstAsync(x =>
|
||
x.CategoryEnum.Equals(typeStr) &&
|
||
x.GradeId == gradeId &&
|
||
x.Sex == sexType &&
|
||
data.Sit_And_ReachValue >= x.MinValue &&
|
||
data.Sit_And_ReachValue < x.MaxValue
|
||
);
|
||
|
||
if (standard != null)
|
||
{
|
||
entity.Score = standard.Score;
|
||
entity.Rank = standard.Rank;
|
||
}
|
||
}
|
||
else if (type == SportsTestItemType.VitalCapacity)
|
||
{
|
||
entity.Value = data.VitalCapacityValue;
|
||
|
||
// 根据测试项目查找标准
|
||
var standard = await _healthStandardsRepository.FindFirstAsync(x =>
|
||
x.CategoryEnum.Equals(typeStr) &&
|
||
x.GradeId == gradeId &&
|
||
x.Sex == sexType &&
|
||
data.VitalCapacityValue >= x.MinValue &&
|
||
data.VitalCapacityValue < x.MaxValue
|
||
);
|
||
|
||
if (standard != null)
|
||
{
|
||
entity.Score = standard.Score;
|
||
entity.Rank = standard.Rank;
|
||
}
|
||
}
|
||
else if (type == SportsTestItemType.MeterRun_50)
|
||
{
|
||
entity.Value = data.MeterRun_50Value;
|
||
|
||
// 根据测试项目查找标准
|
||
var standard = await _healthStandardsRepository.FindFirstAsync(x =>
|
||
x.CategoryEnum.Equals(typeStr) &&
|
||
x.GradeId == gradeId &&
|
||
x.Sex == sexType &&
|
||
data.MeterRun_50Value >= x.MinValue &&
|
||
data.MeterRun_50Value < x.MaxValue
|
||
);
|
||
|
||
if (standard != null)
|
||
{
|
||
entity.Score = standard.Score;
|
||
entity.Rank = standard.Rank;
|
||
}
|
||
}
|
||
else if (type == SportsTestItemType.OneMinuteJumpRope)
|
||
{
|
||
entity.Value = data.OneMinuteJumpRopeValue;
|
||
|
||
// 根据测试项目查找标准
|
||
var standard = await _healthStandardsRepository.FindFirstAsync(x =>
|
||
x.CategoryEnum.Equals(typeStr) &&
|
||
x.GradeId == gradeId &&
|
||
x.Sex == sexType &&
|
||
data.OneMinuteJumpRopeValue >= x.MinValue &&
|
||
data.OneMinuteJumpRopeValue < x.MaxValue
|
||
);
|
||
|
||
if (standard != null)
|
||
{
|
||
entity.Score = standard.Score;
|
||
entity.Rank = standard.Rank;
|
||
}
|
||
}
|
||
else if (type == SportsTestItemType.One_Minute_Sit_Up)
|
||
{
|
||
entity.Value = data.One_Minute_Sit_UpValue;
|
||
|
||
// 根据测试项目查找标准
|
||
var standard = await _healthStandardsRepository.FindFirstAsync(x =>
|
||
x.CategoryEnum.Equals(typeStr) &&
|
||
x.GradeId == gradeId &&
|
||
x.Sex == sexType &&
|
||
data.One_Minute_Sit_UpValue >= x.MinValue &&
|
||
data.One_Minute_Sit_UpValue < x.MaxValue
|
||
);
|
||
|
||
if (standard != null)
|
||
{
|
||
entity.Score = standard.Score;
|
||
entity.Rank = standard.Rank;
|
||
}
|
||
}
|
||
else if (type == SportsTestItemType.ShuttleRun_50x8)
|
||
{
|
||
entity.Value = data.ShuttleRun_50x8Value;
|
||
|
||
// 根据测试项目查找标准
|
||
var standard = await _healthStandardsRepository.FindFirstAsync(x =>
|
||
x.CategoryEnum.Equals(typeStr) &&
|
||
x.GradeId == gradeId &&
|
||
x.Sex == sexType &&
|
||
data.ShuttleRun_50x8Value >= x.MinValue &&
|
||
data.ShuttleRun_50x8Value < x.MaxValue
|
||
);
|
||
|
||
if (standard != null)
|
||
{
|
||
entity.Score = standard.Score;
|
||
entity.Rank = standard.Rank;
|
||
}
|
||
}
|
||
else if (type == SportsTestItemType.StandingLongJump)
|
||
{
|
||
entity.Value = data.StandingLongJumpValue;
|
||
|
||
// 根据测试项目查找标准
|
||
var standard = await _healthStandardsRepository.FindFirstAsync(x =>
|
||
x.CategoryEnum.Equals(typeStr) &&
|
||
x.GradeId == gradeId &&
|
||
x.Sex == sexType &&
|
||
data.StandingLongJumpValue >= x.MinValue &&
|
||
data.StandingLongJumpValue < x.MaxValue
|
||
);
|
||
|
||
if (standard != null)
|
||
{
|
||
entity.Score = standard.Score;
|
||
entity.Rank = standard.Rank;
|
||
}
|
||
}
|
||
else if (type == SportsTestItemType.MeterRun_800)
|
||
{
|
||
entity.Value = data.MeterRun_800Value;
|
||
|
||
// 根据测试项目查找标准
|
||
var standard = await _healthStandardsRepository.FindFirstAsync(x =>
|
||
x.CategoryEnum.Equals(typeStr) &&
|
||
x.GradeId == gradeId &&
|
||
x.Sex == sexType &&
|
||
data.MeterRun_800Value >= x.MinValue &&
|
||
data.MeterRun_800Value < x.MaxValue
|
||
);
|
||
|
||
if (standard != null)
|
||
{
|
||
entity.Score = standard.Score;
|
||
entity.Rank = standard.Rank;
|
||
}
|
||
}
|
||
else if (type == SportsTestItemType.MeterRun_1000)
|
||
{
|
||
entity.Value = data.MeterRun_1000Value;
|
||
|
||
// 根据测试项目查找标准
|
||
var standard = await _healthStandardsRepository.FindFirstAsync(x =>
|
||
x.CategoryEnum.Equals(typeStr) &&
|
||
x.GradeId == gradeId &&
|
||
x.Sex == sexType &&
|
||
data.MeterRun_1000Value >= x.MinValue &&
|
||
data.MeterRun_1000Value < x.MaxValue
|
||
);
|
||
|
||
if (standard != null)
|
||
{
|
||
entity.Score = standard.Score;
|
||
entity.Rank = standard.Rank;
|
||
}
|
||
}
|
||
else if (type == SportsTestItemType.Pull_Up)
|
||
{
|
||
entity.Value = data.Pull_UpValue;
|
||
|
||
// 根据测试项目查找标准
|
||
var standard = await _healthStandardsRepository.FindFirstAsync(x =>
|
||
x.CategoryEnum.Equals(typeStr) &&
|
||
x.GradeId == gradeId &&
|
||
x.Sex == sexType &&
|
||
data.Pull_UpValue >= x.MinValue &&
|
||
data.Pull_UpValue < x.MaxValue
|
||
);
|
||
|
||
if (standard != null)
|
||
{
|
||
entity.Score = standard.Score;
|
||
entity.Rank = standard.Rank;
|
||
}
|
||
}
|
||
|
||
entity.CategoryEnum = type.ToString();
|
||
entity.CategoryValue = (int)type;
|
||
|
||
return entity;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 大屏数据统计
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
/// <exception cref="NotImplementedException"></exception>
|
||
public async Task<LargeScreenDataStatModel> LargeScreenDataStat(LargeScreenDataStatParam paramDto)
|
||
{
|
||
if (paramDto.StartTime == DateTime.MinValue || paramDto.EndTime == DateTime.MinValue)
|
||
{
|
||
throw new Exception($"请求参数不可为空");
|
||
}
|
||
|
||
var res = new LargeScreenDataStatModel();
|
||
|
||
//学校信息
|
||
res.SchoolInfo = await GetLargeScreenSchoolInfo(paramDto);
|
||
|
||
//体测情况(体质健康监控)
|
||
res.TestSituations = await GetLargeScreenTestSituations(paramDto);
|
||
|
||
//体质监测排行榜
|
||
res.PhysicalMonitoringRanking = await GetLargeScreenPhysicalMonitoringRanking(paramDto);
|
||
|
||
//赛事活动情况
|
||
res.ActivitiesSituation = await GetLargeScreenActivitiesSituation(paramDto);
|
||
|
||
//肥胖情况
|
||
res.ObesitySituation = await GetLargeScreenObesitySituation(paramDto);
|
||
|
||
//视力情况
|
||
res.DicVisionSituation = await GetLargeScreenDicVisionSituation(paramDto);
|
||
|
||
//年级体测项目成绩监控
|
||
res.GradeSportsTestTranscript = await GetLargeScreenGradeSportsTestTranscript(paramDto);
|
||
|
||
return res;
|
||
}
|
||
|
||
#region 大屏信息
|
||
|
||
/// <summary>
|
||
/// 大屏学校信息
|
||
/// </summary>
|
||
/// <param name="paramDto"></param>
|
||
/// <returns></returns>
|
||
public async Task<SchoolInfoModel> GetLargeScreenSchoolInfo(LargeScreenDataStatParam paramDto)
|
||
{
|
||
var schoolInfo = new SchoolInfoModel();
|
||
|
||
var tenantId = UserContext.Current.TenantId;
|
||
|
||
//年级信息
|
||
var gradeModels = await (
|
||
from g in _gradeRepository.DbContext.Set<S_Grade>()
|
||
join a in _gradeRepository.DbContext.Set<S_SchoolAssocGrade>() on g.Id equals a.GradeId
|
||
join c in _gradeRepository.DbContext.Set<S_Class>() on g.Id equals c.GradeId into classGroup
|
||
from c in classGroup.DefaultIfEmpty()
|
||
|
||
where a.SchoolCode.Equals(tenantId) && c.SchoolCode.Equals(tenantId)
|
||
|
||
group new { c } by new { g.Id, g.GradeName } into groupedData
|
||
select new
|
||
{
|
||
groupedData.Key.Id,
|
||
groupedData.Key.GradeName,
|
||
ClassCount = groupedData.Select(x => x.c.Id).Distinct().Count(),
|
||
ClassIds = groupedData.Select(x => x.c.Id).Distinct().ToList()
|
||
}).ToListAsync();
|
||
|
||
//老师信息
|
||
var teacherCountModels = await (
|
||
from t in _gradeRepository.DbContext.Set<S_Teacher>()
|
||
join a in _gradeRepository.DbContext.Set<S_ClassAssocTeacher>() on t.Id equals a.TeacherId into assocTeachers
|
||
from at in assocTeachers.DefaultIfEmpty()
|
||
where t.SchoolCode.Equals(UserContext.Current.TenantId) && t.TeacherStatus != TeacherStatus.Depart
|
||
group new { t, at } by new { t.Id } into groupedData
|
||
select new TeacherPageListModel()
|
||
{
|
||
Id = groupedData.Key.Id
|
||
}).ToListAsync();
|
||
|
||
var tCount = teacherCountModels.Count;
|
||
|
||
//老师信息
|
||
var teacherDetailsModels = from a in _gradeRepository.DbContext.Set<S_ClassAssocTeacher>()
|
||
join t in _gradeRepository.DbContext.Set<S_Teacher>() on a.TeacherId equals t.Id into teacher
|
||
from tea in teacher.DefaultIfEmpty()
|
||
where tea.SchoolCode.Equals(UserContext.Current.TenantId) && tea.TeacherStatus != TeacherStatus.Depart
|
||
group new { a } by new { a.ClassId } into groupedData
|
||
select new
|
||
{
|
||
ClassId = groupedData.Key.ClassId,
|
||
TeacherIds = groupedData
|
||
.Where(x => x.a.ClassId == groupedData.Key.ClassId)
|
||
.Select(x => x.a.TeacherId)
|
||
};
|
||
|
||
var teacherModels = await teacherDetailsModels.ToListAsync();
|
||
|
||
///班级信息
|
||
gradeModels.ForEach(x =>
|
||
{
|
||
schoolInfo.ClassData.Add(new ClassModel() { GradeName = x.GradeName, ClassCount = x.ClassCount });
|
||
|
||
var teachers = teacherModels.Where(t => x.ClassIds.Contains(t.ClassId)).ToList();
|
||
|
||
schoolInfo.TeacherData.Add(new TeacherModel()
|
||
{
|
||
GradeName = x.GradeName,
|
||
TeacherCount = teachers
|
||
.SelectMany(c => c.TeacherIds)
|
||
.Distinct()
|
||
.Count()
|
||
});
|
||
});
|
||
|
||
var classIds = gradeModels.SelectMany(x => x.ClassIds).ToList();
|
||
|
||
var students = await (from s in _studentRepository.DbContext.Set<S_Student>()
|
||
join c in _studentRepository.DbContext.Set<S_Class>() on s.ClassId equals c.Id
|
||
join g in _studentRepository.DbContext.Set<S_Grade>() on c.GradeId equals g.Id
|
||
where s.SchoolCode.Equals(tenantId) && s.StudentStatus == StudentStatus.Normal
|
||
select s
|
||
).ToListAsync();
|
||
|
||
schoolInfo.StudentData.MaleCount = students.Where(x => x.Sex == SexType.Male).Count();
|
||
schoolInfo.StudentData.FemaleCount = students.Where(x => x.Sex == SexType.Female).Count();
|
||
|
||
schoolInfo.TotalClassCount = gradeModels.Select(x => x.ClassCount).Sum();
|
||
schoolInfo.TotalTeacherCount = tCount;
|
||
|
||
// 从缓存中获取数据
|
||
var sportsTestResults = await _cacheQueryService.GeSportsTestDataCacheAsync(x => x.ScoreTime >= paramDto.StartTime && x.ScoreTime <= paramDto.EndTime);
|
||
|
||
// 运动时长
|
||
schoolInfo.AccumulatedTrainDuration = sportsTestResults.Select(x => x.MotionDuration).Sum();
|
||
|
||
var largeScreenTrainingDataModel = new List<LargeScreenTrainingDataModel>();
|
||
|
||
largeScreenTrainingDataModel.Add(await GeLargeScreenTrainingInfo(1, paramDto));
|
||
largeScreenTrainingDataModel.Add(await GeLargeScreenTrainingInfo(2, paramDto));
|
||
largeScreenTrainingDataModel.Add(await GeLargeScreenTrainingInfo(3, paramDto));
|
||
|
||
schoolInfo.LargeScreenTrainingDataModel = largeScreenTrainingDataModel;
|
||
|
||
return schoolInfo;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 大屏训练数据
|
||
/// </summary>
|
||
/// <param name="dateType">时间类型(1:今日,2:本周,3:本月)</param>
|
||
/// <param name="paramDto"></param>
|
||
/// <returns></returns>
|
||
public async Task<LargeScreenTrainingDataModel> GeLargeScreenTrainingInfo(int dateType, LargeScreenDataStatParam paramDto)
|
||
{
|
||
var largeScreenTrainingDataModel = new LargeScreenTrainingDataModel();
|
||
|
||
var tenantId = UserContext.Current.TenantId;
|
||
|
||
DateTime startTime;
|
||
DateTime endTime;
|
||
|
||
if (dateType == 1)
|
||
{
|
||
startTime = DateTime.Today;
|
||
endTime = DateTime.Today.AddDays(1).AddSeconds(-1);
|
||
largeScreenTrainingDataModel.DataType = "今日";
|
||
}
|
||
else if (dateType == 2)
|
||
{
|
||
// 获取本周的开始和结束时间
|
||
int diff = (7 + (DateTime.Now.DayOfWeek - DayOfWeek.Monday)) % 7;
|
||
startTime = DateTime.Now.AddDays(-1 * diff).Date;
|
||
endTime = startTime.AddDays(7).AddSeconds(-1);
|
||
largeScreenTrainingDataModel.DataType = "本周";
|
||
}
|
||
else if (dateType == 3)
|
||
{
|
||
// 获取本月的开始和结束时间
|
||
startTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
|
||
endTime = startTime.AddMonths(1).AddSeconds(-1);
|
||
largeScreenTrainingDataModel.DataType = "本月";
|
||
}
|
||
else
|
||
{
|
||
return largeScreenTrainingDataModel;
|
||
}
|
||
|
||
|
||
// 从缓存中获取数据
|
||
var sportsTestResults = await _cacheQueryService.GeSportsTestDataCacheAsync(x => x.ScoreTime >= startTime && x.ScoreTime <= endTime);
|
||
|
||
var testCategorys = sportsTestResults.Select(x => x.CategoryEnum).Distinct().ToList();
|
||
|
||
#region 总数据
|
||
|
||
// 训练次数
|
||
largeScreenTrainingDataModel.TrainingCount = sportsTestResults.Count();
|
||
// 上课节数
|
||
largeScreenTrainingDataModel.AttendClassCount = sportsTestResults.GroupBy(x => x.ClassRoomRecordId).Count();
|
||
// 上课时长
|
||
largeScreenTrainingDataModel.AttendClassDuration = sportsTestResults.Select(x => x.MotionDuration).Sum();
|
||
// 赛事参与人数
|
||
var activitiestDatas = await (from ad in _gradeRepository.DbContext.Set<Ai_ActivitiestData>()
|
||
join a in _gradeRepository.DbContext.Set<G_Activities>() on ad.ActivitiesId equals a.Id into activitiesDto
|
||
from a in activitiesDto.DefaultIfEmpty()
|
||
where a.SchoolCode == tenantId && a.StartDate >= startTime &&
|
||
a.EndDate <= endTime && a.ActivitiesStatus == ActivitiesStatus.Completed
|
||
select ad).ToListAsync();
|
||
|
||
largeScreenTrainingDataModel.EventParticipationBodCount = activitiestDatas.GroupBy(x => x.StudentNo).Count();
|
||
// 项目测试人数
|
||
largeScreenTrainingDataModel.ProjectTestingBodCount = sportsTestResults.GroupBy(x => x.StudentNo).Count();
|
||
#endregion
|
||
|
||
#region 平均数据 (全校学生不区分训练/体测/AI赛事/考级测评/作业)
|
||
// 运动人数
|
||
largeScreenTrainingDataModel.AccumulatedTrainCount = sportsTestResults.GroupBy(x => x.StudentNo).Count();
|
||
// 平均跳绳次数(跳绳个数少于10个不计算在内)
|
||
var sportsTestCategorys = await _sportsTestCategoryRepository
|
||
.FindAsIQueryable(x => x.StatisticType >= 0 && testCategorys.Contains(x.CategoryEnum))
|
||
.Select(x => new SportsTestCategoryModel()
|
||
{
|
||
Id = x.Id,
|
||
CategoryEnum = x.CategoryEnum,
|
||
CategoryName = x.CategoryName,
|
||
StatisticType = x.StatisticType,
|
||
IsRopeSkip = x.IsRopeSkip
|
||
}).ToListAsync();
|
||
var ropeSkipCategorys = sportsTestCategorys.Where(x => x.IsRopeSkip).Select(x => x.CategoryEnum).ToList();
|
||
var avgRopeSkips = sportsTestResults.Where(x => x.CategoryValue.Equals((int)SportsTestItemType.OneMinuteJumpRope) && ropeSkipCategorys.Contains(x.CategoryEnum)).ToList();
|
||
largeScreenTrainingDataModel.AvgRopeSkipCount = avgRopeSkips.Count > 0 ? (int)avgRopeSkips.Where(x => x.Value > 10).Average(x => x.Value) : 0;
|
||
// 平均运动强度
|
||
largeScreenTrainingDataModel.AvgStrength = sportsTestResults.Count > 0 ? (int)sportsTestResults.Average(x => x.Strength) : 0;
|
||
// 运动时长
|
||
largeScreenTrainingDataModel.MotionDuration = sportsTestResults.Select(x => x.MotionDuration).Sum();
|
||
// 平均心率
|
||
//var avgHeartRates = sportsTestResults.Where(x => x.CategoryEnum.Equals("HeartRate")).ToList();
|
||
largeScreenTrainingDataModel.AvgHeartRate = sportsTestResults.Count > 0 ? (int)sportsTestResults.Average(x => x.Value) : 0;
|
||
// 平均消耗
|
||
largeScreenTrainingDataModel.AvgConsume = sportsTestResults.Count > 0 ? (int)sportsTestResults.Average(x => x.Consumption) : 0;
|
||
|
||
#endregion
|
||
|
||
return largeScreenTrainingDataModel;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 大屏体测情况(体质健康监控)
|
||
/// </summary>
|
||
/// <param name="paramDto"></param>
|
||
/// <returns></returns>
|
||
public async Task<TestSituations> GetLargeScreenTestSituations(LargeScreenDataStatParam paramDto)
|
||
{
|
||
var testSituations = new TestSituations();
|
||
var tenantId = UserContext.Current.TenantId;
|
||
|
||
// 从缓存中获取数据
|
||
var sportsTestResults = await _cacheQueryService.GeSportsTestDataCacheAsync(x => x.ScoreTime >= paramDto.StartTime && x.ScoreTime <= paramDto.EndTime);
|
||
|
||
var monitorList = sportsTestResults
|
||
.GroupBy(x => new { x.StudentNo })
|
||
.Select(g => new
|
||
{
|
||
g.Key.StudentNo,
|
||
g.First().Sex,
|
||
Score = (g.Sum(x => x.Score) + g.Sum(x => x.AdditionalScore)) / (g.Select(x => x.CategoryEnum).Distinct().Count())
|
||
})
|
||
.Select(x => new
|
||
{
|
||
x.StudentNo,
|
||
x.Sex,
|
||
x.Score,
|
||
Rank = x.Score.GetRank()
|
||
}).ToList();
|
||
|
||
var rankValues = new List<string> { "优秀", "良好", "及格", "不及格" };
|
||
|
||
// 计算每个 Rank 的百分比和性别统计
|
||
var rankStats = rankValues.ToDictionary(rank => rank, rank => new
|
||
{
|
||
Count = monitorList.Count(x => x.Rank == rank),
|
||
MaleCount = monitorList.Count(x => x.Sex == SexType.Male && x.Rank == rank),
|
||
FemaleCount = monitorList.Count(x => x.Sex == SexType.Female && x.Rank == rank)
|
||
});
|
||
|
||
// 计算总人数
|
||
float totalCount = monitorList.Count(x => rankValues.Contains(x.Rank));
|
||
|
||
// 计算各个 Rank 的百分比
|
||
var rankPercentages = rankStats.ToDictionary(
|
||
rank => rank.Key,
|
||
rank => (float)Math.Round((rank.Value.Count / totalCount) * 100)
|
||
);
|
||
|
||
// 计算并调整最后一个百分比(确保总和为100%)
|
||
float sum = rankPercentages.Values.Sum();
|
||
float adjustment = 100 - sum;
|
||
rankPercentages["不及格"] += adjustment;
|
||
|
||
// 更新 TestSituation,保留男女人数和百分比
|
||
var dicMonitorList = rankValues.Select(rank => new TestSituation()
|
||
{
|
||
Title = $"{rank}率",
|
||
Value = rankPercentages[rank],
|
||
MaleCount = rankStats[rank].MaleCount,
|
||
FemaleCount = rankStats[rank].FemaleCount
|
||
}).ToList();
|
||
|
||
// 计算 "优秀率" 和 "良好率" 的总和
|
||
var goodValues = dicMonitorList.Where(x => x.Title == "优秀率" || x.Title == "良好率").ToList();
|
||
testSituations.ExcellentRate = goodValues.Sum(x => x.Value);
|
||
testSituations.ExcellentCount = goodValues.Sum(x => x.MaleCount) + goodValues.Sum(x => x.FemaleCount);
|
||
|
||
// 填充 TestSituationsData
|
||
testSituations.TestSituationsData = dicMonitorList;
|
||
|
||
return testSituations;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取视力统计数据
|
||
/// </summary>
|
||
/// <param name="paramDto">查询参数</param>
|
||
/// <returns>左右眼统计数据</returns>
|
||
public async Task<List<SportsProportionData>> GetLargeScreenDicVisionSituation(LargeScreenDataStatParam paramDto)
|
||
{
|
||
var sportsProportionDataList = new List<SportsProportionData>();
|
||
|
||
// 获取指定时间范围内的视力记录
|
||
var visionData = await _sportsTestCategoryRepository.DbContext.Set<N_VisionData>()
|
||
.Where(v => v.SchoolCode == UserContext.Current.TenantId)
|
||
.ToListAsync();
|
||
|
||
// 定义维度范围
|
||
var visionCategories = new List<(string Title, float Min, float Max)>
|
||
{
|
||
("正常", float.MinValue, 50), // 正常 (<50°)
|
||
("轻度", 50, 300), // 轻度 (50-300°)
|
||
("中度", 300, 600), // 中度 (300-600°)
|
||
("高度", 600, float.MaxValue) // 高度 (>600°)
|
||
};
|
||
|
||
// 左右眼统计
|
||
var leftEyeStats = new List<StudentSportsProportionData>();
|
||
var rightEyeStats = new List<StudentSportsProportionData>();
|
||
|
||
foreach (var category in visionCategories)
|
||
{
|
||
// 左眼统计
|
||
var leftCount = visionData
|
||
.Count(v => v.VisionLeft >= category.Min && v.VisionLeft < category.Max);
|
||
leftEyeStats.Add(new StudentSportsProportionData
|
||
{
|
||
Title = category.Title,
|
||
Value = leftCount
|
||
});
|
||
|
||
// 右眼统计
|
||
var rightCount = visionData
|
||
.Count(v => v.VisionReight >= category.Min && v.VisionReight < category.Max);
|
||
rightEyeStats.Add(new StudentSportsProportionData
|
||
{
|
||
Title = category.Title,
|
||
Value = rightCount
|
||
});
|
||
}
|
||
|
||
// 组装结果
|
||
sportsProportionDataList.Add(new SportsProportionData
|
||
{
|
||
Name = "右眼",
|
||
Datas = rightEyeStats
|
||
});
|
||
sportsProportionDataList.Add(new SportsProportionData
|
||
{
|
||
Name = "左眼",
|
||
Datas = leftEyeStats
|
||
});
|
||
|
||
return sportsProportionDataList;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 大屏肥胖情况
|
||
/// </summary>
|
||
/// <param name="paramDto"></param>
|
||
/// <returns></returns>
|
||
public async Task<List<SportsProportionData>> GetLargeScreenObesitySituation(LargeScreenDataStatParam paramDto)
|
||
{
|
||
var sportsProportionDataList = new List<SportsProportionData>();
|
||
|
||
var tenantId = UserContext.Current.TenantId;
|
||
|
||
// 从缓存中获取数据
|
||
var sportsTestResults = await _cacheQueryService.GeSportsTestDataCacheAsync(x => x.CategoryEnum != null && x.Rank != null && x.ScoreTime >= paramDto.StartTime && x.ScoreTime <= paramDto.EndTime);
|
||
|
||
var obesityTitles = new List<string>() { "偏瘦", "正常", "超重", "肥胖" };
|
||
|
||
var m_Obesity = new List<StudentSportsProportionData>();
|
||
var f_Obesity = new List<StudentSportsProportionData>();
|
||
|
||
foreach (var title in obesityTitles)
|
||
{
|
||
var maleCount = sportsTestResults.Where(x => x.Sex == SexType.Male && x.CategoryEnum.Equals("BMI") && x.Rank.Equals(title)).Count();
|
||
var femaleCount = sportsTestResults.Where(x => x.Sex == SexType.Female && x.CategoryEnum.Equals("BMI") && x.Rank.Equals(title)).Count();
|
||
|
||
if (m_Obesity.Any(c => c.Title == title) || f_Obesity.Any(c => c.Title == title))
|
||
{
|
||
m_Obesity.First().Value += maleCount;
|
||
f_Obesity.First().Value += femaleCount;
|
||
}
|
||
else
|
||
{
|
||
m_Obesity.Add(new StudentSportsProportionData()
|
||
{
|
||
Title = title,
|
||
Value = maleCount,
|
||
});
|
||
f_Obesity.Add(new StudentSportsProportionData()
|
||
{
|
||
Title = title,
|
||
Value = femaleCount,
|
||
});
|
||
}
|
||
}
|
||
|
||
sportsProportionDataList.Add(new SportsProportionData() { Name = "男", Datas = m_Obesity });
|
||
sportsProportionDataList.Add(new SportsProportionData() { Name = "女", Datas = f_Obesity });
|
||
|
||
return sportsProportionDataList;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 大屏赛事活动情况
|
||
/// </summary>
|
||
/// <param name="paramDto"></param>
|
||
/// <returns></returns>
|
||
public async Task<ActivitiesSituation> GetLargeScreenActivitiesSituation(LargeScreenDataStatParam paramDto)
|
||
{
|
||
var activitiesSituation = new ActivitiesSituation();
|
||
|
||
var tenantId = UserContext.Current.TenantId;
|
||
|
||
// 从缓存中获取数据
|
||
var sportsTestResults = await _cacheQueryService.GeSportsTestDataCacheAsync(x => x.ScoreTime >= paramDto.StartTime && x.ScoreTime <= paramDto.EndTime);
|
||
|
||
var activities = await _gradeRepository.DbContext.Set<G_Activities>().Where(x => x.SchoolCode == tenantId).ToListAsync();
|
||
|
||
activitiesSituation.ActivitiesTotalCount = activities.Count();
|
||
activitiesSituation.CompletedCount = activities.Where(x => x.ActivitiesStatus == ActivitiesStatus.Completed).Count();
|
||
activitiesSituation.AfootCount = activities.Where(x => x.ActivitiesStatus == ActivitiesStatus.Afoot).Count();
|
||
activitiesSituation.NotStartedCount = activities.Where(x => x.ActivitiesStatus == ActivitiesStatus.NotStarted).Count();
|
||
activitiesSituation.ParticipationRate = activitiesSituation.ActivitiesTotalCount > 0 ? activitiesSituation.CompletedCount / activitiesSituation.ActivitiesTotalCount * 100 : 0;
|
||
|
||
return activitiesSituation;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 大屏体质监测排行榜
|
||
/// </summary>
|
||
/// <param name="paramDto"></param>
|
||
/// <returns></returns>
|
||
public async Task<List<PhysicalMonitoring>> GetLargeScreenPhysicalMonitoringRanking(LargeScreenDataStatParam paramDto)
|
||
{
|
||
var physicalMonitoringList = new List<PhysicalMonitoring>();
|
||
|
||
var tenantId = UserContext.Current.TenantId;
|
||
|
||
// 从缓存中获取数据
|
||
var sportsTestResults = await _cacheQueryService.GeSportsTestDataCacheAsync(x => x.ScoreTime >= paramDto.StartTime && x.ScoreTime <= paramDto.EndTime);
|
||
|
||
// 年级-班级信息
|
||
var gradeClassQuery = from c in _classRepository.DbContext.Set<S_Class>()
|
||
join g in _classRepository.DbContext.Set<S_Grade>() on c.GradeId equals g.Id
|
||
join a in _classRepository.DbContext.Set<S_SchoolAssocGrade>() on g.Id equals a.GradeId
|
||
where a.SchoolCode == tenantId && c.SchoolCode.Equals(tenantId)
|
||
select new
|
||
{
|
||
GradeAndClassName = $"{g.GradeName}-{c.ClassName}",
|
||
};
|
||
|
||
var gradeClassModels = await gradeClassQuery.ToListAsync();
|
||
|
||
var monitorList = sportsTestResults
|
||
.GroupBy(x => new { x.StudentNo })
|
||
.Select(g => new
|
||
{
|
||
g.Key.StudentNo,
|
||
g.First().Sex,
|
||
g.First().ClassId,
|
||
g.First().GradeId,
|
||
g.First().ClassName,
|
||
g.First().GradeName,
|
||
Score = (g.Sum(x => x.Score) + g.Sum(x => x.AdditionalScore)) / (g.Select(x => x.CategoryEnum).Distinct().Count())
|
||
})
|
||
.Select(x => new
|
||
{
|
||
x.StudentNo,
|
||
x.Sex,
|
||
x.ClassId,
|
||
x.GradeId,
|
||
x.ClassName,
|
||
x.GradeName,
|
||
x.Score,
|
||
Rank = x.Score.GetRank()
|
||
}).ToList();
|
||
|
||
physicalMonitoringList = monitorList
|
||
.GroupBy(x => new { x.ClassId, x.GradeId, x.ClassName, x.GradeName })
|
||
.Select(g => new
|
||
{
|
||
GradeAndClassName = $"{g.Key.GradeName}-{g.Key.ClassName}",
|
||
MaleValue = (float)g.Count(x => x.Sex == SexType.Male && x.Score >= 80) / g.Count() * 100,
|
||
FemaleValue = (float)g.Count(x => x.Sex == SexType.Female && x.Score >= 80) / g.Count() * 100,
|
||
OverallValue = (float)g.Where(x => x.Rank == "优秀" || x.Rank == "良好").Count(x => x.Score >= 80) / g.Count() * 100,
|
||
})
|
||
.OrderByDescending(g => g.OverallValue)
|
||
.Select((g, index) => new PhysicalMonitoring
|
||
{
|
||
GradeAndClassName = g.GradeAndClassName,
|
||
ExcellentRate = Math.Round(g.OverallValue),
|
||
Ranking = index + 1
|
||
})
|
||
.ToList();
|
||
|
||
var ranking = physicalMonitoringList.Count + 1;
|
||
|
||
foreach (var gradeClass in gradeClassModels)
|
||
{
|
||
var physicalMonitoring = physicalMonitoringList.FirstOrDefault(c => c.GradeAndClassName == gradeClass.GradeAndClassName);
|
||
if (physicalMonitoring == null)
|
||
{
|
||
physicalMonitoringList.Add(new PhysicalMonitoring()
|
||
{
|
||
GradeAndClassName = gradeClass.GradeAndClassName,
|
||
ExcellentRate = 0,
|
||
Ranking = ranking++
|
||
});
|
||
}
|
||
}
|
||
|
||
return physicalMonitoringList;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 大屏 年级体测项目成绩监控
|
||
/// </summary>
|
||
/// <param name="paramDto"></param>
|
||
/// <returns></returns>
|
||
public async Task<List<GradeSportsTestTranscript>> GetLargeScreenGradeSportsTestTranscript(LargeScreenDataStatParam paramDto)
|
||
{
|
||
var gradeSportsTestTranscriptList = new List<GradeSportsTestTranscript>();
|
||
|
||
var tenantId = UserContext.Current.TenantId;
|
||
|
||
// 从缓存中获取数据
|
||
var sportsTestResults = await _cacheQueryService.GeSportsTestDataCacheAsync(x => x.ScoreTime >= paramDto.StartTime && x.ScoreTime <= paramDto.EndTime);
|
||
|
||
// 年级-班级信息
|
||
var gradeClassQuery = from g in _classRepository.DbContext.Set<S_Grade>()
|
||
join a in _classRepository.DbContext.Set<S_SchoolAssocGrade>() on g.Id equals a.GradeId
|
||
where a.SchoolCode == tenantId
|
||
select new
|
||
{
|
||
GradeId = g.Id,
|
||
GradeAndClassName = $"{g.GradeName}",
|
||
};
|
||
|
||
var gradeCategory = await (
|
||
from g in _gradeRepository.DbContext.Set<S_GradeAssocCategory>()
|
||
join s in _gradeRepository.DbContext.Set<N_SportsTestCategory>() on g.CategoryValue equals s.CategoryValue
|
||
select new
|
||
{
|
||
GradeId = g.GradeId,
|
||
CategoryId = g.CategoryValue,
|
||
CategoryName = s.CategoryName,
|
||
}).ToListAsync();
|
||
|
||
var gradeClassModels = await gradeClassQuery.ToListAsync();
|
||
|
||
var sportsTestList = sportsTestResults.GroupBy(x => new { x.GradeId, x.GradeName }).OrderBy(g => g.Key.GradeId).ToList();
|
||
|
||
foreach (var gradeClass in gradeClassModels)
|
||
{
|
||
var sportsProportionDataList = new List<SportsProportionData>();
|
||
|
||
var sportsTest = sportsTestList.FirstOrDefault(s => s.Key.GradeId == gradeClass.GradeId);
|
||
|
||
foreach (var type in gradeCategory.Where(c => c.GradeId == gradeClass.GradeId).OrderBy(c => c.CategoryId))
|
||
{
|
||
var typeSportsTestResults = sportsTest != null ? sportsTest.Where(x => x.CategoryValue == type.CategoryId).ToList() : new List<SportsTestValueModel>();
|
||
|
||
// 计算平均值
|
||
var maleAverage = typeSportsTestResults.Where(x => x.Sex == SexType.Male).Any()
|
||
? typeSportsTestResults.Where(x => x.Sex == SexType.Male).Average(x => x.Score)
|
||
: 0;
|
||
|
||
var femaleAverage = typeSportsTestResults.Where(x => x.Sex == SexType.Female).Any()
|
||
? typeSportsTestResults.Where(x => x.Sex == SexType.Female).Average(x => x.Score)
|
||
: 0;
|
||
|
||
var sumAverage = typeSportsTestResults.Any() ? typeSportsTestResults.Average(x => x.Score) : 0;
|
||
|
||
var studentSportsProportionData = new List<StudentSportsProportionData>
|
||
{
|
||
new StudentSportsProportionData { Title = "总分数", Value = (int)sumAverage },
|
||
new StudentSportsProportionData { Title = "男生", Value = (int)maleAverage },
|
||
new StudentSportsProportionData { Title = "女生", Value = (int)femaleAverage }
|
||
};
|
||
|
||
sportsProportionDataList.Add(new SportsProportionData
|
||
{
|
||
Name = type.CategoryName,
|
||
Datas = studentSportsProportionData
|
||
});
|
||
}
|
||
|
||
gradeSportsTestTranscriptList.Add(new GradeSportsTestTranscript()
|
||
{
|
||
GradeAndClassName = gradeClass.GradeAndClassName,
|
||
Datas = sportsProportionDataList
|
||
});
|
||
}
|
||
|
||
return gradeSportsTestTranscriptList;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 大屏 班级平均运动强度监控
|
||
/// </summary>
|
||
/// <param name="paramDto"></param>
|
||
/// <returns></returns>
|
||
public async Task<List<SportsProportionData>> LargeScreenAverageClassExerciseIntensity(LargeScreenAverageClassExerciseIntensityParam paramDto)
|
||
{
|
||
if (paramDto.GradeId < 0 || paramDto.StartTime == DateTime.MinValue || paramDto.EndTime == DateTime.MinValue)
|
||
{
|
||
throw new Exception($"请求参数不可为空");
|
||
}
|
||
var sportsProportionDataList = new List<SportsProportionData>();
|
||
|
||
var tenantId = UserContext.Current.TenantId;
|
||
|
||
// 从缓存中获取数据
|
||
var sportsTestResults = await _cacheQueryService.GeSportsTestDataCacheAsync(x => x.GradeId == paramDto.GradeId && x.ScoreTime >= paramDto.StartTime && x.ScoreTime <= paramDto.EndTime);
|
||
|
||
// 班级信息
|
||
var classQuery = from c in _classRepository.DbContext.Set<S_Class>()
|
||
join g in _classRepository.DbContext.Set<S_Grade>() on c.GradeId equals g.Id
|
||
join a in _classRepository.DbContext.Set<S_SchoolAssocGrade>() on g.Id equals a.GradeId
|
||
where a.SchoolCode == tenantId && c.SchoolCode == tenantId && g.Id == paramDto.GradeId
|
||
select c;
|
||
|
||
var classModels = await classQuery.ToListAsync();
|
||
|
||
if (classModels == null || classModels.Count == 0)
|
||
throw new ArgumentNullException("未找到班级数据");
|
||
|
||
var totalStrength = sportsTestResults.Any() ? sportsTestResults.Select(x => x.Strength).Average(x => x) : 0;
|
||
|
||
var classGroups = sportsTestResults.Any() ? sportsTestResults.GroupBy(c => new { c.ClassId, c.ClassName }).ToList() : null;
|
||
|
||
foreach (var classModel in classModels)
|
||
{
|
||
var classGroup = classGroups?.FirstOrDefault(c => c.Key.ClassId == classModel.Id && c.Key.ClassName == classModel.ClassName);
|
||
if (classGroup != null)
|
||
{
|
||
// 计算该班级的平均强度
|
||
var averageStrength = classGroup.Select(x => x.Strength).Average(x => x);
|
||
|
||
var percentage = averageStrength == 0 ? 0 : (averageStrength / totalStrength) * 100;
|
||
|
||
var studentSportsProportionData = new List<StudentSportsProportionData>
|
||
{
|
||
new StudentSportsProportionData { Title = "平均强度", Value =((int)Math.Round(percentage) > 100 ? 100 : (int)Math.Round(percentage)) }
|
||
};
|
||
|
||
sportsProportionDataList.Add(new SportsProportionData
|
||
{
|
||
Name = classGroup.Key.ClassName,
|
||
Datas = studentSportsProportionData
|
||
});
|
||
}
|
||
else
|
||
{
|
||
var studentSportsProportionData = new List<StudentSportsProportionData>
|
||
{
|
||
new StudentSportsProportionData { Title = "平均强度", Value = 0 }
|
||
};
|
||
|
||
sportsProportionDataList.Add(new SportsProportionData
|
||
{
|
||
Name = classModel.ClassName,
|
||
Datas = studentSportsProportionData
|
||
});
|
||
}
|
||
}
|
||
|
||
return sportsProportionDataList;
|
||
}
|
||
#endregion
|
||
|
||
public async Task<PageDataDto<StudentsTestDataModel>> GetSportsTestCategoryPageList(StudentsTestDataListParam paramDto)
|
||
{
|
||
var res = new PageDataDto<StudentsTestDataModel>();
|
||
|
||
var query = from r in _healthStandardsRepository.DbContext.Set<N_SportsTestValue>()
|
||
join c in _healthStandardsRepository.DbContext.Set<N_SportsTestCategory>() on r.CategoryEnum equals c.CategoryEnum
|
||
|
||
where r.SchoolCode.Equals(UserContext.Current.TenantId)
|
||
|
||
select new StudentsTestDataModel()
|
||
{
|
||
Id = r.Id,
|
||
GradeId = r.Id,
|
||
GradeName = r.GradeName,
|
||
StudentNo = r.StudentNo,
|
||
CategoryName = c.CategoryName,
|
||
ClassId = r.ClassId,
|
||
ClassName = r.ClassName,
|
||
ClassRank = r.ClassRank,
|
||
Consumption = r.Consumption,
|
||
MotionDuration = r.MotionDuration,
|
||
Strength = r.Strength,
|
||
TeacherId = r.TeacherId,
|
||
Remarks = r.Remarks,
|
||
Value = r.Value,
|
||
Rank = r.Rank,
|
||
CategoryId = c.Id,
|
||
Score = r.Score,
|
||
Sex = r.Sex == SexType.Male ? "男" : "女"
|
||
};
|
||
|
||
if (!string.IsNullOrWhiteSpace(paramDto.StudentNo))
|
||
{
|
||
query = query.Where(x => x.StudentNo.Equals(paramDto.StudentNo));
|
||
}
|
||
|
||
if (paramDto.TeacherId > 0)
|
||
{
|
||
query = query.Where(x => x.TeacherId == paramDto.TeacherId);
|
||
}
|
||
|
||
if (paramDto.GradeId > 0)
|
||
{
|
||
query = query.Where(x => x.GradeId == paramDto.GradeId);
|
||
}
|
||
|
||
if (paramDto.ClassId > 0)
|
||
{
|
||
query = query.Where(x => x.ClassId == paramDto.ClassId);
|
||
}
|
||
|
||
if (paramDto.CategoryId > 0)
|
||
{
|
||
query = query.Where(x => x.CategoryId == paramDto.CategoryId);
|
||
}
|
||
|
||
if (paramDto.Sex > 0)
|
||
{
|
||
query = query.Where(x => x.Sex.Equals(paramDto.Sex == SexType.Male ? "男" : "女"));
|
||
}
|
||
|
||
res.Total = await query.CountAsync();
|
||
|
||
var list = await query
|
||
.Skip((paramDto.PageIndex - 1) * paramDto.PageSize)
|
||
.Take(paramDto.PageSize)
|
||
.ToListAsync();
|
||
res.Datas = list;
|
||
|
||
return res;
|
||
}
|
||
|
||
public async Task<List<StudentsTestDataModel>> GetStudentsTestDataList(StudentsTestDataListParam paramDto)
|
||
{
|
||
var query = from r in _healthStandardsRepository.DbContext.Set<N_SportsTestValue>()
|
||
join c in _healthStandardsRepository.DbContext.Set<N_SportsTestCategory>() on r.CategoryEnum equals c.CategoryEnum
|
||
|
||
where r.SchoolCode.Equals(UserContext.Current.TenantId)
|
||
|
||
select new StudentsTestDataModel()
|
||
{
|
||
Id = r.Id,
|
||
GradeId = r.Id,
|
||
GradeName = r.GradeName,
|
||
StudentNo = r.StudentNo,
|
||
CategoryName = c.CategoryName,
|
||
ClassId = r.ClassId,
|
||
ClassName = r.ClassName,
|
||
ClassRank = r.ClassRank,
|
||
Consumption = r.Consumption,
|
||
MotionDuration = r.MotionDuration,
|
||
Strength = r.Strength,
|
||
TeacherId = r.TeacherId,
|
||
Remarks = r.Remarks,
|
||
Value = r.Value,
|
||
Rank = r.Rank,
|
||
CategoryId = c.Id,
|
||
Score = r.Score,
|
||
Sex = r.Sex == SexType.Male ? "男" : "女"
|
||
};
|
||
|
||
if (!string.IsNullOrWhiteSpace(paramDto.StudentNo))
|
||
{
|
||
query = query.Where(x => x.StudentNo.Equals(paramDto.StudentNo));
|
||
}
|
||
|
||
if (paramDto.TeacherId > 0)
|
||
{
|
||
query = query.Where(x => x.TeacherId == paramDto.TeacherId);
|
||
}
|
||
|
||
if (paramDto.GradeId > 0)
|
||
{
|
||
query = query.Where(x => x.GradeId == paramDto.GradeId);
|
||
}
|
||
|
||
if (paramDto.ClassId > 0)
|
||
{
|
||
query = query.Where(x => x.ClassId == paramDto.ClassId);
|
||
}
|
||
|
||
if (paramDto.CategoryId > 0)
|
||
{
|
||
query = query.Where(x => x.CategoryId == paramDto.CategoryId);
|
||
}
|
||
|
||
if (paramDto.Sex > 0)
|
||
{
|
||
query = query.Where(x => x.Sex.Equals(paramDto.Sex == SexType.Male ? "男" : "女"));
|
||
}
|
||
|
||
|
||
var list = await query.ToListAsync();
|
||
|
||
return list;
|
||
}
|
||
|
||
public async Task AddStudentsTestData(List<AddStudentsTestDataParam> paramDto)
|
||
{
|
||
var studentNos = paramDto.Select(x => x.StudentNo).Distinct().ToList();
|
||
|
||
var students = await (from s in _studentRepository.DbContext.Set<S_Student>()
|
||
join c in _studentRepository.DbContext.Set<S_Class>() on s.ClassId equals c.Id
|
||
join g in _studentRepository.DbContext.Set<S_Grade>() on c.GradeId equals g.Id
|
||
|
||
where g.SchoolCode.Equals(UserContext.Current.TenantId)
|
||
select new
|
||
{
|
||
Id = s.Id,
|
||
Age = s.Age,
|
||
ClassId = s.ClassId,
|
||
ClassName = c.ClassName,
|
||
GradeId = g.Id,
|
||
GradeName = g.GradeName,
|
||
Sex = s.Sex,
|
||
StudentNo = s.StudentNo,
|
||
}).ToListAsync();
|
||
|
||
var distinctCategoryTypes = paramDto.Select(c => c.CategoryEnum).Distinct().ToList();
|
||
|
||
var healthStandards = await _healthStandardsRepository.FindAsync(x => distinctCategoryTypes.Contains(x.CategoryEnum));
|
||
|
||
var entityList = new List<N_SportsTestValue>();
|
||
|
||
var timeNow = DateTime.Now;
|
||
|
||
foreach (var data in paramDto)
|
||
{
|
||
var entity = _mapper.Map<N_SportsTestValue>(data);
|
||
|
||
var student = students.FirstOrDefault(x => x.StudentNo.Equals(data.StudentNo));
|
||
if (student == null)
|
||
throw new Exception($"未找到此编号为{data.StudentNo}的学生");
|
||
|
||
var standard = healthStandards.Where(x =>
|
||
x.CategoryEnum.Equals(data.CategoryEnum) &&
|
||
x.GradeId == student.GradeId &&
|
||
x.Sex == student.Sex &&
|
||
data.Value >= x.MinValue &&
|
||
data.Value < x.MaxValue
|
||
).FirstOrDefault();
|
||
|
||
if (standard != null)
|
||
{
|
||
entity.Score = standard.Score;
|
||
entity.Rank = standard.Rank;
|
||
}
|
||
entity.GradeId = student.GradeId;
|
||
entity.ClassId = student.ClassId;
|
||
entity.GradeName = student.GradeName;
|
||
entity.ClassName = student.ClassName;
|
||
entity.Sex = student.Sex;
|
||
entity.Creator = UserContext.Current.UserId;
|
||
entity.CreateDate = timeNow;
|
||
|
||
entityList.Add(entity);
|
||
}
|
||
|
||
await _sportsTestResultRepository.AddRangeAsync(entityList);
|
||
|
||
await _sportsTestResultRepository.SaveChangesAsync();
|
||
|
||
var ranks = await _sportsTestResultRepository.FindAsIQueryable(x => distinctCategoryTypes.Contains(x.CategoryEnum))
|
||
.Select(x => x.Score)
|
||
.Distinct()
|
||
.OrderByDescending(value => value)
|
||
.ToListAsync();
|
||
|
||
foreach (var entity in entityList)
|
||
{
|
||
if (entity.Score > 0)
|
||
{
|
||
entity.ClassRank = ranks.IndexOf(entity.Score) + 1;
|
||
}
|
||
}
|
||
|
||
_sportsTestResultRepository.UpdateRange(entityList);
|
||
await _sportsTestResultRepository.SaveChangesAsync();
|
||
}
|
||
public async Task ModifyStudentsTestData(List<AddStudentsTestDataParam> paramDto)
|
||
{
|
||
var studentNos = paramDto.Select(x => x.StudentNo).Distinct().ToList();
|
||
|
||
var entityList = await _sportsTestResultRepository.FindAsync(x => studentNos.Contains(x.StudentNo));
|
||
|
||
var distinctCategoryTypes = paramDto.Select(c => c.CategoryEnum).Distinct().ToList();
|
||
|
||
var healthStandards = await _healthStandardsRepository.FindAsync(x => distinctCategoryTypes.Contains(x.CategoryEnum));
|
||
|
||
|
||
var timeNow = DateTime.Now;
|
||
|
||
foreach (var data in paramDto)
|
||
{
|
||
var entity = entityList.FirstOrDefault(x => x.StudentNo.Equals(data.StudentNo));
|
||
|
||
if (entity == null)
|
||
throw new Exception($"未找到要更新的数据");
|
||
|
||
entity = _mapper.Map<N_SportsTestValue>(data);
|
||
|
||
var standard = healthStandards.Where(x =>
|
||
x.CategoryEnum.Equals(data.CategoryEnum) &&
|
||
x.GradeId == entity.GradeId &&
|
||
x.Sex == entity.Sex &&
|
||
data.Value >= x.MinValue &&
|
||
data.Value < x.MaxValue
|
||
).FirstOrDefault();
|
||
|
||
if (standard != null)
|
||
{
|
||
entity.Score = standard.Score;
|
||
entity.Rank = standard.Rank;
|
||
}
|
||
entity.Modifier = UserContext.Current.UserId;
|
||
entity.ModifyDate = timeNow;
|
||
|
||
entityList.Add(entity);
|
||
}
|
||
|
||
_sportsTestResultRepository.UpdateRange(entityList);
|
||
|
||
await _sportsTestResultRepository.SaveChangesAsync();
|
||
|
||
var ranks = await _sportsTestResultRepository.FindAsIQueryable(x => distinctCategoryTypes.Contains(x.CategoryEnum))
|
||
.Select(x => x.Score)
|
||
.Distinct()
|
||
.OrderByDescending(value => value)
|
||
.ToListAsync();
|
||
|
||
foreach (var entity in entityList)
|
||
{
|
||
if (entity.Score > 0)
|
||
{
|
||
entity.ClassRank = ranks.IndexOf(entity.Score) + 1;
|
||
}
|
||
}
|
||
|
||
_sportsTestResultRepository.UpdateRange(entityList);
|
||
await _sportsTestResultRepository.SaveChangesAsync();
|
||
}
|
||
public async Task DeleteStudentsTestData(List<int> Ids)
|
||
{
|
||
var model = await _sportsTestResultRepository.FindAsync(x => Ids.Contains(x.Id));
|
||
|
||
if (model == null)
|
||
throw new ArgumentNullException($"未找到删除的数据");
|
||
|
||
|
||
_sportsTestResultRepository.DbContext.RemoveRange(model);
|
||
await _sportsTestResultRepository.SaveChangesAsync();
|
||
}
|
||
}
|
||
} |