OpenApiService.cs 126 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320
  1. using Azure;
  2. using Azure.Cosmos;
  3. using HTEXLib.COMM.Helpers;
  4. using Microsoft.AspNetCore.Http;
  5. using Microsoft.Azure.Cosmos.Table;
  6. using Microsoft.Azure.Functions.Worker.Http;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.IO;
  10. using System.Linq;
  11. using System.Net;
  12. using System.Net.Http;
  13. using System.Text;
  14. using System.Text.Json;
  15. using System.Threading.Tasks;
  16. using TEAMModelOS.Filter;
  17. using TEAMModelOS.SDK;
  18. using TEAMModelOS.SDK.DI;
  19. using TEAMModelOS.SDK.Extension;
  20. using TEAMModelOS.SDK.Models;
  21. using TEAMModelOS.SDK.Models.Table;
  22. using TEAMModelOS.SDK.Helper.Common.ReflectorExtensions;
  23. using TEAMModelOS.SDK.Context.Constant;
  24. using TEAMModelOS.SDK.Models.Dtos;
  25. using TEAMModelOS.SDK.Services;
  26. using Microsoft.Extensions.Configuration;
  27. using Azure.Messaging.ServiceBus;
  28. using TEAMModelOS.Models;
  29. using TEAMModelOS.SDK.Models.Service;
  30. using TEAMModelOS.SDK.Models.Cosmos.BI.BINormal;
  31. using TEAMModelOS.SDK.Models.Cosmos.Student;
  32. using Microsoft.OData.Edm;
  33. using System.IdentityModel.Tokens.Jwt;
  34. using TEAMModelOS.SDK.Models.Cosmos.OpenEntity;
  35. using Microsoft.OData.UriParser;
  36. using Azure.Core;
  37. using System.Security.Policy;
  38. using System.Net.Http.Json;
  39. using System.Drawing;
  40. using Microsoft.AspNetCore.DataProtection;
  41. using Newtonsoft.Json.Linq;
  42. using Microsoft.Extensions.Hosting;
  43. using Microsoft.AspNetCore.Hosting;
  44. using TEAMModelOS.Models.ShanDa;
  45. using System.Runtime.ConstrainedExecution;
  46. using DocumentFormat.OpenXml.Wordprocessing;
  47. using DocumentFormat.OpenXml.Office2010.Excel;
  48. namespace TEAMModelOS.SDK
  49. {
  50. public class OpenApiService
  51. {
  52. private static List<string> weekDays = new List<string> { "MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN" };
  53. /// <summary>
  54. /// 第三方获取学校列表
  55. /// [ApiToken(Auth = "1000", Name = "合作商获取可访问的学校列表",TName ="",EName ="", RWN = "R", Limit = false)]
  56. /// </summary>
  57. /// <param name="_azureCosmos"></param>
  58. /// <param name="_dingDing"></param>
  59. /// <param name="json"></param>
  60. /// <returns></returns>
  61. public static async Task<ResponseData<List<BizSchool>>> GetSchools(AzureCosmosFactory _azureCosmos, DingDing _dingDing, string bizId)
  62. {
  63. try
  64. {
  65. List<BizSchool> schools = new();
  66. var response = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Normal").ReadItemStreamAsync(bizId, new PartitionKey("BizConfig"));
  67. if (response.Status == 200)
  68. {
  69. using var resJson = await JsonDocument.ParseAsync(response.ContentStream);
  70. Business bizConfig = resJson.ToObject<Business>();
  71. schools = bizConfig.schools;
  72. }
  73. else return new ResponseData<List<BizSchool>>() { code = RespondCode.NotFound, msg = "未找到该企业" };
  74. return new ResponseData<List<BizSchool>>() { code = RespondCode.Ok, msg = "成功", data = schools };
  75. }
  76. catch (Exception ex)
  77. {
  78. await _dingDing.SendBotMsg($"OpenApi,{Environment.GetEnvironmentVariable("Option:Location")} OpenApiService/GetSchools() 参数:bizId:{bizId} \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  79. return new ResponseData<List<BizSchool>>() { code = RespondCode.Error, msg = "服务端异常" };
  80. }
  81. }
  82. /// <summary>
  83. /// josn:
  84. /// {
  85. /// "roles":"",
  86. /// "scope":""
  87. /// "pageCount":"",
  88. /// "DESC":"",
  89. /// "ASC":"",
  90. /// "continuationToken":"",
  91. /// "school":"",
  92. /// "tmdid":""
  93. /// }
  94. /// </summary>
  95. /// <param name="azureCosmos"></param>
  96. /// <param name="dingDing"></param>
  97. /// <param name="id"></param>
  98. /// <param name="school"></param>
  99. /// <param name="json"></param>
  100. /// <returns></returns>
  101. /// <exception cref="NotImplementedException"></exception>
  102. public static async Task<ResponseData<dynamic>> GetLessonRecordCount(AzureCosmosFactory _azureCosmos, IConfiguration _configuration, AzureServiceBusFactory _serviceBus,
  103. Option _option, DingDing _dingDing, string id, string school, JsonElement json)
  104. {
  105. json.TryGetProperty("identity", out JsonElement _identity);
  106. string identity = "";
  107. if (!string.IsNullOrWhiteSpace($"{_identity}"))
  108. {
  109. identity = $"{_identity}";
  110. }
  111. json.TryGetProperty("managePage", out JsonElement _managePage);
  112. bool managePage = false;
  113. if (_managePage.ValueKind.Equals(JsonValueKind.True))
  114. {
  115. managePage = true;
  116. }
  117. StringBuilder sql = new StringBuilder();
  118. sql.Append("select c.id,c.groupIds,c.courseId from c ");
  119. Dictionary<string, object> dict = LessonService.GetLessonCond(json);
  120. AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql);
  121. string tbname = "";
  122. string code = "";
  123. List<string> autoTch = new List<string>();
  124. string sqlPrivate = "";
  125. code = $"LessonRecord-{school}";
  126. tbname = "School";
  127. List<string> ids = new List<string>();
  128. //只查询某个老师的课例
  129. if (json.TryGetProperty("tmdid", out JsonElement tmdid) && !string.IsNullOrWhiteSpace($"{tmdid}"))
  130. {
  131. ids.Add($"{tmdid}");
  132. }
  133. else
  134. {
  135. string sqltch = "select distinct value(c.id) from c ";
  136. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
  137. .GetItemQueryIterator<string>(queryText: sqltch, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Teacher-{school}") }))
  138. {
  139. ids.Add(item);
  140. }
  141. }
  142. if (ids.Any())
  143. {
  144. string sqlTechbase = $"select distinct value(c.id) from c where c.id in ({string.Join(",", ids.Select(x => $"'{x}'"))}) and (array_contains(c.lessonShow,'student') or array_contains(c.lessonShow,'all')) ";
  145. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher)
  146. .GetItemQueryIterator<string>(queryText: sqlTechbase, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Base") }))
  147. {
  148. autoTch.Add(item);
  149. }
  150. }
  151. int count = 0;
  152. string sqlShow = "";
  153. if (identity.Equals("student"))
  154. {
  155. string autoSql = "";
  156. if (autoTch.Any())
  157. {
  158. autoSql = $" or c.tmdid in ({string.Join(",", autoTch.Select(x => $"'{x}'"))})";
  159. }
  160. sqlShow = $" and (array_contains(c.show,'student') or array_contains(c.show,'all') {autoSql} ) ";
  161. }
  162. string sql_status_managePage = " (c.status<>404 or IS_DEFINED(c.status) = false ) and ";
  163. if (managePage)
  164. {
  165. sql_status_managePage = "";
  166. }
  167. cosmosDbQuery.QueryText = cosmosDbQuery.QueryText.Replace("where", $" where {sql_status_managePage} array_length(c.groupIds)>0 {sqlPrivate} {sqlShow} and ");
  168. List<LessonRecord> records = new List<LessonRecord>();
  169. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname).GetItemQueryIterator<LessonRecord>(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey(code) }))
  170. {
  171. records.Add(item);
  172. }
  173. if (records.Any())
  174. {
  175. var groupIds = records.SelectMany(x => x.groupIds).ToHashSet();
  176. if (groupIds.Any())
  177. {
  178. var groups = await GroupListService.GetGroupListByListids(_azureCosmos.GetCosmosClient(), _dingDing, groupIds.ToList(), school, " c.id ");
  179. //获取已经被删除的名单。
  180. var idsExp = groupIds.Except(groups.Select(x => x.id));
  181. if (idsExp.Any())
  182. {
  183. foreach (var item in records)
  184. {
  185. int countRmv = item.groupIds.RemoveAll(x => idsExp.Contains(x));
  186. if (countRmv > 0)
  187. {
  188. try
  189. {
  190. LessonRecord record = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname).ReadItemAsync<LessonRecord>(item.id, new PartitionKey(code));
  191. record.groupIds = item.groupIds;
  192. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname).ReplaceItemAsync<LessonRecord>(record, item.id, new PartitionKey(code));
  193. }
  194. catch (CosmosException ex) when (ex.Status == 404)
  195. {
  196. continue;
  197. }
  198. }
  199. }
  200. }
  201. }
  202. }
  203. count = records.Count;
  204. ResponseData<dynamic> resDate = new ResponseData<dynamic>
  205. {
  206. code = RespondCode.Ok,
  207. msg = "成功",
  208. data = new
  209. {
  210. count = count,
  211. }
  212. };
  213. return resDate;
  214. }
  215. /// <summary>
  216. /// josn:
  217. /// {
  218. /// "roles":"",
  219. /// "scope":""
  220. /// "pageCount":"",
  221. /// "DESC":"",
  222. /// "ASC":"",
  223. /// "continuationToken":"",
  224. /// "school":"",
  225. /// "tmdid":""
  226. /// }
  227. /// </summary>
  228. /// <param name="azureCosmos"></param>
  229. /// <param name="dingDing"></param>
  230. /// <param name="id"></param>
  231. /// <param name="school"></param>
  232. /// <param name="json"></param>
  233. /// <returns></returns>
  234. /// <exception cref="NotImplementedException"></exception>
  235. public static async Task<ResponseData<dynamic>> GetLessonRecord(AzureCosmosFactory _azureCosmos, IConfiguration _configuration, AzureServiceBusFactory _serviceBus,
  236. Option _option, DingDing _dingDing, string id, string school, JsonElement json)
  237. {
  238. json.TryGetProperty("identity", out JsonElement _identity);
  239. string identity = "";
  240. if (!string.IsNullOrWhiteSpace($"{_identity}"))
  241. {
  242. identity = $"{_identity}";
  243. }
  244. json.TryGetProperty("managePage", out JsonElement _managePage);
  245. bool managePage = false;
  246. if (_managePage.ValueKind.Equals(JsonValueKind.True))
  247. {
  248. managePage = true;
  249. }
  250. StringBuilder sql = new StringBuilder();
  251. sql.Append("select value(c) from c ");
  252. int pageCount = 10;
  253. Dictionary<string, object> dict = LessonService.GetLessonCond(json);
  254. if (json.TryGetProperty("pageCount", out JsonElement _pageCount))
  255. {
  256. int.TryParse($"{_pageCount}", out int pcount);
  257. if (pcount > 0)
  258. {
  259. pageCount = pcount;
  260. }
  261. }
  262. if (json.TryGetProperty("DESC", out JsonElement desc))
  263. {
  264. dict.Add("@DESC", desc.ToString());
  265. }
  266. if (json.TryGetProperty("ASC", out JsonElement asc))
  267. {
  268. dict.Add("@ASC", asc.ToString());
  269. }
  270. string continuationToken = null;
  271. if (json.TryGetProperty("continuationToken", out JsonElement _continuationToken))
  272. {
  273. if (!string.IsNullOrEmpty($"{_continuationToken}"))
  274. {
  275. continuationToken = $"{_continuationToken}";
  276. }
  277. }
  278. AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql);
  279. string tbname = "";
  280. string code = "";
  281. string sqlPrivate = "";
  282. List<string> autoTch = new List<string>();
  283. code = $"LessonRecord-{school}";
  284. tbname = "School";
  285. List<string> ids = new List<string>();
  286. //只查询某个老师的课例
  287. if (json.TryGetProperty("tmdid", out JsonElement tmdid) && !string.IsNullOrWhiteSpace($"{tmdid}"))
  288. {
  289. ids.Add($"{tmdid}");
  290. }
  291. else
  292. {
  293. string sqltch = "select distinct value(c.id) from c ";
  294. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
  295. .GetItemQueryIterator<string>(queryText: sqltch, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Teacher-{school}") }))
  296. {
  297. ids.Add(item);
  298. }
  299. }
  300. if (ids.Any())
  301. {
  302. string sqlTechbase = $"select distinct value(c.id) from c where c.id in ({string.Join(",", ids.Select(x => $"'{x}'"))}) and (array_contains(c.lessonShow,'student') or array_contains(c.lessonShow,'all')) ";
  303. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher)
  304. .GetItemQueryIterator<string>(queryText: sqlTechbase, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Base") }))
  305. {
  306. autoTch.Add(item);
  307. }
  308. }
  309. List<LessonRecord> lessonRecords = new List<LessonRecord>();
  310. try
  311. {
  312. string sqlShow = "";
  313. if (identity.Equals("student"))
  314. {
  315. string autoSql = "";
  316. if (autoTch.Any())
  317. {
  318. autoSql = $" or c.tmdid in ({string.Join(",", autoTch.Select(x => $"'{x}'"))})";
  319. }
  320. sqlShow = $" and (array_contains(c.show,'student') or array_contains(c.show,'all') {autoSql} ) ";
  321. }
  322. string sql_status_managePage = "(c.status<>404 or IS_DEFINED(c.status) = false ) and ";
  323. if (managePage)
  324. {
  325. sql_status_managePage = "";
  326. }
  327. cosmosDbQuery.QueryText = cosmosDbQuery.QueryText.Replace("where", $" where {sql_status_managePage} array_length(c.groupIds)>0 {sqlPrivate} {sqlShow} and ");
  328. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname)
  329. .GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, continuationToken: continuationToken,
  330. requestOptions: new QueryRequestOptions() { MaxItemCount = pageCount, PartitionKey = new PartitionKey(code) }))
  331. {
  332. using var jsonData = await JsonDocument.ParseAsync(item.ContentStream);
  333. if (jsonData.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  334. {
  335. foreach (var obj in jsonData.RootElement.GetProperty("Documents").EnumerateArray())
  336. {
  337. lessonRecords.Add(obj.ToObject<LessonRecord>());
  338. }
  339. continuationToken = item.GetContinuationToken();
  340. break;
  341. }
  342. }
  343. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  344. //查询时处理已经过期的课例。防止ServiceBus未触发的。
  345. var expireRecords = lessonRecords.Where(x => x.expire > 0 && now > x.expire);
  346. try
  347. {
  348. foreach (var item in expireRecords)
  349. {
  350. //item.status = 404;
  351. //await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname).ReplaceItemAsync(item, item.id, new PartitionKey(item.code));
  352. var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
  353. var messageChange = new ServiceBusMessage(new { delete_id = item.id, tmdid = item.tmdid, scope = item.scope, opt = "delete", school = item.school }.ToJsonString());
  354. messageChange.ApplicationProperties.Add("name", "LessonRecordEvent");
  355. await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageChange);
  356. }
  357. }
  358. catch (Exception ex)
  359. {
  360. await _dingDing.SendBotMsg($"{_option.Location},ServiceBus ,LessonRecordEvent 发送消息失败,检查是否配置正常。", GroupNames.成都开发測試群組);
  361. }
  362. var tmdids = lessonRecords.Select(x => x.tmdid).ToHashSet();
  363. if (tmdids != null && tmdids.Count > 0)
  364. {
  365. List<IdNameCode> codes = new List<IdNameCode>();
  366. string sqltmd = $"select c.id,c.name,c.picture from c where c.id in ({string.Join(",", tmdids.Select(x => $"'{x}'"))})";
  367. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<IdNameCode>(queryText: sqltmd, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base") }))
  368. {
  369. codes.Add(item);
  370. }
  371. if (codes.IsNotEmpty())
  372. {
  373. lessonRecords.ForEach(x =>
  374. {
  375. var tmd = codes.Find(z => z.id.Equals(x.tmdid));
  376. if (tmd != null)
  377. {
  378. x.tmdname = tmd.name;
  379. x.tmdpicture = tmd.picture;
  380. }
  381. });
  382. }
  383. }
  384. var groupIds = lessonRecords.SelectMany(x => x.groupIds);
  385. if (groupIds.Any())
  386. {
  387. List<GroupListDto> groupLists = await GroupListService.GetGroupListByListids(_azureCosmos.GetCosmosClient(), _dingDing, groupIds.ToList(), school);
  388. lessonRecords.ForEach(x =>
  389. {
  390. List<string> groupNmae = new List<string>();
  391. x.groupIds.ForEach(y =>
  392. {
  393. var dto = groupLists.Find(z => z.id.Equals(y));
  394. string name = dto != null ? dto.name : "-";
  395. groupNmae.Add(name);
  396. });
  397. x.groupNames = groupNmae;
  398. });
  399. }
  400. ResponseData<dynamic> resDate = new ResponseData<dynamic>
  401. {
  402. code = RespondCode.Ok,
  403. msg = "成功",
  404. data = new
  405. {
  406. currCount = lessonRecords.Count,
  407. continuationToken,
  408. lessonRecords = lessonRecords.Select(x => new { x.tmdid, x.tmdname, x.tmdpicture, x.name, x.school, x.startTime, x.duration, x.courseId, x.groupIds, x.periodId, x.subjectId, x.grade, x.id, x.category })
  409. }
  410. };
  411. return resDate;
  412. }
  413. catch (Exception)
  414. {
  415. continuationToken = null;
  416. ResponseData<dynamic> resDate = new ResponseData<dynamic> { code = RespondCode.Ok, msg = "成功", data = new { currCount = 0, continuationToken = continuationToken, lessonRecords } };
  417. return resDate;
  418. }
  419. }
  420. /// <summary>
  421. /// 学校基本信息
  422. /// //[ApiToken(Auth = "1001", Name = "学校基本信息",TName ="",EName ="", RWN = "R", Limit = false)]
  423. /// </summary>
  424. /// <param name="_azureCosmos"></param>
  425. /// <param name="_dingDing"></param>
  426. /// <param name="bizId"></param>
  427. /// <param name="schoolId"></param>
  428. /// <returns></returns>
  429. public static async Task<ResponseData<dynamic>> GetSchoolInfo(AzureCosmosFactory _azureCosmos, DingDing _dingDing, string bizId, string schoolId)
  430. {
  431. try
  432. {
  433. ResponseData<dynamic> resDate = new();
  434. School data = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(schoolId, new PartitionKey("Base"));
  435. List<dynamic> period = new();
  436. data.period.ForEach(x => { period.Add(new { x.subjects, x.grades, x.name, x.id, x.campusId, x.semesters }); });
  437. if (data != null)
  438. {
  439. resDate.code = RespondCode.Ok;
  440. resDate.msg = "成功";
  441. resDate.data = new { data.id, data.name, data.areaId, data.type, data.region, data.province, data.city, data.dist, data.campuses, period };
  442. }
  443. else
  444. {
  445. resDate.code = RespondCode.NotFound;
  446. resDate.msg = "未找到学校信息";
  447. }
  448. return resDate;
  449. }
  450. catch (Exception ex)
  451. {
  452. await _dingDing.SendBotMsg($"OpenApi,{Environment.GetEnvironmentVariable("Option:Location")} OpenApiService/GetSchoolInfo() 参数:bizId:{bizId},school:{schoolId} \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  453. return new ResponseData<dynamic>() { code = RespondCode.Error, msg = "服务端异常" };
  454. }
  455. }
  456. /// <summary>
  457. /// 名单列表信息 获取学校的行政班,教学班,教研组,研修名单
  458. /// [ApiToken(Auth = "1201", Name = "名单列表信息",TName ="",EName ="", RWN = "R", Limit = false)]
  459. /// </summary>
  460. /// <param name="_azureCosmos"></param>
  461. /// <param name="_dingDing"></param>
  462. /// <param name="bizId"></param>
  463. /// <param name="school"></param>
  464. /// <param name="json"></param>
  465. /// <returns></returns>
  466. public static async Task<ResponseData<List<OGroupList>>> GetGroupList(AzureCosmosFactory _azureCosmos, DingDing _dingDing, string bizId, string school, JsonElement json)
  467. {
  468. try
  469. {
  470. ResponseData<List<OGroupList>> resDate = new();
  471. List<OGroupList> groupLists = new();
  472. var client = _azureCosmos.GetCosmosClient();
  473. json.TryGetProperty("periodId", out JsonElement periodId);
  474. List<GroupListGrp> tempGroupLists = new();
  475. //包含,学校的行政班,教学班
  476. json.TryGetProperty("type", out JsonElement _type);
  477. List<string> types = null;
  478. if (_type.ValueKind.Equals(JsonValueKind.Array))
  479. {
  480. types = _type.ToObject<List<string>>();
  481. }
  482. else if (_type.ValueKind.Equals(JsonValueKind.String))
  483. {
  484. types = new List<string> { $"{types}" };
  485. }
  486. if (types.IsEmpty() || types.Contains("class"))
  487. {
  488. StringBuilder classsql = new StringBuilder($"SELECT c.id,c.name,c.periodId ,c.year FROM c ");
  489. if (!string.IsNullOrEmpty($"{periodId}"))
  490. {
  491. classsql.Append($" where c.periodId='{periodId}' ");
  492. }
  493. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<ClassInfo>(queryText: classsql.ToString(),
  494. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Class-{school}") }))
  495. {
  496. HashSet<string> groupNames = new HashSet<string>();
  497. string gpsql = $"SELECT distinct c.groupId,c.groupName FROM c where c.classId='{item.id}'and c.groupName <>null";
  498. await foreach (var gp in client.GetContainer(Constant.TEAMModelOS, "Student").GetItemQueryIterator<Student>(queryText: gpsql,
  499. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-{school}") }))
  500. {
  501. groupNames.Add(gp.groupName);
  502. }
  503. ///行政班(学生搜寻classId动态返回)class
  504. GroupListGrp group = new GroupListGrp
  505. {
  506. id = item.id,
  507. code = $"GroupList-{school}",
  508. name = item.name,
  509. periodId = item.periodId,
  510. scope = "school",
  511. school = $"{school}",
  512. type = "class",
  513. year = item.year,
  514. expire = 0,
  515. groupName = groupNames
  516. };
  517. tempGroupLists.Add(group);
  518. }
  519. }
  520. if (types.IsEmpty() || types.Contains("teach"))
  521. {
  522. //教学班
  523. StringBuilder teachsql = new StringBuilder($" SELECT distinct value(c) FROM c where c.type='teach'");
  524. if (!string.IsNullOrEmpty($"{periodId}"))
  525. {
  526. teachsql.Append($" and c.periodId='{periodId}'");
  527. }
  528. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").
  529. GetItemQueryIterator<GroupList>(queryText: teachsql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"GroupList-{school}") }))
  530. {
  531. HashSet<string> groupName = item.members.Where(x => !string.IsNullOrEmpty(x.groupName)).Select(y => y.groupName).ToHashSet();
  532. tempGroupLists.Add(new GroupListGrp(item, groupName));
  533. }
  534. }
  535. if (types.IsEmpty() || types.Contains("research"))
  536. {
  537. //教研组
  538. StringBuilder researchsql = new StringBuilder($"SELECT distinct value(c) FROM c where c.type='research'");
  539. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").
  540. GetItemQueryIterator<GroupList>(queryText: researchsql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"GroupList-{school}") }))
  541. {
  542. HashSet<string> groupName = item.members.Where(x => !string.IsNullOrEmpty(x.groupName)).Select(y => y.groupName).ToHashSet();
  543. tempGroupLists.Add(new GroupListGrp(item, groupName));
  544. }
  545. }
  546. if (types.IsEmpty() || types.Contains("yxtrain"))
  547. {
  548. //研修名单
  549. StringBuilder yxtrainsql = new StringBuilder($"SELECT distinct value(c) FROM c where c.type='yxtrain'");
  550. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").
  551. GetItemQueryIterator<GroupList>(queryText: yxtrainsql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"GroupList-{school}") }))
  552. {
  553. HashSet<string> groupName = item.members.Where(x => !string.IsNullOrEmpty(x.groupName)).Select(y => y.groupName).ToHashSet();
  554. tempGroupLists.Add(new GroupListGrp(item, groupName));
  555. }
  556. }
  557. groupLists = tempGroupLists.Select(x => new OGroupList { id = x.id, name = x.name, type = x.type, periodId = x.periodId, school = x.school, scope = x.scope, year = x.year, expire = x.expire }).ToList();
  558. if (groupLists.Count > 0)
  559. {
  560. resDate.code = RespondCode.Ok;
  561. resDate.msg = "成功";
  562. resDate.data = groupLists;
  563. }
  564. else
  565. {
  566. resDate.code = RespondCode.NotFound;
  567. resDate.msg = "未找到学校信息";
  568. }
  569. return resDate;
  570. }
  571. catch (Exception ex)
  572. {
  573. await _dingDing.SendBotMsg($"OpenApi,{Environment.GetEnvironmentVariable("Option:Location")} OpenApiService/GetGroupList() 参数:bizId:{bizId},school:{school},json:{json.ToJsonString()} \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  574. return new ResponseData<List<OGroupList>>() { code = RespondCode.Error, msg = "服务端异常" };
  575. }
  576. }
  577. /// <summary>
  578. /// 名单成员信息,学生成员信息,包含(学生,成员)基本信息,分组等信息
  579. /// [ApiToken(Auth = "1202", Name = "名单成员信息",TName ="",EName ="", RWN = "R", Limit = false)]
  580. /// </summary>
  581. /// <param name="_azureCosmos"></param>
  582. /// <param name="_coreAPIHttpService"></param>
  583. /// <param name="_dingDing"></param>
  584. /// <param name="bizId"></param>
  585. /// <param name="school"></param>
  586. /// <param name="json"></param>
  587. /// <returns></returns>
  588. public static async Task<ResponseData<dynamic>> GetGroupMembers(AzureCosmosFactory _azureCosmos, CoreAPIHttpService _coreAPIHttpService, DingDing _dingDing, string bizId, string school, JsonElement json)
  589. {
  590. try
  591. {
  592. List<OGgroup> groups = new();
  593. var client = _azureCosmos.GetCosmosClient();
  594. if (!json.TryGetProperty("ids", out JsonElement ids)) return new ResponseData<dynamic>() { code = RespondCode.NotFound, msg = "参数错误" };
  595. List<string> listids = ids.ToObject<List<string>>();
  596. (List<RMember> members, List<RGroupList> tGroups) = await GroupListService.GetMemberByListids(_coreAPIHttpService, client, _dingDing, listids, $"{school}");
  597. groups = tGroups.Select(x => new OGgroup
  598. {
  599. name = x.name,
  600. no = x.no,
  601. periodId = x.periodId,
  602. school = x.school,
  603. type = x.type,
  604. year = x.year,
  605. expire = x.expire,
  606. tcount = x.tcount,
  607. scount = x.scount,
  608. leader = x.leader,
  609. members = x.members,
  610. id = x.id
  611. }).ToList();
  612. if (bizId.Equals("cc7e900c-4881-4fe9-9c64-abb1a1f95518") || bizId.Equals("633d4d36-2cae-469a-bdcb-c52ce2e416b3") || bizId.Equals("8254bc86-aae9-4fef-9655-4fbda1bd39da"))
  613. {
  614. if (listids.Count == 1 && listids.First().Equals("TeacherAll") && !string.IsNullOrEmpty(school))
  615. {
  616. var keys = members.Select(x => x.id).ToHashSet();
  617. var content = new StringContent(keys.ToJsonString(), Encoding.UTF8, "application/json");
  618. string ujson = await _coreAPIHttpService.GetUserInfos(content);
  619. if (!string.IsNullOrWhiteSpace(ujson))
  620. {
  621. var coreUsers = ujson.ToObject<List<CoreUser>>();
  622. if (coreUsers.IsNotEmpty())
  623. {
  624. coreUsers.ForEach(z => {
  625. var mb = members.Find(x => x.id.Equals(z.id));
  626. if (mb != null)
  627. {
  628. mb.no = z.mobile;
  629. }
  630. });
  631. }
  632. }
  633. }
  634. }
  635. return new ResponseData<dynamic>() { code = RespondCode.Ok, msg = "成功", data = new { groups, members } };
  636. }
  637. catch (Exception ex)
  638. {
  639. await _dingDing.SendBotMsg($"OpenApi,{Environment.GetEnvironmentVariable("Option:Location")} OpenApiService/GetGroupMembers() 参数:bizId:{bizId},school:{school},json:{json.ToJsonString()} \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  640. return new ResponseData<dynamic>() { code = RespondCode.Error, msg = "服务端异常" };
  641. }
  642. }
  643. /// <summary>
  644. /// 获取课程列表信息
  645. /// [ApiToken(Auth = "1301", Name = "获取课程列表信息",TName ="",EName ="", RWN = "R", Limit = false)]
  646. /// </summary>
  647. /// <param name="_azureCosmos"></param>
  648. /// <param name="_dingDing"></param>
  649. /// <param name="bizId"></param>
  650. /// <param name="school"></param>
  651. /// <param name="json"></param>
  652. /// <returns></returns>
  653. public static async Task<ResponseData<dynamic>> GetCourseList(AzureCosmosFactory _azureCosmos, DingDing _dingDing, string bizId, string school, JsonElement json)
  654. {
  655. try
  656. {
  657. var client = _azureCosmos.GetCosmosClient();
  658. json.TryGetProperty("periodId", out JsonElement periodId);
  659. json.TryGetProperty("subjectId", out JsonElement subjectId);
  660. StringBuilder sql = new StringBuilder($"SELECT c.id,c.name,c.subject,c.period,c.scope,c.no,c.school FROM c where 1=1 ");
  661. if (!string.IsNullOrWhiteSpace($"{periodId}"))
  662. {
  663. sql.Append($" and c.period.id='{periodId}'");
  664. }
  665. if (!string.IsNullOrWhiteSpace($"{subjectId}"))
  666. {
  667. sql.Append($" and c.subject.id='{subjectId}'");
  668. }
  669. List<dynamic> courses = new List<dynamic>();
  670. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<dynamic>(queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Course-{school}") }))
  671. {
  672. courses.Add(item);
  673. }
  674. return new ResponseData<dynamic>() { code = RespondCode.Ok, msg = "成功", data = courses };
  675. }
  676. catch (Exception ex)
  677. {
  678. await _dingDing.SendBotMsg($"OpenApi,{Environment.GetEnvironmentVariable("Option:Location")} OpenApiService/GetCourseList() 参数:bizId:{bizId},school:{school},json:{json.ToJsonString()} \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  679. return new ResponseData<dynamic>() { code = RespondCode.Error, msg = "服务端异常" };
  680. }
  681. }
  682. /// <summary>
  683. /// 课程详细信息
  684. /// [ApiToken(Auth = "1302", Name = "课程详细信息",TName ="",EName ="", RWN = "R", Limit = false)]
  685. /// </summary>
  686. /// <param name="_azureCosmos"></param>
  687. /// <param name="_dingDing"></param>
  688. /// <param name="bizId"></param>
  689. /// <param name="school"></param>
  690. /// <param name="json"></param>
  691. /// <returns></returns>
  692. public static async Task<ResponseData<dynamic>> GetCourseInfo(AzureCosmosFactory _azureCosmos, DingDing _dingDing, string bizId, string school, JsonElement json)
  693. {
  694. try
  695. {
  696. json.TryGetProperty("courseId", out JsonElement courseId);
  697. Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{courseId}", new PartitionKey($"Course-{school}"));
  698. if (response.Status == 200)
  699. {
  700. JsonDocument document = JsonDocument.Parse(response.Content);
  701. Course course = document.RootElement.Deserialize<Course>();
  702. return new ResponseData<dynamic>() { code = RespondCode.Ok, msg = "成功", data = new { course.name, course.id, course.subject, course.period, course.scope, course.school, course.no, course.desc, course.schedule } };
  703. }
  704. else
  705. return new ResponseData<dynamic>() { code = RespondCode.NotFound, msg = "未找到相关课程" };
  706. }
  707. catch (Exception ex)
  708. {
  709. await _dingDing.SendBotMsg($"OpenApi,{Environment.GetEnvironmentVariable("Option:Location")} OpenApiService/GetCourseInfo() 参数:bizId:{bizId},school:{school},json:{json.ToJsonString()} \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  710. return new ResponseData<dynamic>() { code = RespondCode.Error, msg = "服务端异常" };
  711. }
  712. }
  713. /// <summary>
  714. /// 获取指定学段作息
  715. /// [ApiToken(Auth = "1303", Name = "获取指定学段作息",TName ="",EName ="", RWN = "R", Limit = false)]
  716. /// </summary>
  717. /// <param name="_azureCosmos"></param>
  718. /// <param name="_dingDing"></param>
  719. /// <param name="bizId"></param>
  720. /// <param name="school"></param>
  721. /// <param name="json"></param>
  722. /// <returns></returns>
  723. public static async Task<ResponseData<dynamic>> GetPaperExamCondition(AzureCosmosFactory _azureCosmos, DingDing _dingDing, string bizId, string school, JsonElement json)
  724. {
  725. try
  726. {
  727. json.TryGetProperty("periodId", out JsonElement _periodId);
  728. School data = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(school, new PartitionKey("Base"));
  729. var period = data.period.Find(x => x.id.Equals($"{_periodId}"));
  730. if (period != null)
  731. {
  732. return new ResponseData<dynamic>() { code = RespondCode.Ok, msg = "成功", data = new { period.subjects, period.timetable, period.grades, period.majors, weekDays } };
  733. }
  734. else
  735. return new ResponseData<dynamic>() { code = RespondCode.NotFound, msg = "未找到相关课程" };
  736. }
  737. catch (Exception ex)
  738. {
  739. await _dingDing.SendBotMsg($"OpenApi,{Environment.GetEnvironmentVariable("Option:Location")} OpenApiService/GetPaperExamCondition() 参数:bizId:{bizId},school:{school},json:{json.ToJsonString()} \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  740. return new ResponseData<dynamic>() { code = RespondCode.Error, msg = "服务端异常" };
  741. }
  742. }
  743. public static async Task<ResponseData<dynamic>> getCourseTechnology(IHttpClientFactory _httpClient, DingDing _dingDing, string bizId, string school, JsonElement json, IWebHostEnvironment _environment)
  744. {
  745. try
  746. {
  747. _httpClient.CreateClient().DefaultRequestHeaders.Add("ContentLength", "0");
  748. HttpContent httpContent = new StringContent(new { method = "statistic/data/" }.ToJsonString());
  749. /*Dictionary<string, object> data = new Dictionary<string, object>();
  750. data.Add("method", "statistic/data/");*/
  751. //data.Add("params", new { method = "statistic/data/"});
  752. //HttpResponseMessage responseMessage = await _httpClient.CreateClient().PostAsJsonAsync("http://116.204.72.199:81/statistic/data/", data);
  753. var response = await _httpClient.CreateClient().PostAsync("http://116.204.72.199:81/statistic/data/", httpContent);
  754. //获取配置文件内容
  755. string path = $"{_environment.ContentRootPath}/JsonFile/Core/field.json";
  756. StreamReader streamReader = new(new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Encoding.UTF8);
  757. StringBuilder stringBuilder = new();
  758. string text;
  759. while ((text = streamReader.ReadLine()) != null)
  760. {
  761. stringBuilder.Append(text.ToString());
  762. }
  763. streamReader.Close();
  764. string input = stringBuilder.ToString();
  765. Field fields = input.ToObject<Field>();
  766. List<OCourseBase> courses = new();
  767. List<(string name, double T, double P, int attendCount, int mCount, int groups, long time,
  768. List<(string name, int count)> counts, List<(string name, double score)> ps,
  769. List<(string name, long time)> appTimes, List<(string name, string url, int duration, long time)> vd)> scores = new();
  770. //List<(string name, List<(string name, int count)> counts)> eveCounts = new();
  771. if (response.IsSuccessStatusCode)
  772. {
  773. string responseBody = response.Content.ReadAsStringAsync().Result;
  774. JObject jo = JObject.Parse(responseBody.ToString());
  775. JArray array = jo.Value<JArray>("base");
  776. foreach (var ne in array)
  777. {
  778. OCourseBase @base = new();
  779. var tname = ne["tmdname"].Value<string>();
  780. var cname = ne["courseName"].Value<string>();
  781. var attendCount = ne["attendCount"].Value<int>();
  782. var mCount = ne["mCount"].Value<int>();
  783. var time = ne["time"].Value<long>();
  784. var obj = ne["events"].ToObject<List<Events>>();
  785. var video = ne["videos"].ToObject<List<Videos>>();
  786. @base.tmdname = tname;
  787. @base.courseName = cname;
  788. @base.attendCount = attendCount;
  789. @base.mCount = mCount;
  790. @base.groups = new List<string>();
  791. @base.time = time;
  792. @base.eves = obj;
  793. @base.videos = video;
  794. //events.Add(obj);
  795. courses.Add(@base);
  796. }
  797. foreach (var eve in courses)
  798. {
  799. var countEve = eve.eves.GroupBy(x => x.@event).Select(y => new { name = y.Key, value = y.Sum(c => c.freq) });
  800. double scoreA = 0;
  801. if (countEve.Any())
  802. {
  803. scoreA += 20;
  804. }
  805. double scoreB = 0;
  806. int P1Count = 0;
  807. int P2Count = 0;
  808. int P3Count = 0;
  809. int P4Count = 0;
  810. int P5Count = 0;
  811. List<(string name, long time)> eveTimes = new();
  812. List<(string name, string url, int duration, long time)> videos = new();
  813. foreach (var v in eve.videos)
  814. {
  815. videos.Add((v.videoName, v.video, v.duration, v.startTime));
  816. }
  817. foreach (var apps in eve.eves)
  818. {
  819. var name = fields.fields.Where(x => x.field.Equals(apps.@event)).FirstOrDefault()?.desc;
  820. eveTimes.Add((name, apps.createTime));
  821. }
  822. List<(string name, int count)> eves = new();
  823. foreach (var per in countEve)
  824. {
  825. var name = fields.fields.Where(x => x.field.Equals(per.name)).FirstOrDefault()?.desc;
  826. eves.Add((name, per.value));
  827. foreach (var evePercent in fields.fields)
  828. {
  829. //计算T分
  830. if (per.name.Equals(evePercent.field))
  831. {
  832. if (evePercent.dimension.Equals("小组学习"))
  833. {
  834. P1Count++;
  835. }
  836. if (evePercent.dimension.Equals("全班互动"))
  837. {
  838. P2Count++;
  839. }
  840. if (evePercent.dimension.Equals("生本决策"))
  841. {
  842. P3Count++;
  843. }
  844. if (evePercent.dimension.Equals("全班测验"))
  845. {
  846. P4Count++;
  847. }
  848. if (evePercent.dimension.Equals("个人学习"))
  849. {
  850. P5Count++;
  851. }
  852. double bScore = 0;
  853. if (per.value == 1)
  854. {
  855. bScore += evePercent.percent * 0.9;
  856. }
  857. else if (per.value == 2)
  858. {
  859. bScore += evePercent.percent * 0.95;
  860. }
  861. else if (per.value >= 3)
  862. {
  863. bScore += evePercent.percent;
  864. }
  865. scoreB += bScore;
  866. }
  867. }
  868. }
  869. List<(string name, double score)> PScore = new();
  870. double P1Score = 0;
  871. if (P1Count == 1)
  872. {
  873. P1Score = 18 * 0.8;
  874. }
  875. else if (P1Count == 2)
  876. {
  877. P1Score = 18 * 0.9;
  878. }
  879. else if (P1Count >= 3)
  880. {
  881. P1Score = 18;
  882. }
  883. double P2Score = 0;
  884. if (P2Count == 1)
  885. {
  886. P2Score = 18 * 0.8;
  887. }
  888. else if (P2Count == 2)
  889. {
  890. P2Score = 18 * 0.9;
  891. }
  892. else if (P2Count >= 3)
  893. {
  894. P2Score = 18;
  895. }
  896. double P3Score = 0;
  897. if (P3Count == 1)
  898. {
  899. P3Score = 18 * 0.8;
  900. }
  901. else if (P3Count == 2)
  902. {
  903. P3Score = 18 * 0.9;
  904. }
  905. else if (P3Count >= 3)
  906. {
  907. P3Score = 18;
  908. }
  909. double P4Score = 0;
  910. if (P4Count == 1)
  911. {
  912. P4Score = 18 * 0.8;
  913. }
  914. else if (P3Count == 2)
  915. {
  916. P4Score = 18 * 0.9;
  917. }
  918. else if (P4Count >= 3)
  919. {
  920. P4Score = 18;
  921. }
  922. double P5Score = 0;
  923. if (P5Count == 1)
  924. {
  925. P5Score = 18 * 0.8;
  926. }
  927. else if (P5Count == 2)
  928. {
  929. P5Score = 18 * 0.9;
  930. }
  931. else if (P5Count >= 3)
  932. {
  933. P5Score = 18;
  934. }
  935. double P6Score = (P1Score + P2Score + P3Score + P4Score + P5Score) * 0.1;
  936. PScore.Add(("小组学习", P1Score));
  937. PScore.Add(("全班互动", P2Score));
  938. PScore.Add(("生本决策", P3Score));
  939. PScore.Add(("全班测验", P4Score));
  940. PScore.Add(("个人学习", P5Score));
  941. PScore.Add(("多元评价", P6Score));
  942. double P = P1Score + P2Score + P3Score + P4Score + P5Score + P6Score;
  943. double scoreC = (scoreA + scoreB) * 0.1;
  944. double scoreT = scoreA + scoreB + scoreC;
  945. scoreT = scoreT > 0 ? Math.Round(scoreT, 2) : 0;
  946. P = P > 0 ? Math.Round(P, 2) : 0;
  947. scores.Add((eve.courseName, scoreT, P, eve.attendCount, eve.mCount, eve.groups.Count, eve.time, eves, PScore, eveTimes, videos));
  948. //eveCounts.Add((eve.courseName, eves));
  949. }
  950. //var eve = courses.Select(c => c.eves).ToList();
  951. /*using JsonDocument document = JsonDocument.Parse(responseBody.ToString());
  952. if (document.RootElement.TryGetProperty("base", out JsonElement AccessTokenObj))
  953. {
  954. //AccessToken = AccessTokenObj.ToString();
  955. }*/
  956. }
  957. var courseScore = scores.Select(c => new
  958. {
  959. c.name,
  960. c.T,
  961. c.P,
  962. c.attendCount,
  963. c.mCount,
  964. c.groups,
  965. c.time,
  966. count = c.counts.Select(x => new { x.name, x.count }),
  967. pScore = c.ps.Select(x => new { x.name, x.score }),
  968. appTime = c.appTimes.Select(x => new { x.name, x.time }),
  969. videos = c.vd.Select(x => new { x.name, x.url, x.duration, x.time })
  970. });
  971. /*var courseCount = eveCounts.Select(c => new
  972. {
  973. c.name,
  974. count = c.counts.Select(x => new { x.name, x.count })
  975. });*/
  976. return new ResponseData<dynamic>() { code = RespondCode.Ok, msg = "成功", data = new { courseScore } };
  977. /*if (period != null)
  978. {
  979. return new ResponseData<dynamic>() { code = RespondCode.Ok, msg = "成功", data = new { period.subjects, period.timetable, period.grades, period.majors, weekDays } };
  980. }
  981. else
  982. return new ResponseData<dynamic>() { code = RespondCode.NotFound, msg = "未找到相关课程" };*/
  983. }
  984. catch (Exception ex)
  985. {
  986. await _dingDing.SendBotMsg($"OpenApi,{Environment.GetEnvironmentVariable("Option:Location")} OpenApiService/getCourseTechnology() 参数:bizId:{bizId},school:{school},json:{json.ToJsonString()} \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  987. return new ResponseData<dynamic>() { code = RespondCode.Error, msg = "服务端异常" };
  988. }
  989. }
  990. /// <summary>
  991. /// 物理教室列表
  992. /// [ApiToken(Auth = "1401", Name = "物理教室列表",TName ="",EName ="", RWN = "R", Limit = false)]
  993. /// </summary>
  994. /// <param name="_azureCosmos"></param>
  995. /// <param name="_dingDing"></param>
  996. /// <param name="bizId"></param>
  997. /// <param name="school"></param>
  998. /// <param name="json"></param>
  999. /// <returns></returns>
  1000. public static async Task<ResponseData<List<ORoom>>> GetRoomList(AzureCosmosFactory _azureCosmos, DingDing _dingDing, string bizId, string school, JsonElement json)
  1001. {
  1002. try
  1003. {
  1004. var client = _azureCosmos.GetCosmosClient();
  1005. List<ORoom> dtRooms = new();
  1006. StringBuilder sql = new StringBuilder($"select value(c) from c where 1=1 ");
  1007. json.TryGetProperty("openType", out JsonElement openType);
  1008. json.TryGetProperty("no", out JsonElement no);
  1009. if (!string.IsNullOrWhiteSpace($"{openType}"))
  1010. {
  1011. sql.Append($" and c.openType='{openType}'");
  1012. }
  1013. if (!string.IsNullOrWhiteSpace($"{no}"))
  1014. {
  1015. sql.Append($" and c.no='{no}'");
  1016. }
  1017. List<Room> rooms = new List<Room>();
  1018. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<Room>(queryText: sql.ToString(),
  1019. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Room-{school}") }))
  1020. {
  1021. rooms.Add(item);
  1022. }
  1023. dtRooms = rooms.Select(s => new ORoom { id = s.id, name = s.name, x = s.x, y = s.y, openType = s.openType, style = s.style, area = s.area, address = s.address, school = school }).ToList();
  1024. if (dtRooms.Count > 0)
  1025. return new ResponseData<List<ORoom>>() { code = RespondCode.Ok, data = dtRooms };
  1026. else
  1027. return new ResponseData<List<ORoom>>() { code = RespondCode.NotFound, msg = "未找到该学校的物理教室" };
  1028. }
  1029. catch (Exception ex)
  1030. {
  1031. await _dingDing.SendBotMsg($"OpenApi,{Environment.GetEnvironmentVariable("Option:Location")} OpenApiService/GetRoomList() 参数:bizId:{bizId},school:{school},json:{json.ToJsonString()} \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  1032. return new ResponseData<List<ORoom>>() { code = RespondCode.Error, msg = "服务端异常" };
  1033. }
  1034. }
  1035. /// <summary>
  1036. /// 物理教室详细
  1037. /// [ApiToken(Auth = "1402", Name = "物理教室详细",TName ="",EName ="", RWN = "R", Limit = false)]
  1038. /// </summary>
  1039. /// <param name="_azureCosmos"></param>
  1040. /// <param name="_dingDing"></param>
  1041. /// <param name="bizId"></param>
  1042. /// <param name="school"></param>
  1043. /// <param name="json"></param>
  1044. /// <returns></returns>
  1045. public static async Task<ResponseData<dynamic>> GetRoomInfo(AzureCosmosFactory _azureCosmos, DingDing _dingDing, string bizId, string school, JsonElement json)
  1046. {
  1047. try
  1048. {
  1049. var client = _azureCosmos.GetCosmosClient();
  1050. if (!json.TryGetProperty("roomId", out JsonElement roomId)) return new ResponseData<dynamic>() { code = RespondCode.ParamsError, msg = "参数错误" };
  1051. Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{roomId}", new PartitionKey($"Room-{school}"));
  1052. if (response.Status == 200)
  1053. {
  1054. JsonDocument document = JsonDocument.Parse(response.Content);
  1055. Room tRoom = document.RootElement.Deserialize<Room>();
  1056. return new ResponseData<dynamic>() { code = RespondCode.Ok, msg = "成功", data = new { tRoom.id, tRoom.name, tRoom.x, tRoom.y, tRoom.openType, tRoom.style, tRoom.area, tRoom.address, school } };
  1057. }
  1058. else
  1059. return new ResponseData<dynamic>() { code = RespondCode.NotFound, msg = "未找到物理教室详情" };
  1060. }
  1061. catch (Exception ex)
  1062. {
  1063. await _dingDing.SendBotMsg($"OpenApi,{Environment.GetEnvironmentVariable("Option:Location")} OpenApiService/GetRoomInfo() 参数:bizId:{bizId},school:{school},json:{json.ToJsonString()} \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  1064. return new ResponseData<dynamic>() { code = RespondCode.Error, msg = "服务端异常" };
  1065. }
  1066. }
  1067. /// <summary>
  1068. /// 教师列表信息
  1069. /// [ApiToken(Auth = "1501", Name = "教师列表信息",TName ="",EName ="", RWN = "R", Limit = false)]
  1070. /// </summary>
  1071. /// <param name="_azureCosmos"></param>
  1072. /// <param name="_coreAPIHttpService"></param>
  1073. /// <param name="_dingDing"></param>
  1074. /// <param name="bizId"></param>
  1075. /// <param name="school"></param>
  1076. /// <param name="json"></param>
  1077. /// <returns></returns>
  1078. public static async Task<ResponseData<dynamic>> GetTeacherList(AzureCosmosFactory _azureCosmos, CoreAPIHttpService _coreAPIHttpService, DingDing _dingDing, string bizId, string school, JsonElement json)
  1079. {
  1080. try
  1081. {
  1082. var client = _azureCosmos.GetCosmosClient();
  1083. json.TryGetProperty("searchKey", out JsonElement _searchKey);
  1084. List<CoreUser> coreUsers = new(); List<CoreUser> unjoined = new();
  1085. IEnumerable<string> unexist = null;
  1086. StringBuilder sql = new("select c.id,c.name ,c.picture,c.job ,c.subjectIds,c.roles from c");
  1087. if (_searchKey.ValueKind.Equals(JsonValueKind.Array))
  1088. {
  1089. List<string> searchKey = _searchKey.ToObject<List<string>>();
  1090. if (searchKey.Any())
  1091. {
  1092. var keys = searchKey.Where(x => !string.IsNullOrWhiteSpace(x));
  1093. var content = new StringContent(keys.ToJsonString(), Encoding.UTF8, "application/json");
  1094. string ujson = await _coreAPIHttpService.GetUserInfos(content);
  1095. if (!string.IsNullOrWhiteSpace(ujson))
  1096. {
  1097. coreUsers = ujson.ToObject<List<CoreUser>>();
  1098. }
  1099. if (coreUsers.Any())
  1100. unexist = searchKey.Except(coreUsers.Select(x => x.searchKey));
  1101. else
  1102. return new ResponseData<dynamic>() { code = RespondCode.NotFound, msg = "没有找到对应的教师信息", data = _searchKey };
  1103. }
  1104. }
  1105. List<SchoolTeacher> teachers = new();
  1106. //string insql = "";
  1107. if (coreUsers.Any())
  1108. sql.Append($" where c.id in ({string.Join(",", coreUsers.Select(x => $"'{x.id}'"))}) ");
  1109. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<SchoolTeacher>
  1110. (queryText: sql.ToString(), requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Teacher-{school}") }))
  1111. {
  1112. teachers.Add(item);
  1113. }
  1114. if (coreUsers.Count > 0)
  1115. {
  1116. var teacherIds = coreUsers.Select(x => x.id).Except(teachers.Select(x => x.id));
  1117. unjoined = coreUsers.FindAll(x => teacherIds.Contains(x.id));
  1118. }
  1119. List<dynamic> tchs = new List<dynamic>();
  1120. teachers.Select(x => new { x.id, x.name, x.picture, x.job, x.subjectIds, x.roles }).ToList().ForEach(x =>
  1121. {
  1122. if (coreUsers.Count > 0)
  1123. {
  1124. var coreUser = coreUsers.Find(c => c.id.Equals(x.id));
  1125. if (coreUser != null)
  1126. {
  1127. tchs.Add(new { x.id, coreUser.name, coreUser.picture, x.job, x.subjectIds, x.roles, coreUser.searchKey, school });
  1128. }
  1129. }
  1130. else
  1131. tchs.Add(new { x.id, x.name, x.picture, x.job, x.subjectIds, x.roles, school });
  1132. });
  1133. return new ResponseData<dynamic>() { code = RespondCode.Ok, msg = "成功", data = new { tchs, unjoined = unjoined.Select(x => new { id = x.id, name = x.name, picture = x.picture, searchKey = x.searchKey }).ToList(), unexist } };
  1134. }
  1135. catch (Exception ex)
  1136. {
  1137. //await _dingDing.SendBotMsg($"OpenApi,{Environment.GetEnvironmentVariable("Option:Location")} OpenApiService/GetTeacherList() 参数:bizId:{bizId},school:{school},json:{json.ToJsonString()} \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  1138. return new ResponseData<dynamic>() { code = RespondCode.Error, msg = "服务端异常" };
  1139. }
  1140. }
  1141. /// <summary>
  1142. /// 教师执教的班级和课程
  1143. /// [ApiToken(Auth = "1502", Name = "教师详细信息",TName ="",EName ="", RWN = "R", Limit = false)]
  1144. /// </summary>
  1145. /// <param name="_azureCosmos"></param>
  1146. /// <param name="_dingDing"></param>
  1147. /// <param name="bizId"></param>
  1148. /// <param name="school"></param>
  1149. /// <param name="json"></param>
  1150. /// <returns></returns>
  1151. public static async Task<ResponseData<dynamic>> GetTeacherTeach(AzureCosmosFactory _azureCosmos, DingDing _dingDing, string bizId, string school, JsonElement json)
  1152. {
  1153. try
  1154. {
  1155. if (json.TryGetProperty("tmdid", out JsonElement _tmdid))
  1156. {
  1157. json.TryGetProperty("period", out JsonElement _period);
  1158. List<OCourse> courses = new List<OCourse>();
  1159. var query = $"SELECT distinct c.code,c.id,c.no,c.name,c.period,c.subject,c.scope ,c['desc'] ,c.creatorId , c.year ,s as schedule FROM c join s in c.schedule where s.teacherId='{_tmdid}' ";
  1160. HashSet<string> classIds = new HashSet<string>();
  1161. if (!string.IsNullOrWhiteSpace($"{_period}"))
  1162. {
  1163. query = $"{query} and c.period.id ='{_period}'";
  1164. }
  1165. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<OCourse>(queryText: query,
  1166. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Course-{school}") }))
  1167. {
  1168. if (!string.IsNullOrWhiteSpace(item.schedule?.stulist))
  1169. {
  1170. classIds.Add(item.schedule?.stulist);
  1171. }
  1172. if (!string.IsNullOrWhiteSpace(item.schedule?.classId))
  1173. {
  1174. classIds.Add(item.schedule?.classId);
  1175. }
  1176. courses.Add(item);
  1177. }
  1178. List<OGroupList> groupLists = new List<OGroupList>();
  1179. if (classIds.Any())
  1180. {
  1181. var tempGroupLists = await GroupListService.GetGroupListByListids(_azureCosmos.GetCosmosClient(), _dingDing, classIds.ToList(), school);
  1182. groupLists = tempGroupLists.Select(x => new OGroupList { id = x.id, name = x.name, type = x.type, periodId = x.periodId, school = x.school, scope = x.scope, year = x.year, expire = x.expire }).ToList();
  1183. }
  1184. var group = courses.GroupBy(x => x.id).Select(g => new { key = g.Key, list = g.ToList() });
  1185. List<Course> coursesR = new List<Course>();
  1186. group.ToList().ForEach(x =>
  1187. {
  1188. var first = x.list.First();
  1189. coursesR.Add(new Course
  1190. {
  1191. id = x.key,
  1192. name = first.name,
  1193. code = first.code,
  1194. no = first.no,
  1195. period = first.period,
  1196. subject = first.subject,
  1197. desc = first.desc,
  1198. creatorId = first.creatorId,
  1199. year = first.year,
  1200. schedule = x.list.Select(x => x.schedule).ToList()
  1201. });
  1202. });
  1203. return new ResponseData<dynamic>()
  1204. {
  1205. code = RespondCode.Ok,
  1206. data = new
  1207. {
  1208. courses = coursesR.Select(x => new
  1209. {
  1210. x.id,
  1211. school = school,
  1212. x.name,
  1213. x.no,
  1214. x.period,
  1215. x.subject,
  1216. x.desc,
  1217. x.creatorId,
  1218. x.year,
  1219. x.schedule
  1220. }),
  1221. groupLists
  1222. }
  1223. };
  1224. }
  1225. else
  1226. {
  1227. return new ResponseData<dynamic>() { code = RespondCode.ParamsError, msg = "参数错误" };
  1228. }
  1229. }
  1230. catch (Exception ex)
  1231. {
  1232. await _dingDing.SendBotMsg($"OpenApi,{Environment.GetEnvironmentVariable("Option:Location")} OpenApiService/GetTeacherTeach() 参数:bizId:{bizId},school:{school},json:{json.ToJsonString()} \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  1233. return new ResponseData<dynamic>() { code = RespondCode.Error, msg = "服务端异常" };
  1234. }
  1235. }
  1236. /// <summary>
  1237. /// 教师详细信息
  1238. /// [ApiToken(Auth = "1502", Name = "教师详细信息",TName ="",EName ="", RWN = "R", Limit = false)]
  1239. /// </summary>
  1240. /// <param name="_azureCosmos"></param>
  1241. /// <param name="_dingDing"></param>
  1242. /// <param name="bizId"></param>
  1243. /// <param name="school"></param>
  1244. /// <param name="json"></param>
  1245. /// <returns></returns>
  1246. public static async Task<ResponseData<dynamic>> GetTeacherInfo(AzureCosmosFactory _azureCosmos, DingDing _dingDing, string bizId, string school, JsonElement json)
  1247. {
  1248. try
  1249. {
  1250. var client = _azureCosmos.GetCosmosClient();
  1251. json.TryGetProperty("tmdid", out JsonElement _tmdid);
  1252. Response responseSchoolTch = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School")
  1253. .ReadItemStreamAsync($"{_tmdid}", new PartitionKey($"Teacher-{school}"));
  1254. Response responseTch = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher")
  1255. .ReadItemStreamAsync($"{_tmdid}", new PartitionKey($"Base"));
  1256. Teacher teacher = null;
  1257. if (responseTch.Status == 200)
  1258. {
  1259. teacher = JsonDocument.Parse(responseTch.Content).RootElement.Deserialize<Teacher>();
  1260. }
  1261. else
  1262. return new ResponseData<dynamic> { code = RespondCode.NotFound, msg = "账号未创建" };
  1263. if (responseSchoolTch.Status == 200 && teacher != null)
  1264. {
  1265. SchoolTeacher schoolTeacher = JsonDocument.Parse(responseSchoolTch.Content).RootElement.Deserialize<SchoolTeacher>();
  1266. return new ResponseData<dynamic> { code = RespondCode.Ok, msg = "成功", data = new { teacher.id, teacher.name, teacher.picture, schoolTeacher.job, schoolTeacher.status, schoolTeacher.roles, schoolTeacher.subjectIds, school = teacher.schools?.Find(x => x.schoolId.Equals(school)) } };
  1267. }
  1268. else
  1269. return new ResponseData<dynamic> { code = RespondCode.NotFound, msg = "教师未就职该学校" };
  1270. }
  1271. catch (Exception ex)
  1272. {
  1273. await _dingDing.SendBotMsg($"OpenApi,{Environment.GetEnvironmentVariable("Option:Location")} OpenApiService/GetTeacherInfo() 参数:bizId:{bizId},school:{school},json:{json.ToJsonString()} \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  1274. return new ResponseData<dynamic>() { code = RespondCode.Error, msg = "服务端异常" };
  1275. }
  1276. }
  1277. /// <summary>
  1278. /// 教师批量导入,并加入学校。可以导入学科,但需要填写学段id
  1279. /// [ApiToken(Auth = "1503", Name = "教师批量导入",TName ="",EName ="", RWN = "R", Limit = false)]
  1280. /// </summary>
  1281. /// <param name="_azureCosmos"></param>
  1282. /// <param name="_coreAPIHttpService"></param>
  1283. /// <param name="_dingDing"></param>
  1284. /// <param name="bizId"></param>
  1285. /// <param name="school"></param>
  1286. /// <param name="json"></param>
  1287. /// <returns></returns>
  1288. public static async Task<ResponseData<List<OTeachers>>> GetTeacherInfo(AzureCosmosFactory _azureCosmos, CoreAPIHttpService _coreAPIHttpService, DingDing _dingDing, string bizId, string school, ImportTechDto json)
  1289. {
  1290. try
  1291. {
  1292. //如果需要同时导入学科,则需要填写学段
  1293. List<ImportTech> impTeachers = json.teachers;
  1294. List<string> searchKey = impTeachers.Select(x => x.id).ToList();
  1295. string ujson = null;
  1296. var keys = searchKey.Where(x => !string.IsNullOrWhiteSpace(x));
  1297. if (keys.Any())
  1298. {
  1299. var content = new StringContent(keys.ToJsonString(), Encoding.UTF8, "application/json");
  1300. ujson = await _coreAPIHttpService.GetUserInfos(content);
  1301. }
  1302. List<CoreUser> coreUsers = new List<CoreUser>();
  1303. if (!string.IsNullOrWhiteSpace(ujson))
  1304. {
  1305. coreUsers = ujson.ToObject<List<CoreUser>>();
  1306. }
  1307. IEnumerable<string> unexist = new List<string>();
  1308. if (coreUsers.Any())
  1309. {
  1310. unexist = searchKey.Except(coreUsers.Select(x => x.id));
  1311. }
  1312. else
  1313. {
  1314. return new ResponseData<List<OTeachers>>() { code = RespondCode.NotFound, msg = "没有找到对应的教师信息" };
  1315. }
  1316. var exist = coreUsers.Select(x => x.id);
  1317. //注册了账号的教师
  1318. impTeachers = impTeachers.Where(x => exist.Contains(x.id)).ToList();
  1319. List<Teacher> teachersList = new List<Teacher>();
  1320. List<SchoolTeacher> schoolTeachers = new List<SchoolTeacher>();
  1321. string sql = $"select value(c) from c where c.id in ({string.Join(",", impTeachers.Select(x => $"'{x.id}'"))})";
  1322. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher)
  1323. .GetItemQueryIterator<Teacher>(queryText: sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base") }))
  1324. {
  1325. teachersList.Add(item);
  1326. }
  1327. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
  1328. .GetItemQueryIterator<SchoolTeacher>(queryText: sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Teacher-{school}") }))
  1329. {
  1330. schoolTeachers.Add(item);
  1331. }
  1332. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  1333. School data = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(school, new PartitionKey("Base"));
  1334. //学校学科发生变化。
  1335. List<SchoolTeacher> schoolTeachersAdd = new List<SchoolTeacher>();
  1336. bool baseChange = false;
  1337. foreach (var item in impTeachers)
  1338. {
  1339. var teacher = teachersList.Find(x => x.id.Equals(item.id));
  1340. var coreUser = coreUsers.Find(x => x.id.Equals(item.id));
  1341. if (teacher != null)
  1342. {
  1343. var sch = teacher.schools?.Find(x => x.schoolId.Equals(school));
  1344. if (sch == null)
  1345. {
  1346. if (teacher.schools.IsNotEmpty())
  1347. {
  1348. teacher.schools.Add(new Teacher.TeacherSchool { schoolId = school, name = data.name, status = "invite", time = now, picture = data.picture, areaId = data.areaId });
  1349. }
  1350. else
  1351. {
  1352. teacher.defaultSchool = school;
  1353. teacher.size = teacher.size + 1;
  1354. teacher.schools = new List<Teacher.TeacherSchool> { new Teacher.TeacherSchool { schoolId = school, name = data.name, status = "invite", time = now, picture = data.picture, areaId = data.areaId } };
  1355. }
  1356. }
  1357. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReplaceItemAsync(teacher, teacher.id, new PartitionKey("Base"));
  1358. }
  1359. else
  1360. {
  1361. teacher = new Teacher
  1362. {
  1363. createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
  1364. id = coreUser.id,
  1365. name = coreUser.name,
  1366. picture = coreUser.picture,
  1367. defaultSchool = school,
  1368. size = 2,
  1369. code = "Base",
  1370. pk = "Base",
  1371. schools = new List<Teacher.TeacherSchool> { new Teacher.TeacherSchool { schoolId = school, name = data.name, status = "invite", time = now, picture = data.picture, areaId = data.areaId } }
  1372. };
  1373. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).CreateItemAsync(teacher, new PartitionKey("Base"));
  1374. }
  1375. var schoolTeacher = schoolTeachers.Find(x => x.id.Equals(item.id));
  1376. //处理导入的学科
  1377. List<string> subjectIds = new List<string>();
  1378. if (item.subjects.IsNotEmpty() && !string.IsNullOrWhiteSpace(item.periodId))
  1379. {
  1380. item.subjects.ForEach(s =>
  1381. {
  1382. //同名学科
  1383. var subject = data.period.Find(x => x.id.Equals(item.periodId))?.subjects?.Find(x => x.id.Equals(s.id));
  1384. if (subject == null)
  1385. {
  1386. subject = data.period.Find(x => x.id.Equals(item.periodId))?.subjects?.Find(x => x.name.Equals(s.name));
  1387. }
  1388. else
  1389. {
  1390. subjectIds.Add(subject.id);
  1391. }
  1392. if (subject == null)
  1393. {
  1394. var period = data.period.Find(x => x.id.Equals(item.periodId));
  1395. if (period != null)
  1396. {
  1397. period.subjects.Add(new Subject { id = s.id, name = s.name, type = 2 });
  1398. subjectIds.Add(s.id);
  1399. baseChange = true;
  1400. }
  1401. }
  1402. });
  1403. }
  1404. if (schoolTeacher == null)
  1405. {
  1406. schoolTeacher = new SchoolTeacher
  1407. {
  1408. id = item.id,
  1409. name = coreUser.name,
  1410. picture = coreUser.picture,
  1411. job = item.job,
  1412. subjectIds = subjectIds,
  1413. roles = new List<string> { "teacher" },
  1414. permissions = new List<string> { "content-read", "exercise-read", "knowledge-read", "syllabus-read" },
  1415. status = "invite",
  1416. code = $"Teacher-{school}",
  1417. pk = "Teacher",
  1418. createTime = now,
  1419. };
  1420. schoolTeachersAdd.Add(schoolTeacher);
  1421. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).CreateItemAsync(schoolTeacher, new PartitionKey(schoolTeacher.code));
  1422. }
  1423. else
  1424. {
  1425. if (subjectIds.IsNotEmpty())
  1426. {
  1427. subjectIds.ForEach(x =>
  1428. {
  1429. if (!schoolTeacher.subjectIds.Contains(x))
  1430. {
  1431. schoolTeacher.subjectIds.Add(x);
  1432. }
  1433. });
  1434. }
  1435. schoolTeacher.job = string.IsNullOrWhiteSpace(item.job) ? schoolTeacher.job : item.job;
  1436. schoolTeachersAdd.Add(schoolTeacher);
  1437. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(schoolTeacher, schoolTeacher.id, new PartitionKey(schoolTeacher.code));
  1438. }
  1439. }
  1440. if (baseChange)
  1441. {
  1442. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(data, data.id, new PartitionKey("Base"));
  1443. }
  1444. return new ResponseData<List<OTeachers>>() { code = RespondCode.Ok, msg = "成功", data = schoolTeachersAdd.Select(x => new OTeachers { id = x.id, name = x.name, picture = x.picture, job = x.job, subjectIds = x.subjectIds, roles = x.roles, school = school }).ToList() };
  1445. //return schoolTeachersAdd.Select(x => new OTeachers { id = x.id, name = x.name, picture = x.picture, job = x.job, subjectIds = x.subjectIds, roles = x.roles, school = school }).ToList();
  1446. }
  1447. catch (Exception ex)
  1448. {
  1449. await _dingDing.SendBotMsg($"OpenApi,{Environment.GetEnvironmentVariable("Option:Location")} OpenApiService/GetTeacherInfo() 参数:bizId:{bizId},school:{school},json:{json} \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  1450. return new ResponseData<List<OTeachers>>() { code = RespondCode.Error, msg = "服务端异常" };
  1451. }
  1452. }
  1453. /// <summary>
  1454. /// 查找课纲
  1455. /// [ApiToken(Auth = "1601", Name = "查询课纲",TName ="",EName ="", RWN = "R", Limit = false)]
  1456. /// </summary>
  1457. /// <param name="_azureCosmos"></param>
  1458. /// <param name="json"></param>
  1459. /// <returns></returns>
  1460. public static async Task<ResponseData<List<OSyllabusTreeNode>>> GetSyllabus(AzureCosmosFactory _azureCosmos, DingDing _dingDing, string bizId, string school, JsonElement json)
  1461. {
  1462. try
  1463. {
  1464. if (!json.TryGetProperty("volumeId", out JsonElement volumeId)) return new ResponseData<List<OSyllabusTreeNode>>() { code = RespondCode.ParamsError, msg = "参数错误" };
  1465. //if (!json.TryGetProperty("volumeCode", out JsonElement volumeCode)) return new ResponseData<List<OSyllabusTreeNode>>() { code = RespondCode.ParamsError, msg = "参数错误" };
  1466. if (!json.TryGetProperty("scope", out JsonElement scope)) return new ResponseData<List<OSyllabusTreeNode>>() { code = RespondCode.ParamsError, msg = "参数错误" };
  1467. var client = _azureCosmos.GetCosmosClient();
  1468. OVolume volume = null;
  1469. List<OSyllabusTreeNode> treeNodes = new();
  1470. List<OSyllabusTreeNode> redt = new();
  1471. if ($"{scope}".Equals("school"))
  1472. {
  1473. List<OSyllabus> delSyllabus = new();
  1474. volume = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<OVolume>($"{volumeId}", new PartitionKey($"Volume-{school}"));
  1475. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<OSyllabus>(queryText: $"select value(c) from c where c.volumeId='{volumeId}'",
  1476. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Syllabus-{volume.school}") }))
  1477. {
  1478. if (item.children.IsEmpty())
  1479. {
  1480. delSyllabus.Add(item);
  1481. }
  1482. else
  1483. {
  1484. List<OSyllabusTree> trees = SyllabusService.OListToTree(item.children);
  1485. OSyllabusTreeNode otree = new() { id = item.id, scope = item.scope, trees = trees, volumeId = item.volumeId, codeval = volume.school };
  1486. treeNodes.Add(otree);
  1487. }
  1488. }
  1489. if (delSyllabus.IsNotEmpty())
  1490. {
  1491. await client.GetContainer(Constant.TEAMModelOS, "School").DeleteItemsAsync<OSyllabus>(delSyllabus.Select(x => x.id).ToList(), $"Syllabus-{volume.school}");
  1492. }
  1493. }
  1494. else
  1495. return new ResponseData<List<OSyllabusTreeNode>>() { code = RespondCode.ParamsError, msg = "参数错误" };
  1496. ResponseData<List<OSyllabusTreeNode>> responseData = new();
  1497. //对课纲树形结构排序
  1498. if (volume.syllabusIds.IsNotEmpty())
  1499. {
  1500. volume.syllabusIds.ForEach(x =>
  1501. {
  1502. for (int index = 0; index < treeNodes.Count; index++)
  1503. {
  1504. if (treeNodes[index].id == x)
  1505. {
  1506. redt.Add(treeNodes[index]);
  1507. treeNodes.RemoveAt(index);
  1508. }
  1509. }
  1510. });
  1511. redt.AddRange(treeNodes);
  1512. responseData = new ResponseData<List<OSyllabusTreeNode>>() { code = RespondCode.Ok, msg = "成功", data = redt };
  1513. }
  1514. else
  1515. {
  1516. responseData = new ResponseData<List<OSyllabusTreeNode>>() { code = RespondCode.Ok, msg = "成功", data = treeNodes };
  1517. }
  1518. return responseData;
  1519. }
  1520. catch (Exception ex)
  1521. {
  1522. await _dingDing.SendBotMsg($"OpenApi,{Environment.GetEnvironmentVariable("Option:Location")} OpenApiService/GetSyllabus() 参数:bizId:{bizId},school:{school},参数json:{json.ToJsonString()} \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  1523. return new ResponseData<List<OSyllabusTreeNode>>() { code = RespondCode.Error, msg = "服务端异常" };
  1524. }
  1525. }
  1526. /// <summary>
  1527. /// 查询册别清单
  1528. /// [ApiToken(Auth = "1602", Name = "查询册别",TName ="",EName ="", RWN = "R", Limit = false)]
  1529. /// </summary>
  1530. /// <param name="_azureCosmos"></param>
  1531. /// <param name="_dingDing"></param>
  1532. /// <param name="json"></param>
  1533. /// <returns></returns>
  1534. public static async Task<ResponseData<List<OVolume>>> GetVolumes(AzureCosmosFactory _azureCosmos, DingDing _dingDing, string bizId, string school, JsonElement json)
  1535. {
  1536. try
  1537. {
  1538. ResponseData<List<OVolume>> responseData = new();
  1539. List<OVolume> ovolumes = new List<OVolume>();
  1540. json.TryGetProperty("periodId", out JsonElement periodCode);
  1541. json.TryGetProperty("subjectId", out JsonElement subjectCode);
  1542. json.TryGetProperty("status", out JsonElement status);
  1543. json.TryGetProperty("scope", out JsonElement scope);
  1544. if (scope.GetString().Equals("school"))
  1545. {
  1546. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<OVolume>(queryText: $"select value(c) from c where c.status = {status} and c.periodId = '{periodCode}' and c.subjectId = '{subjectCode}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Volume-{school}") }))
  1547. {
  1548. ovolumes.Add(item);
  1549. }
  1550. }
  1551. else { return new ResponseData<List<OVolume>>() { code = RespondCode.ParamsError, msg = "参数错误" }; };
  1552. if (ovolumes.Count > 0)
  1553. {
  1554. responseData = new ResponseData<List<OVolume>>() { code = RespondCode.Ok, msg = "成功", data = ovolumes };
  1555. }
  1556. else
  1557. responseData = new ResponseData<List<OVolume>>() { code = RespondCode.NotFound, msg = "未找到参数相关的数据" };
  1558. return responseData;
  1559. }
  1560. catch (Exception ex)
  1561. {
  1562. await _dingDing.SendBotMsg($"OpenApi,{Environment.GetEnvironmentVariable("Option:Location")} OpenApiService/GetVolumes() 参数:bizId:{bizId},school:{school},参数json:{json.ToJsonString()} \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  1563. return new ResponseData<List<OVolume>>() { code = RespondCode.Error, msg = "服务端异常" };
  1564. }
  1565. }
  1566. /// <summary>
  1567. /// 查询知识
  1568. /// [ApiToken(Auth = "1701", Name = "查询知识点",TName ="",EName ="", RWN = "R", Limit = false)]
  1569. /// </summary>
  1570. /// <param name="_azureCosmos"></param>
  1571. /// <param name="_dingDing"></param>
  1572. /// <param name="json"></param>
  1573. /// <returns></returns>
  1574. public static async Task<ResponseData<dynamic>> GetKnowledges(AzureCosmosFactory _azureCosmos, DingDing _dingDing, string bizId, string school, JsonElement json)
  1575. {
  1576. try
  1577. {
  1578. ResponseData<dynamic> responseData = new();
  1579. var client = _azureCosmos.GetCosmosClient();
  1580. json.TryGetProperty("periodId", out JsonElement periodId);
  1581. if (!json.TryGetProperty("subjectId", out JsonElement subjectId)) return new ResponseData<dynamic>() { code = RespondCode.ParamsError, msg = "参数错误" };
  1582. //if (!json.TryGetProperty("school_code", out JsonElement school_code)) return new ResponseData<List<Knowledge>>() { code = RespondCode.ParamsError, msg = "参数错误" };
  1583. string code = $"Knowledge-{school}-{subjectId}";
  1584. StringBuilder sql = new($"select value(c) from c");
  1585. if (periodId.ValueKind.Equals(JsonValueKind.String))
  1586. {
  1587. sql.Append($" where c.periodId = '{periodId}'");
  1588. }
  1589. List<dynamic> knowledges = new();
  1590. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<Knowledge>(queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
  1591. {
  1592. knowledges.Add(new { item.periodId, item.subjectId, item.points, item.blocks, item.id });
  1593. }
  1594. if (knowledges.Any())
  1595. {
  1596. var data = knowledges.Select(x => new { });
  1597. responseData = new() { code = RespondCode.Ok, msg = "成功", data = knowledges };
  1598. }
  1599. else
  1600. {
  1601. responseData = new() { code = RespondCode.NotFound, msg = "未找到相关" };
  1602. }
  1603. return responseData;
  1604. }
  1605. catch (Exception ex)
  1606. {
  1607. await _dingDing.SendBotMsg($"OpenApi,{Environment.GetEnvironmentVariable("Option:Location")} OpenApiService/GetKnowledges() 参数:bizId:{bizId},school:{school},参数json:{json.ToJsonString()} \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  1608. return new ResponseData<dynamic>() { code = RespondCode.Error, msg = "服务端异常" };
  1609. }
  1610. }
  1611. /// <summary>
  1612. /// 设置学生全面教育画像
  1613. ///[ApiToken(Auth = "1901", Name = "设置学生全面教育画像", TName = "設置學生全面教育畫像", EName = "Set up students overall education portrait", RWN = "W", Limit = false)]
  1614. /// </summary>
  1615. /// <param name="_azureCosmos"></param>
  1616. /// <param name="_dingDing"></param>
  1617. /// <param name="json"></param>
  1618. /// <returns></returns>
  1619. public static async Task<ResponseData<dynamic>> UpsertStudentPortrait(AzureCosmosFactory _azureCosmos, DingDing _dingDing,AzureRedisFactory _azureRedis , JsonElement json,string school=null)
  1620. {
  1621. try
  1622. {
  1623. ResponseData<dynamic> responseData = new();
  1624. var client = _azureCosmos.GetCosmosClient();
  1625. if (!json.TryGetProperty("schoolCode", out JsonElement schoolCode))
  1626. {
  1627. return responseData = new() { code = RespondCode.ParamsError, msg = "schoolCode为空" };
  1628. }
  1629. #if !DEBUG
  1630. if (!string.IsNullOrWhiteSpace(school) && !school.Equals($"{schoolCode}", StringComparison.OrdinalIgnoreCase)) {
  1631. return responseData = new() { code = RespondCode.ParamsError, msg = "授权学校与参数schoolCode不匹配" };
  1632. }
  1633. #endif
  1634. if (!json.TryGetProperty("periodId", out JsonElement periodId))
  1635. {
  1636. return responseData = new() { code = RespondCode.ParamsError, msg = "periodId为空" };
  1637. }
  1638. if (!json.TryGetProperty("subjectId", out JsonElement subjectId))
  1639. {
  1640. return responseData = new() { code = RespondCode.ParamsError, msg = "subjectId为空" };
  1641. }
  1642. if (!json.TryGetProperty("students", out JsonElement _students) && !_students.ValueKind.Equals(JsonValueKind.Array))
  1643. {
  1644. return responseData = new() { code = RespondCode.ParamsError, msg = "students为空或格式错误" };
  1645. }
  1646. if (!$"{subjectId}".Equals("subject_sport") && !$"{subjectId}".Equals("subject_virtue") && !$"{subjectId}".Equals("subject_labour")
  1647. && !$"{subjectId}".Equals("subject_intelligence")
  1648. && !$"{subjectId}".Equals("subject_art"))
  1649. {
  1650. return responseData = new() { code = RespondCode.ParamsError, msg = "当前subjectId未开放画像业务" };
  1651. }
  1652. School schoolBase = await client.GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>($"{schoolCode}", new PartitionKey("Base"));
  1653. List<PortraitStudent> students = _students.ToObject<List<PortraitStudent>>();
  1654. if (students.IsEmpty()) {
  1655. return responseData = new() { code = RespondCode.ParamsError, msg = "没有学生数据" };
  1656. }
  1657. List<(Student studentBase, PortraitStudent portrait)> studentsBases = new List<(Student, PortraitStudent)>();
  1658. //学生信息不匹配的
  1659. List<PortraitStudent> unmatchStuInfo = new List<PortraitStudent>();
  1660. //学期不匹配的
  1661. List<PortraitStudent> unmatchSemester = new List<PortraitStudent>();
  1662. List<PortraitStudent> upsertDatas = new List<PortraitStudent>();
  1663. //细项类型不匹配的
  1664. List<PortraitStudent> unmatchItemScoreType = new List<PortraitStudent>();
  1665. string stusql = $"select c.id,c.classId,c.name,c.year from c where c.id in ({string.Join(",", students.Select(f => $"'{f.studentId}'"))})";
  1666. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Student)
  1667. .GetItemQueryIterator<Student>(queryText: stusql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Base-{schoolCode}") }))
  1668. {
  1669. var student = students.Find(x => x.studentId.Equals(item.id));
  1670. student.classId = item.classId;
  1671. studentsBases.Add((item, student));
  1672. //if ($"{item.classId}".Equals($"{student.classId}"))
  1673. //{
  1674. // studentsBases.Add((item,student));
  1675. //}
  1676. //else {
  1677. // unmatchStuInfo.Add(student);
  1678. //}
  1679. }
  1680. var unexist = students.FindAll(z => !studentsBases.Select(z => z.studentBase.id).Contains(z.studentId));
  1681. if (unexist.Any())
  1682. {
  1683. unmatchStuInfo.AddRange(unexist);
  1684. }
  1685. Period period = schoolBase.period.Find(x => x.id.Equals($"{periodId}"));
  1686. if (period == null)
  1687. {
  1688. return responseData = new() { code = RespondCode.NotFound, msg = "periodId不存在" };
  1689. }
  1690. else
  1691. {
  1692. bool periodChange = false;
  1693. if (!period.semesters.Any())
  1694. {
  1695. //未设置学期则默认
  1696. period.semesters.Add(new Semester
  1697. {
  1698. id = Guid.NewGuid().ToString(),
  1699. name = "第一学期",
  1700. start = 1,
  1701. month = 9,
  1702. day = 1
  1703. }); period.semesters.Add(new Semester
  1704. {
  1705. id = Guid.NewGuid().ToString(),
  1706. name = "第二学期",
  1707. start = 0,
  1708. month = 3,
  1709. day = 1
  1710. });
  1711. periodChange = true;
  1712. }
  1713. //是否需要创建科目
  1714. if (!$"{subjectId}".Equals("subject_art", StringComparison.OrdinalIgnoreCase) || !$"{subjectId}".Equals("subject_intelligence", StringComparison.OrdinalIgnoreCase))
  1715. {
  1716. var bind = period.subjects.Find(x => !string.IsNullOrWhiteSpace(x.bindId) && x.bindId.Equals($"{subjectId}", StringComparison.OrdinalIgnoreCase));
  1717. if (bind == null)
  1718. {
  1719. string subjectName = "";
  1720. switch (true)
  1721. {
  1722. case bool when $"{subjectId}".Equals("subject_sport"):
  1723. subjectName = "体育";
  1724. break;
  1725. case bool when $"{subjectId}".Equals("subject_virtue"):
  1726. subjectName = "德育";
  1727. break;
  1728. case bool when $"{subjectId}".Equals("subject_labour"):
  1729. subjectName = "劳动";
  1730. break;
  1731. //case bool when $"{subjectId}".Equals("subject_music"):
  1732. // subjectName = "音乐";
  1733. // break;
  1734. //case bool when $"{subjectId}".Equals("subject_painting"):
  1735. // subjectName = "美术";
  1736. // break;
  1737. }
  1738. if (!string.IsNullOrWhiteSpace(subjectName))
  1739. {
  1740. var subName = period.subjects.Find(z => z.name.Contains(subjectName));
  1741. if (subName != null)
  1742. {
  1743. subName.bindId = $"{subjectId}";
  1744. }
  1745. else
  1746. {
  1747. period.subjects.Add(new Subject { id = Guid.NewGuid().ToString(), name = subjectName, bindId = $"{subjectId}", type = 1 });
  1748. }
  1749. periodChange = true;
  1750. }
  1751. }
  1752. }
  1753. //是否要创建艺术类的 音乐,美术科目
  1754. if ($"{subjectId}".Equals("subject_art", StringComparison.OrdinalIgnoreCase))
  1755. {
  1756. var bind_music = period.subjects.Find(x => !string.IsNullOrWhiteSpace(x.bindId) && x.bindId.Equals("subject_music", StringComparison.OrdinalIgnoreCase));
  1757. if (bind_music != null)
  1758. {
  1759. string subjectName = "音乐";
  1760. var subName = period.subjects.Find(z => z.name.Contains(subjectName));
  1761. if (subName != null)
  1762. {
  1763. subName.bindId = "subject_music";
  1764. }
  1765. else
  1766. {
  1767. period.subjects.Add(new Subject { id = Guid.NewGuid().ToString(), name = subjectName, bindId = "subject_music", type = 1 });
  1768. }
  1769. periodChange = true;
  1770. }
  1771. var bind_painting = period.subjects.Find(x => !string.IsNullOrWhiteSpace(x.bindId) && x.bindId.Equals("subject_painting", StringComparison.OrdinalIgnoreCase));
  1772. if (bind_painting != null)
  1773. {
  1774. string subjectName = "美术";
  1775. var subName = period.subjects.Find(z => z.name.Contains(subjectName));
  1776. if (subName != null)
  1777. {
  1778. subName.bindId = "subject_painting";
  1779. }
  1780. else
  1781. {
  1782. period.subjects.Add(new Subject { id = Guid.NewGuid().ToString(), name = subjectName, bindId = "subject_painting", type = 1 });
  1783. }
  1784. periodChange = true;
  1785. }
  1786. }
  1787. if (periodChange)
  1788. {
  1789. await client.GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync<School>(schoolBase, $"{schoolCode}", new PartitionKey("Base"));
  1790. }
  1791. List<Semester> sortedSemesters = SchoolService.SortSemester(period.semesters);
  1792. foreach (var studentInfo in studentsBases)
  1793. {
  1794. Student student = studentInfo.studentBase;
  1795. string studentId = studentInfo.studentBase.id;
  1796. string classId = studentInfo.studentBase.classId;
  1797. List<SemesterData> semesterDatas = studentInfo.portrait.semesterData;
  1798. if (semesterDatas.Any())
  1799. {
  1800. semesterDatas.ForEach(data =>
  1801. {
  1802. if (!string.IsNullOrWhiteSpace(data.semesterId))
  1803. {
  1804. var semester = period.semesters.Find(s => s.id.Equals(data.semesterId));
  1805. //如果找到对应的semesterId则直接使用当前semesterId
  1806. if (semester == null)
  1807. {
  1808. //先处理,最后再检查。
  1809. data.semesterId = $"{data.semesterId}--semesterId学期无效";
  1810. if (data.semester > 0)
  1811. {
  1812. int count = period.semesters.Count();
  1813. if (count >= data.semester)
  1814. {
  1815. data.semesterId = sortedSemesters[data.semester - 1].id;
  1816. }
  1817. else
  1818. {
  1819. data.semesterId = $"{data.semester}--semester学期无效";
  1820. }
  1821. }
  1822. else
  1823. {
  1824. data.semesterId = $"{data.semester}--semester学期无效";
  1825. //无效的学期数
  1826. }
  1827. }
  1828. }
  1829. else
  1830. {
  1831. data.semesterId = $"{data.semesterId}--semesterId学期无效";
  1832. if (data.semester > 0)
  1833. {
  1834. int count = period.semesters.Count();
  1835. if (count >= data.semester)
  1836. {
  1837. data.semesterId = sortedSemesters[data.semester - 1].id;
  1838. }
  1839. else
  1840. {
  1841. data.semesterId = $"{data.semester}--semester学期无效";
  1842. }
  1843. }
  1844. else
  1845. {
  1846. data.semesterId = $"{data.semester}--semester学期无效";
  1847. //无效的学期数
  1848. }
  1849. }
  1850. });
  1851. var noSemesterDatas = semesterDatas.Where(z => z.semesterId.Contains("学期无效")).ToList();
  1852. if (noSemesterDatas.Any())
  1853. {
  1854. unmatchSemester.Add(new PortraitStudent
  1855. {
  1856. studentId = studentInfo.portrait.studentId,
  1857. name = studentInfo.portrait.name,
  1858. classId = studentInfo.portrait.classId,
  1859. semesterData = noSemesterDatas,
  1860. });
  1861. }
  1862. var okSemesterDatas = semesterDatas.Where(z => !z.semesterId.Contains("学期无效"));
  1863. if (okSemesterDatas.Any())
  1864. {
  1865. upsertDatas.Add(new PortraitStudent
  1866. {
  1867. studentId = studentInfo.portrait.studentId,
  1868. name = studentInfo.portrait.name,
  1869. classId = studentInfo.portrait.classId,
  1870. semesterData = okSemesterDatas.ToList(),
  1871. });
  1872. }
  1873. var ids = okSemesterDatas.Select(k => $"{k.year}-{k.semesterId}-{studentId}");
  1874. if (ids.Any())
  1875. {
  1876. List<OverallEducation> overallEducations = new List<OverallEducation>();
  1877. string sql = $"select value c from c where c.id in ({string.Join(",", ids.Select(f => $"'{f}'"))})" +
  1878. $" and c.studentId ='{studentId}' and c.schoolCode='{schoolCode}' and c.periodId='{periodId}' and c.classId='{classId}'";
  1879. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Student)
  1880. .GetItemQueryIterator<OverallEducation>(queryText: sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"OverallEducation-{schoolCode}") }))
  1881. {
  1882. overallEducations.Add(item);
  1883. }
  1884. var nodbids = ids.Except(overallEducations.Select(x => x.id));
  1885. var newDatas = semesterDatas.FindAll(k => nodbids.Contains($"{k.year}-{k.semesterId}-{studentId}"));
  1886. var updateDatas = semesterDatas.FindAll(k => overallEducations.Select(z => z.id).Contains($"{k.year}-{k.semesterId}-{studentId}"));
  1887. List<OverallEducation> newOverallEducations = new List<OverallEducation>();
  1888. newDatas.ForEach(z =>
  1889. {
  1890. //处理新增的学生学期画像
  1891. var overallEducation = newOverallEducations.Find(o => o.id.Equals($"{z.year}-{z.semesterId}-{studentId}") && o.code.Equals($"OverallEducation-{schoolCode}"));
  1892. if (overallEducation == null)
  1893. {
  1894. overallEducation = new OverallEducation
  1895. {
  1896. id = $"{z.year}-{z.semesterId}-{studentId}",
  1897. code = $"OverallEducation-{schoolCode}",
  1898. pk = "OverallEducation",
  1899. ttl = -1,
  1900. name = student.name,
  1901. classId = student.classId,
  1902. schoolCode = $"{schoolCode}",
  1903. semesterId = z.semesterId,
  1904. year = z.year,
  1905. periodId = $"{periodId}",
  1906. stuYear = student.year,
  1907. studentId = student.id,
  1908. };
  1909. newOverallEducations.Add(overallEducation);
  1910. }
  1911. });
  1912. if (newOverallEducations.Any())
  1913. {
  1914. (newOverallEducations, unmatchItemScoreType) = FillSemesterData(studentId, $"{subjectId}", newOverallEducations, unmatchItemScoreType, newDatas,period);
  1915. foreach (var edu in newOverallEducations)
  1916. {
  1917. await client.GetContainer(Constant.TEAMModelOS, Constant.Student).CreateItemAsync(edu, new PartitionKey(edu.code));
  1918. string key = $"OverallEducation:{edu.schoolCode}:{edu.periodId}:{edu.year}:{edu.semesterId}:{edu.classId}";
  1919. await _azureRedis.GetRedisClient(8).HashSetAsync(key, edu.studentId, edu.ToJsonString());
  1920. await _azureRedis.GetRedisClient(8).KeyExpireAsync(key, new TimeSpan(180 * 24, 0, 0));
  1921. }
  1922. }
  1923. if (overallEducations.Any())
  1924. {
  1925. (overallEducations, unmatchItemScoreType) = FillSemesterData(studentId, $"{subjectId}", overallEducations, unmatchItemScoreType, updateDatas, period);
  1926. foreach (var edu in overallEducations)
  1927. {
  1928. await client.GetContainer(Constant.TEAMModelOS, Constant.Student).ReplaceItemAsync(edu, edu.id, new PartitionKey(edu.code));
  1929. string key = $"OverallEducation:{edu.schoolCode}:{edu.periodId}:{edu.year}:{edu.semesterId}:{edu.classId}";
  1930. await _azureRedis.GetRedisClient(8).HashSetAsync(key, edu.studentId, edu.ToJsonString());
  1931. await _azureRedis.GetRedisClient(8).KeyExpireAsync(key, new TimeSpan(180 * 24, 0, 0));
  1932. }
  1933. }
  1934. }
  1935. }
  1936. }
  1937. }
  1938. return responseData = new() { data = new { unmatchStuInfo, unmatchSemester, unmatchItemScoreType, upsertDatas }, code = RespondCode.Ok, msg = "成功" };
  1939. }
  1940. catch (CosmosException cex) when (cex.Status == 404)
  1941. {
  1942. return new ResponseData<dynamic>() { code = RespondCode.NotFound, msg = "学校编码不存在" };
  1943. }
  1944. catch (Exception ex)
  1945. {
  1946. await _dingDing.SendBotMsg($"OpenApi,{Environment.GetEnvironmentVariable("Option:Location")} OpenApiService/UpsertStudentPortrait() ,参数json:{json.ToJsonString()} \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  1947. return new ResponseData<dynamic>() { code = RespondCode.Error, msg = "服务端异常" };
  1948. }
  1949. }
  1950. public static (List<OverallEducation> overallEducations, List<PortraitStudent> unmatchItemScoreType) FillSemesterData(string studentId, string subjectId, List<OverallEducation> overallEducations,List<PortraitStudent> unmatchItemScoreType, List<SemesterData> semestersDatas,Period period)
  1951. {
  1952. foreach (var z in semestersDatas)
  1953. {
  1954. var oedu = overallEducations.Find(x => x.id.Equals($"{z.year}-{z.semesterId}-{studentId}"));
  1955. if (oedu != null)
  1956. {
  1957. List<EducationScore> educationScores = null;
  1958. switch (true)
  1959. {
  1960. case bool when $"{subjectId}".Equals("subject_sport"):
  1961. educationScores = oedu.sports;
  1962. break;
  1963. case bool when $"{subjectId}".Equals("subject_virtue"):
  1964. educationScores = oedu.virtue;
  1965. break;
  1966. case bool when $"{subjectId}".Equals("subject_labour"):
  1967. educationScores = oedu.labour;
  1968. break;
  1969. case bool when $"{subjectId}".Equals("subject_intelligence"):
  1970. {
  1971. educationScores = oedu.intelligence;
  1972. //对评测需要验证 细项的具体信息
  1973. bool isunmatch = false;
  1974. foreach (var v in z.itemScore)
  1975. {
  1976. var subject = period.subjects.Find(b => b.id.Equals(v.type));
  1977. if (subject == null)
  1978. {
  1979. isunmatch = true;
  1980. }
  1981. }
  1982. if (isunmatch)
  1983. {
  1984. unmatchItemScoreType.Add(new PortraitStudent { classId = oedu.classId, name = oedu.name, studentId = oedu.studentId, semesterData = new List<SemesterData> { z } });
  1985. continue;
  1986. }
  1987. break;
  1988. }
  1989. case bool when $"{subjectId}".Equals("subject_art"):
  1990. {
  1991. educationScores = oedu.art;
  1992. //对艺术评测需要验证 细项的具体信息
  1993. bool isunmatch = false;
  1994. foreach (var v in z.itemScore)
  1995. {
  1996. var subject = period.subjects.Find(b =>!string .IsNullOrWhiteSpace(b.bindId) && b.bindId.Equals(v.type));
  1997. if (subject == null)
  1998. {
  1999. isunmatch = true;
  2000. }
  2001. }
  2002. if (isunmatch)
  2003. {
  2004. unmatchItemScoreType.Add(new PortraitStudent { classId = oedu.classId, name = oedu.name, studentId = oedu.studentId, semesterData = new List<SemesterData> { z } });
  2005. continue;
  2006. }
  2007. break;
  2008. }
  2009. default:
  2010. educationScores = new List<EducationScore>();
  2011. break;
  2012. }
  2013. var edu = educationScores.Find(m => m.examId.Equals(z.examId));
  2014. z.totalScore = z.totalScore <= 0 ? 100 : z.totalScore;
  2015. if (edu == null)
  2016. {
  2017. edu = new EducationScore();
  2018. educationScores.Add(edu);
  2019. }
  2020. edu.examId = z.examId;
  2021. edu.examDate = z.examDate;
  2022. edu.examName = z.examName;
  2023. edu.examType = z.examType;
  2024. edu.excellenceRate = z.excellenceRate;
  2025. edu.totalScore = z.totalScore;
  2026. edu.rate = z.sumScore / z.totalScore;
  2027. edu.level = z.sumScore / z.totalScore;
  2028. edu.sumScore = z.sumScore;
  2029. edu.passRate = z.passRate;
  2030. edu.itemScore = z.itemScore;
  2031. }
  2032. }
  2033. return (overallEducations, unmatchItemScoreType);
  2034. }
  2035. public static void GenApiTableRecord(AzureStorageFactory azureStorage)
  2036. {
  2037. //在开发模式时,自检 [ApiToken(Auth = "1")] 有重复的接口 https://teammodelos.table.core.chinacloudapi.cn/IESOpenApi
  2038. (List<OpenApi> openApis, List<ApiTokenAttribute> attributes) = ReflectorExtensions.GetOpenApi(new string[] { "TEAMModelOS" });
  2039. openApis.GroupBy(x => $"{x.PartitionKey}{x.RowKey}").ToList().ForEach(x =>
  2040. {
  2041. if (x.Count() > 1)
  2042. {
  2043. throw new Exception($"接口Auth重复定义{x.ToList()}");
  2044. }
  2045. });
  2046. var table = azureStorage.GetCloudTableClient().GetTableReference("IESOpenApi");
  2047. openApis = openApis.OrderBy(x => x.RowKey).ToList();
  2048. string tbqurey = $"PartitionKey {QueryComparisons.Equal} 'IES5-API' and RowKey {QueryComparisons.GreaterThanOrEqual} '{openApis.First().RowKey}' and RowKey {QueryComparisons.LessThanOrEqual} '{openApis.Last().RowKey}' ";
  2049. var apiResult = table.ExecuteQuerySegmented(new TableQuery<OpenApi>().Where(tbqurey), null);
  2050. List<OpenApi> apis = apiResult.Results;
  2051. //数据库历史数据处理
  2052. apis.ForEach(x =>
  2053. {
  2054. var api = openApis.Find(z => z.RowKey.Equals(x.RowKey));
  2055. if (api != null)
  2056. {
  2057. x.auth = api.auth;
  2058. x.name = api.name;
  2059. x.type = api.type;
  2060. x.url = api.url;
  2061. x.method = api.method;
  2062. }
  2063. });
  2064. openApis.RemoveAll(x => apis.Select(z => z.RowKey).Contains(x.RowKey));
  2065. openApis.AddRange(apis);
  2066. _ = table.SaveOrUpdateAll<OpenApi>(openApis);
  2067. string dataopenApis = openApis.ToJsonString();
  2068. (List<WebHook> webHooks, List<ApiTokenAttribute> _attributes) = ReflectorExtensions.GetWebHook(new string[] { "TEAMModelOS.SDK" });
  2069. webHooks.GroupBy(x => $"{x.PartitionKey}{x.RowKey}").ToList().ForEach(x =>
  2070. {
  2071. if (x.Count() > 1)
  2072. {
  2073. throw new Exception($"接口Auth重复定义{x.ToList()}");
  2074. }
  2075. });
  2076. webHooks = webHooks.OrderBy(x => x.RowKey).ToList();
  2077. tbqurey = $"PartitionKey {QueryComparisons.Equal} 'IES5-WEBHOOK' and RowKey {QueryComparisons.GreaterThanOrEqual} '{webHooks.First().RowKey}' and RowKey {QueryComparisons.LessThanOrEqual} '{webHooks.Last().RowKey}' ";
  2078. var hookResult = table.ExecuteQuerySegmented(new TableQuery<WebHook>().Where(tbqurey), null);
  2079. List<WebHook> hooks = hookResult.Results;
  2080. //数据库历史数据处理
  2081. hooks.ForEach(x =>
  2082. {
  2083. var api = webHooks.Find(z => z.RowKey.Equals(x.RowKey));
  2084. if (api != null)
  2085. {
  2086. x.auth = api.auth;
  2087. x.name = api.name;
  2088. x.ename = api.ename;
  2089. x.tname = api.tname;
  2090. x.type = api.type;
  2091. x.url = api.url;
  2092. x.method = api.method;
  2093. x.notice = api.notice;
  2094. }
  2095. });
  2096. webHooks.RemoveAll(x => hooks.Select(z => z.RowKey).Contains(x.RowKey));
  2097. webHooks.AddRange(hooks);
  2098. _ = table.SaveOrUpdateAll<WebHook>(webHooks);
  2099. string datawebHooks = webHooks.ToJsonString();
  2100. }
  2101. /// <summary>
  2102. /// 学生登录信息
  2103. /// </summary>
  2104. /// <param name="_azureCosmos"></param>
  2105. /// <param name="_dingDing"></param>
  2106. /// <param name="bizId"></param>
  2107. /// <param name="school"></param>
  2108. /// <param name="json"></param>
  2109. /// <returns></returns>
  2110. public static async Task<ResponseData<dynamic>> GetLoginStuInfo(AzureCosmosFactory _azureCosmos, DingDing _dingDing, Option _option, string bizId, string school, JsonElement json)
  2111. {
  2112. if (!json.TryGetProperty("idToken", out JsonElement _idToken)) return new ResponseData<dynamic>() { code = RespondCode.ParamsError, msg = "idToken参数错误", data = null };
  2113. JwtSecurityToken jwt = new($"{_idToken}");
  2114. var iss = jwt.Payload.Iss;
  2115. var stuId = jwt.Payload.Sub;
  2116. var scId = jwt.Payload.Azp;
  2117. try
  2118. {
  2119. var client = _azureCosmos.GetCosmosClient();
  2120. //if (!string.IsNullOrWhiteSpace($"{_idToken}") && JwtAuthExtension.ValidateApiToken($"{_idToken}", _option.JwtSecretKey))
  2121. //{
  2122. // JwtSecurityToken jwt = new($"{_idToken}");
  2123. //}
  2124. OStudent student = new();
  2125. jwt.Payload.TryGetValue("name", out object stuName);
  2126. jwt.Payload.TryGetValue("picture", out object stuPicture);
  2127. if (!jwt.Payload.TryGetValue("scope", out object scope)) return new ResponseData<dynamic>() { code = RespondCode.ParamsError, msg = "参数错误:scope", data = null };
  2128. if (!jwt.Payload.TryGetValue("roles", out object _roles)) return new ResponseData<dynamic>() { code = RespondCode.ParamsError, msg = "参数错误:roles", data = null };
  2129. jwt.Payload.TryGetValue("permissions", out object permissions);
  2130. jwt.Payload.TryGetValue("standard", out object standard);
  2131. jwt.Payload.TryGetValue("area", out object area);
  2132. jwt.Payload.TryGetValue("website", out object website);
  2133. List<string> roles = $"{_roles}".ToObject<List<string>>();
  2134. if (roles.Contains("student") && $"{scope}".Equals("student"))
  2135. {
  2136. if (!string.IsNullOrEmpty(stuId) && !string.IsNullOrEmpty(scId))
  2137. {
  2138. if (school.Equals(scId))
  2139. {
  2140. var responseStu = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Student").ReadItemStreamAsync(stuId, new PartitionKey($"Base-{scId}"));
  2141. if (responseStu.Status == 200)
  2142. {
  2143. JsonDocument jsonD = JsonDocument.Parse(responseStu.Content);
  2144. student = jsonD.RootElement.ToObject<OStudent>();
  2145. switch (student.gender)
  2146. {
  2147. case "M":
  2148. student.gender = "男";
  2149. break;
  2150. case "F":
  2151. student.gender = "女";
  2152. break;
  2153. case "N":
  2154. student.gender = "保密";
  2155. break;
  2156. }
  2157. }
  2158. else
  2159. { return new ResponseData<dynamic>() { code = RespondCode.NotFound, msg = "未找到该学生", data = new { id = stuId, schoolId = scId } }; }
  2160. }
  2161. else
  2162. { return new ResponseData<dynamic>() { code = RespondCode.NotFound, msg = "headers和idToken中的学校ID不匹配", data = null }; }
  2163. }
  2164. else
  2165. { return new ResponseData<dynamic>() { code = RespondCode.ParamsError, msg = "参数错误:Sub/scId", data = null }; }
  2166. }
  2167. else
  2168. { return new ResponseData<dynamic>() { code = RespondCode.ParamsError, msg = "参数错误:roles/Azp", data = null }; }
  2169. return new ResponseData<dynamic>() { code = RespondCode.Ok, msg = "成功", data = student };
  2170. }
  2171. catch (Exception ex)
  2172. {
  2173. await _dingDing.SendBotMsg($"OpenApi,{Environment.GetEnvironmentVariable("Option:Location")} OpenApiService/GetLoginStuInfo() 参数:stu:{stuId},school:{school},json:{json.ToJsonString()} \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  2174. return new ResponseData<dynamic>() { code = RespondCode.Error, msg = "服务器错误" };
  2175. }
  2176. }
  2177. /// <summary>
  2178. /// 获取学生详细信息
  2179. /// </summary>
  2180. /// <param name="_azureCosmos"></param>
  2181. /// <param name="_dingDing"></param>
  2182. /// <param name="bizId"></param>
  2183. /// <param name="school"></param>
  2184. /// <param name="json"></param>
  2185. /// <returns></returns>
  2186. public static async Task<ResponseData<dynamic>> GetStudentInfo(AzureCosmosFactory _azureCosmos, DingDing _dingDing, string bizId, string school, JsonElement json)
  2187. {
  2188. if (!json.TryGetProperty("ids", out JsonElement _ids)) return new ResponseData<dynamic>() { code = RespondCode.ParamsError, msg = "idToken参数错误", data = null };
  2189. try
  2190. {
  2191. List<string> ids = _ids.ToObject<List<string>>();
  2192. List<OStudent> student = new();
  2193. //List<OStudent> tmdId = new();
  2194. string sqlStu = $"select value(c) from c ";
  2195. if (ids.Count > 0)
  2196. sqlStu = $"select value(c) from c where c.id in ({string.Join(",", ids.Select(s => $"'{s}'"))})";
  2197. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Student").GetItemQueryIterator<OStudent>(queryText: sqlStu, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-{school}") }))
  2198. {
  2199. student.Add(item);
  2200. }
  2201. //string sqlTmd = $"select value(c) from c join s in c.schools where c.id in ({string.Join(",", ids.Select(s => $"'{s}'"))}) and s.schoolId='{school}'";
  2202. //await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Student").GetItemQueryIterator<OStudent>(queryText: sqlTmd, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base") }))
  2203. //{
  2204. // tmdId.Add(item);
  2205. //}
  2206. return new ResponseData<dynamic>() { code = RespondCode.Ok, msg = "成功", data = student };
  2207. }
  2208. catch (Exception ex)
  2209. {
  2210. await _dingDing.SendBotMsg($"OpenApi,{Environment.GetEnvironmentVariable("Option:Location")} OpenApiService/GetLoginStuInfo() 参数:学生id集合:{_ids},school:{school},json:{json.ToJsonString()} \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  2211. return new ResponseData<dynamic>() { code = RespondCode.Error, msg = "服务器错误" };
  2212. }
  2213. }
  2214. }
  2215. public class OCourseBase
  2216. {
  2217. public string tmdname { get; set; }
  2218. public string courseName { get; set; }
  2219. public int attendCount { get; set; }
  2220. public int mCount { get; set; }
  2221. public List<string> groups { get; set; }
  2222. public long time { get; set; }
  2223. public List<Events> eves { get; set; }
  2224. public List<Videos> videos { get; set; }
  2225. }
  2226. public class Events
  2227. {
  2228. public string @event { get; set; }
  2229. public int freq { get; set; }
  2230. public long createTime { get; set; }
  2231. }
  2232. public class Videos
  2233. {
  2234. public string videoName { get; set; }
  2235. public string video { get; set; }
  2236. public int duration { get; set; }
  2237. public long startTime { get; set; }
  2238. }
  2239. }