2026-04-30 15:47:26 +08:00

391 lines
14 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 AutoMapper;
using Microsoft.EntityFrameworkCore;
using YD_WeChatApplet.Api.Entitys;
using YD_WeChatApplet.Api.SmartSportsEntitys;
using YD_WeChatApplet.Api.Utilities;
using YD_WeChatApplet.Commons.Dto;
using YD_WeChatApplet.Commons.Dto.HomeWork;
using YD_WeChatApplet.Commons.Dto.Patriarch;
using YD_WeChatApplet.Commons.Dto.Resource;
using YD_WeChatApplet.Commons.Dto.School;
using YD_WeChatApplet.Commons.Dto.SportsTest;
using YD_WeChatApplet.Commons.Dto.Teacher;
using YD_WeChatApplet.Commons.Enum;
using YD_WeChatApplet.Context;
using YD_WeChatApplet.Services;
namespace YD_WeChatApplet.Api.Services.Impl
{
/// <summary>
/// 家长端
/// </summary>
public class PatriarchService : IPatriarchService
{
public UserContext _userContext;
public SmartSportsContext _sportsContext;
private readonly IMapper _mapper;
public PatriarchService(UserContext userContext, SmartSportsContext sportsContext, IMapper mapper)
{
_userContext = userContext;
_sportsContext = sportsContext;
_mapper = mapper;
}
/// <summary>
/// 新建训练数据
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task AddExerciseData(AddExerciseDataDto dto)
{
var entity = _mapper.Map<WCA_ExerciseData>(dto);
entity.RoleId = UserLoginContext.Current.RoleId;
entity.UserId = UserLoginContext.Current.UserId;
entity.UserName = UserLoginContext.Current.UserName;
entity.CreateTime = DateTime.Now;
if (dto.HomeWorkId == 0)
{
await _userContext.AddAsync(entity);
await _userContext.SaveChangesAsync();
return;
}
var work = await _sportsContext.HomeWork.Where(x => x.Id == dto.HomeWorkId).Select(x => new
{
x.Id,
x.Amount,
x.GroupNumber
}).FirstAsync();
entity.Status = dto.GroupNumber >= work.GroupNumber ? 2 : 1;
var student = await _sportsContext.HomeWorkStudents.FirstAsync(x => x.HomeWorkId == dto.HomeWorkId && x.StudentNo == UserLoginContext.Current.UserNo);
student.WorkStatus = entity.Status;
if (entity.RoleId == 3)
{
entity.StudentNo = UserLoginContext.Current.UserNo;
entity.StudentName = UserLoginContext.Current.UserName;
}
student.Value = dto.WorkModeType == 1 ? dto.Amount : dto.Duration;
_sportsContext.HomeWorkStudents.Update(student);
await _sportsContext.SaveChangesAsync();
await _userContext.AddAsync(entity);
await _userContext.SaveChangesAsync();
}
/// <summary>
/// 作业记录
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
public async Task<PageDataDto<HomeWorkRecordByPatriarchDto>> HomeWorkRecordByPatriarch(PatriarchHomeWorkHistoryDto dto)
{
var userNo = UserLoginContext.Current.UserNo;
var currentTime = DateTime.Now;
var query = _sportsContext.HomeWorkStudents
.Join(_sportsContext.HomeWork, a => a.HomeWorkId, s => s.Id, (a, s) => new
{
s.Id,
a.StudentNo,
a.WorkStatus,
s.WorkName,
s.WorkTypeName,
s.GroupNumber,
s.StartTime,
s.EndTime
})
.Where(a => a.StudentNo == userNo);
switch (dto.WorkStatus)
{
case 1: // 未开始
query = query.Where(x => x.StartTime > currentTime);
break;
case 2: // 进行中
query = query.Where(x => x.StartTime <= currentTime && x.EndTime >= currentTime);
break;
case 3: // 已结束
query = query.Where(x => x.EndTime < currentTime);
break;
default:
break;
}
//query = dto.IsHistory
// ? query.Where(x => x.EndTime < currentTime)
// : query.Where(x => x.EndTime >= currentTime);
var totalCount = await query.CountAsync();
var list = await query
.Select(x => new HomeWorkRecordByPatriarchDto
{
Id = x.Id,
WorkName = x.WorkName,
WorkTypeName = x.WorkTypeName,
//WorkStatus = x.EndTime < currentTime ? 3 : (x.StartTime > currentTime ? 1 : 2),
WorkStatus = dto.WorkStatus,
GroupNumber = x.GroupNumber,
IsComplete = x.WorkStatus == 2,
StartTime = x.StartTime,
EndTime = x.EndTime
})
.OrderByDescending(x => x.EndTime)
.Skip((dto.PageIndex - 1) * dto.PageSize)
.Take(dto.PageSize)
.ToListAsync();
return new PageDataDto<HomeWorkRecordByPatriarchDto>
{
Total = totalCount,
Datas = list
};
}
/// <summary>
/// 作业详情
/// </summary>
/// <param name="homeWorkId"></param>
/// <returns></returns>
public async Task<PatriarchHomeWorkDetailsDto> HomeWorkDetailsByPatriarch(int homeWorkId)
{
var res = await _sportsContext.HomeWork.Where(x => x.Id == homeWorkId).Select(x => new PatriarchHomeWorkDetailsDto()
{
Id = x.Id,
WorkName = x.WorkName,
StartTime = x.StartTime,
EndTime = x.EndTime,
WorkText = x.WorkText,
WorkType = (int)x.WorkType,
WorkTypeName = x.WorkTypeName,
WorkModeType = x.WorkModeType,
WorkModeTypeName = x.WorkModeTypeName,
Amount = x.Amount,
Duration = x.Duration,
GroupNumber = x.GroupNumber,
IsRepeat = x.IsRepeat,
RepetitionPeriod = x.RepetitionPeriod,
WorkStatus = x.WorkStatus
}).FirstOrDefaultAsync();
return res;
}
/// <summary>
/// 学生报告
/// </summary>
/// <returns></returns>
public async Task<StudentReportDto> StudentReport(string? studentNo)
{
var res = new StudentReportDto();
// 若参数为空,则尝试从登录上下文获取当前用户编号
if (string.IsNullOrWhiteSpace(studentNo))
{
studentNo = UserLoginContext.Current.UserNo;
}
// 最终编号仍为空,则直接返回空结果
if (string.IsNullOrWhiteSpace(studentNo))
return res;
var student = await _sportsContext.Student.Where(x => x.StudentNo == studentNo).FirstOrDefaultAsync();
if (student == null)
return res;
var classInfo = await _sportsContext.Class.FirstOrDefaultAsync(x => x.Id == student.ClassId);
if (classInfo == null)
return res;
var categorys = new List<dynamic>
{
new
{
Id = 1,
CategoryValue = 1,
CategoryName = "BMI",
CategoryEnum = "BMI",
Weight = 0.15f
},
new
{
Id = 2,
CategoryValue = 2,
CategoryName = "肺活量",
CategoryEnum = "VitalCapacity",
Weight = 0.2f
},
new
{
Id = 4,
CategoryValue = 4,
CategoryName = "坐位体前屈",
CategoryEnum = "Sit_And_Reach",
Weight = 0.15f
},
new
{
Id = 5,
CategoryValue = 5,
CategoryName = "一分钟跳绳",
CategoryEnum = "OneMinuteJumpRope",
Weight = 0.2f
},
new
{
Id = 6,
CategoryValue = 6,
CategoryName = "一分钟仰卧起坐",
CategoryEnum = "One_Minute_Sit_Up",
Weight = 0.15f
},
new
{
Id = 8,
CategoryValue = 6,
CategoryName = "立定跳远",
CategoryEnum = "StandingLongJump",
Weight = 0.15f
}
};
var sportsTestResults = await _sportsContext.SportsTestValue.Where(x => x.IsDisplay && x.SchoolCode == student.SchoolCode).Select(x => new SportsTestValueModel()
{
StudentNo = x.StudentNo,
GradeId = x.GradeId,
Value = x.Value,
Score = x.Score,
Rank = x.Rank,
AdditionalScore = x.AdditionalScore,
CategoryValue = x.CategoryValue,
ScoreTime = x.ScoreTime
}).ToListAsync();
res.CategoryScoreList = new List<CategoryScoreDto>();
foreach (var item in categorys)
{
// ✅ 当前学生数据
var studentResults = sportsTestResults
.Where(x => x.CategoryValue == item.Id && x.StudentNo == studentNo)
.OrderByDescending(x => x.ScoreTime) // 倒序:最新在前
.ToList();
var lastResult = studentResults.FirstOrDefault();
var prevResult = studentResults.Skip(1).FirstOrDefault();
var maxScore = studentResults.Any()
? studentResults.Max(x => x.Value)
: 0;
//var classAvgScore = studentResults.Any()
// ? studentResults.Average(x => x.Value)
// : 0;
// 1. 获取每个学生最新的 ScoreTime
var latestRecords = sportsTestResults
.Where(x => x.CategoryValue == item.Id) // 先按指标过滤,提升效率
.GroupBy(x => x.StudentNo)
.Select(g => new
{
StudentNo = g.Key,
MaxScoreTime = g.Max(x => x.ScoreTime)
});
// 2. 关联原表,取得最新测试的那条记录(该指标的值)
var latestValues = from record in sportsTestResults
join latest in latestRecords
on new { record.StudentNo, record.ScoreTime }
equals new { latest.StudentNo, ScoreTime = latest.MaxScoreTime }
where record.CategoryValue == item.Id
select record.Value;
// 3. 计算平均值(如果没有数据则返回0)
var schoolAvgScore = latestValues.DefaultIfEmpty(0).Average();
// 🚀 趋势图(关键:反转集合)
var trendList = studentResults
.OrderBy(x => x.ScoreTime)
.ToList();
var trendChart = new ScoreTrendChartDataDto
{
AxisX = trendList.Select(x => x.ScoreTime.ToString("yyyy-MM-dd")).ToList(),
AxisY = trendList.Select(x => x.Value ?? 0f).ToList()
};
res.CategoryScoreList.Add(new CategoryScoreDto()
{
CategoryValue = item.CategoryValue,
Name = item.CategoryName,
Rank = lastResult?.Rank,
GradeId = lastResult.GradeId,
PrevScore = prevResult?.Score ?? 0,
LastScore = lastResult?.Score ?? 0,
MaxScore = (float)maxScore,
//ClassAvgScore = (float)classAvgScore,
SchoolAvgScore = (float)schoolAvgScore,
ScoreTrendChart = trendChart,
ImgUrl = $"{AppSettings.ALiYunOSS.CategoryImgUrl}{item.CategoryEnum}.png"
});
}
return res;
}
/// <summary>
/// 训练记录
/// </summary>
/// <returns></returns>
public async Task<PageDataDto<ExerciseRecordDto>> ExerciseRecord(PageDto dto)
{
var userId = UserLoginContext.Current.UserId;
var query = _userContext.ExerciseData.Where(x => x.UserId == userId);
var totalCount = await query.CountAsync();
var list = await query
.Select(x => new ExerciseRecordDto
{
Id = x.Id,
WorkTypeName = x.WorkTypeName,
WorkModeTypeName = x.WorkModeTypeName,
StartTime = x.StartTime,
EndTime = x.CreateTime,
GroupNumber = x.GroupNumber,
Amount = x.Amount ?? 0,
Duration = x.Duration ?? 0,
Calorie = x.Calorie ?? 0
})
.OrderByDescending(x => x.EndTime)
.Skip((dto.PageIndex - 1) * dto.PageSize)
.Take(dto.PageSize)
.ToListAsync();
return new PageDataDto<ExerciseRecordDto>
{
Total = totalCount,
Datas = list
};
}
}
}