优化 考试导入流程

This commit is contained in:
小肥羊 2025-08-26 19:10:33 +08:00
parent b28931ce0f
commit a234d947c1
5 changed files with 136 additions and 46 deletions

View File

@ -7,11 +7,13 @@ using Learn.Archives.Core.Model.Dto;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using MiniExcelLibs; using MiniExcelLibs;
using System.Buffers.Text;
using System.Diagnostics; using System.Diagnostics;
using System.Security.Claims; using System.Security.Claims;
using UserCenter.Model; using UserCenter.Model;
using UserCenter.Model.Common; using UserCenter.Model.Common;
using UserCenter.Model.Enum; using UserCenter.Model.Enum;
using static System.Net.Mime.MediaTypeNames;
namespace Learn.Archives.API.Controllers namespace Learn.Archives.API.Controllers
{ {
@ -89,14 +91,13 @@ namespace Learn.Archives.API.Controllers
.ToArrayAsync(); .ToArrayAsync();
var oldUidHash = oldUidAr.ToHashSet(); var oldUidHash = oldUidAr.ToHashSet();
var db = schoolService.Context; var db = schoolService.Context;
SqlSugarExpand.SetDbAop(db);
foreach (var schoolArr in dataList.GroupBy(s => s.School)) foreach (var schoolArr in dataList.GroupBy(s => s.School))
{ {
var school = await schoolService.GetFirstAsync(s => s.Name == schoolArr.Key); var school = await schoolService.GetFirstAsync(s => s.Name == schoolArr.Key);
if (school == null) Oh.ModelError($"导入失败:学校 [{schoolArr.Key}] 未找到!"); if (school == null) Oh.ModelError($"导入失败:学校 [{schoolArr.Key}] 未找到!");
var gradeInfo = GradeHelper.GetStudentGradeBaseByGrade(schoolArr.First().Grade); var gradeInfo = GradeHelper.GetStudentGradeBaseByGrade(schoolArr.First().Grade);
if (gradeInfo == null) Oh.ModelError($"导入失败:学校 [{schoolArr.Key}] 年级[{schoolArr.First().Grade}]不符合规范!"); if (gradeInfo == null) Oh.ModelError($"导入失败:学校 [{schoolArr.Key}] 年级[{schoolArr.First().Grade}]不符合规范!");
if(exam.Level != GradeHelper.GetGrade(gradeInfo.GradeLevel,gradeInfo.GradeYear).ToEnum<GradeEnum>()) if(exam.GradeLevel != gradeInfo.GradeLevel || exam.GradeYear != gradeInfo.GradeYear)
Oh.ModelError($"导入失败:导入年级[{schoolArr.First().Grade}] 与 考试年级不匹配!"); Oh.ModelError($"导入失败:导入年级[{schoolArr.First().Grade}] 与 考试年级不匹配!");
//学校下的所属班级 //学校下的所属班级
var classArr = await db.Queryable<Classes>().Where(c => c.SchoolId == school.Id && var classArr = await db.Queryable<Classes>().Where(c => c.SchoolId == school.Id &&
@ -165,9 +166,46 @@ namespace Learn.Archives.API.Controllers
}; };
}).ToList(); }).ToList();
insertUserInfo.AddRange(userList); insertUserInfo.AddRange(userList);
insertUserInfo = insertUserInfo.Where(s => s != null).ToList(); insertUserInfo = insertUserInfo.Where(s => s != null).ToList();
foreach (var classUserArr in insertUserInfo.GroupBy(s => s.ClassId)) };
if (errorExcelInfo.Count != 0)
return File(errorExcelInfo.ExportExcel(), "application/ms-excel", $"错误考试信息{DateTime.Now.ToString("MMddHHmm")}.xlsx");
//写入数据库
await examUserInfoService.AsInsertable(insertUserInfo).ExecuteCommandAsync();
await CalculatingTestResults(exam,examUserInfoService,schoolService);
return Ok();
}
/// <summary>
/// 计算考试成绩
/// </summary>
/// <param name="exam"></param>
/// <param name="examUserInfoService"></param>
/// <param name="schoolService"></param>
/// <returns></returns>
[NonAction]
public static async Task CalculatingTestResults(Exam exam, Repository<ExamUserInfo> eUService, Repository<School> sService)
{
var userInfoArr = await eUService.AsQueryable()
.Where(s => s.ExamId == exam.Id)
.ToArrayAsync();
var insertTotalClassInfo = new List<ExamClassInfo>();
var db = sService.Context;
foreach (var schoolArr in userInfoArr.GroupBy(s => s.SchoolId))
{
var insertClassInfo = new List<ExamClassInfo>();
var school = await sService.GetFirstAsync(s => s.Id == schoolArr.Key);
var classArr = await db.Queryable<Classes>().Where(c => c.SchoolId == school.Id &&
c.GradeLevel == exam.GradeLevel &&
c.GraduationYear == exam.GradeYear && !c.DeleteState).ToArrayAsync();
foreach (var classUserArr in userInfoArr.GroupBy(s => s.ClassId))
{ {
var classInfo = classArr.First(s => s.Id == classUserArr.Key); var classInfo = classArr.First(s => s.Id == classUserArr.Key);
var eCInfo = new ExamClassInfo() var eCInfo = new ExamClassInfo()
@ -182,9 +220,7 @@ namespace Learn.Archives.API.Controllers
GradeYear = classInfo.GraduationYear, GradeYear = classInfo.GraduationYear,
PeopleCount = classUserArr.Count(), PeopleCount = classUserArr.Count(),
MinScore = int.MaxValue, MinScore = int.MaxValue,
EntryPersonId = userInfo.Id,
BaseSchoolScore = exam.BaseSchoolScore, BaseSchoolScore = exam.BaseSchoolScore,
EntryPerson = userInfo.Name,
TestPaperType = exam.TestPaperType, TestPaperType = exam.TestPaperType,
Type = exam.Type, Type = exam.Type,
Average1 = exam.BaseSchoolScore, Average1 = exam.BaseSchoolScore,
@ -208,23 +244,14 @@ namespace Learn.Archives.API.Controllers
eCInfo.Average = avgTotal / eCInfo.PeopleCount; eCInfo.Average = avgTotal / eCInfo.PeopleCount;
//计算上线率 //计算上线率
eCInfo.OnLineRate = (decimal)eCInfo.OnLineCount / (decimal)eCInfo.PeopleCount; eCInfo.OnLineRate = (decimal)eCInfo.OnLineCount / (decimal)eCInfo.PeopleCount;
//不计算 直接Excel导入
////处理学生班级排名
//var i = 0;
//foreach (var item in classUserArr.OrderByDescending(s => s.AssignScore)
// .GroupBy(s => s.AssignScore))
//{
// foreach (var u in item)
// u.AssignRanking =++ i;
//}
} }
}; insertTotalClassInfo.AddRange(insertClassInfo);
}
{ //计算年级上线率排名 { //计算年级上线率排名
var i = 0; var i = 0;
foreach (var item in insertClassInfo.OrderByDescending(s => s.OnLineRate) foreach (var item in insertTotalClassInfo.OrderByDescending(s => s.OnLineRate)
.GroupBy(s => s.OnLineRate)) .GroupBy(s => s.OnLineRate))
{ {
foreach (var u in item) foreach (var u in item)
@ -233,25 +260,21 @@ namespace Learn.Archives.API.Controllers
//计算年级平均分排名 //计算年级平均分排名
i = 0; i = 0;
foreach (var item in insertClassInfo.OrderByDescending(s => s.Average) foreach (var item in insertTotalClassInfo.OrderByDescending(s => s.Average)
.GroupBy(s => s.Average)) .GroupBy(s => s.Average))
{ {
foreach (var u in item) foreach (var u in item)
u.AverageRank = ++i; u.AverageRank = ++i;
} }
} }
if (errorExcelInfo.Count != 0)
return File(errorExcelInfo.ExportExcel(), "application/ms-excel", $"错误考试信息{DateTime.Now.ToString("MMddHHmm")}.xlsx");
//写入数据库 //写入数据库
var baseDB = baseService.Context; var baseDB = eUService.Context;
baseDB.Ado.BeginTran(); baseDB.Ado.BeginTran();
try try
{ {
await baseDB.Insertable(insertUserInfo).ExecuteCommandAsync(); await baseDB.Deleteable<ExamClassInfo>().Where(s=>s.ExamId==exam.Id).ExecuteCommandAsync();
await baseDB.Insertable(insertClassInfo).ExecuteCommandAsync(); await baseDB.Insertable(insertTotalClassInfo).ExecuteCommandAsync();
baseDB.Ado.CommitTran(); baseDB.Ado.CommitTran();
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -259,7 +282,6 @@ namespace Learn.Archives.API.Controllers
Oh.ModelError($"导入失败:写入数据时候出现了异常 [{ex.Message}] !"); Oh.ModelError($"导入失败:写入数据时候出现了异常 [{ex.Message}] !");
} }
return Ok();
} }
/// <summary> /// <summary>

View File

@ -3,11 +3,13 @@ using Learn.Archives.API.Controllers.Dto;
using Learn.Archives.API.Expand; using Learn.Archives.API.Expand;
using Learn.Archives.Core.Common; using Learn.Archives.Core.Common;
using Learn.Archives.Core.Model; using Learn.Archives.Core.Model;
using Learn.Archives.Core.Model.Dto;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System.Diagnostics; using System.Diagnostics;
using System.Security.Claims; using System.Security.Claims;
using UserCenter.Model; using UserCenter.Model;
using UserCenter.Model.Common;
namespace Learn.Archives.API.Controllers namespace Learn.Archives.API.Controllers
{ {
@ -17,17 +19,59 @@ namespace Learn.Archives.API.Controllers
public class ExamController : BackController<Exam> public class ExamController : BackController<Exam>
{ {
readonly Repository<Exam> baseService; readonly Repository<Exam> baseService;
readonly Repository<School> schoolService;
readonly Repository<ExamClassInfo> examClassInfoService; readonly Repository<ExamClassInfo> examClassInfoService;
readonly Repository<ExamUserInfo> examUserInfoService; readonly Repository<ExamUserInfo> examUserInfoService;
readonly LiveUserInfo userInfo; readonly LiveUserInfo userInfo;
public ExamController(Repository<Exam> baseService, LiveUserInfo userInfo, Repository<ExamClassInfo> examClassInfoService, Repository<ExamUserInfo> examUserInfoService) : base(baseService) public ExamController(Repository<Exam> baseService, LiveUserInfo userInfo,
Repository<ExamClassInfo> examClassInfoService, Repository<ExamUserInfo> examUserInfoService,
Repository<School> schoolService) : base(baseService)
{ {
this.baseService = baseService; this.baseService = baseService;
this.userInfo = userInfo; this.userInfo = userInfo;
this.examClassInfoService = examClassInfoService; this.examClassInfoService = examClassInfoService;
this.examUserInfoService = examUserInfoService; this.examUserInfoService = examUserInfoService;
this.schoolService = schoolService;
}
public override Task<dynamic> PageList([FromBody] QueryRequestBase model)
{
var c = model.Conditions.FirstOrDefault(s => s.FieldName == "Grade");
if (c != null)
{
var gInfo = GradeHelper.GetStudentGradeBaseByGrade(c.FieldValue);
if (gInfo != null)
{
model.Conditions = model.Conditions.Where(s => s != c).ToList();
model.Conditions.Add(new SqlSugar.ConditionalModel()
{
FieldName = "GradeLevel",
FieldValue = gInfo.GradeLevel,
});
model.Conditions.Add(new SqlSugar.ConditionalModel()
{
FieldName = "GradeYear",
FieldValue = gInfo.GradeYear.ToString(),
CSharpTypeName = "int"
});
}
} }
return base.PageList(model);
}
public override async Task<bool> Edit([FromBody] Exam model)
{
if (!string.IsNullOrEmpty(model._grade))
{
var g = GradeHelper.GetStudentGradeBaseByGrade(model._grade);
model.GradeLevel = g.GradeLevel;
model.GradeYear = g.GradeYear;
}
var res =await base.Edit(model);
if (res)
await ExamClassInfoController.CalculatingTestResults(model, examUserInfoService, schoolService);
return res ;
}
public override async Task<bool> Del([FromBody] params long[] ids) public override async Task<bool> Del([FromBody] params long[] ids)
{ {
if (ids.Length > 1) if (ids.Length > 1)

View File

@ -165,6 +165,12 @@ namespace Learn.Archives.API.Controllers
var adminArr = await adminService.AsQueryable() var adminArr = await adminService.AsQueryable()
.Where(s => adminNameArr.Contains(s.Name)) .Where(s => adminNameArr.Contains(s.Name))
.Select(s => s.Name).ToArrayAsync(); .Select(s => s.Name).ToArrayAsync();
if (adminArr == null || adminArr.Length!= adminNameArr.Length)
{
imp.Error = $"赴校人员未能完全识别成功";
errorExcelInfo.Add(imp);
continue;
}
var qStr = new Dictionary<FeedbackQuestionTypeEnum, (string Questions, string Solutions)>() var qStr = new Dictionary<FeedbackQuestionTypeEnum, (string Questions, string Solutions)>()
{ {
{FeedbackQuestionTypeEnum.,(imp.Q学校领导班子,imp.P学校领导班子) }, {FeedbackQuestionTypeEnum.,(imp.Q学校领导班子,imp.P学校领导班子) },
@ -255,8 +261,6 @@ namespace Learn.Archives.API.Controllers
}; };
business.SolutionEnd = business.SolutionRecord.EndRecordTime != null; business.SolutionEnd = business.SolutionRecord.EndRecordTime != null;
insertInfo.Add(business); insertInfo.Add(business);
}; };
if (errorExcelInfo.Count != 0) if (errorExcelInfo.Count != 0)
return File(errorExcelInfo.ExportExcel(), "application/ms-excel" return File(errorExcelInfo.ExportExcel(), "application/ms-excel"
@ -292,7 +296,15 @@ namespace Learn.Archives.API.Controllers
//todo完善数据转换 //todo完善数据转换
var resultList = new List<SchoolBusinessImport>() { new SchoolBusinessImport() { } }; var resultList = new List<SchoolBusinessImport>() { new SchoolBusinessImport()
{
School="必填 与系统对应",
Grade="必填 : 初一/高一/初2025",
IsDiscussion="是/否",
IsClassMeeting="是/否",
Remark="备注",
Users="必填: 例 用户1,用户2 与系统中用户名称对应"
} };
return File(resultList.ExportExcel(), "application/ms-excel", "导入赴校信息模板.xlsx"); return File(resultList.ExportExcel(), "application/ms-excel", "导入赴校信息模板.xlsx");
} }

View File

@ -5,6 +5,7 @@ using System.ComponentModel.DataAnnotations;
using System.Net; using System.Net;
using System.Text.Json; using System.Text.Json;
using UserCenter.Model; using UserCenter.Model;
using UserCenter.Model.Common;
using UserCenter.Model.Enum; using UserCenter.Model.Enum;
using UserCenter.Model.Interface; using UserCenter.Model.Interface;
@ -24,8 +25,27 @@ namespace Learn.Archives.Core.Model
/// <summary> /// <summary>
/// 年级 /// 年级
/// </summary> /// </summary>
[SugarColumn(Length = 12)] [SugarColumn(Length = 2)]
public GradeEnum Level { get; set; } public string? GradeLevel { get; set; }
/// <summary>
/// 毕业届
/// </summary>
[SugarColumn(Length = 2)]
public int GradeYear { get; set; }
/// <summary>
/// dto 处理的grade
/// </summary>
public string? _grade;
/// <summary>
/// 年级
/// </summary>
[SugarColumn(IsIgnore = true)]
public string Grade
{
get => GradeHelper.GetGrade(GradeLevel, GradeYear);
set => _grade = value;
}
/// <summary> /// <summary>
/// 试卷类型 /// 试卷类型
/// </summary> /// </summary>

View File

@ -61,6 +61,7 @@ namespace Learn.Archives.Core.Model
[SugarColumn(IsIgnore = true)] [SugarColumn(IsIgnore = true)]
public string Grade => GradeHelper.GetGrade(GradeLevel, GradeYear); public string Grade => GradeHelper.GetGrade(GradeLevel, GradeYear);
/// <summary> /// <summary>
/// 年级 /// 年级
/// </summary> /// </summary>
@ -119,15 +120,6 @@ namespace Learn.Archives.Core.Model
public decimal BaseSchoolScore { get; set; } public decimal BaseSchoolScore { get; set; }
/// <summary>
/// 录入人Id
/// </summary>
public long EntryPersonId { get; set; }
/// <summary>
/// 录入人名称
/// </summary>
public string EntryPerson { get; set; } = string.Empty;
/// <summary> /// <summary>
/// 创建时间 /// 创建时间
/// </summary> /// </summary>