YD_SmartSports.Api/VOL.Ai/Services/AiSportsStationService.cs
ltx 0eb9c90c31 feat: 补齐壹路AI运动站全部课目映射
根据提供的六张课目编号截图,将 CourseNames 补齐为 63 个项目,覆盖俯卧撑、仰卧起坐、跑步、球类、互动项目和体测项目。未知编号仍保留待确认课目的兜底显示,不修改实体数据类型、表结构或数据。

将项目名称筛选改为精确匹配,避免选择深蹲时混入深蹲跳等名称相近的记录。

验证:后端 Debug 构建成功(0 错误);与前端下拉选项核对均为 63 个项目。
2026-10-22 11:53:34 +08:00

249 lines
9.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Microsoft.EntityFrameworkCore;
using VOL.Ai.IServices;
using VOL.Core.EFDbContext;
using VOL.Core.Extensions.AutofacManager;
using VOL.Core.ManageUser;
using VOL.Entity.DomainModels;
using VOL.Entity.DomainModels.YiLu;
using VOL.Entity.Enum;
using VOL.Model;
using VOL.Model.Ai.Request;
using VOL.Model.Ai.Response;
namespace VOL.Ai.Services
{
public class AiSportsStationService : IAiSportsStationService, IDependency
{
private readonly VOLContext _dbContext;
private static readonly Dictionary<int, string> CourseNames = new()
{
{ 1, "俯卧撑" },
{ 2, "仰卧起坐" },
{ 3, "引体向上" },
{ 7, "立定跳远" },
{ 8, "跳绳" },
{ 9, "开合跳" },
{ 10, "高抬腿" },
{ 11, "深蹲" },
{ 12, "50米跑" },
{ 13, "100米跑" },
{ 14, "800米跑" },
{ 15, "1000米跑" },
{ 16, "3000米跑" },
{ 20, "50米×8" },
{ 21, "篮球绕杆" },
{ 22, "足球绕杆" },
{ 23, "坐位体前屈" },
{ 24, "单脚跳" },
{ 25, "动态臀桥" },
{ 26, "左右跳" },
{ 27, "打地鼠" },
{ 28, "七上八下" },
{ 29, "消灭蚊子" },
{ 30, "石头剪刀布" },
{ 31, "变脸" },
{ 32, "打钉子" },
{ 33, "击鼓传花" },
{ 34, "踢足球" },
{ 35, "手脚并用" },
{ 36, "踢毽子" },
{ 37, "风火轮" },
{ 38, "顺序摸数字" },
{ 39, "俄罗斯方块" },
{ 40, "诗词满腹" },
{ 41, "单词大王" },
{ 42, "数学王者" },
{ 43, "音乐大师" },
{ 44, "历史小生" },
{ 45, "科学达人" },
{ 46, "纵跳摸高" },
{ 47, "半蹲跳" },
{ 48, "深蹲跳" },
{ 49, "侧向蹲起" },
{ 50, "篮球单手运球" },
{ 51, "篮球双手交替运球" },
{ 52, "身体绕球" },
{ 53, "足球踩球" },
{ 54, "足球颠球" },
{ 55, "足球踩单车" },
{ 56, "排球垫球" },
{ 57, "排球自传挑战" },
{ 60, "实心球" },
{ 61, "阳光跑" },
{ 62, "健身长拳" },
{ 63, "200米跑" },
{ 64, "400米×4" },
{ 65, "400米跑" },
{ 66, "6分钟跑" },
{ 67, "9分钟跑" },
{ 68, "1500米跑" },
{ 69, "60米跑" },
{ 1001, "体重系数(BMI)" },
{ 1002, "肺活量" }
};
public AiSportsStationService(VOLContext dbContext)
{
_dbContext = dbContext;
}
public async Task<PageDataDto<AiSportsStationDto>> GetAiSportsStationList(AiSportsStationListRequest paramDto)
{
paramDto.PageIndex = paramDto.PageIndex <= 0 ? 1 : paramDto.PageIndex;
paramDto.PageSize = paramDto.PageSize <= 0 ? 10 : paramDto.PageSize;
var currentUser = UserContext.Current;
var isAdmin = currentUser?.IsSuperAdmin == true
|| string.Equals(currentUser?.UserName, "admin", StringComparison.OrdinalIgnoreCase);
var schoolCode = currentUser?.TenantId;
int? schoolId = null;
if (!isAdmin)
{
schoolId = await _dbContext.Set<S_School>()
.Where(x => x.SchoolCode == schoolCode)
.Select(x => (int?)x.Id)
.FirstOrDefaultAsync();
if (schoolId == null)
{
return new PageDataDto<AiSportsStationDto>
{
Total = 0,
TotalPages = 0,
PageIndex = paramDto.PageIndex,
PageSize = paramDto.PageSize,
Datas = new List<AiSportsStationDto>()
};
}
}
var studentName = paramDto.StudentName?.Trim();
var projectName = paramDto.ProjectName?.Trim();
var sex = GetSexType(paramDto.Sex);
var query =
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 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,
DeviceSchoolCode = school.SchoolCode,
train.CourseId,
train.StartTime,
train.EndTime,
train.Score,
// Cast in SQL so int and float columns both materialize as the original int type.
StandardCounts = Convert.ToInt32(Convert.ToDouble(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 = 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.DeviceSchoolCode == schoolCode);
}
if (!string.IsNullOrWhiteSpace(studentName))
query = query.Where(x => x.StudentName.Contains(studentName));
if (sex.HasValue)
query = query.Where(x => x.Sex == sex.Value);
if (paramDto.ClassId > 0)
query = query.Where(x => x.ClassId == paramDto.ClassId);
if (paramDto.StartTime.HasValue)
query = query.Where(x => x.StartTime >= paramDto.StartTime.Value);
if (paramDto.EndTime.HasValue)
query = query.Where(x => x.StartTime <= paramDto.EndTime.Value);
var rows = await query
.OrderByDescending(x => x.StartTime)
.ThenByDescending(x => x.Id)
.ToListAsync();
if (!string.IsNullOrWhiteSpace(projectName))
rows = rows.Where(x => GetCourseName(x.CourseId) == projectName).ToList();
var total = rows.Count;
var datas = rows
.Skip((paramDto.PageIndex - 1) * paramDto.PageSize)
.Take(paramDto.PageSize)
.Select((x, index) => new AiSportsStationDto
{
Ind = (paramDto.PageIndex - 1) * paramDto.PageSize + index + 1,
StudentName = x.StudentName,
Sex = GetSexName(x.Sex),
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
})
.ToList();
return new PageDataDto<AiSportsStationDto>
{
Total = total,
TotalPages = (int)Math.Ceiling(total / (double)paramDto.PageSize),
PageIndex = paramDto.PageIndex,
PageSize = paramDto.PageSize,
Datas = datas
};
}
private static string GetCourseName(int courseId)
{
return CourseNames.TryGetValue(courseId, out var name) ? name : $"待确认课目(编号{courseId})";
}
private static SexType? GetSexType(string sex)
{
return sex switch
{
"男" => SexType.Male,
"女" => SexType.Female,
_ => null
};
}
private static string GetSexName(SexType? sex)
{
if (sex == null) return string.Empty;
return sex == SexType.Male ? "男" : "女";
}
}
}