From 3661747123667a77fa991883242e78025dab56d0 Mon Sep 17 00:00:00 2001
From: tanglong <842690096@qq.com>
Date: Fri, 24 Apr 2026 13:53:01 +0800
Subject: [PATCH] =?UTF-8?q?=E8=BF=90=E5=8A=A8=E9=A6=86=E6=88=90=E7=BB=A9?=
=?UTF-8?q?=E5=AF=BC=E5=85=A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Norm/IN_SportsTestResultService.cs | 6 +-
.../SportsHall/ISportsHallService.cs | 26 +-
.../Norm/N_SportsTestResultService.cs | 26 +-
.../Services/SportsHall/SportsHallService.cs | 386 +++++++++++++++++-
.../Request/ImportStudentsTestDataParam.cs | 1 -
.../SportsHallImportStudentsTestDataParam.cs | 82 ++++
.../Request/SportsHallStudentsTestParam.cs | 39 ++
.../Response/SportsHallStudentsTestModel.cs | 95 +++++
.../Business/SportsTestResultController.cs | 1 -
.../SportsHall/SportsHallController.cs | 41 ++
10 files changed, 672 insertions(+), 31 deletions(-)
create mode 100644 VOL.Model/School/Request/SportsHallImportStudentsTestDataParam.cs
create mode 100644 VOL.Model/School/Request/SportsHallStudentsTestParam.cs
create mode 100644 VOL.Model/School/Response/SportsHallStudentsTestModel.cs
diff --git a/VOL.Business/IServices/Norm/IN_SportsTestResultService.cs b/VOL.Business/IServices/Norm/IN_SportsTestResultService.cs
index e017b41..a1fa9c9 100644
--- a/VOL.Business/IServices/Norm/IN_SportsTestResultService.cs
+++ b/VOL.Business/IServices/Norm/IN_SportsTestResultService.cs
@@ -3,11 +3,13 @@ using Microsoft.AspNetCore.Http;
using VOL.Model;
using VOL.Model.Norm.Request;
using VOL.Model.Norm.Response;
+using VOL.Model.School.Request;
+using VOL.Model.School.Response;
-namespace VOL.Business.IServices
+ namespace VOL.Business.IServices
{
public interface IN_SportsTestResultService
- {
+ {
///
/// 导入学生体测成绩
///
diff --git a/VOL.Business/IServices/SportsHall/ISportsHallService.cs b/VOL.Business/IServices/SportsHall/ISportsHallService.cs
index b973416..f58df29 100644
--- a/VOL.Business/IServices/SportsHall/ISportsHallService.cs
+++ b/VOL.Business/IServices/SportsHall/ISportsHallService.cs
@@ -1,9 +1,12 @@
-using System;
+using Microsoft.AspNetCore.Http;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VOL.Model;
+using VOL.Model.School.Request;
+using VOL.Model.School.Response;
using VOL.Model.SportsHall;
namespace VOL.Business.IServices.SportsHall
@@ -23,5 +26,26 @@ namespace VOL.Business.IServices.SportsHall
///
///
Task ModifyClass(ModifySportsHallClassParam paramDto);
+
+ ///
+ /// 导入运动馆学生体测成绩
+ ///
+ ///
+ ///
+ Task SportsHallImportStudentsTestData(IFormFile file);
+
+ ///
+ /// 运动馆体测成绩分页列表
+ ///
+ ///
+ ///
+ Task> GetSportsHallStudentsTestPageList(SportsHallStudentsTestParam paramDto);
+
+ ///
+ /// 成绩推送
+ ///
+ ///
+ ///
+ Task ScorePush(SportsHallStudentsTestParam paramDto);
}
}
diff --git a/VOL.Business/Services/Norm/N_SportsTestResultService.cs b/VOL.Business/Services/Norm/N_SportsTestResultService.cs
index 2591db4..42be987 100644
--- a/VOL.Business/Services/Norm/N_SportsTestResultService.cs
+++ b/VOL.Business/Services/Norm/N_SportsTestResultService.cs
@@ -1,29 +1,11 @@
using AutoMapper;
-using Castle.DynamicProxy.Generators;
-using Confluent.Kafka;
using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
-using Microsoft.ML;
-using OfficeOpenXml.ConditionalFormatting;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
-using SkiaSharp;
using StackExchange.Redis;
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Dynamic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using VOL.Business.IServices;
using VOL.Business.IServices.Norm;
using VOL.Core.CacheManager;
-using VOL.Core.Configuration;
using VOL.Core.Extensions;
using VOL.Core.Extensions.AutofacManager;
using VOL.Core.ManageUser;
@@ -32,15 +14,11 @@ using VOL.Entity.DomainModels;
using VOL.Entity.DomainModels.Business.People;
using VOL.Entity.Enum;
using VOL.Model;
-using VOL.Model.Ai;
-using VOL.Model.IOT.Request;
using VOL.Model.Norm.Request;
using VOL.Model.Norm.Response;
+using VOL.Model.School.Request;
using VOL.Model.School.Response;
using VOL.System.IRepositories;
-using VOL.System.Repositories;
-using static Dapper.SqlMapper;
-using static System.Formats.Asn1.AsnWriter;
namespace VOL.Business.Services
{
@@ -180,6 +158,7 @@ namespace VOL.Business.Services
await _sportsTestResultRepository.SaveChangesAsync();
}
+
public async Task AddEnumStudentsTestData(ImportStudentsTestDataParam data, SportsTestItemType type, dynamic student, DateTime timeNow)
{
int classId = student.ClassId;
@@ -2032,7 +2011,6 @@ namespace VOL.Business.Services
return scoreToAdditionalPoints[score];
}
-
//获取引体向上和仰卧起坐附加分
public int GetPullUpSitUpsAdditionalScore(string gender, int score)
{
diff --git a/VOL.Business/Services/SportsHall/SportsHallService.cs b/VOL.Business/Services/SportsHall/SportsHallService.cs
index 7737310..2a32a19 100644
--- a/VOL.Business/Services/SportsHall/SportsHallService.cs
+++ b/VOL.Business/Services/SportsHall/SportsHallService.cs
@@ -1,4 +1,5 @@
using AutoMapper;
+using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
@@ -15,10 +16,13 @@ using VOL.Business.Services.School;
using VOL.Core.CacheManager;
using VOL.Core.Extensions.AutofacManager;
using VOL.Core.ManageUser;
+using VOL.Core.Utilities;
using VOL.Entity.DomainModels;
using VOL.Entity.Enum;
using VOL.Model;
using VOL.Model.IOT.Request;
+using VOL.Model.School.Request;
+using VOL.Model.School.Response;
using VOL.Model.SportsHall;
using VOL.System.IRepositories;
using VOL.System.Repositories;
@@ -35,14 +39,23 @@ namespace VOL.Business.Services.SportsHall
private readonly IS_GradeRepository _gradeRepository;
private readonly IS_ClassAssocTeacherRepository _classAssocTeacherRepository;
private readonly IS_StudentRepository _studentRepository;
+ IN_HealthStandardsRepository _healthStandardsRepository;
+ IN_SportsTestResultRepository _sportsTestResultRepository;
[ActivatorUtilitiesConstructor]
- public SportsHallService(IS_ClassRepository classRepository, IS_GradeRepository gradeRepository, IS_ClassAssocTeacherRepository classAssocTeacherRepository, IS_StudentRepository studentRepository)
+ public SportsHallService(IS_ClassRepository classRepository,
+ IS_GradeRepository gradeRepository,
+ IS_ClassAssocTeacherRepository classAssocTeacherRepository,
+ IS_StudentRepository studentRepository,
+ IN_HealthStandardsRepository healthStandardsRepository,
+ IN_SportsTestResultRepository sportsTestResultRepository)
{
_classRepository = classRepository;
_gradeRepository = gradeRepository;
_classAssocTeacherRepository = classAssocTeacherRepository;
_studentRepository = studentRepository;
+ _healthStandardsRepository = healthStandardsRepository;
+ _sportsTestResultRepository = sportsTestResultRepository;
}
#endregion
@@ -188,7 +201,7 @@ namespace VOL.Business.Services.SportsHall
}
else
{
- student.ClassId = 0;
+ student.ClassId = 0;
student.OrderNo = 0;
}
}
@@ -206,5 +219,374 @@ namespace VOL.Business.Services.SportsHall
}
}
}
+
+ ///
+ /// 导入运动馆学生体测成绩
+ ///
+ ///
+ ///
+ ///
+ public async Task SportsHallImportStudentsTestData(IFormFile file)
+ {
+ if (file == null || file.Length <= 0)
+ throw new Exception("操作失败");
+
+ List dataObjects;
+
+ using (var fileStream = file.OpenReadStream())
+ {
+ dataObjects = Tool.ConvertExcelToList(fileStream);
+ }
+
+ var studentNos = dataObjects.Select(x => x.StudentNo).Distinct().ToList();
+
+ // 用一个查询一次性获取所有学生信息
+ var students = await (from s in _studentRepository.DbContext.Set()
+ join c in _studentRepository.DbContext.Set() on s.ClassId equals c.Id
+ join g in _studentRepository.DbContext.Set() on c.GradeId equals g.Id
+ where c.SchoolCode.Equals(UserContext.Current.TenantId)
+ select new
+ {
+ s.Id,
+ s.Age,
+ s.ClassId,
+ c.ClassName,
+ s.StudentName,
+ GradeId = g.Id,
+ g.GradeName,
+ s.Sex,
+ s.StudentNo
+ }).ToListAsync();
+
+ // 将学生信息存入字典,快速查找
+ var studentsDict = students.ToDictionary(x => x.StudentNo);
+
+ var entityList = new List();
+
+ foreach (var data in dataObjects)
+ {
+ if (!studentsDict.TryGetValue(data.StudentNo, out var student))
+ {
+ throw new Exception($"未找到此编号为{data.StudentNo}的学生");
+ }
+
+ var timeNow = Convert.ToDateTime(data.ScoreTime);
+
+ // 为每个学生添加多条体测数据
+ if (data.BMIValue > 0)
+ entityList.Add(await AddSportsHallEnumStudentsTestData(data, SportsTestItemType.BMI, student, timeNow));
+
+ if (data.Sit_And_ReachValue > 0)
+ entityList.Add(await AddSportsHallEnumStudentsTestData(data, SportsTestItemType.Sit_And_Reach, student, timeNow));
+
+ if (data.VitalCapacityValue > 0)
+ entityList.Add(await AddSportsHallEnumStudentsTestData(data, SportsTestItemType.VitalCapacity, student, timeNow));
+
+ if (data.OneMinuteJumpRopeValue > 0)
+ entityList.Add(await AddSportsHallEnumStudentsTestData(data, SportsTestItemType.OneMinuteJumpRope, student, timeNow));
+
+ if (data.One_Minute_Sit_UpValue > 0)
+ entityList.Add(await AddSportsHallEnumStudentsTestData(data, SportsTestItemType.One_Minute_Sit_Up, student, timeNow));
+
+ if (data.StandingLongJumpValue > 0)
+ entityList.Add(await AddSportsHallEnumStudentsTestData(data, SportsTestItemType.StandingLongJump, student, timeNow));
+ }
+
+ // 批量添加数据
+ await _sportsTestResultRepository.AddRangeAsync(entityList);
+
+ // 一次性保存所有修改
+ await _sportsTestResultRepository.SaveChangesAsync();
+ }
+
+ public async Task AddSportsHallEnumStudentsTestData(SportsHallImportStudentsTestDataParam data, SportsTestItemType type, dynamic student, DateTime timeNow)
+ {
+ var entity = new N_SportsTestValue
+ {
+ TeacherId = 0,
+ TeacherName = "",
+ DataSource = DataSource.IOT,
+ ScoreTime = timeNow,
+ GradeId = student.GradeId,
+ ClassId = student.ClassId,
+ GradeName = student.GradeName,
+ ClassName = student.ClassName,
+ SchoolCode = UserContext.Current.TenantId,
+ Sex = student.Sex,
+ StudentNo = data.StudentNo,
+ StudentName = student.StudentName,
+ Creator = UserContext.Current.UserId,
+ CreateDate = timeNow,
+ IsDisplay = false
+ };
+
+ int gradeId = student.GradeId;
+ SexType sexType = student.Sex;
+
+ string sex = sexType == SexType.Male ? "男" : "女";
+
+ string typeStr = type.ToString();
+
+ // 根据测试项目类型设置对应的值
+ if (type == SportsTestItemType.BMI)
+ {
+ entity.Value = data.BMIValue;
+
+ // 根据测试项目查找标准
+ var standard = await _healthStandardsRepository.FindFirstAsync(x =>
+ x.CategoryEnum.Equals(typeStr) &&
+ x.GradeId == gradeId &&
+ x.Sex == sexType &&
+ data.BMIValue >= x.MinValue &&
+ data.BMIValue < x.MaxValue
+ );
+
+ if (standard != null)
+ {
+ entity.Score = standard.Score;
+ entity.Rank = standard.Rank;
+ }
+
+ }
+ else if (type == SportsTestItemType.Sit_And_Reach)
+ {
+ entity.Value = data.Sit_And_ReachValue;
+
+ // 根据测试项目查找标准
+ var standard = await _healthStandardsRepository.FindFirstAsync(x =>
+ x.CategoryEnum.Equals(typeStr) &&
+ x.GradeId == gradeId &&
+ x.Sex == sexType &&
+ data.Sit_And_ReachValue >= x.MinValue &&
+ data.Sit_And_ReachValue < x.MaxValue
+ );
+
+ if (standard != null)
+ {
+ entity.Score = standard.Score;
+ entity.Rank = standard.Rank;
+ }
+ }
+ else if (type == SportsTestItemType.VitalCapacity)
+ {
+ entity.Value = data.VitalCapacityValue;
+
+ // 根据测试项目查找标准
+ var standard = await _healthStandardsRepository.FindFirstAsync(x =>
+ x.CategoryEnum.Equals(typeStr) &&
+ x.GradeId == gradeId &&
+ x.Sex == sexType &&
+ data.VitalCapacityValue >= x.MinValue &&
+ data.VitalCapacityValue < x.MaxValue
+ );
+
+ if (standard != null)
+ {
+ entity.Score = standard.Score;
+ entity.Rank = standard.Rank;
+ }
+ }
+
+ else if (type == SportsTestItemType.OneMinuteJumpRope)
+ {
+ entity.Value = data.OneMinuteJumpRopeValue;
+
+ // 根据测试项目查找标准
+ var standard = await _healthStandardsRepository.FindFirstAsync(x =>
+ x.CategoryEnum.Equals(typeStr) &&
+ x.GradeId == gradeId &&
+ x.Sex == sexType &&
+ data.OneMinuteJumpRopeValue >= x.MinValue &&
+ data.OneMinuteJumpRopeValue < x.MaxValue
+ );
+
+ if (standard != null)
+ {
+ entity.Score = standard.Score;
+ entity.Rank = standard.Rank;
+ }
+ }
+ else if (type == SportsTestItemType.One_Minute_Sit_Up)
+ {
+ entity.Value = data.One_Minute_Sit_UpValue;
+
+ // 根据测试项目查找标准
+ var standard = await _healthStandardsRepository.FindFirstAsync(x =>
+ x.CategoryEnum.Equals(typeStr) &&
+ x.GradeId == gradeId &&
+ x.Sex == sexType &&
+ data.One_Minute_Sit_UpValue >= x.MinValue &&
+ data.One_Minute_Sit_UpValue < x.MaxValue
+ );
+
+ if (standard != null)
+ {
+ entity.Score = standard.Score;
+ entity.Rank = standard.Rank;
+ }
+ }
+
+ else if (type == SportsTestItemType.StandingLongJump)
+ {
+ entity.Value = data.StandingLongJumpValue;
+
+ // 根据测试项目查找标准
+ var standard = await _healthStandardsRepository.FindFirstAsync(x =>
+ x.CategoryEnum.Equals(typeStr) &&
+ x.GradeId == gradeId &&
+ x.Sex == sexType &&
+ data.StandingLongJumpValue >= x.MinValue &&
+ data.StandingLongJumpValue < x.MaxValue
+ );
+
+ if (standard != null)
+ {
+ entity.Score = standard.Score;
+ entity.Rank = standard.Rank;
+ }
+ }
+
+ entity.CategoryEnum = type.ToString();
+ entity.CategoryValue = (int)type;
+
+ return entity;
+ }
+
+ ///
+ /// 运动馆体测成绩分页列表
+ ///
+ ///
+ ///
+ ///
+ public async Task> GetSportsHallStudentsTestPageList(SportsHallStudentsTestParam paramDto)
+ {
+ var res = new PageDataDto();
+
+ var query = _sportsTestResultRepository.DbContext.Set()
+ .Where(s => s.SchoolCode == UserContext.Current.TenantId);
+
+ // 条件过滤
+ if (paramDto.StartTime.HasValue)
+ query = query.Where(x => x.CreateDate >= paramDto.StartTime.Value);
+
+ if (paramDto.EndTime.HasValue)
+ query = query.Where(x => x.CreateDate <= paramDto.EndTime.Value);
+
+ if (paramDto.ClassId.HasValue)
+ query = query.Where(x => x.ClassId == paramDto.ClassId.Value);
+
+ if (paramDto.Sex.HasValue)
+ query = query.Where(x => (int)x.Sex == paramDto.Sex);
+
+ if (!string.IsNullOrWhiteSpace(paramDto.ResultLevel))
+ query = query.Where(x => x.Rank == paramDto.ResultLevel);
+
+ // ✅ 正确分组(去掉 Id)
+ var groupedQuery = query.GroupBy(x => new
+ {
+ x.StudentNo,
+ x.StudentName,
+ x.Sex,
+ x.ClassName,
+ x.GradeName,
+ x.ScoreTime,
+ x.IsDisplay
+ });
+
+ res.Total = await groupedQuery.CountAsync();
+
+ var list = await groupedQuery
+ .Select(g => new SportsHallStudentsTestModel
+ {
+ // 👉 可以取组内任意一条的Id
+ Id = g.Max(x => x.Id),
+
+ StudentNo = g.Key.StudentNo,
+ StudentName = g.Key.StudentName,
+ SexName = g.Key.Sex.GetDescription(),
+
+ GradeAndClass = g.Key.GradeName + "_" + g.Key.ClassName,
+
+ ScoreTime = g.Key.ScoreTime,
+ IsDisplay = g.Key.IsDisplay,
+
+ // 👇 pivot(用 Max 比 FirstOrDefault 更稳)
+ BMIValue = g.Where(x => x.CategoryValue == (int)SportsTestItemType.BMI)
+ .Max(x => (float?)x.Value) ?? 0,
+
+ VitalCapacityValue = g.Where(x => x.CategoryValue == (int)SportsTestItemType.VitalCapacity)
+ .Max(x => (float?)x.Value) ?? 0,
+
+ Sit_And_ReachValue = g.Where(x => x.CategoryValue == (int)SportsTestItemType.Sit_And_Reach)
+ .Max(x => (float?)x.Value) ?? 0,
+
+ OneMinuteJumpRopeValue = g.Where(x => x.CategoryValue == (int)SportsTestItemType.OneMinuteJumpRope)
+ .Max(x => (int?)x.Value) ?? 0,
+
+ One_Minute_Sit_UpValue = g.Where(x => x.CategoryValue == (int)SportsTestItemType.One_Minute_Sit_Up)
+ .Max(x => (int?)x.Value) ?? 0,
+
+ StandingLongJumpValue = g.Where(x => x.CategoryValue == (int)SportsTestItemType.StandingLongJump)
+ .Max(x => (float?)x.Value) ?? 0
+ })
+ .OrderByDescending(x => x.ScoreTime)
+ .Skip((paramDto.PageIndex - 1) * paramDto.PageSize)
+ .Take(paramDto.PageSize)
+ .ToListAsync();
+
+ res.Datas = list;
+
+ return res;
+ }
+
+ ///
+ /// 成绩推送
+ ///
+ ///
+ ///
+ ///
+ public async Task ScorePush(SportsHallStudentsTestParam paramDto)
+ {
+ var sql = new StringBuilder();
+ sql.Append("UPDATE N_SportsTestValue SET IsDisplay = 1 WHERE SchoolCode = {0} ");
+
+ var parameters = new List