From c5840c841ec45d282edcb925a3635d32df9960dc Mon Sep 17 00:00:00 2001
From: tanglong <842690096@qq.com>
Date: Mon, 12 Jan 2026 16:14:49 +0800
Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=88=90=E7=BB=A9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Controllers/FrameworkController.cs | 5 +-
.../Services/Impl/FrameworkService.cs | 5 +-
WeChatApplet/Services/Impl/HomeWorkService.cs | 2 +
.../Services/Impl/JingShiTiJiaoService.cs | 45 +++++++++++++-
.../Services/Impl/PatriarchService.cs | 60 +++++++++++++++++--
.../Services/Interface/IFrameworkService.cs | 3 +-
.../Interface/IJingShiTiJiaoService.cs | 7 +++
WeChatApplet/Utilities/AppSettings.cs | 1 +
WeChatApplet/appsettings.json | 3 +-
.../Dto/JingShiTiJiao/SportsDataPushDto.cs | 30 ++++++++++
.../Utils/JSSaTokenSignHelper.cs | 50 ++++++++++++++++
11 files changed, 195 insertions(+), 16 deletions(-)
create mode 100644 YD_WeChatApplet.Commons/Dto/JingShiTiJiao/SportsDataPushDto.cs
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 位
///