2025-06-06 16:00:39 +08:00
|
|
|
|
using AutoMapper;
|
|
|
|
|
using Castle.Core.Internal;
|
|
|
|
|
using Microsoft.AspNetCore.Http;
|
|
|
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
|
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
|
using Newtonsoft.Json;
|
2025-06-06 16:55:14 +08:00
|
|
|
|
using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
|
2025-06-06 16:00:39 +08:00
|
|
|
|
using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
|
|
|
|
|
using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
|
|
|
|
|
using Quartz.Util;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Dynamic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Linq.Expressions;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Tea.Utils;
|
|
|
|
|
using VOL.Business.IRepositories;
|
|
|
|
|
using VOL.Business.IServices.Norm;
|
|
|
|
|
using VOL.Business.IServices.School;
|
|
|
|
|
using VOL.Business.IServices.Training;
|
|
|
|
|
using VOL.Business.Services.Norm;
|
|
|
|
|
using VOL.Business.Services.School;
|
|
|
|
|
using VOL.Core.CacheManager;
|
|
|
|
|
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;
|
2025-06-06 16:55:14 +08:00
|
|
|
|
using VOL.Entity.DomainModels.XinWei;
|
2025-06-06 16:00:39 +08:00
|
|
|
|
using VOL.Entity.Enum;
|
|
|
|
|
using VOL.Model;
|
|
|
|
|
using VOL.Model.Ai;
|
|
|
|
|
using VOL.Model.IOT.Request;
|
|
|
|
|
using VOL.Model.IOT.Response;
|
|
|
|
|
using VOL.Model.Norm.Request;
|
|
|
|
|
using VOL.Model.Norm.Response;
|
|
|
|
|
using VOL.Model.School.Request;
|
|
|
|
|
using VOL.Model.School.Response;
|
|
|
|
|
using VOL.Model.Training.Response;
|
|
|
|
|
using VOL.System.IRepositories;
|
|
|
|
|
using VOL.System.Repositories;
|
2025-06-06 16:55:14 +08:00
|
|
|
|
using YD_XinWei.Api.SmartSportsEntitys;
|
|
|
|
|
using static Dapper.SqlMapper;
|
2025-06-06 16:00:39 +08:00
|
|
|
|
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
|
|
|
|
|
using static Microsoft.ML.Transforms.Text.LatentDirichletAllocationTransformer.ModelParameters;
|
|
|
|
|
|
|
|
|
|
namespace VOL.Business.Services.Training
|
|
|
|
|
{
|
|
|
|
|
public class I_TrainingDataService : II_TrainingDataService, IDependency
|
|
|
|
|
{
|
|
|
|
|
#region 初始化
|
|
|
|
|
private readonly IMapper _mapper;
|
|
|
|
|
private readonly ICacheService _cacheService;
|
|
|
|
|
private readonly ICacheQueryService _cacheQueryService;
|
|
|
|
|
private readonly S_TeacherRepository _teacherRepository;
|
|
|
|
|
private readonly IN_SportsTestCategoryRepository _sportsTestCategoryRepository;
|
|
|
|
|
|
|
|
|
|
[ActivatorUtilitiesConstructor]
|
|
|
|
|
public I_TrainingDataService(IMapper mapper,
|
|
|
|
|
ICacheService cacheService,
|
|
|
|
|
ICacheQueryService cacheQueryService,
|
|
|
|
|
S_TeacherRepository teacherRepository,
|
|
|
|
|
IN_SportsTestCategoryRepository sportsTestCategoryRepository)
|
|
|
|
|
{
|
|
|
|
|
_mapper = mapper;
|
|
|
|
|
_cacheService = cacheService;
|
|
|
|
|
_teacherRepository = teacherRepository;
|
|
|
|
|
_sportsTestCategoryRepository = sportsTestCategoryRepository;
|
|
|
|
|
_cacheQueryService = cacheQueryService;
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region 项目类型
|
2025-06-06 16:55:14 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取体测项目来源
|
|
|
|
|
/// </summary>
|
|
|
|
|
public DataSource GetSportsTestItemTypeDataSource(int itemType)
|
|
|
|
|
{
|
|
|
|
|
var sportsTestItemType = (SportsTestItemType)itemType;
|
|
|
|
|
if (
|
|
|
|
|
sportsTestItemType == SportsTestItemType.BMI ||
|
|
|
|
|
sportsTestItemType == SportsTestItemType.VitalCapacity ||
|
|
|
|
|
sportsTestItemType == SportsTestItemType.One_Minute_Sit_Up ||
|
|
|
|
|
sportsTestItemType == SportsTestItemType.OneMinuteJumpRope ||
|
|
|
|
|
sportsTestItemType == SportsTestItemType.Sit_And_Reach ||
|
|
|
|
|
sportsTestItemType == SportsTestItemType.Pull_Up ||
|
|
|
|
|
sportsTestItemType == SportsTestItemType.StandingLongJump ||
|
|
|
|
|
sportsTestItemType == SportsTestItemType.MeterRun_50 ||
|
|
|
|
|
sportsTestItemType == SportsTestItemType.ShuttleRun_50x8 ||
|
|
|
|
|
sportsTestItemType == SportsTestItemType.MeterRun_1000 ||
|
|
|
|
|
sportsTestItemType == SportsTestItemType.MeterRun_800
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
return DataSource.IOT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2025-06-06 16:00:39 +08:00
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取训练项目来源
|
|
|
|
|
/// </summary>
|
|
|
|
|
public DataSource GetTrainingItemTypeDataSource(int itemType)
|
|
|
|
|
{
|
|
|
|
|
var trainingItemType = (TrainingItemType)itemType;
|
|
|
|
|
if (
|
|
|
|
|
trainingItemType == TrainingItemType.Coordinate ||
|
|
|
|
|
trainingItemType == TrainingItemType.Agility ||
|
|
|
|
|
trainingItemType == TrainingItemType.Strength ||
|
|
|
|
|
trainingItemType == TrainingItemType.Balance ||
|
|
|
|
|
trainingItemType == TrainingItemType.Speed ||
|
|
|
|
|
trainingItemType == TrainingItemType.HeartRate
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
return DataSource.IOT;
|
|
|
|
|
}
|
|
|
|
|
if (
|
|
|
|
|
trainingItemType == TrainingItemType.HighKnee ||
|
|
|
|
|
trainingItemType == TrainingItemType.JumpingJack ||
|
|
|
|
|
trainingItemType == TrainingItemType.JumpSquat ||
|
|
|
|
|
trainingItemType == TrainingItemType.KneeDrivePalmarPalpation ||
|
|
|
|
|
trainingItemType == TrainingItemType.CrossQuadrantJump
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
return DataSource.AI;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2025-06-06 16:00:39 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取年级对应测试项目
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="gradeId"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
public async Task<List<CategoryColumnNameModel>> GetCategoryColumnNameList(int gradeId)
|
|
|
|
|
{
|
|
|
|
|
var categoryList = await (from s in _teacherRepository.DbContext.Set<S_GradeAssocCategory>()
|
|
|
|
|
join n in _teacherRepository.DbContext.Set<N_SportsTestCategory>()
|
|
|
|
|
on s.CategoryValue equals n.CategoryValue
|
|
|
|
|
where s.GradeId == gradeId
|
|
|
|
|
select new CategoryColumnNameModel()
|
|
|
|
|
{
|
|
|
|
|
ColumnName = n.CategoryEnum,
|
|
|
|
|
ColumnCnName = n.CategoryName
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
return categoryList;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取训练项目类型
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<DataTypeAndCategory> ItemTypeList()
|
|
|
|
|
{
|
|
|
|
|
var trainingList = await (from t in _sportsTestCategoryRepository.DbContext.Set<N_TrainingAssocCategory>()
|
|
|
|
|
join a in _sportsTestCategoryRepository.DbContext.Set<N_SportsTrainingCategory>() on t.CategoryValue equals a.CategoryValue
|
|
|
|
|
select new
|
|
|
|
|
{
|
|
|
|
|
Id = a.CategoryValue,
|
|
|
|
|
t.ModeId,
|
|
|
|
|
t.DataSource,
|
|
|
|
|
ItemTypeName = a.CategoryName
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
List<ModeAndCategory> trainingResult = Enum.GetValues(typeof(Ai_ModeEnum))
|
|
|
|
|
.Cast<Ai_ModeEnum>()
|
|
|
|
|
.Select(modeEnum => new ModeAndCategory
|
|
|
|
|
{
|
|
|
|
|
ModeId = modeEnum,
|
|
|
|
|
ModeName = modeEnum.GetDescription(),
|
|
|
|
|
ItemTypeList = trainingList
|
|
|
|
|
.Where(x => x.ModeId == (int)modeEnum)
|
|
|
|
|
.Select(x => new IOT_ItemTypeModel
|
|
|
|
|
{
|
|
|
|
|
Id = x.Id,
|
|
|
|
|
ItemTypeName = x.ItemTypeName
|
|
|
|
|
}).DistinctBy(x => x.Id)
|
|
|
|
|
.ToList()
|
|
|
|
|
})
|
|
|
|
|
.Where(model => model.ItemTypeList.Any())
|
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return new DataTypeAndCategory() { DataType = SportsTestDataType.TrainingData, ModeAndCategoryList = trainingResult };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取体测项目类型
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
public async Task<DataTypeAndCategory> CategoryList()
|
|
|
|
|
{
|
|
|
|
|
var trainingList = await (from t in _sportsTestCategoryRepository.DbContext.Set<N_TestAssocCategory>()
|
|
|
|
|
join a in _sportsTestCategoryRepository.DbContext.Set<N_SportsTestCategory>() on t.CategoryValue equals a.CategoryValue
|
|
|
|
|
select new
|
|
|
|
|
{
|
|
|
|
|
Id = a.CategoryValue,
|
|
|
|
|
t.ModeId,
|
|
|
|
|
t.DataSource,
|
|
|
|
|
ItemTypeName = a.CategoryName
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
List<ModeAndCategory> trainingResult = Enum.GetValues(typeof(Ai_ModeEnum))
|
|
|
|
|
.Cast<Ai_ModeEnum>()
|
|
|
|
|
.Select(modeEnum => new ModeAndCategory
|
|
|
|
|
{
|
|
|
|
|
ModeId = modeEnum,
|
|
|
|
|
ModeName = modeEnum.GetDescription(),
|
|
|
|
|
ItemTypeList = trainingList
|
2025-06-06 16:55:14 +08:00
|
|
|
|
.Where(x => x.ModeId == (int)Ai_ModeEnum.ClassRoomMode)
|
2025-06-06 16:00:39 +08:00
|
|
|
|
.Select(x => new IOT_ItemTypeModel
|
|
|
|
|
{
|
|
|
|
|
Id = x.Id,
|
|
|
|
|
ItemTypeName = x.ItemTypeName
|
|
|
|
|
}).DistinctBy(x => x.Id)
|
|
|
|
|
.ToList()
|
|
|
|
|
})
|
|
|
|
|
.Where(model => model.ItemTypeList.Any())
|
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return new DataTypeAndCategory() { DataType = SportsTestDataType.TrainingData, ModeAndCategoryList = trainingResult };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region 训练数据
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 训练数据课堂模式列表
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="paramDto"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
public async Task<PageDataDto<ClassRoomModeDataModel>> GetTrainingClassRoomModeDataList(ClassRoomModeDataParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var res = new PageDataDto<ClassRoomModeDataModel>();
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
if (paramDto.DataSource == 0)
|
|
|
|
|
{
|
|
|
|
|
paramDto.DataSource = GetTrainingItemTypeDataSource(paramDto.ItemType);
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-06 16:00:39 +08:00
|
|
|
|
if (paramDto.DataSource == DataSource.IOT)
|
|
|
|
|
{
|
|
|
|
|
res = await QueryIotTrainingDataList(paramDto);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
res = await QueryAiTrainingDataList(paramDto);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 训练数据课堂模式导出
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="paramDto"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
public async Task<List<ClassRoomModeDataModel>> GetTrainingClassRoomModeDataExport(ClassRoomModeExportParam paramDto)
|
|
|
|
|
{
|
2025-06-06 16:55:14 +08:00
|
|
|
|
if (paramDto.DataSource == 0)
|
|
|
|
|
{
|
|
|
|
|
paramDto.DataSource = GetTrainingItemTypeDataSource(paramDto.ItemType);
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-06 16:00:39 +08:00
|
|
|
|
if (paramDto.DataSource == DataSource.IOT)
|
|
|
|
|
{
|
|
|
|
|
return await QueryIotTrainingDataExport(paramDto);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return await QueryAiTrainingDataExport(paramDto);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取IOT训练数据
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="paramDto"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<PageDataDto<ClassRoomModeDataModel>> QueryIotTrainingDataList(ClassRoomModeDataParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var res = new PageDataDto<ClassRoomModeDataModel>();
|
|
|
|
|
|
|
|
|
|
var query = from td in _teacherRepository.DbContext.Set<I_TrainingData>()
|
|
|
|
|
join t in _teacherRepository.DbContext.Set<S_Teacher>() on td.TeacherId equals t.Id into teacherDatas
|
|
|
|
|
from teacher in teacherDatas.DefaultIfEmpty()
|
|
|
|
|
where td.IsDisplay &&
|
2025-06-06 16:55:14 +08:00
|
|
|
|
//td.ModelName == (int)Ai_ModeEnum.ClassRoomMode &&
|
2025-06-06 16:00:39 +08:00
|
|
|
|
td.SchoolCode.Equals(UserContext.Current.TenantId) &&
|
|
|
|
|
td.ItemType == (int)paramDto.ItemType
|
|
|
|
|
select new ClassRoomModeDataModel()
|
|
|
|
|
{
|
|
|
|
|
Id = td.Id,
|
|
|
|
|
ClassId = td.ClassId,
|
|
|
|
|
TeacherName = teacher.TeacherName,
|
|
|
|
|
ItemType = td.ItemType,
|
|
|
|
|
StartTime = td.InsertTime,
|
|
|
|
|
GradeAndClassName = td.ClassName,
|
2025-06-06 16:55:14 +08:00
|
|
|
|
ModelName = td.ModelName,
|
2025-06-06 16:00:39 +08:00
|
|
|
|
Avg = td.ClassNumAvg,
|
|
|
|
|
Max = td.ClassMaxNum,
|
|
|
|
|
Min = td.ClassMinNum,
|
|
|
|
|
CenterNumber = td.ClassMedian,
|
|
|
|
|
FinishNumber = td.TotalNumber,
|
2025-06-06 16:55:14 +08:00
|
|
|
|
NotFinishedNumber = (td.ClassNum - td.TotalNumber) < 0 ? 0 : (td.ClassNum - td.TotalNumber)
|
2025-06-06 16:00:39 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (paramDto.StartTime.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.StartTime >= paramDto.StartTime);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.EndTime.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.StartTime <= paramDto.StartTime);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.ClassId.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.ClassId.Equals(paramDto.ClassId));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!paramDto.TeacherName.IsNullOrEmpty())
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.TeacherName.Contains(paramDto.TeacherName ?? ""));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res.Total = await query.CountAsync();
|
|
|
|
|
|
|
|
|
|
var list = await query
|
|
|
|
|
.OrderByDescending(c => c.Id)
|
|
|
|
|
.Skip((paramDto.PageIndex - 1) * paramDto.PageSize)
|
|
|
|
|
.Take(paramDto.PageSize)
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
|
|
|
|
|
res.Datas = list;
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取IOT训练数据导出
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="paramDto"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<List<ClassRoomModeDataModel>> QueryIotTrainingDataExport(ClassRoomModeExportParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var query = from td in _teacherRepository.DbContext.Set<I_TrainingData>()
|
|
|
|
|
join t in _teacherRepository.DbContext.Set<S_Teacher>() on td.TeacherId equals t.Id into teacherDatas
|
|
|
|
|
from teacher in teacherDatas.DefaultIfEmpty()
|
2025-06-06 16:55:14 +08:00
|
|
|
|
where td.IsDisplay &&
|
2025-06-06 16:00:39 +08:00
|
|
|
|
td.ModeType == (int)Ai_ModeEnum.ClassRoomMode &&
|
|
|
|
|
td.SchoolCode.Equals(UserContext.Current.TenantId) &&
|
|
|
|
|
td.ItemType == (int)paramDto.ItemType
|
|
|
|
|
select new ClassRoomModeDataModel()
|
|
|
|
|
{
|
|
|
|
|
Id = td.Id,
|
|
|
|
|
ClassId = td.ClassId,
|
|
|
|
|
TeacherName = teacher.TeacherName,
|
|
|
|
|
ItemType = td.ItemType,
|
|
|
|
|
StartTime = td.InsertTime,
|
|
|
|
|
GradeAndClassName = td.ClassName,
|
2025-06-06 16:55:14 +08:00
|
|
|
|
ModelName = td.ModelName,
|
2025-06-06 16:00:39 +08:00
|
|
|
|
Avg = td.ClassNumAvg,
|
|
|
|
|
Max = td.ClassMaxNum,
|
|
|
|
|
Min = td.ClassMinNum,
|
|
|
|
|
CenterNumber = td.ClassMedian,
|
|
|
|
|
FinishNumber = td.TotalNumber,
|
2025-06-06 16:55:14 +08:00
|
|
|
|
NotFinishedNumber = (td.ClassNum - td.TotalNumber) < 0 ? 0 : (td.ClassNum - td.TotalNumber)
|
2025-06-06 16:00:39 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (paramDto.StartTime.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.StartTime >= paramDto.StartTime);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.EndTime.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.StartTime <= paramDto.StartTime);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.ClassId.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.ClassId.Equals(paramDto.ClassId));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!paramDto.TeacherName.IsNullOrEmpty())
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.TeacherName.Contains(paramDto.TeacherName ?? ""));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var list = await query.OrderByDescending(c => c.Id).ToListAsync();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 课堂模式数据详情
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="paramDto"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
public async Task<PageDataDto<ClassRoomModeDataDetails>> GetClassRoomModeDataDetails(ClassRoomModeDataDetailsParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var res = new PageDataDto<ClassRoomModeDataDetails>();
|
|
|
|
|
var tenantId = UserContext.Current.TenantId;
|
|
|
|
|
|
|
|
|
|
IQueryable<ClassRoomModeDataDetails> query;
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
if (paramDto.DataSource == 0)
|
|
|
|
|
{
|
|
|
|
|
paramDto.DataSource = GetTrainingItemTypeDataSource(paramDto.ItemType);
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-06 16:00:39 +08:00
|
|
|
|
if (paramDto.DataSource == DataSource.IOT)
|
|
|
|
|
{
|
|
|
|
|
query = from student in _teacherRepository.DbContext.Set<I_TrainRanking>()
|
|
|
|
|
join trainingData in _teacherRepository.DbContext.Set<I_TrainingData>()
|
|
|
|
|
on student.TrainingDataId equals trainingData.Id
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
where trainingData.IsDisplay && trainingData.SchoolCode == tenantId && trainingData.Id == paramDto.Id && trainingData.ItemType == paramDto.ItemType
|
2025-06-06 16:00:39 +08:00
|
|
|
|
select new ClassRoomModeDataDetails
|
|
|
|
|
{
|
|
|
|
|
ClassId = student.ClassId,
|
|
|
|
|
GradeAndClassName = $"{trainingData.GradeName}{trainingData.ClassName}",
|
|
|
|
|
StartTime = trainingData.EndTime,
|
|
|
|
|
ItemType = trainingData.ItemType,
|
|
|
|
|
Id = student.Id,
|
|
|
|
|
Sex = student.Gender,
|
|
|
|
|
ResultLevel = student.ResultLevel,
|
|
|
|
|
StudentName = student.StudentName,
|
|
|
|
|
StudentNo = student.StudentNo,
|
|
|
|
|
JumpValue = student.JumpValue,
|
|
|
|
|
SpeedTime = student.SpeedTime,
|
|
|
|
|
ErrorNumber = student.ErrorNumber,
|
|
|
|
|
Kcal = student.Kcal
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
query = from trainingData in _teacherRepository.DbContext.Set<Ai_SportsTestData>()
|
2025-06-06 16:55:14 +08:00
|
|
|
|
where trainingData.IsDisplay && trainingData.SchoolCode == tenantId && trainingData.ClassRoomRecordId == paramDto.Id && trainingData.CategoryValue == paramDto.ItemType
|
2025-06-06 16:00:39 +08:00
|
|
|
|
select new ClassRoomModeDataDetails
|
|
|
|
|
{
|
|
|
|
|
Id = trainingData.Id,
|
|
|
|
|
ClassId = trainingData.ClassId,
|
|
|
|
|
GradeAndClassName = $"{trainingData.GradeName}{trainingData.ClassName}",
|
|
|
|
|
StartTime = trainingData.StartTime,
|
|
|
|
|
ItemType = trainingData.CategoryValue,
|
|
|
|
|
Sex = (int)trainingData.Sex,
|
|
|
|
|
ResultLevel = (int)trainingData.RankEnum,
|
|
|
|
|
StudentName = trainingData.StudentName,
|
|
|
|
|
StudentNo = trainingData.StudentNo,
|
|
|
|
|
JumpValue = (int)trainingData.Value,
|
|
|
|
|
ErrorNumber = trainingData.ErrorNumber
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!paramDto.StudentName.IsNullOrEmpty())
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.StudentName.Contains(paramDto.StudentName));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!paramDto.StudentNo.IsNullOrEmpty())
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.StudentNo.Contains(paramDto.StudentNo));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.Sex.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.Sex == paramDto.Sex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.ResultLevel.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.ResultLevel == paramDto.ResultLevel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取总数
|
|
|
|
|
res.Total = await query.CountAsync();
|
|
|
|
|
|
|
|
|
|
// 分页和排序
|
|
|
|
|
var list = await query
|
|
|
|
|
.OrderBy(c => c.Id)
|
|
|
|
|
.Skip((paramDto.PageIndex - 1) * paramDto.PageSize)
|
|
|
|
|
.Take(paramDto.PageSize)
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
|
|
|
|
|
res.Datas = list;
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 课堂模式数据详情导出
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="paramDto"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
public async Task<List<ClassRoomModeDataDetails>> ClassRoomModeDataDetailsExport(ClassRoomModeDataExportParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var res = new PageDataDto<ClassRoomModeDataDetails>();
|
|
|
|
|
var tenantId = UserContext.Current.TenantId;
|
|
|
|
|
|
|
|
|
|
IQueryable<ClassRoomModeDataDetails> query;
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
if (paramDto.DataSource == 0)
|
|
|
|
|
{
|
|
|
|
|
paramDto.DataSource = GetTrainingItemTypeDataSource(paramDto.ItemType);
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-06 16:00:39 +08:00
|
|
|
|
if (paramDto.DataSource == DataSource.IOT)
|
|
|
|
|
{
|
|
|
|
|
query = from trainingData in _teacherRepository.DbContext.Set<I_TrainingData>()
|
|
|
|
|
join student in _teacherRepository.DbContext.Set<I_TrainRanking>()
|
|
|
|
|
on trainingData.Id equals student.TrainingDataId
|
2025-06-06 16:55:14 +08:00
|
|
|
|
where trainingData.IsDisplay && trainingData.SchoolCode == tenantId && trainingData.Id == paramDto.Id && trainingData.ItemType == paramDto.ItemType
|
2025-06-06 16:00:39 +08:00
|
|
|
|
select new ClassRoomModeDataDetails
|
|
|
|
|
{
|
|
|
|
|
ClassId = trainingData.ClassId,
|
|
|
|
|
GradeAndClassName = $"{trainingData.GradeName}{trainingData.ClassName}",
|
|
|
|
|
StartTime = trainingData.InsertTime,
|
|
|
|
|
ItemType = trainingData.ItemType,
|
|
|
|
|
Id = student.Id,
|
|
|
|
|
Sex = student.Gender,
|
|
|
|
|
ResultLevel = student.ResultLevel,
|
|
|
|
|
StudentName = student.StudentName,
|
|
|
|
|
StudentNo = student.StudentNo,
|
|
|
|
|
JumpValue = student.JumpValue,
|
|
|
|
|
SpeedTime = student.SpeedTime,
|
|
|
|
|
ErrorNumber = student.ErrorNumber,
|
|
|
|
|
Kcal = student.Kcal
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
query = from trainingData in _teacherRepository.DbContext.Set<Ai_SportsTestData>()
|
2025-06-06 16:55:14 +08:00
|
|
|
|
where trainingData.IsDisplay && trainingData.SchoolCode == tenantId && trainingData.ClassRoomRecordId == paramDto.Id && trainingData.CategoryValue == paramDto.ItemType
|
2025-06-06 16:00:39 +08:00
|
|
|
|
select new ClassRoomModeDataDetails
|
|
|
|
|
{
|
|
|
|
|
Id = trainingData.Id,
|
|
|
|
|
ClassId = trainingData.ClassId,
|
|
|
|
|
GradeAndClassName = $"{trainingData.GradeName}{trainingData.ClassName}",
|
|
|
|
|
StartTime = trainingData.StartTime,
|
|
|
|
|
ItemType = trainingData.CategoryValue,
|
|
|
|
|
Sex = (int)trainingData.Sex,
|
|
|
|
|
ResultLevel = (int)trainingData.RankEnum,
|
|
|
|
|
StudentName = trainingData.StudentName,
|
|
|
|
|
StudentNo = trainingData.StudentNo,
|
|
|
|
|
JumpValue = (int)trainingData.Value,
|
|
|
|
|
ErrorNumber = trainingData.ErrorNumber
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
if (!paramDto.StudentName.IsNullOrEmpty())
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.StudentName.Contains(paramDto.StudentName));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!paramDto.StudentNo.IsNullOrEmpty())
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.StudentNo.Contains(paramDto.StudentNo));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.Sex.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.Sex == paramDto.Sex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.ResultLevel.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.ResultLevel == paramDto.ResultLevel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return await query.ToListAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region 自由模式
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 自由模式
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="paramDto"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
public async Task<PageDataDto<FreeModeDataModel>> FreeModeDataList(FreeModeDataParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var res = new PageDataDto<FreeModeDataModel>();
|
2025-06-06 16:55:14 +08:00
|
|
|
|
|
|
|
|
|
var tenantId = UserContext.Current.TenantId;
|
|
|
|
|
|
|
|
|
|
var projectId = await _teacherRepository.DbContext.Set<XW_TestingProject>()
|
|
|
|
|
.Where(x => x.CategoryValue == paramDto.ItemCode)
|
|
|
|
|
.Select(x => x.ProjectId)
|
|
|
|
|
.FirstOrDefaultAsync();
|
|
|
|
|
|
|
|
|
|
var orgId = await _teacherRepository.DbContext.Set<S_School>()
|
|
|
|
|
.Where(x => x.SchoolCode == tenantId)
|
|
|
|
|
.Select(x => x.Id)
|
|
|
|
|
.FirstOrDefaultAsync();
|
|
|
|
|
|
|
|
|
|
// First query
|
|
|
|
|
var queryBW = from a in _teacherRepository.DbContext.Set<Ai_SportsTestData>()
|
|
|
|
|
where a.IsDisplay && a.SchoolCode.Equals(tenantId) &&
|
|
|
|
|
a.ModeType == Ai_ModeEnum.FreeMode &&
|
|
|
|
|
a.CategoryValue == paramDto.ItemCode
|
|
|
|
|
select new FreeModeDataModel()
|
|
|
|
|
{
|
|
|
|
|
Id = a.Id,
|
|
|
|
|
StartTime = a.StartTime,
|
|
|
|
|
StudentNo = a.StudentNo,
|
|
|
|
|
StudentName = a.StudentName,
|
|
|
|
|
Weight = a.Weight,
|
|
|
|
|
Height = a.Height,
|
|
|
|
|
Sex = (int)a.Sex,
|
|
|
|
|
ClassId = a.ClassId,
|
|
|
|
|
Result = a.Value,
|
|
|
|
|
GradeAndClassName = $"{a.GradeName}{a.ClassName}",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Second query
|
|
|
|
|
var queryXW = from s in _teacherRepository.DbContext.Set<XW_SportsTestData>()
|
|
|
|
|
join t in _teacherRepository.DbContext.Set<XW_TrainStudents>()
|
|
|
|
|
on s.Id equals t.XW_SportsTestDataId
|
|
|
|
|
where s.OrgId == orgId && s.ProjectId == projectId
|
|
|
|
|
select new FreeModeDataModel()
|
|
|
|
|
{
|
|
|
|
|
Id = s.Id,
|
|
|
|
|
StartTime = Convert.ToDateTime(s.CreateTime),
|
|
|
|
|
StudentNo = t.StudentNo,
|
|
|
|
|
StudentName = t.StudentName,
|
|
|
|
|
Weight = s.ProjectId == 21 ? t.OriginalAchievement / 100 : 0,
|
|
|
|
|
Height = s.ProjectId == 21 ? t.Achievement / 10 : 0,
|
|
|
|
|
Sex = (int)t.Sex,
|
|
|
|
|
ClassId = t.ClassId,
|
|
|
|
|
Result = s.ProjectId == 21 ? (double)t.Achievement2 : (double)t.Achievement,
|
|
|
|
|
GradeAndClassName = $"{t.GradeName}{t.ClassName}",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 异步执行查询,获取结果
|
|
|
|
|
var dataBW = await queryBW.ToListAsync();
|
|
|
|
|
var dataXW = await queryXW.ToListAsync();
|
|
|
|
|
|
|
|
|
|
// 合并数据
|
|
|
|
|
var combinedData = dataBW.Concat(dataXW);
|
|
|
|
|
|
|
|
|
|
// 过滤条件
|
2025-06-06 16:00:39 +08:00
|
|
|
|
if (paramDto.StartTime.HasValue)
|
|
|
|
|
{
|
2025-06-06 16:55:14 +08:00
|
|
|
|
combinedData = combinedData.Where(x => x.StartTime >= paramDto.StartTime);
|
2025-06-06 16:00:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.EndTime.HasValue)
|
|
|
|
|
{
|
2025-06-06 16:55:14 +08:00
|
|
|
|
combinedData = combinedData.Where(x => x.StartTime <= paramDto.EndTime);
|
2025-06-06 16:00:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.ClassId.HasValue)
|
|
|
|
|
{
|
2025-06-06 16:55:14 +08:00
|
|
|
|
combinedData = combinedData.Where(x => x.ClassId.Equals(paramDto.ClassId));
|
2025-06-06 16:00:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!paramDto.StudentName.IsNullOrEmpty())
|
|
|
|
|
{
|
2025-06-06 16:55:14 +08:00
|
|
|
|
combinedData = combinedData.Where(x => x.StudentName.Contains(paramDto.StudentName ?? ""));
|
2025-06-06 16:00:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!paramDto.StudentNo.IsNullOrEmpty())
|
|
|
|
|
{
|
2025-06-06 16:55:14 +08:00
|
|
|
|
combinedData = combinedData.Where(x => x.StudentNo.Contains(paramDto.StudentNo ?? ""));
|
2025-06-06 16:00:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.Sex.HasValue)
|
|
|
|
|
{
|
2025-06-06 16:55:14 +08:00
|
|
|
|
combinedData = combinedData.Where(x => x.Sex == paramDto.Sex);
|
2025-06-06 16:00:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
// 计算总记录数
|
|
|
|
|
res.Total = combinedData.Count();
|
|
|
|
|
|
|
|
|
|
// 分页处理
|
|
|
|
|
var list = combinedData
|
|
|
|
|
.OrderByDescending(c => c.Id)
|
|
|
|
|
.Skip((paramDto.PageIndex - 1) * paramDto.PageSize)
|
|
|
|
|
.Take(paramDto.PageSize)
|
|
|
|
|
.ToList();
|
2025-06-06 16:00:39 +08:00
|
|
|
|
|
|
|
|
|
res.Datas = list;
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
|
2025-06-06 16:00:39 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 自由模式导出
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="paramDto"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
public async Task<List<FreeModeDataModel>> FreeModeDataExport(FreeModeDataExportParam paramDto)
|
|
|
|
|
{
|
2025-06-06 16:55:14 +08:00
|
|
|
|
var tenantId = UserContext.Current.TenantId;
|
|
|
|
|
|
|
|
|
|
var projectId = await _teacherRepository.DbContext.Set<XW_TestingProject>()
|
|
|
|
|
.Where(x => x.CategoryValue == paramDto.ItemCode)
|
|
|
|
|
.Select(x => x.ProjectId)
|
|
|
|
|
.FirstAsync();
|
|
|
|
|
|
|
|
|
|
var orgId = await _teacherRepository.DbContext.Set<S_School>()
|
|
|
|
|
.Where(x => x.SchoolCode == tenantId)
|
|
|
|
|
.Select(x => x.Id)
|
|
|
|
|
.FirstAsync();
|
|
|
|
|
|
|
|
|
|
// First query
|
|
|
|
|
var queryBW = from a in _teacherRepository.DbContext.Set<Ai_SportsTestData>()
|
|
|
|
|
where a.IsDisplay && a.SchoolCode.Equals(tenantId) &&
|
|
|
|
|
a.ModeType == Ai_ModeEnum.FreeMode &&
|
|
|
|
|
a.CategoryValue == paramDto.ItemCode
|
|
|
|
|
select new FreeModeDataModel()
|
|
|
|
|
{
|
|
|
|
|
Id = a.Id,
|
|
|
|
|
StartTime = a.StartTime,
|
|
|
|
|
StudentNo = a.StudentNo,
|
|
|
|
|
StudentName = a.StudentName,
|
|
|
|
|
Weight = a.Weight,
|
|
|
|
|
Height = a.Height,
|
|
|
|
|
Sex = (int)a.Sex,
|
|
|
|
|
ClassId = a.ClassId,
|
|
|
|
|
Result = a.Value,
|
|
|
|
|
GradeAndClassName = $"{a.GradeName}{a.ClassName}",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Second query
|
|
|
|
|
var queryXW = from s in _teacherRepository.DbContext.Set<XW_SportsTestData>()
|
|
|
|
|
join t in _teacherRepository.DbContext.Set<XW_TrainStudents>()
|
|
|
|
|
on s.Id equals t.XW_SportsTestDataId
|
|
|
|
|
where s.OrgId == orgId && s.ProjectId == projectId
|
|
|
|
|
select new FreeModeDataModel()
|
|
|
|
|
{
|
|
|
|
|
Id = s.Id,
|
|
|
|
|
StartTime = Convert.ToDateTime(s.CreateTime),
|
|
|
|
|
StudentNo = t.StudentNo,
|
|
|
|
|
StudentName = t.StudentName,
|
|
|
|
|
Weight = s.ProjectId == 21 ? t.OriginalAchievement / 100 : 0,
|
|
|
|
|
Height = s.ProjectId == 21 ? t.Achievement / 10 : 0,
|
|
|
|
|
Sex = (int)t.Sex,
|
|
|
|
|
ClassId = t.ClassId,
|
|
|
|
|
Result = s.ProjectId == 21 ? (double)t.Achievement2 : (double)t.Achievement,
|
|
|
|
|
GradeAndClassName = $"{t.GradeName}{t.ClassName}",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 异步执行查询,获取结果
|
|
|
|
|
var dataBW = await queryBW.ToListAsync();
|
|
|
|
|
var dataXW = await queryXW.ToListAsync();
|
|
|
|
|
|
|
|
|
|
// 合并数据
|
|
|
|
|
var combinedData = dataBW.Concat(dataXW);
|
|
|
|
|
|
|
|
|
|
// 过滤条件
|
2025-06-06 16:00:39 +08:00
|
|
|
|
if (paramDto.StartTime.HasValue)
|
|
|
|
|
{
|
2025-06-06 16:55:14 +08:00
|
|
|
|
combinedData = combinedData.Where(x => x.StartTime >= paramDto.StartTime);
|
2025-06-06 16:00:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.EndTime.HasValue)
|
|
|
|
|
{
|
2025-06-06 16:55:14 +08:00
|
|
|
|
combinedData = combinedData.Where(x => x.StartTime <= paramDto.EndTime);
|
2025-06-06 16:00:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.ClassId.HasValue)
|
|
|
|
|
{
|
2025-06-06 16:55:14 +08:00
|
|
|
|
combinedData = combinedData.Where(x => x.ClassId.Equals(paramDto.ClassId));
|
2025-06-06 16:00:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!paramDto.StudentName.IsNullOrEmpty())
|
|
|
|
|
{
|
2025-06-06 16:55:14 +08:00
|
|
|
|
combinedData = combinedData.Where(x => x.StudentName.Contains(paramDto.StudentName ?? ""));
|
2025-06-06 16:00:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!paramDto.StudentNo.IsNullOrEmpty())
|
|
|
|
|
{
|
2025-06-06 16:55:14 +08:00
|
|
|
|
combinedData = combinedData.Where(x => x.StudentNo.Contains(paramDto.StudentNo ?? ""));
|
2025-06-06 16:00:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.Sex.HasValue)
|
|
|
|
|
{
|
2025-06-06 16:55:14 +08:00
|
|
|
|
combinedData = combinedData.Where(x => x.Sex == paramDto.Sex);
|
2025-06-06 16:00:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
return combinedData.OrderByDescending(c => c.Id).ToList();
|
2025-06-06 16:00:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region AI数据
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取AI训练和体测数据
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="paramDto"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<PageDataDto<ClassRoomModeDataModel>> QueryAiTrainingDataList(ClassRoomModeDataParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var res = new PageDataDto<ClassRoomModeDataModel>();
|
|
|
|
|
|
|
|
|
|
var query = from room in _teacherRepository.DbContext.Set<Ai_ClassRoomRecord>()
|
|
|
|
|
join a in _teacherRepository.DbContext.Set<Ai_SportsTestData>()
|
|
|
|
|
on room.Id equals a.ClassRoomRecordId into sportsTestDatas
|
|
|
|
|
from a in sportsTestDatas.DefaultIfEmpty() // Left join
|
|
|
|
|
where a.IsDisplay && room.SchoolCode.Equals(UserContext.Current.TenantId) &&
|
|
|
|
|
a.ModeType == Ai_ModeEnum.ClassRoomMode &&
|
|
|
|
|
a.DataType == SportsTestDataType.TrainingData &&
|
|
|
|
|
a.CategoryValue == paramDto.ItemType
|
|
|
|
|
select new
|
|
|
|
|
{
|
|
|
|
|
room.SchoolCode,
|
|
|
|
|
room.Code,
|
|
|
|
|
room.Id,
|
|
|
|
|
a.UniqueId,
|
|
|
|
|
a.GradeId,
|
|
|
|
|
a.ClassId,
|
|
|
|
|
a.GradeName,
|
|
|
|
|
a.ClassName,
|
|
|
|
|
a.StudentCount,
|
|
|
|
|
a.TeacherId,
|
|
|
|
|
room.TeacherName,
|
|
|
|
|
room.StartTime,
|
|
|
|
|
room.Name,
|
|
|
|
|
a.ModeType,
|
|
|
|
|
a.ModelName,
|
|
|
|
|
a.DataType,
|
|
|
|
|
a.CategoryValue,
|
|
|
|
|
a.StudentNo,
|
|
|
|
|
a.StudentName,
|
|
|
|
|
a.Value,
|
|
|
|
|
a.MaxValue,
|
|
|
|
|
a.MinValue,
|
|
|
|
|
a.RankEnum
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (paramDto.StartTime.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.StartTime >= paramDto.StartTime);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.EndTime.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.StartTime <= paramDto.EndTime);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.ClassId.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.ClassId.Equals(paramDto.ClassId));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!paramDto.TeacherName.IsNullOrEmpty())
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.TeacherName.Contains(paramDto.TeacherName ?? ""));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 按照 ClassRoomRecordId 分组
|
|
|
|
|
var list = await query
|
|
|
|
|
.GroupBy(t => new
|
|
|
|
|
{
|
|
|
|
|
t.Id,
|
|
|
|
|
t.CategoryValue,
|
|
|
|
|
t.GradeId,
|
|
|
|
|
t.GradeName,
|
|
|
|
|
t.ClassId,
|
|
|
|
|
t.ClassName,
|
|
|
|
|
t.TeacherId,
|
|
|
|
|
t.TeacherName
|
|
|
|
|
})
|
|
|
|
|
.Select(g => new
|
|
|
|
|
{
|
|
|
|
|
g.Key.Id,
|
|
|
|
|
g.Key.CategoryValue,
|
|
|
|
|
g.Key.GradeId,
|
|
|
|
|
g.Key.GradeName,
|
|
|
|
|
g.Key.ClassId,
|
|
|
|
|
g.Key.ClassName,
|
|
|
|
|
g.Key.TeacherId,
|
|
|
|
|
g.Key.TeacherName,
|
|
|
|
|
Data = g.ToList()
|
|
|
|
|
})
|
|
|
|
|
.OrderByDescending(x => x.Id)
|
|
|
|
|
.Skip((paramDto.PageIndex - 1) * paramDto.PageSize)
|
|
|
|
|
.Take(paramDto.PageSize)
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
|
|
|
|
|
// 计算总记录数
|
|
|
|
|
var totalCount = list.Count();
|
|
|
|
|
|
|
|
|
|
var studentCountList = await (from c in _teacherRepository.DbContext.Set<S_Class>()
|
|
|
|
|
join g in _teacherRepository.DbContext.Set<S_Grade>() on c.GradeId equals g.Id
|
|
|
|
|
join a in _teacherRepository.DbContext.Set<S_SchoolAssocGrade>() on g.Id equals a.GradeId
|
|
|
|
|
where c.SchoolCode == UserContext.Current.TenantId
|
|
|
|
|
select new
|
|
|
|
|
{
|
|
|
|
|
c.Id,
|
|
|
|
|
c.ClassName,
|
|
|
|
|
c.GradeId,
|
|
|
|
|
g.GradeName,
|
|
|
|
|
StudentCount = _teacherRepository.DbContext.Set<S_Student>()
|
|
|
|
|
.Where(s => s.ClassId == c.Id && s.SchoolCode == UserContext.Current.TenantId)
|
|
|
|
|
.Count()
|
|
|
|
|
}).Distinct().ToListAsync();
|
|
|
|
|
|
|
|
|
|
var result = list.Select(g => new ClassRoomModeDataModel()
|
|
|
|
|
{
|
|
|
|
|
Id = g.Id,
|
|
|
|
|
ItemType = g.Data.FirstOrDefault()?.CategoryValue ?? 0,
|
|
|
|
|
ClassId = g.ClassId,
|
|
|
|
|
GradeAndClassName = $"{g.GradeName}{g.ClassName}",
|
|
|
|
|
TeacherName = g.TeacherName,
|
|
|
|
|
ModelName = ((TrainingItemType)g.CategoryValue).GetDescription(),
|
|
|
|
|
FinishNumber = g.Data.Count,
|
|
|
|
|
NotFinishedNumber = studentCountList.FirstOrDefault(c => c.Id == g.ClassId).StudentCount - g.Data.Count(),
|
|
|
|
|
Avg = g.Data.Average(d => d.Value),
|
|
|
|
|
CenterNumber = g.Data.Select(d => (float)d.Value).ToList().Median(),
|
|
|
|
|
Max = g.Data.Max(d => d.Value),
|
|
|
|
|
Min = g.Data.Min(d => d.Value),
|
|
|
|
|
StartTime = g.Data.Max(d => d.StartTime)
|
|
|
|
|
}).ToList();
|
|
|
|
|
|
|
|
|
|
res.Total = totalCount;
|
|
|
|
|
|
|
|
|
|
res.Datas = result;
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取AI训练和体测数据导出
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="paramDto"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<List<ClassRoomModeDataModel>> QueryAiTrainingDataExport(ClassRoomModeExportParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
// 获取所有符合条件的主表数据
|
|
|
|
|
var query = from a in _teacherRepository.DbContext.Set<Ai_SportsTestData>()
|
|
|
|
|
join t in _teacherRepository.DbContext.Set<S_Teacher>() on a.TeacherId equals t.Id into teacherDatas
|
|
|
|
|
from teacher in teacherDatas.DefaultIfEmpty()
|
|
|
|
|
where a.IsDisplay && a.SchoolCode.Equals(UserContext.Current.TenantId) &&
|
|
|
|
|
a.ModeType == Ai_ModeEnum.ClassRoomMode &&
|
|
|
|
|
a.DataType == SportsTestDataType.TrainingData &&
|
|
|
|
|
a.CategoryValue == paramDto.ItemType
|
|
|
|
|
select new
|
|
|
|
|
{
|
|
|
|
|
a.SchoolCode,
|
|
|
|
|
a.Code,
|
|
|
|
|
a.ClassRoomRecordId,
|
|
|
|
|
a.UniqueId,
|
|
|
|
|
a.GradeId,
|
|
|
|
|
a.ClassId,
|
|
|
|
|
a.GradeName,
|
|
|
|
|
a.ClassName,
|
|
|
|
|
a.StudentCount,
|
|
|
|
|
a.TeacherId,
|
|
|
|
|
teacher.TeacherName,
|
|
|
|
|
a.ModeType,
|
|
|
|
|
a.ModelName,
|
|
|
|
|
a.DataType,
|
|
|
|
|
a.CategoryValue,
|
|
|
|
|
a.StartTime,
|
|
|
|
|
a.StudentNo,
|
|
|
|
|
a.StudentName,
|
|
|
|
|
a.Value,
|
|
|
|
|
a.MaxValue,
|
|
|
|
|
a.MinValue,
|
|
|
|
|
a.RankEnum
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (paramDto.StartTime.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.StartTime >= paramDto.StartTime);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.EndTime.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.StartTime <= paramDto.StartTime);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.ClassId.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.ClassId.Equals(paramDto.ClassId));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!paramDto.TeacherName.IsNullOrEmpty())
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.TeacherName.Contains(paramDto.TeacherName ?? ""));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 按照指定字段分组
|
|
|
|
|
var list = await query
|
|
|
|
|
.GroupBy(t => new
|
|
|
|
|
{
|
|
|
|
|
t.CategoryValue,
|
|
|
|
|
t.GradeId,
|
|
|
|
|
t.GradeName,
|
|
|
|
|
t.ClassId,
|
|
|
|
|
t.ClassName,
|
|
|
|
|
t.TeacherId,
|
|
|
|
|
t.TeacherName
|
|
|
|
|
})
|
|
|
|
|
.Select(g => new
|
|
|
|
|
{
|
|
|
|
|
g.Key.CategoryValue,
|
|
|
|
|
g.Key.GradeId,
|
|
|
|
|
g.Key.GradeName,
|
|
|
|
|
g.Key.ClassId,
|
|
|
|
|
g.Key.ClassName,
|
|
|
|
|
g.Key.TeacherId,
|
|
|
|
|
g.Key.TeacherName,
|
|
|
|
|
Data = g.GroupBy(x => x.StudentNo)
|
|
|
|
|
.Select(studentGroup => studentGroup.OrderByDescending(x => x.StartTime).FirstOrDefault())
|
|
|
|
|
.ToList()
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
// 计算总记录数
|
|
|
|
|
var totalCount = await query
|
|
|
|
|
.GroupBy(t => new
|
|
|
|
|
{
|
|
|
|
|
t.CategoryValue,
|
|
|
|
|
t.GradeId,
|
|
|
|
|
t.GradeName,
|
|
|
|
|
t.ClassId,
|
|
|
|
|
t.ClassName,
|
|
|
|
|
t.TeacherId,
|
|
|
|
|
t.TeacherName
|
|
|
|
|
})
|
|
|
|
|
.CountAsync();
|
|
|
|
|
|
|
|
|
|
var studentCountList = await (from c in _teacherRepository.DbContext.Set<S_Class>()
|
|
|
|
|
join g in _teacherRepository.DbContext.Set<S_Grade>() on c.GradeId equals g.Id
|
|
|
|
|
join a in _teacherRepository.DbContext.Set<S_SchoolAssocGrade>() on g.Id equals a.GradeId
|
|
|
|
|
where c.SchoolCode == UserContext.Current.TenantId
|
|
|
|
|
select new
|
|
|
|
|
{
|
|
|
|
|
c.Id,
|
|
|
|
|
c.ClassName,
|
|
|
|
|
c.GradeId,
|
|
|
|
|
g.GradeName,
|
|
|
|
|
StudentCount = _teacherRepository.DbContext.Set<S_Student>()
|
|
|
|
|
.Where(s => s.ClassId == c.Id && s.SchoolCode == UserContext.Current.TenantId)
|
|
|
|
|
.Count()
|
|
|
|
|
}).Distinct().ToListAsync();
|
|
|
|
|
var result = list.Select(g => new ClassRoomModeDataModel()
|
|
|
|
|
{
|
|
|
|
|
ItemType = g.CategoryValue,
|
|
|
|
|
ClassId = g.ClassId,
|
|
|
|
|
GradeAndClassName = $"{g.GradeName}{g.ClassName}",
|
|
|
|
|
TeacherName = g.TeacherName,
|
|
|
|
|
ModelName = ((TrainingItemType)g.CategoryValue).GetDescription(),
|
|
|
|
|
FinishNumber = g.Data.Count,
|
|
|
|
|
NotFinishedNumber = studentCountList.FirstOrDefault(c => c.Id == g.ClassId).StudentCount - g.Data.Count(),
|
|
|
|
|
Avg = g.Data.Average(d => d.Value),
|
|
|
|
|
CenterNumber = g.Data.Select(d => (float)d.Value).ToList().Median(),
|
|
|
|
|
Max = g.Data.Max(d => d.Value),
|
|
|
|
|
Min = g.Data.Min(d => d.Value),
|
|
|
|
|
StartTime = g.Data.Max(d => d.StartTime)
|
|
|
|
|
}).ToList();
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region 体测数据
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 体测数据课堂模式列表
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="paramDto"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<PageDataDto<ClassRoomModeDataModel>> GetTestClassRoomModeDataList(ClassRoomModeDataParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var res = new PageDataDto<ClassRoomModeDataModel>();
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
if (paramDto.DataSource == 0)
|
|
|
|
|
{
|
|
|
|
|
paramDto.DataSource = GetSportsTestItemTypeDataSource(paramDto.ItemType);
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-06 16:00:39 +08:00
|
|
|
|
if (paramDto.DataSource == DataSource.IOT)
|
|
|
|
|
{
|
|
|
|
|
res = await QueryIotTestDataList(paramDto);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
res = await QueryAiTrainingDataList(paramDto);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取IOT体测数据
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="paramDto"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<PageDataDto<ClassRoomModeDataModel>> QueryIotTestDataList(ClassRoomModeDataParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var res = new PageDataDto<ClassRoomModeDataModel>();
|
|
|
|
|
|
|
|
|
|
// 查询基础数据
|
|
|
|
|
var query = _teacherRepository.DbContext.Set<N_SportsTestValue>()
|
|
|
|
|
.Where(s => s.IsDisplay && s.SchoolCode == UserContext.Current.TenantId &&
|
2025-06-06 16:55:14 +08:00
|
|
|
|
s.CategoryValue == paramDto.ItemType && s.DataSource != DataSource.XW);
|
2025-06-06 16:00:39 +08:00
|
|
|
|
|
|
|
|
|
// 添加条件过滤
|
|
|
|
|
if (paramDto.StartTime.HasValue)
|
|
|
|
|
query = query.Where(x => x.CreateDate >= paramDto.StartTime);
|
|
|
|
|
|
|
|
|
|
if (paramDto.EndTime.HasValue)
|
|
|
|
|
query = query.Where(x => x.CreateDate <= paramDto.EndTime);
|
|
|
|
|
|
|
|
|
|
if (paramDto.ClassId.HasValue)
|
|
|
|
|
query = query.Where(x => x.ClassId == paramDto.ClassId);
|
|
|
|
|
|
|
|
|
|
if (!paramDto.TeacherName.IsNullOrEmpty())
|
|
|
|
|
query = query.Where(x => x.TeacherName.Contains(paramDto.TeacherName ?? ""));
|
|
|
|
|
|
|
|
|
|
// 获取学生人数数据(按班级分组计算总人数)
|
|
|
|
|
var classValues = await query.Select(x => new
|
|
|
|
|
{
|
|
|
|
|
x.ClassId,
|
|
|
|
|
x.CreateDate,
|
|
|
|
|
x.Value
|
|
|
|
|
}).Distinct().ToListAsync();
|
|
|
|
|
var classIds = classValues.Select(x => x.ClassId).ToList();
|
|
|
|
|
|
|
|
|
|
var studentList = await _teacherRepository.DbContext.Set<S_Student>()
|
|
|
|
|
.Where(x => classIds.Contains(x.ClassId) && x.SchoolCode == UserContext.Current.TenantId)
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
|
|
|
|
|
var studentCountDictionary = studentList
|
|
|
|
|
.GroupBy(x => x.ClassId)
|
|
|
|
|
.ToDictionary(g => g.Key, g => g.Count());
|
|
|
|
|
|
|
|
|
|
// 获取分页数据
|
|
|
|
|
var groupedQuery = query
|
|
|
|
|
.GroupBy(x => new
|
|
|
|
|
{
|
|
|
|
|
x.ClassId,
|
|
|
|
|
Date = x.CreateDate
|
|
|
|
|
})
|
|
|
|
|
.Select(g => new
|
|
|
|
|
{
|
|
|
|
|
g.Key.ClassId,
|
|
|
|
|
g.Key.Date,
|
|
|
|
|
g.FirstOrDefault().GradeName,
|
|
|
|
|
g.FirstOrDefault().ClassName,
|
|
|
|
|
g.FirstOrDefault().TeacherName,
|
|
|
|
|
g.FirstOrDefault().CategoryValue,
|
|
|
|
|
FinishNumber = g.Count(),
|
|
|
|
|
Avg = Math.Round(g.Average(x => x.Value), 0),
|
|
|
|
|
Max = Math.Round(g.Max(d => d.Value), 0),
|
|
|
|
|
Min = Math.Round(g.Min(d => d.Value), 0)
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 计算总记录数(此时是分组后的记录数)
|
|
|
|
|
var totalCount = await groupedQuery.CountAsync();
|
|
|
|
|
|
|
|
|
|
// 获取分页数据
|
|
|
|
|
var pagedData = await groupedQuery
|
|
|
|
|
.OrderByDescending(c => c.ClassId)
|
|
|
|
|
.Skip((paramDto.PageIndex - 1) * paramDto.PageSize)
|
|
|
|
|
.Take(paramDto.PageSize)
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
|
|
|
|
|
var result = pagedData.Select(g => new ClassRoomModeDataModel()
|
|
|
|
|
{
|
|
|
|
|
ItemType = g.CategoryValue,
|
|
|
|
|
ClassId = g.ClassId,
|
|
|
|
|
StartTime = g.Date,
|
|
|
|
|
GradeAndClassName = $"{g.GradeName}{g.ClassName}",
|
|
|
|
|
TeacherName = g.TeacherName,
|
|
|
|
|
FinishNumber = g.FinishNumber,
|
|
|
|
|
NotFinishedNumber = studentCountDictionary.ContainsKey(g.ClassId) ? studentCountDictionary[g.ClassId] - g.FinishNumber : 0,
|
|
|
|
|
Avg = g.Avg,
|
|
|
|
|
CenterNumber = Math.Round(classValues.Where(x => x.ClassId == g.ClassId && x.CreateDate == g.Date).Select(x => x.Value).ToList().Median(), 0),
|
|
|
|
|
Max = g.Max,
|
2025-06-06 16:55:14 +08:00
|
|
|
|
Min = g.Min,
|
|
|
|
|
ModelName = "/"
|
2025-06-06 16:00:39 +08:00
|
|
|
|
}).ToList();
|
|
|
|
|
|
|
|
|
|
// 设置返回值
|
|
|
|
|
res.Total = totalCount;
|
|
|
|
|
res.Datas = result;
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取IOT体测数据导出
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="paramDto"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<List<ClassRoomModeDataModel>> QueryIotTestDataExport(ClassRoomModeExportParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var res = new PageDataDto<ClassRoomModeDataModel>();
|
|
|
|
|
|
|
|
|
|
// 查询基础数据
|
|
|
|
|
var query = _teacherRepository.DbContext.Set<N_SportsTestValue>()
|
|
|
|
|
.Where(s => s.IsDisplay && s.SchoolCode == UserContext.Current.TenantId &&
|
|
|
|
|
s.CategoryValue == paramDto.ItemType);
|
|
|
|
|
|
|
|
|
|
// 添加条件过滤
|
|
|
|
|
if (paramDto.StartTime.HasValue)
|
|
|
|
|
query = query.Where(x => x.CreateDate >= paramDto.StartTime);
|
|
|
|
|
|
|
|
|
|
if (paramDto.EndTime.HasValue)
|
|
|
|
|
query = query.Where(x => x.CreateDate <= paramDto.EndTime);
|
|
|
|
|
|
|
|
|
|
if (paramDto.ClassId.HasValue)
|
|
|
|
|
query = query.Where(x => x.ClassId == paramDto.ClassId);
|
|
|
|
|
|
|
|
|
|
if (!paramDto.TeacherName.IsNullOrEmpty())
|
|
|
|
|
query = query.Where(x => x.TeacherName.Contains(paramDto.TeacherName ?? ""));
|
|
|
|
|
|
|
|
|
|
// 获取学生人数数据(按班级分组计算总人数)
|
|
|
|
|
var classValues = await query.Select(x => new
|
|
|
|
|
{
|
|
|
|
|
x.ClassId,
|
|
|
|
|
x.CreateDate,
|
|
|
|
|
x.Value
|
|
|
|
|
}).Distinct().ToListAsync();
|
|
|
|
|
var classIds = classValues.Select(x => x.ClassId).ToList();
|
|
|
|
|
|
|
|
|
|
var studentList = await _teacherRepository.DbContext.Set<S_Student>()
|
|
|
|
|
.Where(x => classIds.Contains(x.ClassId) && x.SchoolCode == UserContext.Current.TenantId)
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
|
|
|
|
|
var studentCountDictionary = studentList
|
|
|
|
|
.GroupBy(x => x.ClassId)
|
|
|
|
|
.ToDictionary(g => g.Key, g => g.Count());
|
|
|
|
|
|
|
|
|
|
// 获取分页数据
|
|
|
|
|
var groupedQuery = query
|
|
|
|
|
.GroupBy(x => new
|
|
|
|
|
{
|
|
|
|
|
x.ClassId,
|
|
|
|
|
Date = x.CreateDate
|
|
|
|
|
})
|
|
|
|
|
.Select(g => new
|
|
|
|
|
{
|
|
|
|
|
g.Key.ClassId,
|
|
|
|
|
g.Key.Date,
|
|
|
|
|
g.FirstOrDefault().GradeName,
|
|
|
|
|
g.FirstOrDefault().ClassName,
|
|
|
|
|
g.FirstOrDefault().TeacherName,
|
|
|
|
|
g.FirstOrDefault().CategoryValue,
|
|
|
|
|
FinishNumber = g.Count(),
|
|
|
|
|
Avg = Math.Round(g.Average(x => x.Value), 0),
|
|
|
|
|
Max = Math.Round(g.Max(d => d.Value), 0),
|
|
|
|
|
Min = Math.Round(g.Min(d => d.Value), 0)
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 获取分页数据
|
|
|
|
|
var pagedData = await groupedQuery
|
|
|
|
|
.OrderByDescending(c => c.ClassId)
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var result = pagedData.Select(g => new ClassRoomModeDataModel()
|
|
|
|
|
{
|
|
|
|
|
ItemType = g.CategoryValue,
|
|
|
|
|
ClassId = g.ClassId,
|
|
|
|
|
StartTime = g.Date,
|
|
|
|
|
GradeAndClassName = $"{g.GradeName}{g.ClassName}",
|
|
|
|
|
TeacherName = g.TeacherName,
|
|
|
|
|
FinishNumber = g.FinishNumber,
|
|
|
|
|
NotFinishedNumber = studentCountDictionary.ContainsKey(g.ClassId) ? studentCountDictionary[g.ClassId] - g.FinishNumber : 0,
|
|
|
|
|
Avg = g.Avg,
|
|
|
|
|
CenterNumber = Math.Round(classValues.Where(x => x.ClassId == g.ClassId && x.CreateDate == g.Date).Select(x => x.Value).ToList().Median(), 0),
|
|
|
|
|
Max = g.Max,
|
2025-06-06 16:55:14 +08:00
|
|
|
|
Min = g.Min,
|
|
|
|
|
ModelName = "/"
|
2025-06-06 16:00:39 +08:00
|
|
|
|
}).ToList();
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 体测数据导出
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="paramDto"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
public async Task<List<ClassRoomModeDataModel>> SportsTestDataExport(ClassRoomModeExportParam paramDto)
|
|
|
|
|
{
|
2025-06-06 16:55:14 +08:00
|
|
|
|
if (paramDto.DataSource == 0)
|
|
|
|
|
{
|
|
|
|
|
paramDto.DataSource = GetSportsTestItemTypeDataSource(paramDto.ItemType);
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-06 16:00:39 +08:00
|
|
|
|
if (paramDto.DataSource == DataSource.IOT)
|
|
|
|
|
{
|
|
|
|
|
return await QueryIotTestDataExport(paramDto);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return await QueryAiTrainingDataExport(paramDto);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 体测数据详情
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="paramDto"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
public async Task<PageDataDto<SportsTestDetailsModel>> GetSportsTestDetails(SportsTestDetailsParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var res = new PageDataDto<SportsTestDetailsModel>();
|
|
|
|
|
var tenantId = UserContext.Current.TenantId;
|
|
|
|
|
|
|
|
|
|
IQueryable<SportsTestDetailsModel> query;
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
if (paramDto.DataSource == 0)
|
|
|
|
|
{
|
|
|
|
|
paramDto.DataSource = GetSportsTestItemTypeDataSource((int)paramDto.ItemType);
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-06 16:00:39 +08:00
|
|
|
|
if (paramDto.DataSource == DataSource.IOT)
|
|
|
|
|
{
|
|
|
|
|
query = from s in _teacherRepository.DbContext.Set<N_SportsTestValue>()
|
|
|
|
|
where s.IsDisplay &&
|
|
|
|
|
s.SchoolCode == tenantId &&
|
|
|
|
|
s.ClassId == paramDto.ClassId &&
|
|
|
|
|
s.CategoryValue == (int)paramDto.ItemType &&
|
|
|
|
|
s.CreateDate.Value.Year == paramDto.StartTime.Year &&
|
|
|
|
|
s.CreateDate.Value.Month == paramDto.StartTime.Month &&
|
|
|
|
|
s.CreateDate.Value.Day == paramDto.StartTime.Day &&
|
|
|
|
|
s.CreateDate.Value.Hour == paramDto.StartTime.Hour &&
|
|
|
|
|
s.CreateDate.Value.Minute == paramDto.StartTime.Minute &&
|
|
|
|
|
s.CreateDate.Value.Second == paramDto.StartTime.Second
|
|
|
|
|
select new SportsTestDetailsModel
|
|
|
|
|
{
|
|
|
|
|
Id = s.Id,
|
|
|
|
|
ClassId = s.ClassId,
|
|
|
|
|
Grade = s.Rank,
|
|
|
|
|
StudentNo = s.StudentNo,
|
|
|
|
|
StudentName = s.StudentName ?? "",
|
|
|
|
|
Sex = (int)s.Sex,
|
|
|
|
|
Result = (double)s.Value,
|
2025-06-06 16:55:14 +08:00
|
|
|
|
Height = s.Height,
|
|
|
|
|
Weight = s.Weight,
|
2025-06-06 16:00:39 +08:00
|
|
|
|
GradeAndClassName = $"{s.GradeName ?? ""}{s.ClassName ?? ""}",
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
query = from trainingData in _teacherRepository.DbContext.Set<Ai_SportsTestData>()
|
|
|
|
|
where trainingData.IsDisplay && trainingData.SchoolCode == tenantId && trainingData.ClassRoomRecordId == paramDto.Id
|
|
|
|
|
select new SportsTestDetailsModel
|
|
|
|
|
{
|
|
|
|
|
Id = trainingData.Id,
|
|
|
|
|
ClassId = trainingData.ClassId,
|
|
|
|
|
Grade = trainingData.Rank,
|
|
|
|
|
StudentNo = trainingData.StudentNo,
|
|
|
|
|
StudentName = trainingData.StudentName ?? "",
|
|
|
|
|
Sex = (int)trainingData.Sex,
|
|
|
|
|
Result = (double)Math.Round(trainingData.Value),
|
|
|
|
|
GradeAndClassName = $"{trainingData.GradeName ?? ""}{trainingData.ClassName ?? ""}",
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!paramDto.StudentName.IsNullOrEmpty())
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.StudentName.Contains(paramDto.StudentName));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!paramDto.StudentNo.IsNullOrEmpty())
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.StudentNo.Contains(paramDto.StudentNo));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.Sex.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.Sex == paramDto.Sex);
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
if (paramDto.ResultLevel.HasValue)
|
2025-06-06 16:00:39 +08:00
|
|
|
|
{
|
2025-06-06 16:55:14 +08:00
|
|
|
|
var grade = paramDto.ResultLevel.GetDescription();
|
|
|
|
|
|
|
|
|
|
if (paramDto.ItemType == SportsTestItemType.BMI)
|
|
|
|
|
{
|
|
|
|
|
switch (grade)
|
|
|
|
|
{
|
|
|
|
|
case "优秀":
|
|
|
|
|
grade = "正常";
|
|
|
|
|
break;
|
|
|
|
|
case "及格":
|
|
|
|
|
grade = "超重";
|
|
|
|
|
break;
|
|
|
|
|
case "良好":
|
|
|
|
|
grade = "偏瘦";
|
|
|
|
|
break;
|
|
|
|
|
case "不及格":
|
|
|
|
|
grade = "肥胖";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
query = query.Where(x => x.Grade == grade); // 修改为使用 Rank 过滤
|
2025-06-06 16:00:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取总数
|
|
|
|
|
res.Total = await query.CountAsync();
|
|
|
|
|
|
|
|
|
|
// 分页和排序
|
|
|
|
|
var list = await query
|
|
|
|
|
.OrderBy(c => c.Id)
|
|
|
|
|
.Skip((paramDto.PageIndex - 1) * paramDto.PageSize)
|
|
|
|
|
.Take(paramDto.PageSize)
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
//if (paramDto.ItemType == SportsTestItemType.BMI)
|
|
|
|
|
//{
|
|
|
|
|
// foreach (var item in list)
|
|
|
|
|
// {
|
|
|
|
|
// if (item.Height.HasValue && Math.Abs(item.Height.Value - Math.Round(item.Height.Value, 2)) > 0)
|
|
|
|
|
// {
|
|
|
|
|
// item.Height = Math.Round(item.Height.Value, 2);
|
|
|
|
|
// }
|
|
|
|
|
// if (item.Weight.HasValue && Math.Abs(item.Weight.Value - Math.Round(item.Weight.Value, 2)) > 0)
|
|
|
|
|
// {
|
|
|
|
|
// item.Weight = Math.Round(item.Weight.Value, 2);
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// switch (item.Grade)
|
|
|
|
|
// {
|
|
|
|
|
// case "正常":
|
|
|
|
|
// item.Grade = "优秀";
|
|
|
|
|
// break;
|
|
|
|
|
// case "超重":
|
|
|
|
|
// item.Grade = "及格";
|
|
|
|
|
// break;
|
|
|
|
|
// case "偏瘦":
|
|
|
|
|
// item.Grade = "良好";
|
|
|
|
|
// break;
|
|
|
|
|
// case "肥胖":
|
|
|
|
|
// item.Grade = "不及格";
|
|
|
|
|
// break;
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
//}
|
|
|
|
|
|
2025-06-06 16:00:39 +08:00
|
|
|
|
res.Datas = list;
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 体测数据详情导出
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="paramDto"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
public async Task<List<SportsTestDetailsModel>> GetSportsTestDetailsExport(SportsTestExportParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var res = new List<SportsTestDetailsModel>();
|
|
|
|
|
var tenantId = UserContext.Current.TenantId;
|
|
|
|
|
|
|
|
|
|
IQueryable<SportsTestDetailsModel> query;
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
if (paramDto.DataSource == 0)
|
|
|
|
|
{
|
|
|
|
|
paramDto.DataSource = GetSportsTestItemTypeDataSource((int)paramDto.ItemType);
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-06 16:00:39 +08:00
|
|
|
|
if (paramDto.DataSource == DataSource.IOT)
|
|
|
|
|
{
|
|
|
|
|
query = from s in _teacherRepository.DbContext.Set<N_SportsTestValue>()
|
|
|
|
|
where s.IsDisplay && s.SchoolCode == tenantId &&
|
|
|
|
|
s.ClassId == paramDto.ClassId &&
|
|
|
|
|
s.CategoryValue == (int)paramDto.ItemType &&
|
|
|
|
|
s.CreateDate.Value.Year == paramDto.StartTime.Year &&
|
|
|
|
|
s.CreateDate.Value.Month == paramDto.StartTime.Month &&
|
|
|
|
|
s.CreateDate.Value.Day == paramDto.StartTime.Day &&
|
|
|
|
|
s.CreateDate.Value.Hour == paramDto.StartTime.Hour &&
|
|
|
|
|
s.CreateDate.Value.Minute == paramDto.StartTime.Minute &&
|
|
|
|
|
s.CreateDate.Value.Second == paramDto.StartTime.Second
|
|
|
|
|
select new SportsTestDetailsModel
|
|
|
|
|
{
|
|
|
|
|
Id = s.Id,
|
|
|
|
|
ClassId = s.ClassId,
|
|
|
|
|
Grade = s.Rank,
|
|
|
|
|
StudentNo = s.StudentNo,
|
|
|
|
|
StudentName = s.StudentName ?? "",
|
|
|
|
|
Sex = (int)s.Sex,
|
|
|
|
|
Result = (double)s.Value,
|
|
|
|
|
GradeAndClassName = $"{s.GradeName ?? ""}{s.ClassName ?? ""}",
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
query = from trainingData in _teacherRepository.DbContext.Set<Ai_SportsTestData>()
|
|
|
|
|
where trainingData.IsDisplay && trainingData.SchoolCode == tenantId && trainingData.ClassRoomRecordId == paramDto.Id
|
|
|
|
|
select new SportsTestDetailsModel
|
|
|
|
|
{
|
|
|
|
|
Id = trainingData.Id,
|
|
|
|
|
ClassId = trainingData.ClassId,
|
|
|
|
|
Grade = trainingData.Rank,
|
|
|
|
|
StudentNo = trainingData.StudentNo,
|
|
|
|
|
StudentName = trainingData.StudentName ?? "",
|
|
|
|
|
Sex = (int)trainingData.Sex,
|
|
|
|
|
Result = (double)trainingData.Value,
|
|
|
|
|
GradeAndClassName = $"{trainingData.GradeName ?? ""}{trainingData.ClassName ?? ""}",
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!paramDto.StudentName.IsNullOrEmpty())
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.StudentName.Contains(paramDto.StudentName));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!paramDto.StudentNo.IsNullOrEmpty())
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.StudentNo.Contains(paramDto.StudentNo));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.Sex.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.Sex == paramDto.Sex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(paramDto.ResultLevel))
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.Grade == paramDto.ResultLevel); // 修改为使用 Rank 过滤
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 分页和排序
|
|
|
|
|
var list = await query
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
if (paramDto.ItemType == SportsTestItemType.BMI)
|
|
|
|
|
{
|
|
|
|
|
foreach (var item in list)
|
|
|
|
|
{
|
|
|
|
|
if (item.Height.HasValue && Math.Abs(item.Height.Value - Math.Round(item.Height.Value, 2)) > 0)
|
|
|
|
|
{
|
|
|
|
|
item.Height = Math.Round(item.Height.Value, 2);
|
|
|
|
|
}
|
|
|
|
|
if (item.Weight.HasValue && Math.Abs(item.Weight.Value - Math.Round(item.Weight.Value, 2)) > 0)
|
|
|
|
|
{
|
|
|
|
|
item.Weight = Math.Round(item.Weight.Value, 2);
|
|
|
|
|
}
|
|
|
|
|
switch (item.Grade)
|
|
|
|
|
{
|
|
|
|
|
case "正常":
|
|
|
|
|
item.Grade = "优秀";
|
|
|
|
|
break;
|
|
|
|
|
case "超重":
|
|
|
|
|
item.Grade = "及格";
|
|
|
|
|
break;
|
|
|
|
|
case "偏瘦":
|
|
|
|
|
item.Grade = "良好";
|
|
|
|
|
break;
|
|
|
|
|
case "肥胖":
|
|
|
|
|
item.Grade = "不及格";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-06 16:00:39 +08:00
|
|
|
|
res = list;
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 总体数据列表
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="paramDto"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
public async Task<PageDataDto<dynamic>> GetOverallDataPageList(GetOverallDataPageListParam paramDto)
|
|
|
|
|
{
|
2025-06-06 16:55:14 +08:00
|
|
|
|
var classList = await _teacherRepository.DbContext.Set<S_Class>()
|
|
|
|
|
.Where(x => x.SchoolCode == UserContext.Current.TenantId && x.GradeId == paramDto.GradeId)
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
|
|
|
|
|
var classIds = classList.Select(c => c.Id).ToList();
|
|
|
|
|
|
|
|
|
|
// 获取体测成绩
|
|
|
|
|
var list = await _cacheQueryService.GeSportsTestDataCacheAsync
|
|
|
|
|
(s =>
|
|
|
|
|
(paramDto.DataSource == null || s.DataSource == paramDto.DataSource) &&
|
|
|
|
|
s.GradeId == paramDto.GradeId && classIds.Contains(s.ClassId)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 获取年级关联的分类
|
|
|
|
|
var categoryList = from s in _teacherRepository.DbContext.Set<S_GradeAssocCategory>()
|
|
|
|
|
join n in _teacherRepository.DbContext.Set<N_SportsTestCategory>()
|
|
|
|
|
on s.CategoryValue equals n.CategoryValue
|
|
|
|
|
where s.GradeId == paramDto.GradeId
|
|
|
|
|
select new
|
|
|
|
|
{
|
|
|
|
|
s.CategoryValue,
|
|
|
|
|
n.CategoryName,
|
|
|
|
|
s.Weight
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 获取所有与条件匹配的学生
|
|
|
|
|
var stuNos = list.Select(s => s.StudentNo).Distinct().ToList();
|
2025-06-06 16:00:39 +08:00
|
|
|
|
|
|
|
|
|
// 初始化查询
|
2025-06-06 16:55:14 +08:00
|
|
|
|
var query = _teacherRepository.DbContext.Set<S_Student>()
|
|
|
|
|
.Where(x => stuNos.Contains(x.StudentNo) && x.SchoolCode == UserContext.Current.TenantId && classIds.Contains(x.ClassId))
|
|
|
|
|
.AsQueryable();
|
2025-06-06 16:00:39 +08:00
|
|
|
|
|
|
|
|
|
// 动态添加条件
|
|
|
|
|
if (paramDto.ClassId > 0)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(s => s.ClassId == paramDto.ClassId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(paramDto.StudentNo))
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(s => s.StudentNo == paramDto.StudentNo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(paramDto.StudentName))
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(s => s.StudentName.Contains(paramDto.StudentName));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.Sex.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(s => s.Sex == (SexType)paramDto.Sex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 执行查询并进行分页
|
|
|
|
|
var stuList = await query
|
|
|
|
|
.Skip((paramDto.PageIndex - 1) * paramDto.PageSize)
|
|
|
|
|
.Take(paramDto.PageSize)
|
|
|
|
|
.Select(s => new
|
|
|
|
|
{
|
|
|
|
|
s.ClassId,
|
|
|
|
|
s.StudentName,
|
|
|
|
|
s.StudentNo,
|
|
|
|
|
s.Sex
|
|
|
|
|
})
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
|
|
|
|
|
// 准备返回的动态列表
|
|
|
|
|
var result = new List<dynamic>();
|
|
|
|
|
|
|
|
|
|
foreach (var stu in stuList)
|
|
|
|
|
{
|
|
|
|
|
dynamic row = new ExpandoObject();
|
2025-06-06 16:55:14 +08:00
|
|
|
|
var classStu = classList.FirstOrDefault(i => i.Id == stu.ClassId);
|
|
|
|
|
row.GradeNameAndClassName = $"{classStu?.GradeName}{classStu?.ClassName}";
|
2025-06-06 16:00:39 +08:00
|
|
|
|
row.StudentName = stu.StudentName;
|
|
|
|
|
row.StudentNo = stu.StudentNo;
|
|
|
|
|
row.Sex = stu.Sex == SexType.Male ? "男" : "女";
|
|
|
|
|
|
|
|
|
|
// 用于累积 currentScore 的变量
|
|
|
|
|
double totalScore = 0;
|
|
|
|
|
|
|
|
|
|
foreach (var category in categoryList)
|
|
|
|
|
{
|
2025-06-06 16:55:14 +08:00
|
|
|
|
// 获取与该学生和分类匹配的体测数据
|
2025-06-06 16:00:39 +08:00
|
|
|
|
var data = list.FirstOrDefault(i => i.CategoryValue == category.CategoryValue && i.StudentNo == stu.StudentNo);
|
|
|
|
|
|
|
|
|
|
double currentValue = data?.Value ?? 0;
|
|
|
|
|
double currentScore = data?.Score ?? 0;
|
|
|
|
|
double currentAdditionalScore = data?.AdditionalScore ?? 0;
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
// 将分类的体测数据值赋给动态对象
|
2025-06-06 16:00:39 +08:00
|
|
|
|
((IDictionary<string, object>)row)[category.CategoryName] = currentValue;
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
// 累积分数
|
|
|
|
|
totalScore += ((currentScore + currentAdditionalScore) * category.Weight);
|
2025-06-06 16:00:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 计算总分
|
|
|
|
|
row.TotalScore = totalScore;
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
//// 计算 Rank
|
|
|
|
|
//var rank = totalScore / (categoryList.Count() * 100) * 100;
|
2025-06-06 16:00:39 +08:00
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
row.Rank = totalScore.GetRank();
|
2025-06-06 16:00:39 +08:00
|
|
|
|
|
|
|
|
|
result.Add(row);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 构造分页数据
|
|
|
|
|
var pageData = new PageDataDto<dynamic>
|
|
|
|
|
{
|
|
|
|
|
Total = await query.CountAsync(),
|
|
|
|
|
Datas = result
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return pageData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 总体数据导出
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="paramDto"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<List<Dictionary<string, string>>> GetOverallDataExport(GetOverallDataExportParam paramDto)
|
|
|
|
|
{
|
2025-06-06 16:55:14 +08:00
|
|
|
|
var classList = await _teacherRepository.DbContext.Set<S_Class>()
|
|
|
|
|
.Where(x => x.SchoolCode == UserContext.Current.TenantId && x.GradeId == paramDto.GradeId)
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
|
|
|
|
|
var classIds = classList.Select(c => c.Id).ToList();
|
|
|
|
|
|
|
|
|
|
// 获取体测成绩
|
|
|
|
|
var list = await _cacheQueryService.GeSportsTestDataCacheAsync
|
|
|
|
|
(s =>
|
|
|
|
|
(paramDto.DataSource == null || s.DataSource == paramDto.DataSource) &&
|
|
|
|
|
s.GradeId == paramDto.GradeId && classIds.Contains(s.ClassId)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 获取年级关联的分类
|
|
|
|
|
var categoryList = from s in _teacherRepository.DbContext.Set<S_GradeAssocCategory>()
|
|
|
|
|
join n in _teacherRepository.DbContext.Set<N_SportsTestCategory>()
|
|
|
|
|
on s.CategoryValue equals n.CategoryValue
|
|
|
|
|
where s.GradeId == paramDto.GradeId
|
|
|
|
|
select new
|
|
|
|
|
{
|
|
|
|
|
n.CategoryEnum,
|
|
|
|
|
s.CategoryValue,
|
|
|
|
|
n.CategoryName,
|
|
|
|
|
s.Weight
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 获取所有涉及的学生
|
|
|
|
|
var stuNos = list.Select(s => s.StudentNo).Distinct().ToList();
|
2025-06-06 16:00:39 +08:00
|
|
|
|
|
|
|
|
|
// 初始化查询
|
2025-06-06 16:55:14 +08:00
|
|
|
|
var query = _teacherRepository.DbContext.Set<S_Student>()
|
|
|
|
|
.Where(x => stuNos.Contains(x.StudentNo) && x.SchoolCode == UserContext.Current.TenantId && classIds.Contains(x.ClassId))
|
|
|
|
|
.AsQueryable();
|
2025-06-06 16:00:39 +08:00
|
|
|
|
|
|
|
|
|
// 动态添加条件
|
|
|
|
|
if (paramDto.ClassId > 0)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(s => s.ClassId == paramDto.ClassId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(paramDto.StudentNo))
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(s => s.StudentNo == paramDto.StudentNo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(paramDto.StudentName))
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(s => s.StudentName.Contains(paramDto.StudentName));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.Sex.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(s => s.Sex == (SexType)paramDto.Sex);
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
// 执行查询并进行分页
|
2025-06-06 16:00:39 +08:00
|
|
|
|
var stuList = await query
|
|
|
|
|
.Select(s => new
|
|
|
|
|
{
|
|
|
|
|
s.ClassId,
|
|
|
|
|
s.StudentName,
|
|
|
|
|
s.StudentNo,
|
|
|
|
|
s.Sex
|
|
|
|
|
})
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
// 准备返回的动态列表
|
|
|
|
|
var result = new List<Dictionary<string, string>>();
|
|
|
|
|
|
|
|
|
|
foreach (var stu in stuList)
|
|
|
|
|
{
|
|
|
|
|
var row = new Dictionary<string, string>();
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
// 获取该学生的体测数据
|
2025-06-06 16:00:39 +08:00
|
|
|
|
var iotStu = list.FirstOrDefault(i => i.StudentNo == stu.StudentNo);
|
|
|
|
|
row["学籍号"] = stu.StudentNo;
|
|
|
|
|
row["姓名"] = stu.StudentName;
|
|
|
|
|
row["性别"] = stu.Sex == SexType.Male ? "男" : "女";
|
|
|
|
|
row["年级-班级"] = $"{iotStu?.GradeName ?? string.Empty}{iotStu?.ClassName ?? string.Empty}";
|
|
|
|
|
|
|
|
|
|
// 用于累积 currentScore 的变量
|
|
|
|
|
double totalScore = 0;
|
|
|
|
|
|
|
|
|
|
foreach (var category in categoryList)
|
|
|
|
|
{
|
|
|
|
|
var data = list.FirstOrDefault(i => i.CategoryValue == category.CategoryValue && i.StudentNo == stu.StudentNo);
|
|
|
|
|
|
|
|
|
|
double currentValue = data?.Value ?? 0;
|
|
|
|
|
double currentScore = data?.Score ?? 0;
|
|
|
|
|
double currentAdditionalScore = data?.AdditionalScore ?? 0;
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
// BMI相关数据
|
2025-06-06 16:00:39 +08:00
|
|
|
|
if (category.CategoryValue == (int)SportsTestItemType.BMI)
|
|
|
|
|
{
|
|
|
|
|
var height = list.FirstOrDefault(i => i.CategoryEnum == "Height" && i.StudentNo == stu.StudentNo);
|
|
|
|
|
var weight = list.FirstOrDefault(i => i.CategoryEnum == "Weight" && i.StudentNo == stu.StudentNo);
|
|
|
|
|
row["身高(cm)"] = height?.Value.ToString("F2") ?? "0";
|
|
|
|
|
row["体重(kg)"] = weight?.Value.ToString("F2") ?? "0";
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
// 根据导出类型处理
|
2025-06-06 16:00:39 +08:00
|
|
|
|
row[category.CategoryName] = paramDto.ExportType switch
|
|
|
|
|
{
|
|
|
|
|
OverallDataExportType.Result => currentValue.ToString("F2"),
|
|
|
|
|
OverallDataExportType.ScoreAndRank => $"{currentScore:F2} {data?.Rank}",
|
|
|
|
|
OverallDataExportType.AdditionalScore => currentAdditionalScore.ToString("F2"),
|
|
|
|
|
_ => string.Empty
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 累积 currentScore
|
2025-06-06 16:55:14 +08:00
|
|
|
|
totalScore += ((currentScore + currentAdditionalScore) * category.Weight);
|
2025-06-06 16:00:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
// 计算总分和等级
|
2025-06-06 16:00:39 +08:00
|
|
|
|
if (paramDto.ExportType == OverallDataExportType.ScoreAndRank)
|
|
|
|
|
{
|
|
|
|
|
// 计算总分
|
|
|
|
|
row["测试总成绩"] = totalScore.ToString("F2");
|
|
|
|
|
// 计算 Rank
|
2025-06-06 16:55:14 +08:00
|
|
|
|
//var rank = totalScore / (categoryList.Count() * 100) * 100;
|
|
|
|
|
row["等级"] = totalScore.GetRank();
|
2025-06-06 16:00:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result.Add(row);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region 视力记录
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 导入视力记录
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="file"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task ImportVisionData(IFormFile file)
|
|
|
|
|
{
|
|
|
|
|
if (file == null || file.Length <= 0)
|
|
|
|
|
throw new Exception("操作失败");
|
|
|
|
|
|
|
|
|
|
var tenantId = UserContext.Current.TenantId;
|
|
|
|
|
|
|
|
|
|
var dataObjects = new List<ImportVisionDataParam>();
|
|
|
|
|
|
|
|
|
|
using (var fileStream = file.OpenReadStream())
|
|
|
|
|
{
|
|
|
|
|
dataObjects = Tool.ConvertExcelToList<ImportVisionDataParam>(fileStream);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var greadNames = dataObjects.Select(x => x.GradeName).Distinct().ToList();
|
|
|
|
|
|
|
|
|
|
var studentNos = dataObjects.Select(x => x.StudentNo).Distinct().ToList();
|
|
|
|
|
|
|
|
|
|
var greadList = await _sportsTestCategoryRepository.DbContext.Set<S_Grade>().Where(x => greadNames.Contains(x.GradeName)).ToListAsync();
|
|
|
|
|
|
|
|
|
|
var greadIds = greadList.Select(x => x.Id).ToList();
|
|
|
|
|
|
|
|
|
|
var classList = await _sportsTestCategoryRepository.DbContext.Set<S_Class>().Where(x => greadIds.Contains(x.GradeId) && x.SchoolCode == tenantId).ToListAsync();
|
|
|
|
|
|
|
|
|
|
var studentList = await _sportsTestCategoryRepository.DbContext.Set<S_Student>().Where(x => studentNos.Contains(x.StudentNo)).ToListAsync();
|
|
|
|
|
|
|
|
|
|
var dbEntitys = await _sportsTestCategoryRepository.DbContext.Set<N_VisionData>().Where(x => studentNos.Contains(x.StudentNo)).ToListAsync();
|
|
|
|
|
|
|
|
|
|
var entitys = new List<N_VisionData>();
|
|
|
|
|
|
|
|
|
|
var updateEntitys = new List<N_VisionData>();
|
|
|
|
|
|
|
|
|
|
foreach (var data in dataObjects)
|
|
|
|
|
{
|
|
|
|
|
var greadModel = greadList.Where(x => x.GradeName.Equals(data.GradeName)).FirstOrDefault();
|
|
|
|
|
if (greadModel == null)
|
|
|
|
|
throw new Exception("未找到年级信息");
|
|
|
|
|
|
|
|
|
|
var classModel = classList.Where(x => x.GradeId == greadModel.Id && x.ClassName == data.ClassName).FirstOrDefault();
|
|
|
|
|
if (classModel == null)
|
|
|
|
|
throw new Exception("未找到班级信息");
|
|
|
|
|
|
|
|
|
|
var studentModel = studentList.Where(x => x.StudentNo.Equals(data.StudentNo) && x.ClassId == classModel.Id).FirstOrDefault();
|
|
|
|
|
if (studentModel == null)
|
|
|
|
|
throw new Exception("未找到学生信息");
|
|
|
|
|
|
|
|
|
|
var dbEntity = dbEntitys.Where(x => x.StudentNo.Equals(data.StudentNo) && x.ClassId.Equals(classModel.Id) && x.GradeId.Equals(greadModel.Id)).FirstOrDefault();
|
|
|
|
|
if (dbEntity != null)
|
|
|
|
|
{
|
|
|
|
|
dbEntity.VisionLeft = data.VisionLeft;
|
|
|
|
|
dbEntity.VisionReight = data.VisionReight;
|
|
|
|
|
dbEntity.ImportDate = DateTime.Now;
|
|
|
|
|
dbEntity.Modifier = UserContext.Current.UserId;
|
|
|
|
|
dbEntity.ModifyDate = DateTime.Now;
|
|
|
|
|
updateEntitys.Add(dbEntity);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var studentEntity = new N_VisionData()
|
|
|
|
|
{
|
|
|
|
|
SchoolCode = tenantId,
|
|
|
|
|
StudentName = studentModel.StudentName,
|
|
|
|
|
StudentNo = studentModel.StudentNo,
|
|
|
|
|
ClassId = classModel.Id,
|
|
|
|
|
ClassName = data.ClassName,
|
|
|
|
|
GradeId = greadModel.Id,
|
|
|
|
|
GradeName = greadModel.GradeName,
|
|
|
|
|
ImportDate = DateTime.Now,
|
|
|
|
|
VisionLeft = data.VisionLeft,
|
|
|
|
|
VisionReight = data.VisionReight,
|
|
|
|
|
Creator = UserContext.Current.UserId,
|
|
|
|
|
CreateDate = DateTime.Now
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
entitys.Add(studentEntity);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await _sportsTestCategoryRepository.DbContext.Set<N_VisionData>().AddRangeAsync(entitys);
|
|
|
|
|
_sportsTestCategoryRepository.DbContext.Set<N_VisionData>().UpdateRange(updateEntitys);
|
|
|
|
|
await _sportsTestCategoryRepository.SaveChangesAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 视力记录列表
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="paramDto"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<PageDataDto<VisionDataModel>> GetVisionDataList(VisionDataListParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var res = new PageDataDto<VisionDataModel>();
|
|
|
|
|
|
|
|
|
|
var query = from vd in _teacherRepository.DbContext.Set<N_VisionData>()
|
|
|
|
|
where vd.SchoolCode.Equals(UserContext.Current.TenantId)
|
|
|
|
|
select new VisionDataModel()
|
|
|
|
|
{
|
|
|
|
|
Id = vd.Id,
|
|
|
|
|
ClassId = vd.ClassId,
|
|
|
|
|
GradeAndClass = $"{vd.GradeName}-{vd.ClassName}",
|
|
|
|
|
StudentName = vd.StudentName,
|
|
|
|
|
VisionLeft = vd.VisionLeft,
|
|
|
|
|
VisionReight = vd.VisionReight,
|
|
|
|
|
ImportDate = vd.ImportDate.ToString("yyyy-MM-dd HH:mm")
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (paramDto.ClassId.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.ClassId.Equals(paramDto.ClassId));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!paramDto.StudentName.IsNullOrEmpty())
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.StudentName.Contains(paramDto.StudentName ?? ""));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res.Total = await query.CountAsync();
|
|
|
|
|
|
|
|
|
|
var list = await query
|
|
|
|
|
.OrderBy(c => c.Id)
|
|
|
|
|
.Skip((paramDto.PageIndex - 1) * paramDto.PageSize)
|
|
|
|
|
.Take(paramDto.PageSize)
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
|
|
|
|
|
res.Datas = list;
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region 课堂报告
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 课堂记录列表
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="paramDto"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<PageDataDto<ClassReportModel>> GetClassReportList(ClassReportListParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var res = new PageDataDto<ClassReportModel>();
|
|
|
|
|
|
|
|
|
|
var query = from td in _teacherRepository.DbContext.Set<Ai_ClassRoomRecord>()
|
|
|
|
|
where td.SchoolCode.Equals(UserContext.Current.TenantId)
|
|
|
|
|
select new ClassReportModel()
|
|
|
|
|
{
|
|
|
|
|
Id = td.Id,
|
|
|
|
|
ClassId = td.ClassId,
|
|
|
|
|
GradeAndClass = $"{td.GradeName}-{td.ClassName}",
|
|
|
|
|
TeacherName = td.TeacherName,
|
|
|
|
|
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)}"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (paramDto.ClassId.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.ClassId.Equals(paramDto.ClassId));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!paramDto.TeacherName.IsNullOrEmpty())
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.TeacherName.Contains(paramDto.TeacherName ?? ""));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res.Total = await query.CountAsync();
|
|
|
|
|
|
|
|
|
|
var list = await query
|
|
|
|
|
.OrderByDescending(c => c.Id)
|
|
|
|
|
.Skip((paramDto.PageIndex - 1) * paramDto.PageSize)
|
|
|
|
|
.Take(paramDto.PageSize)
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
|
|
|
|
|
res.Datas = list;
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 课堂报告详情
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<GetClassReportDetailsModel> GetClassReportDetails(int id)
|
|
|
|
|
{
|
|
|
|
|
var res = new GetClassReportDetailsModel();
|
|
|
|
|
|
|
|
|
|
var query = from hrd in _teacherRepository.DbContext.Set<Ai_HeartRateData>()
|
2025-06-06 16:55:14 +08:00
|
|
|
|
//where hrd.SchoolCode.Equals(UserContext.Current.TenantId) && hrd.ClassRoomRecordId.Equals(id) && hrd.Strength > 0
|
|
|
|
|
where hrd.SchoolCode.Equals(UserContext.Current.TenantId) && hrd.ClassRoomRecordId == id
|
2025-06-06 16:00:39 +08:00
|
|
|
|
select hrd;
|
|
|
|
|
|
|
|
|
|
var heartRateDataList = await query.ToListAsync();
|
|
|
|
|
|
|
|
|
|
if (heartRateDataList.Count == 0)
|
|
|
|
|
return res;
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
var classRoom = await _teacherRepository.DbContext.Set<Ai_ClassRoomRecord>().Include(x => x.ClassroomStudentRecord)
|
|
|
|
|
.Where(x => x.SchoolCode == UserContext.Current.TenantId && x.Id == id)
|
|
|
|
|
.FirstAsync();
|
|
|
|
|
|
|
|
|
|
var classRoomStudent = await _teacherRepository.DbContext.Set<Ai_ClassroomStudentRecord>()
|
|
|
|
|
.Where(x => x.SchoolCode == UserContext.Current.TenantId && x.ClassRoomRecordId == id)
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
|
|
|
|
|
res.GradeAndClass = $"{classRoom.GradeName}-{classRoom.ClassName}";
|
|
|
|
|
res.TeacherName = classRoom.TeacherName;
|
|
|
|
|
res.StartingEndingTime = $"{(classRoom.StartTime.HasValue ? classRoom.StartTime.Value.ToString("yyyy-MM-dd HH:mm") : string.Empty)}{(classRoom.EndTime.HasValue ? " - " + classRoom.EndTime.Value.ToString("yyyy-MM-dd HH:mm") : string.Empty)}";
|
|
|
|
|
res.PeopleNumber = $"{heartRateDataList.GroupBy(x => x.StudentNo).Count()}/{classRoomStudent.Count}";
|
|
|
|
|
res.PeopleNumberBySex = $"{classRoomStudent.Count(x => x.Sex == SexType.Male)}/{classRoomStudent.Count(x => x.Sex == SexType.Female)}";
|
|
|
|
|
|
|
|
|
|
res.AvgHR = $"{(int)(heartRateDataList.Sum(x => x.Value) / heartRateDataList.Count)} 次/分";
|
|
|
|
|
res.Consumption = $"{Math.Abs(heartRateDataList.Sum(x => x.Consumption ?? 0) / heartRateDataList.Count)} 千卡";
|
|
|
|
|
//res.Density = $"{(int)(heartRateDataList.Where(x => x.Strength > 50).Sum(x => x.Strength) / heartRateDataList.Count)} %";
|
|
|
|
|
|
2025-07-11 09:37:06 +08:00
|
|
|
|
res.Density = $"{(int)Tool.CalculatePercentage(heartRateDataList.Count(x => x.Strength > 50), heartRateDataList.Count)} %";
|
2025-06-06 16:55:14 +08:00
|
|
|
|
res.HighIntensity = $"{heartRateDataList.Where(x => x.Strength > 50).GroupBy(x => x.StudentNo).Count()} 人";
|
|
|
|
|
|
|
|
|
|
var studentTrainingRecordList = classRoom.ClassroomStudentRecord.ToList();
|
|
|
|
|
List<StudentTrainingRecordDto> studentList = new List<StudentTrainingRecordDto>();
|
|
|
|
|
|
|
|
|
|
foreach (var item in studentTrainingRecordList)
|
2025-06-06 16:00:39 +08:00
|
|
|
|
{
|
2025-06-06 16:55:14 +08:00
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
student.AvgHR = (int)(studentTrainingData.Sum(x => x.Value) / studentTrainingData.Count);
|
2025-07-11 09:37:06 +08:00
|
|
|
|
student.Density = (int)Tool.CalculatePercentage(studentTrainingData.Count(x => x.Strength > 50), studentTrainingData.Count);
|
2025-06-06 16:55:14 +08:00
|
|
|
|
student.Strength = (int)studentTrainingData.Average(x => x.Strength);
|
|
|
|
|
student.Consumption = Math.Abs((int)studentTrainingData.Average(x => x.Consumption ?? 0));
|
|
|
|
|
|
|
|
|
|
studentList.Add(student);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-11 09:37:06 +08:00
|
|
|
|
res.HeartRateNumber = Tool.GetHeartRateNumber(heartRateDataList);
|
|
|
|
|
res.HeartRateTrend = Tool.GetHeartRateTrend(heartRateDataList);
|
2025-06-06 16:55:14 +08:00
|
|
|
|
res.StudentTrainingRecordList = studentList;
|
|
|
|
|
|
|
|
|
|
//return new GetClassReportDetailsModel()
|
|
|
|
|
//{
|
|
|
|
|
// HeartRateNumber = GetHeartRateNumber(heartRateDataList),
|
|
|
|
|
// HeartRateTrend = GetHeartRateTrend(heartRateDataList),
|
|
|
|
|
// HeartRateIntensityNumber = GetHeartRateIntensityNumber(heartRateDataList),
|
|
|
|
|
// TimeIntervalHeartRateIntensityNumber = GetTimeIntervalHeartRateIntensityNumber(heartRateDataList)
|
|
|
|
|
//};
|
|
|
|
|
|
|
|
|
|
return res;
|
2025-06-06 16:00:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-06-06 16:55:14 +08:00
|
|
|
|
/// 学生课堂报告详情
|
2025-06-06 16:00:39 +08:00
|
|
|
|
/// </summary>
|
2025-06-06 16:55:14 +08:00
|
|
|
|
/// <param name="studentNo"></param>
|
2025-06-06 16:00:39 +08:00
|
|
|
|
/// <returns></returns>
|
2025-06-06 16:55:14 +08:00
|
|
|
|
public async Task<GetStudentClassReportDetailsModel> GetStudentClassReportDetails(GetStudentClassReportDetailsDto paramDto)
|
2025-06-06 16:00:39 +08:00
|
|
|
|
{
|
2025-06-06 16:55:14 +08:00
|
|
|
|
var res = new GetStudentClassReportDetailsModel();
|
2025-06-06 16:00:39 +08:00
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
var schoolCode = UserContext.Current.TenantId;
|
|
|
|
|
|
|
|
|
|
var query = from hrd in _teacherRepository.DbContext.Set<Ai_HeartRateData>()
|
|
|
|
|
where hrd.SchoolCode == schoolCode &&
|
|
|
|
|
hrd.ClassRoomRecordId == paramDto.ClassRoomRecordId &&
|
|
|
|
|
hrd.StudentNo == paramDto.StudentNo
|
|
|
|
|
select hrd;
|
|
|
|
|
|
|
|
|
|
var heartRateDataList = await query.ToListAsync();
|
|
|
|
|
|
|
|
|
|
if (heartRateDataList.Count == 0)
|
|
|
|
|
return res;
|
|
|
|
|
|
|
|
|
|
var student = heartRateDataList[0];
|
|
|
|
|
|
|
|
|
|
res.StudentNo = student.StudentNo;
|
|
|
|
|
res.StudentName = student.StudentName;
|
|
|
|
|
res.Sex = student.Sex;
|
|
|
|
|
res.GradeAndClass = $"{student.GradeName}-{student.ClassName}";
|
|
|
|
|
|
|
|
|
|
res.AvgHR = (int)(heartRateDataList.Sum(x => x.Value) / heartRateDataList.Count);
|
2025-07-11 09:37:06 +08:00
|
|
|
|
res.Density = (int)Tool.CalculatePercentage(heartRateDataList.Count(x => x.Strength > 50), heartRateDataList.Count);
|
2025-06-06 16:55:14 +08:00
|
|
|
|
res.Strength = (int)heartRateDataList.Average(x => x.Strength);
|
|
|
|
|
res.Consumption = Math.Abs((int)heartRateDataList.Average(x => x.Consumption ?? 0));
|
|
|
|
|
|
|
|
|
|
//var baseTime = heartRateDataList.Min(x => x.ScoreTime);
|
|
|
|
|
var baseTime = await _teacherRepository.DbContext.Set<Ai_HeartRateData>().Where(x => x.SchoolCode == schoolCode && x.ClassRoomRecordId == paramDto.ClassRoomRecordId).MinAsync(x => x.ScoreTime);
|
2025-06-06 16:00:39 +08:00
|
|
|
|
|
|
|
|
|
var heartRateWithMinutes = heartRateDataList
|
|
|
|
|
.Select(data => new
|
|
|
|
|
{
|
|
|
|
|
Data = data,
|
2025-06-06 16:55:14 +08:00
|
|
|
|
MinuteBucket = (int)(data.ScoreTime - baseTime).TotalMinutes
|
2025-06-06 16:00:39 +08:00
|
|
|
|
})
|
|
|
|
|
.ToList();
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
var maxMinute = heartRateWithMinutes.Max(x => x.MinuteBucket);
|
2025-06-06 16:00:39 +08:00
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
for (int minute = 0; minute <= maxMinute; minute++)
|
2025-06-06 16:00:39 +08:00
|
|
|
|
{
|
2025-06-06 16:55:14 +08:00
|
|
|
|
var minuteData = heartRateWithMinutes
|
|
|
|
|
.Where(x => x.MinuteBucket == minute)
|
2025-06-06 16:00:39 +08:00
|
|
|
|
.Select(x => x.Data)
|
|
|
|
|
.ToList();
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
if (minuteData.Any())
|
|
|
|
|
{
|
|
|
|
|
res.HeartRateTrend.Add(new SportsProportionData()
|
|
|
|
|
{
|
|
|
|
|
Name = $"{minute + 1} 分钟",
|
|
|
|
|
Datas = new List<StudentSportsProportionData>
|
|
|
|
|
{
|
|
|
|
|
new StudentSportsProportionData {
|
|
|
|
|
Title = "心率",
|
|
|
|
|
Value = (int)minuteData.Average(x => x.Value)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-06 16:00:39 +08:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 心率各强度达成人数
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="id"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public List<SportsProportionData> GetHeartRateIntensityNumber(List<Ai_HeartRateData> heartRateDataList)
|
|
|
|
|
{
|
|
|
|
|
// 初始化返回结果
|
|
|
|
|
var result = new List<SportsProportionData>();
|
|
|
|
|
|
|
|
|
|
// 定义强度区间
|
|
|
|
|
var intensityRanges = new List<(string Name, string Title, double Min, double Max)>
|
|
|
|
|
{
|
|
|
|
|
("区间(<50% MHR)" ,"基本热身", 0, 50),
|
|
|
|
|
("区间(50~60% MHR)" ,"低等强度", 50, 60),
|
|
|
|
|
("区间(60~70% MHR)" ,"中等强度", 60, 70),
|
|
|
|
|
("区间(70~85% MHR)" ,"高等强度", 70, 85),
|
|
|
|
|
("区间(>85% MHR)" ,"安全预警", 85, 100)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 针对每个强度区间计算学生数量
|
|
|
|
|
foreach (var range in intensityRanges)
|
|
|
|
|
{
|
|
|
|
|
var sportsData = new SportsProportionData
|
|
|
|
|
{
|
|
|
|
|
Name = range.Name, // 设置区间名称
|
|
|
|
|
Datas = new List<StudentSportsProportionData>()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 筛选出符合当前强度区间的数据
|
|
|
|
|
var intensityData = heartRateDataList
|
|
|
|
|
.Where(hrd => hrd.Strength >= range.Min && hrd.Strength < range.Max)
|
|
|
|
|
.DistinctBy(x => x.StudentNo)
|
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
|
|
// 计算符合该区间的学生人数
|
|
|
|
|
int studentCountInRange = intensityData.Count;
|
|
|
|
|
|
|
|
|
|
sportsData.Datas.Add(new StudentSportsProportionData
|
|
|
|
|
{
|
|
|
|
|
Title = range.Title,
|
|
|
|
|
Value = studentCountInRange
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
result.Add(sportsData);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 各时间区间中高强度人数
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="id"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public List<SportsProportionData> GetTimeIntervalHeartRateIntensityNumber(List<Ai_HeartRateData> heartRateDataList)
|
|
|
|
|
{
|
|
|
|
|
// 初始化返回结果
|
|
|
|
|
var result = new List<SportsProportionData>();
|
|
|
|
|
|
|
|
|
|
// 获取基准时间
|
|
|
|
|
var baseTime = heartRateDataList.Min(x => x.ScoreTime);
|
|
|
|
|
|
|
|
|
|
// 将心率数据按分钟转换
|
|
|
|
|
var heartRateWithMinutes = heartRateDataList
|
|
|
|
|
.Select(data => new
|
|
|
|
|
{
|
|
|
|
|
Data = data,
|
|
|
|
|
Minutes = (data.ScoreTime - baseTime).TotalMinutes
|
|
|
|
|
})
|
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
|
|
// 计算最大时间值
|
|
|
|
|
var maxMinutes = heartRateWithMinutes.Max(x => x.Minutes);
|
|
|
|
|
|
|
|
|
|
// 每10分钟一个区间
|
|
|
|
|
for (int i = 1; i <= Math.Ceiling(maxMinutes / 10.0); i++)
|
|
|
|
|
{
|
|
|
|
|
var upperBound = i * 10;
|
|
|
|
|
var lowerBound = (i - 1) * 10;
|
|
|
|
|
|
|
|
|
|
var sportsData = new SportsProportionData
|
|
|
|
|
{
|
|
|
|
|
Name = $"{lowerBound}-{upperBound}分钟", // 时间区间
|
|
|
|
|
Datas = new List<StudentSportsProportionData>()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 筛选出符合当前时间区间的数据
|
|
|
|
|
var timeIntervalData = heartRateWithMinutes
|
|
|
|
|
.Where(hrd => hrd.Minutes > lowerBound && hrd.Minutes <= upperBound)
|
|
|
|
|
.Select(hrd => hrd.Data)
|
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
|
|
// 计算中等强度和高等强度人数
|
|
|
|
|
int moderateIntensityCount = timeIntervalData.Where(hrd =>
|
|
|
|
|
hrd.Strength >= 60 && hrd.Strength < 70).DistinctBy(x => x.StudentNo).Count();
|
|
|
|
|
|
|
|
|
|
int highIntensityCount = timeIntervalData.Where(hrd =>
|
|
|
|
|
hrd.Strength >= 70 && hrd.Strength < 85).DistinctBy(x => x.StudentNo).Count();
|
|
|
|
|
|
2025-06-06 16:55:14 +08:00
|
|
|
|
// 计算总人数
|
|
|
|
|
int totalCount = moderateIntensityCount + highIntensityCount;
|
|
|
|
|
|
2025-06-06 16:00:39 +08:00
|
|
|
|
// 添加总人数数据
|
|
|
|
|
sportsData.Datas.Add(new StudentSportsProportionData
|
|
|
|
|
{
|
|
|
|
|
Title = "总人数",
|
|
|
|
|
Value = totalCount
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 添加中等强度人数数据
|
|
|
|
|
sportsData.Datas.Add(new StudentSportsProportionData
|
|
|
|
|
{
|
|
|
|
|
Title = "中等强度人数",
|
|
|
|
|
Value = moderateIntensityCount
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 添加高等强度人数数据
|
|
|
|
|
sportsData.Datas.Add(new StudentSportsProportionData
|
|
|
|
|
{
|
|
|
|
|
Title = "高等强度人数",
|
|
|
|
|
Value = highIntensityCount
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
result.Add(sportsData);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
2025-06-06 16:55:14 +08:00
|
|
|
|
|
|
|
|
|
#region 用户训练数据
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取用户训练数据列表
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="paramDto">查询参数</param>
|
|
|
|
|
/// <returns>用户训练数据列表</returns>
|
|
|
|
|
public async Task<PageDataDto<UserTrainingDataModel>> GetUserTrainingDataList(UserTrainingDataQueryParam paramDto)
|
|
|
|
|
{
|
|
|
|
|
var res = new PageDataDto<UserTrainingDataModel>();
|
|
|
|
|
var tenantId = UserContext.Current.TenantId;
|
|
|
|
|
|
|
|
|
|
// 查询用户训练数据
|
|
|
|
|
var query = from td in _teacherRepository.DbContext.Set<I_TrainingData>()
|
|
|
|
|
join sd in _teacherRepository.DbContext.Set<I_TrainingStudentData>() on td.Id equals sd.TrainingDataId
|
|
|
|
|
where td.SchoolCode == tenantId && td.TeacherId == paramDto.UserId
|
|
|
|
|
select new UserTrainingDataModel
|
|
|
|
|
{
|
|
|
|
|
Id = td.Id,
|
|
|
|
|
TrainingType = td.ItemType,
|
|
|
|
|
TrainingTypeName = td.ItemType == 1 ? "个人" : "团队",
|
|
|
|
|
ModeType = td.ModeType,
|
|
|
|
|
ModeTypeName = td.ModelName,
|
|
|
|
|
Duration = td.TrainTimer.GetValueOrDefault() / 60,
|
|
|
|
|
JumpCount = sd.JumpValue,
|
|
|
|
|
Kcal = sd.Kcal,
|
|
|
|
|
TrainingTime = td.ClassTime
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 训练类型筛选(可选)
|
|
|
|
|
if (paramDto.TrainingType.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.TrainingType == paramDto.TrainingType);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 训练模式筛选(可选)
|
|
|
|
|
if (paramDto.ModeType.HasValue)
|
|
|
|
|
{
|
|
|
|
|
query = query.Where(x => x.ModeType == paramDto.ModeType);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 时间范围筛选(可选)
|
|
|
|
|
if (paramDto.StartTime.HasValue)
|
|
|
|
|
{
|
|
|
|
|
var startTimeStr = paramDto.StartTime.Value.ToString("yyyy-MM-dd");
|
|
|
|
|
query = query.Where(x => EF.Functions.Like(x.TrainingTime, $"{startTimeStr}%") ||
|
|
|
|
|
x.TrainingTime.CompareTo(startTimeStr) > 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramDto.EndTime.HasValue)
|
|
|
|
|
{
|
|
|
|
|
var endTimeStr = paramDto.EndTime.Value.ToString("yyyy-MM-dd");
|
|
|
|
|
query = query.Where(x => EF.Functions.Like(x.TrainingTime, $"{endTimeStr}%") ||
|
|
|
|
|
x.TrainingTime.CompareTo(endTimeStr) < 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取总记录数
|
|
|
|
|
res.Total = await query.CountAsync();
|
|
|
|
|
|
|
|
|
|
// 分页查询数据
|
|
|
|
|
var list = await query
|
|
|
|
|
.OrderByDescending(x => x.TrainingTime)
|
|
|
|
|
.Skip((paramDto.PageIndex - 1) * paramDto.PageSize)
|
|
|
|
|
.Take(paramDto.PageSize)
|
|
|
|
|
.ToListAsync();
|
|
|
|
|
|
|
|
|
|
res.Datas = list;
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
2025-06-06 16:00:39 +08:00
|
|
|
|
}
|
|
|
|
|
}
|