using Furion.DatabaseAccessor.Extensions;
using Furion.JsonSerialization;
using NPOI.OpenXmlFormats.Wordprocessing;
using NPOI.SS.UserModel;
using NPOI.XWPF.UserModel;
using System.Dynamic;
using YBEE.EQM.Core;
namespace YBEE.EQM.Application;
///
/// 缺测替补管理服务
///
public partial class ExamAbsentReplaceService : IExamAbsentReplaceService, ITransient
{
private readonly IRepository _rep;
private readonly IExamGradeService _examGradeService;
private readonly ISysDictDataService _sysDictDataService;
private readonly ISchoolClassService _schoolClassService;
private readonly IResourceFileService _resourceFileService;
private readonly ICourseService _courseService;
public ExamAbsentReplaceService(IRepository rep, IExamGradeService examGradeService, ISysDictDataService sysDictDataService, ISchoolClassService schoolClassService, IResourceFileService resourceFileService, ICourseService courseService)
{
_rep = rep;
_examGradeService = examGradeService;
_sysDictDataService = sysDictDataService;
_schoolClassService = schoolClassService;
_resourceFileService = resourceFileService;
_courseService = courseService;
}
#region 批量导入
///
/// 上传监测缺测替补批量导入文件
///
///
///
///
public async Task> Upload(string filePath, int examPlanId)
{
UploadExamDataOutput result = new();
try
{
using FileStream fs = new(filePath, FileMode.Open, FileAccess.Read);
IWorkbook workbook = ExcelUtil.GetWorkbook(filePath, fs);
var sheet = workbook.GetSheetAt(0);
var rows = sheet.GetRowEnumerator();
#region 验证表结构
// 少于2行验证
if (sheet.LastRowNum < 2)
{
result.ErrorMessage.Add("第一行应为填写说明,第二行应为标题行,请勿修改模板结构。");
return result;
}
// 跳过第一行
rows.MoveNext();
// 读取表头
rows.MoveNext();
IRow headerRow = (IRow)rows.Current;
int index = 0;
int GRADE_INDEX = index++;
int CLASS_INDEX = index++;
int NAME_INDEX = index++;
int EXAM_NUM_INDEX = index++;
int REASON_INDEX = index++;
int COURSES_INDEX = index++;
int TEL_INDEX = index++;
int REPLACE_NAME_INDEX = index++;
int REPLACE_EXAM_NUM_INDEX = index++;
int REMARK_INDEX = index;
Dictionary headers = new()
{
{ GRADE_INDEX, "年级号" },
{ CLASS_INDEX, "班级号" },
{ NAME_INDEX, "缺测学生姓名" },
{ EXAM_NUM_INDEX, "缺测学生监测号" },
{ REASON_INDEX, "缺测原因" },
{ COURSES_INDEX, "缺测科目" },
{ TEL_INDEX, "缺测学生家长电话" },
{ REPLACE_NAME_INDEX, "替补学生姓名" },
{ REPLACE_EXAM_NUM_INDEX, "替补学生监测号" },
{ REMARK_INDEX, "备注" },
};
List headerErrors = new();
for (int i = 0; i <= index; i++)
{
if (headerRow.GetCell(i)?.ToString() != headers[i])
{
char letter = (char)('A' + i);
headerErrors.Add(letter.ToString());
}
}
if (headerErrors.Any())
{
string columnErrors = string.Join("、", headerErrors);
result.ErrorMessage.Add($"第2行标题行{columnErrors}列名错误。从A列开始依次应为年级号、班级号、缺测学生姓名、缺测学生监测号、缺测原因、缺测科目、家长电话、替补学生姓名、替补学生监测号和备注。");
return result;
}
result.StructureCorrect = true;
#endregion
#region 处理数据
// 监测年级
var examGrades = await _examGradeService.GetListByExamPlanId(examPlanId);
// 科目列表
var courses = await _courseService.GetAllLiteList();
// 科目字典
var courseDicts = courses.ToDictionary(t => t.Name);
// 读取数据
List data = new();
int rn = 0;
while (rows.MoveNext())
{
IRow row = (IRow)rows.Current;
string rv = row.GetCell(0)?.ToString().Trim() ?? "";
rv += row.GetCell(1)?.ToString().Trim() ?? "";
if (rv == "")
{
break;
}
UploadExamAbsentReplaceOutput item = new() { RowNumber = ++rn };
// 年级
if (short.TryParse(row.GetCell(GRADE_INDEX)?.ToString(), out short gradeNumber))
{
var g = examGrades.FirstOrDefault(t => t.Grade.GradeNumber == gradeNumber);
if (g == null)
{
item.ErrorMessage.Add($"{headers[GRADE_INDEX]}与监测年级不符");
}
else
{
item.ExamGradeId = g.Id;
item.GradeId = g.GradeId;
}
}
else
{
item.ErrorMessage.Add(headers[CLASS_INDEX]);
}
// 班级
if (short.TryParse(row.GetCell(CLASS_INDEX)?.ToString(), out short classNumber))
{
item.ClassNumber = classNumber;
if (item.ClassNumber < 1 || item.ClassNumber > 35)
{
item.ErrorMessage.Add($"{headers[CLASS_INDEX]}超限");
}
}
else
{
item.ErrorMessage.Add(headers[CLASS_INDEX]);
}
// 缺测学生姓名
item.AbsentName = (row.GetCell(NAME_INDEX)?.ToString() ?? "").ClearWhitespace();
if (item.AbsentName == "" || item.AbsentName.Length > 100)
{
item.ErrorMessage.Add($"{headers[NAME_INDEX]}未填或超出100字");
}
if (item.AbsentName.Length > 100) { item.AbsentName = item.AbsentName[..100]; }
// 缺测学生监测号
item.AbsentExamNumber = (row.GetCell(EXAM_NUM_INDEX)?.ToString() ?? "").ClearWhitespace().ToUpper();
if (item.AbsentExamNumber == "" || item.AbsentExamNumber.Length > 20)
{
item.ErrorMessage.Add($"{headers[EXAM_NUM_INDEX]}格式错误");
}
if (item.AbsentExamNumber.Length > 20) { item.AbsentExamNumber = item.AbsentExamNumber[..20]; }
// 缺测原因
item.AbsentReason = (row.GetCell(REASON_INDEX)?.ToString() ?? "").ClearWhitespace();
if (item.AbsentReason == "" || item.AbsentReason.Length > 200)
{
item.ErrorMessage.Add($"{headers[REASON_INDEX]}未填或超出200字");
}
if (item.AbsentReason.Length > 200) { item.AbsentReason = item.AbsentReason[..200]; }
// 缺测科目
item.AbsentCourseText = (row.GetCell(COURSES_INDEX)?.ToString() ?? "").ClearWhitespace();
if (item.AbsentCourseText == "")
{
item.ErrorMessage.Add($"{headers[COURSES_INDEX]}未填");
}
else
{
var acourses = GetCourses(courseDicts, item.AbsentCourseText);
item.AbsentCourseList = acourses.courses;
if (acourses.errorMessage.Count > 0)
{
item.ErrorMessage.Add($"{headers[COURSES_INDEX]}({string.Join("、", acourses.errorMessage)})名称错误");
}
}
// 缺测学生家长电话
item.PatriarchTel = (row.GetCell(TEL_INDEX)?.ToString() ?? "").ClearWhitespace();
if (item.PatriarchTel == "" || item.PatriarchTel.Length > 50)
{
item.ErrorMessage.Add($"{headers[TEL_INDEX]}未填或超出50字");
}
if (item.PatriarchTel.Length > 50) { item.PatriarchTel = item.PatriarchTel[..50]; }
// 替补学生姓名
item.ReplaceName = (row.GetCell(REPLACE_NAME_INDEX)?.ToString() ?? "").ClearWhitespace();
if (item.ReplaceName.Length > 100) { item.ReplaceName = item.ReplaceName[..100]; }
// 替补学生监测号
item.ReplaceExamNumber = (row.GetCell(REPLACE_EXAM_NUM_INDEX)?.ToString() ?? "").ClearWhitespace().ToUpper();
if (item.ReplaceExamNumber.Length > 20) { item.ReplaceExamNumber = item.ReplaceExamNumber[..20]; }
if (item.ReplaceName.Length == 0 && item.ReplaceExamNumber.Length != 0 || item.ReplaceName.Length != 0 && item.ReplaceExamNumber.Length == 0)
{
item.ErrorMessage.Add($"有替补时替补学生姓名和监测号必须都填写");
}
// 备注
item.Remark = (row.GetCell(REMARK_INDEX)?.ToString() ?? "").ClearWhitespace();
if (item.Remark.Length > 200) { item.Remark = item.Remark[..200]; }
// 行是否验证通过
item.IsSuccess = item.ErrorMessage.Count == 0;
data.Add(item);
result.TotalRowCount++;
if (!item.IsSuccess)
{
result.ErrorRowCount++;
}
}
result.Rows = data;
#endregion
workbook.Close();
fs.Close();
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
finally
{
File.Delete(filePath);
}
return result;
}
///
/// 批量导入监测缺测替补
///
///
///
public async Task Import(ImportExamAbsentReplaceInput input)
{
var orgId = input.SysOrgId ?? CurrentSysUserInfo.SysOrgId;
var existsIdNumberList = await _rep.DetachedEntities.Where(t => t.ExamPlanId == input.ExamPlanId && t.SysOrgId == orgId).Select(t => t.AbsentExamNumber).Distinct().ToListAsync() ?? new List();
List items = new();
var spStus = input.Items.Where(t => !existsIdNumberList.Contains(t.AbsentExamNumber)).ToList();
var gs = spStus.Select(t => t.ExamGradeId).Distinct().ToList();
var examGrades = await _rep.Change().DetachedEntities.Where(t => gs.Contains(t.Id)).Select(t => t.Adapt()).ToListAsync();
int c = 0;
foreach (var eg in examGrades)
{
var classNumbers = spStus.Where(t => t.ExamGradeId == eg.Id).Select(t => t.ClassNumber).Distinct().ToList();
var classDict = await _schoolClassService.GetImportSchoolClassList(new()
{
SysOrgId = orgId,
SysOrgBranchId = input.SysOrgBranchId,
ExamGrade = eg,
ClassNumberList = classNumbers,
});
var citems = spStus.Where(t => t.ExamGradeId == eg.Id).ToList();
foreach (var ni in citems)
{
var item = ni.Adapt();
item.ExamPlanId = input.ExamPlanId;
item.SysOrgId = orgId;
item.SysOrgBranchId = input.SysOrgBranchId;
item.SchoolClassId = classDict[ni.ClassNumber];
item.AbsentName = item.AbsentName?.ClearWhitespace();
item.AbsentExamNumber = item.AbsentExamNumber?.ClearWhitespace();
item.ReplaceName = item.ReplaceName?.ClearWhitespace();
item.ReplaceExamNumber = item.ReplaceExamNumber?.ClearWhitespace();
items.Add(item);
c++;
}
}
await _rep.InsertAsync(items);
return c;
}
#endregion
#region 创建编辑
///
/// 添加监测缺测替补
///
///
///
public async Task Add(AddExamAbsentReplaceInput input)
{
var orgId = CurrentSysUserInfo.SysOrgId;
// 检测同一监测计划中同机构内是否有相同监测号的学生
var sameItems = await _rep.DetachedEntities.Where(t => t.ExamPlanId == input.ExamPlanId && t.SysOrgId == orgId && t.AbsentExamNumber.ToUpper() == input.AbsentExamNumber.ToUpper()).ProjectToType().ToListAsync();
if (sameItems.Any())
{
throw Oops.Oh(ErrorCode.E2003, string.Join("、", sameItems.Select(t => $"{t.ExamGrade.Grade.Name}{t.ClassNumber}班{t.AbsentName}")), "监测号");
}
var examGrade = await _examGradeService.GetById(input.ExamGradeId);
var schoolClass = await _schoolClassService.GetSchoolClass(orgId, input.SysOrgBranchId, examGrade, input.ClassNumber);
var item = input.Adapt();
item.SysOrgId = orgId;
item.SchoolClassId = schoolClass.Id;
item.AbsentName = item.AbsentName?.ClearWhitespace();
item.AbsentExamNumber = item.AbsentExamNumber?.ClearWhitespace();
item.ReplaceName = item.ReplaceName?.ClearWhitespace();
item.ReplaceExamNumber = item.ReplaceExamNumber?.ClearWhitespace();
await item.InsertAsync();
}
///
/// 更新监测缺测替补
///
///
///
public async Task Update(UpdateExamAbsentReplaceInput input)
{
var oitem = await _rep.DetachedEntities.FirstOrDefaultAsync(t => t.Id == input.Id) ?? throw Oops.Oh(ErrorCode.E2001);
var examGrade = await _examGradeService.GetById(oitem.ExamGradeId);
var schoolClass = await _schoolClassService.GetSchoolClass(oitem.SysOrgId, input.SysOrgBranchId, examGrade, input.ClassNumber);
var item = input.Adapt();
item.SchoolClassId = schoolClass.Id;
item.AbsentName = item.AbsentName?.ClearWhitespace();
item.AbsentExamNumber = item.AbsentExamNumber?.ClearWhitespace();
item.ReplaceName = item.ReplaceName?.ClearWhitespace();
item.ReplaceExamNumber = item.ReplaceExamNumber?.ClearWhitespace();
await item.UpdateIncludeAsync(new[] {
nameof(item.SysOrgBranchId),
nameof(item.SchoolClassId),
nameof(item.ClassNumber),
nameof(item.AbsentName),
nameof(item.AbsentExamNumber),
nameof(item.AbsentReason),
nameof(item.AbsentCourses),
nameof(item.IsReplaced),
nameof(item.ReplaceName),
nameof(item.ReplaceExamNumber),
nameof(item.Remark),
nameof(item.PatriarchName),
nameof(item.PatriarchTel),
});
}
///
/// 添加缺测替补佐证材料
///
///
///
public async Task AddAttachment(AddAttachmentInput input)
{
var item = await _rep.FirstOrDefaultAsync(t => t.Id == input.SourceId) ?? throw Oops.Oh(ErrorCode.E2001);
item.Attachments = AttachmentUtil.InsertInto(item.Attachments, input.Adapt());
await item.UpdateIncludeAsync(new[] { nameof(item.Attachments) });
}
///
/// 删除缺测替补佐证材料
///
///
///
public async Task DelAttachment(DeleteAttachmentInput input)
{
var item = await _rep.FirstOrDefaultAsync(t => t.Id == input.SourceId) ?? throw Oops.Oh(ErrorCode.E2001);
var attachments = AttachmentUtil.GetList(item.Attachments);
var a = attachments.FirstOrDefault(t => t.FileId == input.FileId);
if (a != null)
{
attachments.Remove(a);
item.Attachments = JSON.Serialize(attachments);
await item.UpdateIncludeAsync(new[] { nameof(item.Attachments) });
await _resourceFileService.Del(new() { Id = a.FileId });
if (a.ThumbFileId.HasValue && a.ThumbFileId > 0)
{
await _resourceFileService.Del(new() { Id = a.ThumbFileId.Value });
}
}
}
///
/// 验证缺测替补佐证材料
///
///
///
public async Task VerifyAttachment(int examPlanId)
{
var items = await _rep.DetachedEntities.Where(t => t.ExamPlanId == examPlanId && t.SysOrgId == CurrentSysUserInfo.SysOrgId).ProjectToType().ToListAsync();
if (items.Any(t => t.AttachmentList.Count == 0))
{
return false;
}
return true;
}
///
/// 删除监测缺测替补
///
///
///
public async Task Del(BaseId input)
{
var item = await _rep.FirstOrDefaultAsync(t => t.Id == input.Id) ?? throw Oops.Oh(ErrorCode.E2001);
var attachments = JSON.Deserialize>(item.Attachments);
if (attachments != null && attachments.Any())
{
foreach (var attachment in attachments)
{
await _resourceFileService.Del(new() { Id = attachment.FileId });
if (attachment.ThumbFileId.HasValue && attachment.ThumbFileId > 0)
{
await _resourceFileService.Del(new() { Id = attachment.ThumbFileId.Value });
}
}
}
await item.DeleteAsync();
}
///
/// 清空监测缺测替补
///
///
///
public async Task Clear(ClearExamAbsentReplaceInput input)
{
var orgId = CurrentSysUserInfo.SysOrgId;
await _rep.Where(t => t.ExamPlanId == input.ExamPlanId && t.SysOrgId == orgId).ExecuteDeleteAsync();
}
///
/// 导出监测缺测替补上报打印表格
///
///
///
public async Task ExportPrintTable(int examPlanId)
{
var items = await _rep.DetachedEntities.Include(t => t.Grade).Include(t => t.SysOrg).Where(t => t.ExamPlanId == examPlanId && t.SysOrgId == CurrentSysUserInfo.SysOrgId).ToListAsync();
if (!items.Any())
{
throw Oops.Oh(ErrorCode.E2001);
}
// 获取证件类型
var cts = await _sysDictDataService.GetListByDictTypeId(304);
var certificateTypes = cts.ToDictionary(x => (CertificateType)x.Value, y => y.Name);
XWPFDocument doc = new();
doc.Document.body.sectPr = new();
var sectPr = doc.Document.body.sectPr;
sectPr.pgSz.orient = ST_PageOrientation.landscape;
sectPr.pgSz.w = 16838;
sectPr.pgSz.h = 11906;
sectPr.pgMar.left = sectPr.pgMar.right = 1080;
sectPr.pgMar.top = sectPr.pgMar.bottom = 1440;
var gradeItems = items.GroupBy(t => t.GradeId).OrderBy(t => t.Key).ToList();
int pi = 0;
foreach (var gitem in gradeItems)
{
var gradeFirst = gitem.First();
// 多于一个年级分多页
if (0 < pi++)
{
doc.CreateParagraph().IsPageBreak = true;
}
// 标题行
XWPFParagraph pHeader = doc.CreateParagraph();
pHeader.Alignment = ParagraphAlignment.CENTER;
pHeader.SpacingLineRule = LineSpacingRule.AUTO;
pHeader.SetSpacingBetween(1.5, LineSpacingRule.AUTO);
var pHeaderRun = pHeader.CreateRun();
pHeaderRun.SetText($"{gradeFirst.SysOrg.FullName.Replace("重庆市", "").Replace("重庆", "")}缺测替补明细表({gradeFirst.Grade.Name})");
pHeaderRun.FontSize = 18;
pHeaderRun.IsBold = true;
// 空行
CreateBlanParagraph();
// 签字行
XWPFParagraph pSign = doc.CreateParagraph();
pSign.SpacingLineRule = LineSpacingRule.AUTO;
pSign.SetSpacingBetween(2, LineSpacingRule.AUTO);
var pSignRun = pSign.CreateRun();
pSignRun.SetText("学校盖章: 纪检负责人: 校长签字:");
pSignRun.FontSize = 12;
// 签字行
XWPFParagraph pCount = doc.CreateParagraph();
pCount.SpacingLineRule = LineSpacingRule.AUTO;
pCount.SetSpacingBetween(2, LineSpacingRule.AUTO);
var dt = DateTime.Now;
var pCountRun = pCount.CreateRun();
pCountRun.SetText($"填表人: 联系电话: 督考签字: 缺测替补计({gitem.Count()})人 {dt.Year}年{dt.Month}月{dt.Day}日");
pCountRun.FontSize = 12;
// 空行
CreateBlanParagraph(1);
#region 生成表格
const int COLUMN_COUNT = 10;
XWPFTable table = doc.CreateTable(gitem.Count() + 2, COLUMN_COUNT);
var tableLayout = table.GetCTTbl().tblPr.AddNewTblLayout();
tableLayout.type = ST_TblLayoutType.@fixed;
table.Width = 5080;
table.SetColumnWidth(0, 280);
table.SetColumnWidth(1, 280);
table.SetColumnWidth(2, 540);
table.SetColumnWidth(3, 640);
table.SetColumnWidth(4, 1000);
table.SetColumnWidth(5, 1200);
table.SetColumnWidth(6, 660);
table.SetColumnWidth(7, 540);
table.SetColumnWidth(8, 640);
table.SetColumnWidth(9, 660);
int ri = 0;
table.GetRow(ri).GetCTRow().AddNewTrPr().AddNewTrHeight().val = 480;
table.GetRow(ri).GetCell(0).SetParagraph(SetCellText(table, "序号", ParagraphAlignment.CENTER, true));
table.GetRow(ri).GetCell(1).SetParagraph(SetCellText(table, "班级", ParagraphAlignment.CENTER, true));
table.GetRow(ri).GetCell(2).SetParagraph(SetCellText(table, "学生姓名", ParagraphAlignment.CENTER, true));
table.GetRow(ri).GetCell(3).SetParagraph(SetCellText(table, "监测号", ParagraphAlignment.CENTER, true));
table.GetRow(ri).GetCell(4).SetParagraph(SetCellText(table, "缺测原因", ParagraphAlignment.CENTER, true));
table.GetRow(ri).GetCell(5).SetParagraph(SetCellText(table, "缺测科目", ParagraphAlignment.CENTER, true));
table.GetRow(ri).GetCell(6).SetParagraph(SetCellText(table, "家长电话", ParagraphAlignment.CENTER, true));
table.GetRow(ri).GetCell(7).SetParagraph(SetCellText(table, "有替补学生", ParagraphAlignment.CENTER, true));
table.GetRow(ri).GetCell(8).SetParagraph(SetCellText(table, null, ParagraphAlignment.CENTER, true));
table.GetRow(ri).GetCell(9).SetParagraph(SetCellText(table, "备注", ParagraphAlignment.CENTER, true));
for (int ci = 0; ci < COLUMN_COUNT; ci++)
{
table.GetRow(ri).GetCell(ci).GetCTTc().AddNewTcPr().AddNewVAlign().val = ST_VerticalJc.center;
}
ri++;
table.GetRow(ri).GetCTRow().AddNewTrPr().AddNewTrHeight().val = 480;
table.GetRow(ri).GetCell(7).SetParagraph(SetCellText(table, "姓名", ParagraphAlignment.CENTER, true));
table.GetRow(ri).GetCell(7).GetCTTc().AddNewTcPr().AddNewVAlign().val = ST_VerticalJc.center;
table.GetRow(ri).GetCell(8).SetParagraph(SetCellText(table, "监测号", ParagraphAlignment.CENTER, true));
table.GetRow(ri).GetCell(8).GetCTTc().AddNewTcPr().AddNewVAlign().val = ST_VerticalJc.center;
MergeCells(table, 9, 9, ri - 1, ri);
MergeCells(table, 7, 8, ri - 1, ri - 1);
for (int i = 0; i < 7; i++)
{
MergeCells(table, i, i, ri - 1, ri);
}
int tableRowNumber = 1;
foreach (var item in gitem)
{
var courses = JSON.Deserialize>(item.AbsentCourses);
var courseText = string.Join("、", courses.Select(t => t.Name));
ri++;
table.GetRow(ri).GetCTRow().AddNewTrPr().AddNewTrHeight().val = 480;
table.GetRow(ri).GetCell(0).SetParagraph(SetCellText(table, $"{tableRowNumber++}", ParagraphAlignment.CENTER));
table.GetRow(ri).GetCell(1).SetParagraph(SetCellText(table, $"{item.ClassNumber}", ParagraphAlignment.CENTER));
table.GetRow(ri).GetCell(2).SetParagraph(SetCellText(table, item.AbsentName, ParagraphAlignment.CENTER));
table.GetRow(ri).GetCell(3).SetParagraph(SetCellText(table, item.AbsentExamNumber, ParagraphAlignment.CENTER));
table.GetRow(ri).GetCell(4).SetParagraph(SetCellText(table, item.AbsentReason, ParagraphAlignment.LEFT));
table.GetRow(ri).GetCell(5).SetParagraph(SetCellText(table, courseText, ParagraphAlignment.LEFT));
table.GetRow(ri).GetCell(6).SetParagraph(SetCellText(table, item.PatriarchTel, ParagraphAlignment.CENTER));
table.GetRow(ri).GetCell(7).SetParagraph(SetCellText(table, item.ReplaceName, ParagraphAlignment.CENTER));
table.GetRow(ri).GetCell(8).SetParagraph(SetCellText(table, item.ReplaceExamNumber, ParagraphAlignment.CENTER));
table.GetRow(ri).GetCell(9).SetParagraph(SetCellText(table, item.Remark, ParagraphAlignment.LEFT));
for (int ci = 0; ci < COLUMN_COUNT; ci++)
{
table.GetRow(ri).GetCell(ci).GetCTTc().AddNewTcPr().AddNewVAlign().val = ST_VerticalJc.center;
}
}
// 空行
CreateBlanParagraph();
#endregion
}
// 生成流
using MemoryStream ms = new();
doc.Write(ms);
doc.Close();
var retDoc = ms.ToArray();
ms.Close();
return retDoc;
// 创建空行
void CreateBlanParagraph(double lineSpacing = 1.5)
{
var p = doc.CreateParagraph();
p.SpacingLineRule = LineSpacingRule.AUTO;
p.SetSpacingBetween(lineSpacing, LineSpacingRule.AUTO);
p.CreateRun().FontSize = 12;
}
}
#endregion
#region 查询统计
///
/// 分页查询监测缺测替补列表
///
///
///
public async Task> QueryPageList(ExamAbsentReplacePageInput input)
{
var orgId = input.SysOrgId ?? CurrentSysUserInfo.SysOrgId;
var query = GetQueryBase(input);
var ret = await query.OrderBy(t => t.GradeId).ThenBy(t => t.ClassNumber).ThenBy(t => t.Id)
.ProjectToType()
.ToADPagedListAsync(input.PageIndex, input.PageSize);
return ret;
}
///
/// 分页查询监测缺测替补列表
///
///
///
public async Task> QueryAuditPageList(ExamAbsentReplacePageInput input)
{
var orgId = input.SysOrgId ?? CurrentSysUserInfo.SysOrgId;
var query = GetQueryBase(input);
var ret = await query.OrderBy(t => t.GradeId).ThenBy(t => t.ClassNumber).ThenBy(t => t.Id)
.ProjectToType()
.ToADPagedListAsync(input.PageIndex, input.PageSize);
return ret;
}
///
/// 获取机构班级缺测替补上报人数统计列表
///
///
///
///
public async Task GetOrgGradeClassStudentCount(int examPlanId, short? sysOrgId = null)
{
var orgId = sysOrgId ?? CurrentSysUserInfo.SysOrgId;
var items = await _rep.DetachedEntities.Where(t => t.ExamPlanId == examPlanId && t.SysOrgId == orgId)
.GroupBy(t => new { t.GradeId, t.ClassNumber })
.Select(t => new
{
t.Key.GradeId,
t.Key.ClassNumber,
t.FirstOrDefault().Grade,
Count = t.Count(),
})
.ToListAsync();
var cols = items.Select(t => t.ClassNumber).Distinct().ToList();
var retItems = items.ToPivotList(c => c.ClassNumber, r => r.GradeId, d => d.Any() ? d.Sum(x => x.Count) : 0);
foreach (var item in retItems)
{
item.Grade = items.FirstOrDefault(t => t.GradeId == item.GradeId).Grade;
item.GradeTotal = items.Where(t => t.GradeId == item.GradeId).Sum(x => x.Count);
}
int total = retItems.Sum(x => x.GradeTotal);
IDictionary totalItem = new ExpandoObject();
totalItem.Add("GradeId", 9999);
totalItem.Add("Grade", new { Id = 9999, Name = "合计" });
totalItem.Add("GradeTotal", total);
retItems.Add(totalItem);
return new()
{
ClassNumberList = cols,
Items = retItems,
Total = total,
};
}
///
/// 获取状态数量
///
///
public async Task> QueryStatusCount(ExamAbsentReplacePageInput input)
{
var query = GetQueryBase(input);
if (query == null)
{
return new List();
}
var counts = await query.GroupBy(t => t.Status).Select(t => new StatusCount { Status = (int)t.Key, Count = t.Count() }).ToListAsync();
return counts;
}
#endregion
#region 私有方法
///
/// 构建查询
///
///
///
private IQueryable GetQueryBase(ExamAbsentReplacePageInput input)
{
var orgId = input.SysOrgId ?? CurrentSysUserInfo.SysOrgId;
var absentName = !string.IsNullOrEmpty(input.AbsentName?.Trim());
var absentExamNumber = !string.IsNullOrEmpty(input.AbsentExamNumber?.Trim());
var absentReason = !string.IsNullOrEmpty(input.AbsentReason?.Trim());
var replaceName = !string.IsNullOrEmpty(input.ReplaceName?.Trim());
var replaceExamNumber = !string.IsNullOrEmpty(input.ReplaceExamNumber?.Trim());
var patriarchTel = !string.IsNullOrEmpty(input.PatriarchTel?.Trim());
var remark = !string.IsNullOrEmpty(input.Remark?.Trim());
var query = _rep.DetachedEntities.Where(t => t.ExamPlanId == input.ExamPlanId && t.SysOrgId == orgId)
.Where((absentName, u => EF.Functions.Like(u.AbsentName, $"%{input.AbsentName.Trim()}%")))
.Where((absentExamNumber, u => EF.Functions.Like(u.AbsentExamNumber, $"%{input.AbsentExamNumber.Trim()}%")))
.Where((absentReason, u => EF.Functions.Like(u.AbsentReason, $"%{input.AbsentReason.Trim()}%")))
.Where((replaceName, u => EF.Functions.Like(u.ReplaceName, $"%{input.ReplaceName.Trim()}%")))
.Where((replaceExamNumber, u => EF.Functions.Like(u.ReplaceExamNumber, $"%{input.ReplaceExamNumber.Trim()}%")))
.Where((patriarchTel, u => EF.Functions.Like(u.PatriarchTel, $"%{input.PatriarchTel.Trim()}%")))
.Where((remark, u => EF.Functions.Like(u.Remark, $"%{input.Remark.Trim()}%")))
.Where((input.AbentCourseId.HasValue, u => EF.Functions.Like(u.AbsentCourses, $"%{input.AbentCourseId}%")))
.Where(input.Status.HasValue, t => t.Status == input.Status)
.Where(input.IsReplaced.HasValue, t => t.IsReplaced == input.IsReplaced)
.Where(input.GradeId.HasValue, t => t.GradeId == input.GradeId)
.Where(input.ClassNumber.HasValue, t => t.ClassNumber == input.ClassNumber)
.Where(input.SysOrgBranchId.HasValue, t => t.SchoolClass.SysOrgBranchId == input.SysOrgBranchId);
return query;
}
///
/// 根据科目字符串组合获取科目列表
///
/// 科目字典
/// 科目组合
///
private static (List errorMessage, List courses) GetCourses(Dictionary courseDict, string courses)
{
List ret = [];
List errs = [];
var cns = courses.ClearWhitespace().Split(['、', ',', ',', ';', ';']);
foreach (var cn in cns)
{
if (courseDict.TryGetValue(cn, out CourseLiteOutput c))
{
if (ret.Any(t => t.Id != c.Id))
{
ret.Add(c.Adapt());
}
}
else
{
errs.Add(cn);
}
}
return (errs, ret);
}
///
/// 设置单元格文本
///
///
///
///
///
///
private static XWPFParagraph SetCellText(XWPFTable table, string text, ParagraphAlignment align = ParagraphAlignment.CENTER, bool isBold = false)
{
CT_P para = new();
XWPFParagraph pCell = new(para, table.Body)
{
Alignment = align,
VerticalAlignment = TextAlignment.CENTER,
};
XWPFRun r1 = pCell.CreateRun();
r1.SetText(text);
r1.FontSize = 11;
r1.FontFamily = "宋体";
r1.IsBold = isBold;
return pCell;
}
///
/// 合并单元格
///
///
///
///
///
///
///
private static XWPFTableCell MergeCells(XWPFTable table, int fromCol, int toCol, int fromRow, int toRow)
{
for (int rowIndex = fromRow; rowIndex <= toRow; rowIndex++)
{
if (fromCol < toCol)
{
table.GetRow(rowIndex).MergeCells(fromCol, toCol);
}
XWPFTableCell rowcell = table.GetRow(rowIndex).GetCell(fromCol);
CT_Tc cttc = rowcell.GetCTTc();
if (cttc.tcPr == null)
{
cttc.AddNewTcPr();
}
if (rowIndex == fromRow)
{
// The first merged cell is set with RESTART merge value
rowcell.GetCTTc().tcPr.AddNewVMerge().val = ST_Merge.restart;
}
else
{
// Cells which join (merge) the first one, are set with CONTINUE
rowcell.GetCTTc().tcPr.AddNewVMerge().val = ST_Merge.@continue;
}
}
table.GetRow(fromRow).GetCell(fromCol).SetVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
//table.GetRow(fromRow).GetCell(fromCol).Paragraphs[0].Alignment = ParagraphAlignment.CENTER;
table.GetRow(fromRow).GetCell(fromCol).Paragraphs[0].Alignment = ParagraphAlignment.LEFT;
return table.GetRow(fromRow).GetCell(fromCol);
}
#endregion
}