feat: 完善运动记录与体测数据接口
AI运动站:按设备学校和学生学号关联学生、班级,返回课目编号与成绩值,并修正壹路训练有效次数的数值类型。 AI阳光跑:在分页查询与导出共用条件中排除零有效里程、零有效次数记录。 体测数据记录:补全年级与课目编号、姓名和测试时间,新增按当前筛选条件导出完整记录的 Excel 接口;800/1000 米成绩格式化为分秒。
This commit is contained in:
parent
cd7206ede5
commit
c4b01d2f53
@ -82,28 +82,44 @@ namespace VOL.Ai.Services
|
||||
from train in _dbContext.Set<YL_Train>().AsNoTracking()
|
||||
join device in _dbContext.Set<YL_Device>().AsNoTracking()
|
||||
on train.DeviceSerial equals device.SerialNumber
|
||||
join school in _dbContext.Set<S_School>().AsNoTracking()
|
||||
on device.OrgId equals (int?)school.Id into schoolGroup
|
||||
from school in schoolGroup.DefaultIfEmpty()
|
||||
join student in _dbContext.Set<S_Student>().AsNoTracking()
|
||||
on train.UserSerial equals student.StudentNo into studentGroup
|
||||
on new { StudentNo = train.UserSerial, SchoolCode = school.SchoolCode }
|
||||
equals new { student.StudentNo, student.SchoolCode } into studentGroup
|
||||
from student in studentGroup.DefaultIfEmpty()
|
||||
join studentClass in _dbContext.Set<S_Class>().AsNoTracking()
|
||||
on new { Id = student.ClassId, student.SchoolCode }
|
||||
equals new { studentClass.Id, studentClass.SchoolCode } into classGroup
|
||||
from studentClass in classGroup.DefaultIfEmpty()
|
||||
select new
|
||||
{
|
||||
train.Id,
|
||||
device.OrgId,
|
||||
StudentSchoolCode = student == null ? schoolCode : student.SchoolCode,
|
||||
DeviceSchoolCode = school.SchoolCode,
|
||||
train.CourseId,
|
||||
train.StartTime,
|
||||
train.EndTime,
|
||||
train.Score,
|
||||
train.StandardCounts,
|
||||
train.UnStandardCounts,
|
||||
train.TimeKeeping,
|
||||
train.Duration,
|
||||
train.Distance,
|
||||
train.UserSerial,
|
||||
StudentName = student == null ? train.UserSerial : student.StudentName,
|
||||
Sex = student == null ? (SexType?)null : student.Sex,
|
||||
ClassId = student == null ? 0 : student.ClassId,
|
||||
ClassName = student == null ? string.Empty : student.ClassName
|
||||
ClassName = studentClass == null || studentClass.ClassName == null || studentClass.ClassName == ""
|
||||
? (student == null ? string.Empty : student.ClassName)
|
||||
: (studentClass.GradeName ?? string.Empty) + studentClass.ClassName
|
||||
};
|
||||
|
||||
if (!isAdmin)
|
||||
{
|
||||
var currentSchoolId = schoolId.GetValueOrDefault();
|
||||
query = query.Where(x => x.OrgId == currentSchoolId && x.StudentSchoolCode == schoolCode);
|
||||
query = query.Where(x => x.OrgId == currentSchoolId && x.DeviceSchoolCode == schoolCode);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(studentName))
|
||||
@ -138,8 +154,15 @@ namespace VOL.Ai.Services
|
||||
Ind = (paramDto.PageIndex - 1) * paramDto.PageSize + index + 1,
|
||||
StudentName = x.StudentName,
|
||||
Sex = GetSexName(x.Sex),
|
||||
ClassName = x.ClassName,
|
||||
ClassName = string.IsNullOrWhiteSpace(x.ClassName) ? "未匹配班级" : x.ClassName,
|
||||
ProjectName = GetCourseName(x.CourseId),
|
||||
CourseId = x.CourseId,
|
||||
Score = x.Score,
|
||||
StandardCounts = x.StandardCounts,
|
||||
UnStandardCounts = x.UnStandardCounts,
|
||||
TimeKeeping = x.TimeKeeping,
|
||||
Duration = x.Duration,
|
||||
Distance = x.Distance,
|
||||
StartTime = x.StartTime,
|
||||
EndTime = x.EndTime
|
||||
})
|
||||
@ -157,7 +180,7 @@ namespace VOL.Ai.Services
|
||||
|
||||
private static string GetCourseName(int courseId)
|
||||
{
|
||||
return CourseNames.TryGetValue(courseId, out var name) ? name : courseId.ToString();
|
||||
return CourseNames.TryGetValue(courseId, out var name) ? name : $"待确认课目(编号{courseId})";
|
||||
}
|
||||
|
||||
private static SexType? GetSexType(string sex)
|
||||
|
||||
@ -1625,7 +1625,7 @@ namespace VOL.Business.Services
|
||||
select new StudentsTestDataModel()
|
||||
{
|
||||
Id = r.Id,
|
||||
GradeId = r.Id,
|
||||
GradeId = r.GradeId,
|
||||
GradeName = r.GradeName,
|
||||
StudentNo = r.StudentNo,
|
||||
StudentName = r.StudentName,
|
||||
@ -1641,6 +1641,7 @@ namespace VOL.Business.Services
|
||||
Value = r.Value,
|
||||
Rank = r.Rank,
|
||||
CategoryId = c.Id,
|
||||
CategoryValue = c.CategoryValue,
|
||||
Score = r.Score,
|
||||
Sex = r.Sex == SexType.Male ? "男" : "女",
|
||||
ScoreTime = r.ScoreTime
|
||||
@ -1697,9 +1698,10 @@ namespace VOL.Business.Services
|
||||
select new StudentsTestDataModel()
|
||||
{
|
||||
Id = r.Id,
|
||||
GradeId = r.Id,
|
||||
GradeId = r.GradeId,
|
||||
GradeName = r.GradeName,
|
||||
StudentNo = r.StudentNo,
|
||||
StudentName = r.StudentName,
|
||||
CategoryName = c.CategoryName,
|
||||
ClassId = r.ClassId,
|
||||
ClassName = r.ClassName,
|
||||
@ -1712,8 +1714,10 @@ namespace VOL.Business.Services
|
||||
Value = r.Value,
|
||||
Rank = r.Rank,
|
||||
CategoryId = c.Id,
|
||||
CategoryValue = c.CategoryValue,
|
||||
Score = r.Score,
|
||||
Sex = r.Sex == SexType.Male ? "男" : "女"
|
||||
Sex = r.Sex == SexType.Male ? "男" : "女",
|
||||
ScoreTime = r.ScoreTime
|
||||
};
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(paramDto.StudentNo))
|
||||
@ -1747,7 +1751,7 @@ namespace VOL.Business.Services
|
||||
}
|
||||
|
||||
|
||||
var list = await query.ToListAsync();
|
||||
var list = await query.OrderByDescending(x => x.ScoreTime).ThenByDescending(x => x.Id).ToListAsync();
|
||||
|
||||
return list;
|
||||
}
|
||||
@ -2090,4 +2094,4 @@ namespace VOL.Business.Services
|
||||
return scoreToAdditionalPoints[score];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,7 +69,11 @@ namespace VOL.Business.Services.SunshineRun
|
||||
|
||||
private static string BuildWhere(SunshineRunFilterParam param, string schoolId)
|
||||
{
|
||||
var conditions = new List<string> { "1 = 1" };
|
||||
var conditions = new List<string>
|
||||
{
|
||||
"ISNULL(r.EffectiveDistance, 0) > 0",
|
||||
"ISNULL(r.Times, 0) - ISNULL(r.InvalidTimes, 0) > 0"
|
||||
};
|
||||
if (schoolId != null)
|
||||
conditions.Add("r.OrgId = @OrgId");
|
||||
if (!string.IsNullOrWhiteSpace(param.StudentName))
|
||||
|
||||
@ -72,7 +72,7 @@ namespace VOL.Entity.DomainModels.YiLu
|
||||
/// <summary>
|
||||
/// 有效个数
|
||||
/// </summary>
|
||||
public int StandardCounts { get; set; }
|
||||
public double StandardCounts { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 不合格动作数
|
||||
|
||||
@ -32,6 +32,35 @@ namespace VOL.Model.Ai.Response
|
||||
/// </summary>
|
||||
public string ProjectName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 壹路课目编号
|
||||
/// </summary>
|
||||
public int CourseId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 统一成绩值
|
||||
/// </summary>
|
||||
public double? Score { get; set; }
|
||||
|
||||
public double StandardCounts { get; set; }
|
||||
|
||||
public int UnStandardCounts { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 有效时长(秒)
|
||||
/// </summary>
|
||||
public double? TimeKeeping { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 训练时长(秒)
|
||||
/// </summary>
|
||||
public int Duration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 距离(米)
|
||||
/// </summary>
|
||||
public double? Distance { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 运动开始时间
|
||||
/// </summary>
|
||||
|
||||
@ -39,6 +39,9 @@ namespace VOL.Model
|
||||
[Display(Name = "IgnoreColumnAttribute")]
|
||||
public int CategoryId { get; set; }
|
||||
|
||||
[Display(Name = "IgnoreColumnAttribute")]
|
||||
public int CategoryValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///年级名称
|
||||
/// </summary>
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace VOL.Model
|
||||
{
|
||||
public class SummaryOfGradesTestRecordExportModel
|
||||
{
|
||||
[Display(Name = "序号")]
|
||||
public int Index { get; set; }
|
||||
|
||||
[Display(Name = "年级-班级")]
|
||||
public string GradeAndClass { get; set; }
|
||||
|
||||
[Display(Name = "学生姓名")]
|
||||
public string StudentName { get; set; }
|
||||
|
||||
[Display(Name = "学生学号")]
|
||||
public string StudentNo { get; set; }
|
||||
|
||||
[Display(Name = "性别")]
|
||||
public string Sex { get; set; }
|
||||
|
||||
[Display(Name = "测试类别")]
|
||||
public string CategoryName { get; set; }
|
||||
|
||||
[Display(Name = "测试结果")]
|
||||
public string TestResult { get; set; }
|
||||
|
||||
[Display(Name = "得分")]
|
||||
public float Score { get; set; }
|
||||
|
||||
[Display(Name = "等级")]
|
||||
public string Rank { get; set; }
|
||||
|
||||
[Display(Name = "班级排名")]
|
||||
public int ClassRank { get; set; }
|
||||
|
||||
[Display(Name = "测试时间")]
|
||||
public string ScoreTime { get; set; }
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,8 @@ using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using VOL.Business.IServices;
|
||||
using VOL.Business.Services;
|
||||
@ -79,6 +81,57 @@ namespace VOL.WebApi.Controllers.Business
|
||||
return File(excelBytes, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", $"学生成绩{DateTime.Now.ToString("yyyyMMddHHmmss")}");
|
||||
}
|
||||
|
||||
[HttpGet(nameof(ExportSummaryOfGrades))]
|
||||
public async Task<ActionResult> ExportSummaryOfGrades(StudentsTestDataListParam paramDto)
|
||||
{
|
||||
var records = await _sportsTestResultService.GetStudentsTestDataList(paramDto);
|
||||
var rows = records.Select((row, index) => new SummaryOfGradesTestRecordExportModel
|
||||
{
|
||||
Index = index + 1,
|
||||
GradeAndClass = string.Join("-", new[] { row.GradeName, row.ClassName }
|
||||
.Where(x => !string.IsNullOrWhiteSpace(x))),
|
||||
StudentName = row.StudentName,
|
||||
StudentNo = row.StudentNo,
|
||||
Sex = row.Sex,
|
||||
CategoryName = row.CategoryName,
|
||||
TestResult = FormatTestResult(row),
|
||||
Score = row.Score,
|
||||
Rank = row.Rank,
|
||||
ClassRank = row.ClassRank,
|
||||
ScoreTime = row.ScoreTime.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture)
|
||||
}).ToList();
|
||||
var columns = new List<string>
|
||||
{
|
||||
nameof(SummaryOfGradesTestRecordExportModel.Index),
|
||||
nameof(SummaryOfGradesTestRecordExportModel.GradeAndClass),
|
||||
nameof(SummaryOfGradesTestRecordExportModel.StudentName),
|
||||
nameof(SummaryOfGradesTestRecordExportModel.StudentNo),
|
||||
nameof(SummaryOfGradesTestRecordExportModel.Sex),
|
||||
nameof(SummaryOfGradesTestRecordExportModel.CategoryName),
|
||||
nameof(SummaryOfGradesTestRecordExportModel.TestResult),
|
||||
nameof(SummaryOfGradesTestRecordExportModel.Score),
|
||||
nameof(SummaryOfGradesTestRecordExportModel.Rank),
|
||||
nameof(SummaryOfGradesTestRecordExportModel.ClassRank),
|
||||
nameof(SummaryOfGradesTestRecordExportModel.ScoreTime)
|
||||
};
|
||||
var bytes = Tool.ExportToExcel(
|
||||
new Dictionary<string, List<SummaryOfGradesTestRecordExportModel>> { ["体测数据记录"] = rows },
|
||||
columns, autoFitColumns: false);
|
||||
return File(bytes, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
$"体测数据记录{DateTime.Now:yyyyMMddHHmmss}.xlsx");
|
||||
}
|
||||
|
||||
private static string FormatTestResult(StudentsTestDataModel row)
|
||||
{
|
||||
if (row.CategoryValue != 10 && row.CategoryValue != 11)
|
||||
return row.Value.ToString("0.##", CultureInfo.InvariantCulture);
|
||||
|
||||
// Some historical imports contain millisecond values despite the seconds-based category unit.
|
||||
var seconds = row.Value >= 10000 ? row.Value / 1000d : row.Value;
|
||||
var totalSeconds = (int)Math.Round(Math.Max(0, seconds), MidpointRounding.AwayFromZero);
|
||||
return $"{totalSeconds / 60}分{totalSeconds % 60:D2}秒";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新增
|
||||
/// </summary>
|
||||
@ -115,4 +168,4 @@ namespace VOL.WebApi.Controllers.Business
|
||||
return Ok("更新成功");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user