LessonService.cs 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965
  1. using Azure.Core;
  2. using Azure.Cosmos;
  3. using Azure.Messaging.ServiceBus;
  4. using HTEXLib.COMM.Helpers;
  5. using Microsoft.Extensions.Configuration;
  6. using Microsoft.Extensions.Hosting;
  7. using OpenXmlPowerTools;
  8. using StackExchange.Redis;
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Linq;
  12. using System.Text;
  13. using System.Text.Json;
  14. using System.Threading.Tasks;
  15. using TEAMModelOS.SDK.DI;
  16. using TEAMModelOS.SDK.DI.CoreAPI;
  17. using TEAMModelOS.SDK.Extension;
  18. using TEAMModelOS.SDK.Helper.Common.DateTimeHelper;
  19. using TEAMModelOS.SDK.Models.Cosmos.Common;
  20. namespace TEAMModelOS.SDK.Models.Service
  21. {
  22. public class LessonService
  23. {
  24. public static readonly DateTime dateTime1970 = new DateTime(1970, 1, 1).ToLocalTime();
  25. public static Dictionary<string, object> GetLessonCond(JsonElement request)
  26. {
  27. Dictionary<string, object> dict = new Dictionary<string, object>();
  28. if (request.TryGetProperty("tmdid", out JsonElement tmdid) && !string.IsNullOrWhiteSpace($"{tmdid}"))
  29. {
  30. dict.Add("tmdid", tmdid);
  31. }
  32. if (request.TryGetProperty("courseId", out JsonElement courseId) && !string.IsNullOrWhiteSpace($"{courseId}"))
  33. {
  34. dict.Add("courseId", courseId);
  35. }
  36. if (request.TryGetProperty("courseIds", out JsonElement courseIds))
  37. {
  38. dict.Add("courseId[*]", courseIds);
  39. }
  40. if (request.TryGetProperty("periodId", out JsonElement periodId) && !string.IsNullOrWhiteSpace($"{periodId}"))
  41. {
  42. dict.Add("periodId", periodId);
  43. }
  44. if (request.TryGetProperty("subjectId", out JsonElement subjectId))
  45. {
  46. dict.Add("subjectId", subjectId);
  47. }
  48. if (request.TryGetProperty("groupIds", out JsonElement groupIds))
  49. {
  50. dict.Add("groupIds[*]", groupIds);
  51. }
  52. if (request.TryGetProperty("grade", out JsonElement grade))
  53. {
  54. dict.Add("grade[*]", grade);
  55. }
  56. if (request.TryGetProperty("category", out JsonElement category))
  57. {
  58. dict.Add("category[*]", category);
  59. }
  60. if (request.TryGetProperty("doubleGreen", out JsonElement doubleGreen) && doubleGreen.GetBoolean())
  61. {
  62. dict.Add("=.tLevel", 2);
  63. dict.Add("=.pLevel", 2);
  64. //dict.Add(">=.tScore", 70);
  65. //dict.Add(">=.pScore", 70);
  66. }
  67. if (request.TryGetProperty("doubleRed", out JsonElement doubleRed) && doubleRed.GetBoolean())
  68. {
  69. dict.Add("=.tLevel", 0);
  70. dict.Add("=.pLevel", 0);
  71. //dict.Add(">=.tScore", 70);
  72. //dict.Add(">=.pScore", 70);
  73. }
  74. if (request.TryGetProperty("quality", out JsonElement quality) && quality.GetBoolean())
  75. {
  76. dict.Add(">=.discuss", 1);
  77. }
  78. if (request.TryGetProperty("excellent", out JsonElement excellent) && excellent.GetBoolean())
  79. {
  80. dict.Add(">=.excellent", 1);
  81. }
  82. if (request.TryGetProperty("name", out JsonElement name) && !string.IsNullOrWhiteSpace($"{name}"))
  83. {
  84. dict.Add("$.name", name);
  85. }
  86. if (request.TryGetProperty("today", out JsonElement today) && today.GetBoolean())
  87. {
  88. DateTime dateTimeA = Convert.ToDateTime(DateTimeOffset.UtcNow.ToString("D"));
  89. DateTime dateTimeB = Convert.ToDateTime(DateTimeOffset.UtcNow.ToString("D")).AddDays(1);
  90. double dayOf00_00_00 = (dateTimeA - dateTime1970).TotalMilliseconds;
  91. double day1Of00_00_00 = (dateTimeB - dateTime1970).TotalMilliseconds;
  92. dict.Add(">=.startTime", dayOf00_00_00);
  93. dict.Add("<.startTime", day1Of00_00_00);
  94. }
  95. if (request.TryGetProperty("week", out JsonElement week) && week.GetBoolean())
  96. {
  97. // DateTime dateTimeA = Convert.ToDateTime(DateTimeOffset.UtcNow.ToString("D"));
  98. DateTime dateTimeB = Convert.ToDateTime(DateTimeOffset.UtcNow.ToString("D")).AddDays(-7);
  99. double now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  100. double dayB = (dateTimeB - dateTime1970).TotalMilliseconds;
  101. dict.Add("<=.startTime", now);
  102. dict.Add(">=.startTime", dayB);
  103. }
  104. //查询即将到期的且没有被清理的。
  105. if (request.TryGetProperty("expire", out JsonElement expire) && expire.ValueKind.Equals(JsonValueKind.True))
  106. {
  107. dict.Add(">.expire", 0);
  108. dict.Add("!=.status", 404);
  109. }
  110. //查询已经清理的
  111. if (request.TryGetProperty("is404", out JsonElement is404) && is404.ValueKind.Equals(JsonValueKind.True))
  112. {
  113. dict.Add("=.status", 404);
  114. }
  115. //只查有效的
  116. if (request.TryGetProperty("isOk", out JsonElement isOk) && isOk.ValueKind.Equals(JsonValueKind.True))
  117. {
  118. dict.Add("<=.expire", 0);
  119. dict.Add("!=.status", 404);
  120. }
  121. if (request.TryGetProperty("month", out JsonElement month) && month.GetBoolean())
  122. {
  123. //DateTime dateTimeA = Convert.ToDateTime(DateTimeOffset.UtcNow.ToString("D"));
  124. DateTime dateTimeB = Convert.ToDateTime(DateTimeOffset.UtcNow.ToString("D")).AddDays(-30);
  125. double now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  126. double dayB = (dateTimeB - dateTime1970).TotalMilliseconds;
  127. dict.Add("<=.startTime", now);
  128. dict.Add(">=.startTime", dayB);
  129. }
  130. if (request.TryGetProperty("stime", out JsonElement stime) && !string.IsNullOrWhiteSpace($"{stime}"))
  131. {
  132. dict.Add(">=.startTime", stime);
  133. }
  134. if (request.TryGetProperty("etime", out JsonElement etime) && !string.IsNullOrWhiteSpace($"{etime}"))
  135. {
  136. dict.Add("<=.startTime", etime);
  137. }
  138. if (request.TryGetProperty("conds", out JsonElement conds) && conds.ValueKind.Equals(JsonValueKind.Array))
  139. {
  140. List<LessonSettingCond> settingConds = conds.Deserialize<List<LessonSettingCond>>();
  141. foreach (var item in settingConds)
  142. {
  143. dict.TryAdd($"{item.type}.{item.key}", item.val);
  144. //switch (item.type)
  145. //{
  146. // case ">=":
  147. // dict.TryAdd($">=.{item.key}",item.val);
  148. // break;
  149. // case "<=":
  150. // dict.TryAdd($"<=.{item.key}", item.val);
  151. // break;
  152. //}
  153. }
  154. }
  155. return dict;
  156. }
  157. public static async void DoLessonStudentRecord(DingDing _dingding, SnowflakeId snowflakeId, LessonRecord lessonRecord, string scope, CosmosClient client, string school, string tmdid,
  158. Teacher teacher, NotificationService _notificationService, AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, IConfiguration _configuration, LessonBase lessonBase)
  159. {
  160. try
  161. {
  162. int year = DateTimeOffset.UtcNow.Year;
  163. var clientSummaryList = lessonBase.report.clientSummaryList.Where(x => x.groupTaskCompleteCount != 0 || x.groupScore != 0 || x.score != 0 || x.tnteractScore != 0 || x.taskCompleteCount != 0);
  164. IEnumerable<LessonStudent> students = new List<LessonStudent>();
  165. if (clientSummaryList.Any())
  166. {
  167. students = lessonBase.student.Where(x => clientSummaryList.Select(x => x.seatID).Contains(x.seatID));
  168. }
  169. var stuids = students.Where(x => x.type == 2);
  170. if (stuids.Any())
  171. {
  172. stuids.ToList().ForEach(x => {
  173. x.school = string.IsNullOrWhiteSpace(x.school) ? school : x.school;
  174. });
  175. }
  176. var groups = stuids.Where(z => !string.IsNullOrWhiteSpace(z.school)).GroupBy(x => x.school).Select(y => new { code = y.Key, list = y.ToList() });
  177. List<StudentScoreRecord> lessonStudentRecords = new List<StudentScoreRecord>();
  178. foreach (var group in groups)
  179. {
  180. string stusql = $"select value(c) from c where c.stuid in({string.Join(",", group.list.Select(x => $"'{x.id}'"))}) and c.school='{group.code}' and c.year={year}";
  181. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Student).GetItemQueryIterator<StudentScoreRecord>(queryText: stusql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"StudentScoreRecord") }))
  182. {
  183. lessonStudentRecords.Add(item);
  184. }
  185. }
  186. var tmdids = students.Where(x => x.type == 1);
  187. if (tmdids.Any())
  188. {
  189. string tmdsql = $"select value(c) from c where c.tmdid in({string.Join(",", tmdids.Select(x => $"'{x}'"))}) and c.year={year}";
  190. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Student).GetItemQueryIterator<StudentScoreRecord>(queryText: tmdsql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"StudentScoreRecord") }))
  191. {
  192. lessonStudentRecords.Add(item);
  193. }
  194. }
  195. List<Task<ItemResponse<StudentScoreRecord>>> records = new List<Task<ItemResponse<StudentScoreRecord>>>();
  196. stuids.ToList().ForEach(x => {
  197. var record = lessonStudentRecords.Find(l => l.stuid.Equals(x.id) && l.code.Equals($"StudentScoreRecord") && l.school.Equals(x.school));
  198. ClientSummaryList clientSummaryList = lessonBase.report.clientSummaryList.Find(c => c.seatID == x.seatID);
  199. if (record != null)
  200. {
  201. if (clientSummaryList != null)
  202. {
  203. var hasrecord= record.lessonRecords.Find(x => x.lessonId.Equals(lessonRecord.id));
  204. if (hasrecord != null)
  205. {
  206. hasrecord.gscore = clientSummaryList.groupScore;
  207. hasrecord.pscore = clientSummaryList.score;
  208. hasrecord.tscore = clientSummaryList.tnteractScore;
  209. hasrecord.tmdid = teacher.id;
  210. hasrecord.school = school;
  211. hasrecord.scope = lessonRecord.scope;
  212. hasrecord.lessonId = lessonRecord.id;
  213. hasrecord.courseId = lessonRecord.courseId;
  214. hasrecord.periodId = lessonRecord.periodId;
  215. hasrecord.subjectId = lessonRecord.subjectId;
  216. hasrecord.time = lessonRecord.startTime;
  217. }
  218. else {
  219. record.lessonRecords.Add(
  220. new StudentLessonRecord
  221. {
  222. gscore = clientSummaryList.groupScore,
  223. pscore = clientSummaryList.score,
  224. tscore = clientSummaryList.tnteractScore,
  225. tmdid = teacher.id,
  226. school = school,
  227. scope = lessonRecord.scope,
  228. lessonId = lessonRecord.id,
  229. courseId = lessonRecord.courseId,
  230. periodId = lessonRecord.periodId,
  231. subjectId = lessonRecord.subjectId,
  232. time = lessonRecord.startTime
  233. }
  234. );
  235. }
  236. }
  237. }
  238. else
  239. {
  240. record = new StudentScoreRecord
  241. {
  242. userType = Constant.ScopeStudent,
  243. id = $"{snowflakeId.NextId()}",
  244. year = year,
  245. stuid = x.id,
  246. school = x.school,
  247. code = $"StudentScoreRecord",
  248. pk = "StudentScoreRecord",
  249. ttl = -1,
  250. lessonRecords = new List<StudentLessonRecord> { new StudentLessonRecord
  251. {
  252. gscore = clientSummaryList.groupScore,
  253. pscore = clientSummaryList.score,
  254. tscore = clientSummaryList.tnteractScore,
  255. tmdid = teacher.id,
  256. school = school,
  257. scope = lessonRecord.scope,
  258. lessonId = lessonRecord.id,
  259. courseId = lessonRecord.courseId,
  260. periodId = lessonRecord.periodId,
  261. subjectId = lessonRecord.subjectId,
  262. time= lessonRecord.startTime
  263. }}
  264. };
  265. }
  266. record.userType = Constant.ScopeStudent;
  267. record.gscore = record.lessonRecords.Select(x => x.gscore).Sum();
  268. record.pscore = record.lessonRecords.Select(x => x.pscore).Sum();
  269. record.tscore = record.lessonRecords.Select(x => x.tscore).Sum();
  270. records.Add(client.GetContainer(Constant.TEAMModelOS, Constant.Student).UpsertItemAsync(record, partitionKey: new PartitionKey(record.code)));
  271. });
  272. tmdids.ToList().ForEach(x => {
  273. var record = lessonStudentRecords.Find(l => l.tmdid.Equals(x.id) && l.code.Equals($"StudentScoreRecord"));
  274. ClientSummaryList clientSummaryList = lessonBase.report.clientSummaryList.Find(c => c.seatID == x.seatID);
  275. if (record != null)
  276. {
  277. if (clientSummaryList != null)
  278. {
  279. var hasrecord = record.lessonRecords.Find(x => x.lessonId.Equals(lessonRecord.id));
  280. if (hasrecord != null)
  281. {
  282. hasrecord.gscore = clientSummaryList.groupScore;
  283. hasrecord.pscore = clientSummaryList.score;
  284. hasrecord.tscore = clientSummaryList.tnteractScore;
  285. hasrecord.tmdid = teacher.id;
  286. hasrecord.school = school;
  287. hasrecord.scope = lessonRecord.scope;
  288. hasrecord.lessonId = lessonRecord.id;
  289. hasrecord.courseId = lessonRecord.courseId;
  290. hasrecord.periodId = lessonRecord.periodId;
  291. hasrecord.subjectId = lessonRecord.subjectId;
  292. hasrecord.time = lessonRecord.startTime;
  293. }
  294. else
  295. {
  296. record.lessonRecords.Add(
  297. new StudentLessonRecord
  298. {
  299. gscore = clientSummaryList.groupScore,
  300. pscore = clientSummaryList.score,
  301. tscore = clientSummaryList.tnteractScore,
  302. tmdid = teacher.id,
  303. school = school,
  304. scope = lessonRecord.scope,
  305. lessonId = lessonRecord.id,
  306. courseId = lessonRecord.courseId,
  307. periodId = lessonRecord.periodId,
  308. subjectId = lessonRecord.subjectId,
  309. time = lessonRecord.startTime
  310. }
  311. );
  312. }
  313. }
  314. }
  315. else
  316. {
  317. record = new StudentScoreRecord
  318. {
  319. userType = Constant.ScopeTmdUser,
  320. id = $"{snowflakeId.NextId()}",
  321. code = $"StudentScoreRecord",
  322. pk = "StudentScoreRecord",
  323. ttl = -1,
  324. year = year,
  325. tmdid = x.id,
  326. lessonRecords = new List<StudentLessonRecord>
  327. {
  328. new StudentLessonRecord
  329. {
  330. gscore = clientSummaryList.groupScore,
  331. pscore = clientSummaryList.score,
  332. tscore = clientSummaryList.tnteractScore,
  333. tmdid = teacher.id,
  334. school = school,
  335. scope = lessonRecord.scope,
  336. lessonId = lessonRecord.id,
  337. courseId = lessonRecord.courseId,
  338. periodId = lessonRecord.periodId,
  339. subjectId = lessonRecord.subjectId,
  340. time=lessonRecord.startTime
  341. }
  342. }
  343. };
  344. }
  345. record.userType = Constant.ScopeStudent;
  346. record.gscore = record.lessonRecords.Select(x => x.gscore).Sum();
  347. record.pscore = record.lessonRecords.Select(x => x.pscore).Sum();
  348. record.tscore = record.lessonRecords.Select(x => x.tscore).Sum();
  349. records.Add(client.GetContainer(Constant.TEAMModelOS, Constant.Student).UpsertItemAsync(record, partitionKey: new PartitionKey(record.code)));
  350. });
  351. if (records.Any())
  352. {
  353. await Task.WhenAll(records);
  354. }
  355. }
  356. catch (Exception ex)
  357. {
  358. await _dingding.SendBotMsg($"学生个人课例统计信息异常,{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  359. }
  360. }
  361. public static async void DoAutoDeleteSchoolLessonRecord(LessonRecord lessonRecord, string scope, CosmosClient client, string school, string tmdid,
  362. Teacher teacher, NotificationService _notificationService, AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, IConfiguration _configuration, CoreAPIHttpService _coreAPIHttpService,DingDing _dingDing,AzureRedisFactory _azureRedis)
  363. {
  364. if (lessonRecord.scope.Equals("school"))
  365. {
  366. SchoolSetting setting = null;
  367. Azure.Response schoolSetting = await client.GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemStreamAsync(school, new PartitionKey("SchoolSetting"));
  368. School schoolBase = await client.GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(school, new PartitionKey("Base"));
  369. if (schoolSetting.Status == 200)
  370. {
  371. setting = JsonDocument.Parse(schoolSetting.Content).RootElement.Deserialize<SchoolSetting>();
  372. if (setting.lessonSetting != null)
  373. {
  374. if (setting.lessonSetting.openAutoClean != 0 && setting.lessonSetting.openAutoClean != 1)
  375. {
  376. setting.lessonSetting.openAutoClean = 0;
  377. setting.lessonSetting.expireDays = Constant.school_lesson_expire;
  378. }
  379. }
  380. else
  381. {
  382. setting.lessonSetting = new LessonSetting() { openAutoClean = 0, expireDays = Constant.school_lesson_expire };
  383. }
  384. }
  385. else
  386. {
  387. setting = new SchoolSetting() { lessonSetting = new LessonSetting { openAutoClean = 0, expireDays = Constant.school_lesson_expire } };
  388. }
  389. int school_lesson_expire = 0;
  390. bool save = true;
  391. List<string> msg = new List<string>();
  392. if (setting.lessonSetting.openAutoClean == 1)
  393. {
  394. if (setting.lessonSetting.conds.IsEmpty())
  395. {
  396. save = false;
  397. }
  398. else
  399. {
  400. school_lesson_expire = setting.lessonSetting.expireDays;
  401. foreach (var item in setting.lessonSetting.conds)
  402. {
  403. switch (item.type)
  404. {
  405. case ">=":
  406. switch (item.key)
  407. {
  408. case "attendRate":
  409. if (!(lessonRecord.attendRate >= item.val))
  410. {
  411. save = false;
  412. msg.Add($"{item.key}:{lessonRecord.attendRate}{item.type}{item.val}");
  413. }
  414. break;
  415. case "groupCount":
  416. if (!(lessonRecord.groupCount >= item.val))
  417. {
  418. save = false;
  419. msg.Add($"{item.key}:{lessonRecord.groupCount}{item.type}{item.val}");
  420. }
  421. break;
  422. case "totalPoint":
  423. if (!(lessonRecord.totalPoint >= item.val))
  424. {
  425. save = false;
  426. msg.Add($"{item.key}:{lessonRecord.totalPoint}{item.type}{item.val}");
  427. }
  428. break;
  429. case "collateTaskCount":
  430. if (!(lessonRecord.collateTaskCount >= item.val))
  431. {
  432. save = false;
  433. msg.Add($"{item.key}:{lessonRecord.collateTaskCount}{item.type}{item.val}");
  434. }
  435. break;
  436. case "collateCount":
  437. if (!(lessonRecord.collateCount >= item.val))
  438. {
  439. save = false;
  440. msg.Add($"{item.key}:{lessonRecord.collateCount}{item.type}{item.val}");
  441. }
  442. break;
  443. case "pushCount":
  444. if (!(lessonRecord.pushCount >= item.val))
  445. {
  446. save = false;
  447. msg.Add($"{item.key}:{lessonRecord.pushCount}{item.type}{item.val}");
  448. }
  449. break;
  450. case "totalInteractPoint":
  451. if (!(lessonRecord.totalInteractPoint >= item.val))
  452. {
  453. save = false;
  454. msg.Add($"{item.key}:{lessonRecord.totalInteractPoint}{item.type}{item.val}");
  455. }
  456. break;
  457. case "interactionCount":
  458. if (!(lessonRecord.interactionCount >= item.val))
  459. {
  460. save = false;
  461. msg.Add($"{item.key}:{lessonRecord.interactionCount}{item.type}{item.val}");
  462. }
  463. break;
  464. case "clientInteractionCount":
  465. if (!(lessonRecord.clientInteractionCount >= item.val))
  466. {
  467. save = false;
  468. msg.Add($"{item.key}:{lessonRecord.clientInteractionCount}{item.type}{item.val}");
  469. }
  470. break;
  471. case "examQuizCount":
  472. if (!(lessonRecord.examQuizCount >= item.val))
  473. {
  474. save = false;
  475. msg.Add($"{item.key}:{lessonRecord.examQuizCount}{item.type}{item.val}");
  476. }
  477. break;
  478. case "examPointRate":
  479. if (!(lessonRecord.examPointRate >= item.val))
  480. {
  481. save = false;
  482. msg.Add($"{item.key}:{lessonRecord.examPointRate}{item.type}{item.val}");
  483. }
  484. break;
  485. }
  486. break;
  487. case "<=":
  488. switch (item.key)
  489. {
  490. case "attendRate":
  491. if (!(lessonRecord.attendRate <= item.val))
  492. {
  493. save = false;
  494. msg.Add($"{item.key}:{lessonRecord.attendRate}{item.type}{item.val}");
  495. }
  496. break;
  497. case "groupCount":
  498. if (!(lessonRecord.groupCount <= item.val))
  499. {
  500. save = false;
  501. msg.Add($"{item.key}:{lessonRecord.groupCount}{item.type}{item.val}");
  502. }
  503. break;
  504. case "totalPoint":
  505. if (!(lessonRecord.totalPoint <= item.val))
  506. {
  507. save = false;
  508. msg.Add($"{item.key}:{lessonRecord.totalPoint}{item.type}{item.val}");
  509. }
  510. break;
  511. case "collateTaskCount":
  512. if (!(lessonRecord.collateTaskCount <= item.val))
  513. {
  514. save = false;
  515. msg.Add($"{item.key}:{lessonRecord.collateTaskCount}{item.type}{item.val}");
  516. }
  517. break;
  518. case "collateCount":
  519. if (!(lessonRecord.collateCount <= item.val))
  520. {
  521. save = false;
  522. msg.Add($"{item.key}:{lessonRecord.collateCount}{item.type}{item.val}");
  523. }
  524. break;
  525. case "pushCount":
  526. if (!(lessonRecord.pushCount <= item.val))
  527. {
  528. save = false;
  529. msg.Add($"{item.key}:{lessonRecord.pushCount}{item.type}{item.val}");
  530. }
  531. break;
  532. case "totalInteractPoint":
  533. if (!(lessonRecord.totalInteractPoint <= item.val))
  534. {
  535. save = false;
  536. msg.Add($"{item.key}:{lessonRecord.totalInteractPoint}{item.type}{item.val}");
  537. }
  538. break;
  539. case "interactionCount":
  540. if (!(lessonRecord.interactionCount <= item.val))
  541. {
  542. save = false;
  543. msg.Add($"{item.key}:{lessonRecord.interactionCount}{item.type}{item.val}");
  544. }
  545. break;
  546. case "clientInteractionCount":
  547. if (!(lessonRecord.clientInteractionCount <= item.val))
  548. {
  549. save = false;
  550. msg.Add($"{item.key}:{lessonRecord.clientInteractionCount}{item.type}{item.val}");
  551. }
  552. break;
  553. case "examQuizCount":
  554. if (!(lessonRecord.examQuizCount <= item.val))
  555. {
  556. save = false;
  557. msg.Add($"{item.key}:{lessonRecord.examQuizCount}{item.type}{item.val}");
  558. }
  559. break;
  560. case "examPointRate":
  561. if (!(lessonRecord.examPointRate <= item.val))
  562. {
  563. save = false;
  564. msg.Add($"{item.key}:{lessonRecord.examPointRate}{item.type}{item.val}");
  565. }
  566. break;
  567. }
  568. break;
  569. }
  570. }
  571. }
  572. }
  573. else
  574. {
  575. ///未设置openAutoClean=1时,则检查学校使用空间是否充足。
  576. var sbm = new List<ServiceBusMessage>();
  577. double usize = 0;
  578. int tsize = schoolBase.tsize;
  579. //schoolBase.tsize
  580. //計算學校或個人的使用空間
  581. RedisValue redisValue = _azureRedis.GetRedisClient(8).HashGet($"Blob:Record", $"{schoolBase.id}");
  582. if (redisValue.HasValue && long.TryParse(redisValue.ToString(), out var bsize))
  583. {
  584. usize = Math.Round(bsize / 1073741824.0 - (tsize), 2, MidpointRounding.AwayFromZero); //1073741824 1G
  585. }
  586. else //如果檢測不到緩存,觸發刷新計算空間
  587. {
  588. var messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "update", name = $"{schoolBase.id}" }.ToJsonString()); ;
  589. messageBlob.ApplicationProperties.Add("name", "BlobRoot");
  590. sbm.Add(messageBlob);
  591. await _serviceBus.GetServiceBusClient().SendBatchMessageAsync(_configuration.GetValue<string>("Azure:ServiceBus:ActiveTask"), sbm);
  592. }
  593. ///空间充足的情况保存。
  594. if (schoolBase.size - usize > 0)
  595. {
  596. save = true;
  597. }
  598. else {
  599. save = false;
  600. school_lesson_expire = Constant.school_lesson_expire;
  601. }
  602. }
  603. if (!save && school_lesson_expire > 0)
  604. {
  605. // 1-时间戳,7-时间戳
  606. Dictionary<int, ExpireTag> result = new Dictionary<int, ExpireTag>();
  607. //暂定7天
  608. var now = DateTimeOffset.UtcNow;
  609. //剩余3天的通知
  610. //var day3= now.AddDays(school_lesson_expire - 3).ToUnixTimeMilliseconds();
  611. //result.Add(3, day3);
  612. //剩余1天的通知
  613. var day1 = now.AddDays(school_lesson_expire - (school_lesson_expire - 1)).ToUnixTimeMilliseconds();
  614. result.Add(1, new ExpireTag { expire = day1, tag = "notification" });
  615. //到期通知
  616. //不到五点上传的课例,七天之后直接删除。
  617. int addSecond = 0;
  618. if (now.Hour > 5)
  619. {
  620. // 到凌晨00点还差 (24 - now.Hour) *60 * 60 分钟,再加天数;
  621. addSecond = school_lesson_expire * 86400 + (24 - now.Hour) * 3600 - (now.Hour * 3600);
  622. //再加 00到05小时内的 随机秒数
  623. Random rand = new Random();
  624. int randInt = rand.Next(0, 18000);
  625. addSecond += randInt;
  626. }
  627. else
  628. {
  629. addSecond = school_lesson_expire * 24 * 60 * 60;
  630. }
  631. lessonRecord.expire = now.AddSeconds(addSecond).ToUnixTimeMilliseconds();
  632. result.Add(school_lesson_expire, new ExpireTag { expire = lessonRecord.expire, tag = "delete" });
  633. // result.Add(school_lesson_expire, lessonRecord.expire);
  634. string biz = "expire";
  635. Notification notification = new Notification
  636. {
  637. hubName = "hita",
  638. type = "msg",
  639. from = $"ies5:{Environment.GetEnvironmentVariable("Option:Location")}:private",
  640. to = new List<string> { tmdid },
  641. label = $"{biz}_lessonRecord",
  642. body = new
  643. {
  644. location = $"{Environment.GetEnvironmentVariable("Option:Location")}",
  645. biz = biz,
  646. tmdid = tmdid,
  647. tmdname = teacher.name,
  648. scope = scope,
  649. school = school,
  650. schoolName = schoolBase.name,
  651. sid = lessonRecord.id,
  652. sname = lessonRecord.name,
  653. stime = lessonRecord.startTime,
  654. expire = lessonRecord.expire,
  655. status = 1,
  656. //day = school_lesson_expire,
  657. time = now
  658. }.ToJsonString(),
  659. expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
  660. };
  661. var url = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
  662. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  663. var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
  664. var location = $"{Environment.GetEnvironmentVariable("Option:Location")}";
  665. await _notificationService.SendNotification(clientID, clientSecret, location, url, notification); //站内发送消息
  666. string expireTime = DateTimeOffset.FromUnixTimeMilliseconds(lessonRecord.expire).ToString("yyyy-MM-dd HH:mm:ss");
  667. Teacher targetTeacher = await client.GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemAsync<Teacher>($"{tmdid}", new PartitionKey($"Base"));
  668. _coreAPIHttpService.PushNotify(new List<IdNameCode> { new IdNameCode { id = targetTeacher.id, name = targetTeacher.name, code = targetTeacher.lang } }, "expire-school_lessonRecord", Constant.NotifyType_IES5_Course,
  669. new Dictionary<string, object> { { "tmdid", teacher.id }, { "tmdname", teacher.name }, { "schoolName", schoolBase.name },
  670. { "schoolId", $"{school}" },{ "lessonId",lessonRecord.id }, { "expireTime", expireTime },{ "lessonName",lessonRecord.name } }, $"{Environment.GetEnvironmentVariable("Option:Location")}", _configuration, _dingDing, "");
  671. var table = _azureStorage.GetCloudTableClient().GetTableReference("ChangeRecord");
  672. List<ChangeRecord> records = await table.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", lessonRecord.id } });
  673. if (records.Count <= 0)
  674. {
  675. foreach (var item in result)
  676. {
  677. string PartitionKey = string.Format("{0}{1}{2}", lessonRecord.code, "-", $"expire-{item.Key}");
  678. //课堂的id ,
  679. //课堂的通知时间类型progress, 默认就会发送一条,到期前一天发送一条,最后已到期发送一条。
  680. var message = new ServiceBusMessage(new
  681. {
  682. id = lessonRecord.id,
  683. progress = item.Key,
  684. code = lessonRecord.code,
  685. scope = lessonRecord.scope,
  686. school = lessonRecord.school,
  687. opt = "delete",
  688. expire = lessonRecord.expire,
  689. tmdid = tmdid,
  690. tmdname = teacher.name,
  691. name = lessonRecord.name,
  692. startTime = lessonRecord.startTime,
  693. tag = item.Value.tag
  694. }.ToJsonString());
  695. message.ApplicationProperties.Add("name", "LessonRecordExpire");
  696. long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), message, DateTimeOffset.FromUnixTimeMilliseconds(item.Value.expire));
  697. ChangeRecord changeRecord = new ChangeRecord
  698. {
  699. RowKey = lessonRecord.id,
  700. PartitionKey = PartitionKey,
  701. sequenceNumber = start,
  702. msgId = message.MessageId
  703. };
  704. await table.Save<ChangeRecord>(changeRecord);
  705. }
  706. }
  707. }
  708. else
  709. {
  710. if (lessonRecord.expire > 0)
  711. {
  712. var table = _azureStorage.GetCloudTableClient().GetTableReference("ChangeRecord");
  713. List<ChangeRecord> records = await table.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", lessonRecord.id } });
  714. foreach (var record in records)
  715. {
  716. try
  717. {
  718. await table.DeleteSingle<ChangeRecord>(record.PartitionKey, record.RowKey);
  719. await _serviceBus.GetServiceBusClient().CancelMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), record.sequenceNumber);
  720. }
  721. catch (Exception)
  722. {
  723. continue;
  724. }
  725. }
  726. }
  727. lessonRecord.save = 1;
  728. lessonRecord.expire = -1;
  729. }
  730. }
  731. }
  732. public record ExpireTag
  733. {
  734. public long expire { get; set; }
  735. public string tag { get; set; }
  736. }
  737. /// <summary>
  738. ///
  739. /// </summary>
  740. /// <param name="client"></param>
  741. /// <param name="_dingDing"></param>
  742. /// <param name="data"></param>
  743. /// <returns></returns>
  744. public static LessonDis DisLessonCount(LessonRecord oldRecord, LessonRecord newRecord, LessonDis lessonDis)
  745. {
  746. //创建课堂的情况
  747. if (oldRecord == null && newRecord != null)
  748. {
  749. lessonDis.record = 1;
  750. }
  751. //删除数据的情况
  752. //不再对LessonCount进行减
  753. else if (oldRecord != null && newRecord == null)
  754. {
  755. /*lessonDis.record = -1;
  756. //P分数量加减
  757. if (oldRecord.pScore >= 70)
  758. {
  759. lessonDis.disPCount = -1;
  760. }
  761. //T分数量加减
  762. if (oldRecord.tScore >= 70)
  763. {
  764. lessonDis.disTCount = -1;
  765. }
  766. if (oldRecord.tScore >= 70 && oldRecord.pScore >= 70)
  767. {
  768. lessonDis.disTCount = -1;
  769. }*/
  770. }
  771. //无效操作
  772. else if (oldRecord == null && newRecord == null)
  773. {
  774. }
  775. //前后操作都有值,则表示更新
  776. else
  777. {
  778. //P分数量加减
  779. if (oldRecord.pScore >= 70)
  780. {
  781. if (newRecord.pScore < 70)
  782. {
  783. lessonDis.disPCount = -1;
  784. }
  785. }
  786. else
  787. {
  788. if (newRecord.pScore >= 70)
  789. {
  790. lessonDis.disPCount = 1;
  791. }
  792. }
  793. //T分数量加减
  794. if (oldRecord.tScore >= 70)
  795. {
  796. if (newRecord.tScore < 70)
  797. {
  798. lessonDis.disTCount = -1;
  799. }
  800. }
  801. else
  802. {
  803. if (newRecord.tScore >= 70)
  804. {
  805. lessonDis.disTCount = 1;
  806. }
  807. }
  808. //双绿灯数量
  809. if (oldRecord.tScore >= 70 && oldRecord.pScore >= 70)
  810. {
  811. if (newRecord.tScore < 70 || newRecord.pScore < 70)
  812. {
  813. lessonDis.disDCount = -1;
  814. }
  815. }
  816. else
  817. {
  818. if (newRecord.tScore >= 70 && newRecord.pScore >= 70)
  819. {
  820. lessonDis.disDCount = 1;
  821. }
  822. }
  823. }
  824. return lessonDis;
  825. }
  826. public static LessonDis DisLessonCount_2(LessonRecord oldRecord, LessonRecord newRecord, LessonDis lessonDis)
  827. {
  828. //创建课堂的情况
  829. if (oldRecord == null && newRecord != null)
  830. {
  831. lessonDis.record = 1;
  832. //P分数量加减
  833. if (newRecord.pScore >= 70)
  834. {
  835. lessonDis.disPCount = 1;
  836. }
  837. //T分数量加减
  838. if (newRecord.tScore >= 70)
  839. {
  840. lessonDis.disTCount = 1;
  841. }
  842. //双绿灯数量
  843. if (newRecord.tScore >= 70 && newRecord.pScore >= 70)
  844. {
  845. lessonDis.disDCount = 1;
  846. }
  847. }
  848. return lessonDis;
  849. }
  850. public static async Task FixLessonCount(CosmosClient client, DingDing _dingDing, LessonRecord record, LessonRecord oldRecord, LessonDis lessonDis)
  851. {
  852. LessonRecord data = null;
  853. try
  854. {
  855. if (record != null && oldRecord == null)
  856. {
  857. data = record;
  858. }
  859. if (record == null && oldRecord != null)
  860. {
  861. data = oldRecord;
  862. }
  863. if (record != null && oldRecord != null)
  864. {
  865. data = record;
  866. }
  867. int day = DateTimeOffset.FromUnixTimeMilliseconds(data.startTime).DayOfYear;
  868. int year = DateTimeOffset.FromUnixTimeMilliseconds(data.startTime).Year;
  869. int days = DateTimeHelper.getDays(year);
  870. //int years = DateTimeOffset.UtcNow.DayOfYear;
  871. string tbname = string.Empty;
  872. string code = string.Empty;
  873. if (data.scope != null && data.scope.Equals("school"))
  874. {
  875. if (string.IsNullOrEmpty(data.periodId))
  876. {
  877. code = $"LessonCount-{data.school}-{year}";
  878. tbname = "School";
  879. }
  880. else
  881. {
  882. code = $"LessonCount-{data.school}-{year}-{data.periodId}";
  883. tbname = "School";
  884. }
  885. }
  886. else
  887. {
  888. code = $"LessonCount-{year}";
  889. tbname = "Teacher";
  890. }
  891. var response = await client.GetContainer(Constant.TEAMModelOS, tbname).ReadItemStreamAsync(data.tmdid.ToString(), new PartitionKey(code));
  892. if (response.Status == 200)
  893. {
  894. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  895. LessonCount count = json.ToObject<LessonCount>();
  896. count.tCount[day - 1] += lessonDis.disTCount;
  897. count.pCount[day - 1] += lessonDis.disPCount;
  898. count.ptCount[day - 1] += lessonDis.disDCount;
  899. count.beginCount[day - 1] += lessonDis.record;
  900. await client.GetContainer("TEAMModelOS", tbname).ReplaceItemAsync(count, count.id, new PartitionKey(code));
  901. }
  902. else
  903. {
  904. LessonCount count = new()
  905. {
  906. id = data.tmdid,
  907. code = code,
  908. ttl = -1
  909. };
  910. double[] da = new double[days];
  911. List<double> list = new(da);
  912. List<double> listT = new(da);
  913. List<double> listP = new(da);
  914. List<double> listPT = new(da);
  915. list[day - 1] += lessonDis.record;
  916. listT[day - 1] += lessonDis.disTCount;
  917. listP[day - 1] += lessonDis.disPCount;
  918. listPT[day - 1] += lessonDis.disDCount;
  919. count.beginCount.AddRange(list);
  920. count.tCount.AddRange(listT);
  921. count.pCount.AddRange(listP);
  922. count.ptCount.AddRange(listPT);
  923. //count.courseIds.Add(data.courseId);
  924. await client.GetContainer("TEAMModelOS", tbname).CreateItemAsync(count, new PartitionKey(code));
  925. }
  926. }
  927. catch (Exception ex)
  928. {
  929. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-LessonCount-FixLessonCount\n{ex.Message}\n{ex.StackTrace}{data.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
  930. }
  931. }
  932. }
  933. }