CorrectController.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. using Azure.Cosmos;
  2. using Microsoft.AspNetCore.Http;
  3. using Microsoft.AspNetCore.Mvc;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.IdentityModel.Tokens.Jwt;
  7. using System.Linq;
  8. using System.Text;
  9. using System.Text.Json;
  10. using System.Threading.Tasks;
  11. using TEAMModelOS.Models.Dto;
  12. using TEAMModelOS.SDK.Models;
  13. using TEAMModelOS.SDK;
  14. using TEAMModelOS.SDK.DI;
  15. using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
  16. using TEAMModelOS.SDK.Extension;
  17. using TEAMModelOS.SDK.Helper.Common.StringHelper;
  18. using TEAMModelOS.Models;
  19. using Microsoft.Extensions.Options;
  20. using TEAMModelOS.SDK.Models.Cosmos;
  21. using Microsoft.AspNetCore.Authorization;
  22. using TEAMModelOS.Filter;
  23. using StackExchange.Redis;
  24. using TEAMModelOS.SDK.Models.Cosmos.Common.Inner;
  25. using TEAMModelOS.SDK.Models.Service;
  26. using Microsoft.Extensions.Configuration;
  27. using HTEXLib.COMM.Helpers;
  28. using TEAMModelOS.SDK.DI.CoreAPI;
  29. using TEAMModelOS.SDK.Models.Dtos;
  30. using Microsoft.Extensions.Hosting;
  31. using Microsoft.AspNetCore.Hosting;
  32. using DocumentFormat.OpenXml.Office2010.Excel;
  33. namespace TEAMModelOS.Controllers
  34. {
  35. [ProducesResponseType(StatusCodes.Status200OK)]
  36. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  37. [Route("school/correct")]
  38. [ApiController]
  39. public class CorrectController : ControllerBase
  40. {
  41. private readonly AzureRedisFactory _azureRedis;
  42. private readonly AzureCosmosFactory _azureCosmos;
  43. private readonly SnowflakeId _snowflakeId;
  44. private readonly AzureServiceBusFactory _serviceBus;
  45. private readonly DingDing _dingDing;
  46. private readonly Option _option;
  47. private readonly AzureStorageFactory _azureStorage;
  48. private readonly IConfiguration _configuration;
  49. private readonly NotificationService _notificationService;
  50. private readonly CoreAPIHttpService _coreAPIHttpService;
  51. private readonly IWebHostEnvironment _environment;
  52. public CorrectController(IWebHostEnvironment environment,CoreAPIHttpService coreAPIHttpService,AzureCosmosFactory azureCosmos, AzureServiceBusFactory serviceBus, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration, NotificationService notificationService,
  53. AzureRedisFactory azureRedis, AzureStorageFactory azureStorage)
  54. {
  55. _environment = environment;
  56. _azureCosmos = azureCosmos;
  57. _serviceBus = serviceBus;
  58. _snowflakeId = snowflakeId;
  59. _dingDing = dingDing;
  60. _option = option?.Value;
  61. _azureRedis = azureRedis;
  62. _azureStorage = azureStorage;
  63. _configuration = configuration;
  64. _notificationService = notificationService;
  65. _coreAPIHttpService = coreAPIHttpService;
  66. }
  67. ///<summary>
  68. ///查询教师的阅卷任务列表
  69. /// </summary>
  70. /// <data>
  71. /// ! "code":"tmdid"
  72. /// </data>
  73. /// <param name="request"></param>
  74. /// <returns></returns>
  75. [ProducesDefaultResponseType]
  76. [AuthToken(Roles = "teacher,admin")]
  77. [HttpPost("find-task")]
  78. [Authorize(Roles = "IES")]
  79. public async Task<IActionResult> FindTask(JsonElement request)
  80. {
  81. List<CorrectTask> tasks = new List<CorrectTask>();
  82. try
  83. {
  84. var client = _azureCosmos.GetCosmosClient();
  85. //活动分区
  86. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  87. var (_, _, _, school) = HttpContext.GetAuthTokenInfo();
  88. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<CorrectTask>(queryText: $"select value(c) from c where c.scode = 'Correct-{school}'",
  89. requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"CorrectTask-{code}") }))
  90. {
  91. tasks.Add(item);
  92. }
  93. return Ok(new { tasks = tasks });
  94. }
  95. catch (CosmosException ex)
  96. {
  97. await _dingDing.SendBotMsg($"OS,{_option.Location},common/Correct/find-task()\n{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  98. return Ok(new { tasks = tasks });
  99. }
  100. }
  101. /*
  102. {
  103. "id":"uuid",//新增为null或者空
  104. "code":"hbcn",
  105. "owner":"school",
  106. "name":"xxx评测-阅卷",
  107. "creatorId":"1558635535",
  108. "progress":"pending 待发布|going 已发布|finish 已结束",
  109. "scope":"school",
  110. "startTime":158556666658,//评测结束的时间
  111. "createTime":158556666658,//当前时间
  112. "endTime":158556666658,//指定一个结束时间
  113. "examType":"评测活动的类型",
  114. "scode":"评测的源数据code值",
  115. "mode":"阅卷模式,1 按题目,0 按人/学生",
  116. "corSubs":[//科目的设置
  117. {
  118. "id":"科目id",
  119. "corTmdids":[//设置的醍摩豆账号
  120. {
  121. "tmdid":"1558635535,评卷教师的id",
  122. "corCount":100
  123. },
  124. ]
  125. }
  126. ]
  127. }
  128. */
  129. /// <summary>
  130. /// 新增 或 修改阅卷设置
  131. /// </summary>
  132. /// <param name="request"></param>
  133. /// <returns></returns>
  134. [ProducesDefaultResponseType]
  135. [AuthToken(Roles = "teacher,admin")]
  136. [HttpPost("upsert")]
  137. [Authorize(Roles = "IES")]
  138. public async Task<IActionResult> Upsert(Correct request)
  139. {
  140. try
  141. {
  142. //新增阅卷活动设置
  143. var client = _azureCosmos.GetCosmosClient();
  144. request.pk = $"Correct";
  145. request.code = $"Correct-{request.code}";
  146. request.ttl = -1;
  147. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  148. request.createTime = now;
  149. var (userid, name, _, school) = HttpContext.GetAuthTokenInfo();
  150. //取得学校基本信息
  151. var schresponse = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(school.ToString(), new PartitionKey("Base"));
  152. string schname = string.Empty;
  153. if (schresponse.Status == 200)
  154. {
  155. using var schjson = await JsonDocument.ParseAsync(schresponse.ContentStream);
  156. schjson.RootElement.TryGetProperty("name", out JsonElement jsonschname);
  157. schname = jsonschname.ToString();
  158. }
  159. //如果设置的时间是小于当前时间则立即发布
  160. if (request.startTime <= 0)
  161. {
  162. request.startTime = now;
  163. }
  164. if (string.IsNullOrEmpty(request.id))
  165. {
  166. request.id = Guid.NewGuid().ToString();
  167. if (request.startTime > now)
  168. {
  169. request.progress = "pending";
  170. }
  171. else
  172. {
  173. request.progress = "going";
  174. }
  175. request.subs.Select(r => r.markers).ToList();
  176. request = await client.GetContainer(Constant.TEAMModelOS, "Common").CreateItemAsync(request, new PartitionKey($"{request.code}"));
  177. }
  178. else
  179. {
  180. var response = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync(request.id, new PartitionKey($"{request.code}"));
  181. if (response.Status == 200)
  182. {
  183. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  184. var info = json.ToObject<Correct>();
  185. if (info.progress.Equals("going"))
  186. {
  187. return Ok(new { v = "活动正在进行中" });
  188. }
  189. if (request.startTime > now)
  190. {
  191. request.progress = "pending";
  192. }
  193. else
  194. {
  195. request.progress = "going";
  196. }
  197. request.progress = info.progress;
  198. request = await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(request, info.id, new PartitionKey($"{info.code}"));
  199. }
  200. else
  201. {
  202. if (request.startTime > now)
  203. {
  204. request.progress = "pending";
  205. }
  206. else
  207. {
  208. request.progress = "going";
  209. }
  210. request = await client.GetContainer(Constant.TEAMModelOS, "Common").CreateItemAsync(request, new PartitionKey($"{request.code}"));
  211. }
  212. }
  213. string bizcode = "scoring-mark";
  214. List<string> ids = new List<string>();
  215. foreach (CorSub sub in request.subs)
  216. {
  217. foreach (CorTmd tmd in sub.markers)
  218. {
  219. ids.Add(tmd.id);
  220. }
  221. }
  222. Notification notification = new Notification
  223. {
  224. hubName = "hita",
  225. type = "msg",
  226. from = $"ies5:{_option.Location}:private",
  227. to = ids,
  228. label = $"{bizcode}_school",
  229. body = new { location = _option.Location,
  230. biz = bizcode,
  231. tmdid = userid,
  232. tmdname = name.ToString(),
  233. schoolcode = school,
  234. schoolname = $"{schname}",
  235. examname = request.name,
  236. status = 1,
  237. time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
  238. }.ToJsonString(),
  239. expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
  240. };
  241. var url = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
  242. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  243. var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
  244. var location = _option.Location;
  245. await _notificationService.SendNotification(clientID, clientSecret, location, url, notification);
  246. string sql = $"select c.id, c.name ,c.lang as code from c where c.id in ({string.Join(",", ids.Select(x => $"'{x}'"))})";
  247. List<IdNameCode> idNameCodes = new List<IdNameCode>();
  248. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher)
  249. .GetItemQueryIterator<IdNameCode>(queryText: sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base") }))
  250. {
  251. idNameCodes.Add(item);
  252. }
  253. _coreAPIHttpService.PushNotify(idNameCodes, $"{bizcode}_school", Constant.NotifyType_IES5_Task,
  254. new Dictionary<string, object> { { "tmdname", name }, { "schooName", schname }, { "schoolId", $"{school}" }, { "tmdid", userid } }, _option.Location, _configuration, _dingDing, _environment.ContentRootPath);
  255. return Ok(new { vote = request });
  256. }
  257. catch (Exception e)
  258. {
  259. await _dingDing.SendBotMsg($"OS,{_option.Location},common/Correct/upsert()\n{e.Message}\n{e.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  260. return BadRequest(e.StackTrace);
  261. }
  262. }
  263. ///<summary>
  264. ///
  265. /// </summary>
  266. /// <data>
  267. /// ! "id":"3c075347-75ef-4bcb-ae03-68678d02d5ef", //评测id
  268. /// ! "code":"hbcn"//
  269. /// </data>
  270. /// <param name="request"></param>
  271. /// <returns></returns>
  272. [ProducesDefaultResponseType]
  273. [HttpPost("find-id")]
  274. [Authorize(Roles = "IES")]
  275. public async Task<IActionResult> FindById(JsonElement request)
  276. {
  277. try
  278. {
  279. //活动id
  280. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  281. //活动分区
  282. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  283. var client = _azureCosmos.GetCosmosClient();
  284. Correct correct = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<Correct>(id.GetString(), new PartitionKey($"Correct-{code}"));
  285. return Ok(new { correct });
  286. }
  287. catch (CosmosException ex)
  288. {
  289. Correct correct = null;
  290. return Ok(new { correct, status = ex.Status });
  291. }
  292. catch (Exception ex)
  293. {
  294. await _dingDing.SendBotMsg($"OS,{_option.Location},common/Correct/find-id()\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  295. Correct correct = null;
  296. return Ok(new { correct });
  297. }
  298. }
  299. [ProducesDefaultResponseType]
  300. [HttpPost("delete-task")]
  301. [Authorize(Roles = "IES")]
  302. public async Task<IActionResult> delete(JsonElement request)
  303. {
  304. try
  305. {
  306. //活动id
  307. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  308. //活动分区
  309. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  310. var client = _azureCosmos.GetCosmosClient();
  311. List<SDK.Models.Cosmos.Common.Scoring> attr = new();
  312. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<SDK.Models.Cosmos.Common.Scoring>(
  313. queryText: $"select value(c) from c where c.examId = '{id}'",
  314. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Scoring-{code}") }))
  315. {
  316. attr.Add(item);
  317. }
  318. await client.GetContainer(Constant.TEAMModelOS, "Teacher").DeleteItemsAsync<SDK.Models.Cosmos.Common.Scoring>(attr.Select(a => a.id).ToList(), $"Scoring-{code}");
  319. //var cresponse = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync(id.ToString(), new PartitionKey($"Scoring-{code}"));
  320. //删除阅卷配置
  321. var cresponse = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync(id.ToString(), new PartitionKey($"Correct-{code}"));
  322. if (cresponse.Status == 200)
  323. {
  324. using var json = await JsonDocument.ParseAsync(cresponse.ContentStream);
  325. Correct correct = json.ToObject<Correct>();
  326. if (correct.subs.IsNotEmpty())
  327. {
  328. foreach (var sub in correct.subs)
  329. {
  330. //List<string> correctIds = new List<string>();
  331. if (sub.markers.IsNotEmpty())
  332. {
  333. foreach (var marker in sub.markers)
  334. {
  335. await ExamService.deleteAsync(client, id.GetString(), marker.id);
  336. }
  337. }
  338. if (sub.err.Count > 0)
  339. {
  340. foreach (var tId in sub.err)
  341. {
  342. await ExamService.deleteAsync(client, id.GetString(), tId);
  343. }
  344. }
  345. if (sub.arb.Count > 0)
  346. {
  347. foreach (var tId in sub.arb)
  348. {
  349. await ExamService.deleteAsync(client, id.GetString(), tId);
  350. }
  351. }
  352. }
  353. }
  354. await client.GetContainer(Constant.TEAMModelOS, "Common").DeleteItemStreamAsync(id.GetString(), new PartitionKey($"Correct-{code}"));
  355. return Ok(new { id });
  356. }
  357. else
  358. {
  359. return Ok(new { code = 404 });
  360. }
  361. }
  362. catch (CosmosException ex)
  363. {
  364. Correct correct = null;
  365. return Ok(new { correct, status = ex.Status });
  366. }
  367. catch (Exception ex)
  368. {
  369. await _dingDing.SendBotMsg($"OS,{_option.Location},common/Correct/find-id()\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  370. Correct correct = null;
  371. return Ok(new { correct });
  372. }
  373. }
  374. }
  375. }