AbilityStatisticsController.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. using Azure.Cosmos;
  2. using Microsoft.AspNetCore.Http;
  3. using Microsoft.AspNetCore.Mvc;
  4. using Microsoft.Extensions.Options;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. using System.Text;
  9. using System.Text.Json;
  10. using System.Threading.Tasks;
  11. using TEAMModelOS.Models;
  12. using TEAMModelOS.SDK.DI;
  13. using TEAMModelOS.SDK;
  14. using TEAMModelOS.SDK.Models;
  15. using TEAMModelOS.SDK.Extension;
  16. using static TEAMModelOS.Controllers.SchoolTeacherController;
  17. using HTEXLib.COMM.Helpers;
  18. using TEAMModelOS.Filter;
  19. using static TEAMModelOS.Controllers.AbilitySubController;
  20. using Microsoft.AspNetCore.Authorization;
  21. namespace TEAMModelOS.Controllers
  22. {
  23. [ProducesResponseType(StatusCodes.Status200OK)]
  24. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  25. [Route("research")]
  26. [ApiController]
  27. public class AbilityStatisticsController : ControllerBase
  28. {
  29. private readonly AzureCosmosFactory _azureCosmos;
  30. private readonly DingDing _dingDing;
  31. private readonly Option _option;
  32. public AbilityStatisticsController(AzureCosmosFactory azureCosmos, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option)
  33. {
  34. _azureCosmos = azureCosmos;
  35. _dingDing = dingDing;
  36. _option = option?.Value;
  37. }
  38. /// <summary>
  39. /// 更新教师最终学习分数。
  40. /// </summary>
  41. /// <param name="request"></param>
  42. /// <returns></returns>
  43. [ProducesDefaultResponseType]
  44. [Authorize(Roles = "IES")]
  45. [HttpPost("upsert-teacher-finalScore")]
  46. [AuthToken(Roles = "admin,teacher", Permissions = "train-appraise")]
  47. public async Task<IActionResult> UpsertFinalScore(JsonElement request)
  48. {
  49. var (userid, name, picture, school) = HttpContext.GetAuthTokenInfo();
  50. var client = _azureCosmos.GetCosmosClient();
  51. if (!request.TryGetProperty("finalScore", out JsonElement _finalScore)) return BadRequest();
  52. if (!request.TryGetProperty("tmdids", out JsonElement _tmdids)) return BadRequest();
  53. int finalScore = -999;
  54. int.TryParse($"{_finalScore}", out finalScore);
  55. List<string> tmdids = _tmdids.ToObject<List<string>>();
  56. if (tmdids.IsNotEmpty() && finalScore >= -1 && finalScore <= 2)
  57. {
  58. List<TeacherTrain> trains = new List<TeacherTrain>();
  59. string insql = $"select value(c) from c where c.id in ({string.Join(",", tmdids.Select(x => $"'{x}'"))})";
  60. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher")
  61. .GetItemQueryIterator<TeacherTrain>(queryText: insql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"TeacherTrain-{school}") }))
  62. {
  63. trains.Add(item);
  64. }
  65. List<Task<ItemResponse<TeacherTrain>>> teacherTrains = new List<Task<ItemResponse<TeacherTrain>>>();
  66. trains.ForEach(x => {
  67. x.finalScore = finalScore;
  68. teacherTrains.Add(client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync(x, x.id, new PartitionKey(x.code)));
  69. });
  70. int pagesize = 50;
  71. if (teacherTrains.Count <= pagesize)
  72. {
  73. await Task.WhenAll(teacherTrains);
  74. }
  75. else
  76. {
  77. int pages = (teacherTrains.Count + pagesize) / pagesize; //256是批量操作最大值,pages = (total + max -1) / max;
  78. for (int i = 0; i < pages; i++)
  79. {
  80. var listssb = teacherTrains.Skip((i) * pagesize).Take(pagesize).ToList();
  81. await Task.WhenAll(listssb);
  82. }
  83. }
  84. return Ok(new { status = 200 });
  85. }
  86. else
  87. {
  88. return Ok(new { });
  89. }
  90. }
  91. /// <summary>
  92. /// 提交学习总结、。
  93. /// </summary>
  94. /// <param name="request"></param>
  95. /// <returns></returns>
  96. [ProducesDefaultResponseType]
  97. [HttpPost("upsert-teacher-summary")]
  98. [Authorize(Roles = "IES")]
  99. [AuthToken(Roles = "teacher,admin,area")]
  100. public async Task<IActionResult> UpsertSummary(JsonElement request)
  101. {
  102. var client = _azureCosmos.GetCosmosClient();
  103. request.TryGetProperty("summary", out JsonElement _summary);
  104. if (string.IsNullOrEmpty($"{_summary}"))
  105. {
  106. return BadRequest();
  107. }
  108. var (userid, name, picture, school) = HttpContext.GetAuthTokenInfo();
  109. if (!HttpContext.Items.TryGetValue("Standard", out object standard)) return BadRequest();
  110. try
  111. {
  112. TeacherTrain teacherTrain = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<TeacherTrain>(userid, new PartitionKey($"TeacherTrain-{school}"));
  113. teacherTrain.name = name;
  114. teacherTrain.picture = picture;
  115. teacherTrain.summary = $"{_summary}";
  116. await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<TeacherTrain>(teacherTrain, userid, new PartitionKey($"TeacherTrain-{school}"));
  117. return Ok(new { status = 200 });
  118. }
  119. catch (CosmosException ex)
  120. {
  121. return Ok(new { error = 1, msg = "你没有学习记录" });
  122. }
  123. }
  124. /// <summary>
  125. /// 区级数据统计
  126. /// </summary>
  127. /// <param name="request"></param>
  128. /// <returns></returns>
  129. [ProducesDefaultResponseType]
  130. [HttpPost("statistics-area")]
  131. [AuthToken(Roles = "teacher,admin,area")]
  132. public async Task<IActionResult> StatisticsArea(JsonElement request)
  133. {
  134. var (userid, _, _, _) = HttpContext.GetAuthTokenInfo();
  135. request.TryGetProperty("standard", out JsonElement _standard);
  136. string standard = $"{_standard}";
  137. if (string.IsNullOrEmpty(standard))
  138. {
  139. return BadRequest();
  140. }
  141. var client = _azureCosmos.GetCosmosClient();
  142. Area area = null;
  143. string sql = $"select value(c) from c where c.standard='{standard}'";
  144. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Area>(queryText: sql,
  145. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-Area") }))
  146. {
  147. area = item;
  148. }
  149. AreaSetting setting = null;
  150. if (area != null)
  151. {
  152. try
  153. {
  154. setting = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<AreaSetting>(area.id, new PartitionKey("AreaSetting"));
  155. }
  156. catch (CosmosException)
  157. {
  158. setting = null;
  159. }
  160. }
  161. if (setting == null)
  162. {
  163. setting = new AreaSetting
  164. {
  165. allTime = 50,
  166. classTime = 5,
  167. submitTime = 15,
  168. onlineTime = 20,
  169. offlineTime = 10,
  170. lessonMinutes = 45,
  171. };
  172. }
  173. try
  174. {
  175. List<TeacherTrain> teacherTrains = new List<TeacherTrain>();
  176. List<School> schools = new List<School>();
  177. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<School>(queryText: $"select value(c) from c where c.areaId='{area.id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base") }))
  178. {
  179. schools.Add(item);
  180. }
  181. List<Task<(List<TeacherTrain> trains, List<RGroupList> yxtrain)>> trains = new List<Task<(List<TeacherTrain> trains, List<RGroupList> yxtrain)>>();
  182. int countArea = 0;
  183. int appraiseArea = 0;
  184. List<SchoolInfos> schoolInfos = new List<SchoolInfos>();
  185. foreach (var school in schools)
  186. {
  187. int count = 0;
  188. int appraise = 0;
  189. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<bool>(queryText: $"select value(ARRAY_CONTAINS( c.permissions,'train-appraise')) from c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Teacher-{school.id}") }))
  190. {
  191. if (item)
  192. {
  193. appraise += 1;
  194. appraiseArea += 1;
  195. }
  196. countArea += 1;
  197. count += 1;
  198. }
  199. schoolInfos.Add(new SchoolInfos { schoolId = school.id, schoolName = school.name, picture = school.picture, teacherCount = count, appraiseCount = appraise });
  200. //增加评审人员总人数,学习总人数。
  201. trains.Add(StatisticsService.StatisticsSchool(school.id, setting, area, client, _dingDing, null));
  202. }
  203. int pagesize = 100;
  204. if (trains.Count <= pagesize)
  205. {
  206. (List<TeacherTrain> trains, List<RGroupList> yxtrain)[] tasks = await Task.WhenAll(trains);
  207. tasks.ToList().ForEach(x => {
  208. teacherTrains.AddRange(x.trains);
  209. schoolInfos.ForEach(y => {
  210. var list = x.yxtrain.Find(z => z.school.Equals(y.schoolId));
  211. if (list != null)
  212. {
  213. y.trainCount = list.members.Count;
  214. }
  215. });
  216. });
  217. }
  218. else
  219. {
  220. int pages = (trains.Count + pagesize) / pagesize; //256是批量操作最大值,pages = (total + max -1) / max;
  221. for (int i = 0; i < pages; i++)
  222. {
  223. var listssb = trains.Skip((i) * pagesize).Take(pagesize).ToList();
  224. (List<TeacherTrain> trains, List<RGroupList> yxtrain)[] tasks = await Task.WhenAll(listssb);
  225. tasks.ToList().ForEach(x => {
  226. teacherTrains.AddRange(x.trains);
  227. schoolInfos.ForEach(y => {
  228. var list = x.yxtrain.Find(z => z.school.Equals(y.schoolId));
  229. if (list != null)
  230. {
  231. y.trainCount = list.members.Count;
  232. }
  233. });
  234. });
  235. }
  236. }
  237. long totalTime = teacherTrains.Select(x => x.totalTime).Sum();
  238. int hgcount = teacherTrains.Where(x => x.finalScore == 1 || x.finalScore == 2).Count();
  239. var teacherAilities = teacherTrains.SelectMany(x => x.currency.teacherAilities);
  240. setting.accessConfig = null;
  241. teacherTrains.ForEach(x => {
  242. x.currency.videoTime = (int)x.currency.videoTime;
  243. x.currency.teacherAilities.ForEach(y => {
  244. y.videoTime = (int)y.videoTime;
  245. y.onlineTime = (int)y.onlineTime;
  246. y.debateOrther = y.debateOrther > 0 ? y.debateOrther : 0;
  247. });
  248. });
  249. return Ok(new { teacherTrains, setting, schools = schoolInfos, totalTime, hgcount, teacherAilities, teacherCount = countArea, appraiseCount = appraiseArea });
  250. }
  251. catch (Exception ex)
  252. {
  253. await _dingDing.SendBotMsg($"OS,{_option.Location},UpsertSubmitScore/UpsertSubmitScore()\n{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  254. return BadRequest(new { ex.Message, ex.StackTrace });
  255. }
  256. }
  257. public class SchoolInfos
  258. {
  259. public string schoolId { get; set; }
  260. public string schoolName { get; set; }
  261. public string picture { get; set; }
  262. public int teacherCount { get; set; }
  263. public int appraiseCount { get; set; }
  264. public int trainCount { get; set; }
  265. }
  266. /// <summary>
  267. /// 校级数据统计
  268. /// </summary>
  269. /// <param name="request"></param>
  270. /// <returns></returns>
  271. [ProducesDefaultResponseType]
  272. [HttpPost("get-school-appraise")]
  273. [AuthToken(Roles = "teacher,admin,area")]
  274. public async Task<IActionResult> GetSchoolAppraise(JsonElement request)
  275. {
  276. request.TryGetProperty("school", out JsonElement _school);
  277. string school = "";
  278. var (userid, _, _, __school) = HttpContext.GetAuthTokenInfo();
  279. if (!string.IsNullOrEmpty($"{_school}"))
  280. {
  281. school = $"{_school}";
  282. }
  283. else
  284. {
  285. school = __school;
  286. }
  287. request.TryGetProperty("update", out JsonElement _update);
  288. HashSet<string> update = null;
  289. if (_update.ValueKind.Equals(JsonValueKind.Array))
  290. {
  291. update = _update.ToObject<HashSet<string>>();
  292. }
  293. if (!HttpContext.Items.TryGetValue("Standard", out object standard)) return BadRequest();
  294. var client = _azureCosmos.GetCosmosClient();
  295. Area area = null;
  296. string sql = $"select value(c) from c where c.standard='{standard}'";
  297. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Area>(queryText: sql,
  298. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-Area") }))
  299. {
  300. area = item;
  301. }
  302. AreaSetting setting = null;
  303. if (area != null)
  304. {
  305. try
  306. {
  307. //优先找校级
  308. setting = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<AreaSetting>(school, new PartitionKey("AreaSetting"));
  309. }
  310. catch (CosmosException)
  311. {
  312. try
  313. {
  314. setting = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<AreaSetting>(area.id, new PartitionKey("AreaSetting"));
  315. }
  316. catch (CosmosException)
  317. {
  318. setting = null;
  319. }
  320. }
  321. }
  322. if (setting == null)
  323. {
  324. setting = new AreaSetting
  325. {
  326. allTime = 50,
  327. classTime = 5,
  328. submitTime = 15,
  329. onlineTime = 20,
  330. offlineTime = 10,
  331. lessonMinutes = 45,
  332. };
  333. }
  334. try
  335. {
  336. int count = 0;
  337. int appraise = 0;
  338. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<bool>(queryText: $" select value(ARRAY_CONTAINS( c.permissions,'train-appraise') ) from c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Teacher-{school}") }))
  339. {
  340. if (item)
  341. {
  342. appraise += 1;
  343. }
  344. count += 1;
  345. }
  346. //增加评审人员总人数,学习总人数。
  347. (List<TeacherTrain> teacherTrains, List<RGroupList> yxtrain) = await StatisticsService.StatisticsSchool(school, setting, area, client, _dingDing, update);
  348. teacherTrains.ForEach(x => {
  349. x.currency.videoTime = (int)x.currency.videoTime;
  350. x.currency.teacherAilities.ForEach(y => {
  351. y.videoTime = (int)y.videoTime;
  352. y.onlineTime = (int)y.onlineTime;
  353. y.debateOrther= y.debateOrther>0? y.debateOrther: 0;
  354. });
  355. });
  356. //try
  357. //{
  358. // teacherTrain = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<TeacherTrain>(userid, new PartitionKey($"TeacherTrain-{school}"));
  359. //}
  360. //catch (CosmosException)
  361. //{
  362. // await client.GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync<TeacherTrain>(teacherTrain, new PartitionKey($"TeacherTrain-{school}"));
  363. //}
  364. setting.accessConfig = null;
  365. return Ok(new { teacherTrains, setting, teacherCount = count, appraiseCount = appraise, yxtrain });
  366. }
  367. catch (Exception ex)
  368. {
  369. return BadRequest(new { ex.Message, ex.StackTrace });
  370. }
  371. }
  372. /// <summary>
  373. /// 教师个人数据统计
  374. /// </summary>
  375. /// <param name="request"></param>
  376. /// <returns></returns>
  377. [ProducesDefaultResponseType]
  378. [HttpPost("statistics-teacher")]
  379. [AuthToken(Roles = "teacher,admin,area")]
  380. public async Task<IActionResult> StatisticsTeacher(JsonElement request)
  381. {
  382. //{"tmdid":"1595321354","school":"hbcn"}
  383. var (_userid, name, picture, school) = HttpContext.GetAuthTokenInfo();
  384. if (!HttpContext.Items.TryGetValue("Standard", out object standard)) return BadRequest();
  385. var client = _azureCosmos.GetCosmosClient();
  386. request.TryGetProperty("update", out JsonElement _update);
  387. HashSet<string> update = null;
  388. if (_update.ValueKind.Equals(JsonValueKind.Array))
  389. {
  390. update = _update.ToObject<HashSet<string>>();
  391. }
  392. request.TryGetProperty("tmdid", out JsonElement _tmdid);
  393. string tmdid = "";
  394. if (_tmdid.ValueKind.Equals(JsonValueKind.String))
  395. {
  396. tmdid = $"{_tmdid}";
  397. }
  398. else
  399. {
  400. tmdid = $"{_userid}";
  401. }
  402. Area area = null;
  403. string sql = $"select value(c) from c where c.standard='{standard}'";
  404. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Area>(queryText: sql,
  405. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-Area") }))
  406. {
  407. area = item;
  408. }
  409. AreaSetting setting = null;
  410. if (area != null)
  411. {
  412. try
  413. {
  414. //优先找校级
  415. setting = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<AreaSetting>(school, new PartitionKey("AreaSetting"));
  416. }
  417. catch (CosmosException)
  418. {
  419. try
  420. {
  421. setting = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<AreaSetting>(area.id, new PartitionKey("AreaSetting"));
  422. }
  423. catch (CosmosException)
  424. {
  425. setting = null;
  426. }
  427. }
  428. }
  429. if (setting == null)
  430. {
  431. setting = new AreaSetting
  432. {
  433. allTime = 50,
  434. classTime = 5,
  435. submitTime = 15,
  436. onlineTime = 20,
  437. offlineTime = 10,
  438. lessonMinutes = 45,
  439. };
  440. }
  441. try
  442. {
  443. TeacherTrain teacherTrain = null;
  444. try
  445. {
  446. teacherTrain = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<TeacherTrain>(tmdid, new PartitionKey($"TeacherTrain-{school}"));
  447. teacherTrain.name = name;
  448. teacherTrain.picture = picture;
  449. if (update != null && update.Count > 0)
  450. {
  451. foreach (var up in update)
  452. {
  453. teacherTrain.update.Add(up);
  454. }
  455. }
  456. ///强制教师个人信息统计的时候 都再去统计一次。
  457. teacherTrain.update.Add(StatisticsService.TeacherAbility);
  458. if (teacherTrain.update.Count > 0)
  459. {
  460. await StatisticsService.StatisticsTeacher(teacherTrain, setting, area, client, null);
  461. }
  462. }
  463. catch (CosmosException)
  464. {
  465. teacherTrain = await StatisticsService.StatisticsTeacher(new TeacherTrain
  466. {
  467. pk = "TeacherTrain",
  468. id = tmdid,
  469. code = $"TeacherTrain-{school}",
  470. tmdid = tmdid,
  471. school = school,
  472. name = name,
  473. picture = picture,
  474. update = new HashSet<string> { StatisticsService.TeacherAbility,
  475. StatisticsService.TeacherClass, StatisticsService.OfflineRecord }
  476. }, setting, area, client, null);
  477. }
  478. setting.accessConfig = null;
  479. teacherTrain.currency.videoTime = (int)teacherTrain.currency.videoTime;
  480. teacherTrain.currency.teacherAilities.ForEach(y => {
  481. y.videoTime = (int)y.videoTime;
  482. y.onlineTime = (int)y.onlineTime;
  483. y.debateOrther = y.debateOrther > 0 ? y.debateOrther : 0;
  484. });
  485. return Ok(new { teacherTrain, setting });
  486. }
  487. catch (Exception ex)
  488. {
  489. return BadRequest(new { ex.Message, ex.StackTrace });
  490. }
  491. }
  492. }
  493. }