上传成绩

This commit is contained in:
tanglong 2026-01-12 16:14:49 +08:00
parent 31e943e5dd
commit c5840c841e
11 changed files with 195 additions and 16 deletions

View File

@ -24,12 +24,11 @@ namespace YD_WeChatApplet.Api.Controllers
/// Ai一体机扫描登录
/// </summary>
/// <param name="code"></param>
/// <param name="teacherNo"></param>
/// <returns></returns>
[HttpPost("ScanCodeLogin")]
public async Task<bool> ScanCodeLogin(string code, string teacherNo)
public async Task<bool> ScanCodeLogin(string code)
{
return await _frameworkService.ScanCodeLogin(code, teacherNo);
return await _frameworkService.ScanCodeLogin(code);
}
}
}

View File

@ -23,9 +23,8 @@ namespace YD_WeChatApplet.Api.Services.Impl
/// Ai一体机扫描登录
/// </summary>
/// <param name="code"></param>
/// <param name="teacherNo"></param>
/// <returns></returns>
public async Task<bool> ScanCodeLogin(string code,string teacherNo)
public async Task<bool> 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
};

View File

@ -61,6 +61,7 @@ namespace YD_WeChatApplet.Api.Services.Impl
var homeWorkEntity = _mapper.Map<S_HomeWork>(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<S_HomeWork>(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;

View File

@ -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;
}
/// <summary>
/// 上传成绩数据
/// </summary>
/// <param name="list"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<bool> PushSportsData(List<SportsDataPushDto> list)
{
long timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
string nonce = SaTokenSignHelper.RandomString();
var paramMap = new Dictionary<string, object>
{
{ "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<JingShiResponse<object>>(result);
return res != null && res.Code == 0;
}
}
}

View File

@ -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<PatriarchService> _logger;
private readonly IJingShiTiJiaoService _jingShiTiJiaoService;
public PatriarchService(UserContext userContext, SmartSportsContext sportsContext, IMapper mapper, ILogger<PatriarchService> logger, IJingShiTiJiaoService jingShiTiJiaoService)
{
_userContext = userContext;
_sportsContext = sportsContext;
_mapper = mapper;
_logger = logger;
_jingShiTiJiaoService = jingShiTiJiaoService;
}
/// <summary>
@ -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<SportsDataPushDto>
{
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);
}
});
}
/// <summary>

View File

@ -9,8 +9,7 @@
/// Ai一体机扫描登录
/// </summary>
/// <param name="code"></param>
/// <param name="teacherNo"></param>
/// <returns></returns>
Task<bool> ScanCodeLogin(string code, string teacherNo);
Task<bool> ScanCodeLogin(string code);
}
}

View File

@ -26,5 +26,12 @@ namespace YD_WeChatApplet.Api.Services.Interface
/// <param name="stuNo"></param>
/// <returns></returns>
Task<StudentDetailDto> GetStudentInfo(string stuNo);
/// <summary>
/// 上传数据
/// </summary>
/// <param name="list"></param>
/// <returns></returns>
Task<bool> PushSportsData(List<SportsDataPushDto> list);
}
}

View File

@ -116,5 +116,6 @@
public string SecretKey { get; set; }
public string BaseUrl { get; set; }
public string SchoolCode { get; set; }
public string SportsItem { get; set; }
}
}

View File

@ -71,6 +71,7 @@
"Channel": "sk-yuedong",
"SecretKey": "JSTJ-kGfs6J7bkgdxr9mz",
"BaseUrl": "https://api-test.aitibao.com",
"SchoolCode": "202512240056"
"SchoolCode": "202512240056",
"SportsItem": "JS010000"
}
}

View File

@ -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
}
}

View File

@ -47,6 +47,56 @@ namespace YD_WeChatApplet.Commons.Utils
return sbQuery.ToString();
}
/// <summary>
/// 构建 POST JSON 上传接口的 QueryString(包含 sign)
/// ⚠️ 不与 GET 共用,避免误用
/// </summary>
public static string BuildPostJsonQueryString(
Dictionary<string, object> 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<string, string>(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();
}
/// <summary>
/// MD5 小写 32 位
/// </summary>