From 7c340bd5c75050c84ab173ca13618a94ee19e081 Mon Sep 17 00:00:00 2001 From: xiaochanghai Date: Wed, 30 Apr 2025 18:11:47 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AF=BE=E7=A8=8B=E5=9C=BA=E6=99=AF=E7=BB=9F?= =?UTF-8?q?=E8=AE=A1=E5=88=86=E6=9E=90=E6=8E=A5=E5=8F=A3=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Ghre/Ghre_CourseSceneController.cs | 11 + Tiobon.Core.Api/Tiobon.Core.xml | 7 + .../Ghre/IGhre_CourseSceneServices.cs | 6 +- .../Ghre/Ghre_CourseSceneServices.cs | 195 +++++++++++++++++- 4 files changed, 214 insertions(+), 5 deletions(-) diff --git a/Tiobon.Core.Api/Controllers/Ghre/Ghre_CourseSceneController.cs b/Tiobon.Core.Api/Controllers/Ghre/Ghre_CourseSceneController.cs index 3925d71b..3c936784 100644 --- a/Tiobon.Core.Api/Controllers/Ghre/Ghre_CourseSceneController.cs +++ b/Tiobon.Core.Api/Controllers/Ghre/Ghre_CourseSceneController.cs @@ -11,4 +11,15 @@ public class Ghre_CourseSceneController : BaseController + /// 统计 + /// + /// + /// + [Route("QueryStatistic/{id}")] + public async Task QueryStatistic(long id) + { + return await _service.QueryStatistic(id); + } } \ No newline at end of file diff --git a/Tiobon.Core.Api/Tiobon.Core.xml b/Tiobon.Core.Api/Tiobon.Core.xml index b82334ce..5b627a90 100644 --- a/Tiobon.Core.Api/Tiobon.Core.xml +++ b/Tiobon.Core.Api/Tiobon.Core.xml @@ -808,6 +808,13 @@ 课程场景(Controller) + + + 统计 + + + + Ghre_CourseSnap(Controller) diff --git a/Tiobon.Core.IServices/Ghre/IGhre_CourseSceneServices.cs b/Tiobon.Core.IServices/Ghre/IGhre_CourseSceneServices.cs index 09ead8b8..3206eabc 100644 --- a/Tiobon.Core.IServices/Ghre/IGhre_CourseSceneServices.cs +++ b/Tiobon.Core.IServices/Ghre/IGhre_CourseSceneServices.cs @@ -1,11 +1,9 @@ -using Tiobon.Core.IServices.BASE; -using Tiobon.Core.Model.Models; - -namespace Tiobon.Core.IServices; +namespace Tiobon.Core.IServices; /// /// 课程场景(自定义服务接口) /// public interface IGhre_CourseSceneServices : IBaseServices { + Task QueryStatistic(long id); } \ No newline at end of file diff --git a/Tiobon.Core.Services/Ghre/Ghre_CourseSceneServices.cs b/Tiobon.Core.Services/Ghre/Ghre_CourseSceneServices.cs index 6ff3902c..4f90e244 100644 --- a/Tiobon.Core.Services/Ghre/Ghre_CourseSceneServices.cs +++ b/Tiobon.Core.Services/Ghre/Ghre_CourseSceneServices.cs @@ -1,4 +1,6 @@ -namespace Tiobon.Core.Services; +using static Tiobon.Core.Model.Consts; + +namespace Tiobon.Core.Services; /// /// 课程场景 (服务) @@ -250,4 +252,195 @@ public class Ghre_CourseSceneServices : BaseServices.OprateSuccess("导入成功!", data); } #endregion + + + + #region 课程统计 + /// + /// 课程统计 + /// + /// + /// + public async Task QueryStatistic(long id) + { + + dynamic obj = new ExpandoObject(); + dynamic data = new ExpandoObject(); + var entity = await QueryById(id); + + //data.CourseClassName = entity.CourseClassName; + //data.StandardHour = entity.StandardHour; + //data.CreditPoints = entity.CreditPoints; + //data.ManagerStaffName = entity.ManagerStaffName; + //data.InOrOut = entity.InOrOutLabel; + //data.IsOpen = entity.IsOPenLabel; + //data.ValidityPeriod = entity.ValidityPeriod; + //data.CourseSceneName = entity.CourseSceneName; + + //必修人数 + var RequiredCount = await Db.Queryable().Where(x => x.CourseId == id && (x.CourseType == "ManualRequired" || x.CourseType == "Required")).CountAsync(); + data.RequiredCount = RequiredCount; + + //选修人次 + var ElectiveCount = await Db.Queryable().Where(x => x.CourseId == id && (x.CourseType == "ManualElective" || x.CourseType == "Elective")).CountAsync(); + data.ElectiveCount = ElectiveCount; + + var CompleteCount = await Db.Queryable().Where(x => x.CourseId == id && x.CompleteStatus == DIC_STUDY_RECORD_STUDY_COMPLETE_STATUS.FINISHED && (x.CourseType == "ManualElective" || x.CourseType == "Elective" || x.CourseType == "ManualElective" || x.CourseType == "Elective")).CountAsync(); + //完成人数 + data.CompleteCount = CompleteCount; + //开班人数 + var OpenClassCount = await Db.Queryable().Where(x => x.CourseId == id && x.OpenClassId != null).CountAsync(); + data.OpenClassCount = OpenClassCount; + + var studyRecordIds = await Db.Queryable().Where(x => x.CourseId == id).Select(x => x.Id).ToListAsync(); + //总学习时长 + data.TotalStudyDuration = await Db.Queryable().Where(x => x.StudyRecordId != null && studyRecordIds.Contains(x.StudyRecordId.Value)).SumAsync(x => x.StudyDuration); + + var AvgStudyDuration = await Db.Queryable().Where(x => x.StudyRecordId != null && studyRecordIds.Contains(x.StudyRecordId.Value)).GroupBy(x => x.StaffId) + .Select(m => new { m.StaffId, StudyDuration = SqlFunc.AggregateSum(m.StudyDuration) }).ToListAsync(); + //平均学习时长 + data.AvgStudyDuration = AvgStudyDuration.Average(x => x.StudyDuration); + //平均分 + var AvgScore = await Db.Queryable().Where(x => x.StudyRecordId != null && studyRecordIds.Contains(x.StudyRecordId.Value)).AvgAsync(x => x.FinallyScore ?? (x.Score + x.AdjustScore)); + data.AvgScore = AvgScore ?? 0; + + //通过率 + var passPercent = 0; + + if (CompleteCount > 0 && (RequiredCount + ElectiveCount + OpenClassCount) > 0) + passPercent = CompleteCount / (RequiredCount + ElectiveCount + OpenClassCount); + data.PassPercent = passPercent; + + //考试安排次数 + data.ExamScheduleCount = await Db.Queryable().Where(x => x.CourseId == id).CountAsync(); + + //考试人数 + data.ExamCount = await Db.Queryable().Where(x => x.CourseId == id).CountAsync(); + + //考试人次 + data.ExamGroupCount = await Db.Queryable() + .Where(x => x.StudyRecordId != null && studyRecordIds.Contains(x.StudyRecordId.Value)) + .CountAsync(); + + //反馈人数 + data.FeedbackCount = 0; + + #region 课件学习时长 + var courseWareStudyDuration = await Db.Queryable() + .Where(a => a.StudyRecordId != null && studyRecordIds.Contains(a.StudyRecordId.Value)) + + .GroupBy(a => new { a.CourseWareId, a.CourseWareAttachmentId }) + .Select(a => new + { + a.CourseWareId, + a.CourseWareAttachmentId, + StudyDuration = SqlFunc.AggregateSum(a.StudyDuration) + }) + .ToListAsync(); + + var courseWareStudyDurations = new JArray(); + + for (int i = 0; i < courseWareStudyDuration.Count; i++) + { + var courseWare = await Db.Queryable().Where(x => x.Id == courseWareStudyDuration[i].CourseWareId).FirstAsync(); + var courseWareAttachment = await Db.Queryable().Where(x => x.Id == courseWareStudyDuration[i].CourseWareAttachmentId).FirstAsync(); + var item = new JObject + { + new JProperty("CourseWareId", courseWareStudyDuration[i].CourseWareAttachmentId), + new JProperty("CourseWareAttachmentId", courseWareStudyDuration[i].CourseWareAttachmentId), + new JProperty("StudyDuration", courseWareStudyDuration[i].StudyDuration), + new JProperty("CourseWareName", courseWare?.CourseWareNo+courseWare?.CourseWareName+courseWare?.VersionNo+courseWareAttachment.AttachmentName), + }; + courseWareStudyDurations.Add(item); + } + data.CourseWareStudyDurations = courseWareStudyDurations; + #endregion + + #region 课件学习人数占比 + var courseWareStudyCount1 = await Db.Queryable() + .Where(a => a.StudyRecordId != null && studyRecordIds.Contains(a.StudyRecordId.Value)) + .Select(a => new { a.CourseWareAttachmentId, a.StaffId }) + .Distinct().ToListAsync(); + var courseWareStudyCount = courseWareStudyCount1 + .GroupBy(a => a.CourseWareAttachmentId) + .Select(a => new + { + CourseWareAttachmentId = a.Key, + Count = a.Count() + }) + .ToList(); + + var courseWareStudyCounts = new JArray(); + + for (int i = 0; i < courseWareStudyCount.Count; i++) + { + var courseWareAttachment = await Db.Queryable().Where(x => x.Id == courseWareStudyCount[i].CourseWareAttachmentId).FirstAsync(); + var item = new JObject + { + new JProperty("CourseWareAttachmentId", courseWareStudyCount[i].CourseWareAttachmentId), + new JProperty("CourseWareName", courseWareAttachment.AttachmentName), + new JProperty("Count", courseWareStudyCount[i].Count), + }; + courseWareStudyCounts.Add(item); + } + data.CourseWareStudyCounts = courseWareStudyCounts; + #endregion + + #region 关联的考试排行 + var exams = await Db.Queryable() + .LeftJoin((a, b) => a.ExamPaperId == b.Id)//多个条件用&& + .Where(a => a.CourseId == id && a.Status != "Draft") + .Select((a, b) => new + { + a.Id, + a.ExamNo, + a.ExamName, + b.PaperName + }) + .ToListAsync(); + var examRanking = new JArray(); + var examRankings = new JArray(); + + for (int i = 0; i < exams.Count; i++) + { + + var groups = await Db.Queryable().Where(x => x.ExamId == exams[i].Id).CountAsync(); + var examRecordCount = await Db.Queryable().Where(x => x.ExamId == exams[i].Id).CountAsync(); + var examRecordPassCount = await Db.Queryable() + .Where(x => x.ExamId == exams[i].Id && x.IsPass == true && x.IsPass != null) + .CountAsync(); + var examRecordRetakeCount = await Db.Queryable() + .Where(x => x.ExamId == exams[i].Id && x.RetakeTimes > 0 && x.RetakeTimes != null) + .CountAsync(); + + passPercent = 0; + var retakePercent = 0; + + if (examRecordCount > 0) + { + if (examRecordPassCount > 0) passPercent = (examRecordPassCount / examRecordCount) * 100; + if (examRecordRetakeCount > 0) retakePercent = (examRecordRetakeCount / examRecordCount) * 100; + } + + var item = new JObject + { + new JProperty("ExamName", $"{exams[i].ExamName}({exams[i].ExamNo})" ), + new JProperty("PaperName", exams[i].PaperName), + new JProperty("Attempts", groups), + new JProperty("PassPercent", passPercent), + new JProperty("RetakePercent", retakePercent), + //new JProperty("CourseWareName", courseWareAttachment.AttachmentName), + }; + examRankings.Add(item); + } + data.ExamRankings = examRankings; + #endregion + + obj.Data = data; + obj.Success = true; + obj.Status = 200; + obj.Message = "查询成功!"; + return obj; + } + #endregion } \ No newline at end of file