StudyController.cs 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885
  1. using Azure.Cosmos;
  2. using Azure.Messaging.ServiceBus;
  3. using DinkToPdf;
  4. using DinkToPdf.Contracts;
  5. using HTEXLib.COMM.Helpers;
  6. using Microsoft.AspNetCore.Authorization;
  7. using Microsoft.AspNetCore.Http;
  8. using Microsoft.AspNetCore.Mvc;
  9. using Microsoft.Extensions.Configuration;
  10. using Microsoft.Extensions.Options;
  11. using System;
  12. using System.Collections.Generic;
  13. using System.IO;
  14. using System.Linq;
  15. using System.Net;
  16. using System.Net.Http;
  17. using System.Text;
  18. using System.Text.Json;
  19. using System.Threading.Tasks;
  20. using TEAMModelOS.Filter;
  21. using TEAMModelOS.Models;
  22. using TEAMModelOS.SDK;
  23. using TEAMModelOS.SDK.DI;
  24. using TEAMModelOS.SDK.Extension;
  25. using TEAMModelOS.SDK.Models;
  26. using TEAMModelOS.SDK.Models.Service;
  27. namespace TEAMModelOS.Controllers.Common
  28. {
  29. [ProducesResponseType(StatusCodes.Status200OK)]
  30. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  31. [Route("common/study")]
  32. [ApiController]
  33. public class StudyController : ControllerBase
  34. {
  35. private readonly AzureCosmosFactory _azureCosmos;
  36. private readonly SnowflakeId _snowflakeId;
  37. private readonly AzureServiceBusFactory _serviceBus;
  38. private readonly DingDing _dingDing;
  39. private readonly Option _option;
  40. private readonly AzureStorageFactory _azureStorage;
  41. private readonly AzureRedisFactory _azureRedis;
  42. private readonly IConverter _converter;
  43. public IConfiguration _configuration { get; set; }
  44. private readonly CoreAPIHttpService _coreAPIHttpService;
  45. public StudyController(IConverter converter,CoreAPIHttpService coreAPIHttpService, AzureCosmosFactory azureCosmos, AzureServiceBusFactory serviceBus, SnowflakeId snowflakeId, DingDing dingDing,
  46. IOptionsSnapshot<Option> option, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, IConfiguration configuration)
  47. {
  48. _coreAPIHttpService = coreAPIHttpService;
  49. _azureCosmos = azureCosmos;
  50. _serviceBus = serviceBus;
  51. _snowflakeId = snowflakeId;
  52. _dingDing = dingDing;
  53. _option = option?.Value;
  54. _azureStorage = azureStorage;
  55. _azureRedis = azureRedis;
  56. _configuration = configuration;
  57. _converter = converter;
  58. }
  59. /// <summary>
  60. /// 保存研修信息
  61. /// </summary>
  62. /// <param name="request"></param>
  63. /// <returns></returns>
  64. [ProducesDefaultResponseType]
  65. [AuthToken(Roles = "teacher,admin")]
  66. [HttpPost("save")]
  67. [Authorize(Roles = "IES")]
  68. public async Task<IActionResult> Save(JsonElement request)
  69. {
  70. try
  71. {
  72. if (!request.TryGetProperty("study", out JsonElement stu)) return BadRequest();
  73. var client = _azureCosmos.GetCosmosClient();
  74. Study study = stu.ToObject<Study>();
  75. string code = study.school;
  76. study.publish = 0;
  77. study.ttl = -1;
  78. study.progress = "going";
  79. if (!study.owner.Equals("area"))
  80. {
  81. study.owner = "school";
  82. study.code = "Study-" + code;
  83. study.scope = "school";
  84. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  85. study.createTime = now;
  86. }
  87. if (string.IsNullOrEmpty(study.id))
  88. {
  89. study.id = Guid.NewGuid().ToString();
  90. await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(study, new PartitionKey($"{study.code}"));
  91. }
  92. else
  93. {
  94. if (request.TryGetProperty("ids", out JsonElement ids))
  95. {
  96. List<string> gIds = study.tchLists;
  97. List<string> tIds = ids.ToObject<List<string>>();
  98. foreach (string gId in gIds)
  99. {
  100. var response = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemStreamAsync(gId, new PartitionKey($"GroupList"));
  101. if (response.Status == 200)
  102. {
  103. var json = await JsonDocument.ParseAsync(response.ContentStream);
  104. GroupList group = json.ToObject<GroupList>();
  105. foreach (string id in tIds)
  106. {
  107. Member member = new();
  108. member.id = id;
  109. member.type = 1;
  110. member.code = study.school;
  111. group.members.Add(member);
  112. }
  113. await GroupListService.UpsertList(group, _azureCosmos, _configuration, _serviceBus);
  114. // await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(group, group.id, new PartitionKey($"{group.code}"));
  115. }
  116. }
  117. }
  118. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(study, study.id, new PartitionKey($"{study.code}"));
  119. }
  120. return Ok(new { study });
  121. }
  122. catch (Exception ex)
  123. {
  124. await _dingDing.SendBotMsg($"OS,{_option.Location},study/save()\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  125. return BadRequest();
  126. }
  127. }
  128. /// <summary>
  129. /// 签到
  130. /// </summary>
  131. /// <param name="request"></param>
  132. /// <returns></returns>
  133. [ProducesDefaultResponseType]
  134. //[Authorize(Roles = "IES")]
  135. //[AuthToken(Roles = "teacher,admin")]
  136. [HttpPost("sign-in")]
  137. public async Task<IActionResult> Sign(JsonElement request)
  138. {
  139. try
  140. {
  141. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  142. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  143. request.TryGetProperty("tId", out JsonElement tId);
  144. request.TryGetProperty("mobile", out JsonElement mobile);
  145. string tmdid = "";
  146. if (!string.IsNullOrWhiteSpace($"{mobile}"))
  147. {
  148. var coreUser = await _coreAPIHttpService.GetUserInfo(new Dictionary<string, string> { { "key", $"{mobile}" } }, _option.Location, _configuration);
  149. if (coreUser != null)
  150. {
  151. tmdid = coreUser.id;
  152. }
  153. }
  154. else
  155. {
  156. if (!string.IsNullOrWhiteSpace($"{tId}") && string.IsNullOrWhiteSpace(tmdid))
  157. {
  158. var coreUser = await _coreAPIHttpService.GetUserInfo(new Dictionary<string, string> { { "key", $"{tId}" } }, _option.Location, _configuration);
  159. if (coreUser != null)
  160. {
  161. tmdid = coreUser.id;
  162. }
  163. }
  164. }
  165. if (string.IsNullOrWhiteSpace(tmdid))
  166. {
  167. return Ok(new { code = HttpStatusCode.NotFound, msg = "账号不存在!" });
  168. }
  169. var client = _azureCosmos.GetCosmosClient();
  170. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  171. var response = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemStreamAsync(id.ToString(), new PartitionKey($"StudyRecord-{tmdid}"));
  172. var sresponse = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(id.ToString(), new PartitionKey($"Study-{code}"));
  173. if (sresponse.Status == (int)HttpStatusCode.OK)
  174. {
  175. var sJson = await JsonDocument.ParseAsync(sresponse.ContentStream);
  176. Study study = sJson.ToObject<Study>();
  177. if (response.Status == (int)HttpStatusCode.OK)
  178. {
  179. var json = await JsonDocument.ParseAsync(response.ContentStream);
  180. StudyRecord record = json.ToObject<StudyRecord>();
  181. if (!string.IsNullOrEmpty(record.sign))
  182. {
  183. return Ok(new { code = 200, msg = "已经签到" });
  184. }
  185. else
  186. {
  187. record.sign = study.startTime < now ? "2" : "1";
  188. record.signTime = now;
  189. }
  190. await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(record, record.id, new PartitionKey($"{record.code}"));
  191. }
  192. else
  193. {
  194. StudyRecord setting = new();
  195. setting.id = id.GetString();
  196. setting.tId = tmdid;
  197. setting.signTime = now;
  198. setting.code = "StudyRecord-" + tmdid;
  199. setting.sign = study.startTime < now ? "2" : "1";
  200. if (string.IsNullOrEmpty(setting.sign) || setting.signTime == 0)
  201. {
  202. return Ok(new { code = 500, msg = "签到失败,请重新签到" });
  203. }
  204. await client.GetContainer("TEAMModelOS", "Teacher").CreateItemAsync(setting, new PartitionKey($"{setting.code}"));
  205. }
  206. }
  207. else
  208. {
  209. return Ok(new { code = HttpStatusCode.NotFound });
  210. }
  211. var srecord = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemStreamAsync(id.ToString(), new PartitionKey($"StudyRecord-{tmdid}"));
  212. if (srecord.Status == (int)HttpStatusCode.OK)
  213. {
  214. return Ok();
  215. }
  216. else
  217. {
  218. return Ok(new { code = 500, msg = "签到失败,请重新签到" });
  219. }
  220. }
  221. catch (Exception ex)
  222. {
  223. await _dingDing.SendBotMsg($"OS,{_option.Location},study/sign-in()\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  224. return BadRequest();
  225. }
  226. }
  227. /*/// <summary>
  228. /// 上传作业
  229. /// </summary>
  230. /// <param name="request"></param>
  231. /// <returns></returns>
  232. [ProducesDefaultResponseType]
  233. [AuthToken(Roles = "teacher,admin")]
  234. [HttpPost("upload")]
  235. public async Task<IActionResult> Upload(JsonElement request)
  236. {
  237. try
  238. {
  239. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  240. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  241. if (!request.TryGetProperty("tId", out JsonElement tId)) return BadRequest();
  242. if (!request.TryGetProperty("hw", out JsonElement hw)) return BadRequest();
  243. var client = _azureCosmos.GetCosmosClient();
  244. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  245. var response = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(id.ToString(), new PartitionKey($"Study-{code}"));
  246. if (response.Status == (int)HttpStatusCode.OK)
  247. {
  248. var json = await JsonDocument.ParseAsync(response.ContentStream);
  249. Study study = json.ToObject<Study>();
  250. bool flag = study.teachers.Exists(s => s.id.Equals(tId.GetString()));
  251. if (flag)
  252. {
  253. foreach (Setting setting in study.teachers)
  254. {
  255. if (setting.id.Equals(tId.GetString()))
  256. {
  257. setting.hwTime = now;
  258. setting.hw = hw.GetString();
  259. }
  260. }
  261. }
  262. else {
  263. Setting setting = new Setting();
  264. setting.id = tId.GetString();
  265. setting.hwTime = now;
  266. setting.hw = hw.GetString();
  267. study.teachers.Add(setting);
  268. }
  269. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(study, study.id, new PartitionKey($"{study.code}"));
  270. }
  271. else
  272. {
  273. return Ok(new { code = HttpStatusCode.NotFound });
  274. }
  275. return Ok(new { code = HttpStatusCode.OK});
  276. }
  277. catch (Exception ex)
  278. {
  279. await _dingDing.SendBotMsg($"OS,{_option.Location},study/upload()\n{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  280. return BadRequest();
  281. }
  282. }*/
  283. [ProducesDefaultResponseType]
  284. [AuthToken(Roles = "teacher,admin")]
  285. [HttpPost("delete")]
  286. [Authorize(Roles = "IES")]
  287. public async Task<IActionResult> Delete(JsonElement request)
  288. {
  289. try
  290. {
  291. object userScope = null;
  292. object _standard = null;
  293. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  294. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  295. string standard = null;
  296. HttpContext?.Items?.TryGetValue("Scope", out userScope);
  297. if (userScope != null && $"{userScope}".Equals(Constant.ScopeTeacher))
  298. {
  299. HttpContext?.Items?.TryGetValue("Standard", out _standard);
  300. standard = _standard != null && string.IsNullOrEmpty($"{userScope}") ? _standard.ToString() : null;
  301. }
  302. var (userid, _, _, school) = HttpContext.GetAuthTokenInfo();
  303. var client = _azureCosmos.GetCosmosClient();
  304. var sresponse = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(id.ToString(), new PartitionKey($"Study-{code}"));
  305. if (sresponse.Status == 200)
  306. {
  307. using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
  308. Study study = json.ToObject<Study>();
  309. //必须是本人或者这个学校的管理者才能删除
  310. bool flag = false;
  311. if (study.creatorId == userid)
  312. {
  313. flag = true;
  314. }
  315. else
  316. {
  317. if (study.scope == "school" && study.school.Equals(school))
  318. {
  319. flag = true;
  320. }
  321. }
  322. List<(string pId, List<string> gid)> ps = new List<(string pId, List<string> gid)>();
  323. if (study.groupLists.Count > 0)
  324. {
  325. var group = study.groupLists;
  326. foreach (var gp in group)
  327. {
  328. foreach (KeyValuePair<string, List<string>> pp in gp)
  329. {
  330. ps.Add((pp.Key, pp.Value));
  331. }
  332. }
  333. }
  334. try
  335. {
  336. (List<RMember> members, List<RGroupList> groups) = await GroupListService.GetMemberByListids(_coreAPIHttpService, client, _dingDing, study.tchLists, study.school, ps);
  337. await StatisticsService.DoChange(new TeacherTrainChange
  338. { standard = standard, tmdids = members.Select(x => x.id)?.ToList(), school = study.school, update = new HashSet<string> { StatisticsService.OfflineRecord }, statistics = 0 }, _azureCosmos);
  339. }
  340. catch (Exception ex)
  341. {
  342. await _dingDing.SendBotMsg($"OS,{_option.Location},study/delete()ex\n{ex.Message}\n{ex.StackTrace},\n", GroupNames.醍摩豆服務運維群組);
  343. }
  344. if (flag)
  345. {
  346. study.status = 404;
  347. if (!string.IsNullOrEmpty(study.examId))
  348. {
  349. Azure.Response response = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(study.examId, new PartitionKey($"ExamLite-{code}"));
  350. if (response.Status == 200)
  351. {
  352. ExamLite data = JsonDocument.Parse(response.Content).RootElement.Deserialize<ExamLite>();
  353. data.status = 404;
  354. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(data, data.id, new PartitionKey($"ExamLite-{code}"));
  355. }
  356. }
  357. if (!string.IsNullOrEmpty(study.surveyId))
  358. {
  359. Azure.Response response = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(study.surveyId, new PartitionKey($"Survey-{code}"));
  360. if (response.Status == 200)
  361. {
  362. Survey data = JsonDocument.Parse(response.Content).RootElement.Deserialize<Survey>();
  363. data.status = 404;
  364. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(data, data.id, new PartitionKey($"Survey-{code}"));
  365. }
  366. }
  367. if (!string.IsNullOrEmpty(study.workId))
  368. {
  369. Azure.Response response = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(study.workId, new PartitionKey($"Homework-{code}"));
  370. if (response.Status == 200)
  371. {
  372. Homework data = JsonDocument.Parse(response.Content).RootElement.Deserialize<Homework>();
  373. data.status = 404;
  374. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(data, data.id, new PartitionKey($"Homework-{code}"));
  375. }
  376. }
  377. await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(study, study.id, new PartitionKey($"{study.code}"));
  378. }
  379. }
  380. return Ok(new { id });
  381. }
  382. catch (Exception e)
  383. {
  384. await _dingDing.SendBotMsg($"OS,{_option.Location},study/delete()\n{e.Message}\n{e.StackTrace},\n", GroupNames.醍摩豆服務運維群組);
  385. return BadRequest();
  386. }
  387. }
  388. /// <param name="request"></param>
  389. /// <returns></returns>
  390. [ProducesDefaultResponseType]
  391. [Authorize(Roles = "IES")]
  392. [AuthToken(Roles = "teacher,admin")]
  393. [HttpPost("find")]
  394. public async Task<IActionResult> Find(JsonElement requert)
  395. {
  396. try
  397. {
  398. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  399. var client = _azureCosmos.GetCosmosClient();
  400. var query = $"select c.id,c.img,c.name,c.type,c.startTime,c.endTime,c.presenter,c.topic,c.address,c.owner,c.progress,c.groupLists from c where (c.status<>404 or IS_DEFINED(c.status) = false ) ";
  401. string continuationToken = string.Empty;
  402. string token = default;
  403. //是否需要进行分页查询,默认不分页
  404. bool iscontinuation = false;
  405. if (requert.TryGetProperty("token", out JsonElement token_1))
  406. {
  407. token = token_1.GetString();
  408. iscontinuation = true;
  409. };
  410. //默认不指定返回大小
  411. int? topcout = null;
  412. if (requert.TryGetProperty("count", out JsonElement jcount))
  413. {
  414. if (!jcount.ValueKind.Equals(JsonValueKind.Undefined) && !jcount.ValueKind.Equals(JsonValueKind.Null) && jcount.TryGetInt32(out int data))
  415. {
  416. topcout = data;
  417. }
  418. }
  419. List<object> studies = new();
  420. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, continuationToken: token, requestOptions: new QueryRequestOptions() { MaxItemCount = topcout, PartitionKey = new PartitionKey($"Study-{code}") }))
  421. {
  422. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  423. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  424. {
  425. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  426. {
  427. studies.Add(obj.ToObject<object>());
  428. }
  429. }
  430. if (iscontinuation)
  431. {
  432. continuationToken = item.GetContinuationToken();
  433. break;
  434. }
  435. }
  436. return Ok(new { studies });
  437. }
  438. catch (Exception e)
  439. {
  440. await _dingDing.SendBotMsg($"OS,{_option.Location},study/find()\n{e.Message}\n{e.StackTrace}\n{e .StackTrace}", GroupNames.醍摩豆服務運維群組);
  441. return BadRequest();
  442. }
  443. }
  444. [ProducesDefaultResponseType]
  445. [Authorize(Roles = "IES")]
  446. [AuthToken(Roles = "teacher,admin")]
  447. [HttpPost("find-summary")]
  448. public async Task<IActionResult> FindSummary(JsonElement requert)
  449. {
  450. try
  451. {
  452. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  453. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  454. var client = _azureCosmos.GetCosmosClient();
  455. Study study = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<Study>(id.GetString(), new PartitionKey($"Study-{code}"));
  456. if (study != null)
  457. {
  458. (List<RMember> tchList, List<RGroupList> classInfo) = await GroupListService.GetMemberByListids(_coreAPIHttpService, client, _dingDing, study.tchLists, study.school);
  459. List<StudyRecord> records = new();
  460. foreach (var member in tchList)
  461. {
  462. var response = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemStreamAsync(id.ToString(), new PartitionKey($"StudyRecord-{member.id}"));
  463. if (response.Status == (int)HttpStatusCode.OK)
  464. {
  465. var json = await JsonDocument.ParseAsync(response.ContentStream);
  466. StudyRecord record = json.ToObject<StudyRecord>();
  467. records.Add(record);
  468. }
  469. }
  470. List<ufo> ufos = new();
  471. if (study.teacIds != null && study.teacIds.Count > 0)
  472. {
  473. List<string> tIds = new();
  474. var content = new StringContent(study.teacIds.ToJsonString(), Encoding.UTF8, "application/json");
  475. string json = await _coreAPIHttpService.GetUserInfos(content);
  476. if (!string.IsNullOrWhiteSpace(json))
  477. {
  478. try
  479. {
  480. List<ufo> tmdInfos = json.ToObject<List<ufo>>();
  481. if (tmdInfos.IsNotEmpty())
  482. {
  483. foreach (ufo fo in tmdInfos)
  484. {
  485. fo.type = 1;
  486. tIds.Add(fo.id);
  487. }
  488. ufos.AddRange(tmdInfos);
  489. }
  490. }
  491. catch (Exception ex)
  492. {
  493. await _dingDing.SendBotMsg($"{_coreAPIHttpService.options.Get("Default").location}用户转换失败:{_coreAPIHttpService.options.Get("Default").url}{json}\n ", GroupNames.醍摩豆服務運維群組);
  494. }
  495. }
  496. }
  497. else
  498. {
  499. long time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  500. study.updateTime = time;
  501. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(study, study.id, new PartitionKey($"{study.code}"));
  502. }
  503. // (List<TmdInfo> tmdInfos, List<ClassListInfo> classInfos) = await TriggerStuActivity.GetTchList(client, _dingDing, ids, $"{school}");
  504. //(List<TmdInfo> tchList, _) = await TriggerStuActivity.GetTchList(client, _dingDing, study.tchLists, study.school);
  505. return Ok(new { study, records, ufos, status = 200 });
  506. }
  507. else
  508. {
  509. return Ok(new { study, status = 404 });
  510. }
  511. }
  512. catch (CosmosException ex) when (ex.Status == 404)
  513. {
  514. return Ok(new { status = 404 });
  515. }
  516. catch (Exception e)
  517. {
  518. await _dingDing.SendBotMsg($"OS,{_option.Location},study/FindSummary()\n{e.Message}\n{e.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  519. return Ok(new { status = 404 });
  520. }
  521. }
  522. /// <param name="request"></param>
  523. /// <returns></returns>
  524. [ProducesDefaultResponseType]
  525. [Authorize(Roles = "IES")]
  526. [AuthToken(Roles = "teacher,admin")]
  527. [HttpPost("find-by-teacher")]
  528. public async Task<IActionResult> FindByTeacher(JsonElement requert)
  529. {
  530. try
  531. {
  532. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  533. if (!requert.TryGetProperty("tId", out JsonElement tId)) return BadRequest();
  534. var client = _azureCosmos.GetCosmosClient();
  535. var query = $"select c.id,c.img,c.name,c.startTime,c.type,c.endTime,c.presenter,c.topic,c.address,c.owner from c join A0 in c.teachers where A0.id = '{tId}'";
  536. List<object> studies = new();
  537. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Study-{code}") }))
  538. {
  539. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  540. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  541. {
  542. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  543. {
  544. studies.Add(obj.ToObject<object>());
  545. }
  546. }
  547. }
  548. return Ok(new { studies });
  549. }
  550. catch (Exception e)
  551. {
  552. await _dingDing.SendBotMsg($"OS,{_option.Location},study/find-by-teacher()\n{e.Message}\n{e.StackTrace}\n{e .StackTrace}", GroupNames.醍摩豆服務運維群組);
  553. return BadRequest();
  554. }
  555. }
  556. [ProducesDefaultResponseType]
  557. [Authorize(Roles = "IES")]
  558. [AuthToken(Roles = "teacher,admin")]
  559. [HttpPost("find-summary-by-teacher")]
  560. public async Task<IActionResult> FindSummaryByTeacher(JsonElement requert)
  561. {
  562. try
  563. {
  564. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  565. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  566. if (!requert.TryGetProperty("tId", out JsonElement tId)) return BadRequest();
  567. var client = _azureCosmos.GetCosmosClient();
  568. List<object> studies = new();
  569. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: $"select value(c) from c join A0 in c.teachers where A0.id = '{tId}' and c.id = '{id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Study-{code}") }))
  570. {
  571. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  572. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  573. {
  574. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  575. {
  576. studies.Add(obj.ToObject<object>());
  577. }
  578. }
  579. }
  580. return Ok(new { studies });
  581. }
  582. catch (Exception e)
  583. {
  584. await _dingDing.SendBotMsg($"OS,{_option.Location},study/find-summary-by-teacher()\n{e.Message}\n{e.StackTrace}\n{e .StackTrace}", GroupNames.醍摩豆服務運維群組);
  585. return BadRequest();
  586. }
  587. }
  588. [ProducesDefaultResponseType]
  589. [AuthToken(Roles = "teacher,admin,area")]
  590. [HttpPost("audit")]
  591. [Authorize(Roles = "IES")]
  592. public async Task<IActionResult> Audit(JsonElement request)
  593. {
  594. try
  595. {
  596. (string tmdid, _, _, string school) = HttpContext.GetAuthTokenInfo();
  597. if (!HttpContext.Items.TryGetValue("Standard", out object standard)) return BadRequest();
  598. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  599. //if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  600. //if (!request.TryGetProperty("tId", out JsonElement tId)) return BadRequest();
  601. if (!request.TryGetProperty("type", out JsonElement type)) return BadRequest();
  602. var client = _azureCosmos.GetCosmosClient();
  603. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  604. List<Dictionary<string, List<string>>> acId = id.ToObject<List<Dictionary<string, List<string>>>>();
  605. List<string> value = new List<string>();
  606. List<Task> tasks = new();
  607. List<Task<ItemResponse<StudyRecord>>> tasky = new();
  608. List<(string op, string tId)> opp = new List<(string op, string tId)>();
  609. int statu = type.GetInt32();
  610. (string standard, List<string> tmdid, string school, List<string> update, int statistics) list = ($"{standard}", null, school, new List<string> { StatisticsService.OfflineRecord }, 0);
  611. HashSet<string> tch = new HashSet<string>();
  612. foreach (var aId in acId)
  613. {
  614. foreach (KeyValuePair<string, List<string>> pair in aId)
  615. {
  616. /* await foreach (var key in TeacTask(pair.Key, pair.Value, client, type.GetInt32(), now, standard, school)) {
  617. opp.Add((key.op,key.tId));
  618. };*/
  619. foreach (var teacId in pair.Value)
  620. {
  621. var response = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemStreamAsync(pair.Key, new PartitionKey($"StudyRecord-{teacId}"));
  622. if (response.Status == 200)
  623. {
  624. var json = await JsonDocument.ParseAsync(response.ContentStream);
  625. StudyRecord study = json.ToObject<StudyRecord>();
  626. if (study.tId.Equals(teacId) && study.status == statu)
  627. {
  628. continue;
  629. }
  630. else
  631. {
  632. study.status = statu;
  633. study.aTime = now;
  634. }
  635. tasky.Add(client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(study, study.id, new PartitionKey($"{study.code}")));
  636. }
  637. else
  638. {
  639. StudyRecord setting = new()
  640. {
  641. id = pair.Key,
  642. tId = teacId,
  643. code = "StudyRecord-" + teacId,
  644. status = statu,
  645. aTime = now
  646. };
  647. tasky.Add(client.GetContainer("TEAMModelOS", "Teacher").CreateItemAsync(setting, new PartitionKey($"{setting.code}")));
  648. }
  649. tch.Add($"{teacId}");
  650. }
  651. }
  652. }
  653. list.tmdid = new List<string>(tch);
  654. await tasky.TaskPage(10);
  655. if (statu == 1) {
  656. var messageBlobPDF= new ServiceBusMessage(new { id = tch, school, userType = "tmdid" }.ToJsonString());
  657. var GenPdfQueue = _configuration.GetValue<string>("Azure:ServiceBus:GenPdfQueue");
  658. await _serviceBus.GetServiceBusClient().SendMessageAsync(GenPdfQueue, messageBlobPDF);
  659. }
  660. await StatisticsService.SendServiceBus(list, _configuration, _serviceBus, client);
  661. return Ok(new { code = HttpStatusCode.OK });
  662. }
  663. catch (Exception ex)
  664. {
  665. await _dingDing.SendBotMsg($"OS,{_option.Location},Study/audit()\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  666. return BadRequest();
  667. }
  668. }
  669. private async IAsyncEnumerable<(string op, string tId)> AuditTask(List<Dictionary<string, List<string>>> ids, CosmosClient client, int type, long now, object standard, string school)
  670. {
  671. List<Task> tasks = new();
  672. List<Task<ItemResponse<StudyRecord>>> tasky = new();
  673. foreach (var id in ids)
  674. {
  675. foreach (KeyValuePair<string, List<string>> pair in id)
  676. {
  677. foreach (var teacId in pair.Value)
  678. {
  679. //var response = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemStreamAsync(pair.Key, new PartitionKey($"StudyRecord-{teacId}"));
  680. List<StudyRecord> studyRecords = new();
  681. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<StudyRecord>(queryText: $"select value(c) from c where c.id = '{pair.Key}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"StudyRecord-{teacId}") }))
  682. {
  683. studyRecords.Add(item);
  684. }
  685. if (studyRecords.Count > 0)
  686. {
  687. if (studyRecords[0].tId.Equals(teacId))
  688. {
  689. studyRecords[0].status = type;
  690. studyRecords[0].aTime = now;
  691. }
  692. tasky.Add(client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(studyRecords[0], studyRecords[0].id, new PartitionKey($"{studyRecords[0].code}")));
  693. }
  694. else
  695. {
  696. StudyRecord setting = new()
  697. {
  698. id = pair.Key,
  699. tId = teacId,
  700. code = "StudyRecord-" + teacId,
  701. status = type,
  702. aTime = now
  703. };
  704. tasky.Add(client.GetContainer("TEAMModelOS", "Teacher").CreateItemAsync(setting, new PartitionKey($"{setting.code}")));
  705. }
  706. //tasks.Add(StatisticsService.SendServiceBus($"{standard}", $"{teacId}", $"{school}", StatisticsService.OfflineRecord, 1, _configuration, _serviceBus));
  707. }
  708. yield return ("", "");
  709. }
  710. }
  711. await Task.WhenAll(tasks);
  712. await Task.WhenAll(tasky);
  713. }
  714. private async IAsyncEnumerable<(string op, string tId)> TeacTask(string id, List<string> ids, CosmosClient client, int type, long now, object standard, string school)
  715. {
  716. List<Task> tasks = new();
  717. foreach (var teacId in ids)
  718. {
  719. /* var response = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemStreamAsync(id, new PartitionKey($"StudyRecord-{teacId}"));*/
  720. List<StudyRecord> studyRecords = new();
  721. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<StudyRecord>(queryText: $"select value(c) from c where c.id = '{id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"StudyRecord-{teacId}") }))
  722. {
  723. studyRecords.Add(item);
  724. }
  725. string op;
  726. if (studyRecords.Count > 0)
  727. {
  728. if (studyRecords[0].tId.Equals(teacId))
  729. {
  730. studyRecords[0].status = type;
  731. studyRecords[0].aTime = now;
  732. }
  733. op = "update";
  734. await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(studyRecords[0], studyRecords[0].id, new PartitionKey($"{studyRecords[0].code}"));
  735. }
  736. else
  737. {
  738. StudyRecord setting = new()
  739. {
  740. id = id,
  741. tId = teacId,
  742. code = "StudyRecord-" + teacId,
  743. status = type,
  744. aTime = now
  745. };
  746. op = "insert";
  747. await client.GetContainer("TEAMModelOS", "Teacher").CreateItemAsync(setting, new PartitionKey($"{setting.code}"));
  748. }
  749. //tasks.Add(StatisticsService.SendServiceBus($"{standard}", $"{teacId}", $"{school}", StatisticsService.OfflineRecord, 1, _configuration, _serviceBus));
  750. yield return (op, teacId);
  751. }
  752. await Task.WhenAll(tasks);
  753. }
  754. [HttpPost("gen-pdf")]
  755. //[Authorize(Roles = Constant.Role_Root)]
  756. public IActionResult GenPdf(JsonElement json)
  757. {
  758. //https://article.itxueyuan.com/JAxOnG
  759. //http://t.zoukankan.com/hsiang-p-14608694.html
  760. //https://github.com/rdvojmoc/DinkToPdf
  761. //https://blog.csdn.net/u011966339/article/details/114964016?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-0-114964016-blog-118609642.pc_relevant_antiscanv2&spm=1001.2101.3001.4242.1&utm_relevant_index=3
  762. try
  763. {
  764. var html = Constant.html.Replace("{c.stuname}", "黄总");
  765. html = html.Replace("{c.details}", @"<tr>
  766. <td> 语文学科如何在A1技术支持下进行学情分析 </td>
  767. <td> 信息化教学案例展示与分享 </td >
  768. <td> 1 </td >
  769. <td> 1 </td >
  770. <td> 2022 - 04 - 07 到 2022 - 04 - 14 </td>
  771. <td></td>
  772. <td> 扫码签到、作业提交、问卷反馈、评测活动 </td>
  773. <td> 已完成 </td >
  774. </tr> ");
  775. GlobalSettings globalSettings = new GlobalSettings();
  776. globalSettings.ColorMode = ColorMode.Color;
  777. globalSettings.Orientation = Orientation.Portrait;
  778. globalSettings.PaperSize = PaperKind.A4;
  779. globalSettings.Margins = new MarginSettings { Top = 25, Bottom = 25 };
  780. globalSettings.Out = @"E:\pdf\test.pdf";
  781. ObjectSettings objectSettings = new ObjectSettings();
  782. objectSettings.PagesCount = true;
  783. objectSettings.HtmlContent = html;
  784. WebSettings webSettings = new WebSettings();
  785. webSettings.DefaultEncoding = "utf-8";
  786. HeaderSettings headerSettings = new HeaderSettings();
  787. headerSettings.FontSize = 15;
  788. headerSettings.FontName = "fangsong";
  789. headerSettings.Right = "";
  790. // headerSettings.Line = true;
  791. FooterSettings footerSettings = new FooterSettings();
  792. footerSettings.FontSize = 12;
  793. footerSettings.FontName = "Ariel";
  794. footerSettings.Center = "校本研修活动完成情况([page]/[toPage])页";
  795. // footerSettings.Line = true;
  796. objectSettings.HeaderSettings = headerSettings;
  797. objectSettings.FooterSettings = footerSettings;
  798. objectSettings.WebSettings = webSettings;
  799. HtmlToPdfDocument htmlToPdfDocument = new HtmlToPdfDocument()
  800. {
  801. GlobalSettings = globalSettings,
  802. Objects = { objectSettings },
  803. };
  804. var a = _converter.Convert(htmlToPdfDocument);
  805. MemoryStream m = new MemoryStream(a);
  806. /* FileStream fs = new FileStream("F:\\1111111111111\\SimplePdf1.pdf", FileMode.Create, FileAccess.Write, FileShare.Read);
  807. m.WriteTo(fs);
  808. m.Close();
  809. fs.Close();*/
  810. //var doc = new HtmlToPdfDocument()
  811. //{
  812. // GlobalSettings = {
  813. // ColorMode = ColorMode.Color,
  814. // Orientation = Orientation.Portrait,
  815. // PaperSize = PaperKind.A4,
  816. // Margins = new MarginSettings() { Top = 10 },
  817. // Out = @"F:\test.pdf",
  818. // },
  819. // Objects = {
  820. // new ObjectSettings()
  821. // {
  822. // Page = "https://zhidao.baidu.com/question/175696719173618004.html",
  823. // },
  824. // }
  825. //};
  826. //_converter.Convert(doc);
  827. return Ok();
  828. // return Ok(File(a, "application/octet-stream", "SimplePdf.pdf"));
  829. }
  830. catch (Exception ex)
  831. {
  832. return BadRequest(new { ex = ex.StackTrace, exmsg = ex.Message });
  833. }
  834. }
  835. }
  836. }