孤兰 2 months ago
commit 6df47339ca
  1. 1696
      Model/Tiobon.Web.pdm
  2. 10
      Tiobon.Core.Api/Controllers/Ghre/Ghre_OpenClassController.cs
  3. 10
      Tiobon.Core.Api/Tiobon.Core.Model.xml
  4. 7
      Tiobon.Core.Api/Tiobon.Core.xml
  5. 2
      Tiobon.Core.Api/appsettings.json
  6. 37
      Tiobon.Core.Common/Helper/ExamHelper.cs
  7. 2
      Tiobon.Core.IServices/Ghre/IGhre_OpenClassServices.cs
  8. 4
      Tiobon.Core.IServices/Ghre/IGhre_StudyRecordServices.cs
  9. 8
      Tiobon.Core.Model/Base/Ghre/Ghre_Plan.Dto.Base.cs
  10. 8
      Tiobon.Core.Model/Models/Ghre/Ghre_Plan.cs
  11. 5
      Tiobon.Core.Model/ViewModels/Extend/Ghre_StudyRecordESS.cs
  12. 11
      Tiobon.Core.Services/Ghre/Ghre_ExamRecordServices.cs
  13. 108
      Tiobon.Core.Services/Ghre/Ghre_OpenClassServices.cs
  14. 46
      Tiobon.Core.Services/Ghre/Ghre_StudyRecordServices.cs
  15. 37
      Tiobon.Core.Tasks/QuartzNet/Jobs/Job_AutoMarkCompleteStatus_Quartz.cs
  16. 10
      Tiobon.Core/Tiobon.Core.Model.xml
  17. 7
      Tiobon.Core/Tiobon.Core.xml

File diff suppressed because it is too large Load Diff

@ -220,4 +220,14 @@ public class Ghre_OpenClassController : BaseController<IGhre_OpenClassServices,
[HttpPost, Route("AttendCheckOut/{Id}")]
public async Task<ServiceResult> AttendCheckOut(long Id) => await _service.Attend(Id, "CheckOut");
#endregion
#region 邮件
/// <summary>
/// 邮件
/// </summary>
/// <param name="Id">开班ID</param>
/// <returns></returns>
[HttpPost, Route("Email/{Id}")]
public async Task<ServiceResult> Email(long Id) => await _service.Email(Id);
#endregion
}

@ -6855,6 +6855,11 @@
系统内置
</summary>
</member>
<member name="P:Tiobon.Core.Model.Models.Ghre_PlanBase.OutSideOrg">
<summary>
外训机构
</summary>
</member>
<member name="T:Tiobon.Core.Model.Models.Ghre_QuestionBase">
<summary>
题目 (Dto.Base)
@ -25472,6 +25477,11 @@
系统内置
</summary>
</member>
<member name="P:Tiobon.Core.Model.Models.Ghre_Plan.OutSideOrg">
<summary>
外训机构
</summary>
</member>
<member name="T:Tiobon.Core.Model.Models.Ghre_Question">
<summary>
题目 (Model)

@ -1260,6 +1260,13 @@
<param name="Id">开班ID</param>
<returns></returns>
</member>
<member name="M:Tiobon.Core.Api.Controllers.Ghre_OpenClassController.Email(System.Int64)">
<summary>
邮件
</summary>
<param name="Id">开班ID</param>
<returns></returns>
</member>
<member name="T:Tiobon.Core.Api.Controllers.Ghre_OpenClassFeeController">
<summary>
开班费用(Controller)

@ -269,7 +269,7 @@
"Enabled": false
},
"QuartzNetJob": {
"Enabled": false
"Enabled": true
},
"Consul": {
"Enabled": false

@ -91,4 +91,41 @@ public class ExamHelper
record.Score = score ?? 0;
}
public static async Task MarkCompleteStatusAsync(ISqlSugarClient Db, Ghre_StudyRecord record)
{
if (record.ExamId != null)
{
if (await Db.Queryable<Ghre_Exam>().Where(x => x.Id == record.ExamId && x.StudyFinishedRule == DIC_EXAM_STUDY_FINISHED_RULE.STUDY_FINISHED).AnyAsync() || await Db.Queryable<Ghre_ExamRecord>().Where(x => x.StudyRecordId == record.Id && x.IsPass == true).AnyAsync())
record.CompleteStatus = DIC_STUDY_RECORD_STUDY_COMPLETE_STATUS.FINISHED;
}
else
{
if (record.CourseSceneId.IsNotEmptyOrNull())
record.CompleteStatus = DIC_STUDY_RECORD_STUDY_COMPLETE_STATUS.FINISHED;
else if (record.CourseId != null)
{
var course = await Db.Queryable<Ghre_Course>().Where(x => x.Id == record.CourseId).FirstAsync();
if (course != null)
{
if (course.ExamPaperId.IsNullOrEmpty())
course.ExamPaperId = "[]";
var examPaperIds = JsonHelper.JsonToObj<List<long>>(course.ExamPaperId);
if (!examPaperIds.Any())
record.CompleteStatus = DIC_STUDY_RECORD_STUDY_COMPLETE_STATUS.FINISHED;
}
}
}
record.ReverseI1 = 0;
await Db.Updateable(record)
.UpdateColumns(it => new
{
it.ReverseI1,
it.CompleteStatus
}, true)
.ExecuteCommandAsync();
}
}

@ -35,4 +35,6 @@ public interface IGhre_OpenClassServices : IBaseServices<Ghre_OpenClass, Ghre_Op
Task<ServiceResult<Ghre_OpenClassSchedule1>> QuerySchedule(long Id);
Task<ServiceResult> Attend(long Id, string type);
Task<ServiceResult> Email(long Id);
}

@ -1,7 +1,5 @@
using Tiobon.Core.Common;
using Tiobon.Core.IServices.BASE;
using Tiobon.Core.Model;
using Tiobon.Core.Model.Models;
using Tiobon.Core.Model.ViewModels.Extend;
namespace Tiobon.Core.IServices;
@ -32,4 +30,6 @@ public interface IGhre_StudyRecordServices : IBaseServices<Ghre_StudyRecord, Ghr
Task<ServicePageResult<TeacherClassAnalysis>> QueryTeacherClassAnalysis(QueryBody filter);
Task<ServiceResult> IssueCredit();
Task<ServiceResult> MarkCompleteStatus();
}

@ -6,7 +6,7 @@
*
* Ver
*
*V0.01 2025/4/8 11:44:41 SimonHsiao
*V0.01 2025/4/29 18:06:23 SimonHsiao
*
* Copyright(c) 2025 Tiobon Corporation. All Rights Reserved.
*
@ -232,6 +232,12 @@ public class Ghre_PlanBase
/// </summary>
public int? BuiltIn { get; set; }
/// <summary>
/// 外训机构
/// </summary>
[Display(Name = "OutSideOrg"), Description("外训机构"), MaxLength(256, ErrorMessage = "外训机构 不能超过 256 个字符")]
public string OutSideOrg { get; set; }
public List<int> StaffId { get; set; }
public List<string> Months { get; set; } = new List<string>();
}

@ -6,7 +6,7 @@
*
* Ver
*
*V0.01 2025/4/8 11:44:41 SimonHsiao
*V0.01 2025/4/29 18:06:23 SimonHsiao
*
* Copyright(c) 2025 Tiobon Corporation. All Rights Reserved.
*
@ -232,4 +232,10 @@ public class Ghre_Plan : BasePoco
/// 系统内置
/// </summary>
public int? BuiltIn { get; set; }
/// <summary>
/// 外训机构
/// </summary>
[Display(Name = "OutSideOrg"), Description("外训机构"), MaxLength(256, ErrorMessage = "外训机构 不能超过 256 个字符")]
public string OutSideOrg { get; set; }
}

@ -1,4 +1,6 @@
namespace Tiobon.Core.Model;
using static Tiobon.Core.Model.Consts;
namespace Tiobon.Core.Model;
public class Ghre_StudyRecordESS
{
@ -109,6 +111,7 @@ public class Ghre_StudyRecordESS
public string ExamDateString { get; set; }
public string ExamStatus { get; set; }
public string CompleteStatus { get; set; } = DIC_STUDY_RECORD_STUDY_COMPLETE_STATUS.NO_FINISH;
public long? ExamId { get; set; }

@ -1315,15 +1315,8 @@ public class Ghre_ExamRecordServices : BaseServices<Ghre_ExamRecord, Ghre_ExamRe
#region 处理学习完成状态
if (record.IsPass == true)
{
var exam = await Db.Queryable<Ghre_Exam>().Where(x => x.Id == record.ExamId && (x.StudyFinishedRule == DIC_EXAM_STUDY_FINISHED_RULE.NO_STUDY_EXAM_PASS || x.StudyFinishedRule == DIC_EXAM_STUDY_FINISHED_RULE.EXAM_PASS)).FirstAsync();
if (exam != null)
{
studyRecord.CompleteStatus = DIC_STUDY_RECORD_STUDY_COMPLETE_STATUS.FINISHED;
await Db.Updateable(studyRecord).UpdateColumns(it => new { it.CompleteStatus }, true)
.ExecuteCommandAsync();
}
}
await ExamHelper.MarkCompleteStatusAsync(Db, studyRecord);
#endregion
_logger.LogInformation($"【DealPass:{studyRecordId}】2");

@ -1,4 +1,5 @@
using MongoDB.Driver.Linq;
using System.Collections.Generic;
namespace Tiobon.Core.Services;
@ -9,12 +10,14 @@ public class Ghre_OpenClassServices : BaseServices<Ghre_OpenClass, Ghre_OpenClas
{
private readonly IGhre_OpenClassStaffServices _ghre_OpenClassStaffServices;
private readonly IGhre_OpenClassFeeServices _ghre_OpenClassFeeServices;
private readonly IGhre_StaffGroupServices _ghre_StaffGroupServices;
private readonly IGhre_OpenClassScheduleServices _ghre_OpenClassScheduleServices;
private readonly IBaseRepository<Ghre_OpenClass> _dal;
public Ghre_OpenClassServices(ICaching caching,
IBaseRepository<Ghre_OpenClass> dal,
IGhre_OpenClassStaffServices ghre_OpenClassStaffServices,
IGhre_OpenClassFeeServices ghre_OpenClassFeeServices,
IGhre_StaffGroupServices ghre_StaffGroupServices,
IGhre_OpenClassScheduleServices ghre_OpenClassScheduleServices)
{
this._dal = dal;
@ -23,6 +26,7 @@ public class Ghre_OpenClassServices : BaseServices<Ghre_OpenClass, Ghre_OpenClas
_ghre_OpenClassStaffServices = ghre_OpenClassStaffServices;
_ghre_OpenClassFeeServices = ghre_OpenClassFeeServices;
_ghre_OpenClassScheduleServices = ghre_OpenClassScheduleServices;
_ghre_StaffGroupServices = ghre_StaffGroupServices;
}
public override async Task<ServicePageResult<Ghre_OpenClassDto>> QueryFilterPage(QueryBody filter, string condition, bool? IsEnable = true)
@ -117,6 +121,7 @@ public class Ghre_OpenClassServices : BaseServices<Ghre_OpenClass, Ghre_OpenClas
prefixTemp = prefixTemp + "K";
entity.OpenClassNo = await GenerateContinuousSequence("Ghre_OpenClass", "OpenClassNo", prefixTemp, prefixTemp.Length + 4, 4);
var result = await base.Add(entity);
if (entity.Schedules != null && entity.Schedules.Any())
@ -224,7 +229,25 @@ public class Ghre_OpenClassServices : BaseServices<Ghre_OpenClass, Ghre_OpenClas
public async Task<ServiceResult> InsertStaff(long Id, List<int> staffIds)
{
var staffIds1 = await Db.Queryable<Ghre_OpenClassStaff>().Where(x => x.OpenClassId == Id).Select(s => s.StaffId).ToListAsync();
var entity = await base.QueryById(Id);
var stafffIds = new List<int>();
if (entity.StaffGroupId.IsNotEmptyOrNull())
{
var staffGroups = await _ghre_StaffGroupServices.QueryStaff(entity.StaffGroupId.Value, new QueryBody(), "", true);
stafffIds = staffGroups.result.DT_TableDataT1.Select(x => x.StaffID).ToList();
}
var staffIds1 = await Db.Queryable<Ghre_OpenClassStaff>().Where(x => x.OpenClassId == Id && x.StaffId != null).Select(s => s.StaffId.Value).ToListAsync();
stafffIds.AddRange(staffIds1);
stafffIds.AddRange(staffIds);
stafffIds = stafffIds.Distinct().ToList();
if (stafffIds.Count > entity.StudentCount)
throw new Exception($"学员人数上限是:{entity.StudentCount}!");
var inserts = staffIds.Where(x => !staffIds1.Contains(x))
.Select(x => new InsertGhre_OpenClassStaffInput()
{
@ -646,4 +669,87 @@ WHERE A.OpenClassId = '{Id}' AND A.IsEnable = 1";
return ServiceResult.OprateSuccess("签到成功!");
}
#endregion
#region 邮件
/// <summary>
/// 邮件
/// </summary>
/// <param name="Id">开班ID</param>
/// <returns></returns>
public async Task<ServiceResult> Email(long Id)
{
var entity = await base.QueryById(Id);
var stafffIds = new List<int>();
if (entity.StaffGroupId.IsNotEmptyOrNull())
{
var staffGroups = await _ghre_StaffGroupServices.QueryStaff(entity.StaffGroupId.Value, new QueryBody(), "", true);
stafffIds = staffGroups.result.DT_TableDataT1.Select(x => x.StaffID).ToList();
}
var staffIds1 = await Db.Queryable<Ghre_OpenClassStaff>().Where(x => x.OpenClassId == Id && x.StaffId != null).Select(s => s.StaffId.Value).ToListAsync();
stafffIds.AddRange(staffIds1);
stafffIds = stafffIds.Distinct().ToList();
var staffs = await Db.Queryable<Ghra_Staff>().Where(x => stafffIds.Contains(x.StaffID) && !string.IsNullOrEmpty(x.Email)).Select(x => new { x.StaffID, x.Email }).ToListAsync();
var courseName = await Db.Ado.GetStringAsync($"select CourseName from Ghre_CourseScene_V where id='{entity.LinkId}'");
var content = entity.NoticeContent + " </br>"
+ $"开班编号: {entity.OpenClassNo}</br>"
+ $"开班名称: {entity.OpenClassName}</br>"
+ $"课程名称: {courseName}</br>"
+ $"开班起止日期: {DateTimeHelper.ConvertToMiniuteString(entity.StartTime)}~{DateTimeHelper.ConvertToMiniuteString(entity.EndTime)}</br>"
+ $"报名起止日期: {DateTimeHelper.ConvertToMiniuteString(entity.RegisterStartTime)}~{DateTimeHelper.ConvertToMiniuteString(entity.RegisterStartTime)}</br>"
+ $"考试起止日期: {DateTimeHelper.ConvertToMiniuteString(entity.ExamStartTime)}~{DateTimeHelper.ConvertToMiniuteString(entity.ExamStartTime)}</br>";
for (int i = 0; i < staffs.Count; i++)
{
#region 发送邮件
var mailOutbox = new Ghrs_MailOutbox();
mailOutbox.TOMail = staffs[i].Email;
mailOutbox.MailTitle = "开班通知";
mailOutbox.MailBody = content;
mailOutbox.MailPriority = 1;
mailOutbox.ScheduleTime = DateTime.Now;
mailOutbox.IsEnable = 1;
mailOutbox.SortNo = 1;
mailOutbox.CompanyID = 0;
mailOutbox.IsDefault = 0;
mailOutbox.CreateProg = "OpenClass";
var id1 = await Db.Insertable(mailOutbox).ExecuteReturnIdentityAsync();
#endregion
}
var teacher = await Db.Queryable<Ghre_Teacher>().Where(x => x.Id == entity.TeacherId).FirstAsync();
if (teacher != null && teacher.Email.IsNotEmptyOrNull())
{
content = entity.TeacherNoticeContent + " </br>"
+ $"开班编号: {entity.OpenClassNo}</br>"
+ $"开班名称: {entity.OpenClassName}</br>"
+ $"课程名称: {courseName}</br>"
+ $"开班起止日期: {DateTimeHelper.ConvertToMiniuteString(entity.StartTime)}~{DateTimeHelper.ConvertToMiniuteString(entity.EndTime)}</br>"
+ $"报名起止日期: {DateTimeHelper.ConvertToMiniuteString(entity.RegisterStartTime)}~{DateTimeHelper.ConvertToMiniuteString(entity.RegisterStartTime)}</br>"
+ $"考试起止日期: {DateTimeHelper.ConvertToMiniuteString(entity.ExamStartTime)}~{DateTimeHelper.ConvertToMiniuteString(entity.ExamStartTime)}</br>";
#region 发送邮件
var mailOutbox = new Ghrs_MailOutbox();
mailOutbox.TOMail = teacher.Email;
mailOutbox.MailTitle = "开班通知";
mailOutbox.MailBody = content;
mailOutbox.MailPriority = 1;
mailOutbox.ScheduleTime = DateTime.Now;
mailOutbox.IsEnable = 1;
mailOutbox.SortNo = 1;
mailOutbox.CompanyID = 0;
mailOutbox.IsDefault = 0;
mailOutbox.CreateProg = "OpenClass";
await Db.Insertable(mailOutbox).ExecuteReturnIdentityAsync();
#endregion
}
return ServiceResult.OprateSuccess("发送成功!");
}
#endregion
}

@ -846,7 +846,7 @@ public class Ghre_StudyRecordServices : BaseServices<Ghre_StudyRecord, Ghre_Stud
entity.SearchFields.Add(new CoursePublicSearchField()
{
label = "学习状态",
field = "StudyStatus",
field = "CompleteStatus",
elementType = "ApiSelect",
dataSource = "TBParaDetail_Train_TrainingStudyStatus",
editable = true,
@ -920,7 +920,7 @@ public class Ghre_StudyRecordServices : BaseServices<Ghre_StudyRecord, Ghre_Stud
A.ExamDateType,
A.AfterHowLong,
A.StudyProgress,
A.ExamId,A.ExamStatus,A.CoursePublishTime,A.IsRequireStudy
A.ExamId,A.ExamStatus,A.CoursePublishTime,A.IsRequireStudy,A.CompleteStatus
FROM Ghre_StudyRecord_V A";
string conditions = $" WHERE UserId={App.User.ID} ";
@ -1811,18 +1811,7 @@ WHERE A.Id = '{id}'";
if (studyProgress == 100)
{
studyStatus = DIC_STUDY_RECORD_STUDY_STATUS.HAS_FINISH;
if (completeStatus == DIC_STUDY_RECORD_STUDY_COMPLETE_STATUS.NO_FINISH)
if (record.ExamId.IsNullOrEmpty())
{
if (record.CourseSceneId.IsNotEmptyOrNull() || (record.CourseId != null && await Db.Queryable<Ghre_Course>().AnyAsync(x => x.Id == record.CourseId && x.ExamPaperId == null)))
completeStatus = DIC_STUDY_RECORD_STUDY_COMPLETE_STATUS.FINISHED;
}
else
{
if (await Db.Queryable<Ghre_Exam>().AnyAsync(x => x.Id == record.ExamId && x.StudyFinishedRule == DIC_EXAM_STUDY_FINISHED_RULE.STUDY_FINISHED))
completeStatus = DIC_STUDY_RECORD_STUDY_COMPLETE_STATUS.FINISHED;
}
await ExamHelper.MarkCompleteStatusAsync(Db, record);
}
var studyProgress1 = studyProgress.ObjToInt();
@ -1833,7 +1822,6 @@ WHERE A.Id = '{id}'";
StudyProgress = studyProgress1,
StudyStatus = studyStatus,
StandardDuration = mins,
CompleteStatus = completeStatus,
ReverseI1 = 1
})
.Where(it => it.Id == studyRecordId)
@ -2078,8 +2066,6 @@ ORDER BY {filter.orderBy}";
}
#endregion
#region 发放学分
/// <summary>
/// 发放学分
@ -2192,4 +2178,30 @@ ORDER BY {filter.orderBy}";
return ServiceResult.OprateSuccess("发放成功!");
}
#endregion
#region 自动刷新完成状态
/// <summary>
/// 自动刷新完成状态
/// </summary>
/// <returns></returns>
public async Task<ServiceResult> MarkCompleteStatus()
{
var now = DateTime.Now;
//抓取当天提交考试的数据
var records = await Db.Queryable<Ghre_StudyRecord>()
.Where(x => x.ReverseI1 == 1)
.ToListAsync();
_logger.LogInformation($"【自动刷新完成状态】查询到{records.Count}条考试数据");
if (!records.Any())
return ServiceResult.OprateSuccess("自动刷新完成状态!");
for (int i = 0; i < records.Count; i++)
{
await ExamHelper.MarkCompleteStatusAsync(Db, records[i]);
}
return ServiceResult.OprateSuccess("自动刷新完成状态!");
}
#endregion
}

@ -0,0 +1,37 @@
using Microsoft.Extensions.Logging;
/// <summary>
/// 这里要注意下,命名空间和程序集是一样的,不然反射不到(任务类要去JobSetup添加注入)
/// </summary>
namespace Tiobon.Core.Tasks;
public class Job_AutoMarkCompleteStatus_Quartz : JobBase, IJob
{
private readonly ILogger<Job_URL_Quartz> _logger;
private readonly IGhre_StudyRecordServices _services;
public Job_AutoMarkCompleteStatus_Quartz(ILogger<Job_URL_Quartz> logger,
ITasksQzServices tasksQzServices,
ITasksLogServices tasksLogServices,
IGhre_StudyRecordServices services)
: base(tasksQzServices, tasksLogServices)
{
_tasksQzServices = tasksQzServices;
_logger = logger;
_services = services;
}
public async Task Execute(IJobExecutionContext context)
{
// 可以直接获取 JobDetail 的值
var jobKey = context.JobDetail.Key;
var jobId = jobKey.Name;
var executeLog = await ExecuteJob(context, async () => await Run(context, jobId.ObjToInt()));
}
public async Task Run(IJobExecutionContext context, int jobid)
{
if (jobid > 0)
await _services.MarkCompleteStatus();
}
}

@ -6855,6 +6855,11 @@
系统内置
</summary>
</member>
<member name="P:Tiobon.Core.Model.Models.Ghre_PlanBase.OutSideOrg">
<summary>
外训机构
</summary>
</member>
<member name="T:Tiobon.Core.Model.Models.Ghre_QuestionBase">
<summary>
题目 (Dto.Base)
@ -25472,6 +25477,11 @@
系统内置
</summary>
</member>
<member name="P:Tiobon.Core.Model.Models.Ghre_Plan.OutSideOrg">
<summary>
外训机构
</summary>
</member>
<member name="T:Tiobon.Core.Model.Models.Ghre_Question">
<summary>
题目 (Model)

@ -1260,6 +1260,13 @@
<param name="Id">开班ID</param>
<returns></returns>
</member>
<member name="M:Tiobon.Core.Api.Controllers.Ghre_OpenClassController.Email(System.Int64)">
<summary>
邮件
</summary>
<param name="Id">开班ID</param>
<returns></returns>
</member>
<member name="T:Tiobon.Core.Api.Controllers.Ghre_OpenClassFeeController">
<summary>
开班费用(Controller)

Loading…
Cancel
Save