fix: 考试收集优化

This commit is contained in:
lyndonliu 2024-03-25 14:40:39 +08:00
parent 9c53c18db9
commit 0043320cd4
22 changed files with 416 additions and 258 deletions

View File

@ -1,10 +1,14 @@
using Dolphin.ExamPictureCut.Constants;
using Dolphin.ExamPictureCut.Domains;
using Dolphin.ExamPictureCut.Domains.Basic; using Dolphin.ExamPictureCut.Domains.Basic;
using Dolphin.ExamPictureCut.Domains.Biz; using Dolphin.ExamPictureCut.Domains.Biz;
using Dolphin.ExamPictureCut.Domains.Quest; using Dolphin.ExamPictureCut.Domains.Quest;
using Dolphin.ExamPictureCut.Exams.Dto; using Dolphin.ExamPictureCut.Exams.Dto;
using Dolphin.ExamPictureCut.Extensions; using Dolphin.ExamPictureCut.Extensions;
using Dolphin.ExamPictureCut.Options;
using Flurl.Http; using Flurl.Http;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json; using Newtonsoft.Json;
using NoFurion; using NoFurion;
using NoFurion.SqlSugar; using NoFurion.SqlSugar;
@ -12,6 +16,7 @@ using SkiaSharp;
using SqlSugar; using SqlSugar;
using Volo.Abp.BlobStoring; using Volo.Abp.BlobStoring;
using Volo.Abp.Domain.Services; using Volo.Abp.Domain.Services;
using Volo.Abp.Uow;
using Yitter.IdGenerator; using Yitter.IdGenerator;
namespace Dolphin.ExamPictureCut.Exams; namespace Dolphin.ExamPictureCut.Exams;
@ -19,7 +24,9 @@ namespace Dolphin.ExamPictureCut.Exams;
public class ExamManager : DomainService, IExamManager public class ExamManager : DomainService, IExamManager
{ {
private readonly ISqlSugarClient Db; private readonly ISqlSugarClient Db;
private readonly ISqlSugarClient DbPenOffline;
private readonly IBlobContainer _blobContainer; private readonly IBlobContainer _blobContainer;
private readonly AliyunOption _aliyunOption;
private readonly SKPaint skPaint = new SKPaint private readonly SKPaint skPaint = new SKPaint
{ {
Color = SKColors.Black, Color = SKColors.Black,
@ -28,20 +35,22 @@ public class ExamManager : DomainService, IExamManager
StrokeWidth = 1, StrokeWidth = 1,
StrokeCap = SKStrokeCap.Round, StrokeCap = SKStrokeCap.Round,
}; };
public ExamManager(ISqlSugarClient db, IBlobContainer blobContainer) public ExamManager(ISqlSugarClient db, IBlobContainer blobContainer, IOptions<AliyunOption> aliyunOption)
{ {
Db = db; Db = db;
DbPenOffline = (db as SqlSugarScope).GetConnection(DbConsts.penoffline);
_blobContainer = blobContainer; _blobContainer = blobContainer;
_aliyunOption = aliyunOption.Value;
} }
[UnitOfWork(false)]
public async Task ExamStudentGather(ExamStudentGatherEto eto) public async Task ExamStudentGather(ExamStudentGatherEto eto)
{ {
var penSerial = eto.StudentExamNum; var penSerial = eto.StudentExamNum;
Logger.LogInformation("{ExamSubjectId} {penSerial} 开始收集...", eto.ExamSubjectId, penSerial); Logger.LogInformation("{ExamSubjectId} {penSerial} 开始收集...", eto.ExamSubjectId, penSerial);
var guid = GuidGenerator.Create().ToString("N"); var guid = GuidGenerator.Create().ToString("N");
var templateIds = JsonConvert.DeserializeObject<List<string>>(eto.TemplateId); var templates = await Db.Queryable<GroupBookPaperTemplate>().Where(w => w.BookId == eto.BookId)
var templates = await Db.Queryable<GroupBookPaperTemplate>().Where(w => templateIds.Contains(w.Id))
.Select(s => new { s.Id, s.PaperId, s.PartId, s.PageIndex, s.ImgUrl, s.QueData, s.Order }).ToListAsync(); .Select(s => new { s.Id, s.PaperId, s.PartId, s.PageIndex, s.ImgUrl, s.QueData, s.Order }).ToListAsync();
var paperInfo = templates.Select(s => var paperInfo = templates.Select(s =>
{ {
@ -61,8 +70,9 @@ public class ExamManager : DomainService, IExamManager
var paperIds = templates.Select(s => s.PaperId).ToList(); var paperIds = templates.Select(s => s.PaperId).ToList();
// 获取点阵数据 // 获取点阵数据
var lattices = await Db.Queryable<PenOfflineData>() var timespan = (long)(eto.LastCollectTime - new DateTime(1970, 1, 1, 0, 0, 0)).TotalMilliseconds;
.Where(w => w.PenSerial == penSerial && paperIds.Contains(w.PageSerial) && w.logType == LogType.) 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 .Select(s => new PenOfflineData
{ {
PageSerial = s.PageSerial, PageSerial = s.PageSerial,
@ -71,23 +81,26 @@ public class ExamManager : DomainService, IExamManager
Time = s.Time, Time = s.Time,
strokeIndex = s.strokeIndex, strokeIndex = s.strokeIndex,
}).ToListAsync(); }).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) if (lattices.Count == 0)
{ {
Logger.LogInformation("{ExamSubjectId} {penSerial} 无点阵数据", eto.ExamSubjectId, penSerial); Logger.LogInformation("{ExamSubjectId} {penSerial} 无点阵数据", eto.ExamSubjectId, penSerial);
return; return;
} }
var DbBiz = await GetTenantDb(eto.SchoolId);
var kgtDtls = await DbBiz.Queryable<MarkingSettingObjective>() var kgtDtls = await DbBiz.Queryable<MarkingSettingObjective>()
.Where(w => w.ExamSubjectId == eto.ExamSubjectId) .Where(w => w.ExamSubjectId == eto.ExamSubjectId)
.Select(s => new MkExamResult .Select(s => new MkExamResult
{ {
Id = YitIdHelper.NextId(),
StudentNo = penSerial, StudentNo = penSerial,
ExamId = eto.ExamId, ExamId = eto.ExamSubjectSchoolId,
ExamSubjectId = eto.ExamSubjectId, ExamSubjectId = eto.ExamSubjectId,
QuestionNumber = s.QuestionNum, QuestionNumber = s.QuestionNum,
IsObjectiveQuestion = true, IsObjectiveQuestion = true,
QuestionValue = string.Empty,
GroupNo = guid, GroupNo = guid,
}).ToListAsync(); }).ToListAsync();
@ -104,15 +117,18 @@ public class ExamManager : DomainService, IExamManager
return; return;
} }
var redisLockKey = "LockKey:" + eto.ExamSubjectId; var redisLockKey = "GatherLockKey:" + eto.ExamSubjectId;
var redisLock = await RedisHelper.GetAsync(redisLockKey); var redisLock = await RedisHelper.GetAsync(redisLockKey);
if (string.IsNullOrEmpty(redisLock)) if (string.IsNullOrEmpty(redisLock))
{ {
await RedisHelper.SetAsync(redisLockKey, "1"); await RedisHelper.SetAsync(redisLockKey, "1");
try
{
var dotPenOriginalImgs = new List<string>();
foreach (var paper in paperInfo) foreach (var paper in paperInfo)
{ {
var imgStream = await paper.ImgUrl.GetStreamAsync(); var imgBytes = await paper.ImgUrl.GetBytesAsync();
var bitmap = SKBitmap.Decode(imgStream); var bitmap = SKBitmap.Decode(imgBytes);
var nextPaper = paperInfo.FirstOrDefault(w => w.PartId == paper.PartId && w.PageIndex == paper.PageIndex + 1); var nextPaper = paperInfo.FirstOrDefault(w => w.PartId == paper.PartId && w.PageIndex == paper.PageIndex + 1);
@ -121,6 +137,9 @@ public class ExamManager : DomainService, IExamManager
if (que.type != "2") continue; if (que.type != "2") continue;
if (que.options == null || que.options.Count == 0) continue; if (que.options == null || que.options.Count == 0) continue;
var dotPenOriginalImg = $"que/{eto.ExamSubjectId}/{que.no}.jpg";
if (dotPenOriginalImgs.Contains(dotPenOriginalImg)) continue;
var area = que.options[0].AnswerArea; var area = que.options[0].AnswerArea;
var areaTop = area.pxTop; var areaTop = area.pxTop;
var areaHeight = area.pxHeight; var areaHeight = area.pxHeight;
@ -133,8 +152,8 @@ public class ExamManager : DomainService, IExamManager
var queOnNextPaper = nextPaper?.QueData.FirstOrDefault(w => w.no == que.no); var queOnNextPaper = nextPaper?.QueData.FirstOrDefault(w => w.no == que.no);
if (queOnNextPaper?.options?.Count >= 1) if (queOnNextPaper?.options?.Count >= 1)
{ {
var nextImgStream = await nextPaper.ImgUrl.GetStreamAsync(); var nextImgBytes = await nextPaper.ImgUrl.GetBytesAsync();
nextImgBitmap = SKBitmap.Decode(nextImgStream); nextImgBitmap = SKBitmap.Decode(nextImgBytes);
var nextArea = queOnNextPaper.options[0].AnswerArea; var nextArea = queOnNextPaper.options[0].AnswerArea;
var nextAreaTop = nextArea.pxTop; var nextAreaTop = nextArea.pxTop;
@ -154,13 +173,21 @@ public class ExamManager : DomainService, IExamManager
} }
var dtl = zgtSettingDtls.FirstOrDefault(w => w.QuestionNum == que.no); var dtl = zgtSettingDtls.FirstOrDefault(w => w.QuestionNum == que.no);
dtl.DotPenOriginalImg = $"que/{eto.ExamSubjectId}/{paper.Sort}/{que.no}.png"; dtl.DotPenOriginalImg = dotPenOriginalImg;
await _blobContainer.SaveAsync(dtl.DotPenOriginalImg, newBitmap.Encode(SKEncodedImageFormat.Png, 100).ToArray(), true); await _blobContainer.SaveAsync(dtl.DotPenOriginalImg, newBitmap.Encode(SKEncodedImageFormat.Jpeg, 100).ToArray(), true);
dotPenOriginalImgs.Add(dotPenOriginalImg);
} }
} }
} }
await Db.Updateable(zgtSettingDtls).UpdateColumns(s => s.DotPenOriginalImg).Where(w => w.DotPenOriginalImg.IsNotNullOrEmpty()).ExecuteCommandAsync(); await DbBiz.Updateable(zgtSettingDtls).UpdateColumns(s => s.DotPenOriginalImg).ExecuteCommandAsync();
await RedisHelper.SetAsync(redisLockKey, "0"); await RedisHelper.DelAsync(redisLockKey);
}
catch (Exception ex)
{
Logger.LogError("{ExamSubjectId} {penSerial} 收集失败! 原题切割异常: {error}", eto.ExamSubjectId, penSerial, ex);
await RedisHelper.DelAsync(redisLockKey);
throw;
}
} }
else else
{ {
@ -173,6 +200,18 @@ public class ExamManager : DomainService, IExamManager
} }
} }
// 锁处理
var studentRedisLockKey = "LockKey:" + eto.ExamSubjectId + penSerial;
var studentRedisLock = await RedisHelper.GetAsync(studentRedisLockKey);
if (studentRedisLock == "1")
{
Logger.LogInformation("{ExamSubjectId} {penSerial} 正在收集中,此次收集跳过", eto.ExamSubjectId, penSerial);
return;
}
await RedisHelper.SetAsync(studentRedisLockKey, "1");
try
{
var zgtDtls = zgtSettingDtls.Select(s => new SubjectiveMarkingResult var zgtDtls = zgtSettingDtls.Select(s => new SubjectiveMarkingResult
{ {
Id = YitIdHelper.NextId(), Id = YitIdHelper.NextId(),
@ -183,6 +222,7 @@ public class ExamManager : DomainService, IExamManager
TotalScore = s.Score, TotalScore = s.Score,
SubQuestionCount = s.SubQuestionCount, SubQuestionCount = s.SubQuestionCount,
SubQuestionDetail = s.SubQuestionDetail, SubQuestionDetail = s.SubQuestionDetail,
StudentAnswer = $"[\"{_aliyunOption.Host}/{s.DotPenOriginalImg}\"]",
GroupNo = guid, GroupNo = guid,
BigQuestionNum = s.BigQuestionNum, BigQuestionNum = s.BigQuestionNum,
IsExcess = s.IsExcess, IsExcess = s.IsExcess,
@ -228,6 +268,10 @@ public class ExamManager : DomainService, IExamManager
} }
} }
foreach (var _kgtDtl in kgtDtls)
{
_kgtDtl.Id = YitIdHelper.NextId();
}
var kgtPapers = kgt.GroupBy(s => s.Item1).Select(s => s.Key).ToList(); // 客观题处理 var kgtPapers = kgt.GroupBy(s => s.Item1).Select(s => s.Key).ToList(); // 客观题处理
foreach (var paperId in kgtPapers) foreach (var paperId in kgtPapers)
{ {
@ -270,7 +314,6 @@ public class ExamManager : DomainService, IExamManager
foreach (var paperId in zgtPapers) foreach (var paperId in zgtPapers)
{ {
var paper = paperInfo.FirstOrDefault(w => w.PaperId == paperId); 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 paperLatts = lattices.Where(w => w.PageSerial == paperId).ToList();
var ques = zgt.Where(w => w.Item1 == paperId).ToList(); var ques = zgt.Where(w => w.Item1 == paperId).ToList();
@ -325,32 +368,52 @@ public class ExamManager : DomainService, IExamManager
canvas.DrawPoints(skPointMode, points, skPaint); canvas.DrawPoints(skPointMode, points, skPaint);
} }
stuAnswer = $"queAnswer/{eto.ExamSubjectId}/{penSerial}/{paper.Sort}/{queNo}.png"; stuAnswer = $"stu-answer/{eto.ExamSubjectId}/{penSerial}/{queNo}.jpg";
await _blobContainer.SaveAsync(stuAnswer, queBitmap.Encode(SKEncodedImageFormat.Png, 100).ToArray(), true); await _blobContainer.SaveAsync(stuAnswer, queBitmap.Encode(SKEncodedImageFormat.Jpeg, 100).ToArray(), true);
} }
var dtl = zgtDtls.FirstOrDefault(w => w.QuestionNum == queNo); var dtl = zgtDtls.FirstOrDefault(w => w.QuestionNum == queNo);
if (dtl != null) if (dtl != null)
{ {
dtl.StudentAnswer = stuAnswer; 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.Deleteable<MkExamResult>().Where(w => w.ExamSubjectId == eto.ExamSubjectId && w.StudentNo == penSerial).ExecuteCommandAsync();
await DbBiz.Updateable<SubjectiveMarkingResult>() await DbBiz.Updateable<SubjectiveMarkingResult>()
.SetColumns(s => s.IsDeleted == true) .SetColumns(s => new SubjectiveMarkingResult { IsDeleted = true, UpdateDate = Clock.Now })
.Where(w => w.ExamSubjectId == eto.ExamSubjectId && w.StudentExamNum == penSerial && w.IsDeleted == false) .Where(w => w.ExamSubjectId == eto.ExamSubjectId && w.StudentExamNum == penSerial && w.IsDeleted == false)
.ExecuteCommandAsync(); .ExecuteCommandAsync();
// 新增 // 新增
await DbBiz.Insertable(kgtDtls).ExecuteCommandAsync(); await DbBiz.Insertable(kgtDtls).ExecuteCommandAsync();
await DbBiz.Insertable(zgtDtls).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)
{
Logger.LogError("{ExamSubjectId} {penSerial} 收集失败! {error}", eto.ExamSubjectId, penSerial, ex);
}
finally
{
await RedisHelper.DelAsync(studentRedisLockKey);
}
} }
[AutoTran]
public async Task ExamAnnotate(ExamAnnotateEto eto) 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(); var tenant = await Db.Queryable<Tenant>().Where(w => w.TenantCode == tenantCode).FirstAsync();
ExceptionExt.ThrowIf(tenant == null, $"{nameof(tenant)} is null with ${tenantCode}"); ExceptionExt.ThrowIf(tenant == null, $"{nameof(tenant)} is null with ${tenantCode}");
var config = new SqlSugarConfig();
return new SqlSugarClient(new ConnectionConfig() return new SqlSugarClient(new ConnectionConfig()
{ {
DbType = DbType.MySql, DbType = DbType.MySql,
ConnectionString = tenant.ConnectionString, ConnectionString = tenant.ConnectionString,
IsAutoCloseConnection = true, IsAutoCloseConnection = true,
ConfigureExternalServices = config.ExtService, ConfigureExternalServices = MySqlConfigureExternalServices.MySqlExtService,
}); });
} }
} }

View File

@ -12,6 +12,6 @@ public class ExamAppService : DolphinAppService
public async Task Test() 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 });
} }
} }

View File

@ -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;
}
}

View File

@ -17,17 +17,13 @@
<PackageReference Include="CSRedisCore" Version="3.8.802" /> <PackageReference Include="CSRedisCore" Version="3.8.802" />
<PackageReference Include="Flurl.Http" Version="4.0.2" /> <PackageReference Include="Flurl.Http" Version="4.0.2" />
<PackageReference Include="NoFurion" Version="0.0.7" /> <PackageReference Include="NoFurion" Version="0.0.7" />
<PackageReference Include="SkiaSharp" Version="2.88.6" /> <PackageReference Include="SkiaSharp" Version="2.88.7" />
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="2.88.6" /> <PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="2.88.7" />
<PackageReference Include="Volo.Abp.BlobStoring.Aliyun" Version="8.0.2" /> <PackageReference Include="Volo.Abp.BlobStoring.Aliyun" Version="8.0.5" />
<PackageReference Include="Volo.Abp.EventBus.RabbitMQ" Version="8.0.2" /> <PackageReference Include="Volo.Abp.EventBus.RabbitMQ" Version="8.0.5" />
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" /> <PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Options\" />
</ItemGroup>
</Project> </Project>

View File

@ -1,4 +1,8 @@
using Dolphin.ExamPictureCut.Localization; using Dolphin.ExamPictureCut.Localization;
using Dolphin.ExamPictureCut.Options;
using Mapster;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using NoFurion.Extensions; using NoFurion.Extensions;
using Volo.Abp.Application; using Volo.Abp.Application;
using Volo.Abp.BlobStoring; using Volo.Abp.BlobStoring;
@ -22,11 +26,22 @@ public class DolphinExamPictureCutCoreModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) 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 => Configure<AbpBlobStoringOptions>(options =>
{ {
options.Containers.ConfigureDefault(container => 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;
});
}); });
}); });

View File

@ -7,8 +7,8 @@ namespace Dolphin.ExamPictureCut.Domains.Basic;
[Table(nameof(GroupBook)), Tenant(DbConsts.marking_basic)] [Table(nameof(GroupBook)), Tenant(DbConsts.marking_basic)]
public class GroupBook public class GroupBook
{ {
[SugarColumn(IsPrimaryKey = true, ColumnName = "id", Length = 32)] [SugarColumn(IsPrimaryKey = true, ColumnName = "id")]
public string Id { get; set; } public long Id { get; set; }
[SugarColumn(ColumnName = "book_id")] [SugarColumn(ColumnName = "book_id")]
public long BookId { get; set; } public long BookId { get; set; }

View File

@ -7,8 +7,8 @@ namespace Dolphin.ExamPictureCut.Domains.Basic;
[Table(nameof(GroupBookPaperTemplate)), Tenant(DbConsts.marking_basic)] [Table(nameof(GroupBookPaperTemplate)), Tenant(DbConsts.marking_basic)]
public class GroupBookPaperTemplate public class GroupBookPaperTemplate
{ {
[SugarColumn(IsPrimaryKey = true, ColumnName = "id", Length = 32)] [SugarColumn(IsPrimaryKey = true, ColumnName = "id")]
public string Id { get; set; } public long Id { get; set; }
[SugarColumn(ColumnName = "book_id")] [SugarColumn(ColumnName = "book_id")]
public long BookId { get; set; } public long BookId { get; set; }

View File

@ -19,7 +19,7 @@ public class Tenant : ISoftDelete
public string TenantName { get; set; } public string TenantName { get; set; }
[NotMapped] [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 IsEnable { get; set; }
public bool IsDeleted { get; set; } public bool IsDeleted { get; set; }

View File

@ -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; }
}

View File

@ -1,7 +1,12 @@
using SqlSugar;
using System.ComponentModel.DataAnnotations.Schema;
namespace Dolphin.ExamPictureCut.Domains.Biz; namespace Dolphin.ExamPictureCut.Domains.Biz;
[Table(nameof(MarkingSettingSubjective))]
public class MarkingSettingSubjective public class MarkingSettingSubjective
{ {
[SugarColumn(IsPrimaryKey = true)]
public long Id { get; set; } public long Id { get; set; }
public long ExamSubjectId { get; set; } public long ExamSubjectId { get; set; }
public string QuestionNum { get; set; } public string QuestionNum { get; set; }

View File

@ -1,8 +1,9 @@
using Dolphin.ExamPictureCut.Options;
using SqlSugar; using SqlSugar;
namespace Dolphin.ExamPictureCut.Domains.Biz; namespace Dolphin.ExamPictureCut.Domains.Biz;
[SugarTable("MK_ExamResult")] [SugarTable("MK_ExamResult"), IgnoreUnderLine]
public class MkExamResult public class MkExamResult
{ {
[SugarColumn(IsPrimaryKey = true, ColumnName = "ID_bigint")] [SugarColumn(IsPrimaryKey = true, ColumnName = "ID_bigint")]
@ -14,6 +15,7 @@ public class MkExamResult
[SugarColumn(ColumnName = "ExamId_bigint")] [SugarColumn(ColumnName = "ExamId_bigint")]
public long ExamId { get; set; } public long ExamId { get; set; }
[SugarColumn(ColumnName = "ExamSubjectId")]
public long ExamSubjectId { get; set; } public long ExamSubjectId { get; set; }
[SugarColumn(ColumnName = "QuestionNumber_int")] [SugarColumn(ColumnName = "QuestionNumber_int")]
@ -34,5 +36,6 @@ public class MkExamResult
[SugarColumn(ColumnName = "GroupNo_nvarchar")] [SugarColumn(ColumnName = "GroupNo_nvarchar")]
public string GroupNo { get; set; } public string GroupNo { get; set; }
[SugarColumn(ColumnName = "IsSync")]
public bool IsSync { get; set; } public bool IsSync { get; set; }
} }

View File

@ -1,7 +1,10 @@
using SqlSugar;
using System.ComponentModel.DataAnnotations.Schema;
using Volo.Abp; using Volo.Abp;
namespace Dolphin.ExamPictureCut.Domains.Biz; namespace Dolphin.ExamPictureCut.Domains.Biz;
[Table(nameof(SubjectiveMarkingResult))]
public class SubjectiveMarkingResult : ISoftDelete public class SubjectiveMarkingResult : ISoftDelete
{ {
public long Id { get; set; } public long Id { get; set; }
@ -17,10 +20,15 @@ public class SubjectiveMarkingResult : ISoftDelete
public string GroupNo { get; set; } public string GroupNo { get; set; }
public bool IsAssign { get; set; } public bool IsAssign { get; set; }
public bool IsRating { get; set; } public bool IsRating { get; set; }
public string CommentImgUrl { get; set; } = "[]"; public string CommentImageUrl { get; set; } = "[]";
public string BigQuestionNum { get; set; } public string BigQuestionNum { get; set; }
public bool IsExcess { get; set; } public bool IsExcess { get; set; }
public bool IsDeleted { get; set; } public bool IsDeleted { get; set; }
[SugarColumn(InsertServerTime = true)]
public DateTime CreateDate { get; set; } public DateTime CreateDate { get; set; }
[SugarColumn(InsertServerTime = true, UpdateServerTime = true)]
public DateTime UpdateDate { get; set; } public DateTime UpdateDate { get; set; }
} }

View File

@ -0,0 +1,5 @@
namespace Dolphin.ExamPictureCut.Domains;
public class IgnoreUnderLineAttribute : Attribute
{
}

View File

@ -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);
}
}
};
}

View File

@ -1,5 +1,6 @@
using Dolphin.ExamPictureCut.Constants; using Dolphin.ExamPictureCut.Constants;
using Dolphin.ExamPictureCut.Domains.Basic; using Dolphin.ExamPictureCut.Domains.Basic;
using Dolphin.ExamPictureCut.Options;
using SqlSugar; using SqlSugar;
namespace Dolphin.ExamPictureCut.Domains.Quest; namespace Dolphin.ExamPictureCut.Domains.Quest;
@ -7,7 +8,7 @@ namespace Dolphin.ExamPictureCut.Domains.Quest;
/// <summary> /// <summary>
/// 点阵笔离线数据 /// 点阵笔离线数据
/// </summary> /// </summary>
[Tenant(DbConsts.penoffline)] [Tenant(DbConsts.penoffline), IgnoreUnderLine]
public class PenOfflineData public class PenOfflineData
{ {
/// <summary> /// <summary>

View File

@ -24,9 +24,10 @@ public class ExamStudentGatherEto
/// <summary> /// <summary>
/// 模板id /// 模板id
/// </summary> /// </summary>
public string TemplateId { get; set; } public long BookId { get; set; }
/// <summary> /// <summary>
/// 所属学生 /// 所属学生
/// </summary> /// </summary>
public string StudentExamNum { get; set; } public string StudentExamNum { get; set; }
public DateTime LastCollectTime { get; set; }
} }

View File

@ -20,7 +20,7 @@ public class TemplateJsonModel_DataArr
} }
public class PaperQueData public class PaperQueData
{ {
public string TemplateId { get; set; } public long TemplateId { get; set; }
public string PaperId { get; set; } public string PaperId { get; set; }
public long PartId { get; set; } public long PartId { get; set; }
public int PageIndex { get; set; } public int PageIndex { get; set; }

View File

@ -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; }
}

View File

@ -11,10 +11,10 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" /> <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.Authentication.JwtBearer" Version="8.0.5" />
<PackageReference Include="Volo.Abp.AspNetCore.Serilog" Version="8.0.2" /> <PackageReference Include="Volo.Abp.AspNetCore.Serilog" Version="8.0.5" />
<PackageReference Include="Volo.Abp.Autofac" Version="8.0.2" /> <PackageReference Include="Volo.Abp.Autofac" Version="8.0.5" />
<PackageReference Include="Volo.Abp.Swashbuckle" Version="8.0.2" /> <PackageReference Include="Volo.Abp.Swashbuckle" Version="8.0.5" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,5 +1,7 @@
using Dolphin.ExamPictureCut.Constants; using Dolphin.ExamPictureCut.Constants;
using Dolphin.ExamPictureCut.Domains;
using Dolphin.ExamPictureCut.Extensions; using Dolphin.ExamPictureCut.Extensions;
using Dolphin.ExamPictureCut.Options;
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Cors;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
@ -41,45 +43,6 @@ public class DolphinExamPictureCutHttpApiHostModule : AbpModule
private void ConfigureSqlSugar(ServiceConfigurationContext context, IConfiguration configuration) 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 => context.Services.AddSingleton<ISqlSugarClient>(s =>
{ {
var scope = new SqlSugarScope( var scope = new SqlSugarScope(
@ -90,7 +53,7 @@ public class DolphinExamPictureCutHttpApiHostModule : AbpModule
DbType = DbType.MySql, DbType = DbType.MySql,
ConnectionString = configuration.GetConnectionString(DbConsts.marking_basic), ConnectionString = configuration.GetConnectionString(DbConsts.marking_basic),
IsAutoCloseConnection = true, IsAutoCloseConnection = true,
ConfigureExternalServices = ExtService, ConfigureExternalServices = MySqlConfigureExternalServices.MySqlExtService,
}, },
new ConnectionConfig() new ConnectionConfig()
{ {
@ -98,13 +61,14 @@ public class DolphinExamPictureCutHttpApiHostModule : AbpModule
DbType = DbType.QuestDB, DbType = DbType.QuestDB,
ConnectionString = configuration.GetConnectionString(DbConsts.penoffline), ConnectionString = configuration.GetConnectionString(DbConsts.penoffline),
IsAutoCloseConnection = true, IsAutoCloseConnection = true,
ConfigureExternalServices = ExtService, ConfigureExternalServices = MySqlConfigureExternalServices.MySqlExtService,
}, },
}, },
db => db =>
{ {
db.QueryFilter.AddTableFilter<ISoftDelete>(s => s.IsDeleted == false); db.QueryFilter.AddTableFilter<ISoftDelete>(s => s.IsDeleted == false);
var config = new SqlSugarConfig();
db.Aop.DataExecuting = config.DataExecuting(context.Services); db.Aop.DataExecuting = config.DataExecuting(context.Services);
db.Aop.OnLogExecuting = (sql, pars) => db.Aop.OnLogExecuting = (sql, pars) =>

View File

@ -4,7 +4,7 @@
}, },
"ConnectionStrings": { "ConnectionStrings": {
"marking_basic": "Server=192.168.2.9;Port=3306;Database=marking_basic;Uid=root;Pwd=qwe123!@#;AllowLoadLocalInfile=true;", "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": { "Redis": {
"Configuration": "192.168.2.7:6379,password=qwe123!@#,defaultDatabase=14,idleTimeout=3000,poolsize=5,prefix=marking" "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", "HostName": "192.168.2.7",
"Port": "5672", "Port": "5672",
"UserName": "rabbit", "UserName": "rabbit",
"Password": "qwe123!@#" "Password": "qwe123!@#",
"VirtualHost": "marking"
} }
}, },
"EventBus": { "EventBus": {
"ClientName": "collect_queue", "ClientName": "collect_queue",
"ExchangeName": "tenant_ex" "ExchangeName": "exam_gather_ex"
} }
}, },
"Aliyun": { "Aliyun": {

View File

@ -18,12 +18,13 @@
"HostName": "192.168.2.7", "HostName": "192.168.2.7",
"Port": "5672", "Port": "5672",
"UserName": "rabbit", "UserName": "rabbit",
"Password": "qwe123!@#" "Password": "qwe123!@#",
"VirtualHost": "marking"
} }
}, },
"EventBus": { "EventBus": {
"ClientName": "collect_queue", "ClientName": "collect_queue",
"ExchangeName": "tenant_ex" "ExchangeName": "exam_gather_ex"
} }
}, },
"Aliyun": { "Aliyun": {