fix: 考试收集优化
This commit is contained in:
parent
9c53c18db9
commit
0043320cd4
|
|
@ -1,10 +1,14 @@
|
|||
using Dolphin.ExamPictureCut.Constants;
|
||||
using Dolphin.ExamPictureCut.Domains;
|
||||
using Dolphin.ExamPictureCut.Domains.Basic;
|
||||
using Dolphin.ExamPictureCut.Domains.Biz;
|
||||
using Dolphin.ExamPictureCut.Domains.Quest;
|
||||
using Dolphin.ExamPictureCut.Exams.Dto;
|
||||
using Dolphin.ExamPictureCut.Extensions;
|
||||
using Dolphin.ExamPictureCut.Options;
|
||||
using Flurl.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json;
|
||||
using NoFurion;
|
||||
using NoFurion.SqlSugar;
|
||||
|
|
@ -12,6 +16,7 @@ using SkiaSharp;
|
|||
using SqlSugar;
|
||||
using Volo.Abp.BlobStoring;
|
||||
using Volo.Abp.Domain.Services;
|
||||
using Volo.Abp.Uow;
|
||||
using Yitter.IdGenerator;
|
||||
|
||||
namespace Dolphin.ExamPictureCut.Exams;
|
||||
|
|
@ -19,7 +24,9 @@ namespace Dolphin.ExamPictureCut.Exams;
|
|||
public class ExamManager : DomainService, IExamManager
|
||||
{
|
||||
private readonly ISqlSugarClient Db;
|
||||
private readonly ISqlSugarClient DbPenOffline;
|
||||
private readonly IBlobContainer _blobContainer;
|
||||
private readonly AliyunOption _aliyunOption;
|
||||
private readonly SKPaint skPaint = new SKPaint
|
||||
{
|
||||
Color = SKColors.Black,
|
||||
|
|
@ -28,20 +35,22 @@ public class ExamManager : DomainService, IExamManager
|
|||
StrokeWidth = 1,
|
||||
StrokeCap = SKStrokeCap.Round,
|
||||
};
|
||||
public ExamManager(ISqlSugarClient db, IBlobContainer blobContainer)
|
||||
public ExamManager(ISqlSugarClient db, IBlobContainer blobContainer, IOptions<AliyunOption> aliyunOption)
|
||||
{
|
||||
Db = db;
|
||||
DbPenOffline = (db as SqlSugarScope).GetConnection(DbConsts.penoffline);
|
||||
_blobContainer = blobContainer;
|
||||
_aliyunOption = aliyunOption.Value;
|
||||
}
|
||||
|
||||
[UnitOfWork(false)]
|
||||
public async Task ExamStudentGather(ExamStudentGatherEto eto)
|
||||
{
|
||||
var penSerial = eto.StudentExamNum;
|
||||
Logger.LogInformation("{ExamSubjectId} {penSerial} 开始收集...", eto.ExamSubjectId, penSerial);
|
||||
var guid = GuidGenerator.Create().ToString("N");
|
||||
|
||||
var templateIds = JsonConvert.DeserializeObject<List<string>>(eto.TemplateId);
|
||||
var templates = await Db.Queryable<GroupBookPaperTemplate>().Where(w => templateIds.Contains(w.Id))
|
||||
var templates = await Db.Queryable<GroupBookPaperTemplate>().Where(w => w.BookId == eto.BookId)
|
||||
.Select(s => new { s.Id, s.PaperId, s.PartId, s.PageIndex, s.ImgUrl, s.QueData, s.Order }).ToListAsync();
|
||||
var paperInfo = templates.Select(s =>
|
||||
{
|
||||
|
|
@ -61,8 +70,9 @@ public class ExamManager : DomainService, IExamManager
|
|||
var paperIds = templates.Select(s => s.PaperId).ToList();
|
||||
|
||||
// 获取点阵数据
|
||||
var lattices = await Db.Queryable<PenOfflineData>()
|
||||
.Where(w => w.PenSerial == penSerial && paperIds.Contains(w.PageSerial) && w.logType == LogType.作业)
|
||||
var timespan = (long)(eto.LastCollectTime - new DateTime(1970, 1, 1, 0, 0, 0)).TotalMilliseconds;
|
||||
var lattices = await DbPenOffline.Queryable<PenOfflineData>()
|
||||
.Where(w => w.PenSerial == penSerial && paperIds.Contains(w.PageSerial) && w.logType == LogType.作业 && w.Time <= timespan)
|
||||
.Select(s => new PenOfflineData
|
||||
{
|
||||
PageSerial = s.PageSerial,
|
||||
|
|
@ -71,23 +81,26 @@ public class ExamManager : DomainService, IExamManager
|
|||
Time = s.Time,
|
||||
strokeIndex = s.strokeIndex,
|
||||
}).ToListAsync();
|
||||
|
||||
var DbBiz = await GetTenantDb(eto.SchoolId);
|
||||
await DbBiz.Updateable<ExamSubjectSchoolStudent>().SetColumns(s => s.CollectStatus == 2).Where(w => w.ExamSubjectSchoolId == eto.ExamSubjectSchoolId && w.StudentExamNum == penSerial).ExecuteCommandAsync();
|
||||
|
||||
if (lattices.Count == 0)
|
||||
{
|
||||
Logger.LogInformation("{ExamSubjectId} {penSerial} 无点阵数据", eto.ExamSubjectId, penSerial);
|
||||
return;
|
||||
}
|
||||
|
||||
var DbBiz = await GetTenantDb(eto.SchoolId);
|
||||
var kgtDtls = await DbBiz.Queryable<MarkingSettingObjective>()
|
||||
.Where(w => w.ExamSubjectId == eto.ExamSubjectId)
|
||||
.Select(s => new MkExamResult
|
||||
{
|
||||
Id = YitIdHelper.NextId(),
|
||||
StudentNo = penSerial,
|
||||
ExamId = eto.ExamId,
|
||||
ExamId = eto.ExamSubjectSchoolId,
|
||||
ExamSubjectId = eto.ExamSubjectId,
|
||||
QuestionNumber = s.QuestionNum,
|
||||
IsObjectiveQuestion = true,
|
||||
QuestionValue = string.Empty,
|
||||
GroupNo = guid,
|
||||
}).ToListAsync();
|
||||
|
||||
|
|
@ -104,63 +117,77 @@ public class ExamManager : DomainService, IExamManager
|
|||
return;
|
||||
}
|
||||
|
||||
var redisLockKey = "LockKey:" + eto.ExamSubjectId;
|
||||
var redisLockKey = "GatherLockKey:" + eto.ExamSubjectId;
|
||||
var redisLock = await RedisHelper.GetAsync(redisLockKey);
|
||||
if (string.IsNullOrEmpty(redisLock))
|
||||
{
|
||||
await RedisHelper.SetAsync(redisLockKey, "1");
|
||||
foreach (var paper in paperInfo)
|
||||
try
|
||||
{
|
||||
var imgStream = await paper.ImgUrl.GetStreamAsync();
|
||||
var bitmap = SKBitmap.Decode(imgStream);
|
||||
|
||||
var nextPaper = paperInfo.FirstOrDefault(w => w.PartId == paper.PartId && w.PageIndex == paper.PageIndex + 1);
|
||||
|
||||
foreach (var que in paper.QueData)
|
||||
var dotPenOriginalImgs = new List<string>();
|
||||
foreach (var paper in paperInfo)
|
||||
{
|
||||
if (que.type != "2") continue;
|
||||
if (que.options == null || que.options.Count == 0) continue;
|
||||
var imgBytes = await paper.ImgUrl.GetBytesAsync();
|
||||
var bitmap = SKBitmap.Decode(imgBytes);
|
||||
|
||||
var area = que.options[0].AnswerArea;
|
||||
var areaTop = area.pxTop;
|
||||
var areaHeight = area.pxHeight;
|
||||
var sourceRect = new SKRect(0, areaTop, bitmap.Width, areaTop + areaHeight);
|
||||
var nextPaper = paperInfo.FirstOrDefault(w => w.PartId == paper.PartId && w.PageIndex == paper.PageIndex + 1);
|
||||
|
||||
var height = areaHeight;
|
||||
|
||||
SKBitmap nextImgBitmap = null;
|
||||
SKRect nextSourceRect = new();
|
||||
var queOnNextPaper = nextPaper?.QueData.FirstOrDefault(w => w.no == que.no);
|
||||
if (queOnNextPaper?.options?.Count >= 1)
|
||||
foreach (var que in paper.QueData)
|
||||
{
|
||||
var nextImgStream = await nextPaper.ImgUrl.GetStreamAsync();
|
||||
nextImgBitmap = SKBitmap.Decode(nextImgStream);
|
||||
if (que.type != "2") continue;
|
||||
if (que.options == null || que.options.Count == 0) continue;
|
||||
|
||||
var nextArea = queOnNextPaper.options[0].AnswerArea;
|
||||
var nextAreaTop = nextArea.pxTop;
|
||||
var nextAreaHeight = nextArea.pxHeight;
|
||||
height += nextAreaHeight;
|
||||
var dotPenOriginalImg = $"que/{eto.ExamSubjectId}/{que.no}.jpg";
|
||||
if (dotPenOriginalImgs.Contains(dotPenOriginalImg)) continue;
|
||||
|
||||
nextSourceRect = new SKRect(0, nextAreaTop, bitmap.Width, nextAreaTop + nextAreaHeight);
|
||||
}
|
||||
var area = que.options[0].AnswerArea;
|
||||
var areaTop = area.pxTop;
|
||||
var areaHeight = area.pxHeight;
|
||||
var sourceRect = new SKRect(0, areaTop, bitmap.Width, areaTop + areaHeight);
|
||||
|
||||
using (var newBitmap = new SKBitmap(bitmap.Width, height.SSWR(), SKColorType.Rgba8888, SKAlphaType.Premul))
|
||||
{
|
||||
using (var canvas = new SKCanvas(newBitmap))
|
||||
var height = areaHeight;
|
||||
|
||||
SKBitmap nextImgBitmap = null;
|
||||
SKRect nextSourceRect = new();
|
||||
var queOnNextPaper = nextPaper?.QueData.FirstOrDefault(w => w.no == que.no);
|
||||
if (queOnNextPaper?.options?.Count >= 1)
|
||||
{
|
||||
canvas.DrawBitmap(bitmap, sourceRect, new SKRect(0, 0, bitmap.Width, areaHeight));
|
||||
if (nextImgBitmap != null)
|
||||
canvas.DrawBitmap(nextImgBitmap, nextSourceRect, new SKRect(0, areaHeight, bitmap.Width, height));
|
||||
var nextImgBytes = await nextPaper.ImgUrl.GetBytesAsync();
|
||||
nextImgBitmap = SKBitmap.Decode(nextImgBytes);
|
||||
|
||||
var nextArea = queOnNextPaper.options[0].AnswerArea;
|
||||
var nextAreaTop = nextArea.pxTop;
|
||||
var nextAreaHeight = nextArea.pxHeight;
|
||||
height += nextAreaHeight;
|
||||
|
||||
nextSourceRect = new SKRect(0, nextAreaTop, bitmap.Width, nextAreaTop + nextAreaHeight);
|
||||
}
|
||||
|
||||
var dtl = zgtSettingDtls.FirstOrDefault(w => w.QuestionNum == que.no);
|
||||
dtl.DotPenOriginalImg = $"que/{eto.ExamSubjectId}/{paper.Sort}/{que.no}.png";
|
||||
await _blobContainer.SaveAsync(dtl.DotPenOriginalImg, newBitmap.Encode(SKEncodedImageFormat.Png, 100).ToArray(), true);
|
||||
using (var newBitmap = new SKBitmap(bitmap.Width, height.SSWR(), SKColorType.Rgba8888, SKAlphaType.Premul))
|
||||
{
|
||||
using (var canvas = new SKCanvas(newBitmap))
|
||||
{
|
||||
canvas.DrawBitmap(bitmap, sourceRect, new SKRect(0, 0, bitmap.Width, areaHeight));
|
||||
if (nextImgBitmap != null)
|
||||
canvas.DrawBitmap(nextImgBitmap, nextSourceRect, new SKRect(0, areaHeight, bitmap.Width, height));
|
||||
}
|
||||
|
||||
var dtl = zgtSettingDtls.FirstOrDefault(w => w.QuestionNum == que.no);
|
||||
dtl.DotPenOriginalImg = dotPenOriginalImg;
|
||||
await _blobContainer.SaveAsync(dtl.DotPenOriginalImg, newBitmap.Encode(SKEncodedImageFormat.Jpeg, 100).ToArray(), true);
|
||||
dotPenOriginalImgs.Add(dotPenOriginalImg);
|
||||
}
|
||||
}
|
||||
}
|
||||
await DbBiz.Updateable(zgtSettingDtls).UpdateColumns(s => s.DotPenOriginalImg).ExecuteCommandAsync();
|
||||
await RedisHelper.DelAsync(redisLockKey);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("{ExamSubjectId} {penSerial} 收集失败! 原题切割异常: {error}", eto.ExamSubjectId, penSerial, ex);
|
||||
await RedisHelper.DelAsync(redisLockKey);
|
||||
throw;
|
||||
}
|
||||
await Db.Updateable(zgtSettingDtls).UpdateColumns(s => s.DotPenOriginalImg).Where(w => w.DotPenOriginalImg.IsNotNullOrEmpty()).ExecuteCommandAsync();
|
||||
await RedisHelper.SetAsync(redisLockKey, "0");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -173,184 +200,220 @@ public class ExamManager : DomainService, IExamManager
|
|||
}
|
||||
}
|
||||
|
||||
var zgtDtls = zgtSettingDtls.Select(s => new SubjectiveMarkingResult
|
||||
// 锁处理
|
||||
var studentRedisLockKey = "LockKey:" + eto.ExamSubjectId + penSerial;
|
||||
var studentRedisLock = await RedisHelper.GetAsync(studentRedisLockKey);
|
||||
if (studentRedisLock == "1")
|
||||
{
|
||||
Id = YitIdHelper.NextId(),
|
||||
ExamSubjectId = eto.ExamSubjectId,
|
||||
ExamSubjectSchoolId = eto.ExamSubjectSchoolId,
|
||||
StudentExamNum = penSerial,
|
||||
QuestionNum = s.QuestionNum,
|
||||
TotalScore = s.Score,
|
||||
SubQuestionCount = s.SubQuestionCount,
|
||||
SubQuestionDetail = s.SubQuestionDetail,
|
||||
GroupNo = guid,
|
||||
BigQuestionNum = s.BigQuestionNum,
|
||||
IsExcess = s.IsExcess,
|
||||
}).ToList();
|
||||
Logger.LogInformation("{ExamSubjectId} {penSerial} 正在收集中,此次收集跳过", eto.ExamSubjectId, penSerial);
|
||||
return;
|
||||
}
|
||||
await RedisHelper.SetAsync(studentRedisLockKey, "1");
|
||||
|
||||
var kgt = new List<Tuple<string, string>>();
|
||||
var zgt = new List<Tuple<string, string, bool>>(); // 纸张Id, 题号, 是否跨页
|
||||
var pageSerials = new List<string>(); // 需要计算的页
|
||||
foreach (var paper in paperInfo)
|
||||
try
|
||||
{
|
||||
var paperLatts = lattices.Where(w => w.PageSerial == paper.PaperId).ToList();
|
||||
foreach (var que in paper.QueData)
|
||||
var zgtDtls = zgtSettingDtls.Select(s => new SubjectiveMarkingResult
|
||||
{
|
||||
if (que.type == "1") // 客观题
|
||||
Id = YitIdHelper.NextId(),
|
||||
ExamSubjectId = eto.ExamSubjectId,
|
||||
ExamSubjectSchoolId = eto.ExamSubjectSchoolId,
|
||||
StudentExamNum = penSerial,
|
||||
QuestionNum = s.QuestionNum,
|
||||
TotalScore = s.Score,
|
||||
SubQuestionCount = s.SubQuestionCount,
|
||||
SubQuestionDetail = s.SubQuestionDetail,
|
||||
StudentAnswer = $"[\"{_aliyunOption.Host}/{s.DotPenOriginalImg}\"]",
|
||||
GroupNo = guid,
|
||||
BigQuestionNum = s.BigQuestionNum,
|
||||
IsExcess = s.IsExcess,
|
||||
}).ToList();
|
||||
|
||||
var kgt = new List<Tuple<string, string>>();
|
||||
var zgt = new List<Tuple<string, string, bool>>(); // 纸张Id, 题号, 是否跨页
|
||||
var pageSerials = new List<string>(); // 需要计算的页
|
||||
foreach (var paper in paperInfo)
|
||||
{
|
||||
var paperLatts = lattices.Where(w => w.PageSerial == paper.PaperId).ToList();
|
||||
foreach (var que in paper.QueData)
|
||||
{
|
||||
if (que.options.Any() && que.options.Any(opt => paperLatts.Any(s => RectExt.IsRectContainsLattice(opt.AnswerArea, s))))
|
||||
if (que.type == "1") // 客观题
|
||||
{
|
||||
pageSerials.Add(paper.PaperId);
|
||||
kgt.Add(new(paper.PaperId, que.no));
|
||||
}
|
||||
}
|
||||
else if (que.type == "2") // 主观题
|
||||
{
|
||||
if (que.options.Any() && paperLatts.Any(s => RectExt.IsRectContainsLattice(que.options[0].AnswerArea, s)))
|
||||
{
|
||||
pageSerials.Add(paper.PaperId);
|
||||
var ky = false;
|
||||
var quePaperId = paper.PaperId;
|
||||
var queOthPaper = paperInfo.FirstOrDefault(w => w.PartId == paper.PartId && w.PageIndex != paper.PageIndex && w.QueData.Any(s => s.no == que.no));
|
||||
if (queOthPaper != null)
|
||||
if (que.options.Any() && que.options.Any(opt => paperLatts.Any(s => RectExt.IsRectContainsLattice(opt.AnswerArea, s))))
|
||||
{
|
||||
ky = true;
|
||||
if (paper.PageIndex > queOthPaper.PageIndex)
|
||||
{
|
||||
pageSerials.Add(queOthPaper.PaperId);
|
||||
quePaperId = queOthPaper.PaperId;
|
||||
}
|
||||
pageSerials.Add(paper.PaperId);
|
||||
kgt.Add(new(paper.PaperId, que.no));
|
||||
}
|
||||
}
|
||||
else if (que.type == "2") // 主观题
|
||||
{
|
||||
if (que.options.Any() && paperLatts.Any(s => RectExt.IsRectContainsLattice(que.options[0].AnswerArea, s)))
|
||||
{
|
||||
pageSerials.Add(paper.PaperId);
|
||||
var ky = false;
|
||||
var quePaperId = paper.PaperId;
|
||||
var queOthPaper = paperInfo.FirstOrDefault(w => w.PartId == paper.PartId && w.PageIndex != paper.PageIndex && w.QueData.Any(s => s.no == que.no));
|
||||
if (queOthPaper != null)
|
||||
{
|
||||
ky = true;
|
||||
if (paper.PageIndex > queOthPaper.PageIndex)
|
||||
{
|
||||
pageSerials.Add(queOthPaper.PaperId);
|
||||
quePaperId = queOthPaper.PaperId;
|
||||
}
|
||||
}
|
||||
if (!zgt.Any(s => s.Item1 == quePaperId && s.Item2 == que.no))
|
||||
zgt.Add(new(quePaperId, que.no, ky));
|
||||
}
|
||||
if (!zgt.Any(s => s.Item1 == quePaperId && s.Item2 == que.no))
|
||||
zgt.Add(new(quePaperId, que.no, ky));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var kgtPapers = kgt.GroupBy(s => s.Item1).Select(s => s.Key).ToList(); // 客观题处理
|
||||
foreach (var paperId in kgtPapers)
|
||||
{
|
||||
var paper = paperInfo.FirstOrDefault(w => w.PaperId == paperId);
|
||||
var paperLatts = lattices.Where(w => w.PageSerial == paperId).ToList();
|
||||
|
||||
var queNos = kgt.Where(w => w.Item1 == paperId).Select(s => s.Item2).ToList();
|
||||
foreach (var queNo in queNos)
|
||||
foreach (var _kgtDtl in kgtDtls)
|
||||
{
|
||||
var queInfo = paper.QueData.FirstOrDefault(w => w.no == queNo);
|
||||
var queLatts = paperLatts.Where(w => queInfo.options.Any(s => RectExt.IsRectContainsLattice(s.AnswerArea, w))
|
||||
|| queInfo.resetPoint.Any(s => RectExt.IsRectContainsLattice(s, w))).ToList();
|
||||
_kgtDtl.Id = YitIdHelper.NextId();
|
||||
}
|
||||
var kgtPapers = kgt.GroupBy(s => s.Item1).Select(s => s.Key).ToList(); // 客观题处理
|
||||
foreach (var paperId in kgtPapers)
|
||||
{
|
||||
var paper = paperInfo.FirstOrDefault(w => w.PaperId == paperId);
|
||||
var paperLatts = lattices.Where(w => w.PageSerial == paperId).ToList();
|
||||
|
||||
long? resetTime = null;
|
||||
if (queInfo.resetPoint.Any())
|
||||
var queNos = kgt.Where(w => w.Item1 == paperId).Select(s => s.Item2).ToList();
|
||||
foreach (var queNo in queNos)
|
||||
{
|
||||
var resetLatts = queLatts.Where(w => RectExt.IsRectContainsLattice(queInfo.resetPoint[0], w)).ToList();
|
||||
resetTime = resetLatts.Any() ? resetLatts.Max(w => w.Time) : null;
|
||||
}
|
||||
var queInfo = paper.QueData.FirstOrDefault(w => w.no == queNo);
|
||||
var queLatts = paperLatts.Where(w => queInfo.options.Any(s => RectExt.IsRectContainsLattice(s.AnswerArea, w))
|
||||
|| queInfo.resetPoint.Any(s => RectExt.IsRectContainsLattice(s, w))).ToList();
|
||||
|
||||
var stuAnswer = "";
|
||||
// 遍历每个选项
|
||||
foreach (var option in queInfo.options)
|
||||
{
|
||||
if (!option.point.Any()) continue; // 该选项无坐标数据
|
||||
var choose = queLatts.WhereIF(resetTime.HasValue, w => w.Time > resetTime).Where(a => RectExt.IsRectContainsLattice(option.point[0], a));
|
||||
if (!choose.Any()) continue;
|
||||
stuAnswer += option.option;
|
||||
}
|
||||
long? resetTime = null;
|
||||
if (queInfo.resetPoint.Any())
|
||||
{
|
||||
var resetLatts = queLatts.Where(w => RectExt.IsRectContainsLattice(queInfo.resetPoint[0], w)).ToList();
|
||||
resetTime = resetLatts.Any() ? resetLatts.Max(w => w.Time) : null;
|
||||
}
|
||||
|
||||
var dtl = kgtDtls.FirstOrDefault(w => w.QuestionNumber == queNo);
|
||||
if (dtl != null)
|
||||
{
|
||||
dtl.QuestionValue = stuAnswer;
|
||||
var stuAnswer = "";
|
||||
// 遍历每个选项
|
||||
foreach (var option in queInfo.options)
|
||||
{
|
||||
if (!option.point.Any()) continue; // 该选项无坐标数据
|
||||
var choose = queLatts.WhereIF(resetTime.HasValue, w => w.Time > resetTime).Where(a => RectExt.IsRectContainsLattice(option.point[0], a));
|
||||
if (!choose.Any()) continue;
|
||||
stuAnswer += option.option;
|
||||
}
|
||||
|
||||
var dtl = kgtDtls.FirstOrDefault(w => w.QuestionNumber == queNo);
|
||||
if (dtl != null)
|
||||
{
|
||||
dtl.QuestionValue = stuAnswer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var zgtPapers = zgt.GroupBy(s => s.Item1).Select(s => s.Key).ToList(); // 主观题处理
|
||||
foreach (var paperId in zgtPapers)
|
||||
{
|
||||
var paper = paperInfo.FirstOrDefault(w => w.PaperId == paperId);
|
||||
var paperJobPage = templateIds.FindIndex(s => s == paper.TemplateId) + 1;
|
||||
var paperLatts = lattices.Where(w => w.PageSerial == paperId).ToList();
|
||||
|
||||
var ques = zgt.Where(w => w.Item1 == paperId).ToList();
|
||||
foreach (var que in ques)
|
||||
var zgtPapers = zgt.GroupBy(s => s.Item1).Select(s => s.Key).ToList(); // 主观题处理
|
||||
foreach (var paperId in zgtPapers)
|
||||
{
|
||||
var queNo = que.Item2;
|
||||
var queInfo = paper.QueData.FirstOrDefault(w => w.no == queNo);
|
||||
var answerArea = queInfo.options[0].AnswerArea;
|
||||
var queLatts = paperLatts.Where(w => RectExt.IsRectContainsLattice(answerArea, w))
|
||||
.Select(s => new SubjectiveLatt()
|
||||
{
|
||||
Stroke = s.strokeIndex,
|
||||
X = s.CX.AUToPX(),
|
||||
Y = s.CY.AUToPX() - answerArea.pxTop,
|
||||
Time = s.Time,
|
||||
}).ToList();
|
||||
var paper = paperInfo.FirstOrDefault(w => w.PaperId == paperId);
|
||||
var paperLatts = lattices.Where(w => w.PageSerial == paperId).ToList();
|
||||
|
||||
if (que.Item3) // 跨页
|
||||
var ques = zgt.Where(w => w.Item1 == paperId).ToList();
|
||||
foreach (var que in ques)
|
||||
{
|
||||
var queOnNextPaper = paperInfo.FirstOrDefault(w => w.PartId == paper.PartId && w.PageIndex == paper.PageIndex + 1 && w.QueData.Any(s => s.no == queNo));
|
||||
var queInfoOnNextPaper = queOnNextPaper.QueData.FirstOrDefault(w => w.no == queNo);
|
||||
var answerAreaOnNextPaper = queInfoOnNextPaper.options[0].AnswerArea;
|
||||
var queLattsOnNextPaper = lattices.Where(w => w.PageSerial == queOnNextPaper.PaperId && RectExt.IsRectContainsLattice(answerAreaOnNextPaper, w))
|
||||
var queNo = que.Item2;
|
||||
var queInfo = paper.QueData.FirstOrDefault(w => w.no == queNo);
|
||||
var answerArea = queInfo.options[0].AnswerArea;
|
||||
var queLatts = paperLatts.Where(w => RectExt.IsRectContainsLattice(answerArea, w))
|
||||
.Select(s => new SubjectiveLatt()
|
||||
{
|
||||
Stroke = s.strokeIndex,
|
||||
X = s.CX.AUToPX(),
|
||||
Y = s.CY.AUToPX() + answerArea.pxHeight - answerAreaOnNextPaper.pxTop,
|
||||
Y = s.CY.AUToPX() - answerArea.pxTop,
|
||||
Time = s.Time,
|
||||
}).ToList();
|
||||
queLatts.AddRange(queLattsOnNextPaper);
|
||||
}
|
||||
|
||||
var stuAnswer = "";
|
||||
|
||||
var queImgUrl = zgtSettingDtls.FirstOrDefault(w => w.QuestionNum == queNo).DotPenOriginalImg;
|
||||
var imgStream = await _blobContainer.GetAsync(queImgUrl);
|
||||
var queBitmap = SKBitmap.Decode(imgStream);
|
||||
|
||||
using (var canvas = new SKCanvas(queBitmap))
|
||||
{
|
||||
// 一笔一笔的画上去
|
||||
var strokeIndexs = queLatts.GroupBy(g => g.Stroke).Select(s => s.Key).ToList();
|
||||
foreach (var stroke in strokeIndexs)
|
||||
if (que.Item3) // 跨页
|
||||
{
|
||||
var points = queLatts.Where(w => w.Stroke == stroke).OrderBy(s => s.Time).Select(s => new SKPoint(s.X, s.Y)).ToArray();
|
||||
var skPointMode = SKPointMode.Polygon;
|
||||
if (points.Length == 1)
|
||||
skPointMode = SKPointMode.Points;
|
||||
else if (points.Length == 2)
|
||||
skPointMode = SKPointMode.Lines;
|
||||
|
||||
canvas.DrawPoints(skPointMode, points, skPaint);
|
||||
var queOnNextPaper = paperInfo.FirstOrDefault(w => w.PartId == paper.PartId && w.PageIndex == paper.PageIndex + 1 && w.QueData.Any(s => s.no == queNo));
|
||||
var queInfoOnNextPaper = queOnNextPaper.QueData.FirstOrDefault(w => w.no == queNo);
|
||||
var answerAreaOnNextPaper = queInfoOnNextPaper.options[0].AnswerArea;
|
||||
var queLattsOnNextPaper = lattices.Where(w => w.PageSerial == queOnNextPaper.PaperId && RectExt.IsRectContainsLattice(answerAreaOnNextPaper, w))
|
||||
.Select(s => new SubjectiveLatt()
|
||||
{
|
||||
Stroke = s.strokeIndex,
|
||||
X = s.CX.AUToPX(),
|
||||
Y = s.CY.AUToPX() + answerArea.pxHeight - answerAreaOnNextPaper.pxTop,
|
||||
Time = s.Time,
|
||||
}).ToList();
|
||||
queLatts.AddRange(queLattsOnNextPaper);
|
||||
}
|
||||
stuAnswer = $"queAnswer/{eto.ExamSubjectId}/{penSerial}/{paper.Sort}/{queNo}.png";
|
||||
await _blobContainer.SaveAsync(stuAnswer, queBitmap.Encode(SKEncodedImageFormat.Png, 100).ToArray(), true);
|
||||
}
|
||||
|
||||
var dtl = zgtDtls.FirstOrDefault(w => w.QuestionNum == queNo);
|
||||
if (dtl != null)
|
||||
{
|
||||
dtl.StudentAnswer = stuAnswer;
|
||||
var stuAnswer = "";
|
||||
|
||||
var queImgUrl = zgtSettingDtls.FirstOrDefault(w => w.QuestionNum == queNo).DotPenOriginalImg;
|
||||
var imgStream = await _blobContainer.GetAsync(queImgUrl);
|
||||
var queBitmap = SKBitmap.Decode(imgStream);
|
||||
|
||||
using (var canvas = new SKCanvas(queBitmap))
|
||||
{
|
||||
// 一笔一笔的画上去
|
||||
var strokeIndexs = queLatts.GroupBy(g => g.Stroke).Select(s => s.Key).ToList();
|
||||
foreach (var stroke in strokeIndexs)
|
||||
{
|
||||
var points = queLatts.Where(w => w.Stroke == stroke).OrderBy(s => s.Time).Select(s => new SKPoint(s.X, s.Y)).ToArray();
|
||||
var skPointMode = SKPointMode.Polygon;
|
||||
if (points.Length == 1)
|
||||
skPointMode = SKPointMode.Points;
|
||||
else if (points.Length == 2)
|
||||
skPointMode = SKPointMode.Lines;
|
||||
|
||||
canvas.DrawPoints(skPointMode, points, skPaint);
|
||||
}
|
||||
stuAnswer = $"stu-answer/{eto.ExamSubjectId}/{penSerial}/{queNo}.jpg";
|
||||
await _blobContainer.SaveAsync(stuAnswer, queBitmap.Encode(SKEncodedImageFormat.Jpeg, 100).ToArray(), true);
|
||||
}
|
||||
|
||||
var dtl = zgtDtls.FirstOrDefault(w => w.QuestionNum == queNo);
|
||||
if (dtl != null)
|
||||
{
|
||||
dtl.StudentAnswer = $"[\"{_aliyunOption.Host}/{stuAnswer}\"]";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await DbBiz.UseTranAsync(async () =>
|
||||
try
|
||||
{
|
||||
await DbBiz.BeginTranAsync();
|
||||
|
||||
// 删除
|
||||
await DbBiz.Deleteable<MkExamResult>().Where(w => w.ExamSubjectId == eto.ExamSubjectId && w.StudentNo == penSerial).ExecuteCommandAsync();
|
||||
await DbBiz.Updateable<SubjectiveMarkingResult>()
|
||||
.SetColumns(s => new SubjectiveMarkingResult { IsDeleted = true, UpdateDate = Clock.Now })
|
||||
.Where(w => w.ExamSubjectId == eto.ExamSubjectId && w.StudentExamNum == penSerial && w.IsDeleted == false)
|
||||
.ExecuteCommandAsync();
|
||||
// 新增
|
||||
await DbBiz.Insertable(kgtDtls).ExecuteCommandAsync();
|
||||
await DbBiz.Insertable(zgtDtls).ExecuteCommandAsync();
|
||||
|
||||
await DbBiz.CommitTranAsync();
|
||||
Logger.LogInformation("{ExamSubjectId} {penSerial} 收集成功", eto.ExamSubjectId, penSerial);
|
||||
}
|
||||
catch (Exception saveEx)
|
||||
{
|
||||
await DbBiz.RollbackTranAsync();
|
||||
Logger.LogError("{ExamSubjectId} {penSerial} 收集失败! 数据存储异常: {error}", eto.ExamSubjectId, penSerial, saveEx);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 删除
|
||||
await DbBiz.Deleteable<MkExamResult>().Where(w => w.ExamSubjectId == eto.ExamSubjectId && w.StudentNo == penSerial).ExecuteCommandAsync();
|
||||
await DbBiz.Updateable<SubjectiveMarkingResult>()
|
||||
.SetColumns(s => s.IsDeleted == true)
|
||||
.Where(w => w.ExamSubjectId == eto.ExamSubjectId && w.StudentExamNum == penSerial && w.IsDeleted == false)
|
||||
.ExecuteCommandAsync();
|
||||
// 新增
|
||||
await DbBiz.Insertable(kgtDtls).ExecuteCommandAsync();
|
||||
await DbBiz.Insertable(zgtDtls).ExecuteCommandAsync();
|
||||
});
|
||||
Logger.LogError("{ExamSubjectId} {penSerial} 收集失败! {error}", eto.ExamSubjectId, penSerial, ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
await RedisHelper.DelAsync(studentRedisLockKey);
|
||||
}
|
||||
}
|
||||
|
||||
[AutoTran]
|
||||
public async Task ExamAnnotate(ExamAnnotateEto eto)
|
||||
{
|
||||
}
|
||||
|
|
@ -360,13 +423,12 @@ public class ExamManager : DomainService, IExamManager
|
|||
var tenant = await Db.Queryable<Tenant>().Where(w => w.TenantCode == tenantCode).FirstAsync();
|
||||
ExceptionExt.ThrowIf(tenant == null, $"{nameof(tenant)} is null with ${tenantCode}");
|
||||
|
||||
var config = new SqlSugarConfig();
|
||||
return new SqlSugarClient(new ConnectionConfig()
|
||||
{
|
||||
DbType = DbType.MySql,
|
||||
ConnectionString = tenant.ConnectionString,
|
||||
IsAutoCloseConnection = true,
|
||||
ConfigureExternalServices = config.ExtService,
|
||||
ConfigureExternalServices = MySqlConfigureExternalServices.MySqlExtService,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,6 @@ public class ExamAppService : DolphinAppService
|
|||
|
||||
public async Task Test()
|
||||
{
|
||||
await _examManager.ExamStudentGather(new() { SchoolId = 1, StudentExamNum = "BP2-3G3-07K-C0", TemplateId = "[]" });
|
||||
await _examManager.ExamStudentGather(new() { SchoolId = 1, StudentExamNum = "BP2-3G3-07K-BZ", BookId = 528102717276229, ExamSubjectSchoolId = 528066671910982, ExamSubjectId = 528066655817797, LastCollectTime = DateTime.Now });
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
using Volo.Abp.BlobStoring;
|
||||
using Volo.Abp.BlobStoring.Aliyun;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
|
||||
namespace Dolphin.ExamPictureCut.BlobStoring;
|
||||
|
||||
public class AppAliyunBlobNameCalculator : IAliyunBlobNameCalculator, ITransientDependency
|
||||
{
|
||||
public virtual string Calculate(BlobProviderArgs args)
|
||||
{
|
||||
return args.BlobName;
|
||||
}
|
||||
}
|
||||
|
|
@ -17,16 +17,12 @@
|
|||
<PackageReference Include="CSRedisCore" Version="3.8.802" />
|
||||
<PackageReference Include="Flurl.Http" Version="4.0.2" />
|
||||
<PackageReference Include="NoFurion" Version="0.0.7" />
|
||||
<PackageReference Include="SkiaSharp" Version="2.88.6" />
|
||||
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="2.88.6" />
|
||||
<PackageReference Include="Volo.Abp.BlobStoring.Aliyun" Version="8.0.2" />
|
||||
<PackageReference Include="Volo.Abp.EventBus.RabbitMQ" Version="8.0.2" />
|
||||
<PackageReference Include="SkiaSharp" Version="2.88.7" />
|
||||
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="2.88.7" />
|
||||
<PackageReference Include="Volo.Abp.BlobStoring.Aliyun" Version="8.0.5" />
|
||||
<PackageReference Include="Volo.Abp.EventBus.RabbitMQ" Version="8.0.5" />
|
||||
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Options\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
using Dolphin.ExamPictureCut.Localization;
|
||||
using Dolphin.ExamPictureCut.Options;
|
||||
using Mapster;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NoFurion.Extensions;
|
||||
using Volo.Abp.Application;
|
||||
using Volo.Abp.BlobStoring;
|
||||
|
|
@ -22,11 +26,22 @@ public class DolphinExamPictureCutCoreModule : AbpModule
|
|||
{
|
||||
public override void ConfigureServices(ServiceConfigurationContext context)
|
||||
{
|
||||
var Configuration = context.Services.GetConfiguration();
|
||||
var aliyunOption = Configuration.GetSection("Aliyun").Get<AliyunOption>();
|
||||
Configure<AliyunOption>(options => aliyunOption.Adapt(options));
|
||||
Configure<AbpBlobStoringOptions>(options =>
|
||||
{
|
||||
options.Containers.ConfigureDefault(container =>
|
||||
{
|
||||
container.UseAliyun(aliyun => { });
|
||||
container.UseAliyun(aliyun =>
|
||||
{
|
||||
aliyun.AccessKeyId = aliyunOption.AccessKeyId;
|
||||
aliyun.AccessKeySecret = aliyunOption.AccessKeySecret;
|
||||
aliyun.Endpoint = aliyunOption.Endpoint;
|
||||
aliyun.RegionId = aliyunOption.RegionId;
|
||||
aliyun.ContainerName = aliyunOption.ContainerName;
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ namespace Dolphin.ExamPictureCut.Domains.Basic;
|
|||
[Table(nameof(GroupBook)), Tenant(DbConsts.marking_basic)]
|
||||
public class GroupBook
|
||||
{
|
||||
[SugarColumn(IsPrimaryKey = true, ColumnName = "id", Length = 32)]
|
||||
public string Id { get; set; }
|
||||
[SugarColumn(IsPrimaryKey = true, ColumnName = "id")]
|
||||
public long Id { get; set; }
|
||||
|
||||
[SugarColumn(ColumnName = "book_id")]
|
||||
public long BookId { get; set; }
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ namespace Dolphin.ExamPictureCut.Domains.Basic;
|
|||
[Table(nameof(GroupBookPaperTemplate)), Tenant(DbConsts.marking_basic)]
|
||||
public class GroupBookPaperTemplate
|
||||
{
|
||||
[SugarColumn(IsPrimaryKey = true, ColumnName = "id", Length = 32)]
|
||||
public string Id { get; set; }
|
||||
[SugarColumn(IsPrimaryKey = true, ColumnName = "id")]
|
||||
public long Id { get; set; }
|
||||
|
||||
[SugarColumn(ColumnName = "book_id")]
|
||||
public long BookId { get; set; }
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ public class Tenant : ISoftDelete
|
|||
public string TenantName { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public string ConnectionString => $"Server={IpAddr};Port={Port};Database={Database};Uid={Dbuser};Pwd={Password};";
|
||||
public string ConnectionString => $"Server={IpAddr};Port={Port};Database={Database};Uid={Dbuser};Pwd={Password};CharSet=utf8mb4;AllowLoadLocalInfile=true;AllowUserVariables=True;ConvertZeroDatetime=true;";
|
||||
|
||||
public bool IsEnable { get; set; }
|
||||
public bool IsDeleted { get; set; }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Dolphin.ExamPictureCut.Domains.Biz;
|
||||
|
||||
[Table(nameof(ExamSubjectSchoolStudent))]
|
||||
public class ExamSubjectSchoolStudent
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public long ExamSubjectSchoolId { get; set; }
|
||||
public string StudentExamNum { get; set; }
|
||||
public int CollectStatus { get; set; }
|
||||
}
|
||||
|
|
@ -1,7 +1,12 @@
|
|||
using SqlSugar;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Dolphin.ExamPictureCut.Domains.Biz;
|
||||
|
||||
[Table(nameof(MarkingSettingSubjective))]
|
||||
public class MarkingSettingSubjective
|
||||
{
|
||||
[SugarColumn(IsPrimaryKey = true)]
|
||||
public long Id { get; set; }
|
||||
public long ExamSubjectId { get; set; }
|
||||
public string QuestionNum { get; set; }
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
using Dolphin.ExamPictureCut.Options;
|
||||
using SqlSugar;
|
||||
|
||||
namespace Dolphin.ExamPictureCut.Domains.Biz;
|
||||
|
||||
[SugarTable("MK_ExamResult")]
|
||||
[SugarTable("MK_ExamResult"), IgnoreUnderLine]
|
||||
public class MkExamResult
|
||||
{
|
||||
[SugarColumn(IsPrimaryKey = true, ColumnName = "ID_bigint")]
|
||||
|
|
@ -14,6 +15,7 @@ public class MkExamResult
|
|||
[SugarColumn(ColumnName = "ExamId_bigint")]
|
||||
public long ExamId { get; set; }
|
||||
|
||||
[SugarColumn(ColumnName = "ExamSubjectId")]
|
||||
public long ExamSubjectId { get; set; }
|
||||
|
||||
[SugarColumn(ColumnName = "QuestionNumber_int")]
|
||||
|
|
@ -34,5 +36,6 @@ public class MkExamResult
|
|||
[SugarColumn(ColumnName = "GroupNo_nvarchar")]
|
||||
public string GroupNo { get; set; }
|
||||
|
||||
[SugarColumn(ColumnName = "IsSync")]
|
||||
public bool IsSync { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
using SqlSugar;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Volo.Abp;
|
||||
|
||||
namespace Dolphin.ExamPictureCut.Domains.Biz;
|
||||
|
||||
[Table(nameof(SubjectiveMarkingResult))]
|
||||
public class SubjectiveMarkingResult : ISoftDelete
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
|
@ -17,10 +20,15 @@ public class SubjectiveMarkingResult : ISoftDelete
|
|||
public string GroupNo { get; set; }
|
||||
public bool IsAssign { get; set; }
|
||||
public bool IsRating { get; set; }
|
||||
public string CommentImgUrl { get; set; } = "[]";
|
||||
public string CommentImageUrl { get; set; } = "[]";
|
||||
public string BigQuestionNum { get; set; }
|
||||
public bool IsExcess { get; set; }
|
||||
|
||||
public bool IsDeleted { get; set; }
|
||||
|
||||
[SugarColumn(InsertServerTime = true)]
|
||||
public DateTime CreateDate { get; set; }
|
||||
|
||||
[SugarColumn(InsertServerTime = true, UpdateServerTime = true)]
|
||||
public DateTime UpdateDate { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
namespace Dolphin.ExamPictureCut.Domains;
|
||||
|
||||
public class IgnoreUnderLineAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
using NoFurion;
|
||||
using SqlSugar;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Dolphin.ExamPictureCut.Domains;
|
||||
|
||||
public class MySqlConfigureExternalServices
|
||||
{
|
||||
public static ConfigureExternalServices MySqlExtService = new ConfigureExternalServices
|
||||
{
|
||||
EntityService = delegate (PropertyInfo prop, EntityColumnInfo col)
|
||||
{
|
||||
if (prop.GetCustomAttribute<NotMappedAttribute>() != null)
|
||||
{
|
||||
col.IsIgnore = true;
|
||||
}
|
||||
|
||||
if (!col.IsPrimarykey)
|
||||
{
|
||||
if (prop.GetCustomAttribute<RequiredAttribute>() != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (new NullabilityInfoContext().Create(prop).WriteState == NullabilityState.Nullable || prop.PropertyType == typeof(string))
|
||||
{
|
||||
col.IsNullable = true;
|
||||
}
|
||||
}
|
||||
|
||||
var sugarColumn = prop.GetCustomAttribute<SugarColumn>();
|
||||
if (sugarColumn != null && sugarColumn.ColumnName.IsNotNullOrEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (prop.DeclaringType.GetCustomAttribute<IgnoreUnderLineAttribute>() == null)
|
||||
{
|
||||
col.DbColumnName = UtilMethods.ToUnderLine(col.DbColumnName);
|
||||
}
|
||||
},
|
||||
EntityNameService = delegate (Type t, EntityInfo entity)
|
||||
{
|
||||
if (t.GetCustomAttribute<SugarTable>() != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TableAttribute customAttribute = t.GetCustomAttribute<TableAttribute>();
|
||||
if (customAttribute != null)
|
||||
{
|
||||
entity.DbTableName = UtilMethods.ToUnderLine(customAttribute.Name);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
using Dolphin.ExamPictureCut.Constants;
|
||||
using Dolphin.ExamPictureCut.Domains.Basic;
|
||||
using Dolphin.ExamPictureCut.Options;
|
||||
using SqlSugar;
|
||||
|
||||
namespace Dolphin.ExamPictureCut.Domains.Quest;
|
||||
|
|
@ -7,7 +8,7 @@ namespace Dolphin.ExamPictureCut.Domains.Quest;
|
|||
/// <summary>
|
||||
/// 点阵笔离线数据
|
||||
/// </summary>
|
||||
[Tenant(DbConsts.penoffline)]
|
||||
[Tenant(DbConsts.penoffline), IgnoreUnderLine]
|
||||
public class PenOfflineData
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -24,9 +24,10 @@ public class ExamStudentGatherEto
|
|||
/// <summary>
|
||||
/// 模板id
|
||||
/// </summary>
|
||||
public string TemplateId { get; set; }
|
||||
public long BookId { get; set; }
|
||||
/// <summary>
|
||||
/// 所属学生
|
||||
/// </summary>
|
||||
public string StudentExamNum { get; set; }
|
||||
public DateTime LastCollectTime { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ public class TemplateJsonModel_DataArr
|
|||
}
|
||||
public class PaperQueData
|
||||
{
|
||||
public string TemplateId { get; set; }
|
||||
public long TemplateId { get; set; }
|
||||
public string PaperId { get; set; }
|
||||
public long PartId { get; set; }
|
||||
public int PageIndex { get; set; }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
namespace Dolphin.ExamPictureCut.Options;
|
||||
|
||||
public class AliyunOption
|
||||
{
|
||||
public string AccessKeyId { get; set; }
|
||||
public string AccessKeySecret { get; set; }
|
||||
public string Endpoint { get; set; }
|
||||
public string RegionId { get; set; }
|
||||
/// <summary>
|
||||
/// Bucket
|
||||
/// </summary>
|
||||
public string ContainerName { get; set; }
|
||||
public string Host { get; set; }
|
||||
}
|
||||
|
|
@ -11,10 +11,10 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
|
||||
<PackageReference Include="Volo.Abp.AspNetCore.Authentication.JwtBearer" Version="8.0.2" />
|
||||
<PackageReference Include="Volo.Abp.AspNetCore.Serilog" Version="8.0.2" />
|
||||
<PackageReference Include="Volo.Abp.Autofac" Version="8.0.2" />
|
||||
<PackageReference Include="Volo.Abp.Swashbuckle" Version="8.0.2" />
|
||||
<PackageReference Include="Volo.Abp.AspNetCore.Authentication.JwtBearer" Version="8.0.5" />
|
||||
<PackageReference Include="Volo.Abp.AspNetCore.Serilog" Version="8.0.5" />
|
||||
<PackageReference Include="Volo.Abp.Autofac" Version="8.0.5" />
|
||||
<PackageReference Include="Volo.Abp.Swashbuckle" Version="8.0.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
using Dolphin.ExamPictureCut.Constants;
|
||||
using Dolphin.ExamPictureCut.Domains;
|
||||
using Dolphin.ExamPictureCut.Extensions;
|
||||
using Dolphin.ExamPictureCut.Options;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
using Microsoft.OpenApi.Models;
|
||||
|
|
@ -41,45 +43,6 @@ public class DolphinExamPictureCutHttpApiHostModule : AbpModule
|
|||
|
||||
private void ConfigureSqlSugar(ServiceConfigurationContext context, IConfiguration configuration)
|
||||
{
|
||||
var config = new SqlSugarConfig();
|
||||
var ExtService = new ConfigureExternalServices
|
||||
{
|
||||
EntityService = delegate (PropertyInfo prop, EntityColumnInfo col)
|
||||
{
|
||||
if (prop.GetCustomAttribute<NotMappedAttribute>() != null)
|
||||
{
|
||||
col.IsIgnore = true;
|
||||
}
|
||||
|
||||
if (prop.PropertyType == typeof(string))
|
||||
{
|
||||
col.DataType = "text";
|
||||
}
|
||||
|
||||
if (!col.IsPrimarykey)
|
||||
{
|
||||
if (prop.GetCustomAttribute<RequiredAttribute>() != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (new NullabilityInfoContext().Create(prop).WriteState == NullabilityState.Nullable || prop.PropertyType == typeof(string))
|
||||
{
|
||||
col.IsNullable = true;
|
||||
}
|
||||
}
|
||||
|
||||
col.DbColumnName = UtilMethods.ToUnderLine(col.DbColumnName);
|
||||
},
|
||||
EntityNameService = delegate (Type t, EntityInfo entity)
|
||||
{
|
||||
TableAttribute customAttribute = t.GetCustomAttribute<TableAttribute>();
|
||||
if (customAttribute != null)
|
||||
{
|
||||
entity.DbTableName = UtilMethods.ToUnderLine(customAttribute.Name);
|
||||
}
|
||||
}
|
||||
};
|
||||
context.Services.AddSingleton<ISqlSugarClient>(s =>
|
||||
{
|
||||
var scope = new SqlSugarScope(
|
||||
|
|
@ -90,7 +53,7 @@ public class DolphinExamPictureCutHttpApiHostModule : AbpModule
|
|||
DbType = DbType.MySql,
|
||||
ConnectionString = configuration.GetConnectionString(DbConsts.marking_basic),
|
||||
IsAutoCloseConnection = true,
|
||||
ConfigureExternalServices = ExtService,
|
||||
ConfigureExternalServices = MySqlConfigureExternalServices.MySqlExtService,
|
||||
},
|
||||
new ConnectionConfig()
|
||||
{
|
||||
|
|
@ -98,13 +61,14 @@ public class DolphinExamPictureCutHttpApiHostModule : AbpModule
|
|||
DbType = DbType.QuestDB,
|
||||
ConnectionString = configuration.GetConnectionString(DbConsts.penoffline),
|
||||
IsAutoCloseConnection = true,
|
||||
ConfigureExternalServices = ExtService,
|
||||
ConfigureExternalServices = MySqlConfigureExternalServices.MySqlExtService,
|
||||
},
|
||||
},
|
||||
db =>
|
||||
{
|
||||
db.QueryFilter.AddTableFilter<ISoftDelete>(s => s.IsDeleted == false);
|
||||
|
||||
var config = new SqlSugarConfig();
|
||||
db.Aop.DataExecuting = config.DataExecuting(context.Services);
|
||||
|
||||
db.Aop.OnLogExecuting = (sql, pars) =>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
},
|
||||
"ConnectionStrings": {
|
||||
"marking_basic": "Server=192.168.2.9;Port=3306;Database=marking_basic;Uid=root;Pwd=qwe123!@#;AllowLoadLocalInfile=true;",
|
||||
"penoffline": "host=192.168.2.7;port=8812;username=zhjs;password=zhjsniubi;database=qdb;ServerCompatibilityMode=NoTypeLoading;"
|
||||
"penoffline": "host=47.108.209.28;port=8812;username=zhjs;password=zhjsniubi;database=qdb;ServerCompatibilityMode=NoTypeLoading;"
|
||||
},
|
||||
"Redis": {
|
||||
"Configuration": "192.168.2.7:6379,password=qwe123!@#,defaultDatabase=14,idleTimeout=3000,poolsize=5,prefix=marking"
|
||||
|
|
@ -18,12 +18,13 @@
|
|||
"HostName": "192.168.2.7",
|
||||
"Port": "5672",
|
||||
"UserName": "rabbit",
|
||||
"Password": "qwe123!@#"
|
||||
"Password": "qwe123!@#",
|
||||
"VirtualHost": "marking"
|
||||
}
|
||||
},
|
||||
"EventBus": {
|
||||
"ClientName": "collect_queue",
|
||||
"ExchangeName": "tenant_ex"
|
||||
"ExchangeName": "exam_gather_ex"
|
||||
}
|
||||
},
|
||||
"Aliyun": {
|
||||
|
|
|
|||
|
|
@ -18,12 +18,13 @@
|
|||
"HostName": "192.168.2.7",
|
||||
"Port": "5672",
|
||||
"UserName": "rabbit",
|
||||
"Password": "qwe123!@#"
|
||||
"Password": "qwe123!@#",
|
||||
"VirtualHost": "marking"
|
||||
}
|
||||
},
|
||||
"EventBus": {
|
||||
"ClientName": "collect_queue",
|
||||
"ExchangeName": "tenant_ex"
|
||||
"ExchangeName": "exam_gather_ex"
|
||||
}
|
||||
},
|
||||
"Aliyun": {
|
||||
|
|
|
|||
Loading…
Reference in New Issue