TeacherController.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. using Azure.Cosmos;
  2. using Microsoft.AspNetCore.Http;
  3. using Microsoft.AspNetCore.Mvc;
  4. using Microsoft.Extensions.Options;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.IdentityModel.Tokens.Jwt;
  8. using System.IO;
  9. using System.Linq;
  10. using System.Text;
  11. using System.Text.Json;
  12. using System.Threading.Tasks;
  13. using TEAMModelOS.Models;
  14. using TEAMModelOS.Models.Dto;
  15. using TEAMModelOS.SDK.Models;
  16. using TEAMModelOS.SDK;
  17. using TEAMModelOS.SDK.DI;
  18. using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
  19. using TEAMModelOS.SDK.Extension;
  20. using TEAMModelOS.SDK.Helper.Common.StringHelper;
  21. using System.Dynamic;
  22. using Azure;
  23. using TEAMModelOS.SDK.Models.Cosmos.Common;
  24. using Azure.Messaging.ServiceBus;
  25. using Microsoft.Extensions.Configuration;
  26. using TEAMModelOS.Filter;
  27. using Azure.Storage.Blobs.Models;
  28. using HTEXLib.COMM.Helpers;
  29. using Microsoft.AspNetCore.Authorization;
  30. using System.Net.Http;
  31. using System.ComponentModel.DataAnnotations;
  32. namespace TEAMModelAPI.Controllers
  33. {
  34. [ProducesResponseType(StatusCodes.Status200OK)]
  35. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  36. [Route("{scope}")]
  37. [ApiController]
  38. public class TeacherController : ControllerBase
  39. {
  40. private AzureCosmosFactory _azureCosmos;
  41. private readonly DingDing _dingDing;
  42. private readonly Option _option;
  43. private readonly AzureServiceBusFactory _serviceBus;
  44. private readonly AzureStorageFactory _azureStorage;
  45. public IConfiguration _configuration { get; set; }
  46. private readonly CoreAPIHttpService _coreAPIHttpService;
  47. public TeacherController(CoreAPIHttpService coreAPIHttpService, AzureCosmosFactory azureCosmos, DingDing dingDing, IOptionsSnapshot<Option> option, AzureServiceBusFactory serviceBus, AzureStorageFactory azureStorage, IConfiguration configuration)
  48. {
  49. _azureCosmos = azureCosmos;
  50. _dingDing = dingDing;
  51. _option = option?.Value;
  52. _serviceBus = serviceBus;
  53. _configuration = configuration;
  54. _azureStorage = azureStorage;
  55. _coreAPIHttpService = coreAPIHttpService;
  56. }
  57. /// <summary>
  58. /// 获取学校教师列表
  59. /// </summary>
  60. /// <param name="request"></param>
  61. /// <returns></returns>
  62. [ProducesDefaultResponseType]
  63. [HttpPost("get-teacher-list")]
  64. [ApiToken(Auth = "1501", Name = "学校教师列表", RWN = "R", Limit = false)]
  65. public async Task<IActionResult> GetTeacherList(JsonElement json)
  66. {
  67. json.TryGetProperty("searchKey", out JsonElement _searchKey);
  68. List<CoreUser> coreUsers = new List<CoreUser>();
  69. IEnumerable<string> unexist = null;
  70. if (_searchKey.ValueKind.Equals(JsonValueKind.Array))
  71. {
  72. List<string> searchKey = _searchKey.ToObject<List<string>>();
  73. var keys = searchKey.Where(x => !string.IsNullOrWhiteSpace(x));
  74. var content = new StringContent(keys.ToJsonString(), Encoding.UTF8, "application/json");
  75. string ujson = await _coreAPIHttpService.GetUserInfos(content);
  76. if (!string.IsNullOrWhiteSpace(ujson))
  77. {
  78. coreUsers = ujson.ToObject<List<CoreUser>>();
  79. }
  80. if (coreUsers.Any())
  81. {
  82. unexist = searchKey.Except(coreUsers.Select(x => x.searchKey));
  83. }
  84. else
  85. {
  86. return Ok(new { error = 1, msg = "没有找到对应的教师信息!" });
  87. }
  88. }
  89. var (id, school) = HttpContext.GetApiTokenInfo();
  90. List<SchoolTeacher> teachers = new List<SchoolTeacher>();
  91. string insql = "";
  92. if (coreUsers.Any())
  93. {
  94. insql = $" c.id in ({string.Join(",", coreUsers.Select(x => $"'{ x.id}'"))}) ";
  95. }
  96. string sql = $"select c.id,c.name ,c.picture,c.job ,c.subjectIds,c.roles from c where {insql}";
  97. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<SchoolTeacher>
  98. (queryText: sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Teacher-{school}") }))
  99. {
  100. teachers.Add(item);
  101. }
  102. var teacherIds = coreUsers.Select(x => x.id).Except(teachers.Select(x => x.id));
  103. List<CoreUser> unjoined = coreUsers.FindAll(x => teacherIds.Contains(x.id));
  104. List<dynamic> tchs = new List<dynamic>();
  105. teachers.Select(x => new { x.id, x.name, x.picture, x.job, x.subjectIds, x.roles }).ToList().ForEach(x => {
  106. var coreUser = coreUsers.Find(c => c.id.Equals(x.id));
  107. if (coreUser != null)
  108. {
  109. tchs.Add(new { x.id, coreUser.name, coreUser.picture, x.job, x.subjectIds, x.roles, coreUser.searchKey, school });
  110. }
  111. });
  112. return Ok(new
  113. {
  114. teachers = tchs,
  115. unjoined = unjoined.Select(x => new { x.id, x.name, x.picture, x.searchKey }),
  116. unexist = unexist
  117. });
  118. }
  119. /// <summary>
  120. /// 获取学校教师信息
  121. /// </summary>
  122. /// <returns></returns>
  123. [ProducesDefaultResponseType]
  124. [HttpPost("get-teacher-info")]
  125. [ApiToken(Auth = "1502", Name = "学校教师信息", RWN = "R", Limit = false)]
  126. public async Task<IActionResult> GetTeacherInfo(JsonElement json)
  127. {
  128. json.TryGetProperty("tmdid", out JsonElement _tmdid);
  129. var (id, school) = HttpContext.GetApiTokenInfo();
  130. Azure.Response responseSchoolTch = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School")
  131. .ReadItemStreamAsync($"{_tmdid}", new PartitionKey($"Teacher-{school}"));
  132. Azure.Response responseTch = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher")
  133. .ReadItemStreamAsync($"{_tmdid}", new PartitionKey($"Base"));
  134. Teacher teacher = null;
  135. if (responseTch.Status == 200)
  136. {
  137. teacher = JsonDocument.Parse(responseTch.Content).RootElement.Deserialize<Teacher>();
  138. }
  139. else
  140. {
  141. return Ok(new { error = 3, msg = "账号未创建!" });
  142. }
  143. if (responseSchoolTch.Status == 200 && teacher != null)
  144. {
  145. SchoolTeacher schoolTeacher = JsonDocument.Parse(responseSchoolTch.Content).RootElement.Deserialize<SchoolTeacher>();
  146. return Ok(new { teacher.id, teacher.name, teacher.picture, schoolTeacher.job, schoolTeacher.status, schoolTeacher.roles, schoolTeacher.subjectIds, school = teacher.schools?.Find(x => x.schoolId.Equals(school)) });
  147. }
  148. else
  149. {
  150. return Ok(new { error = 1, msg = "教师未就职该学校!" });
  151. }
  152. }
  153. /// <summary>
  154. /// 批量导入教师信息,并加入学校。可以导入学科,但需要填写学段id
  155. /// </summary>
  156. /// <returns></returns>
  157. [ProducesDefaultResponseType]
  158. [HttpPost("import-school-teacher")]
  159. [ApiToken(Auth = "1503", Name = "批量导入教师", RWN = "R", Limit = false)]
  160. public async Task<IActionResult> ImportSchoolTeacher(ImportTechDto json)
  161. {
  162. //如果需要同时导入学科,则需要填写学段
  163. var (id, school) = HttpContext.GetApiTokenInfo();
  164. List<ImportTech> teachers = json.teachers;
  165. List<string> searchKey = teachers.Select(x => x.id).ToList();
  166. string ujson = null;
  167. var keys = searchKey.Where(x => !string.IsNullOrWhiteSpace(x));
  168. if (keys.Any())
  169. {
  170. var content = new StringContent(keys.ToJsonString(), Encoding.UTF8, "application/json");
  171. ujson = await _coreAPIHttpService.GetUserInfos(content);
  172. }
  173. List<CoreUser> coreUsers = new List<CoreUser>();
  174. if (!string.IsNullOrWhiteSpace(ujson))
  175. {
  176. coreUsers = ujson.ToObject<List<CoreUser>>();
  177. }
  178. IEnumerable<string> unexist = new List<string>();
  179. if (coreUsers.Any())
  180. {
  181. unexist = searchKey.Except(coreUsers.Select(x => x.id));
  182. }
  183. else
  184. {
  185. return Ok(new { error = 1, msg = "没有找到对应的教师信息!" });
  186. }
  187. var exist = coreUsers.Select(x => x.id);
  188. //注册了账号的教师
  189. teachers = teachers.Where(x => exist.Contains(x.id)).ToList();
  190. List<Teacher> teachersList = new List<Teacher>();
  191. List<SchoolTeacher> schoolTeachers = new List<SchoolTeacher>();
  192. string sql = $"select value(c) from c where c.id in ({string.Join(",", teachers.Select(x => $"'{x.id}'"))})";
  193. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher)
  194. .GetItemQueryIterator<Teacher>(queryText: sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base") }))
  195. {
  196. teachersList.Add(item);
  197. }
  198. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
  199. .GetItemQueryIterator<SchoolTeacher>(queryText: sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Teacher-{school}") }))
  200. {
  201. schoolTeachers.Add(item);
  202. }
  203. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  204. School data = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(school, new PartitionKey("Base"));
  205. //学校学科发生变化。
  206. List<SchoolTeacher> schoolTeachersAdd = new List<SchoolTeacher>();
  207. bool baseChange = false;
  208. foreach (var item in teachers)
  209. {
  210. var teacher = teachersList.Find(x => x.id.Equals(item.id));
  211. var coreUser = coreUsers.Find(x => x.id.Equals(item.id));
  212. if (teacher != null)
  213. {
  214. var sch = teacher.schools?.Find(x => x.schoolId.Equals(school));
  215. if (sch == null)
  216. {
  217. if (teacher.schools.IsNotEmpty())
  218. {
  219. teacher.schools.Add(new Teacher.TeacherSchool { schoolId = school, name = data.name, status = "invite", time = now, picture = data.picture, areaId = data.areaId });
  220. }
  221. else
  222. {
  223. teacher.defaultSchool = school;
  224. teacher.size = teacher.size + 1;
  225. teacher.schools = new List<Teacher.TeacherSchool> { new Teacher.TeacherSchool { schoolId = school, name = data.name, status = "invite", time = now, picture = data.picture, areaId = data.areaId } };
  226. }
  227. }
  228. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReplaceItemAsync<Teacher>(teacher, teacher.id, new PartitionKey("Base"));
  229. }
  230. else
  231. {
  232. teacher = new Teacher
  233. {
  234. createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
  235. id = coreUser.id,
  236. name = coreUser.name,
  237. picture = coreUser.picture,
  238. defaultSchool = school,
  239. size = 2,
  240. code = "Base",
  241. pk = "Base",
  242. schools = new List<Teacher.TeacherSchool> { new Teacher.TeacherSchool { schoolId = school, name = data.name, status = "invite", time = now, picture = data.picture, areaId = data.areaId } }
  243. };
  244. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).CreateItemAsync(teacher, new PartitionKey("Base"));
  245. }
  246. var schoolTeacher = schoolTeachers.Find(x => x.id.Equals(item.id));
  247. //处理导入的学科
  248. List<string> subjectIds = new List<string>();
  249. if (item.subjects.IsNotEmpty() && !string.IsNullOrWhiteSpace(item.periodId))
  250. {
  251. item.subjects.ForEach(s => {
  252. //同名学科
  253. var subject = data.period.Find(x => x.id.Equals(item.periodId))?.subjects?.Find(x => x.id.Equals(s.id));
  254. if (subject == null)
  255. {
  256. subject = data.period.Find(x => x.id.Equals(item.periodId))?.subjects?.Find(x => x.name.Equals(s.name));
  257. }
  258. else
  259. {
  260. subjectIds.Add(subject.id);
  261. }
  262. if (subject == null)
  263. {
  264. var period = data.period.Find(x => x.id.Equals(item.periodId));
  265. if (period != null)
  266. {
  267. period.subjects.Add(new Subject { id = s.id, name = s.name, type = 2 });
  268. subjectIds.Add(s.id);
  269. baseChange = true;
  270. }
  271. }
  272. });
  273. }
  274. if (schoolTeacher == null)
  275. {
  276. schoolTeacher = new SchoolTeacher
  277. {
  278. id = item.id,
  279. name = coreUser.name,
  280. picture = coreUser.picture,
  281. job = item.job,
  282. subjectIds = subjectIds,
  283. roles = new List<string> { "teacher" },
  284. permissions = new List<string> { "content-read", "exercise-read", "knowledge-read", "syllabus-read" },
  285. status = "invite",
  286. code = $"Teacher-{school}",
  287. pk = "Teacher",
  288. createTime = now,
  289. };
  290. schoolTeachersAdd.Add(schoolTeacher);
  291. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).CreateItemAsync(schoolTeacher, new PartitionKey(schoolTeacher.code));
  292. }
  293. else
  294. {
  295. if (subjectIds.IsNotEmpty())
  296. {
  297. subjectIds.ForEach(x => {
  298. if (!schoolTeacher.subjectIds.Contains(x))
  299. {
  300. schoolTeacher.subjectIds.Add(x);
  301. }
  302. });
  303. }
  304. schoolTeacher.job = string.IsNullOrWhiteSpace(item.job) ? schoolTeacher.job : item.job;
  305. schoolTeachersAdd.Add(schoolTeacher);
  306. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(schoolTeacher, schoolTeacher.id, new PartitionKey(schoolTeacher.code));
  307. }
  308. }
  309. if (baseChange)
  310. {
  311. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(data, data.id, new PartitionKey("Base"));
  312. }
  313. return Ok(new { teachers = schoolTeachersAdd.Select(x => new { x.id, x.name, x.picture, x.job, x.subjectIds, x.roles, school }) });
  314. }
  315. }
  316. public class ImportTechDto
  317. {
  318. public List<ImportTech> teachers { get; set; } = new List<ImportTech>();
  319. }
  320. public class ImportTech
  321. {
  322. [Required(ErrorMessage = "教师id必须设置")]
  323. public string id { get; set; }
  324. public List<ImportTechSubject> subjects { get; set; }
  325. [RegularExpression(@"[0-9a-zA-Z]{8}(-[0-9a-zA-Z]{4}){3}-[0-9a-zA-Z]{12}", ErrorMessage = "学段的uuid格式错误!")]
  326. public string periodId { get; set; }
  327. public string job { get; set; }
  328. }
  329. public class ImportTechSubject
  330. {
  331. [RegularExpression(@"[0-9a-zA-Z]{8}(-[0-9a-zA-Z]{4}){3}-[0-9a-zA-Z]{12}", ErrorMessage = "科目的uuid格式错误!")]
  332. public string id { get; set; }
  333. [Required(ErrorMessage = "科目名称 必须设置")]
  334. public string name { get; set; }
  335. }
  336. }