CommentController.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. using Azure.Cosmos;
  2. using Microsoft.AspNetCore.Http;
  3. using Microsoft.AspNetCore.Mvc;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.IdentityModel.Tokens.Jwt;
  7. using System.Text.Json;
  8. using System.Threading.Tasks;
  9. using TEAMModelOS.Models.Dto;
  10. using TEAMModelOS.SDK.Models;
  11. using TEAMModelOS.SDK;
  12. using TEAMModelOS.SDK.DI;
  13. using TEAMModelOS.SDK.Extension;
  14. using TEAMModelOS.SDK;
  15. using TEAMModelOS.SDK.Helper.Common.StringHelper;
  16. using TEAMModelOS.Models;
  17. using Microsoft.Extensions.Options;
  18. using System.Text;
  19. using Azure.Messaging.ServiceBus;
  20. using Microsoft.Extensions.Configuration;
  21. using System.Linq;
  22. namespace TEAMModelOS.Controllers
  23. {
  24. [ProducesResponseType(StatusCodes.Status200OK)]
  25. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  26. //[Authorize(Roles = "IES5")]
  27. [Route("teacher/comment")]
  28. [ApiController]
  29. public class CommentController : ControllerBase
  30. {
  31. private readonly AzureCosmosFactory _azureCosmos;
  32. private readonly DingDing _dingDing;
  33. private readonly Option _option;
  34. private readonly AzureStorageFactory _azureStorage;
  35. public IConfiguration _configuration { get; set; }
  36. private readonly AzureServiceBusFactory _serviceBus;
  37. public CommentController(AzureCosmosFactory azureCosmos, DingDing dingDing, IOptionsSnapshot<Option> option, AzureStorageFactory azureStorage, AzureServiceBusFactory serviceBus, IConfiguration configuration)
  38. {
  39. _azureCosmos = azureCosmos;
  40. _dingDing = dingDing;
  41. _option = option?.Value;
  42. _azureStorage = azureStorage;
  43. _serviceBus = serviceBus;
  44. _configuration = configuration;
  45. }
  46. /// <summary>
  47. /// 添加教师评语快捷回复
  48. /// </summary>
  49. /// <param name="request"></param>
  50. /// <returns></returns>
  51. [ProducesDefaultResponseType]
  52. [HttpPost("add-comment")]
  53. public async Task<IActionResult> AddComment(JsonElement request)
  54. {
  55. //var id = "Comment-" + request.TEAMModelId.Replace("#", "");
  56. //ResponseBuilder builder = ResponseBuilder.custom();
  57. //List<Comment> comments = await _azureCosmos.FindByDict<Comment>(new Dictionary<string, object> { { "code", request.TEAMModelId }, { "id", id } });
  58. //Comment comment = new Comment();
  59. //if (comments.IsEmpty())
  60. //{
  61. // comment.id = id;
  62. // comment.code = request.TEAMModelId;
  63. // comment.comment.Add(request.comment);
  64. // comments.Add(comment);
  65. //}
  66. //else {
  67. // comment = comments[0];
  68. // comment.comment.Add(request.comment);
  69. //}
  70. //builder.Data(await _azureCosmos.SaveOrUpdate(comment));
  71. //return builder.build();
  72. //return Ok(await _azureCosmos.SaveOrUpdate(comment));
  73. return Ok();
  74. }
  75. /// <summary>
  76. /// 查询教师评语罐头
  77. /// </summary>
  78. /// <param name="request"></param>
  79. /// <returns></returns>
  80. [ProducesDefaultResponseType]
  81. [HttpPost("find-comment")]
  82. public async Task<IActionResult> findComment(JsonElement requert)
  83. {
  84. //var client = _azureCosmos.GetCosmosClient();
  85. //if (!requert.TryGetProperty("school_code", out JsonElement school_code)) return BadRequest();
  86. ////var (id, name, picture, _) = HttpContext.GetAuthTokenInfo();
  87. //if (!requert.TryGetProperty("id_token", out JsonElement id_token)) return BadRequest();
  88. //var jwt = new JwtSecurityToken(id_token.GetString());
  89. //if (!jwt.Payload.Iss.Equals("account.teammodel", StringComparison.Ordinal)) return BadRequest();
  90. //var id = jwt.Payload.Sub;
  91. //List<object> comments = new List<object>();
  92. //var query = $"select c.id,c.comment from c";
  93. //await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Comment-{id}") }))
  94. //{
  95. // using var json = await JsonDocument.ParseAsync(item.ContentStream);
  96. // if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  97. // {
  98. // foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  99. // {
  100. // comments.Add(obj.ToObject<object>());
  101. // }
  102. // }
  103. //}
  104. return Ok();
  105. }
  106. /// <summary>
  107. /// 更新保存教师评语罐头,如果评语列表为空则删除
  108. /// </summary>
  109. /// <param name="request"></param>
  110. /// <returns></returns>
  111. [ProducesDefaultResponseType]
  112. [HttpPost("upsert-comment")]
  113. public async Task<IActionResult> UpsertComment(Comment request)
  114. {
  115. // request.TryAdd("PartitionKey", request.lang);
  116. //ResponseBuilder builder = ResponseBuilder.custom();
  117. //Comment comment = null;
  118. //if (request.comment.Count > 0)
  119. //{
  120. // if (string.IsNullOrEmpty(request.id)) {
  121. // request.id = "Comment-" + request.code.Replace("#", "");
  122. // }
  123. // comment = await _azureCosmos.SaveOrUpdate<Comment>(request);
  124. //}
  125. //else {
  126. // if (!string.IsNullOrEmpty(request.id))
  127. // {
  128. // IdPk idPk = await _azureCosmos.DeleteAsync<Comment>(request.id, request.code);
  129. // }
  130. //}
  131. ////return builder.Data(comment).build();
  132. return Ok();
  133. }
  134. //批注
  135. [ProducesDefaultResponseType]
  136. //[AuthToken(Roles = "Teacher")]
  137. [HttpPost("upsert-answer")]
  138. public async Task<IActionResult> upsertAnswer(JsonElement request)
  139. {
  140. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  141. if (!request.TryGetProperty("mark", out JsonElement mark)) return BadRequest();
  142. if (!request.TryGetProperty("studentId", out JsonElement studentId)) return BadRequest();
  143. if (!request.TryGetProperty("tmdId", out JsonElement tId)) return BadRequest();
  144. if (!request.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  145. if (!request.TryGetProperty("classId", out JsonElement classId)) return BadRequest();
  146. if (!request.TryGetProperty("index", out JsonElement itemIndex)) return BadRequest();
  147. //根据不同评测的类型返回对应的编码
  148. if (!request.TryGetProperty("code", out JsonElement school)) return BadRequest();
  149. try
  150. {
  151. var client = _azureCosmos.GetCosmosClient();
  152. List<ExamClassResult> examClassResults = new List<ExamClassResult>();
  153. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(
  154. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}' and c.info.id = '{classId}'",
  155. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{school}") }))
  156. {
  157. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  158. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  159. {
  160. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  161. {
  162. examClassResults.Add(obj.ToObject<ExamClassResult>());
  163. }
  164. }
  165. }
  166. ExamClassResult classResult = new ExamClassResult();
  167. Details ans = mark.ToObject<Details>();
  168. List<List<string>> standard = new List<List<string>>();
  169. List<double> points = new List<double>();
  170. List<Task<string>> tasks = new List<Task<string>>();
  171. foreach (ExamClassResult result in examClassResults)
  172. {
  173. int index = result.studentIds.IndexOf(studentId.ToString());
  174. /*StringBuilder builder = new StringBuilder();
  175. builder.Append(result.examId).Append("/");
  176. builder.Append(result.subjectId).Append("/");
  177. builder.Append(studentId).Append("mark").Append("/");
  178. //builder.Append(tId).Append('/');
  179. builder.Append("ans.json");
  180. *//*string FileName = result.examId + "/" + result.subjectId + "/" + studentId;
  181. string blob = FileName + "/" + "ans.json";*//*
  182. tasks.Add(_azureStorage.UploadFileByContainer(school.ToString(), ans.ToJsonString(), "exam", builder.ToString(), false));
  183. //result.studentAnswers[newIndex].Add(builder.ToString());
  184. *//*string FileName = result.examId + "/" + result.subjectId + "/" + studentId + "mark";
  185. string blob = await _azureStorage.UploadFileByContainer(school.ToString(), ans.ToJsonString(), "exam", FileName + "/" + "ans.json");*//*
  186. //result.studentAnswers[index].Add(blob);*/
  187. List<Details> details = result.mark[index][itemIndex.GetInt32()];
  188. if (details.Count > 0)
  189. {
  190. List<Details> ds = details.Where(x => x.tmdId.Equals(tId.GetString())).ToList();
  191. if (ds.Count > 0)
  192. {
  193. foreach (Details de in ds)
  194. {
  195. if (de.tmdId.Equals(ans.tmdId))
  196. {
  197. de.mark = ans.mark;
  198. de.sc = ans.sc;
  199. //de.index = itemIndex.GetInt32();
  200. }
  201. }
  202. }
  203. else {
  204. result.mark[index][itemIndex.GetInt32()].Add(ans);
  205. }
  206. }
  207. else {
  208. result.mark[index][itemIndex.GetInt32()].Add(ans);
  209. }
  210. /*result.mark[index][itemIndex.GetInt32()].Add(ans);
  211. if (result.mark == null || result.mark.Count == 0)
  212. {
  213. List<List<string>> annotation = new List<List<string>>();
  214. foreach (string ids in result.studentIds)
  215. {
  216. annotation.Add(new List<string>());
  217. }
  218. result.mark = annotation;
  219. }
  220. result.mark[index].Add(builder.ToString());*/
  221. classResult = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(result, result.id, new PartitionKey($"{result.code}"));
  222. }
  223. await Task.WhenAll(tasks);
  224. /* //变更blob 大小
  225. ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new Azure.Cosmos.PartitionKey($"Exam-{school}"));
  226. info.size = await _azureStorage.GetBlobContainerClient(school.ToString()).GetBlobsSize($"exam/{id}");
  227. var messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "annotation", root = $"exam/{id}", name = school }.ToJsonString());
  228. messageBlob.ApplicationProperties.Add("name", "BlobRoot");
  229. var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
  230. await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);*/
  231. return Ok(new { classResult });
  232. }
  233. catch (Exception e)
  234. {
  235. await _dingDing.SendBotMsg($"OS,{_option.Location},teacher/comment/upsertAnswer()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  236. return BadRequest();
  237. }
  238. }
  239. /// <summary>
  240. /// 教师端,查询活动所有活动类型的列表,班主任,任课教师等
  241. /// 执教班级
  242. /// </summary>
  243. /// <param name="request">
  244. /// 教师tmdid !userid:"1255868536"
  245. ///学校编码 !school:"hbcn"
  246. ///执教的班级信息 !classes:[{"classid":"S-C-00001","scope":"school"},{"classid":"P-C-00004","scope":"private"}] TODO 需要排查 对象和班级字符串id设计原因 {"classid":"S-C-00001","scope":"school"}
  247. ///执教的科目 ?subjects:["subjectid1","subjectid2"]
  248. ///活动类型 !"pk":"Vote"/"Exam"/"Homework"/"Learn"/"Survey"" // Vote投票 Survey问卷 Exam评测 Learn学习活动 Homework作业活动
  249. ///时间筛选范围开始时间 默认30天之前 ?"stime":1608274766154
  250. ///时间筛选范围结束时间 默认当前时间 ?"etime":1608274766666
  251. ///每页大小 ?"count":10/null/Undefined
  252. ///分页Token ?"continuationToken":Undefined/null/"[{\"token\":\"+RID:~omxMAP3ipcSEEwAAAAAAAA==#RT:2#TRC:20#ISV:2#IEO:65551#QCF:1#FPC:AYQTAAAAAAAAiRMAAAAAAAA=\",\"range\":{\"min\":\"\",\"max\":\"FF\"}}]"
  253. ///当前状态 ?"progress":Undefined/null/"" 表示两种状态都要查询/ "going"/"finish" 表示查询进行中/ 或者已完成 学生端只能查询正在进行或已经结束 going 已发布|finish 已结束
  254. /// </param>
  255. /// <returns></returns>
  256. [ProducesDefaultResponseType]
  257. [HttpPost("tch-activity")]
  258. //[AuthToken(Roles = "teacher")]
  259. public async Task<IActionResult> TchActivity(JsonElement requert)
  260. {
  261. var (id, _, _, school) = HttpContext.GetAuthTokenInfo();
  262. if (string.IsNullOrWhiteSpace(school))
  263. {
  264. if (requert.TryGetProperty("school", out JsonElement schoolcode))
  265. {
  266. if (!schoolcode.ValueKind.Equals(JsonValueKind.Undefined) && !schoolcode.ValueKind.Equals(JsonValueKind.Null) && schoolcode.ValueKind.Equals(JsonValueKind.String))
  267. {
  268. school = schoolcode.GetString();
  269. }
  270. }
  271. }
  272. if (string.IsNullOrWhiteSpace(id))
  273. {
  274. if (requert.TryGetProperty("userid", out JsonElement userid))
  275. {
  276. if (!userid.ValueKind.Equals(JsonValueKind.Undefined) && !userid.ValueKind.Equals(JsonValueKind.Null) && userid.ValueKind.Equals(JsonValueKind.String))
  277. {
  278. id = userid.GetString();
  279. }
  280. }
  281. }
  282. //var stimestamp = DateTimeOffset.UtcNow.AddDays(-30).ToUnixTimeMilliseconds();
  283. //if (requert.TryGetProperty("stime", out JsonElement stime))
  284. //{
  285. // if (!stime.ValueKind.Equals(JsonValueKind.Undefined) && !stime.ValueKind.Equals(JsonValueKind.Null) && stime.TryGetInt64(out long data))
  286. // {
  287. // stimestamp = data;
  288. // }
  289. //}
  290. //string stimesql = $" c.startTime >= {stimestamp} ";
  291. //var etimestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  292. //string etimesql = $" and c.startTime <= {etimestamp} ";
  293. //var progresssql = "";
  294. //if (requert.TryGetProperty("progress", out JsonElement progress))
  295. //{
  296. // if (!progress.ValueKind.Equals(JsonValueKind.Undefined) && !progress.ValueKind.Equals(JsonValueKind.Null) && progress.ValueKind.Equals(JsonValueKind.String))
  297. // {
  298. // progresssql = $" and c.progress='{progress}' ";
  299. // }
  300. //}
  301. var pksql = "";
  302. string type = null;
  303. if (requert.TryGetProperty("pk", out JsonElement pk))
  304. {
  305. if (!pk.ValueKind.Equals(JsonValueKind.Undefined) && !pk.ValueKind.Equals(JsonValueKind.Null) && pk.ValueKind.Equals(JsonValueKind.String))
  306. {
  307. pksql = $" c.pk='{pk}' ";
  308. type = $"{pk}";
  309. }
  310. }
  311. if (string.IsNullOrEmpty(type)) { return BadRequest("type is required!"); }
  312. string continuationTokenSchool = null;
  313. //默认不指定返回大小
  314. int? topcout = null;
  315. if (requert.TryGetProperty("count", out JsonElement jcount))
  316. {
  317. if (!jcount.ValueKind.Equals(JsonValueKind.Undefined) && !jcount.ValueKind.Equals(JsonValueKind.Null) && jcount.TryGetInt32(out int data))
  318. {
  319. topcout = data;
  320. }
  321. }
  322. //是否需要进行分页查询,默认不分页
  323. bool iscontinuation = false;
  324. if (topcout != null && topcout.Value > 0)
  325. {
  326. iscontinuation = true;
  327. }
  328. //如果指定了返回大小
  329. if (requert.TryGetProperty("continuationTokenSchool", out JsonElement continuationSchool))
  330. {
  331. //指定了cancellationToken continuationSchool
  332. if (!continuationSchool.ValueKind.Equals(JsonValueKind.Null) && continuationSchool.ValueKind.Equals(JsonValueKind.String))
  333. {
  334. continuationTokenSchool = continuationSchool.GetString();
  335. }
  336. }
  337. //班级
  338. string joinSqlClasses = "";
  339. string andSqlClasses = "";
  340. List<string> classes = null;
  341. if (requert.TryGetProperty("classes", out JsonElement jclasses))
  342. {
  343. if (jclasses.ValueKind is JsonValueKind.Array)
  344. {
  345. classes = jclasses.ToObject<List<string>>();
  346. if (classes.IsNotEmpty())
  347. {
  348. joinSqlClasses = " join A1 in c.classes ";
  349. List<string> sqlList = new List<string>();
  350. classes.ForEach(x => { sqlList.Add($" '{x}' "); });
  351. string sql = string.Join(" , ", sqlList);
  352. andSqlClasses = $" A1 in ({sql}) ";
  353. }
  354. }
  355. }
  356. string classesSql = "";
  357. if (!string.IsNullOrWhiteSpace(joinSqlClasses))
  358. {
  359. classesSql = $" and {andSqlClasses } ";
  360. }
  361. //科目
  362. //string joinSqlSubjects = "";
  363. //string andSqlSubjects = "";
  364. //if (requert.TryGetProperty("subjects", out JsonElement jsubjects))
  365. //{
  366. // if (jsubjects.ValueKind is JsonValueKind.Array)
  367. // {
  368. // List<string> subjects = jsubjects.ToObject<List<string>>();
  369. // if (subjects.IsNotEmpty())
  370. // {
  371. // joinSqlSubjects = " join A2 in c.subjects ";
  372. // List<string> sqlList = new List<string>();
  373. // subjects.ForEach(x => { sqlList.Add($" '{x}' "); });
  374. // string sql = string.Join(" , ", sqlList);
  375. // andSqlSubjects = $" and A2 in ({sql}) ";
  376. // }
  377. // }
  378. //}
  379. List<JsonElement> datas = new List<JsonElement>();
  380. var client = _azureCosmos.GetCosmosClient();
  381. //班主任 ,任课教师只需要查询两种校园活动 和班级活动 , 不查询私人教室创建的活动。
  382. if (!string.IsNullOrWhiteSpace(school) && classes.IsNotEmpty())
  383. {
  384. //string querySchool = $" SELECT distinct value c FROM c {joinSqlClasses} {joinSqlSubjects} where {stimesql} {etimesql} {progresssql} {typesql} {andSqlSubjects} {tgSql}";
  385. string querySchool = $" SELECT distinct c.owner, c.id,c.code, c.classes,c.subjects,c.progress,c.scope,c.startTime,c.school,c.creatorId,c.name,c.pk ,c.endTime FROM c {joinSqlClasses} where {pksql} {classesSql}";
  386. //查询数据归属学校的
  387. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(querySchool, continuationToken: continuationTokenSchool, requestOptions: new QueryRequestOptions() { MaxItemCount = topcout, PartitionKey = new PartitionKey($"{type}-{school}") }))
  388. {
  389. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  390. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  391. {
  392. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  393. {
  394. datas.Add(obj.ToObject<JsonElement>());
  395. }
  396. //如果需要分页则跳出
  397. if (iscontinuation)
  398. {
  399. continuationTokenSchool = item.GetContinuationToken();
  400. break;
  401. }
  402. }
  403. }
  404. }
  405. string continuationTokenTeacher = null;
  406. //如果指定了返回大小
  407. if (requert.TryGetProperty("continuationTokenTeacher", out JsonElement continuationTeacher))
  408. {
  409. //指定了cancellationToken continuationSchool
  410. if (!continuationTeacher.ValueKind.Equals(JsonValueKind.Null) && continuationTeacher.ValueKind.Equals(JsonValueKind.String))
  411. {
  412. continuationTokenTeacher = continuationTeacher.GetString();
  413. }
  414. }
  415. string queryTeacher = $" SELECT distinct c.owner, c.id,c.code, c.classes,c.subjects,c.progress,c.scope,c.startTime,c.school,c.creatorId,c.name,c.pk ,c.endTime FROM c where {pksql} ";
  416. //查询数据归属学校的
  417. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryTeacher, continuationToken: continuationTokenSchool, requestOptions: new QueryRequestOptions() { MaxItemCount = topcout, PartitionKey = new PartitionKey($"{type}-{id}") }))
  418. {
  419. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  420. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  421. {
  422. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  423. {
  424. datas.Add(obj.ToObject<JsonElement>());
  425. }
  426. //如果需要分页则跳出
  427. if (iscontinuation)
  428. {
  429. continuationTokenTeacher = item.GetContinuationToken();
  430. break;
  431. }
  432. }
  433. }
  434. return Ok(new { datas, continuationTokenSchool, continuationTokenTeacher });
  435. }
  436. }
  437. }