2025-06-06 16:55:14 +08:00

665 lines
30 KiB
C#

using AutoMapper;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.Extensions.DependencyInjection;
using Quartz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using VOL.Business.IRepositories;
using VOL.Business.IServices;
using VOL.Business.IServices.Norm;
using VOL.Business.Repositories;
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.Enum;
using VOL.Model;
using VOL.Model.Ai;
using VOL.Model.Norm.Request;
using VOL.Model.Norm.Response;
using VOL.Model.School.Response;
using VOL.System.IRepositories;
using VOL.System.Repositories;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
namespace VOL.Business.Services.Norm
{
public class G_ActivitiesService : IG_ActivitiesService, IDependency
{
#region
private readonly IMapper _mapper;
private readonly IG_ActivitiesRepository _activitiesRepository;
private readonly ICacheQueryService _cacheQueryService;
private readonly IN_SportsTestResultRepository _sportsTestResultRepository;
[ActivatorUtilitiesConstructor]
public G_ActivitiesService(IMapper mapper,
IG_ActivitiesRepository activitiesRepository,
IN_SportsTestResultRepository sportsTestResultRepository,
ICacheQueryService cacheQueryService)
{
_mapper = mapper;
_activitiesRepository = activitiesRepository;
_sportsTestResultRepository = sportsTestResultRepository;
_cacheQueryService = cacheQueryService;
}
#endregion
public async Task<PageDataDto<ActivitiesListModel>> GetActivitiesPageList(ActivitiesPageListParam paramDto)
{
var res = new PageDataDto<ActivitiesListModel>();
var query = from s in _activitiesRepository.DbContext.Set<G_Activities>()
where s.SchoolCode.Equals(UserContext.Current.TenantId)
select new ActivitiesListModel()
{
Id = s.Id,
ActivitiesName = s.ActivitiesName,
CategoryId = s.CategoryId,
CategoryName = s.CategoryName,
EndDate = s.EndDate,
StartDate = s.StartDate,
ActivitiesStatus = s.ActivitiesStatus,
ActivitiesStatusName = s.ActivitiesStatus.Description(),
ImagePath = s.ImagePath,
ActivitiesGradeClassList = s.EntryStudents
.GroupBy(x => new { x.GradeId, x.ClassId })
.OrderBy(g => g.Key.GradeId)
.ThenBy(g => g.Key.ClassId)
.Select(g => new ActivitiesGradeClassModel()
{
ClassName = g.First().ClassName,
GradeName = g.First().GradeName
})
.ToList()
};
if (!string.IsNullOrWhiteSpace(paramDto.ActivitiesName))
{
query = query.Where(x => x.ActivitiesName.Contains(paramDto.ActivitiesName));
}
if (paramDto.ActivitiesStatus > 0)
{
query = query.Where(x => x.ActivitiesStatus == paramDto.ActivitiesStatus);
}
if (paramDto.CategoryId > 0)
{
query = query.Where(x => x.CategoryId == paramDto.CategoryId);
}
if (paramDto.StartDate.HasValue)
{
DateTime detectionDate = paramDto.StartDate.Value.Date;
query = query.Where(x => x.StartDate.HasValue && x.StartDate.Value.Date >= detectionDate);
}
if (paramDto.EndDate.HasValue)
{
DateTime detectionDate = paramDto.EndDate.Value.Date;
query = query.Where(x => x.EndDate.HasValue && x.EndDate.Value.Date < detectionDate);
}
res.Total = await query.CountAsync();
var list = await query
.OrderByDescending(x => x.Id)
.Skip((paramDto.PageIndex - 1) * paramDto.PageSize)
.Take(paramDto.PageSize)
.ToListAsync();
res.Datas = list;
return res;
}
public async Task<List<ActivitiesListModel>> GetActivitiesList(ActivitiesExportParam paramDto)
{
var query = from s in _activitiesRepository.DbContext.Set<G_Activities>()
where s.SchoolCode.Equals(UserContext.Current.TenantId)
select new ActivitiesListModel()
{
Id = s.Id,
ActivitiesName = s.ActivitiesName,
CategoryId = s.CategoryId,
CategoryName = s.CategoryName,
EndDate = s.EndDate,
StartDate = s.StartDate,
ActivitiesStatus = s.ActivitiesStatus,
ActivitiesStatusName = s.ActivitiesStatus.GetDescription(),
ImagePath = s.ImagePath
};
if (!string.IsNullOrWhiteSpace(paramDto.ActivitiesName))
{
query = query.Where(x => x.ActivitiesName.Contains(paramDto.ActivitiesName));
}
if (paramDto.ActivitiesStatus > 0)
{
query = query.Where(x => x.ActivitiesStatus.Equals(paramDto.ActivitiesStatus.GetDescription()));
}
if (paramDto.StartDate.HasValue)
{
DateTime detectionDate = paramDto.StartDate.Value.Date;
query = query.Where(x => x.StartDate.HasValue && x.StartDate.Value.Date >= detectionDate);
}
if (paramDto.EndDate.HasValue)
{
DateTime detectionDate = paramDto.EndDate.Value.Date;
query = query.Where(x => x.EndDate.HasValue && x.EndDate.Value.Date < detectionDate);
}
var list = await query.OrderByDescending(x => x.Id).ToListAsync();
return list;
}
public async Task<List<ActivitiesListNameModel>> GetActivitiesNameList()
{
var list = await _activitiesRepository.FindAsIQueryable(x => x.ActivitiesStatus == ActivitiesStatus.NotStarted).Select(x => new ActivitiesListNameModel()
{
Id = x.Id,
ActivitiesName = x.ActivitiesName
}).ToListAsync();
return list;
}
public List<ActivitiesCategoryModel> GetActivitiesCategoryList()
{
var res = new List<ActivitiesCategoryModel>()
{
/*
new ActivitiesCategoryModel()
{
SportsTestType = SportsTestDataType.TrainingData,
CategorId = (int)TrainingItemType.Coordinate,
CategoryName=TrainingItemType.Coordinate.GetDisplayName()
},
new ActivitiesCategoryModel()
{
SportsTestType = SportsTestDataType.SportsTestData,
CategorId = (int)SportsTestItemType.StandingLongJump,
CategoryName=SportsTestItemType.StandingLongJump.GetDisplayName()
},
new ActivitiesCategoryModel()
{
SportsTestType = SportsTestDataType.SportsTestData,
CategorId = (int)SportsTestItemType.Sit_And_Reach,
CategoryName=SportsTestItemType.Sit_And_Reach.GetDisplayName()
},
new ActivitiesCategoryModel()
{
SportsTestType = SportsTestDataType.SportsTestData,
CategorId = (int)SportsTestItemType.Pull_Up,
CategoryName=SportsTestItemType.Pull_Up.GetDisplayName()
},
*/
new ActivitiesCategoryModel()
{
SportsTestType = SportsTestDataType.TrainingData,
CategorId = (int)TrainingItemType.JumpingJack,
CategoryName=TrainingItemType.JumpingJack.GetDisplayName()
},
new ActivitiesCategoryModel()
{
SportsTestType = SportsTestDataType.TrainingData,
CategorId = (int)TrainingItemType.JumpSquat,
CategoryName=TrainingItemType.JumpSquat.GetDisplayName()
},
new ActivitiesCategoryModel()
{
SportsTestType = SportsTestDataType.TrainingData,
CategorId = (int)TrainingItemType.HighKnee,
CategoryName=TrainingItemType.HighKnee.GetDisplayName()
},
new ActivitiesCategoryModel()
{
SportsTestType = SportsTestDataType.TrainingData,
CategorId = (int)TrainingItemType.KneeDrivePalmarPalpation,
CategoryName=TrainingItemType.KneeDrivePalmarPalpation.GetDisplayName()
}
/*
new ActivitiesCategoryModel()
{
SportsTestType = SportsTestDataType.TrainingData,
CategorId = (int)TrainingItemType.CrossQuadrantJump,
CategoryName=TrainingItemType.CrossQuadrantJump.GetDisplayName()
}*/
};
return res;
}
public async Task<int> AddActivities(ActivitiesDetailsParam paramDto)
{
if (paramDto == null)
throw new ArgumentNullException($"{nameof(paramDto)}参数为空");
var entitys = new G_Activities()
{
ActivitiesName = paramDto.ActivitiesName,
ActivitiesStatus = ActivitiesStatus.NotStarted,
SportsTestDataType = paramDto.SportsTestDataType,
CategoryId = paramDto.CategoryId,
CategoryName = paramDto.CategoryName,
StartDate = paramDto.StartDate,
EndDate = paramDto.EndDate,
ImagePath = paramDto.ImagePath,
ParticipantType = paramDto.ParticipantType,
SchoolCode = UserContext.Current.TenantId,
Creator = UserContext.Current.UserId,
CreateDate = DateTime.Now
};
// 全部学生
if (entitys.ParticipantType == ParticipantType.AllStudents)
{
var entryStudent = from s in _activitiesRepository.DbContext.Set<S_Student>()
join c in _activitiesRepository.DbContext.Set<S_Class>() on s.ClassId equals c.Id into sclasss
from sclass in sclasss.DefaultIfEmpty()
where s.SchoolCode.Equals(UserContext.Current.TenantId)
select new G_EntryStudent()
{
SchoolCode = s.SchoolCode,
GradeId = sclass != null ? sclass.GradeId : 0,
GradeName = sclass != null ? sclass.GradeName : "",
ClassId = sclass != null ? sclass.Id : 0,
ClassName = sclass != null ? sclass.ClassName : "",
StudentNo = s.StudentNo,
StudentName = s.StudentName,
Sex = s.Sex,
Age = s.Age,
Photo = s.Photo
};
entitys.EntryStudents = await entryStudent.ToListAsync();
}
// 自定义学生
if (entitys.ParticipantType == ParticipantType.CustomStudent)
{
var studentNoList = paramDto.GradeClassStudentList.SelectMany(c => c.EntryStudentNoList).ToList();
var entryStudent = from s in _activitiesRepository.DbContext.Set<S_Student>()
join c in _activitiesRepository.DbContext.Set<S_Class>() on s.ClassId equals c.Id into sclasss
from sclass in sclasss.DefaultIfEmpty()
where s.SchoolCode.Equals(UserContext.Current.TenantId) && studentNoList.Contains(s.StudentNo)
select new G_EntryStudent()
{
SchoolCode = s.SchoolCode,
GradeId = sclass != null ? sclass.GradeId : 0,
GradeName = sclass != null ? sclass.GradeName : "",
ClassId = sclass != null ? sclass.Id : 0,
ClassName = sclass != null ? sclass.ClassName : "",
StudentNo = s.StudentNo,
StudentName = s.StudentName,
Sex = s.Sex,
Age = s.Age,
Photo = s.Photo
};
entitys.EntryStudents = await entryStudent.ToListAsync();
}
await _activitiesRepository.AddAsync(entitys);
await _activitiesRepository.SaveChangesAsync();
return entitys.Id;
}
public async Task ModifyActivities(ActivitiesDetailsParam paramDto)
{
if (paramDto == null || paramDto.Id == 0)
throw new ArgumentNullException($"参数为空");
var model = await _activitiesRepository.FindAsyncFirst(x => x.Id == paramDto.Id);
if (model == null)
throw new ArgumentNullException($"未找到要更新的数据");
if (model.ActivitiesStatus != ActivitiesStatus.NotStarted)
throw new ArgumentNullException($"已开始无法修改");
model.ActivitiesName = paramDto.ActivitiesName;
model.SportsTestDataType = paramDto.SportsTestDataType;
model.CategoryName = paramDto.CategoryName;
model.CategoryId = paramDto.CategoryId;
model.ActivitiesStatus = ActivitiesStatus.NotStarted;
model.StartDate = paramDto.StartDate;
model.EndDate = paramDto.EndDate;
model.EndDate = paramDto.EndDate;
model.ImagePath = paramDto.ImagePath;
model.ParticipantType = paramDto.ParticipantType;
model.Modifier = UserContext.Current.UserId;
model.ModifyDate = DateTime.Now;
await this.ModifyActivitiesEntryStudent(paramDto);
_activitiesRepository.Update(model);
await _activitiesRepository.SaveChangesAsync();
}
public async Task ModifyActivitiesStatus(int id, ActivitiesStatus status)
{
var model = await _activitiesRepository.FindAsyncFirst(x => x.Id == id);
if (model == null)
throw new ArgumentNullException($"未找到要更新的数据");
model.ActivitiesStatus = status;
model.ModifyDate = DateTime.Now;
_activitiesRepository.Update(model);
await _activitiesRepository.SaveChangesAsync();
}
public async Task ModifyActivitiesEntryStudent(ActivitiesDetailsParam paramDto)
{
var deleteEntryStudents = await this._activitiesRepository.FindAsync<G_EntryStudent>(c => c.SchoolCode == UserContext.Current.TenantId && c.ActivitiesId == paramDto.Id);
foreach (var item in deleteEntryStudents)
{
_activitiesRepository.Delete<G_EntryStudent>(item);
}
var entryStudents = new List<G_EntryStudent>();
// 全部学生
if (paramDto.ParticipantType == ParticipantType.AllStudents)
{
var entryStudent = from s in _activitiesRepository.DbContext.Set<S_Student>()
join c in _activitiesRepository.DbContext.Set<S_Class>() on s.ClassId equals c.Id into sclasss
from sclass in sclasss.DefaultIfEmpty()
where s.SchoolCode.Equals(UserContext.Current.TenantId)
select new G_EntryStudent()
{
ActivitiesId = paramDto.Id,
SchoolCode = s.SchoolCode,
GradeId = sclass.GradeId,
GradeName = sclass.GradeName,
ClassId = sclass.Id,
ClassName = sclass.ClassName,
StudentNo = s.StudentNo,
StudentName = s.StudentName,
Sex = s.Sex,
Age = s.Age,
Photo = s.Photo
};
entryStudents = await entryStudent.ToListAsync();
}
// 自定义学生
if (paramDto.ParticipantType == ParticipantType.CustomStudent)
{
var studentNoList = paramDto.GradeClassStudentList.SelectMany(c => c.EntryStudentNoList).ToList();
var entryStudent = from s in _activitiesRepository.DbContext.Set<S_Student>()
join c in _activitiesRepository.DbContext.Set<S_Class>() on s.ClassId equals c.Id into sclasss
from sclass in sclasss.DefaultIfEmpty()
where s.SchoolCode.Equals(UserContext.Current.TenantId) && studentNoList.Contains(s.StudentNo)
select new G_EntryStudent()
{
ActivitiesId = paramDto.Id,
SchoolCode = s.SchoolCode,
GradeId = sclass.GradeId,
GradeName = sclass.GradeName,
ClassId = sclass.Id,
ClassName = sclass.ClassName,
StudentNo = s.StudentNo,
StudentName = s.StudentName,
Sex = s.Sex,
Age = s.Age,
Photo = s.Photo
};
entryStudents = await entryStudent.ToListAsync();
}
_activitiesRepository.AddRange(entryStudents);
}
/// <summary>
/// 上传活动照片
/// </summary>
public string UploadActivitiesImage(IFormFile file)
{
var url = ALiYunOss.Upload(file, $"Upload/{UserContext.Current.TenantId}/Activities/", file.FileName, true);
return url;
}
public async Task DeleteActivities(List<int> Ids)
{
var model = await _activitiesRepository.FindAsync(x => Ids.Contains(x.Id));
if (model == null)
throw new ArgumentNullException($"未找到删除的数据");
_activitiesRepository.DbContext.RemoveRange(model);
await _activitiesRepository.SaveChangesAsync();
}
public async Task<ActivitiesDetailsModel> GetActivitiesDetails(int id)
{
if (id <= 0)
{
throw new ArgumentNullException("请求参数错误");
}
var model = await _activitiesRepository.FindAsyncFirst(x => x.Id == id);
if (model == null)
{
throw new ArgumentNullException("未找到数据");
}
var entryStudents = await this._activitiesRepository.FindAsync<G_EntryStudent>(c => c.SchoolCode == UserContext.Current.TenantId && c.ActivitiesId == id);
var classEntitys = await this._activitiesRepository.FindAsync<S_Class>(c => c.SchoolCode == UserContext.Current.TenantId);
var classStudentCounts = await _activitiesRepository.DbContext.Set<S_Student>()
.Where(s => s.SchoolCode == UserContext.Current.TenantId)
.GroupBy(s => s.ClassId)
.Select(g => new { ClassId = g.Key, Total = g.Count() })
.ToDictionaryAsync(x => x.ClassId, x => x.Total);
var result = new ActivitiesDetailsModel()
{
Id = model.Id,
EndDate = model.EndDate,
StartDate = model.StartDate,
ActivitiesName = model.ActivitiesName,
ActivitiesStatus = model.ActivitiesStatus,
CategoryId = model.CategoryId,
CategoryName = model.CategoryName,
ImagePath = model.ImagePath,
ParticipantType = model.ParticipantType,
GradeClassStudentList = classEntitys
.OrderBy(c => c.GradeId)
.ThenBy(c => c.Id)
.Select(c =>
{
// 获取当前班级参与人数
var participateCount = entryStudents.Count(d => d.ClassId == c.Id && d.GradeId == c.GradeId);
// 获取当前班级总人数
var totalStudents = classStudentCounts.GetValueOrDefault(c.Id, 0);
return new ActivitiesGradeClassDetailsModel()
{
ClassId = c.Id,
GradeId = c.GradeId,
ClassName = c.ClassName,
GradeName = c.GradeName,
IsAllParticipate = totalStudents > 0 && participateCount == totalStudents, // 判断是否全参与
IsParticipate = participateCount > 0, // 简化的参与判断
NumberParticipate = participateCount
};
})
.ToList()
};
return result;
}
/// <summary>
/// 获取学生详情
/// </summary>
/// <param name="classId"></param>
/// <returns></returns>
public async Task<List<ActivitiesStudentDetailsModel>> GetActivitiesStudentDetails(int classId, int activitiesId)
{
var entryStudentEntitys = await this._activitiesRepository.FindAsync<G_EntryStudent>(c => c.SchoolCode == UserContext.Current.TenantId && c.ClassId == classId && c.Activities.Id == activitiesId);
var studentEntitys = await this._activitiesRepository.FindAsync<S_Student>(c => c.SchoolCode == UserContext.Current.TenantId && c.ClassId == classId && !entryStudentEntitys.Select(d => d.StudentNo).Contains(c.StudentNo));
var combinedList = entryStudentEntitys.Select(c => new ActivitiesStudentDetailsModel()
{
IsParticipate = true,
StudentNo = c.StudentNo,
StudentName = c.StudentName,
Sex = c.Sex,
Age = c.Age,
Photo = c.Photo
})
.Concat(
studentEntitys.Select(c => new ActivitiesStudentDetailsModel()
{
IsParticipate = false,
StudentNo = c.StudentNo,
StudentName = c.StudentName,
Sex = c.Sex,
Age = c.Age,
Photo = c.Photo
})
)
.OrderBy(c => c.Age)
.ToList();
return combinedList;
}
/// <summary>
/// 获取赛事统计列表
/// </summary>
/// <param name="paramDto"></param>
/// <returns></returns>
public async Task<PageDataDto<ActivitiesStatisticsModel>> GetActivitiesStatisticsPageList(ActivitiesStatisticsPageListParam paramDto)
{
var res = new PageDataDto<ActivitiesStatisticsModel>();
var query = from s in _activitiesRepository.DbContext.Set<G_Activities>()
where s.SchoolCode.Equals(UserContext.Current.TenantId)
select new ActivitiesStatisticsModel
{
Id = s.Id,
ActivitiesName = s.ActivitiesName,
CategoryId = s.CategoryId,
CategoryName = s.CategoryName,
EndDate = s.EndDate,
StartDate = s.StartDate,
ActivitiesStatus = s.ActivitiesStatus,
ActivitiesStatusName = s.ActivitiesStatus.GetDescription(),
ImagePath = s.ImagePath,
ParticipantsCount = s.EntryStudents.Count()
};
if (!string.IsNullOrWhiteSpace(paramDto.ActivitiesName))
{
query = query.Where(x => x.ActivitiesName.Equals(paramDto.ActivitiesName));
}
if (paramDto.CategoryId > 0)
{
query = query.Where(x => x.CategoryId == paramDto.CategoryId);
}
if (paramDto.StartDate.HasValue)
{
DateTime detectionDate = paramDto.StartDate.Value.Date;
query = query.Where(x => x.StartDate.HasValue && x.StartDate.Value.Date >= detectionDate);
}
if (paramDto.EndDate.HasValue)
{
DateTime detectionDate = paramDto.EndDate.Value.Date;
query = query.Where(x => x.EndDate.HasValue && x.EndDate.Value.Date < detectionDate);
}
res.Total = await query.CountAsync();
var list = await query
.OrderByDescending(x => x.Id)
.Skip((paramDto.PageIndex - 1) * paramDto.PageSize)
.Take(paramDto.PageSize)
.ToListAsync();
var sportsTestData = _sportsTestResultRepository.DbContext.Set<Ai_SportsTestData>()
.Where(at => at.ActivitiesId != null && at.RankEnum != AchievementRank.Fail)
.ToList();
foreach (var item in list)
{
item.CompletedCount = sportsTestData
.Where(at => at.ActivitiesId == item.Id)
.Count();
}
res.Datas = list;
return res;
}
/// <summary>
/// 赛事统计详情
/// </summary>
/// <returns></returns>
public async Task<List<ActivitiesStatisticsDetailsModel>> GetActivitiesStatisticsDetails(ActivitiesStatisticsDetailsParam paramDto)
{
var entryStudents = await this._activitiesRepository.FindAsync<G_EntryStudent>(c => c.SchoolCode == UserContext.Current.TenantId && c.ActivitiesId == paramDto.ActivitiesId);
var query = from st in _activitiesRepository.DbContext.Set<Ai_SportsTestData>()
join s in _activitiesRepository.DbContext.Set<S_Student>() on st.StudentNo equals s.StudentNo
where st.SchoolCode.Equals(UserContext.Current.TenantId)
&& st.ActivitiesId.Equals(paramDto.ActivitiesId)
&& st.TrainingModule == Ai_TrainingModuleEnum.Arena
&& (
(paramDto.ScoreStatus == 1 && st.RankEnum != AchievementRank.Fail) ||
(paramDto.ScoreStatus == 2 && st.RankEnum == AchievementRank.Fail)
)
select new ActivitiesStatisticsDetailsModel
{
GradeAndClass = $"{st.GradeName}-{st.ClassName}",
StudentName = s.StudentName,
Sex = s.Sex == SexType.Male ? "男" : "女",
Age = s.Age,
Score = st.Score
};
var list = await query.ToListAsync();
if (paramDto.ScoreStatus == 2)
{
var uncompletedStudents = entryStudents.Where(es => !list.Any(l => l.StudentName == es.StudentName))
.Select(es => new ActivitiesStatisticsDetailsModel
{
GradeAndClass = $"{es.GradeName}-{es.ClassName}",
StudentName = es.StudentName,
Sex = es.Sex == SexType.Male ? "男" : "女",
Age = es.Age,
Score = 0
}).ToList();
list.AddRange(uncompletedStudents);
}
return list.OrderBy(c => c.Score)
.Select((c, index) => { c.Ranking = index + 1; return c; })
.ToList();
}
}
}