using Learn.Archives.API.Controllers.Dto; using Learn.Archives.API.Expand; using Learn.Archives.Core.Common; using Learn.Archives.Core.Model; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using MiniExcelLibs; using System.Diagnostics; using System.Security.Claims; using UserCenter.Model; using UserCenter.Model.Common; using UserCenter.Model.Enum; namespace Learn.Archives.API.Controllers { /// /// 年级控制器 /// public class ExamClassInfoController : BackController { readonly Repository baseService; readonly Repository examService; readonly Repository schoolService; readonly Repository examUserInfoService; readonly LiveUserInfo userInfo; readonly IHttpContextAccessor accessor; public ExamClassInfoController(Repository baseService, LiveUserInfo userInfo, IHttpContextAccessor httpContext, Repository examUserInfoService, Repository examService, Repository schoolService) : base(baseService) { this.baseService = baseService; this.userInfo = userInfo; this.accessor = httpContext; this.examUserInfoService = examUserInfoService; this.examService = examService; this.schoolService = schoolService; } [NonAction] private Dictionary? ImportExamInfoSubjectDic(ImportExamInfo info) { return new Dictionary() { { SubjectEnum.语文, info.语文}, { SubjectEnum.数学, info.数学}, { SubjectEnum.英语, info.英语}, { SubjectEnum.物理, info.物理}, { SubjectEnum.化学, info.化学}, { SubjectEnum.生物, info.生物}, { SubjectEnum.政治, info.政治}, { SubjectEnum.历史, info.历史}, { SubjectEnum.地理, info.地理}, }; } /// /// 导入考试信息 /// /// /// [HttpPost, ResultIgnore] [HttpLogEnable] public async Task Import(ImportDto dto) { var exam = await examService.GetByIdAsync(dto.eId); var fl = dto.File!=null? dto .File: accessor.HttpContext?.Request.Form.Files[0]; if (exam == null || fl == null) Oh.ModelError("为传入有效的数据"); if (!Path.GetExtension(fl.FileName).Equals(".xlsx", StringComparison.OrdinalIgnoreCase)) Oh.ModelError("请选择导入文件为.xlsx的后缀名!"); //分析excel IEnumerable dataList; using var stream = new MemoryStream(); { await fl.CopyToAsync(stream); dataList = stream.Query() .Where(s => string.IsNullOrEmpty(s.Student)); } if (dataList == null || dataList.Count() == 0) Oh.ModelError("导入失败:无有效数据"); //处理数据 var errorExcelInfo = new List(); var insertUserInfo = new List(); var insertClassInfo = new List(); var db = schoolService.Context; foreach (var schoolArr in dataList.GroupBy(s => s.School)) { var school = await schoolService.GetFirstAsync(s => s.Name == schoolArr.Key); if (school == null) Oh.ModelError($"导入失败:学校 [{schoolArr.Key}] 未找到!"); var gradeInfo = GradeHelper.GetStudentGradeBaseByGrade(schoolArr.First().Grade); if (gradeInfo == null) Oh.ModelError($"导入失败:学校 [{schoolArr.Key}] 年级[{schoolArr.First().Grade}]不符合规范!"); //学校下的所属班级 var classArr = await db.Queryable().Where(c => c.SchoolId == school.Id && c.GradeLevel == gradeInfo.GradeLevel && c.GraduationYear == gradeInfo.GradeYear && !c.DeleteState).ToArrayAsync(); var userDic = await db.Queryable() .InnerJoin((s, c) => c.SchoolId == s.Id) .InnerJoin((s, c, p) => p.ClassId == c.Id) .InnerJoin((s, c, p, pr) => pr.PositionId == p.Id) .InnerJoin((s, c, p, pr, u) => u.Id == pr.UserId) .Where((s, c, p, pr, u) => s.Id == school.Id && c.GradeLevel == gradeInfo.GradeLevel && c.GraduationYear == gradeInfo.GradeYear && s.Enable && p.Enable && pr.Enable && p.DeleteState != false && c.DeleteState != false && u.DeleteState != false && s.DeleteState != false) .Select((s, c, p, pr, u) => new { Name = c.Name + c.Type.ToString() + u.RealName, u.Id, }).ToDictionaryAsync(s => s.Id, s => s.Name); //处理学生成绩数据 var userList = dataList.Select(s => { var classInfo = classArr .FirstOrDefault(x => x.Name == s.Class && x.Type == s.ClassType.ToEnum()); if (classInfo == null) { s.Error = "未能匹配班级"; errorExcelInfo.Add(s); return null; } var grade = GradeHelper.GetStudentGradeBaseByGrade(s.Grade); var sub = ImportExamInfoSubjectDic(s); var name = s.Class + s.ClassType.ToEnum().GetHashCode() + s.Student; if (userDic.ContainsKey(name)) { s.Error = "未能匹配到年级班级下对应的学生"; errorExcelInfo.Add(s); return null; } var uid = userDic[name]; return new ExamUserInfo() { ExamId = exam.Id, ExamName = exam.Name, GradeYear = grade.GradeYear, GradeLevel = grade.GradeLevel, TestPaperType = exam.TestPaperType, UserId = (long)userDic[name], ClassId = classInfo.Id, SchoolId = classInfo.SchoolId, Type = exam.Type, SubjectDic = sub, AssignScore = s.赋分后总分, AssignRanking = 0, }; }).ToList(); insertUserInfo.AddRange(userList); foreach (var classUserArr in insertUserInfo.GroupBy(s => s.ClassId)) { var classInfo = classArr.First(s => s.Id == classUserArr.Key); var eCInfo = new ExamClassInfo() { ExamId = exam.Id, ExamName = exam.Name, SchoolId = classInfo.SchoolId, SchoolName = school.Name, ClassId = classInfo.Id, ClassName = classInfo.Name, GradeLevel = classInfo.GradeLevel, GradeYear = classInfo.GraduationYear, PeopleCount = classUserArr.Count(), MinScore = int.MaxValue, EntryPersonId = userInfo.Id, EntryPerson = userInfo.Name, }; insertClassInfo.Add(eCInfo); var avgTotal = 0m; foreach (var eUserInfo in classUserArr) { var v = eUserInfo.AssignScore; //上线人数 if (v>=exam.ScoreLine) eCInfo.OnLineCount ++; //最大小分 if (v < eCInfo.MinScore) eCInfo.MinScore = v; else if(v > eCInfo.MaxScore) eCInfo.MaxScore = v; avgTotal += v;//追加得分 } //总分平均分 eCInfo.Average = avgTotal / eCInfo.PeopleCount; //计算上线率 eCInfo.OnLineRate = eCInfo.OnLineCount / eCInfo.PeopleCount; //处理学生班级排名 var i = 0; foreach (var item in classUserArr.OrderByDescending(s => s.AssignScore) .GroupBy(s => s.AssignScore)) { foreach (var u in item) u.AssignRanking =++ i; } } }; { //计算年级上线率排名 var i = 0; foreach (var item in insertClassInfo.OrderByDescending(s => s.OnLineRate) .GroupBy(s => s.OnLineRate)) { foreach (var u in item) u.OnLineRanking = ++i; } //计算年级平均分排名 i = 0; foreach (var item in insertClassInfo.OrderByDescending(s => s.Average) .GroupBy(s => s.Average)) { foreach (var u in item) u.AverageRank = ++i; } } if (errorExcelInfo.Count != 0) return File(errorExcelInfo.ExportExcel(), "application/ms-excel"); //写入数据库 var baseDB = baseService.Context; baseDB.Ado.BeginTran(); await db.Insertable(insertUserInfo).ExecuteCommandAsync(); await db.Insertable(insertClassInfo).ExecuteCommandAsync(); baseDB.Ado.CommitTran(); return Ok(); } } }