InitController.cs 86 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453
  1. using Azure.Cosmos;
  2. using Azure.Storage.Blobs.Models;
  3. using Azure.Storage.Sas;
  4. using Microsoft.AspNetCore.Http;
  5. using Microsoft.AspNetCore.Mvc;
  6. using Microsoft.Extensions.Options;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Dynamic;
  10. using System.IdentityModel.Tokens.Jwt;
  11. using System.IO;
  12. using System.Linq;
  13. using System.Text.Json;
  14. using System.Threading.Tasks;
  15. using TEAMModelOS.Models;
  16. using TEAMModelOS.SDK.Models;
  17. using TEAMModelOS.SDK.DI;
  18. using TEAMModelOS.SDK.Extension;
  19. using TEAMModelOS.Filter;
  20. using TEAMModelOS.SDK.Models.Cosmos;
  21. using HTEXLib.COMM.Helpers;
  22. using TEAMModelOS.SDK.Models.Service;
  23. using Microsoft.Extensions.Configuration;
  24. using System.Net.Http;
  25. using TEAMModelOS.SDK;
  26. using static TEAMModelOS.SDK.Models.Teacher;
  27. using TEAMModelOS.Services;
  28. using Microsoft.AspNetCore.Authorization;
  29. using System.Diagnostics;
  30. using Microsoft.Extensions.Logging;
  31. using System.Text;
  32. using Microsoft.Azure.Cosmos.Table;
  33. using Microsoft.AspNetCore.Hosting;
  34. using DocumentFormat.OpenXml.Office2010.Excel;
  35. using DocumentFormat.OpenXml.Drawing.Charts;
  36. using static TEAMModelOS.Controllers.FixDataController;
  37. using IdCode = TEAMModelOS.SDK.Models.IdCode;
  38. using TEAMModelOS.SDK.Models.Service.BI;
  39. using TEAMModelOS.SDK.Services;
  40. using static TEAMModelOS.Controllers.Client.HiTAControlller;
  41. namespace TEAMModelOS.Controllers
  42. {
  43. [ProducesResponseType(StatusCodes.Status200OK)]
  44. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  45. [Route("teacher/init")]
  46. [ApiController]
  47. public class InitController : ControllerBase
  48. {
  49. private readonly AzureCosmosFactory _azureCosmos;
  50. private readonly AzureStorageFactory _azureStorage;
  51. private readonly AzureRedisFactory _azureRedis;
  52. private readonly DingDing _dingDing;
  53. private readonly Option _option;
  54. private readonly IConfiguration _configuration;
  55. private readonly CoreAPIHttpService _coreAPIHttpService;
  56. private readonly IPSearcher _searcher;
  57. private readonly ILogger<InitController> _logger;
  58. private readonly HttpTrigger _httpTrigger;
  59. private readonly IWebHostEnvironment _environment;
  60. public InitController(IWebHostEnvironment environment,ILogger<InitController> logger, IPSearcher searcher, CoreAPIHttpService coreAPIHttpService, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration, HttpTrigger httpTrigger)
  61. {
  62. _searcher = searcher;
  63. _azureCosmos = azureCosmos;
  64. _azureStorage = azureStorage;
  65. _azureRedis = azureRedis;
  66. _dingDing = dingDing;
  67. _option = option?.Value;
  68. _configuration = configuration;
  69. _coreAPIHttpService = coreAPIHttpService;
  70. _logger = logger;
  71. _httpTrigger = httpTrigger;
  72. _environment = environment;
  73. }
  74. /// <summary>
  75. /// 修改教师信息
  76. /// </summary>
  77. /// <param name="request"></param>
  78. /// <returns></returns>
  79. [ProducesDefaultResponseType]
  80. [HttpPost("GetUserInfo")]
  81. //[Authorize(Roles = "IES")]
  82. public async Task<IActionResult> GetUserInfo(JsonElement request)
  83. {
  84. if (!request.TryGetProperty("key", out JsonElement key)) return BadRequest();
  85. var location = _option.Location;
  86. //https://api2-rc.teammodel.cn
  87. CoreUser core = await _coreAPIHttpService.GetUserInfo(new Dictionary<string, string>()
  88. { { "key",$"{key}" }
  89. }, location, _configuration
  90. );
  91. if (core != null)
  92. {
  93. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  94. TmdidImplicit tmdidImplicit = await _coreAPIHttpService.Implicit(new Dictionary<string, string> { { "grant_type", "implicit" },
  95. { "client_id",clientID },
  96. { "account",core.id },
  97. { "nonce",Guid.NewGuid().ToString()} }, _option.Location, _configuration);
  98. if (tmdidImplicit != null && !string.IsNullOrEmpty(tmdidImplicit.id_token))
  99. {
  100. return Ok(new { coreUser = core, tmdidImplicit });
  101. }
  102. }
  103. return Ok(new { coreUser = core });
  104. }
  105. /// <summary>
  106. /// 修改教师信息
  107. /// </summary>
  108. /// <param name="request"></param>
  109. /// <returns></returns>
  110. [ProducesDefaultResponseType]
  111. [HttpPost("set-teacher-info")]
  112. [AuthToken(Roles = "admin,teacher,area")]
  113. [Authorize(Roles = "IES")]
  114. public async Task<IActionResult> SetTeacherInfo(JsonElement request)
  115. {
  116. var client = _azureCosmos.GetCosmosClient();
  117. var tableClient = _azureStorage.GetCloudTableClient();
  118. var blobClient = _azureStorage.GetBlobContainerClient(containerName: "0-public");
  119. if (!request.TryGetProperty("opt", out JsonElement _opt))
  120. {
  121. return BadRequest();
  122. }
  123. var (userid, name, _, school) = HttpContext.GetAuthTokenInfo();
  124. try
  125. {
  126. switch (true)
  127. {
  128. //修改常用语系
  129. case bool when $"{_opt}".Equals("UpdateLang", StringComparison.OrdinalIgnoreCase) && (request.TryGetProperty("lang", out JsonElement lang)):
  130. {
  131. Teacher teacher = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Teacher>(userid, new PartitionKey("Base"));
  132. if (!string.IsNullOrEmpty($"{lang}"))
  133. {
  134. teacher.lang = $"{lang}";
  135. await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, userid, new PartitionKey("Base"));
  136. return Ok(new { teacher, status = 1 });
  137. }
  138. else
  139. {
  140. return BadRequest(new { status = -1, msg = "语系参数为空!" });
  141. }
  142. }
  143. //修改默认学校
  144. case bool when $"{_opt}".Equals("UpdateDefaultSchool", StringComparison.OrdinalIgnoreCase) && (request.TryGetProperty("defaultSchool", out JsonElement _defaultSchool)):
  145. {
  146. Teacher teacher = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Teacher>(userid, new PartitionKey("Base"));
  147. if (teacher.schools.Select(x => x.schoolId).Contains($"{_defaultSchool}") && !string.IsNullOrEmpty($"{_defaultSchool}"))
  148. {
  149. teacher.defaultSchool = $"{_defaultSchool}";
  150. await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, userid, new PartitionKey("Base"));
  151. return Ok(new { teacher, status = 1 });
  152. }
  153. else
  154. {
  155. return BadRequest(new { status = -1, msg = "您未加入该学校!" });
  156. }
  157. }
  158. //修改教师的最大课例保存数量
  159. case bool when $"{_opt}".Equals("UpdateLessonLimit", StringComparison.OrdinalIgnoreCase) && (request.TryGetProperty("lessonLimit", out JsonElement _lessonLimit)):
  160. {
  161. Teacher teacher = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Teacher>(userid, new PartitionKey("Base"));
  162. teacher.lessonLimit = int.Parse($"{_lessonLimit}");
  163. await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, userid, new PartitionKey("Base"));
  164. return Ok(new { teacher, status = 1 });
  165. }
  166. //修改教师设置自动将课例发布给谁的设置
  167. case bool when $"{_opt}".Equals("UpdateLessonShow", StringComparison.OrdinalIgnoreCase) && (request.TryGetProperty("lessonShow", out JsonElement _lessonShow)):
  168. {
  169. Teacher teacher = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Teacher>(userid, new PartitionKey("Base"));
  170. teacher.lessonShow = _lessonShow.Deserialize<List<string>>();
  171. await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, userid, new PartitionKey("Base"));
  172. return Ok(new { teacher, status = 1 });
  173. }
  174. //设置教师的科目信息
  175. case bool when $"{_opt}".Equals("SetTeacherSubject", StringComparison.OrdinalIgnoreCase) && request.TryGetProperty("targerTecher", out JsonElement _targetTecher)
  176. && request.TryGetProperty("subjectIds", out JsonElement _subjectIds):
  177. if (_subjectIds.ValueKind.Equals(JsonValueKind.Array))
  178. {
  179. if (_targetTecher.ValueKind.Equals(JsonValueKind.Array))
  180. {
  181. List<string> targetTechers = _targetTecher.ToObject<List<string>>();
  182. List<SchoolTeacher> schoolTeachers = new List<SchoolTeacher>();
  183. foreach (string targetTecher in targetTechers)
  184. {
  185. try
  186. {
  187. SchoolTeacher schoolTeacher = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<SchoolTeacher>($"{targetTecher}", new PartitionKey($"Teacher-{school}"));
  188. schoolTeacher.subjectIds = _subjectIds.ToObject<List<string>>();
  189. await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(schoolTeacher, $"{targetTecher}", new PartitionKey($"Teacher-{school}"));
  190. schoolTeachers.Add(schoolTeacher);
  191. }
  192. catch (Exception ex)
  193. {
  194. await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/init/set-teacher-info:SetTeacherSubject()\n{ex.Message}\n{ex.StackTrace}{request.ToJsonString()}-{targetTecher}", GroupNames.醍摩豆服務運維群組);
  195. }
  196. }
  197. return Ok(new { status = 1, schoolTeachers });
  198. }
  199. else
  200. {
  201. try
  202. {
  203. SchoolTeacher schoolTeacher = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<SchoolTeacher>($"{_targetTecher}", new PartitionKey($"Teacher-{school}"));
  204. schoolTeacher.subjectIds = _subjectIds.ToObject<List<string>>();
  205. await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(schoolTeacher, $"{_targetTecher}", new PartitionKey($"Teacher-{school}"));
  206. return Ok(new { status = 1, schoolTeacher });
  207. }
  208. catch (Exception ex)
  209. {
  210. await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/init/set-teacher-info:SetTeacherSubject()\n{ex.Message}\n{ex.StackTrace}{request.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
  211. return Ok(new { error = -1, msg = "设置失败" });
  212. }
  213. }
  214. }
  215. else
  216. {
  217. return Ok(new { error = -1, msg = "设置失败" });
  218. }
  219. ///移交管理员
  220. case bool when $"{_opt}".Equals("TransferAdminRole", StringComparison.OrdinalIgnoreCase) && (request.TryGetProperty("targerTecher", out JsonElement _targetTecher)):
  221. if (!string.IsNullOrEmpty(school) && !string.IsNullOrEmpty($"{_targetTecher}"))
  222. {
  223. StringBuilder strMsg = new($"{name}【{userid}】将");
  224. SchoolTeacher schoolTeacher = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<SchoolTeacher>(userid, new PartitionKey($"Teacher-{school}"));
  225. if (schoolTeacher.roles.IsNotEmpty() && schoolTeacher.roles.Contains("admin"))
  226. {
  227. schoolTeacher.roles.Remove("admin");
  228. SchoolTeacher newSchoolTeacher = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<SchoolTeacher>($"{_targetTecher}", new PartitionKey($"Teacher-{school}"));
  229. if (!newSchoolTeacher.roles.Contains("admin"))
  230. {
  231. newSchoolTeacher.roles.Add("admin");
  232. newSchoolTeacher = await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(newSchoolTeacher, $"{_targetTecher}", new PartitionKey($"Teacher-{school}"));
  233. }
  234. await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(schoolTeacher, userid, new PartitionKey($"Teacher-{school}"));
  235. string code = "transfer-admin";
  236. School schoolBase = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(school, new PartitionKey($"Base"));
  237. strMsg.Append($"学校{schoolBase.name}[{schoolBase.id}] 的管理员权限移交给");
  238. Teacher targetTeacher = await client.GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemAsync<Teacher>($"{_targetTecher}", new PartitionKey($"Base"));
  239. strMsg.Append($"{targetTeacher.name}[{targetTeacher.id}]");
  240. _coreAPIHttpService.PushNotify(new List<IdNameCode> { new IdNameCode { id= targetTeacher.id,name= targetTeacher.name,code=targetTeacher.lang} }, "transfer-admin_school", Constant.NotifyType_IES5_Management,
  241. new Dictionary<string, object> { { "tmdname", name },{ "schoolName", schoolBase.name }, { "schoolId", $"{school}" } , { "tmdid", userid } }, _option.Location, _configuration, _dingDing, _environment.ContentRootPath);
  242. // _ = _azureStorage.SaveLog("transfer-admin-role", new { request, userid, name, school, schoolName = schoolBase.name, targetTecher = _targetTecher, }.ToJsonString(), bizId: $"{userid}-{schoolBase.id}-{_targetTecher}", httpContext: HttpContext, dingDing: _dingDing, scope: "school");
  243. //保存日志
  244. Dictionary<string, object> replaceData = new() { { "oName" ,$"{name}" }, { "oId", $"{userid}" }, { "scName", $"{schoolBase.name}" }, { "scId", $"{schoolBase.id}" } , { "tName", $"{targetTeacher.name}" }, { "tId", $"{targetTeacher.id}" } };
  245. _ = _azureStorage.SaveLogLang("transfer-admin-role", _environment.ContentRootPath, replaceData, _dingDing, bizId: $"{userid}-{schoolBase.id}-{_targetTecher}", httpContext: HttpContext, scope: "school");
  246. //保存管理员移交至BI
  247. await AzureStorageBlobExtensions.SaveBILog(blobClient, tableClient, "school-transfer-admin", strMsg?.ToString(), _dingDing, twebsite: "IES5", httpContext: HttpContext);
  248. var adminAdd = new HashSet<string>();
  249. adminAdd.Add(newSchoolTeacher.id);
  250. var adminRmv = new HashSet<string>();
  251. adminRmv.Add(schoolTeacher.id);
  252. string head_lang = "";
  253. if (HttpContext.Request.Headers.TryGetValue("lang", out var _lang))
  254. {
  255. head_lang = $"{_lang}";
  256. }
  257. string lang = !string.IsNullOrWhiteSpace(head_lang) ? head_lang : _option.Location.Contains("China") ? "zh-cn" : "en-us";
  258. await _coreAPIHttpService.AdminChange(new AdminChange { school = school, adminAdd = adminAdd, adminRmv = adminRmv,lang= lang,adminType= "master" },_option.Location,_configuration,_dingDing);
  259. return Ok(new { status = 1 });
  260. }
  261. else
  262. {
  263. return BadRequest(new { status = -1, msg = "当前登录账号没有admin权限" });
  264. }
  265. }
  266. else
  267. {
  268. return BadRequest(new { status = -1, msg = "参数异常!" });
  269. }
  270. //修改教师其他信息。
  271. case bool when $"{_opt}".Equals("UpdateMoreInfo", StringComparison.OrdinalIgnoreCase) && (request.TryGetProperty("teacherInfo", out JsonElement _teacherInfo)):
  272. var techinfo = _teacherInfo.Deserialize<UpdateTeacherInfo>();
  273. TeacherImport teacherImport = null;
  274. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  275. if (techinfo != null && ! string.IsNullOrWhiteSpace(techinfo.id)) {
  276. try
  277. {
  278. SchoolTeacher schoolTeacher = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<SchoolTeacher>(techinfo.id, new PartitionKey($"Teacher-{school}"));
  279. schoolTeacher.subjectIds =techinfo.subjectIds!=null ? techinfo.subjectIds : schoolTeacher.subjectIds;
  280. schoolTeacher.job = techinfo.job!=null ? techinfo.job : schoolTeacher.job;
  281. schoolTeacher.periodId = techinfo.periodId!=null ? techinfo.periodId : schoolTeacher.periodId;
  282. await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(schoolTeacher, techinfo.id, new PartitionKey($"Teacher-{school}"));
  283. Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemStreamAsync($"{school}", new PartitionKey("TeacherImport"));
  284. if (response.Status == 200)
  285. {
  286. teacherImport = JsonDocument.Parse(response.Content).RootElement.Deserialize<TeacherImport>();
  287. var teacherImportInfo= teacherImport.teachers.Find(x =>!string.IsNullOrWhiteSpace(x.id) && x.id.Equals(techinfo.id));
  288. if (teacherImportInfo == null)
  289. {
  290. teacherImport.teachers.Add(new ImportTeacher
  291. {
  292. time = now,
  293. status = schoolTeacher.status,
  294. name = schoolTeacher.name,
  295. iname = techinfo.iname,
  296. picture = schoolTeacher.picture,
  297. tmdid = schoolTeacher.id,
  298. note = techinfo.note,
  299. id = techinfo.id
  300. });
  301. }
  302. else
  303. {
  304. teacherImportInfo.tmdid = schoolTeacher.id;
  305. teacherImportInfo.picture = schoolTeacher.picture;
  306. teacherImportInfo.status = schoolTeacher.status;
  307. teacherImportInfo.name = schoolTeacher.name;
  308. teacherImportInfo.iname= techinfo.iname !=null ? techinfo.iname:teacherImportInfo.iname;
  309. teacherImportInfo.note = techinfo.note != null ? techinfo.note : teacherImportInfo.note;
  310. }
  311. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(teacherImport, $"{school}", new PartitionKey("TeacherImport"));
  312. }
  313. else {
  314. teacherImport = new TeacherImport { id = $"{school}", code = "TeacherImport", pk = "TeacherImport", teachers = new List<ImportTeacher> { new ImportTeacher {
  315. time = now,
  316. status = schoolTeacher.status,
  317. name = schoolTeacher.name,
  318. iname = techinfo.iname,
  319. picture = schoolTeacher.picture,
  320. tmdid = schoolTeacher.id,
  321. note = techinfo.note,
  322. id = techinfo.id
  323. } } };
  324. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).CreateItemAsync(teacherImport, new PartitionKey("TeacherImport"));
  325. }
  326. return Ok(new { status = 1 });
  327. }
  328. catch (Exception ex)
  329. {
  330. await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/init/set-teacher-info:SetTeacherSubject()\n{ex.Message}\n{ex.StackTrace}{request.ToJsonString()}\n{school}", GroupNames.醍摩豆服務運維群組);
  331. }
  332. }
  333. return BadRequest(new { status = -1, msg = "参数异常!" });
  334. case bool when $"{_opt}".Equals("QuitSchool", StringComparison.OrdinalIgnoreCase) && request.TryGetProperty("schoolCode", out JsonElement _schoolCode) :
  335. School qschool= await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>($"{_schoolCode}", new PartitionKey("Base"));
  336. string sql = $"select value c from c where c.code='Teacher-{_schoolCode}' and c.status='join' and (c.id ='{userid}' or array_contains(c.roles,'admin'))";
  337. List<SchoolTeacher> adminTeachers = new List<SchoolTeacher>();
  338. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetItemQueryIterator<SchoolTeacher>(queryText: sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Teacher-{_schoolCode}") }))
  339. {
  340. adminTeachers.Add(item);
  341. }
  342. var steacher= adminTeachers.Find(z => z.id.Equals(userid));
  343. if (steacher != null)
  344. {
  345. if (!steacher.roles.Contains("admin"))
  346. {
  347. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).DeleteItemStreamAsync(steacher.id, new Azure.Cosmos.PartitionKey(steacher.code));
  348. Teacher qteacher = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemAsync<Teacher>($"{userid}", new PartitionKey("Base"));
  349. var a = qteacher.schools.RemoveAll(z => z.schoolId.Equals($"{_schoolCode}"));
  350. if (a > 0)
  351. {
  352. qteacher.defaultSchool = null;
  353. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReplaceItemAsync<Teacher>(qteacher, qteacher.id, new PartitionKey("Base"));
  354. }
  355. var tmdadmin = adminTeachers.FindAll(z => z.roles.Contains("admin") && !z.id.Equals(userid));
  356. if (tmdadmin.IsNotEmpty()) {
  357. List<IdNameCode> ids = new List<IdNameCode>();
  358. string sqlAdmin = $"select c.id,c.lang as code ,c.name from c where c.id in ({string.Join(",",tmdadmin.Select(z=>$"'{z.id}'"))}) ";
  359. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher)
  360. .GetItemQueryIterator<IdNameCode>(queryText: sqlAdmin, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Base") }))
  361. {
  362. ids.Add(item);
  363. }
  364. _coreAPIHttpService.PushNotify(ids, $"quit_school", Constant.NotifyType_IES5_Management,
  365. new Dictionary<string, object> { { "tmdname", name }, { "schoolName", qschool.name }, { "schoolId", $"{_schoolCode}" }, { "tmdid", userid } }, _option.Location, _configuration, _dingDing, _environment.ContentRootPath);
  366. // return Ok(new { status =0, msg = "退出成功!"/*, msg = "申请成功!"*/ });
  367. }
  368. return Ok(new { status = 0, msg = "退出成功!" });
  369. }
  370. else
  371. {
  372. return Ok(new { status = 2, msg = "请先移交管理员后再退出学校!" });
  373. }
  374. }
  375. else {
  376. Teacher qteacher = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemAsync<Teacher>($"{userid}", new PartitionKey("Base"));
  377. var a = qteacher.schools.RemoveAll(z => z.schoolId.Equals($"{_schoolCode}"));
  378. if (a > 0)
  379. {
  380. qteacher.defaultSchool = null;
  381. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReplaceItemAsync<Teacher>(qteacher,qteacher.id, new PartitionKey("Base"));
  382. return Ok(new { status = 4, msg = "退出成功!" });
  383. }
  384. else {
  385. return Ok(new { status = 1, msg = "未加入学校!" });
  386. }
  387. }
  388. }
  389. }
  390. catch (Exception ex)
  391. {
  392. await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/init/set-teacher-info()\n{ex.Message}\n{ex.StackTrace}{request.ToJsonString()}\n{school}", GroupNames.醍摩豆服務運維群組);
  393. return BadRequest("teacher not exist");
  394. }
  395. return BadRequest();
  396. }
  397. public class UpdateTeacherInfo {
  398. public string id { get; set; }
  399. public string iname { get; set; }
  400. public string periodId { get; set; }
  401. public List<string> subjectIds { get; set; } = new List<string>();
  402. public string job { get; set; }
  403. public string note { get; set; }
  404. }
  405. //TODO 此API需處理對應前端返回的相關數據
  406. [ProducesDefaultResponseType]
  407. [Authorize(Roles = "IES")]
  408. [HttpPost("get-teacher-info")]
  409. public async Task<IActionResult> GetTeacherInfo(JsonElement request)
  410. {
  411. string head_lang = "";
  412. if (HttpContext.Request.Headers.TryGetValue("lang", out var _lang)) {
  413. head_lang = $"{_lang}";
  414. }
  415. string OAuthShow_domain = HttpContext?.Request?.Host.Host;
  416. if (OAuthShow_domain.Equals("teammodelos.chinacloudsites.cn"))
  417. {
  418. OAuthShow_domain = _option.HostName;
  419. }
  420. if (_option.Location.Equals("China"))
  421. {
  422. OAuthShow_domain = _option.HostName;
  423. }
  424. if (OAuthShow_domain.Equals("localhost"))
  425. {
  426. OAuthShow_domain = "test.teammodel.cn";
  427. }
  428. if (!request.TryGetProperty("id_token", out JsonElement id_token)) return BadRequest();
  429. var jwt = new JwtSecurityToken(id_token.GetString());
  430. //TODO 此驗證IdToken先簡單檢查,後面需向Core ID新API,驗證Token
  431. var id = jwt.Payload.Sub;
  432. jwt.Payload.TryGetValue("name", out object name);
  433. jwt.Payload.TryGetValue("picture", out object picture);
  434. jwt.Payload.TryGetValue("lang", out object _jwtlang);
  435. head_lang = !string.IsNullOrWhiteSpace($"{_jwtlang}") ? $"{_jwtlang}" : head_lang;
  436. (string ip, string region) = await LoginService.LoginIp(HttpContext, _searcher);
  437. try
  438. {
  439. Teacher teacher = null;
  440. TeacherInfo teacherInfo = await TeacherService.TeacherInfo(_azureCosmos, teacher, $"{name}", $"{picture}", id, _azureStorage, _option, _azureRedis, ip, _httpTrigger, $"{_lang}");
  441. teacherInfo.areas.ForEach(x => { if (x.setting != null) { x.setting.accessConfig = x.setting.accessConfig; } });
  442. LoginService.LoginLog(HttpContext, _option, _logger, _dingDing, ip, region, id, $"{name}", 200);
  443. int lessonLimit = teacherInfo.teacher.lessonLimit;
  444. if (teacherInfo.teacher.lessonLimit == 0)
  445. {
  446. //未设置的的采用系统设置的默认值30
  447. lessonLimit = Constant.private_lesson_limit;
  448. }
  449. var table = _azureStorage.GetCloudTableClient().GetTableReference("IESOAuth");
  450. List<string> Codes = new List<string>();
  451. if (!string.IsNullOrWhiteSpace(id))
  452. {
  453. Codes.Add($" Code {QueryComparisons.Equal} '{id}' ");
  454. }
  455. string qurey = $"PartitionKey {QueryComparisons.Equal} 'OAuthShow' and Domain {QueryComparisons.Equal} '{OAuthShow_domain}' and ( { string.Join(" or ", Codes)} ) ";
  456. var result = await table.ExecuteQuerySegmentedAsync(new TableQuery<OAuthShow>().Where(qurey), null);
  457. List<OAuthShow> shows = result.Results;
  458. string lang = !string.IsNullOrWhiteSpace(teacherInfo.teacher.lang) ? teacherInfo.teacher.lang : head_lang;
  459. //返回剩余空间
  460. (long usedSize, long teach, long total, long surplus, Dictionary<string, double?> catalog) space =
  461. await BlobService.GetSurplusSpace(teacherInfo.teacher.id, "private", _option.Location, _azureCosmos, _azureRedis, _azureStorage, _dingDing, _httpTrigger);
  462. if (string.IsNullOrWhiteSpace(lang))
  463. {
  464. if (_option.Location.Contains("China"))
  465. {
  466. lang = "zh-cn";
  467. }
  468. else
  469. {
  470. lang = "en-us";
  471. }
  472. }
  473. else {
  474. if (lang.Equals("null")) {
  475. if (_option.Location.Contains("China"))
  476. {
  477. lang = "zh-cn";
  478. }
  479. else
  480. {
  481. lang = "en-us";
  482. }
  483. }
  484. }
  485. return Ok(new
  486. {
  487. lang=lang,
  488. privateShows = shows?.FindAll(x => x.Scope.Equals("private")).Select(x => new { x.Type, x.Status, x.Scope, x.Code }),
  489. location = _option.Location,
  490. teacherInfo.auth_token,
  491. teacherInfo.blob_uri,
  492. teacherInfo.blob_sas,
  493. teacherInfo.schools,
  494. teacherInfo.defaultschool,
  495. teacherInfo.defaultschoolPeriod,
  496. teacherInfo.courses,
  497. teacherInfo.total,
  498. teacherInfo.osblob_uri,
  499. teacherInfo.osblob_sas,
  500. teacherInfo.tsize,
  501. status = 200,
  502. teacherInfo.areas,
  503. lessonLimit,
  504. teacherInfo.teacher.lessonShow,
  505. privateSpace= new { size = space.usedSize, catalog = space.catalog, teach = space.teach, surplus = space.surplus, total = space.total },
  506. schoolSpace = new { size = 0, catalog = 0, teach = 0, surplus = 0, total = 0 }
  507. });
  508. }
  509. catch (CosmosException ex)
  510. {
  511. LoginService.LoginLog(HttpContext, _option, _logger, _dingDing, ip, region, id, $"{name}", 500);
  512. await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/GetTeacherInfo()\n{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  513. return BadRequest();
  514. }
  515. catch (Exception ex)
  516. {
  517. LoginService.LoginLog(HttpContext, _option, _logger, _dingDing, ip, region, id, $"{name}", 500);
  518. _ = _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/GetTeacherInfo()\n{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  519. return BadRequest();
  520. }
  521. }
  522. //TODO 此API需處理對應前端返回的相關數據
  523. [ProducesDefaultResponseType]
  524. [Authorize(Roles = "IES")]
  525. [HttpPost("get-school-info")]
  526. public async Task<IActionResult> GetSchoolInfo(JsonElement request)
  527. {
  528. string OAuthShow_domain = HttpContext?.Request?.Host.Host;
  529. if (OAuthShow_domain.Equals("teammodelos.chinacloudsites.cn") ) {
  530. OAuthShow_domain = _option.HostName;
  531. }
  532. if (_option.Location.Equals("China"))
  533. {
  534. OAuthShow_domain = _option.HostName;
  535. }
  536. if (OAuthShow_domain.Equals("localhost")) {
  537. OAuthShow_domain = "test.teammodel.cn";
  538. }
  539. try
  540. {
  541. if (!request.TryGetProperty("id_token", out JsonElement id_token)) return BadRequest();
  542. if (!request.TryGetProperty("school_code", out JsonElement _school_code)) return BadRequest();
  543. string school_code = $"{_school_code}";
  544. var jwt = new JwtSecurityToken(id_token.GetString());
  545. var id = jwt.Payload.Sub;
  546. var client = _azureCosmos.GetCosmosClient();
  547. //權限token
  548. jwt.Payload.TryGetValue("name", out object name);
  549. jwt.Payload.TryGetValue("picture", out object picture);
  550. List<string> roles = new List<string>();
  551. List<string> permissions = new List<string>();
  552. int size = 0;
  553. Teacher teacher = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Teacher>(id, new PartitionKey("Base"));
  554. List<AreaDto> areas = new List<AreaDto>();
  555. HashSet<string> areaIds = new HashSet<string>();
  556. if (teacher.areas.IsNotEmpty())
  557. {
  558. teacher.areas.ForEach(x => {
  559. areaIds.Add(x.areaId);
  560. });
  561. }
  562. if (teacher.schools.IsNotEmpty())
  563. {
  564. teacher.schools.ForEach(x => {
  565. if (!string.IsNullOrEmpty(x.areaId))
  566. {
  567. areaIds.Add(x.areaId);
  568. }
  569. });
  570. }
  571. List<Area> areasDbs = new List<Area>();
  572. List<AreaSetting> areaSettings = new List<AreaSetting>();
  573. if (areaIds.Count > 0)
  574. {
  575. string queryText = $"select value(c) from c where c.id in ({string.Join(",", areaIds.Select(x => $"'{x}'"))})";
  576. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Area>(queryText: queryText, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base-Area") }))
  577. {
  578. areasDbs.Add(item);
  579. }
  580. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<AreaSetting>(queryText: queryText, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("AreaSetting") }))
  581. {
  582. areaSettings.Add(item);
  583. }
  584. }
  585. if (teacher.areas.IsNotEmpty())
  586. {
  587. foreach (var areat in teacher.areas)
  588. {
  589. Area area = areasDbs.Find(x => x.id.Equals(areat.areaId));
  590. AreaSetting setting = null;
  591. if (area != null)
  592. {
  593. setting = areaSettings.Find(x => x.id.Equals(areat.areaId));
  594. }
  595. int access = 0;
  596. if (setting != null && !string.IsNullOrWhiteSpace(setting.accessConfig))
  597. {
  598. access = 1;
  599. }
  600. //if (setting != null)
  601. //{
  602. // setting.accessConfig = null;
  603. //}
  604. areas.Add(new AreaDto { areaId = area?.id, name = area?.name, standard = area?.standard, standardName = area?.standardName, setting = setting, access = access });
  605. }
  606. }
  607. if (school_code.Equals(teacher.defaultSchool) && teacher.schools.IsNotEmpty() && !teacher.schools.Select(x => x.schoolId).Contains(school_code))
  608. {
  609. school_code = teacher.schools[0].schoolId;
  610. teacher.defaultSchool = school_code;
  611. teacher = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, id, new PartitionKey("Base"));
  612. }
  613. var response = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(id, new PartitionKey($"Teacher-{school_code}"));
  614. string defaultPeriodId = "";
  615. if (response.Status == 200)
  616. {
  617. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  618. if (json.RootElement.TryGetProperty("size", out JsonElement _size) && _size.ValueKind == JsonValueKind.Number)
  619. {
  620. size = _size.GetInt32();
  621. }
  622. if (json.RootElement.TryGetProperty("periodId", out JsonElement _periodId))
  623. {
  624. defaultPeriodId =$"{_periodId}";
  625. }
  626. if (json.RootElement.TryGetProperty("roles", out JsonElement _roles) && _roles.ValueKind != JsonValueKind.Null)
  627. {
  628. foreach (var obj in _roles.EnumerateArray())
  629. {
  630. roles.Add(obj.GetString());
  631. }
  632. }
  633. if (json.RootElement.TryGetProperty("permissions", out JsonElement _permissions) && _permissions.ValueKind != JsonValueKind.Null)
  634. {
  635. foreach (var obj in _permissions.EnumerateArray())
  636. {
  637. permissions.Add(obj.GetString());
  638. }
  639. }
  640. var scteacher = json.RootElement.ToObject<SchoolTeacher>();
  641. if (!$"{teacher.name}".Equals($"{scteacher?.name}") || !$"{teacher.picture}".Equals($"{scteacher?.picture}")) {
  642. scteacher.name=teacher.name;
  643. scteacher.picture=teacher.picture;
  644. await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(scteacher, scteacher.id, new PartitionKey(scteacher.code));
  645. }
  646. }
  647. else //無此學校資料
  648. {
  649. }
  650. if (roles.Count == 0)
  651. {
  652. //助理,管家
  653. //roles.Add("assist");
  654. roles.Add("teacher");
  655. }
  656. //TODO JJ,调整为取得学校基础设置数据,取代下方學校學制、年級
  657. School school_base = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{school_code}", new PartitionKey("Base"));
  658. foreach (var period in school_base.period)
  659. {
  660. try
  661. {
  662. await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<ItemCond>($"{period.id}", new PartitionKey($"ItemCond-{school_code}"));
  663. }
  664. catch (CosmosException)
  665. {
  666. ItemCond itemCond = new ItemCond
  667. {
  668. id = period.id,
  669. pk = "ItemCond",
  670. code = $"ItemCond-{school_code}",
  671. ttl = -1,
  672. };
  673. try
  674. {
  675. await client.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<ItemCond>(itemCond, new PartitionKey($"ItemCond-{school_code}"));
  676. }
  677. catch (CosmosException ex) when (ex.Status == 409)
  678. {
  679. continue;
  680. }
  681. }
  682. }
  683. string currAreaId = "";
  684. dynamic currArea = new ExpandoObject();
  685. if (!string.IsNullOrEmpty(school_base.areaId))
  686. {
  687. try
  688. {
  689. Area area = areasDbs.Find(x => x.id.Equals(school_base.areaId));
  690. AreaSetting setting = null;
  691. if (area != null)
  692. {
  693. //setting =await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<AreaSetting>(school_base.areaId, new PartitionKey("AreaSetting"));
  694. setting = areaSettings.Find(x => x.id.Equals(school_base.areaId));
  695. }
  696. int access = 0;
  697. AccessConfig accessConfig = null;
  698. if (setting != null && !string.IsNullOrWhiteSpace(setting.accessConfig))
  699. {
  700. access = 1;
  701. accessConfig = setting.accessConfig.ToObject<AccessConfig>();
  702. }
  703. //if (setting!=null&& !string.IsNullOrEmpty(setting.accessConfig)) {
  704. // setting.accessConfig = null;
  705. //}
  706. currArea = new
  707. {
  708. areaId = area?.id,
  709. name = area?.name,
  710. standard = area?.standard,
  711. standardName = area?.standardName,
  712. setting = setting,
  713. access = access,
  714. //submitType=accessConfig?.submitType,
  715. homeworkType = accessConfig != null && accessConfig.homeworkType.IsNotEmpty() ? accessConfig.homeworkType : new List<string> { "pdf" },
  716. };
  717. currAreaId = area?.id;
  718. }
  719. catch (CosmosException)
  720. {
  721. //数据库捞不到数据
  722. }
  723. }
  724. if (areas.Count > 0)
  725. {
  726. roles.Add("area");
  727. }
  728. //TODO JJ,更新Token时,在取得学校资讯时,没有传入schoolId
  729. var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id, name?.ToString(), picture?.ToString(), _option.JwtSecretKey, Website: "IES", scope: Constant.ScopeTeacher, schoolID: school_code.ToString(), areaId: currAreaId, standard: school_base.standard, roles: roles.ToArray(), permissions: permissions.ToArray(), expire: 1);
  730. //取得班级
  731. (List < Class > school_classes,_) = await SchoolService.DoGraduateClasses(_httpTrigger, _azureCosmos, null, school_base, _option,_dingDing);
  732. //取得教室
  733. List<Room> school_rooms = new List<Room>();
  734. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<Room>(queryText: $"select value(c) from c ",
  735. requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Room-{school_code}") }))
  736. {
  737. school_rooms.Add(item);
  738. }
  739. //該老師排定的學校課程
  740. List<object> school_courses = new List<object>();
  741. var query = $"SELECT distinct value(c) FROM c JOIN A1 IN c.schedule where A1.teacherId='{id}'";
  742. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Course-{school_code}") }))
  743. {
  744. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  745. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  746. {
  747. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  748. {
  749. school_courses.Add(obj.ToObject<object>());
  750. }
  751. }
  752. }
  753. List<SchoolProductSumData> services = new List<SchoolProductSumData>();
  754. //获取HiTeachCC的授权
  755. int cc_avaliable = 0;
  756. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<int>("select value count(1) from c where c.prodCode='LZLL6ZEI'",
  757. requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Product-{school_code}") }))
  758. {
  759. cc_avaliable = item;
  760. }
  761. services.Add(new SchoolProductSumData { prodCode = "LZLL6ZEI", avaliable = cc_avaliable });
  762. Azure.Response productSumResponse = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(school_code, new PartitionKey("ProductSum"));
  763. if (productSumResponse.Status == 200)
  764. {
  765. var doc = JsonDocument.Parse(productSumResponse.Content);
  766. //if (doc.RootElement.TryGetProperty("serial", out JsonElement serial))
  767. //{
  768. // serials = serial.ToObject<List<SchoolProductSumData>>();
  769. //}
  770. if (doc.RootElement.TryGetProperty("service", out JsonElement service))
  771. {
  772. services .AddRange(service.ToObject<List<SchoolProductSumData>>());
  773. }
  774. }
  775. //校本課綱 [式樣未定 先不取]
  776. //取得School Blob 容器位置及SAS
  777. string school_code_blob = school_code.ToLower();
  778. var container = _azureStorage.GetBlobContainerClient(school_code_blob);
  779. await container.CreateIfNotExistsAsync(PublicAccessType.None); //嘗試創建School容器,如存在則不做任何事,保障容器一定存在
  780. var (blob_uri, blob_sas) = (roles.Contains("admin") || permissions.Contains("schoolAc-upd")) ? _azureStorage.GetBlobContainerSAS(school_code_blob, BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List | BlobContainerSasPermissions.Delete) : _azureStorage.GetBlobContainerSAS(school_code_blob, BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List | BlobContainerSasPermissions.Write);
  781. ///https://teammodelstorage.blob.core.chinacloudapi.cn/teammodelos
  782. var (osblob_uri, osblob_sas) = roles.Contains("area") ? _azureStorage.GetBlobContainerSAS("teammodelos", BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List | BlobContainerSasPermissions.Delete) : _azureStorage.GetBlobContainerSAS("teammodelos", BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List);
  783. areas.ForEach(x => { { if (x.setting != null) { x.setting.accessConfig = x.setting.accessConfig; } } });
  784. int lessonLimit = teacher.lessonLimit;
  785. if (teacher.lessonLimit == 0)
  786. {
  787. //未设置的的采用系统设置的默认值30
  788. lessonLimit = Constant.private_lesson_limit;
  789. }
  790. var table = _azureStorage.GetCloudTableClient().GetTableReference("IESOAuth");
  791. List<string> Codes = new List<string>();
  792. if (!string.IsNullOrWhiteSpace(id))
  793. {
  794. Codes.Add($" Code {QueryComparisons.Equal} '{id}' ");
  795. }
  796. if (!string.IsNullOrWhiteSpace(school_code))
  797. {
  798. Codes.Add($" Code {QueryComparisons.Equal} '{school_code}' ");
  799. }
  800. if (!string.IsNullOrWhiteSpace(currAreaId))
  801. {
  802. Codes.Add($" Code {QueryComparisons.Equal} '{currAreaId}' ");
  803. }
  804. string tbqurey = $"PartitionKey {QueryComparisons.Equal} 'OAuthShow' and Domain {QueryComparisons.Equal} '{OAuthShow_domain}' and ( { string.Join(" or ", Codes)} ) ";
  805. var result = await table.ExecuteQuerySegmentedAsync(new TableQuery<OAuthShow>().Where(tbqurey), null);
  806. List<OAuthShow> shows = result.Results;
  807. List<OAuthShow> schoolShow = new List<OAuthShow>();
  808. List<OAuthShow> areaShow = new List<OAuthShow>();
  809. var schoolShows = shows?.Where(y => !y.Scope.Equals("private"));
  810. if (schoolShows.Any())
  811. {
  812. //剩下的area 和school 的。统一处理为school的,并去重。
  813. schoolShows.ToList().ForEach(y => { y.Scope = "school"; y.Code = school_code; });
  814. schoolShows.GroupBy(x => $"{x.Type}{x.Scope}").Select(s => new { key = s.Key, list = s.ToList() }).ToList().ForEach(z => {
  815. schoolShow.Add(z.list.First());
  816. });
  817. }
  818. //只有管理员才能进行艺术评价相关设置关联。
  819. List<IdCode> hasArt = new List<IdCode>();
  820. if (roles.Contains("admin"))
  821. {
  822. if (schoolShows.Where(x => x.Type.Equals("art")).Any())
  823. {
  824. school_base?.period.ForEach(x => {
  825. var has_music = x?.subjects.Find(x => !string.IsNullOrWhiteSpace(x.bindId) && x.bindId.Equals("subject_music"));
  826. if (has_music == null)
  827. {
  828. hasArt.Add(new IdCode { id = x.id, code = "subject_music" });
  829. }
  830. var has_painting = x.subjects.Find(x => !string.IsNullOrWhiteSpace(x.bindId) && x.bindId.Equals("subject_painting"));
  831. if (has_painting == null)
  832. {
  833. hasArt.Add(new IdCode { id = x.id, code = "subject_painting" });
  834. }
  835. });
  836. }
  837. }
  838. List<OAuthShow> areaShows = new List<OAuthShow>();
  839. //处理区级是否有艺术评价模组授权
  840. if (areas.IsNotEmpty())
  841. {
  842. List<string> area_Codes = new List<string>();
  843. areas.ForEach(x => {
  844. area_Codes.Add($" Code {QueryComparisons.Equal} '{x.areaId}' ");
  845. });
  846. string area_tbqurey = $"PartitionKey {QueryComparisons.Equal} 'OAuthShow' and Domain {QueryComparisons.Equal} '{OAuthShow_domain}' and Type {QueryComparisons.Equal} 'art' and ( {string.Join(" or ", area_Codes)} ) ";
  847. var area_result = await table.ExecuteQuerySegmentedAsync(new TableQuery<OAuthShow>().Where(area_tbqurey), null);
  848. areaShows = area_result.Results;
  849. }
  850. //返回剩余空间
  851. (long usedSize, long teach, long total, long surplus, Dictionary<string, double?> catalog) space =
  852. await BlobService.GetSurplusSpace(school_base.id, "school", _option.Location, _azureCosmos, _azureRedis, _azureStorage, _dingDing, _httpTrigger);
  853. //学校版本处理
  854. _ = BISchoolService.UpSchoolEdition(client, _dingDing, services.Select(s => s.prodCode).ToList(), $"{school_code}");
  855. return Ok(new
  856. {
  857. privateShows = shows?.FindAll(x => x.Scope.Equals("private")).Select(x => new { x.Type, x.Status, x.Scope, x.Code }),
  858. schoolShows = schoolShow.Select(x => new { x.Type, x.Status, x.Scope, x.Code }),
  859. areaShows = areaShows.Select(x => new { x.Type, x.Status, x.Scope, x.Code }),
  860. auth_token,
  861. blob_uri,
  862. blob_sas,
  863. school_base,
  864. school_courses,
  865. school_classes,
  866. school_rooms,
  867. size,
  868. osblob_uri,
  869. osblob_sas,
  870. status = 200,
  871. areas,
  872. currArea,
  873. lessonLimit,
  874. teacher.lessonShow,
  875. defaultPeriodId,
  876. productSum = new
  877. {
  878. //serial = serials,
  879. service = services
  880. }
  881. ,
  882. privateSpace = new { size = 0, catalog = 0, teach = 0, surplus = 0, total = 0 } ,
  883. schoolSpace = new { size = space.usedSize, catalog = space.catalog, teach = space.teach, surplus = space.surplus, total = space.total }
  884. });
  885. }
  886. catch (CosmosException ex)
  887. {
  888. HttpContext.Request.Headers.TryGetValue("referer", out var referer);
  889. HttpContext.Request.Headers.TryGetValue("sec-ch-ua", out var chua);
  890. HttpContext.Request.Headers.TryGetValue("sec-ch-ua-platform", out var platform);
  891. HttpContext.Request.Headers.TryGetValue("user-agent", out var useragent);
  892. await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/init/get-school-info()\n{ex.Message}\n{ex.StackTrace}\n{request.ToJsonString()}\nreferer:{referer}\nsec-ch-ua:{chua}\nsec-ch-ua-platform:{platform}\nuser-agent:{useragent}", GroupNames.醍摩豆服務運維群組);
  893. return BadRequest(new { status = ex.Status });
  894. }
  895. catch (Exception ex)
  896. {
  897. HttpContext.Request.Headers.TryGetValue("referer", out var referer);
  898. HttpContext.Request.Headers.TryGetValue("sec-ch-ua", out var chua);
  899. HttpContext.Request.Headers.TryGetValue("sec-ch-ua-platform", out var platform);
  900. HttpContext.Request.Headers.TryGetValue("user-agent", out var useragent);
  901. await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/init/get-school-info()\n{ex.Message}\n{ex.StackTrace}\n{request.ToJsonString()}\nreferer:{referer}\nsec-ch-ua:{chua}\nsec-ch-ua-platform:{platform}\nuser-agent:{useragent}", GroupNames.醍摩豆服務運維群組);
  902. return BadRequest(new { status = 500 });
  903. }
  904. }
  905. /// <summary>
  906. /// 取得學校所有列表
  907. /// </summary>
  908. /// <param name="request"></param>
  909. /// <returns></returns>
  910. [ProducesDefaultResponseType]
  911. //[AuthToken(Roles = "teacher")]
  912. [HttpPost("get-school-list")]
  913. public async Task<IActionResult> GetSchoolList(JsonElement request)
  914. {
  915. try
  916. {
  917. //輸入值
  918. string sqlSchoolId = (request.TryGetProperty("schoolId", out JsonElement reqSchoolId)) ? reqSchoolId.GetString() : string.Empty;
  919. bool sqlHasManager = (request.TryGetProperty("manager", out JsonElement reqHasManager)) ? reqHasManager.GetBoolean() : false;
  920. bool sqlHasMBaseModule = (request.TryGetProperty("base", out JsonElement reqHasBaseModule)) ? reqHasBaseModule.GetBoolean() : false;
  921. var client = _azureCosmos.GetCosmosClient();
  922. //有管理者的學校
  923. Dictionary<string, List<Dictionary<string, string>>> managerSchDic = new Dictionary<string, List<Dictionary<string, string>>>();
  924. string managerWhereOption = (!string.IsNullOrWhiteSpace(sqlSchoolId)) ? $" AND c.code = 'Teacher-{sqlSchoolId}'" : string.Empty;
  925. string managerSql = $"SELECT DISTINCT REPLACE(c.code, 'Teacher-', '') AS schoolId, c.id, c.name FROM c WHERE ARRAY_CONTAINS(c.roles, 'admin', true) AND c.pk = 'Teacher' AND c.status = 'join'{managerWhereOption}";
  926. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: managerSql, requestOptions: new QueryRequestOptions() { }))
  927. {
  928. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  929. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  930. {
  931. string id = obj.GetProperty("id").GetString(); //管理者ID
  932. string name = obj.GetProperty("name").GetString(); //管理者姓名
  933. string schoolId = obj.GetProperty("schoolId").GetString(); //學校ID
  934. Dictionary<string, string> managerDic = new Dictionary<string, string>();
  935. managerDic.Add("id", id);
  936. managerDic.Add("name", name);
  937. if (managerSchDic.ContainsKey(schoolId))
  938. {
  939. managerSchDic[schoolId].Add(managerDic);
  940. }
  941. else
  942. {
  943. List<Dictionary<string, string>> managerList = new List<Dictionary<string, string>>();
  944. managerList.Add(managerDic);
  945. managerSchDic.Add(schoolId, managerList);
  946. }
  947. }
  948. }
  949. //有管理模組的學校
  950. List<string> baseModuleSchList = new List<string>();
  951. string baseModuleWhereOption = (!string.IsNullOrWhiteSpace(sqlSchoolId)) ? $" AND c.id = '{sqlSchoolId}'" : string.Empty;
  952. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: $"SELECT c.id FROM c JOIN serviceProduct IN c.service.product WHERE serviceProduct.prodCode = 'IPDYZYLC'{baseModuleWhereOption}", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Product") }))
  953. {
  954. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  955. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  956. {
  957. string schoolId = obj.GetProperty("id").GetString(); //學校ID
  958. baseModuleSchList.Add(schoolId);
  959. }
  960. }
  961. //學校資料
  962. List<object> schools = new List<object>();
  963. string schoolWhereOption = (!string.IsNullOrWhiteSpace(sqlSchoolId)) ? $" WHERE c.id = '{sqlSchoolId}'" : string.Empty;
  964. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: $"SELECT c.id, c.name, c.region, c.province, c.city, c.picture FROM c {schoolWhereOption}", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
  965. {
  966. var jsons = await JsonDocument.ParseAsync(item.ContentStream);
  967. if (jsons.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  968. {
  969. foreach (var obj in jsons.RootElement.GetProperty("Documents").EnumerateArray())
  970. {
  971. dynamic schoolExtobj = new ExpandoObject();
  972. schoolExtobj.id = obj.GetProperty("id").GetString(); //學校ID
  973. schoolExtobj.name = obj.GetProperty("name");
  974. schoolExtobj.region = obj.GetProperty("region");
  975. schoolExtobj.province = obj.GetProperty("province");
  976. schoolExtobj.city = obj.GetProperty("city");
  977. schoolExtobj.picture = obj.GetProperty("picture");
  978. if (managerSchDic.ContainsKey(schoolExtobj.id))
  979. {
  980. schoolExtobj.hasManager = true;
  981. schoolExtobj.managers = managerSchDic[schoolExtobj.id];
  982. }
  983. else
  984. {
  985. schoolExtobj.hasManager = false;
  986. schoolExtobj.managers = new List<object>();
  987. }
  988. schoolExtobj.hasBaseModule = (baseModuleSchList.Contains(schoolExtobj.id)) ? true : false;
  989. //學校輸出結果加入篩選
  990. if ((sqlHasManager && sqlHasMBaseModule) && (schoolExtobj.hasManager && schoolExtobj.hasBaseModule))
  991. {
  992. schools.Add(schoolExtobj);
  993. }
  994. else if (sqlHasManager && schoolExtobj.hasManager)
  995. {
  996. schools.Add(schoolExtobj);
  997. }
  998. else if (sqlHasMBaseModule && schoolExtobj.hasBaseModule)
  999. {
  1000. schools.Add(schoolExtobj);
  1001. }
  1002. else if (!sqlHasManager && !sqlHasMBaseModule)
  1003. {
  1004. schools.Add(schoolExtobj);
  1005. }
  1006. }
  1007. }
  1008. }
  1009. return Ok(new { schools });
  1010. }
  1011. catch (Exception ex)
  1012. {
  1013. await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/init/get-school-info()\n{ex.Message}\n{ex.StackTrace}{request.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
  1014. return BadRequest();
  1015. }
  1016. }
  1017. /// <summary>
  1018. /// 申請或同意邀請加入學校
  1019. /// </summary>
  1020. ///
  1021. /// <param name="request"></param>
  1022. /// <returns></returns>
  1023. [ProducesDefaultResponseType]
  1024. [AuthToken(Roles = "teacher")]
  1025. [HttpPost("join-school")]
  1026. [Authorize(Roles = "IES")]
  1027. public async Task<IActionResult> JoinSchool(JsonElement request)
  1028. {
  1029. try
  1030. {
  1031. if (!request.TryGetProperty("grant_type", out JsonElement grant_type)) return BadRequest(); //"invite":學校邀請 "request":老師申請 "join":"成為學校老師",leave 离开,cancel 取消。
  1032. if (!request.TryGetProperty("school_code", out JsonElement school_code)) return BadRequest();
  1033. if (!request.TryGetProperty("school_name", out JsonElement school_name)) return BadRequest();
  1034. ///当邀请某个老师加入学校则需要知道是谁邀请的
  1035. //if (!request.TryGetProperty("school_admin", out JsonElement school_admin)) return BadRequest();
  1036. string authtoken = HttpContext.GetXAuth("AuthToken");
  1037. if (string.IsNullOrEmpty(authtoken)) return BadRequest();
  1038. var jwt = new JwtSecurityToken(authtoken);
  1039. var id = jwt.Payload.Sub;
  1040. var schoolcode = jwt.Payload.Azp;
  1041. var Claims = jwt.Payload.Claims;
  1042. jwt.Payload.TryGetValue("name", out object name);
  1043. jwt.Payload.TryGetValue("picture", out object picture);
  1044. var client = _azureCosmos.GetCosmosClient();
  1045. //在老師表找出老師,處理該學校狀態 (老師基本資料應該要存在)
  1046. Teacher teacher = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Teacher>(id, new PartitionKey("Base"));
  1047. if (teacher.schools == null)
  1048. teacher.schools = new List<Teacher.TeacherSchool>();
  1049. var school = teacher.schools?.FirstOrDefault(x => x.schoolId.Equals(school_code.GetString(), StringComparison.OrdinalIgnoreCase));
  1050. School schoolBase = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{school_code}", new PartitionKey("Base"));
  1051. if (school != null)
  1052. school.status = grant_type.GetString();
  1053. else
  1054. {
  1055. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  1056. teacher.schools.Add(new Teacher.TeacherSchool() { areaId = schoolBase.areaId, picture = schoolBase.picture, schoolId = school_code.GetString(), name = school_name.GetString(), status = grant_type.GetString(), time = now });
  1057. }
  1058. if (grant_type.GetString().Equals("leave") || grant_type.GetString().Equals("cancel"))
  1059. {
  1060. if (teacher.schools.IsNotEmpty())
  1061. {
  1062. //获取之前已经加入的学校或者申请的学校
  1063. var inSchools = teacher.schools.Where(x => x.schoolId == school_code.GetString()).ToList();
  1064. if (inSchools.IsNotEmpty())
  1065. {
  1066. inSchools.ForEach(x => teacher.schools.Remove(x));
  1067. }
  1068. }
  1069. if (teacher.schools.Count > 0 && teacher.size <= 1)
  1070. {
  1071. teacher.size = 2;
  1072. }
  1073. if (!string.IsNullOrEmpty(teacher.defaultSchool) && teacher.defaultSchool.Equals($"{school_code}"))
  1074. {
  1075. if (teacher.schools.IsNotEmpty())
  1076. {
  1077. teacher.defaultSchool = teacher.schools[0].schoolId;
  1078. }
  1079. else
  1080. {
  1081. teacher.defaultSchool = null;
  1082. }
  1083. }
  1084. await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, id, new PartitionKey("Base"));
  1085. var sresponse = await client.GetContainer(Constant.TEAMModelOS, "School").DeleteItemStreamAsync(id, new PartitionKey($"Teacher-{school_code}"));
  1086. Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemStreamAsync($"{school_code}", new PartitionKey("TeacherImport"));
  1087. TeacherImport teacherImport = null;
  1088. if (response.Status == 200)
  1089. {
  1090. teacherImport = JsonDocument.Parse(response.Content).RootElement.Deserialize<TeacherImport>();
  1091. var tchs = teacherImport?.teachers?.RemoveAll(x => !string.IsNullOrWhiteSpace(x.id) && x.id.Equals(id));
  1092. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(teacherImport, $"{school_code}", new PartitionKey("TeacherImport"));
  1093. }
  1094. return Ok(new { stauts = 1 });
  1095. }
  1096. else
  1097. {
  1098. var dft = new List<string>() { "content-read", "exercise-read", "knowledge-read", "syllabus-read" };
  1099. if (teacher.schools.Count > 0 && teacher.size <= 1)
  1100. {
  1101. teacher.size = 2;
  1102. }
  1103. await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, id, new PartitionKey("Base"));
  1104. //在學校表處理該學校教師帳號的狀態
  1105. var sresponse = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(id, new PartitionKey($"Teacher-{school_code}"));
  1106. if (sresponse.Status == 200)
  1107. {
  1108. using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
  1109. SchoolTeacher steacher = json.ToObject<SchoolTeacher>();
  1110. steacher.status = grant_type.GetString();
  1111. if (grant_type.ToString().Equals("join"))
  1112. {
  1113. if (steacher.permissions.IsNotEmpty())
  1114. {
  1115. foreach (var d in dft)
  1116. {
  1117. if (!steacher.permissions.Contains(d))
  1118. {
  1119. steacher.permissions.Add(d);
  1120. }
  1121. }
  1122. }
  1123. else
  1124. {
  1125. steacher.permissions = dft;
  1126. }
  1127. }
  1128. var response = await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync(steacher, id, new PartitionKey($"Teacher-{school_code}"));
  1129. }
  1130. else
  1131. {
  1132. SchoolTeacher st = new SchoolTeacher()
  1133. {
  1134. pk = "Teacher",
  1135. code = $"Teacher-{school_code}",
  1136. createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
  1137. id = id,
  1138. name = name.ToString(),
  1139. picture = picture?.ToString(),
  1140. permissions = grant_type.ToString().Equals("join") ? dft : null,
  1141. roles = new List<string>() { "teacher" },
  1142. size = 0,
  1143. status = grant_type.GetString()
  1144. };
  1145. var response = await client.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync(st, new PartitionKey($"Teacher-{school_code}"));
  1146. }
  1147. Azure.Response responseImport = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemStreamAsync($"{school_code}", new PartitionKey("TeacherImport"));
  1148. TeacherImport teacherImport = null;
  1149. if ($"{grant_type}".Equals("request"))
  1150. {
  1151. if (responseImport.Status == 200)
  1152. {
  1153. teacherImport = JsonDocument.Parse(responseImport.Content).RootElement.Deserialize<TeacherImport>();
  1154. var tchs = teacherImport?.teachers?.FindAll(x => !string.IsNullOrWhiteSpace(x.iname) && x.iname.Equals($"{name}") && string.IsNullOrWhiteSpace(x.id));
  1155. if (tchs.IsNotEmpty())
  1156. {
  1157. var tch = tchs[0];
  1158. string ujson = null;
  1159. var content = new StringContent(new List<string> { $"{id}" }.ToJsonString(), Encoding.UTF8, "application/json");
  1160. ujson = await _coreAPIHttpService.GetUserInfos(content);
  1161. List<CoreUser> coreUsers = new List<CoreUser>();
  1162. if (!string.IsNullOrWhiteSpace(ujson))
  1163. {
  1164. coreUsers = ujson.ToObject<List<CoreUser>>();
  1165. }
  1166. if (coreUsers.IsNotEmpty())
  1167. {
  1168. tch.phone = coreUsers[0].mobile;
  1169. tch.email = coreUsers[0].mail;
  1170. }
  1171. tch.id = $"{id}";
  1172. tch.picture = $"{picture}";
  1173. tch.status = $"{grant_type}";
  1174. tch.time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  1175. tch.tmdid = id;
  1176. tch.name = $"{name }";
  1177. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(teacherImport, $"{school_code}", new PartitionKey("TeacherImport"));
  1178. }
  1179. }
  1180. }
  1181. if (grant_type.ToString().Equals("join"))
  1182. {
  1183. if (responseImport.Status == 200)
  1184. {
  1185. teacherImport = JsonDocument.Parse(responseImport.Content).RootElement.Deserialize<TeacherImport>();
  1186. teacherImport?.teachers.ForEach(x => {
  1187. if (!string.IsNullOrWhiteSpace(x.id) && !string.IsNullOrWhiteSpace(teacher.id) && x.id.Equals(teacher.id))
  1188. {
  1189. x.name = teacher.name;
  1190. x.status = "join";
  1191. x.time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  1192. x.picture = teacher.picture;
  1193. }
  1194. });
  1195. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(teacherImport, $"{school_code}", new PartitionKey("TeacherImport"));
  1196. await TmdUserService.JoinSchool(client, teacher.id, teacher.picture, teacher.name, school.schoolId, school.name);
  1197. }
  1198. }
  1199. List<SchoolTeacher> teachers = new List<SchoolTeacher>();
  1200. var queryslt = $"SELECT value(c) FROM c join A1 in c.roles where A1 in ('admin')";
  1201. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<SchoolTeacher>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Teacher-{school_code}") }))
  1202. {
  1203. teachers.Add(item);
  1204. }
  1205. string code = grant_type.GetString();
  1206. if (grant_type.GetString().Equals("join"))
  1207. {
  1208. code = "invite-join";
  1209. }
  1210. if (teachers.IsNotEmpty()) {
  1211. string sql = $"select c.id, c.name ,c.lang as code from c where c.id in ({string.Join(",", teachers.Select(x => $"'{x.id}'"))})";
  1212. List<IdNameCode> idNameCodes = new List<IdNameCode>();
  1213. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher)
  1214. .GetItemQueryIterator<IdNameCode>(queryText: sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base") }))
  1215. {
  1216. idNameCodes.Add(item);
  1217. }
  1218. _coreAPIHttpService.PushNotify(idNameCodes, $"{code}_school", Constant.NotifyType_IES5_Management,
  1219. new Dictionary<string, object> {{ "tmdname", name }, { "schoolName", schoolBase.name }, { "schoolId",$"{school_code}" },{ "tmdid",id} }, _option.Location,_configuration,_dingDing, _environment.ContentRootPath) ;
  1220. }
  1221. return Ok(new { stauts = 1 });
  1222. }
  1223. }
  1224. catch (Exception ex)
  1225. {
  1226. await _dingDing.SendBotMsg($"TEAMModel,{_option.Location},Init/JoinSchool()\n{ex.Message}\n{ex.StackTrace}\n{request.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
  1227. return BadRequest();
  1228. }
  1229. }
  1230. /// <summary>
  1231. /// 通过学段获取学校班级、教室信息; 教师id获取课程信息
  1232. /// </summary>
  1233. /// <param name="jsonElement"></param>
  1234. /// <returns></returns>
  1235. [ProducesDefaultResponseType]
  1236. [HttpPost("get-info-prdid")]
  1237. [Authorize(Roles="IES")]
  1238. public async Task<IActionResult> GetInfoByPeriodId(JsonElement jsonElement)
  1239. {
  1240. string OAuthShow_domain = HttpContext?.Request?.Host.Host;
  1241. if (OAuthShow_domain.Equals("teammodelos.chinacloudsites.cn"))
  1242. {
  1243. OAuthShow_domain = _option.HostName;
  1244. }
  1245. if (_option.Location.Equals("China"))
  1246. {
  1247. OAuthShow_domain = _option.HostName;
  1248. }
  1249. if (OAuthShow_domain.Equals("localhost"))
  1250. {
  1251. OAuthShow_domain = "test.teammodel.cn";
  1252. }
  1253. try
  1254. {
  1255. if (!jsonElement.TryGetProperty("id_token", out JsonElement id_token)) return BadRequest();
  1256. if (!jsonElement.TryGetProperty("school_code", out JsonElement school_code)) return BadRequest();
  1257. jsonElement.TryGetProperty("periodId", out JsonElement _periodId);
  1258. var jwt = new JwtSecurityToken(id_token.GetString());
  1259. var tchId = jwt.Payload.Sub;
  1260. var client = _azureCosmos.GetCosmosClient();
  1261. string periodId = null;
  1262. if (!string.IsNullOrEmpty($"{_periodId}"))
  1263. periodId = $"{_periodId}";
  1264. else
  1265. {
  1266. School school_base = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{school_code}", new PartitionKey("Base"));
  1267. periodId = school_base.period[0].id;
  1268. }
  1269. //获取班级信息
  1270. List<object> school_Classes = new();
  1271. string classesSql = $"SELECT c.id,c.x,c.y,c.name,c.year,c.teacher,c.periodId,c.gradeId,c.room,c.sn,c.no,c.style,c.status,c.openType,c.school, c.graduate, ARRAY_LENGTH(c.students) AS studCount FROM c where c.graduate = 0 or IS_DEFINED(c.graduate) = false and c.periodId='{periodId}'";
  1272. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: classesSql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Class-{school_code}") }))
  1273. {
  1274. var jsonc = await JsonDocument.ParseAsync(item.ContentStream);
  1275. foreach (var classeinfo in jsonc.RootElement.GetProperty("Documents").EnumerateArray())
  1276. {
  1277. school_Classes.Add(classeinfo.ToObject<object>());
  1278. }
  1279. }
  1280. //获取教师的课程
  1281. List<object> school_Courses = new();
  1282. var query = $"SELECT value(c) FROM c JOIN A1 IN c.schedule where A1.teacherId='{tchId}' and c.period.id='{periodId}'";
  1283. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Course-{school_code}") }))
  1284. {
  1285. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1286. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1287. {
  1288. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1289. {
  1290. school_Courses.Add(obj.ToObject<object>());
  1291. }
  1292. }
  1293. }
  1294. //获取教室
  1295. List<Room> school_Rooms = new();
  1296. //string roomSql = $"select value(c) from c where c.periodId = '{periodId}'"; //注释原因:教室暂时不绑定学段信息
  1297. string roomSql = $"select value(c) from c";
  1298. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<Room>(queryText: roomSql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Room-{school_code}") }))
  1299. {
  1300. school_Rooms.Add(item);
  1301. }
  1302. //获取学校行政班
  1303. List<GroupListDto> school_GroupList = new();
  1304. string glSql = $"select c.id,c.code,c.name,c.no,c.periodId,c.scope,c.school,c.creatorId,c.type,c.year,c.tcount,c.scount,c.leader ,c.froms ,c.joinLock from c";
  1305. string schoolglSql = $"{glSql} where c.periodId ='{periodId}'";
  1306. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<GroupListDto>(queryText: schoolglSql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"GroupList-{school_code}") }))
  1307. {
  1308. school_GroupList.Add(item);
  1309. }
  1310. //获取个人行政班
  1311. List<GroupListDto> personal_GroupList = new();
  1312. string pglSql = $"{glSql} where c.creatorId='{tchId}'";
  1313. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<GroupListDto>(queryText: pglSql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("GroupList") }))
  1314. {
  1315. personal_GroupList.Add(item);
  1316. }
  1317. return Ok(new { status = 200, school_Classes, school_Courses, school_Rooms, school_GroupList, personal_GroupList });
  1318. }
  1319. catch (Exception ex)
  1320. {
  1321. await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/init/get-info-prdid()\n{ex.Message}\n{ex.StackTrace}\n{jsonElement.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
  1322. return BadRequest(new { status = 500 });
  1323. }
  1324. }
  1325. //課綱的model先記在下面,待式樣確定後再轉換
  1326. private List<SyllabusNode> CreateSyllabusTree(List<Syllabus> syllabuses)
  1327. {
  1328. List<SyllabusNode> nodes = new List<SyllabusNode>();
  1329. foreach (var syllabus in syllabuses)
  1330. {
  1331. if (syllabus.pid.Equals(""))
  1332. nodes.Add(new SyllabusNode { id = syllabus.id, name = syllabus.name });
  1333. else
  1334. {
  1335. CreateNode(nodes, syllabus);
  1336. }
  1337. }
  1338. return nodes;
  1339. }
  1340. private void CreateNode(List<SyllabusNode> nodes, Syllabus parent)
  1341. {
  1342. foreach (var node in nodes)
  1343. {
  1344. if (node.id == parent.pid)
  1345. {
  1346. node.children.Add(new SyllabusNode { id = parent.id, name = parent.name });
  1347. }
  1348. else
  1349. {
  1350. CreateNode(node.children, parent);
  1351. }
  1352. }
  1353. }
  1354. public class SyllabusRole
  1355. {
  1356. public string id { get; set; }
  1357. public string name { get; set; }
  1358. public object period { get; set; }
  1359. public object semester { get; set; }
  1360. public object grade { get; set; }
  1361. public object subject { get; set; }
  1362. public int resourceCount { get; set; }
  1363. public int itemCount { get; set; }
  1364. public object structure { get; set; }
  1365. }
  1366. public class Syllabus
  1367. {
  1368. public string id { get; set; }
  1369. public string name { get; set; }
  1370. public string pid { get; set; }
  1371. public int order { get; set; }
  1372. }
  1373. public class SyllabusNode
  1374. {
  1375. public string id { get; set; }
  1376. public string name { get; set; }
  1377. public List<SyllabusNode> children { get; set; }
  1378. public SyllabusNode()
  1379. {
  1380. children = new List<SyllabusNode>();
  1381. }
  1382. }
  1383. }
  1384. }