From d42a18c64c111f8a6911435e595bf5d50744f8c4 Mon Sep 17 00:00:00 2001 From: tanglong <842690096@qq.com> Date: Mon, 7 Jul 2025 14:56:38 +0800 Subject: [PATCH] aiapi --- VOL.Ai/IServices/IAiAppService.cs | 2 +- VOL.Ai/Services/AiAppService.cs | 218 +++++++++++------- VOL.Core/Utilities/ALiYunFace.cs | 12 +- VOL.Model/Ai/Request/Ai_RankingListRequest.cs | 20 +- VOL.Model/Ai/Response/Ai_RankingListDto.cs | 11 +- 5 files changed, 176 insertions(+), 87 deletions(-) diff --git a/VOL.Ai/IServices/IAiAppService.cs b/VOL.Ai/IServices/IAiAppService.cs index 58df0e8..3e22cb8 100644 --- a/VOL.Ai/IServices/IAiAppService.cs +++ b/VOL.Ai/IServices/IAiAppService.cs @@ -163,7 +163,7 @@ namespace VOL.Ai.IServices /// /// 心率成绩上传 /// - void HeartRateResultUpload(AddHeartRateResultUploadRequest paramDto); + Task HeartRateResultUpload(AddHeartRateResultUploadRequest paramDto); /// /// 新增课堂记录 diff --git a/VOL.Ai/Services/AiAppService.cs b/VOL.Ai/Services/AiAppService.cs index 3c6a9c8..f89a39a 100644 --- a/VOL.Ai/Services/AiAppService.cs +++ b/VOL.Ai/Services/AiAppService.cs @@ -114,7 +114,7 @@ namespace VOL.Ai.Services }).FirstOrDefaultAsync(); if (res == null) - throw new ArgumentNullException(nameof(res)); + return new Ai_SchoolDto(); var gIds = await _studentRepository.DbContext.Set().Where(x => x.SchoolCode == res.SchoolCode).Select(x => x.GradeId).ToListAsync(); @@ -247,71 +247,79 @@ namespace VOL.Ai.Services public async Task StudentFace(GetFaceParam paramDto) { - var body = await ALiYunFace.SearchFace(paramDto.Base64); + var faces = await ALiYunFace.SearchFace(paramDto.Base64, false); - if (body != null && body.Confidence >= 72.62) + foreach (var body in faces) { - var student = await (from s in _studentRepository.FindAsIQueryable(x => x.SchoolCode == paramDto.SchoolCode && x.StudentNo == body.EntityId) - join c in _studentRepository.DbContext.Set() on s.ClassId equals c.Id - select new Ai_StudentFaceInfo - { - ClassId = c.Id, - ClassName = c.ClassName, - Age = s.Age, - Sex = s.Sex, - StudentName = s.StudentName, - StudentCode = s.StudentNo, - GradeId = c.GradeId, - GradeName = c.GradeName, - Photo = s.Photo - }).FirstOrDefaultAsync(); + if (body != null && body.Confidence >= 72.62) + { + var student = await (from s in _studentRepository.FindAsIQueryable(x => x.SchoolCode == paramDto.SchoolCode && x.StudentNo == body.EntityId) + join c in _studentRepository.DbContext.Set() on s.ClassId equals c.Id + select new Ai_StudentFaceInfo + { + ClassId = c.Id, + ClassName = c.ClassName, + Age = s.Age, + Sex = s.Sex, + StudentName = s.StudentName, + StudentCode = s.StudentNo, + GradeId = c.GradeId, + GradeName = c.GradeName, + Photo = s.Photo + }).FirstOrDefaultAsync(); + + if (student == null) + throw new Exception("未查询到学生信息"); - if (student != null) return student; + } } - throw new Exception("未查询到学生信息"); ; + throw new Exception("未查询到学生信息"); } public async Task TeacherFace(GetFaceParam paramDto) { - var body = await ALiYunFace.SearchFace(paramDto.Base64, false); + var faces = await ALiYunFace.SearchFace(paramDto.Base64, false); - if (body != null && body.Confidence >= 72.62) + foreach (var body in faces) { - var teacher = await _teacherRepository.FindAsIQueryable(x => x.SchoolCode == paramDto.SchoolCode && x.TeacherStatus != TeacherStatus.Depart && x.TeacherPhoneNo == body.EntityId) - .Select(x => - new Ai_TeacherFaceInfo() - { - Id = x.Id, - Age = x.Age, - //SchoolCode = x.SchoolCode, - Sex = x.Sex, - Phone = x.TeacherPhoneNo, - TeacherName = x.TeacherName, - Photo = x.TeacherPhoto, - }).FirstOrDefaultAsync(); + if (body != null && body.Confidence >= 72.62) + { + var teacher = await _teacherRepository.FindAsIQueryable(x => x.SchoolCode == paramDto.SchoolCode && x.TeacherStatus != TeacherStatus.Depart && x.TeacherPhoneNo == body.EntityId) + .Select(x => + new Ai_TeacherFaceInfo() + { + Id = x.Id, + Age = x.Age, + //SchoolCode = x.SchoolCode, + Sex = x.Sex, + Phone = x.TeacherPhoneNo, + TeacherName = x.TeacherName, + Photo = x.TeacherPhoto, + }).FirstOrDefaultAsync(); - if (teacher == null) - throw new Exception("未查询到老师信息"); + if (teacher == null) + continue; - var grades = await ( - from t in _studentRepository.DbContext.Set() - join c in _studentRepository.DbContext.Set() on t.ClassId equals c.Id into classGroup - from c in classGroup.DefaultIfEmpty() - where t.TeacherId == teacher.Id && c != null - select new Classes() - { - Id = c.Id, - Name = $"{c.GradeName}-{c.ClassName}", - }).ToListAsync(); + var grades = await ( + from t in _studentRepository.DbContext.Set() + join c in _studentRepository.DbContext.Set() on t.ClassId equals c.Id into classGroup + from c in classGroup.DefaultIfEmpty() + where t.TeacherId == teacher.Id && c != null + select new Classes() + { + Id = c.Id, + Name = $"{c.GradeName}-{c.ClassName}", + }).ToListAsync(); - teacher.GradeAndClassList = grades; + teacher.GradeAndClassList = grades; - return teacher; + return teacher; + } } - throw new Exception("人脸识别失败!"); + throw new Exception("未查询到老师信息"); } public async Task> Ai_StudentList(Ai_StudentListRequest paramDto) @@ -320,6 +328,8 @@ namespace VOL.Ai.Services join c in _studentRepository.DbContext.Set() on s.ClassId equals c.Id join g in _studentRepository.DbContext.Set() on c.GradeId equals g.Id where s.SchoolCode == paramDto.SchoolCode && s.ClassId == paramDto.Id && s.StudentStatus == StudentStatus.Normal + orderby s.OrderNo ascending + select new Ai_StudentListDto() { Code = paramDto.Code, @@ -373,8 +383,7 @@ namespace VOL.Ai.Services select new Ai_ItemTypeModel() { ItemCode = s.Id, - ItemTypeName = s.SpecialName, - ImageUrl = s.ImageUrl + ItemTypeName = s.SpecialName }).ToListAsync(); return list; @@ -386,7 +395,10 @@ namespace VOL.Ai.Services public async Task TeachingItemsDetail(Ai_TeachingItemsRequest paramDto) { if (paramDto == null || paramDto.ItemCode <= 0) - throw new Exception("参数错误"); + { + Console.WriteLine("参数为空,跳过..."); + return new Ai_TeachingItemsDetailModel(); + } var result = await ( from s in _studentRepository.DbContext.Set() @@ -703,7 +715,10 @@ namespace VOL.Ai.Services //await _studentRepository.SaveChangesAsync(); if (paramDto == null) - throw new ArgumentNullException($"参数为空"); + { + Console.WriteLine("参数为空,跳过..."); + return; + } var entity = _mapper.Map(paramDto); @@ -720,7 +735,10 @@ namespace VOL.Ai.Services public async Task SportsTestResultUpload(SportsTestResultUploadRequest paramDto) { if (paramDto == null) - throw new ArgumentNullException($"参数为空"); + { + Console.WriteLine("参数为空,跳过..."); + return; + } var entity = _mapper.Map(paramDto); @@ -737,7 +755,10 @@ namespace VOL.Ai.Services }).FirstOrDefaultAsync(); if (student == null) - throw new ArgumentNullException($"未找到学生信息"); + { + Console.WriteLine("未找到学生信息,跳过..."); + return; + } SemesterDto semesterDto = new SemesterDto(); entity.Year = semesterDto.Year; @@ -752,6 +773,7 @@ namespace VOL.Ai.Services entity.ClassName = student.ClassName; entity.StudentName = student.StudentName; entity.Sex = student.Sex; + entity.IsDisplay = true; var categoryEnum = Tool.GetEnumNameByValue(paramDto.CategoryValue); var healthStandards = await _healthStandardsRepository.FindAsync(x => x.CategoryEnum == categoryEnum); @@ -785,7 +807,10 @@ namespace VOL.Ai.Services public async Task ActivitiestResultUpload(Ai_ActivitiestResultUploadRequest paramDto) { if (paramDto == null) - throw new ArgumentNullException($"参数为空"); + { + Console.WriteLine("参数为空,跳过..."); + return; + } var entity = _mapper.Map(paramDto); @@ -806,7 +831,10 @@ namespace VOL.Ai.Services public async Task LevelExamResultUpload(LevelExamDataUploadRequest paramDto) { if (paramDto == null) - throw new ArgumentNullException($"参数为空"); + { + Console.WriteLine("参数为空,跳过..."); + return; + } var entity = _mapper.Map(paramDto); @@ -826,7 +854,11 @@ namespace VOL.Ai.Services }).FirstOrDefaultAsync(); if (student == null) - throw new ArgumentNullException($"未找到学生信息"); + { + Console.WriteLine("未找到学生信息,跳过..."); + return; + } + entity.ScoreTime = paramDto.StartTime; entity.StartTime = paramDto.StartTime; @@ -837,6 +869,7 @@ namespace VOL.Ai.Services entity.ClassName = student.ClassName; entity.StudentName = student.StudentName; entity.Sex = student.Sex; + entity.IsDisplay = true; await _levelExamDataRepository.AddAsync(entity); await _levelExamDataRepository.SaveChangesAsync(); @@ -848,16 +881,22 @@ namespace VOL.Ai.Services /// /// /// - public async void HeartRateResultUpload(AddHeartRateResultUploadRequest paramDto) + public async Task HeartRateResultUpload(AddHeartRateResultUploadRequest paramDto) { if (paramDto == null || paramDto.Datas == null || paramDto.Datas.Count == 0) - throw new ArgumentNullException($"参数为空"); + { + Console.WriteLine("参数为空或数据为空,跳过处理。"); + return; + } var heartRateDatas = _mapper.Map>(paramDto.Datas); + heartRateDatas = heartRateDatas.Where(data => data.Value != 0).ToList(); var classIds = paramDto.Datas.Select(x => x.ClassId).ToList(); var classList = await _classRepository.FindAsync(x => x.SchoolCode == paramDto.SchoolCode && classIds.Contains(x.Id)); + var timeNow = DateTime.Now; + heartRateDatas.ForEach(heartRateData => { var classInfo = classList.Where(x => x.Id == heartRateData.ClassId).First(); @@ -868,11 +907,13 @@ namespace VOL.Ai.Services heartRateData.TeacherId = paramDto.TeacherId; heartRateData.GradeId = classInfo.GradeId; heartRateData.GradeName = classInfo.GradeName; - heartRateData.ScoreTime = DateTime.Now; - - - HeartRateQueueData.Add(heartRateData); + heartRateData.ScoreTime = timeNow; + heartRateData.IsDisplay = true; + //HeartRateQueueData.Add(heartRateData); }); + + await _heartRateDataRepository.AddRangeAsync(heartRateDatas); + await _heartRateDataRepository.SaveChangesAsync(); } /// @@ -884,7 +925,10 @@ namespace VOL.Ai.Services public async Task FastJumpRopeResultUpload(AddFastJumpRopeResultUploadRequest paramDto) { if (paramDto == null || paramDto.Datas == null || paramDto.Datas.Count == 0) - throw new ArgumentNullException($"参数为空"); + { + Console.WriteLine("参数为空或数据为空,跳过处理。"); + return; + } var fastJumpRopeDatas = _mapper.Map>(paramDto.Datas); @@ -898,6 +942,7 @@ namespace VOL.Ai.Services data.Code = paramDto.Code; data.SchoolCode = paramDto.SchoolCode; data.ClassRoomRecordId = paramDto.ClassRoomRecordId; + data.GroupId = paramDto.GroupId; data.TeacherId = paramDto.TeacherId; data.GradeId = classInfo.GradeId; data.GradeName = classInfo.GradeName; @@ -907,7 +952,6 @@ namespace VOL.Ai.Services data.ModelName = paramDto.ModeType.GetDescription(); data.UniqueId = paramDto.UniqueId; }); - await _fastJumpRopeDataRepository.AddRangeAsync(fastJumpRopeDatas); await _fastJumpRopeDataRepository.SaveChangesAsync(); } @@ -922,16 +966,17 @@ namespace VOL.Ai.Services { var res = new PageDataDto(); - // 查询数据并根据 UniqueId 分组 var groupedQuery = from a in _fastJumpRopeDataRepository.FindAsIQueryable(x => - //x.ClassId == paramDto.ClassId && - x.SchoolCode == paramDto.SchoolCode) + x.SchoolCode == paramDto.SchoolCode && + (paramDto.ClassRoomRecordId == null || paramDto.ClassRoomRecordId <= 0 || x.ClassRoomRecordId == paramDto.ClassRoomRecordId)) group a by a.GroupId into g select new { GroupId = g.Key, - ModelName = g.FirstOrDefault().ModelName, - MotionDuration = g.FirstOrDefault().MotionDuration, + g.FirstOrDefault().MotionDuration, + g.FirstOrDefault().ModeType, + g.FirstOrDefault().ModelName, + //MotionDuration = g.FirstOrDefault().MotionDuration, ScoreTime = g.Max(x => x.ScoreTime), TestItem = Ai_TrainingModuleEnum.FastJumpRope.GetDescription() }; @@ -947,6 +992,7 @@ namespace VOL.Ai.Services .Select(x => new Ai_FastJumpRopeDto { GroupId = x.GroupId, + ModeType = x.ModeType, ModelName = x.ModelName, MotionDuration = x.MotionDuration, ScoreTime = x.ScoreTime, @@ -969,11 +1015,16 @@ namespace VOL.Ai.Services { var res = new PageDataDto(); - // 构建查询 + //var query = _fastJumpRopeDataRepository.FindAsIQueryable(x => + // x.ClassRoomRecordId == paramDto.ClassRoomRecordId && + // x.SchoolCode == paramDto.SchoolCode && + // (paramDto.ModeType != Ai_FastJumpRopeModeEnum.FollowMode || x.GroupId == paramDto.GroupId) + // ); + var query = _fastJumpRopeDataRepository.FindAsIQueryable(x => - x.ClassRoomRecordId == paramDto.ClassRoomRecordId && - x.SchoolCode == paramDto.SchoolCode); + x.ClassRoomRecordId == paramDto.ClassRoomRecordId && + x.SchoolCode == paramDto.SchoolCode && x.GroupId == paramDto.GroupId); // 异步获取数据列表 var rawData = await query.ToListAsync(); @@ -1022,7 +1073,10 @@ namespace VOL.Ai.Services public async Task AddClassRoomRecord(Ai_ClassRoomRecordRequest paramDto) { if (paramDto == null) - throw new ArgumentNullException($"参数为空"); + { + Console.WriteLine("参数为空或数据为空,跳过处理。"); + return new Ai_ClassRoomRecordDto(); + } var entity = _mapper.Map(paramDto); @@ -1032,7 +1086,10 @@ namespace VOL.Ai.Services var classInfos = await _classRepository.FindAsync(x => ids.Contains(x.Id) && x.SchoolCode == paramDto.SchoolCode); var classInfo = classInfos.FirstOrDefault(x => x.Id == paramDto.ClassId); if (classInfo == null) - throw new ArgumentNullException($"班级信息为空"); + { + Console.WriteLine("班级信息数据为空,跳过处理。"); + return new Ai_ClassRoomRecordDto(); + } entity.ClassName = classInfo.ClassName; entity.GradeId = classInfo.GradeId; @@ -1046,7 +1103,10 @@ namespace VOL.Ai.Services { var StuClass = classInfos.First(x => x.Id == student.ClassId); if (StuClass == null) - throw new ArgumentNullException($"班级信息为空"); + { + Console.WriteLine("班级信息数据为空,跳过处理。"); + return new Ai_ClassRoomRecordDto(); + } student.ClassName = StuClass.ClassName; student.GradeId = StuClass.GradeId; @@ -1072,7 +1132,11 @@ namespace VOL.Ai.Services public async Task EndTeaching(EndTeachingRequest paramDto) { if (paramDto == null) - throw new ArgumentNullException($"参数为空"); + { + Console.WriteLine("参数为空,跳过..."); + return; + } + var entity = await _classRoomRecordRepository.FindAsyncFirst(x => x.Id == paramDto.ClassRoomRecordId && x.SchoolCode == paramDto.SchoolCode); diff --git a/VOL.Core/Utilities/ALiYunFace.cs b/VOL.Core/Utilities/ALiYunFace.cs index 9bcbf3e..f4c1145 100644 --- a/VOL.Core/Utilities/ALiYunFace.cs +++ b/VOL.Core/Utilities/ALiYunFace.cs @@ -134,9 +134,9 @@ namespace VOL.Core.Utilities catch (Exception _error) { TeaException error = new TeaException(new Dictionary - { - { "message", _error.Message } - }); + { + { "message", _error.Message } + }); throw new Exception($"系统异常:人脸数据添加失败。可能原因包括图片格式或内容不符合要求。请确保图片为正面人脸清晰无遮挡,分辨率不少于 640x480,大小不超过 2MB。错误详情:{error.Message}"); } @@ -146,7 +146,7 @@ namespace VOL.Core.Utilities /// /// /// - public static async Task SearchFace(string base64, bool isStudent = true) + public static async Task> SearchFace(string base64, bool isStudent = true) { AlibabaCloud.SDK.Facebody20191230.Client client = CreateClient(); try @@ -161,7 +161,7 @@ namespace VOL.Core.Utilities var searchFaceAdvanceRequest = new SearchFaceAdvanceRequest { ImageUrlObject = stream, - Limit = 1, + Limit = 10, DbName = isStudent ? AppSetting.ALiYunFaceDetect.StudeneDb : AppSetting.ALiYunFaceDetect.TeacherDb }; @@ -169,7 +169,7 @@ namespace VOL.Core.Utilities var res = await client.SearchFaceAdvanceAsync(searchFaceAdvanceRequest, runtime); - return res.Body.Data.MatchList.Count > 0 && res.Body.Data.MatchList[0].FaceItems.Count > 0 ? res.Body.Data.MatchList[0].FaceItems[0] : null; + return res.Body.Data.MatchList.Count > 0 && res.Body.Data.MatchList[0].FaceItems.Count > 0 ? res.Body.Data.MatchList[0].FaceItems : null; } } catch (TeaException error) diff --git a/VOL.Model/Ai/Request/Ai_RankingListRequest.cs b/VOL.Model/Ai/Request/Ai_RankingListRequest.cs index 8ea2809..379cb51 100644 --- a/VOL.Model/Ai/Request/Ai_RankingListRequest.cs +++ b/VOL.Model/Ai/Request/Ai_RankingListRequest.cs @@ -48,6 +48,7 @@ namespace VOL.Model.Ai.Request public DateTime? TodayTime { get; set; } } + /// /// Ai速度跳绳成绩排行 /// @@ -64,9 +65,9 @@ namespace VOL.Model.Ai.Request public string SchoolCode { get; set; } /// - /// 班级Id + /// 课堂记录Id /// - //public int ClassId { get; set; } + public int? ClassRoomRecordId { get; set; } } @@ -85,9 +86,24 @@ namespace VOL.Model.Ai.Request /// public string SchoolCode { get; set; } + /// + /// GroupId + /// + public string GroupId { get; set; } + /// /// 课堂记录Id /// public int ClassRoomRecordId { get; set; } + + /// + /// 模式类型 + /// + //public Ai_FastJumpRopeModeEnum ModeType { get; set; } + + /// + ///运动时长/分钟 + /// + //public int? MotionDuration { get; set; } } } diff --git a/VOL.Model/Ai/Response/Ai_RankingListDto.cs b/VOL.Model/Ai/Response/Ai_RankingListDto.cs index 58104f3..46db4d9 100644 --- a/VOL.Model/Ai/Response/Ai_RankingListDto.cs +++ b/VOL.Model/Ai/Response/Ai_RankingListDto.cs @@ -34,12 +34,16 @@ namespace VOL.Model.Ai /// public string StudentNo { get; set; } } - /// /// Ai速度跳绳 /// public class Ai_FastJumpRopeDto { + /// + /// 设备上传成绩时唯一标识 + /// + //public string UniqueId { get; set; } + /// /// GroupId /// @@ -60,6 +64,11 @@ namespace VOL.Model.Ai /// public int? MotionDuration { get; set; } + /// + /// 模式类型 + /// + public Ai_FastJumpRopeModeEnum ModeType { get; set; } + /// /// 模式名称 ///