diff --git a/WeChatApplet/Controllers/FrameworkController.cs b/WeChatApplet/Controllers/FrameworkController.cs index ccda551..46a9d41 100644 --- a/WeChatApplet/Controllers/FrameworkController.cs +++ b/WeChatApplet/Controllers/FrameworkController.cs @@ -24,12 +24,11 @@ namespace YD_WeChatApplet.Api.Controllers /// Ai一体机扫描登录 /// /// - /// /// [HttpPost("ScanCodeLogin")] - public async Task ScanCodeLogin(string code, string teacherNo) + public async Task ScanCodeLogin(string code) { - return await _frameworkService.ScanCodeLogin(code, teacherNo); + return await _frameworkService.ScanCodeLogin(code); } } } \ No newline at end of file diff --git a/WeChatApplet/Services/Impl/FrameworkService.cs b/WeChatApplet/Services/Impl/FrameworkService.cs index d586e6b..8a839e5 100644 --- a/WeChatApplet/Services/Impl/FrameworkService.cs +++ b/WeChatApplet/Services/Impl/FrameworkService.cs @@ -23,9 +23,8 @@ namespace YD_WeChatApplet.Api.Services.Impl /// Ai一体机扫描登录 /// /// - /// /// - public async Task ScanCodeLogin(string code,string teacherNo) + public async Task ScanCodeLogin(string code) { var schoolCode = UserLoginContext.Current.SchoolCode; //var teacherId = UserLoginContext.Current.UserId; @@ -43,7 +42,7 @@ namespace YD_WeChatApplet.Api.Services.Impl Code = code, SchoolCode = schoolCode, TeacherId = 0, - TeacherPhoneNo = UserLoginContext.Current.PhoneNo, + TeacherPhoneNo = UserLoginContext.Current.UserNo, CreateDate = DateTime.Now }; diff --git a/WeChatApplet/Services/Impl/HomeWorkService.cs b/WeChatApplet/Services/Impl/HomeWorkService.cs index 224f655..4e2edf5 100644 --- a/WeChatApplet/Services/Impl/HomeWorkService.cs +++ b/WeChatApplet/Services/Impl/HomeWorkService.cs @@ -61,6 +61,7 @@ namespace YD_WeChatApplet.Api.Services.Impl var homeWorkEntity = _mapper.Map(paramDto); homeWorkEntity.SchoolCode = UserLoginContext.Current.SchoolCode; homeWorkEntity.TeacherId = UserLoginContext.Current.UserId; + homeWorkEntity.TeacherNo = UserLoginContext.Current.UserNo; homeWorkEntity.TeacherName = UserLoginContext.Current.UserName; homeWorkEntity.WorkStatus = 1; homeWorkEntity.CreateTime = DateTime.Now; @@ -80,6 +81,7 @@ namespace YD_WeChatApplet.Api.Services.Impl var homeWorkEntity = _mapper.Map(paramDto); homeWorkEntity.SchoolCode = UserLoginContext.Current.SchoolCode; homeWorkEntity.TeacherId = UserLoginContext.Current.UserId; + homeWorkEntity.TeacherNo = UserLoginContext.Current.UserNo; homeWorkEntity.TeacherName = UserLoginContext.Current.UserTrueName; //homeWorkEntity.TeacherName = UserLoginContext.Current.UserName; homeWorkEntity.WorkStatus = 1; diff --git a/WeChatApplet/Services/Impl/JingShiTiJiaoService.cs b/WeChatApplet/Services/Impl/JingShiTiJiaoService.cs index 5d2e5a3..7b96b79 100644 --- a/WeChatApplet/Services/Impl/JingShiTiJiaoService.cs +++ b/WeChatApplet/Services/Impl/JingShiTiJiaoService.cs @@ -148,15 +148,58 @@ namespace YD_WeChatApplet.Api.Services.Impl { User_Id = -1, UserName = data.Data.StudentName, - Role_Id = 2, + Role_Id = 3, PhoneNo = data.Data.TeacherNo, SchoolCode = AppSettings.JingShiTiJiao.SchoolCode, UserNo = data.Data.StudentNo }); data.Data.Token = token; + + return data.Data; } + + return res; } + + /// + /// 上传成绩数据 + /// + /// + /// + /// + public async Task PushSportsData(List list) + { + long timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); + string nonce = SaTokenSignHelper.RandomString(); + + var paramMap = new Dictionary + { + { "channel", AppSettings.JingShiTiJiao.Channel }, + { "timestamp", timestamp }, + { "nonce", nonce } + }; + + string jsonBody = JsonConvert.SerializeObject(list); + + // ⭐ POST JSON 的签名 + string queryStr = SaTokenSignHelper.BuildPostJsonQueryString( + paramMap, + AppSettings.JingShiTiJiao.SecretKey, + jsonBody); + + string url = $"{AppSettings.JingShiTiJiao.BaseUrl}/api/sports/data/push?{queryStr}"; + + using var client = new HttpClient(); + var content = new StringContent(jsonBody, Encoding.UTF8, "application/json"); + + var response = await client.PostAsync(url, content); + string result = await response.Content.ReadAsStringAsync(); + + var res = JsonConvert.DeserializeObject>(result); + + return res != null && res.Code == 0; + } } } diff --git a/WeChatApplet/Services/Impl/PatriarchService.cs b/WeChatApplet/Services/Impl/PatriarchService.cs index 22a1f4e..69a2630 100644 --- a/WeChatApplet/Services/Impl/PatriarchService.cs +++ b/WeChatApplet/Services/Impl/PatriarchService.cs @@ -1,10 +1,13 @@ using AutoMapper; using Microsoft.EntityFrameworkCore; +using Newtonsoft.Json; using YD_WeChatApplet.Api.Entitys; +using YD_WeChatApplet.Api.Services.Interface; using YD_WeChatApplet.Api.SmartSportsEntitys; using YD_WeChatApplet.Api.Utilities; using YD_WeChatApplet.Commons.Dto; using YD_WeChatApplet.Commons.Dto.HomeWork; +using YD_WeChatApplet.Commons.Dto.JingShiTiJiao; using YD_WeChatApplet.Commons.Dto.Patriarch; using YD_WeChatApplet.Commons.Dto.Resource; using YD_WeChatApplet.Commons.Dto.School; @@ -24,11 +27,15 @@ namespace YD_WeChatApplet.Api.Services.Impl public UserContext _userContext; public SmartSportsContext _sportsContext; private readonly IMapper _mapper; - public PatriarchService(UserContext userContext, SmartSportsContext sportsContext, IMapper mapper) + private readonly ILogger _logger; + private readonly IJingShiTiJiaoService _jingShiTiJiaoService; + public PatriarchService(UserContext userContext, SmartSportsContext sportsContext, IMapper mapper, ILogger logger, IJingShiTiJiaoService jingShiTiJiaoService) { _userContext = userContext; _sportsContext = sportsContext; _mapper = mapper; + _logger = logger; + _jingShiTiJiaoService = jingShiTiJiaoService; } /// @@ -66,11 +73,14 @@ namespace YD_WeChatApplet.Api.Services.Impl var student = await _sportsContext.HomeWorkStudents.FirstAsync(x => x.HomeWorkId == dto.HomeWorkId && x.StudentNo == UserLoginContext.Current.UserNo); student.WorkStatus = entity.Status; - if (entity.RoleId == 3) - { - entity.StudentNo = UserLoginContext.Current.UserNo; - entity.StudentName = UserLoginContext.Current.UserName; - } + //if (entity.RoleId == 3) + //{ + // entity.StudentNo = UserLoginContext.Current.UserNo; + // entity.StudentName = UserLoginContext.Current.UserName; + //} + + entity.StudentNo = UserLoginContext.Current.UserNo; + entity.StudentName = UserLoginContext.Current.UserName; student.Value = dto.WorkModeType == 1 ? dto.Amount : dto.Duration; _sportsContext.HomeWorkStudents.Update(student); @@ -78,6 +88,44 @@ namespace YD_WeChatApplet.Api.Services.Impl await _userContext.AddAsync(entity); await _userContext.SaveChangesAsync(); + + _ = Task.Run(async () => + { + try + { + var list = new List + { + new SportsDataPushDto + { + StudentNo = entity.StudentNo, + SportsItem = AppSettings.JingShiTiJiao.SportsItem, + SportsDate = entity.CreateTime.ToString("yyyy-MM-dd"), + SportsService = AppSettings.JingShiTiJiao.Channel, + SportsScene = "homework", + SportsDetail = JsonConvert.SerializeObject(dto) + } + }; + + var res = await _jingShiTiJiaoService.PushSportsData(list); + + if (res) + { + _logger.LogInformation($"数据同步成功,{JsonConvert.SerializeObject(list)}"); + } + else + { + _logger.LogError($"数据同步失败,{JsonConvert.SerializeObject(list)}"); + } + } + catch (Exception ex) + { + // ❗ 只记录日志,绝不抛出 + _logger.LogError(ex, + "运动数据上传失败,StudentNo={StudentNo}, Id={Id}", + entity.StudentNo, + entity.Id); + } + }); } /// diff --git a/WeChatApplet/Services/Interface/IFrameworkService.cs b/WeChatApplet/Services/Interface/IFrameworkService.cs index affb399..42a772b 100644 --- a/WeChatApplet/Services/Interface/IFrameworkService.cs +++ b/WeChatApplet/Services/Interface/IFrameworkService.cs @@ -9,8 +9,7 @@ /// Ai一体机扫描登录 /// /// - /// /// - Task ScanCodeLogin(string code, string teacherNo); + Task ScanCodeLogin(string code); } } diff --git a/WeChatApplet/Services/Interface/IJingShiTiJiaoService.cs b/WeChatApplet/Services/Interface/IJingShiTiJiaoService.cs index 0fb805e..1fd9cac 100644 --- a/WeChatApplet/Services/Interface/IJingShiTiJiaoService.cs +++ b/WeChatApplet/Services/Interface/IJingShiTiJiaoService.cs @@ -26,5 +26,12 @@ namespace YD_WeChatApplet.Api.Services.Interface /// /// Task GetStudentInfo(string stuNo); + + /// + /// 上传数据 + /// + /// + /// + Task PushSportsData(List list); } } diff --git a/WeChatApplet/Utilities/AppSettings.cs b/WeChatApplet/Utilities/AppSettings.cs index d8eae4b..a6b8a8e 100644 --- a/WeChatApplet/Utilities/AppSettings.cs +++ b/WeChatApplet/Utilities/AppSettings.cs @@ -116,5 +116,6 @@ public string SecretKey { get; set; } public string BaseUrl { get; set; } public string SchoolCode { get; set; } + public string SportsItem { get; set; } } } diff --git a/WeChatApplet/appsettings.json b/WeChatApplet/appsettings.json index 95cbbf5..f037599 100644 --- a/WeChatApplet/appsettings.json +++ b/WeChatApplet/appsettings.json @@ -71,6 +71,7 @@ "Channel": "sk-yuedong", "SecretKey": "JSTJ-kGfs6J7bkgdxr9mz", "BaseUrl": "https://api-test.aitibao.com", - "SchoolCode": "202512240056" + "SchoolCode": "202512240056", + "SportsItem": "JS010000" } } diff --git a/YD_WeChatApplet.Commons/Dto/JingShiTiJiao/SportsDataPushDto.cs b/YD_WeChatApplet.Commons/Dto/JingShiTiJiao/SportsDataPushDto.cs new file mode 100644 index 0000000..5ecd0d3 --- /dev/null +++ b/YD_WeChatApplet.Commons/Dto/JingShiTiJiao/SportsDataPushDto.cs @@ -0,0 +1,30 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace YD_WeChatApplet.Commons.Dto.JingShiTiJiao +{ + public class SportsDataPushDto + { + [JsonProperty("studentNo")] + public string StudentNo { get; set; } + + [JsonProperty("sportsItem")] + public string SportsItem { get; set; } + + [JsonProperty("sportsDate")] + public string SportsDate { get; set; } // yyyy-MM-dd + + [JsonProperty("sportsService")] + public string SportsService { get; set; } // channel + + [JsonProperty("sportsScene")] + public string SportsScene { get; set; } + + [JsonProperty("sportsDetail")] + public string SportsDetail { get; set; } // json string + } +} diff --git a/YD_WeChatApplet.Commons/Utils/JSSaTokenSignHelper.cs b/YD_WeChatApplet.Commons/Utils/JSSaTokenSignHelper.cs index 03bb937..f9b967c 100644 --- a/YD_WeChatApplet.Commons/Utils/JSSaTokenSignHelper.cs +++ b/YD_WeChatApplet.Commons/Utils/JSSaTokenSignHelper.cs @@ -47,6 +47,56 @@ namespace YD_WeChatApplet.Commons.Utils return sbQuery.ToString(); } + /// + /// 构建 POST JSON 上传接口的 QueryString(包含 sign) + /// ⚠️ 不与 GET 共用,避免误用 + /// + public static string BuildPostJsonQueryString( + Dictionary paramMap, + string secretKey, + string jsonBody) + { + if (paramMap == null) + throw new ArgumentNullException(nameof(paramMap)); + + if (string.IsNullOrWhiteSpace(jsonBody)) + throw new ArgumentException("POST JSON body 不能为空"); + + // 1️⃣ 参与签名的参数(TreeMap + ASCII 排序) + var signParams = new SortedDictionary(StringComparer.Ordinal); + + foreach (var kv in paramMap) + signParams[kv.Key] = kv.Value.ToString(); + + // ⭐ POST JSON 特有:整个 body 作为 reqbody + signParams["reqbody"] = jsonBody; + + // 2️⃣ 拼接签名字符串 + // k=v&k=v&...&key=secretKey + var sbSign = new StringBuilder(); + foreach (var kv in signParams) + sbSign.Append(kv.Key) + .Append("=") + .Append(kv.Value) + .Append("&"); + + sbSign.Append("key=").Append(secretKey.Trim()); + + string sign = Md5(sbSign.ToString()); + + // 3️⃣ 构建 URL QueryString(⚠️ 不包含 reqbody) + var sbQuery = new StringBuilder(); + foreach (var kv in paramMap) + sbQuery.Append(Uri.EscapeDataString(kv.Key)) + .Append("=") + .Append(Uri.EscapeDataString(kv.Value.ToString())) + .Append("&"); + + sbQuery.Append("sign=").Append(sign); + + return sbQuery.ToString(); + } + /// /// MD5 小写 32 位 ///