Compare commits

..

No commits in common. "d323635ad13e2f6869741f7b0245c41f36b5e09c" and "457b4cd450b91afcbc7d9a39b2bf3669c0252f30" have entirely different histories.

5 changed files with 42 additions and 232 deletions

View File

@ -150,7 +150,7 @@ namespace Learn.Archives.API.Controllers
//处理数据 //处理数据
var accountArr = await baseService.AsQueryable() var accountArr = await baseService.AsQueryable()
.Select(s => s.Account ).Distinct() .Select(s => s.Account).Distinct()
.ToArrayAsync(); .ToArrayAsync();
var accountH = accountArr.ToHashSet(); var accountH = accountArr.ToHashSet();
var roleDic = await roleDB.AsQueryable() var roleDic = await roleDB.AsQueryable()
@ -180,8 +180,6 @@ namespace Learn.Archives.API.Controllers
admin.RoleId = (long)roleDic[imp.Role]; admin.RoleId = (long)roleDic[imp.Role];
admin.Password = imp.Password.Trim().GetMD5(); admin.Password = imp.Password.Trim().GetMD5();
insertInfo.Add(admin); insertInfo.Add(admin);
//excel内预计新增的账号也计入重复
accountH.Add(admin.Account);
} }
if (errorExcelInfo.Count != 0) if (errorExcelInfo.Count != 0)

View File

@ -57,8 +57,18 @@ namespace Learn.Archives.API.Controllers
{ {
var exam = await examService.GetByIdAsync(dto.eId); var exam = await examService.GetByIdAsync(dto.eId);
if (exam == null ) Oh.ModelError("为传入有效的数据"); var fl = dto.File!=null? dto .File: accessor.HttpContext?.Request.Form.Files[0];
var dataList = await accessor.ParsingExcelAsync<ImportExamInfoError>(); if (exam == null || fl == null) Oh.ModelError("为传入有效的数据");
if (!Path.GetExtension(fl.FileName).Equals(".xlsx", StringComparison.OrdinalIgnoreCase))
Oh.ModelError("请选择导入文件为.xlsx的后缀名!");
//分析excel
IEnumerable<ImportExamInfoError> dataList;
using var stream = new MemoryStream();
{
await fl.CopyToAsync(stream);
dataList = stream.Query<ImportExamInfoError>()
.Where(s => !string.IsNullOrEmpty(s.Student));
}
if (dataList == null || dataList.Count() == 0) if (dataList == null || dataList.Count() == 0)
Oh.ModelError("导入失败:无有效数据"); Oh.ModelError("导入失败:无有效数据");
@ -343,7 +353,7 @@ namespace Learn.Archives.API.Controllers
c.GraduationYear == exam.GradeYear && !c.DeleteState) c.GraduationYear == exam.GradeYear && !c.DeleteState)
.ToArrayAsync(); .ToArrayAsync();
foreach (var classUserArr in schoolArr.GroupBy(s => s.ClassId)) foreach (var classUserArr in userInfoArr.Where(s=>s.SchoolId == school.Id).GroupBy(s => s.ClassId))
{ {
var classInfo = classArr.FirstOrDefault(s => s.Id == classUserArr.Key); var classInfo = classArr.FirstOrDefault(s => s.Id == classUserArr.Key);
if (classInfo is null) if (classInfo is null)

View File

@ -31,20 +31,13 @@ namespace Learn.Archives.API.Controllers
readonly Repository<Position> positionService; readonly Repository<Position> positionService;
readonly UserCenterService _userCenterService; readonly UserCenterService _userCenterService;
readonly LiveUserInfo userInfo; readonly LiveUserInfo userInfo;
readonly Repository<School> schoolService; public StudentController(Repository<Student> baseService, LiveUserInfo userInfo, IHttpContextAccessor httpContextAccessor, UserCenterService userCenterService, Repository<Position> positionService) : base(baseService)
readonly Repository<Classes> classesService;
readonly Repository<User> userService;
public StudentController(Repository<Student> baseService, LiveUserInfo userInfo, IHttpContextAccessor httpContextAccessor, UserCenterService userCenterService, Repository<Position> positionService, Repository<School> schoolService, Repository<Classes> classesService, Repository<User> userService) : base(baseService)
{ {
this.baseService = baseService; this.baseService = baseService;
this.userInfo = userInfo; this.userInfo = userInfo;
_httpContextAccessor = httpContextAccessor; _httpContextAccessor = httpContextAccessor;
_userCenterService = userCenterService; _userCenterService = userCenterService;
this.positionService = positionService; this.positionService = positionService;
this.schoolService = schoolService;
this.classesService = classesService;
this.userService = userService;
} }
[NonAction] [NonAction]
@ -73,7 +66,7 @@ namespace Learn.Archives.API.Controllers
[HttpPost] [HttpPost]
public async Task<long[]> PosititonIds(PositionIdsReq[] data) public async Task<long[]> PosititonIds(PositionIdsReq[] data)
{ {
if (data == null || data.Count() == 0) if (data == null || data.Count()==0)
Oh.ModelError("无效数据"); Oh.ModelError("无效数据");
var query = new Expressionable<Position>(); var query = new Expressionable<Position>();
foreach (var pos in data) foreach (var pos in data)
@ -131,9 +124,9 @@ namespace Learn.Archives.API.Controllers
[HttpPost] [HttpPost]
public new async Task<PageResult<StudentInfoRes>> PageList(object data) public new async Task<PageResult<StudentInfoRes>> PageList(object data)
{ {
var apiRes = await _userCenterService.CallAPI_GetPageUserList(_httpContextAccessor.HttpContext); var apiRes =await _userCenterService.CallAPI_GetPageUserList(_httpContextAccessor.HttpContext);
var res = new PageResult<StudentInfoRes>() { Data = new List<StudentInfoRes>() }; var res= new PageResult<StudentInfoRes>() { Data = new List<StudentInfoRes>() };
if (apiRes == null || apiRes.Data.Count == 0) return res; if (apiRes == null|| apiRes.Data.Count == 0) return res;
res.Total = apiRes.Total; res.Total = apiRes.Total;
var uids = apiRes.Data.Select(s => s.Id).ToArray(); var uids = apiRes.Data.Select(s => s.Id).ToArray();
var exData = await baseService.AsQueryable() var exData = await baseService.AsQueryable()
@ -145,8 +138,8 @@ namespace Learn.Archives.API.Controllers
res.Data.Add(item); res.Data.Add(item);
if (!exDataDic.ContainsKey(item.Id)) continue; if (!exDataDic.ContainsKey(item.Id)) continue;
var ex = exDataDic[item.Id].First(); var ex = exDataDic[item.Id].First();
item.Status = ex.Status ?? UserStatusEnum.; item.Status = ex.Status??UserStatusEnum.;
item.ExitTime = ex.ExitTime == null ? string.Empty : ex.ExitTime?.ToString("yyyy-MM-dd"); item.ExitTime = ex.ExitTime==null? string.Empty : ex.ExitTime?.ToString("yyyy-MM-dd");
item.JoinTime = ex.JoinTime == null ? string.Empty : ex.JoinTime?.ToString("yyyy-MM-dd"); item.JoinTime = ex.JoinTime == null ? string.Empty : ex.JoinTime?.ToString("yyyy-MM-dd");
item.AmountRelief = ex.AmountRelief; item.AmountRelief = ex.AmountRelief;
@ -197,15 +190,15 @@ namespace Learn.Archives.API.Controllers
var gStr = GradeHelper.GetGrade(ginfo.GradeLevel, ginfo.GradeYear); var gStr = GradeHelper.GetGrade(ginfo.GradeLevel, ginfo.GradeYear);
if (gStr.ToEnum<GradeEnum>() == null) //无效的传入年级 if (gStr.ToEnum<GradeEnum>() == null) //无效的传入年级
{ {
s.ErrorMsg = "无效的年级 例如[初一/初2028] [年 级范围应当是当前有效的就读年级]"; s.ErrorMsg = "无效的年级 例如[初一/初2028] [年级范围应当是当前有效的就读年级]";
impError.Add(s); impError.Add(s);
continue; continue;
} }
//基础信息校验 //基础信息校验
if (string.IsNullOrEmpty(s.UserType) || if (string.IsNullOrEmpty(s.UserType) ||
string.IsNullOrEmpty(s.School) || string.IsNullOrEmpty(s.School)||
(s.UserType != "年级主任" && string.IsNullOrEmpty(s.Class)) || (s.UserType != "年级主任" && string.IsNullOrEmpty(s.Class)) ||
string.IsNullOrEmpty(s.Phone) || string.IsNullOrEmpty(s.Phone)||
string.IsNullOrEmpty(s.RealName) string.IsNullOrEmpty(s.RealName)
) )
{ {
@ -214,7 +207,7 @@ namespace Learn.Archives.API.Controllers
continue; continue;
} }
//无效的任教学科 //无效的任教学科
if (!string.IsNullOrEmpty(s.Subject) && s.Subject.ToEnum<SubjectEnum>() == null) if (!string.IsNullOrEmpty(s.Subject) && s.Subject.ToEnum<SubjectEnum>()==null)
{ {
s.ErrorMsg = "无效的任教学科"; s.ErrorMsg = "无效的任教学科";
impError.Add(s); impError.Add(s);
@ -282,7 +275,7 @@ namespace Learn.Archives.API.Controllers
foreach (var s in dataList) foreach (var s in dataList)
{ {
var ginfo = GradeHelper.GetStudentGradeBaseByGrade(s.Grade); var ginfo = GradeHelper.GetStudentGradeBaseByGrade(s.Grade);
if (ginfo is null) if(ginfo is null)
{ {
s.ErrorMsg = "未能识别的[初一/初2028] [年级范围应当是当前有效的就读年级]"; s.ErrorMsg = "未能识别的[初一/初2028] [年级范围应当是当前有效的就读年级]";
impError.Add(s); impError.Add(s);
@ -297,18 +290,18 @@ namespace Learn.Archives.API.Controllers
} }
insertInfo.Add(new Student() insertInfo.Add(new Student()
{ {
AmountRelief = decimal.TryParse(s.AmountRelief, out decimal v) ? v : 0, AmountRelief = decimal.TryParse(s.AmountRelief,out decimal v)?v:0,
ExitTime = s.ExitTime, ExitTime = s.ExitTime,
Remark = s.Remark, Remark = s.Remark,
JoinTime = s.JoinTime, JoinTime = s.JoinTime,
Status = s.Status.ToEnum<UserStatusEnum>() ?? default, Status = s.Status.ToEnum<UserStatusEnum>()??default,
UserCenterId = s.Id, UserCenterId = s.Id,
ReliefApplication = s.ReliefApplication?.Contains("已申请") ?? false, ReliefApplication=s.ReliefApplication?.Contains("已申请")??false,
ReliefSubTime = s.ReliefSubTime, ReliefSubTime = s.ReliefSubTime,
ReliefType = s.ReliefType, ReliefType =s.ReliefType,
StudentType = s.StudentType.ToEnum<StudentTypeEnum>(), StudentType =s.StudentType.ToEnum<StudentTypeEnum>(),
}); });
var addExcelUser = new UserExcelExportData() userCenterImp.Add(new UserExcelExportData()
{ {
UserType = "学生", UserType = "学生",
Account = s.Id.ToString(), Account = s.Id.ToString(),
@ -318,11 +311,8 @@ namespace Learn.Archives.API.Controllers
ExamNo = s.Id.ToString(), ExamNo = s.Id.ToString(),
Phone = s.Phone, Phone = s.Phone,
RealName = s.RealName, RealName = s.RealName,
Stages = s.Grade.Contains("初") ? StudentStagesEnum..ToString() : StudentStagesEnum..ToString() Stages = s.Grade.Contains("初")? StudentStagesEnum..ToString() : StudentStagesEnum..ToString()
}; });
userCenterImp.Add(addExcelUser);
if (!string.IsNullOrWhiteSpace(s.))
addExcelUser.GKSubject = s.;
} }
//如果有错误数据则返回excel //如果有错误数据则返回excel
@ -331,7 +321,7 @@ namespace Learn.Archives.API.Controllers
//调用 用户中心 导入接口 //调用 用户中心 导入接口
var importRes = await _userCenterService.CallAPI_ImportJsonData(_httpContextAccessor.HttpContext, userCenterImp); var importRes = await _userCenterService.CallAPI_ImportJsonData(_httpContextAccessor.HttpContext, userCenterImp);
var hUAccount = importRes.InsertUsers.ToDictionary(s => s.Account, s => s.Id); var hUAccount = importRes.InsertUsers.ToDictionary(s=>s.Account,s=>s.Id);
//基于结果判断添加成功` //基于结果判断添加成功`
insertInfo = insertInfo insertInfo = insertInfo
.Where(s => hUAccount.ContainsKey(s.UserCenterId.ToString())).Select(s => .Where(s => hUAccount.ContainsKey(s.UserCenterId.ToString())).Select(s =>
@ -351,152 +341,6 @@ namespace Learn.Archives.API.Controllers
} }
/// <summary>
/// 导入excel 更新学生信息
/// </summary>
/// <returns></returns>
[HttpPost, ResultIgnore]
[HttpLogEnable]
public async Task<IActionResult> ImportUpdateStudent(IFormFile? file)
{
var dataList = await _httpContextAccessor.ParsingExcelAsync<StudentInfoImportError>();
if (dataList == null || dataList.Length == 0)
Oh.ModelError("导入失败:无有效数据");
var updateArr = new List<Student>();
var impError = new List<StudentInfoImportError>();
var userCenterUpdate = new List<User>();
var db = schoolService.Context;
var schoolDic = await schoolService.AsQueryable().ToDictionaryAsync(s => s.Name, s => s.Id);
foreach (var schoolGroup in dataList.GroupBy(s => s.School))
{
if (!schoolDic.ContainsKey(schoolGroup.Key))
Oh.ModelError($"未能识别的学校[{schoolGroup.Key}]");
var schoolId = (long)schoolDic[schoolGroup.Key];
var names = schoolGroup.Select(r => r.RealName)
.Where(n => !string.IsNullOrWhiteSpace(n)).Distinct().ToList();
var userDic = new Dictionary<string, long>();
for (int i = 0; i < names.Count; i += 500)
{
var batch = names.Skip(i).Take(500).ToList();
var part = await db.Queryable<School>()
.LeftJoin<Classes>((s, c) => c.SchoolId == s.Id)
.LeftJoin<Position>((s, c, p) => p.ClassId == c.Id)
.LeftJoin<PositionRelation>((s, c, p, pr) => pr.PositionId == p.Id)
.LeftJoin<User>((s, c, p, pr, u) => u.Id == pr.UserId)
.Where((s, c, p, pr, u) =>
s.Id == schoolId &&
u.UserType == UserTypeEnum..GetHashCode() &&
batch.Contains(u.RealName) &&
s.Enable && p.Enable && pr.Enable &&
!p.DeleteState && !c.DeleteState && !u.DeleteState && !s.DeleteState)
.Select((s, c, p, pr, u) => new
{
Name = c.GradeLevel.ToString() + c.GraduationYear.ToString() + c.Name + u.RealName,
u.Id,
}).ToListAsync();
foreach (var kv in part)
userDic[kv.Name] = (long)kv.Id;
}
foreach (var row in schoolGroup)
{
var ginfo = GradeHelper.GetStudentGradeBaseByGrade(row.Grade);
var key = (ginfo?.GradeLevel.ToString() ?? string.Empty) + (ginfo?.GradeYear.ToString() ?? string.Empty) + row.Class + row.RealName;
if (!userDic.ContainsKey(key))
{
row.ErrorMsg = "未能匹配到学校下对应的班级学生";
impError.Add(row);
continue;
}
var uid = (long)userDic[key];
var u = new Student()
{
UserCenterId = uid,
AmountRelief = decimal.TryParse(row.AmountRelief, out var v) ? v : null,
ReliefApplication = row.ReliefApplication?.Contains("已申请") ?? false,
ReliefType = row.ReliefType,
ReliefSubTime = row.ReliefSubTime,
StudentType = row.StudentType.ToEnum<StudentTypeEnum>(),
Status = row.Status.ToEnum<UserStatusEnum>(),
JoinTime = row.JoinTime,
ExitTime = row.ExitTime,
Remark = row.Remark,
};
updateArr.Add(u);
if (!string.IsNullOrWhiteSpace(row.))
{
var gradeStd = ginfo is null ? row.Grade : GradeHelper.GetGrade(ginfo.GradeLevel, ginfo.GradeYear);
var subjectArr = row..Split("")
.Select(s => s.ToEnum<SubjectEnum>())
.ToArray();
userCenterUpdate.Add(new User
{
Id = uid,
Phone = row.Phone,
GLSubject = (int?)subjectArr[0],
GSubject1 = (int?)subjectArr[1],
GSubject2 = (int?)subjectArr[2],
});
}
}
}
if (impError.Count != 0)
return File(impError.ExportExcel(), "application/ms-excel", $"导入错误学生{DateTime.Now.ToString("MMddHHmm")}.xlsx");
if (updateArr.Count > 0)
{
updateArr = updateArr.Where(s =>
new object[] { s.AmountRelief,
s.ReliefType,
s.ReliefSubTime,
s.StudentType,
s.Status,
s.JoinTime,
s.ExitTime,
s.Remark}.Any(x => !(x == default || x == null))).ToList();
// 测试IgnoreColumns是否真实有效
await baseService.AsUpdateable(updateArr)
.UpdateColumns(s => new
{
s.AmountRelief,
s.ReliefApplication,
s.ReliefType,
s.ReliefSubTime,
s.StudentType,
s.Status,
s.JoinTime,
s.ExitTime,
s.Remark
})
//更新忽略null并且忽略默认值 (比如int默认值是0就不更新)
.IgnoreColumns(ignoreAllNullColumns: true, ignoreAllDefaultValue: true)
.WhereColumns(it => new { it.UserCenterId })
.ExecuteCommandAsync();
}
if (userCenterUpdate.Count > 0)
await userService.AsUpdateable(userCenterUpdate)
.UpdateColumns(s => new
{
s.Phone,
s.GLSubject,
s.GSubject1,
s.GSubject2,
})
//更新忽略null并且忽略默认值 (比如int默认值是0就不更新)
.IgnoreColumns(ignoreAllNullColumns: true, ignoreAllDefaultValue: true)
.WhereColumns(it => new { it.Id })
.ExecuteCommandAsync();
Oh.Error("需要测试");
return Ok();
}
@ -521,7 +365,6 @@ namespace Learn.Archives.API.Controllers
StudentType = "选填: 可选值:\r\n复读生\r\n艺术生\r\n春招生\r\n领导承诺批准全免\r\n资源班\r\n国际班\r\n合同制收费学校\r\n渠道商家属\r\n新开班但领导承诺第一学期不收费", StudentType = "选填: 可选值:\r\n复读生\r\n艺术生\r\n春招生\r\n领导承诺批准全免\r\n资源班\r\n国际班\r\n合同制收费学校\r\n渠道商家属\r\n新开班但领导承诺第一学期不收费",
Phone="选填", Phone="选填",
Remark="选填", Remark="选填",
= "填写学科\r\n 例如 物理 \r\n多学科情况下 物理,化学,生物"
} }; } };
return File(resultList.ExportExcel(), "application/ms-excel", return File(resultList.ExportExcel(), "application/ms-excel",
$"导入学生模板{DateTime.Now.ToString("MMddHHmm")}.xlsx"); $"导入学生模板{DateTime.Now.ToString("MMddHHmm")}.xlsx");

View File

@ -19,8 +19,6 @@ using System.Threading.Tasks;
using UserCenter.Model.Interface; using UserCenter.Model.Interface;
using MiniExcelLibs; using MiniExcelLibs;
using MiniExcelLibs.OpenXml; using MiniExcelLibs.OpenXml;
using Microsoft.AspNetCore.Http;
using Learn.Archives.Core.Model.Dto;
namespace Learn.Archives.Core.Common namespace Learn.Archives.Core.Common
{ {
@ -148,35 +146,7 @@ namespace Learn.Archives.Core.Common
}; };
return JsonSerializer.Serialize(o, jsonOptions); return JsonSerializer.Serialize(o, jsonOptions);
} }
/// <summary>
/// 解析Excel为对象数组
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="context"></param>
/// <returns></returns>
public static async Task<T[]?> ParsingExcelAsync<T>(this IHttpContextAccessor context) where T: class, new()
{
if (context == null) Oh.ModelError("传入无效的请求上下文数据");
var fl =context?.HttpContext?.Request.Form.Files[0];
if (fl == null) Oh.ModelError("传入无效的Excel数据");
if (!Path.GetExtension(fl.FileName).Equals(".xlsx", StringComparison.OrdinalIgnoreCase))
Oh.ModelError("请选择导入文件为.xlsx的后缀名!");
try
{
//分析excel
IEnumerable<T> dataList;
using var stream = new MemoryStream();
{
await fl.CopyToAsync(stream);
return stream.Query<T>().ToArray();
}
}
catch (Exception ex)
{
return Oh.Error<T[]>("分析失败"+ex.Message);
}
}
/// <summary> /// <summary>
/// 获取应用有效程序集 /// 获取应用有效程序集

View File

@ -214,12 +214,6 @@ namespace Learn.Archives.Core.Model.Dto
[ExcelColumn(Name = "备注",Width =50)] [ExcelColumn(Name = "备注",Width =50)]
public string? Remark { get; set; } public string? Remark { get; set; }
/// <summary>
/// 高考选科
/// <para></para>
/// </summary>
[ExcelColumn(Name = "高考选科", Width = 20)]
public string? { get; set; }
/// <summary> /// <summary>
/// id /// id
/// </summary> /// </summary>
@ -317,11 +311,6 @@ namespace Learn.Archives.Core.Model.Dto
/// </summary> /// </summary>
[ExcelColumn(Name="学段")] [ExcelColumn(Name="学段")]
public string? Stages { get; set; } public string? Stages { get; set; }
/// <summary>
/// 选修方向
/// </summary>
[ExcelColumnName("选修方向")]
public string? GKSubject { get; set; }
} }