AbilityStatisticsController.cs 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945
  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. using TEAMModelOS.SDK.Models.Service;
  22. using ScTeacher = TEAMModelOS.SDK.Models.ScTeacher;
  23. using static TEAMModelOS.SDK.StatisticsService;
  24. using Azure.Messaging.ServiceBus;
  25. using Microsoft.Extensions.Configuration;
  26. namespace TEAMModelOS.Controllers
  27. {
  28. [ProducesResponseType(StatusCodes.Status200OK)]
  29. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  30. [Route("research")]
  31. [ApiController]
  32. public class AbilityStatisticsController : ControllerBase
  33. {
  34. private readonly AzureCosmosFactory _azureCosmos;
  35. private readonly DingDing _dingDing;
  36. private readonly Option _option;
  37. private readonly CoreAPIHttpService _coreAPIHttpService;
  38. private readonly HttpTrigger _httpTrigger;
  39. private readonly AzureStorageFactory _azureStorage;
  40. public IConfiguration _configuration { get; set; }
  41. private readonly AzureServiceBusFactory _serviceBus;
  42. private readonly ScsStudyApisService _scsStudyApisService;
  43. public AbilityStatisticsController(ScsStudyApisService scsStudyApisService, AzureStorageFactory azureStorage, HttpTrigger httpTrigger, CoreAPIHttpService coreAPIHttpService, AzureCosmosFactory azureCosmos, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option,
  44. AzureServiceBusFactory serviceBus, IConfiguration configuration)
  45. {
  46. _azureCosmos = azureCosmos;
  47. _dingDing = dingDing;
  48. _option = option?.Value;
  49. _coreAPIHttpService = coreAPIHttpService;
  50. _httpTrigger = httpTrigger;
  51. _azureStorage = azureStorage;
  52. _serviceBus = serviceBus;
  53. _configuration = configuration;
  54. _scsStudyApisService = scsStudyApisService;
  55. }
  56. /// <summary>
  57. /// 更新教师最终学习分数。
  58. /// </summary>
  59. /// <param name="request"></param>
  60. /// <returns></returns>
  61. [ProducesDefaultResponseType]
  62. [Authorize(Roles = "IES")]
  63. [HttpPost("upsert-teacher-finalScore")]
  64. [AuthToken(Roles = "admin,teacher", Permissions = "train-appraise")]
  65. public async Task<IActionResult> UpsertFinalScore(JsonElement request)
  66. {
  67. var (userid, name, picture, school) = HttpContext.GetAuthTokenInfo();
  68. var client = _azureCosmos.GetCosmosClient();
  69. if (!request.TryGetProperty("finalScore", out JsonElement _finalScore)) return BadRequest();
  70. if (!request.TryGetProperty("tmdids", out JsonElement _tmdids)) return BadRequest();
  71. int finalScore = -999;
  72. int.TryParse($"{_finalScore}", out finalScore);
  73. List<string> tmdids = _tmdids.ToObject<List<string>>();
  74. if (tmdids.IsNotEmpty() && finalScore >= -1 && finalScore <= 2)
  75. {
  76. List<TeacherTrain> trains = new List<TeacherTrain>();
  77. string insql = $"select value(c) from c where c.id in ({string.Join(",", tmdids.Select(x => $"'{x}'"))})";
  78. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher")
  79. .GetItemQueryIterator<TeacherTrain>(queryText: insql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"TeacherTrain-{school}") }))
  80. {
  81. trains.Add(item);
  82. }
  83. List<Task<ItemResponse<TeacherTrain>>> teacherTrains = new List<Task<ItemResponse<TeacherTrain>>>();
  84. trains.ForEach(x => {
  85. x.finalScore = finalScore;
  86. teacherTrains.Add(client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync(x, x.id, new PartitionKey(x.code)));
  87. });
  88. int pagesize = 50;
  89. if (teacherTrains.Count <= pagesize)
  90. {
  91. await Task.WhenAll(teacherTrains);
  92. }
  93. else
  94. {
  95. int pages = (teacherTrains.Count + pagesize) / pagesize; //256是批量操作最大值,pages = (total + max -1) / max;
  96. for (int i = 0; i < pages; i++)
  97. {
  98. var listssb = teacherTrains.Skip((i) * pagesize).Take(pagesize).ToList();
  99. await Task.WhenAll(listssb);
  100. }
  101. }
  102. return Ok(new { status = 200 });
  103. }
  104. else
  105. {
  106. return Ok(new { });
  107. }
  108. }
  109. /// <summary>
  110. /// 提交学习总结、。
  111. /// </summary>
  112. /// <param name="request"></param>
  113. /// <returns></returns>
  114. [ProducesDefaultResponseType]
  115. [HttpPost("upsert-teacher-summary")]
  116. [Authorize(Roles = "IES")]
  117. [AuthToken(Roles = "teacher,admin,area")]
  118. public async Task<IActionResult> UpsertSummary(JsonElement request)
  119. {
  120. var client = _azureCosmos.GetCosmosClient();
  121. request.TryGetProperty("summary", out JsonElement _summary);
  122. if (string.IsNullOrEmpty($"{_summary}"))
  123. {
  124. return BadRequest();
  125. }
  126. var (userid, name, picture, school) = HttpContext.GetAuthTokenInfo();
  127. if (!HttpContext.Items.TryGetValue("Standard", out object standard)) return BadRequest();
  128. try
  129. {
  130. TeacherTrain teacherTrain = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<TeacherTrain>(userid, new PartitionKey($"TeacherTrain-{school}"));
  131. teacherTrain.nickname = name;
  132. teacherTrain.name = name;
  133. var table = _azureStorage.GetCloudTableClient().GetTableReference("ScYxpt");
  134. List<ScTeacher> teachers = await table.FindListByDict<ScTeacher>(new Dictionary<string, object>() { { "PartitionKey", "ScTeacher" }, { "schoolCode", school }, { "tmdid", $"{teacherTrain.id}" } });
  135. if (teachers.Any())
  136. {
  137. teacherTrain.name = teachers[0].TeacherName;
  138. }
  139. teacherTrain.picture = picture;
  140. teacherTrain.summary = $"{_summary}";
  141. await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<TeacherTrain>(teacherTrain, userid, new PartitionKey($"TeacherTrain-{school}"));
  142. return Ok(new { status = 200 });
  143. }
  144. catch (CosmosException ex)
  145. {
  146. return Ok(new { error = 1, msg = "你没有学习记录" });
  147. }
  148. }
  149. /// <summary>
  150. /// 区级数据统计
  151. /// </summary>
  152. /// <param name="request"></param>
  153. /// <returns></returns>
  154. [ProducesDefaultResponseType]
  155. //[HttpPost("statistics-area-simple")]
  156. [HttpPost("statistics-area-quick")]
  157. [AuthToken(Roles = "teacher,admin,area")]
  158. [Authorize(Roles = "IES")]
  159. public async Task<IActionResult> StatisticsAreaSimple(JsonElement request)
  160. {
  161. var (userid, _, _, _) = HttpContext.GetAuthTokenInfo();
  162. request.TryGetProperty("standard", out JsonElement _standard);
  163. string standard = $"{_standard}";
  164. if (string.IsNullOrEmpty(standard))
  165. {
  166. return BadRequest();
  167. }
  168. var client = _azureCosmos.GetCosmosClient();
  169. Area area = null;
  170. string sql = $"select value(c) from c where c.standard='{standard}'";
  171. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Area>(queryText: sql,
  172. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-Area") }))
  173. {
  174. area = item;
  175. }
  176. AreaSetting setting = null;
  177. if (area != null)
  178. {
  179. try
  180. {
  181. setting = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<AreaSetting>(area.id, new PartitionKey("AreaSetting"));
  182. }
  183. catch (CosmosException)
  184. {
  185. setting = null;
  186. }
  187. }
  188. if (setting == null)
  189. {
  190. setting = new AreaSetting
  191. {
  192. allTime = 50,
  193. classTime = 5,
  194. submitTime = 15,
  195. onlineTime = 20,
  196. offlineTime = 10,
  197. lessonMinutes = 45,
  198. };
  199. }
  200. try
  201. {
  202. List<TeacherTrain> teacherTrains = new List<TeacherTrain>();
  203. List<School> schools = new List<School>();
  204. 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") }))
  205. {
  206. schools.Add(item);
  207. }
  208. List<Task<(List<TeacherTrain> trains, List<RGroupList> yxtrain)>> trains = new List<Task<(List<TeacherTrain> trains, List<RGroupList> yxtrain)>>();
  209. int countArea = 0;
  210. int appraiseArea = 0;
  211. List<SchoolInfos> schoolInfos = new List<SchoolInfos>();
  212. foreach (var school in schools)
  213. {
  214. schoolInfos.Add(new SchoolInfos { schoolId = school.id, schoolName = school.name, picture = school.picture });
  215. //增加评审人员总人数,学习总人数。
  216. trains.Add(StatisticsService.StatisticsSchool(_coreAPIHttpService, school.id, setting, area, client, _dingDing, null));
  217. }
  218. int pagesize = 100;
  219. if (trains.Count <= pagesize)
  220. {
  221. (List<TeacherTrain> trains, List<RGroupList> yxtrain)[] tasks = await Task.WhenAll(trains);
  222. tasks.ToList().ForEach(x => {
  223. teacherTrains.AddRange(x.trains);
  224. schoolInfos.ForEach(y => {
  225. var list = x.yxtrain.Find(z => z.school.Equals(y.schoolId));
  226. if (list != null)
  227. {
  228. y.trainCount = list.members.Count;
  229. }
  230. });
  231. });
  232. }
  233. else
  234. {
  235. int pages = (trains.Count + pagesize) / pagesize; //256是批量操作最大值,pages = (total + max -1) / max;
  236. for (int i = 0; i < pages; i++)
  237. {
  238. var listssb = trains.Skip((i) * pagesize).Take(pagesize).ToList();
  239. (List<TeacherTrain> trains, List<RGroupList> yxtrain)[] tasks = await Task.WhenAll(listssb);
  240. tasks.ToList().ForEach(x => {
  241. teacherTrains.AddRange(x.trains);
  242. schoolInfos.ForEach(y => {
  243. var list = x.yxtrain.Find(z => z.school.Equals(y.schoolId));
  244. if (list != null)
  245. {
  246. y.trainCount = list.members.Count;
  247. }
  248. });
  249. });
  250. }
  251. }
  252. long totalTime = teacherTrains.Select(x => x.totalTime).Sum();
  253. int hgcount = teacherTrains.Where(x => x.finalScore == 1 || x.finalScore == 2).Count();
  254. setting.accessConfig = null;
  255. List<dynamic> dynamics = new List<dynamic>();
  256. teacherTrains.ForEach(x => {
  257. x.schoolName = schools.Find(s => s.id.Equals(x.school))?.name;
  258. x.currency.videoTime = (int)x.currency.videoTime;
  259. x.currency.teacherAilities.ForEach(y => {
  260. y.videoTime = (int)y.videoTime;
  261. y.onlineTime = (int)y.onlineTime;
  262. y.debateOrther = y.debateOrther > 0 ? y.debateOrther : 0;
  263. });
  264. dynamic dynamic = new {
  265. x.schoolName,
  266. x.classTime,
  267. x.finalScore,
  268. x.name,
  269. x.offlineTime,
  270. x.onlineTime,
  271. x.school,
  272. x.id,
  273. x.totalTime,
  274. currency = new {
  275. x.currency.submitTime,
  276. x.currency.exerciseAbility,
  277. x.currency.learnAbility,
  278. x.currency.uploadDone,
  279. x.currency.uploadTotal,
  280. x.currency.videoTime,
  281. teacherAilities = x.currency.teacherAilities.Select(t => new {
  282. t.onlineTime,
  283. t.videoTime,
  284. t.no,
  285. t.name,
  286. t.dimension,
  287. t.zpscore, t.xzscore, t.hpscore
  288. }),
  289. },
  290. offlineCountNo = x.offlineRecords.Where(o => o.haswork == 1 && string.IsNullOrWhiteSpace(o.url)).Count(),
  291. offlineCountOk = x.offlineRecords.Where(o => o.haswork == 1 && !string.IsNullOrWhiteSpace(o.url)).Count(),
  292. teacherClasseCount = x.teacherClasses.Count
  293. };
  294. dynamics.Add(dynamic);
  295. });
  296. //var table = _azureStorage.GetCloudTableClient().GetTableReference("ScYxpt");
  297. //var ScTeachers = await table.FindListByDict<ScTeacher>(new Dictionary<string, object>() { { "PartitionKey", "ScTeacher" }, { "areaId", $"{setting.id}" } });
  298. //var ttt = ScTeachers.Select(x => x.tmdid).Except(teacherTrains.Select(x => x.id));
  299. return Ok(new { teacherTrains = dynamics, setting, schools = schoolInfos, totalTime, hgcount, teacherCount = countArea, appraiseCount = appraiseArea });
  300. }
  301. catch (Exception ex)
  302. {
  303. await _dingDing.SendBotMsg($"OS,{_option.Location},UpsertSubmitScore/UpsertSubmitScore()\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  304. return BadRequest(new { ex.Message, ex.StackTrace });
  305. }
  306. }
  307. /// <summary>
  308. /// 区级数据统计
  309. /// </summary>
  310. /// <param name="request"></param>
  311. /// <returns></returns>
  312. [ProducesDefaultResponseType]
  313. //[HttpPost("statistics-area-quick")]
  314. [HttpPost("statistics-area-simple")]
  315. [AuthToken(Roles = "teacher,admin,area")]
  316. [Authorize(Roles = "IES")]
  317. public async Task<IActionResult> StatisticsAreaQuick(JsonElement request) {
  318. var (userid, _, _, _) = HttpContext.GetAuthTokenInfo();
  319. request.TryGetProperty("standard", out JsonElement _standard);
  320. string standard = $"{_standard}";
  321. if (string.IsNullOrEmpty(standard))
  322. {
  323. return BadRequest();
  324. }
  325. var client = _azureCosmos.GetCosmosClient();
  326. Area area = null;
  327. string sql = $"select value(c) from c where c.standard='{standard}'";
  328. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Area>(queryText: sql,
  329. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-Area") }))
  330. {
  331. area = item;
  332. }
  333. AreaSetting setting = null;
  334. if (area != null)
  335. {
  336. try
  337. {
  338. setting = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<AreaSetting>(area.id, new PartitionKey("AreaSetting"));
  339. }
  340. catch (CosmosException)
  341. {
  342. setting = null;
  343. }
  344. }
  345. if (setting == null)
  346. {
  347. setting = new AreaSetting
  348. {
  349. allTime = 50,
  350. classTime = 5,
  351. submitTime = 15,
  352. onlineTime = 20,
  353. offlineTime = 10,
  354. lessonMinutes = 45,
  355. };
  356. }
  357. try
  358. {
  359. List<TeacherTrain> teacherTrains = new List<TeacherTrain>();
  360. List<School> schools = new List<School>();
  361. 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") }))
  362. {
  363. schools.Add(item);
  364. }
  365. int countArea = 0;
  366. int appraiseArea = 0;
  367. List<SchoolInfos> schoolInfos = new List<SchoolInfos>();
  368. TeacherTrainChangeMsg msg = new TeacherTrainChangeMsg() { areaId=area.id};
  369. List<Task> tasks = new List<Task>();
  370. List<string> updateTeach = new List<string>();
  371. schools.ForEach( school =>
  372. {
  373. tasks.Add(Task.Run(async () =>
  374. {
  375. schoolInfos.Add(new SchoolInfos { schoolId = school.id, schoolName = school.name, picture = school.picture });
  376. (List<TeacherTrain> trains, List<RGroupList> yxtrain, List<TeacherTrain> updateTeacherTrains) =
  377. await StatisticsService.StatisticsSchoolQuik(_coreAPIHttpService, school.id, setting, area, client, _dingDing, null);
  378. teacherTrains.AddRange(trains);
  379. schoolInfos.ForEach(y =>
  380. {
  381. var list = yxtrain.Find(z => z.school.Equals(y.schoolId));
  382. if (list != null)
  383. {
  384. y.trainCount = list.members.Count;
  385. }
  386. });
  387. if (updateTeacherTrains.IsNotEmpty())
  388. {
  389. updateTeach.AddRange(updateTeacherTrains.Select(z => z.id));
  390. msg.schools.Add(new TeacherTrainChangeMsgSchoolTeachers { school = school.id, teachers = updateTeacherTrains.Select(z => z.id).ToList() });
  391. }
  392. }));
  393. });
  394. await Task.WhenAll(tasks);
  395. bool isnew=false;
  396. if (msg.schools.IsNotEmpty())
  397. {
  398. var messageChange = new ServiceBusMessage(msg.ToJsonString());
  399. messageChange.ApplicationProperties.Add("name", "TeacherTrainChange");
  400. var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
  401. await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageChange);
  402. }
  403. else {
  404. isnew=true;
  405. }
  406. long totalTime = teacherTrains.Select(x => x.totalTime).Sum();
  407. int hgcount = teacherTrains.Where(x => x.finalScore == 1 || x.finalScore == 2).Count();
  408. setting.accessConfig = null;
  409. List<dynamic> dynamics = new List<dynamic>();
  410. teacherTrains.ForEach(x => {
  411. x.schoolName = schools.Find(s => s.id.Equals(x.school))?.name;
  412. x.currency.videoTime = (int)x.currency.videoTime;
  413. x.currency.teacherAilities.ForEach(y => {
  414. y.videoTime = (int)y.videoTime;
  415. y.onlineTime = (int)y.onlineTime;
  416. y.debateOrther = y.debateOrther > 0 ? y.debateOrther : 0;
  417. });
  418. dynamic dynamic = new
  419. {
  420. x.schoolName,
  421. x.classTime,
  422. x.finalScore,
  423. x.name,
  424. x.offlineTime,
  425. x.onlineTime,
  426. x.school,
  427. x.id,
  428. x.totalTime,
  429. currency = new
  430. {
  431. x.currency.submitTime,
  432. x.currency.exerciseAbility,
  433. x.currency.learnAbility,
  434. x.currency.uploadDone,
  435. x.currency.uploadTotal,
  436. x.currency.videoTime,
  437. teacherAilities = x.currency.teacherAilities.Select(t => new {
  438. t.onlineTime,
  439. t.videoTime,
  440. t.no,
  441. t.name,
  442. t.dimension,
  443. t.zpscore,
  444. t.xzscore,
  445. t.hpscore
  446. }),
  447. },
  448. offlineCountNo = x.offlineRecords.Where(o => o.upload == 0).Count(),
  449. offlineCountOk = x.offlineRecords.Where(o => o.upload == 1).Count(),
  450. teacherClasseCount = x.teacherClasses.Count
  451. };
  452. dynamics.Add(dynamic);
  453. });
  454. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  455. if (area.updateTime == 0 && isnew ) {
  456. area.updateTime = now ;
  457. }
  458. if (area.updateTime == 0 && !isnew)
  459. {
  460. area.updateTime = DateTimeOffset.UtcNow.Add(new TimeSpan(-1, 0, 0, 0)).ToUnixTimeMilliseconds();
  461. }
  462. //判断两个上次更新时间差
  463. if (area.updateTime > 0 && !isnew) {
  464. long timedis= 15 * 60 * 1000;//15分钟
  465. if (now - area.updateTime<timedis) {
  466. isnew= true;
  467. }
  468. }
  469. return Ok(new { teacherTrains = dynamics, setting, schools = schoolInfos, totalTime, hgcount, teacherCount = countArea, appraiseCount = appraiseArea, isnew ,area.updateTime, updateTeach });
  470. }
  471. catch (Exception ex)
  472. {
  473. await _dingDing.SendBotMsg($"OS,{_option.Location},StatisticsAreaQuick()\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  474. return BadRequest(new { ex.Message, ex.StackTrace });
  475. }
  476. }
  477. /// <summary>
  478. /// 区级数据统计
  479. /// </summary>
  480. /// <param name="request"></param>
  481. /// <returns></returns>
  482. [ProducesDefaultResponseType]
  483. [HttpPost("statistics-area")]
  484. [AuthToken(Roles = "teacher,admin,area")]
  485. [Authorize(Roles = "IES")]
  486. public async Task<IActionResult> StatisticsArea(JsonElement request)
  487. {
  488. var (userid, _, _, _) = HttpContext.GetAuthTokenInfo();
  489. request.TryGetProperty("standard", out JsonElement _standard);
  490. string standard = $"{_standard}";
  491. if (string.IsNullOrEmpty(standard))
  492. {
  493. return BadRequest();
  494. }
  495. var client = _azureCosmos.GetCosmosClient();
  496. Area area = null;
  497. string sql = $"select value(c) from c where c.standard='{standard}'";
  498. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Area>(queryText: sql,
  499. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-Area") }))
  500. {
  501. area = item;
  502. }
  503. AreaSetting setting = null;
  504. if (area != null)
  505. {
  506. try
  507. {
  508. setting = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<AreaSetting>(area.id, new PartitionKey("AreaSetting"));
  509. }
  510. catch (CosmosException)
  511. {
  512. setting = null;
  513. }
  514. }
  515. if (setting == null)
  516. {
  517. setting = new AreaSetting
  518. {
  519. allTime = 50,
  520. classTime = 5,
  521. submitTime = 15,
  522. onlineTime = 20,
  523. offlineTime = 10,
  524. lessonMinutes = 45,
  525. };
  526. }
  527. try
  528. {
  529. List<TeacherTrain> teacherTrains = new List<TeacherTrain>();
  530. List<School> schools = new List<School>();
  531. 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") }))
  532. {
  533. schools.Add(item);
  534. }
  535. List<Task<(List<TeacherTrain> trains, List<RGroupList> yxtrain)>> trains = new List<Task<(List<TeacherTrain> trains, List<RGroupList> yxtrain)>>();
  536. int countArea = 0;
  537. int appraiseArea = 0;
  538. List<SchoolInfos> schoolInfos = new List<SchoolInfos>();
  539. foreach (var school in schools)
  540. {
  541. int count = 0;
  542. int appraise = 0;
  543. 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}") }))
  544. {
  545. if (item)
  546. {
  547. appraise += 1;
  548. appraiseArea += 1;
  549. }
  550. countArea += 1;
  551. count += 1;
  552. }
  553. schoolInfos.Add(new SchoolInfos { schoolId = school.id, schoolName = school.name, picture = school.picture, teacherCount = count, appraiseCount = appraise });
  554. //增加评审人员总人数,学习总人数。
  555. trains.Add(StatisticsService.StatisticsSchool(_coreAPIHttpService, school.id, setting, area, client, _dingDing, null));
  556. }
  557. int pagesize = 100;
  558. if (trains.Count <= pagesize)
  559. {
  560. (List<TeacherTrain> trains, List<RGroupList> yxtrain)[] tasks = await Task.WhenAll(trains);
  561. tasks.ToList().ForEach(x => {
  562. teacherTrains.AddRange(x.trains);
  563. schoolInfos.ForEach(y => {
  564. var list = x.yxtrain.Find(z => z.school.Equals(y.schoolId));
  565. if (list != null)
  566. {
  567. y.trainCount = list.members.Count;
  568. }
  569. });
  570. });
  571. }
  572. else
  573. {
  574. int pages = (trains.Count + pagesize) / pagesize; //256是批量操作最大值,pages = (total + max -1) / max;
  575. for (int i = 0; i < pages; i++)
  576. {
  577. var listssb = trains.Skip((i) * pagesize).Take(pagesize).ToList();
  578. (List<TeacherTrain> trains, List<RGroupList> yxtrain)[] tasks = await Task.WhenAll(listssb);
  579. tasks.ToList().ForEach(x => {
  580. teacherTrains.AddRange(x.trains);
  581. schoolInfos.ForEach(y => {
  582. var list = x.yxtrain.Find(z => z.school.Equals(y.schoolId));
  583. if (list != null)
  584. {
  585. y.trainCount = list.members.Count;
  586. }
  587. });
  588. });
  589. }
  590. }
  591. long totalTime = teacherTrains.Select(x => x.totalTime).Sum();
  592. int hgcount = teacherTrains.Where(x => x.finalScore == 1 || x.finalScore == 2).Count();
  593. var teacherAilities = teacherTrains.SelectMany(x => x.currency.teacherAilities);
  594. setting.accessConfig = null;
  595. var table = _azureStorage.GetCloudTableClient().GetTableReference("ScYxpt");
  596. teacherTrains.ForEach(x => {
  597. x.currency.videoTime = (int)x.currency.videoTime;
  598. x.currency.teacherAilities.ForEach(y => {
  599. y.videoTime = (int)y.videoTime;
  600. y.onlineTime = (int)y.onlineTime;
  601. y.debateOrther = y.debateOrther > 0 ? y.debateOrther : 0;
  602. });
  603. });
  604. return Ok(new { teacherTrains, setting, schools = schoolInfos, totalTime, hgcount, teacherAilities, teacherCount = countArea, appraiseCount = appraiseArea });
  605. }
  606. catch (Exception ex)
  607. {
  608. await _dingDing.SendBotMsg($"OS,{_option.Location},UpsertSubmitScore/UpsertSubmitScore()\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  609. return BadRequest(new { ex.Message, ex.StackTrace });
  610. }
  611. }
  612. public class SchoolInfos
  613. {
  614. public string schoolId { get; set; }
  615. public string schoolName { get; set; }
  616. public string picture { get; set; }
  617. public int teacherCount { get; set; }
  618. public int appraiseCount { get; set; }
  619. public int trainCount { get; set; }
  620. }
  621. /// <summary>
  622. /// 校级数据统计
  623. /// </summary>
  624. /// <param name="request"></param>
  625. /// <returns></returns>
  626. [ProducesDefaultResponseType]
  627. [HttpPost("push-school-data")]
  628. //[AuthToken(Roles = "teacher,admin,area")]
  629. //[Authorize(Roles = "IES")]
  630. public async Task<IActionResult> SchoolDataPush(JsonElement request) {
  631. var client = _azureCosmos.GetCosmosClient();
  632. request.TryGetProperty("standard", out JsonElement standard);
  633. request.TryGetProperty("school", out JsonElement _school);
  634. request.TryGetProperty("pushTeachers", out JsonElement _pushTeachers);
  635. List<string> pushTeachers = _pushTeachers.ToObject<List<string>>();
  636. (string accessConfig, Area area, AreaSetting setting) = await ThirdService.GetAccessConfig(client, $"{standard}");
  637. School school= await client.GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>($"{_school}",new PartitionKey("Base"));
  638. if (setting.id.Equals($"{school.areaId}"))
  639. {
  640. string json = await ThirdService.SchoolDataPush(setting, _scsStudyApisService, pushTeachers, _option, $"{_school}");
  641. if (!string.IsNullOrWhiteSpace(json)) {
  642. JsonElement element = json.ToObject<JsonElement>();
  643. return Ok(new { element });
  644. }
  645. }
  646. else {
  647. return BadRequest("学校不属于该区");
  648. }
  649. return Ok(pushTeachers);
  650. }
  651. /// <summary>
  652. /// 校级数据统计
  653. /// </summary>
  654. /// <param name="request"></param>
  655. /// <returns></returns>
  656. [ProducesDefaultResponseType]
  657. [HttpPost("get-school-appraise")]
  658. #if !DEBUG
  659. [AuthToken(Roles = "teacher,admin,area")]
  660. [Authorize(Roles = "IES")]
  661. #endif
  662. public async Task<IActionResult> GetSchoolAppraise(JsonElement request)
  663. {
  664. request.TryGetProperty("school", out JsonElement _school);
  665. string school = "";
  666. var (userid, _, _, __school) = HttpContext.GetAuthTokenInfo();
  667. if (!string.IsNullOrEmpty($"{_school}"))
  668. {
  669. school = $"{_school}";
  670. }
  671. else
  672. {
  673. school = __school;
  674. }
  675. request.TryGetProperty("update", out JsonElement _update);
  676. HashSet<string> update = null;
  677. if (_update.ValueKind.Equals(JsonValueKind.Array))
  678. {
  679. update = _update.ToObject<HashSet<string>>();
  680. }
  681. string standard = "";
  682. if (HttpContext.Items.TryGetValue("Standard", out object _standard))
  683. {
  684. standard = $"{_standard}";
  685. }
  686. else {
  687. request.TryGetProperty("standard", out JsonElement _standardParmas);
  688. standard = $"{_standardParmas}";
  689. }
  690. var client = _azureCosmos.GetCosmosClient();
  691. Area area = null;
  692. string sql = $"select value(c) from c where c.standard='{standard}'";
  693. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Area>(queryText: sql,
  694. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-Area") }))
  695. {
  696. area = item;
  697. }
  698. AreaSetting setting = null;
  699. if (area != null)
  700. {
  701. try
  702. {
  703. //优先找校级
  704. setting = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<AreaSetting>(school, new PartitionKey("AreaSetting"));
  705. }
  706. catch (CosmosException)
  707. {
  708. try
  709. {
  710. setting = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<AreaSetting>(area.id, new PartitionKey("AreaSetting"));
  711. }
  712. catch (CosmosException)
  713. {
  714. setting = null;
  715. }
  716. }
  717. }
  718. if (setting == null)
  719. {
  720. setting = new AreaSetting
  721. {
  722. allTime = 50,
  723. classTime = 5,
  724. submitTime = 15,
  725. onlineTime = 20,
  726. offlineTime = 10,
  727. lessonMinutes = 45,
  728. };
  729. }
  730. try
  731. {
  732. int count = 0;
  733. int appraise = 0;
  734. 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}") }))
  735. {
  736. if (item)
  737. {
  738. appraise += 1;
  739. }
  740. count += 1;
  741. }
  742. //增加评审人员总人数,学习总人数。
  743. (List<TeacherTrain> teacherTrains, List<RGroupList> yxtrain) = await StatisticsService.StatisticsSchool(_coreAPIHttpService, school, setting, area, client, _dingDing, update);
  744. var table = _azureStorage.GetCloudTableClient().GetTableReference("ScYxpt");
  745. teacherTrains.ForEach(x => {
  746. x.currency.videoTime = (int)x.currency.videoTime;
  747. x.currency.teacherAilities.ForEach(y => {
  748. y.videoTime = (int)y.videoTime;
  749. y.onlineTime = (int)y.onlineTime;
  750. y.debateOrther= y.debateOrther>0? y.debateOrther: 0;
  751. });
  752. });
  753. //try
  754. //{
  755. // teacherTrain = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<TeacherTrain>(userid, new PartitionKey($"TeacherTrain-{school}"));
  756. //}
  757. //catch (CosmosException)
  758. //{
  759. // await client.GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync<TeacherTrain>(teacherTrain, new PartitionKey($"TeacherTrain-{school}"));
  760. //}
  761. setting.accessConfig = null;
  762. return Ok(new { teacherTrains, setting, teacherCount = count, appraiseCount = appraise, yxtrain });
  763. }
  764. catch (Exception ex)
  765. {
  766. return BadRequest(new { ex.Message, ex.StackTrace });
  767. }
  768. }
  769. /// <summary>
  770. /// 教师个人数据统计
  771. /// </summary>
  772. /// <param name="request"></param>
  773. /// <returns></returns>
  774. [ProducesDefaultResponseType]
  775. [HttpPost("statistics-teacher")]
  776. [AuthToken(Roles = "teacher,admin,area")]
  777. [Authorize(Roles = "IES")]
  778. public async Task<IActionResult> StatisticsTeacher(JsonElement request)
  779. {
  780. //{"tmdid":"1595321354","school":"hbcn"}
  781. var (_userid, name, picture, school) = HttpContext.GetAuthTokenInfo();
  782. if (!HttpContext.Items.TryGetValue("Standard", out object standard)) return BadRequest();
  783. var client = _azureCosmos.GetCosmosClient();
  784. request.TryGetProperty("update", out JsonElement _update);
  785. HashSet<string> update = null;
  786. if (_update.ValueKind.Equals(JsonValueKind.Array))
  787. {
  788. update = _update.ToObject<HashSet<string>>();
  789. }
  790. request.TryGetProperty("tmdid", out JsonElement _tmdid);
  791. string tmdid = "";
  792. if (_tmdid.ValueKind.Equals(JsonValueKind.String))
  793. {
  794. tmdid = $"{_tmdid}";
  795. }
  796. else
  797. {
  798. tmdid = $"{_userid}";
  799. }
  800. Area area = null;
  801. string sql = $"select value(c) from c where c.standard='{standard}'";
  802. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Area>(queryText: sql,
  803. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-Area") }))
  804. {
  805. area = item;
  806. }
  807. AreaSetting setting = null;
  808. if (area != null)
  809. {
  810. try
  811. {
  812. //优先找校级
  813. setting = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<AreaSetting>(school, new PartitionKey("AreaSetting"));
  814. }
  815. catch (CosmosException)
  816. {
  817. try
  818. {
  819. setting = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<AreaSetting>(area.id, new PartitionKey("AreaSetting"));
  820. }
  821. catch (CosmosException)
  822. {
  823. setting = null;
  824. }
  825. }
  826. }
  827. if (setting == null)
  828. {
  829. setting = new AreaSetting
  830. {
  831. allTime = 50,
  832. classTime = 5,
  833. submitTime = 15,
  834. onlineTime = 20,
  835. offlineTime = 10,
  836. lessonMinutes = 45,
  837. };
  838. }
  839. try
  840. {
  841. TeacherTrain teacherTrain = null;
  842. try
  843. {
  844. teacherTrain = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<TeacherTrain>(tmdid, new PartitionKey($"TeacherTrain-{school}"));
  845. var table = _azureStorage.GetCloudTableClient().GetTableReference("ScYxpt");
  846. teacherTrain.nickname = name;
  847. teacherTrain.name = name;
  848. if (!string.IsNullOrWhiteSpace(setting.accessConfig))
  849. {
  850. List<ScTeacher> teachers = await table.FindListByDict<ScTeacher>(new Dictionary<string, object>() { { "PartitionKey", "ScTeacher" }, { "areaId", setting.id }, { "schoolCode", school }, { "tmdid", $"{_tmdid}" } });
  851. if (teachers.Any())
  852. {
  853. teacherTrain.name = teachers[0].TeacherName;
  854. }
  855. }
  856. teacherTrain.picture = picture;
  857. if (update != null && update.Count > 0)
  858. {
  859. foreach (var up in update)
  860. {
  861. teacherTrain.update.Add(up);
  862. }
  863. }
  864. ///强制教师个人信息统计的时候 都再去统计一次。
  865. teacherTrain.update.Add(StatisticsService.TeacherAbility);
  866. if (teacherTrain.update.Count > 0)
  867. {
  868. await StatisticsService.StatisticsTeacher(teacherTrain, setting, area, client, null);
  869. }
  870. }
  871. catch (CosmosException)
  872. {
  873. string tname = name;
  874. if (!string.IsNullOrWhiteSpace(setting.accessConfig)) {
  875. var table = _azureStorage.GetCloudTableClient().GetTableReference("ScYxpt");
  876. List<ScTeacher> teachers = await table.FindListByDict<ScTeacher>(new Dictionary<string, object>() { { "PartitionKey", "ScTeacher" }, { "areaId", setting.id }, { "schoolCode", school }, { "tmdid", $"{_tmdid}" } });
  877. if (teachers.Any())
  878. {
  879. tname = teachers[0].TeacherName;
  880. }
  881. }
  882. teacherTrain = await StatisticsService.StatisticsTeacher(new TeacherTrain
  883. {
  884. pk = "TeacherTrain",
  885. id = tmdid,
  886. code = $"TeacherTrain-{school}",
  887. tmdid = tmdid,
  888. nickname= name,
  889. school = school,
  890. name = tname,
  891. picture = picture,
  892. update = new HashSet<string> { StatisticsService.TeacherAbility,
  893. StatisticsService.TeacherClass, StatisticsService.OfflineRecord }
  894. }, setting, area, client, null);
  895. }
  896. setting.accessConfig = null;
  897. teacherTrain.currency.videoTime = (int)teacherTrain.currency.videoTime;
  898. teacherTrain.currency.teacherAilities.ForEach(y => {
  899. y.videoTime = (int)y.videoTime;
  900. y.onlineTime = (int)y.onlineTime;
  901. y.debateOrther = y.debateOrther > 0 ? y.debateOrther : 0;
  902. });
  903. return Ok(new { teacherTrain, setting });
  904. }
  905. catch (Exception ex)
  906. {
  907. return BadRequest(new { ex.Message, ex.StackTrace });
  908. }
  909. }
  910. }
  911. }