1、添加补考限制次数

2、考试 添加 试卷表单 并完善传值
3、考试完成提示按规定做提示
4、添加考试 及格判断 不及格 根据后台配置次数 判断重考
5、重考 培训内容 按规则重新刷题    课件则 排序错位考试
This commit is contained in:
wyw 2026-02-04 14:39:31 +08:00
parent 7493821ba1
commit 1abe6eef18
5 changed files with 138215 additions and 32 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,24 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace APT.Data.Migrations.Migrations
{
public partial class wyw2026020401 : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "COUNT_RETRY",
table: "T_SE_SECONFIG",
type: "int",
nullable: false,
defaultValue: 1);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "COUNT_RETRY",
table: "T_SE_SECONFIG");
}
}
}

View File

@ -73349,6 +73349,9 @@ namespace APT.Data.Migrations.Migrations
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier"); .HasColumnType("uniqueidentifier");
b.Property<int>("COUNT_RETRY")
.HasColumnType("int");
b.Property<Guid?>("CREATER_ID") b.Property<Guid?>("CREATER_ID")
.HasColumnType("uniqueidentifier"); .HasColumnType("uniqueidentifier");

View File

@ -77,5 +77,12 @@ namespace APT.MS.Domain.Entities.SE
[Description("合格线")] [Description("合格线")]
[FormFieldEdit] [FormFieldEdit]
public int PASS_MARK { get; set; } public int PASS_MARK { get; set; }
/// <summary>
/// 重考次数
/// </summary>
[Description("重考次数")]
[FormFieldEdit]
public int COUNT_RETRY { get; set; } = 1;
} }
} }

View File

@ -229,6 +229,11 @@ namespace APT.SC.WebApi.Controllers.Api.SE
public List<T_SE_TRAIN_RECORD_PAPER> Nav_Papers { get; set; } public List<T_SE_TRAIN_RECORD_PAPER> Nav_Papers { get; set; }
public T_SE_SECONFIG Nav_Config { get; set; } public T_SE_SECONFIG Nav_Config { get; set; }
public Guid TaskID { get; set; } public Guid TaskID { get; set; }
/// <summary>
/// 考卷ID
/// </summary>
public Guid TEXT_ID { get; set; }
} }
[HttpPost, Route("GetUserPapers")] [HttpPost, Route("GetUserPapers")]
@ -247,8 +252,35 @@ namespace APT.SC.WebApi.Controllers.Api.SE
ret.ErrorMessage = ""; ret.ErrorMessage = "";
return ret; return ret;
} }
/// <summary>
/// 考试返回结果
/// </summary>
public class SavePapersResult
{
/// <summary>
/// 是否操作成功
/// </summary>
public bool IsOperateSuccessful { get; set; }
/// <summary>
/// 是否考试通过
/// </summary>
public bool IsPass { get; set; }
/// <summary>
/// 提示消息
/// </summary>
public string Msg { get; set; }
}
/// <summary>
/// 考试
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
[HttpPost, Route("SavePapers")] [HttpPost, Route("SavePapers")]
public JsonActionResult<bool> SavePapers([FromBody] TrainUserPaperModel entity) public JsonActionResult<SavePapersResult> SavePapers([FromBody] TrainUserPaperModel entity)
{ {
return SafeExecute(() => return SafeExecute(() =>
{ {
@ -260,39 +292,83 @@ namespace APT.SC.WebApi.Controllers.Api.SE
{ {
throw new Exception("试卷不能为空"); throw new Exception("试卷不能为空");
} }
var score = 0; //是否课件触发考试
var sscore = entity.Nav_Config.S_TEST_SCORE; bool isCour = false;
var mscore = entity.Nav_Config.M_TEST_SCORE; if (entity.Nav_Papers[0].EDU_CARD_ID.HasValue)
var cscore = entity.Nav_Config.C_TEST_SCORE; isCour = true;
foreach (var item in entity.Nav_Papers)
{
if (item.ANSWER != 0 && item.ANSWER == item.Nav_Test.ANSWER)
{
if (item.Nav_Test.TYPE == SETestTypeEnum.)
{
score += cscore;
}
else if (item.Nav_Test.TYPE == SETestTypeEnum.)
{
score += sscore;
}
else if (item.Nav_Test.TYPE == SETestTypeEnum.)
{
score += mscore;
}
}
}
foreach (var item in entity.Nav_Papers)
{
item.SCORE = score;
}
var finishNotice = NotificationTaskService.GetTaskFinishModel(entity.TaskID); var finishNotice = NotificationTaskService.GetTaskFinishModel(entity.TaskID);
if (finishNotice == null)
{
throw new Exception("请到在待办中进入答题!");
}
#region
decimal score = 0;
T_SE_TRAIN_RECORD_USER RecordUser = null; T_SE_TRAIN_RECORD_USER RecordUser = null;
T_SE_TRAIN_RECORD_TEXT modelText = GetEntity<T_SE_TRAIN_RECORD_TEXT>(entity.TEXT_ID);
if (APT.Infrastructure.Api.AppContext.CurrentSession.UserID.HasValue) if (APT.Infrastructure.Api.AppContext.CurrentSession.UserID.HasValue)
{ {
RecordUser = GetEntity<T_SE_TRAIN_RECORD_USER>(e => e.RECORD_ID == finishNotice.SOURCE_DATA_ID && e.USER_ID == APT.Infrastructure.Api.AppContext.CurrentSession.UserID); RecordUser = GetEntity<T_SE_TRAIN_RECORD_USER>(e => e.RECORD_ID == modelText.RECORD_ID && e.USER_ID == APT.Infrastructure.Api.AppContext.CurrentSession.UserID);
RecordUser.SCORE = score; }
#region
if (isCour)
{
//课件模式 每个课件 计算平均分
var listEduCardID = entity.Nav_Papers.Select(e => e.EDU_CARD_ID).Distinct();
var listCour = GetEntities<T_SE_COURSEWEARLIBRARY>(e => listEduCardID.Contains(e.ID), null, "Nav_Detail.Nav_Test"); //Nav_Detail.SCOREPER
List<T_SE_COURSEWEARLIBRARY_DETAIL> listCourDetail = new List<T_SE_COURSEWEARLIBRARY_DETAIL>();
foreach (var item in listCour)
{
listCourDetail.AddRange(item.Nav_Detail);
}
decimal passScore = listCour.Sum(e => e.SCOREPASS);//合格总分
decimal allScore = 0;
T_SE_COURSEWEARLIBRARY_DETAIL modelCourDetailTest = null;
foreach (var item in entity.Nav_Papers)
{
modelCourDetailTest = listCourDetail.FirstOrDefault(e => e.TEST_ID == item.TEST_ID);
if (modelCourDetailTest != null)
{
allScore += modelCourDetailTest.SCOREPER;
if (modelCourDetailTest.Nav_Test.ANSWER == item.ANSWER)
{
score += modelCourDetailTest.SCOREPER;
}
}
}
RecordUser.EXAMINATION_RESULTS = score < passScore ? SEExaminationResultsEnum. : SEExaminationResultsEnum.;
RecordUser.SCORE = (int)(((decimal)100.0) * score / allScore);
}
else
{
//培训内容模式
var sscore = entity.Nav_Config.S_TEST_SCORE;
var mscore = entity.Nav_Config.M_TEST_SCORE;
var cscore = entity.Nav_Config.C_TEST_SCORE;
foreach (var item in entity.Nav_Papers)
{
if (item.ANSWER != 0 && item.ANSWER == item.Nav_Test.ANSWER)
{
if (item.Nav_Test.TYPE == SETestTypeEnum.)
{
score += cscore;
}
else if (item.Nav_Test.TYPE == SETestTypeEnum.)
{
score += sscore;
}
else if (item.Nav_Test.TYPE == SETestTypeEnum.)
{
score += mscore;
}
}
}
RecordUser.SCORE = (int)score;
int PASS_MARK = entity.Nav_Config.PASS_MARK; int PASS_MARK = entity.Nav_Config.PASS_MARK;
if (PASS_MARK == 0) if (PASS_MARK == 0)
{ {
@ -301,6 +377,38 @@ namespace APT.SC.WebApi.Controllers.Api.SE
RecordUser.EXAMINATION_RESULTS = RecordUser.SCORE < PASS_MARK ? SEExaminationResultsEnum. : SEExaminationResultsEnum.; RecordUser.EXAMINATION_RESULTS = RecordUser.SCORE < PASS_MARK ? SEExaminationResultsEnum. : SEExaminationResultsEnum.;
} }
#endregion
if (RecordUser.SCORE.HasValue)
{
entity.Nav_Papers.ForEach(e => e.SCORE = RecordUser.SCORE.Value);
}
else
{
entity.Nav_Papers.ForEach(e => e.SCORE = (int)score);
}
//foreach (var item in entity.Nav_Papers)
//{
// item.SCORE = (int)score;
//}
#endregion
modelText.SCORE = RecordUser.SCORE;
modelText.ISPASS = RecordUser.EXAMINATION_RESULTS == SEExaminationResultsEnum. ? true : false;
#region
T_SE_TRAIN_RECORD_TEXT modelTextNew = null;
List<T_SE_TRAIN_RECORD_PAPER> listPaperNew = null;
T_FM_NOTIFICATION_TASK reSendNotice = null;
if (RecordUser.EXAMINATION_RESULTS == SEExaminationResultsEnum.)
{
ReText(entity.Nav_Config, entity.Nav_Papers, modelText, finishNotice.NOTICE_TITLE, ref modelTextNew, ref listPaperNew, ref reSendNotice);
}
#endregion
UnifiedCommit(() => UnifiedCommit(() =>
{ {
if (finishNotice != null) if (finishNotice != null)
@ -309,12 +417,312 @@ namespace APT.SC.WebApi.Controllers.Api.SE
UpdateEntityNoCommit(RecordUser); UpdateEntityNoCommit(RecordUser);
BantchSaveEntityNoCommit(entity.Nav_Papers); BantchSaveEntityNoCommit(entity.Nav_Papers);
//重考
if (reSendNotice != null)
UpdateEntityNoCommit(reSendNotice);
if (modelTextNew != null)
UpdateEntityNoCommit(modelTextNew);
if (listPaperNew != null && listPaperNew.Count > 0)
BantchSaveEntityNoCommit(listPaperNew);
}); });
return true; SavePapersResult result = new SavePapersResult();
result.IsOperateSuccessful = true;
if (RecordUser.EXAMINATION_RESULTS == SEExaminationResultsEnum.)
{
result.IsPass = true;
result.Msg = "此次考试成绩为【" + modelText.SCORE + "】,恭喜通过考试!";
}
else
{
result.IsPass = false;
if (reSendNotice != null)
result.Msg = "此次考试成绩为【" + modelText.SCORE + " 】,考试不合格,请重新考试!";
else
result.Msg = "此次考试成绩为【" + modelText.SCORE + " 】,考试不合格,请关注重考培训通知!";
}
return result;
}); });
} }
#region SavePapers
//[HttpPost, Route("SavePapers")]
//public JsonActionResult<bool> SavePapers([FromBody] TrainUserPaperModel entity)
//{
// return SafeExecute(() =>
// {
// if (entity.TaskID == Guid.Empty)
// {
// throw new Exception("获取待办传参失败,请在首页待办进入考试!");
// }
// if (entity.Nav_Papers == null || entity.Nav_Papers.Count == 0)
// {
// throw new Exception("试卷不能为空");
// }
// var score = 0;
// var sscore = entity.Nav_Config.S_TEST_SCORE;
// var mscore = entity.Nav_Config.M_TEST_SCORE;
// var cscore = entity.Nav_Config.C_TEST_SCORE;
// foreach (var item in entity.Nav_Papers)
// {
// if (item.ANSWER != 0 && item.ANSWER == item.Nav_Test.ANSWER)
// {
// if (item.Nav_Test.TYPE == SETestTypeEnum.是非题)
// {
// score += cscore;
// }
// else if (item.Nav_Test.TYPE == SETestTypeEnum.单选题)
// {
// score += sscore;
// }
// else if (item.Nav_Test.TYPE == SETestTypeEnum.多选题)
// {
// score += mscore;
// }
// }
// }
// foreach (var item in entity.Nav_Papers)
// {
// item.SCORE = score;
// }
// var finishNotice = NotificationTaskService.GetTaskFinishModel(entity.TaskID);
// T_SE_TRAIN_RECORD_USER RecordUser = null;
// if (APT.Infrastructure.Api.AppContext.CurrentSession.UserID.HasValue)
// {
// RecordUser = GetEntity<T_SE_TRAIN_RECORD_USER>(e => e.RECORD_ID == finishNotice.SOURCE_DATA_ID && e.USER_ID == APT.Infrastructure.Api.AppContext.CurrentSession.UserID);
// RecordUser.SCORE = score;
// int PASS_MARK = entity.Nav_Config.PASS_MARK;
// if (PASS_MARK == 0)
// {
// PASS_MARK = 60;
// }
// RecordUser.EXAMINATION_RESULTS = RecordUser.SCORE < PASS_MARK ? SEExaminationResultsEnum.不合格 : SEExaminationResultsEnum.合格;
// }
// UnifiedCommit(() =>
// {
// if (finishNotice != null)
// UpdateEntityNoCommit(finishNotice);
// if (RecordUser != null)
// UpdateEntityNoCommit(RecordUser);
// BantchSaveEntityNoCommit(entity.Nav_Papers);
// });
// return true;
// });
//}
#endregion
/// <summary>
/// 考试如果不合格 重新添加试卷 触发考试
/// 生成 考试卷 试题 待办
/// </summary>
/// <param name="config"></param>
/// <param name="listPaper"></param>
/// <param name="modelText"></param>
/// <param name="NoticeTitle">考试待办 的 Title</param>
/// <param name="modelTextNew"></param>
/// <param name="listPaperNew"></param>
/// <param name="sendNotice"></param>
private void ReText(T_SE_SECONFIG config, List<T_SE_TRAIN_RECORD_PAPER> listPaper, T_SE_TRAIN_RECORD_TEXT modelText, string NoticeTitle, ref T_SE_TRAIN_RECORD_TEXT modelTextNew, ref List<T_SE_TRAIN_RECORD_PAPER> listPaperNew, ref T_FM_NOTIFICATION_TASK sendNotice)
{
if (listPaper == null || listPaper.Count < 1)
return;
bool isCour = false; //默认原有方式
if (listPaper[0].EDU_CARD_ID.HasValue)
isCour = true;
// 判断重考次数
// 次数 小于 对应配置
// 有课件 打乱顺序 重考
// 原版 重新获取试题
if (config == null)
config = GetEntity<T_SE_SECONFIG>(t => true);
if (config.COUNT_RETRY > modelText.TEXT_TIMES)
return;
modelTextNew = new T_SE_TRAIN_RECORD_TEXT();
modelTextNew.ID = Guid.NewGuid();
modelTextNew.ORG_ID = modelText.ORG_ID;
modelTextNew.CREATER_ID = APT.Infrastructure.Api.AppContext.CurrentSession.UserID;
modelTextNew.CREATE_TIME = DateTime.Now;
modelTextNew.TEXT_TIMES = modelText.TEXT_TIMES + 1;
modelTextNew.RECORD_ID = modelText.RECORD_ID;
modelTextNew.USER_ID = modelTextNew.CREATER_ID;
if (listPaperNew == null)
listPaperNew = new List<T_SE_TRAIN_RECORD_PAPER>();
T_FM_USER login = GetEntity<T_FM_USER>(e => e.ID == APT.Infrastructure.Api.AppContext.CurrentSession.UserID, "Nav_Person");
//获取试题
if (isCour)
{
//按课件培训打乱顺序重考
var listEduCardID = listPaper.Select(e => e.EDU_CARD_ID).Distinct();
Random random = new Random();
var listEduCardIDNew = listEduCardID.OrderBy(e => random.Next()).ToList();
IEnumerable<Guid?> listTEST_ID = null;
IEnumerable<Guid?> listTEST_IDRand = null;
foreach (var item in listEduCardIDNew)
{
listTEST_ID = listPaper.Where(e => e.EDU_CARD_ID == item && e.TEST_ID.HasValue).Select(e => e.TEST_ID).ToList();
listTEST_IDRand = listTEST_ID.OrderBy(e => random.Next()).ToList();//课件题目乱序
T_SE_TRAIN_RECORD_PAPER modelPafe = null;
foreach (var itemT in listTEST_IDRand)
{
modelPafe = listPaper.First(e => e.TEST_ID == itemT);
listPaperNew.Add(new T_SE_TRAIN_RECORD_PAPER()
{
ID = Guid.NewGuid(),
ORG_ID = modelTextNew.ORG_ID,
TEXT_ID = modelTextNew.ID,
RECORD_UUSER_ID = modelPafe.RECORD_UUSER_ID,//人员试卷 这边不加新的
RECORD_ID = modelPafe.RECORD_ID,
USER_ID = modelTextNew.USER_ID,
TEST_ID = itemT,
EDU_CARD_ID = modelPafe.EDU_CARD_ID,
FILE_PATH = modelPafe.FILE_PATH
});
}
}
}
else
{
//重新获取 试题
var record = GetEntity<T_SE_TRAIN_RECORD>(t => t.ID == modelText.RECORD_ID, new BaseFilter(modelText.ORG_ID), new string[] { "Nav_Notify", "Nav_Notify.Nav_TrainContentList" });
GetPaperPage(config, login, record, record.Nav_Notify, record.Nav_Notify.Nav_TrainContentList, modelTextNew.ID, ref listPaperNew);
}
string title = NoticeTitle;
if (modelTextNew.TEXT_TIMES > 1)
{
title += " 重考(" + modelTextNew.TEXT_TIMES + "";
}
sendNotice = NotificationTaskService.InsertUserNoticeTaskModel(title, modelTextNew.ID, modelTextNew.ORG_ID, login.ID, login.NAME, DateTime.Now, DateTime.Now.AddDays(2), 1, "SE018_PAPERPAGE");
}
/// <summary>
/// 原来的方式查找试题库 获取 试题
/// </summary>
/// <param name="config"></param>
/// <param name="record"></param>
/// <param name="Notify"></param>
/// <param name="ListTrainContent"></param>
/// <param name="TEXT_ID"></param>
/// <param name="login"></param>
/// <param name="listPaper"></param>
/// <exception cref="Exception"></exception>
private void GetPaperPage(T_SE_SECONFIG config, T_FM_USER login, T_SE_TRAIN_RECORD record, T_SE_TRAIN_NOTIFY Notify, List<T_SE_TRAIN_NOTIFY_CONTENT_REL> ListTrainContent, Guid TEXT_ID, ref List<T_SE_TRAIN_RECORD_PAPER> listPaper)
{
#region
if (config == null)
config = GetEntity<T_SE_SECONFIG>(t => true);
var SCount = 1;
var MCount = 1;
var CCount = 1;
if (config != null)
{
if (config.M_TEST_COUNT > 0 || config.S_TEST_COUNT > 0 || config.C_TEST_COUNT > 0)
{
//王永文 只要有配置 就获取
MCount = config.M_TEST_COUNT;
SCount = config.S_TEST_COUNT;
CCount = config.C_TEST_COUNT;
}
else
{
//保持原来的版本
if (config.M_TEST_COUNT > 0)
{
MCount = config.M_TEST_COUNT;
}
if (config.S_TEST_COUNT > 0)
{
SCount = config.S_TEST_COUNT;
}
if (config.C_TEST_COUNT > 0)
{
CCount = config.C_TEST_COUNT;
}
}
}
#endregion
var pointIDS = ListTrainContent.Select(t => t.POINT_ID).ToList();
var testFilter = new BaseFilter(record.ORG_ID);
testFilter.Include = new string[] { "Nav_Points", "Nav_Posts" };//岗位也得进去加以限制
//根据 培训名称 全字 匹配 如果有题库 再判断 知识点
//如果没匹配到题目 只匹配知识点
Guid? LoginPostID = null;
if (login == null && APT.Infrastructure.Api.AppContext.CurrentSession.UserID.HasValue)
{
login = GetEntity<T_FM_USER>(e => e.ID == APT.Infrastructure.Api.AppContext.CurrentSession.UserID, "Nav_Person");
}
LoginPostID = login.Nav_Person?.POST_ID;
bool isNameRule = false;
var allTests = GetEntities<T_SE_TEST>(st => st.Nav_Points.Any(pt => pointIDS.Contains(pt.POINT_ID.Value)) && (LoginPostID == null || st.Nav_Posts.Count() < 1 || st.Nav_Posts.Any(e => e.POST_ID.HasValue && e.POST_ID.Value == LoginPostID.Value)), testFilter).ToList();
if (allTests == null || allTests.Count() == 0)
{
isNameRule = true;
allTests = GetEntities<T_SE_TEST>(st => st.TRAINNAME == Notify.NAME && (LoginPostID == null || st.Nav_Posts.Count() < 1 || st.Nav_Posts.Any(e => e.POST_ID.HasValue && e.POST_ID.Value == LoginPostID.Value)), testFilter).ToList();
}
var errorMsg = "";
if (!isNameRule)
{
//根据名称来的就不要知识点限制了
foreach (var testPoint in pointIDS)
{
var havepoint = allTests.Where(st => st.Nav_Points.Any(pt => pt.POINT_ID == testPoint));
if (havepoint.Count() < 1)
{
var noPoint = GetEntity<T_SE_TEST_ENUM_POINT>(testPoint);
errorMsg += noPoint.NAME + ",";
}
}
}
if (errorMsg != "")
{
if (errorMsg.EndsWith(","))
errorMsg = errorMsg.Substring(0, errorMsg.Length - 1);
throw new Exception("知识点【" + errorMsg + "】没有题目!");
}
List<Guid> testidlist = new List<Guid>();
CreateTestList(allTests, testidlist, pointIDS, (int)SETestTypeEnum., CCount);
CreateTestList(allTests, testidlist, pointIDS, (int)SETestTypeEnum., SCount);
CreateTestList(allTests, testidlist, pointIDS, (int)SETestTypeEnum., MCount);
if (testidlist.Count == 0)
{
throw new Exception("当前题库数据不足,未能正常生成问卷");
}
if (listPaper == null)
{
listPaper = new List<T_SE_TRAIN_RECORD_PAPER>();
}
DateTime dtN = DateTime.Now;
int secAdd = 0;
foreach (var testid in testidlist)
{
var p = new T_SE_TRAIN_RECORD_PAPER
{
RECORD_ID = record.ID,
ID = Guid.NewGuid(),
ORG_ID = record.ORG_ID,
USER_ID = login.ID,
TEST_ID = testid,
ANSWER = 0,
TEXT_ID = TEXT_ID,
CREATE_TIME = dtN.AddSeconds(secAdd)
};
listPaper.Add(p);
secAdd++;
}
}
/// <summary> /// <summary>
/// 获得单条实体数据 /// 获得单条实体数据
/// </summary> /// </summary>