AClassONEController.cs 74 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451
  1. using Microsoft.Azure.Cosmos;
  2. using Azure.Storage.Blobs.Models;
  3. using Azure.Storage.Sas;
  4. using Microsoft.AspNetCore.Authorization;
  5. using Microsoft.AspNetCore.Http;
  6. using Microsoft.AspNetCore.Mvc;
  7. using Microsoft.Extensions.Configuration;
  8. using Microsoft.Extensions.Options;
  9. using StackExchange.Redis;
  10. using System;
  11. using System.Collections.Generic;
  12. using System.ComponentModel.DataAnnotations;
  13. using System.Configuration;
  14. using System.Dynamic;
  15. using System.IdentityModel.Tokens.Jwt;
  16. using System.Linq;
  17. using System.Net;
  18. using System.Net.Http;
  19. using System.Reflection;
  20. using System.Security.Policy;
  21. using System.Text;
  22. using System.Text.Json;
  23. using System.Threading.Tasks;
  24. using TEAMModelOS.Controllers.Analysis;
  25. using TEAMModelOS.Controllers.Both;
  26. using TEAMModelOS.Filter;
  27. using TEAMModelOS.Models;
  28. using TEAMModelOS.SDK;
  29. using TEAMModelOS.SDK.DI;
  30. using TEAMModelOS.SDK.Extension;
  31. using TEAMModelOS.SDK.Models;
  32. using TEAMModelOS.SDK.Models.Cosmos;
  33. using TEAMModelOS.SDK.Models.Cosmos.Student;
  34. using TEAMModelOS.SDK.Models.Service;
  35. using TEAMModelOS.SDK.Services;
  36. using TEAMModelOS.Services;
  37. using static TEAMModelOS.SDK.Services.BlobService;
  38. using Period = TEAMModelOS.SDK.Models.Period;
  39. namespace TEAMModelOS.Controllers
  40. {
  41. /// <summary>
  42. ///
  43. ///
  44. /*
  45. AClassONE
  46. ee6a461a-3b40-4f70-8842-cf275d1e15ee
  47. px-njcS.jL1P7g0-kW:EAkO2Ve7[9k1x
  48. 8124850f-03d8-4949-9355-ed0d0709189e
  49. l2aR-bk2LfCGt7OjSwRi:qZqfXXhL4:=
  50. */
  51. /// </summary>
  52. [Route("aclassone")]
  53. [ApiController]
  54. public class AClassONEController : ControllerBase
  55. {
  56. private readonly IHttpClientFactory _httpClient;
  57. private readonly AzureStorageFactory _azureStorage;
  58. private readonly AzureRedisFactory _azureRedis;
  59. private readonly AzureCosmosFactory _azureCosmos;
  60. private readonly DingDing _dingDing;
  61. private readonly Option _option;
  62. private readonly SnowflakeId _snowflakeId;
  63. private readonly IConfiguration _configuration;
  64. private readonly CoreAPIHttpService _coreAPIHttpService;
  65. private readonly HttpTrigger _httpTrigger;
  66. private readonly IPSearcher _searcher;
  67. public AClassONEController(
  68. AzureStorageFactory azureStorage,
  69. AzureRedisFactory azureRedis,
  70. AzureCosmosFactory azureCosmos,
  71. DingDing dingDing,
  72. SnowflakeId snowflakeId,
  73. IOptionsSnapshot<Option> option, IHttpClientFactory httpClient, IConfiguration configuration, CoreAPIHttpService coreAPIHttpService, IPSearcher searcher, HttpTrigger httpTrigger)
  74. {
  75. _azureStorage = azureStorage;
  76. _azureRedis = azureRedis;
  77. _azureCosmos = azureCosmos;
  78. _dingDing = dingDing;
  79. _snowflakeId = snowflakeId;
  80. _option = option?.Value;
  81. _httpClient = httpClient;
  82. _configuration = configuration;
  83. _coreAPIHttpService=coreAPIHttpService;
  84. _searcher=searcher;
  85. _httpTrigger=httpTrigger;
  86. }
  87. /// <summary>
  88. /// js_code获取小程序用户信息
  89. /// </summary>
  90. /// <param name="json"></param>
  91. /// <returns></returns>
  92. [ProducesDefaultResponseType]
  93. [HttpPost("get-miniapp-userinfo")]
  94. //[Authorize(Roles = "AClassONE")]
  95. public async Task<IActionResult> GetMiniAPPOpenid(JsonElement json)
  96. {
  97. // string Content = await responseMessage.Content.ReadAsStringAsync();
  98. try {
  99. var location = _option.Location;
  100. var clientID = _configuration.GetValue<string>("HaBookAuth:AClassONE:clientID");
  101. var clientSecret = _configuration.GetValue<string>("HaBookAuth:AClassONE:clientSecret");
  102. var wxappid = _configuration.GetValue<string>("HaBookAuth:WXMiniAPP:appid");
  103. var wxsecret = _configuration.GetValue<string>("HaBookAuth:WXMiniAPP:secret");
  104. if (location.Contains("China"))
  105. {
  106. location = "China";
  107. }
  108. else if (location.Contains("Global"))
  109. {
  110. location = "Global";
  111. }
  112. var token = await CoreTokenExtensions.CreateAccessToken(clientID, clientSecret, location);
  113. //return Ok(new { token = new { token.TokenType,token.AccessToken } });
  114. if (!json.TryGetProperty("js_code", out JsonElement js_code)) return BadRequest("js_code is null");
  115. string url = $"https://api.weixin.qq.com/sns/jscode2session?appid={wxappid}&secret={wxsecret}&js_code={js_code}&grant_type=authorization_code";
  116. HttpResponseMessage responseMessage = await _httpClient.CreateClient().GetAsync(url);
  117. if (responseMessage.StatusCode == HttpStatusCode.OK)
  118. {
  119. JsonDocument document = JsonDocument.Parse(responseMessage.Content.ReadAsStream());
  120. return Ok(new { miniappData = document, token = new { token.TokenType, token.AccessToken } });
  121. }
  122. else
  123. {
  124. string Content = await responseMessage.Content?.ReadAsStringAsync();
  125. await _dingDing.SendBotMsg($"get-miniapp-userinfo:{Content}", GroupNames.成都开发測試群組);
  126. return BadRequest(Content);
  127. }
  128. }
  129. catch(Exception ex) {
  130. await _dingDing.SendBotMsg($"get-miniapp-userinfo:{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  131. return BadRequest();
  132. }
  133. }
  134. /// <summary>
  135. /// 获取教师信息
  136. /// </summary>
  137. /// <param name="json"></param>
  138. /// <returns></returns>
  139. [ProducesDefaultResponseType]
  140. [HttpPost("get-teacher-info")]
  141. #if !DEBUG
  142. [Authorize(Roles = "AClassONE")]
  143. #endif
  144. public async Task<IActionResult> GetTeacherInfo(JsonElement json)
  145. {
  146. try {
  147. string head_lang = "";
  148. if (HttpContext.Request.Headers.TryGetValue("lang", out var _lang))
  149. {
  150. head_lang = $"{_lang}";
  151. }
  152. int timezone = 8;
  153. if (HttpContext.Request.Headers.TryGetValue("Time-Zone", out var Time_Zone) && int.TryParse(Time_Zone,out int tz))
  154. {
  155. timezone=tz;
  156. }
  157. if (!json.TryGetProperty("code", out JsonElement _code)) return BadRequest("code is null");
  158. var phoneInfo = await GetWeChatPhoneNumber(_code.ToString());
  159. //phoneInfo.code=200;
  160. if (phoneInfo.code==200)
  161. {
  162. string _mobile = phoneInfo.phone.phoneNumber;
  163. //string _mobile = "18281911681";
  164. var coreUser = await _coreAPIHttpService.GetUserInfo(new Dictionary<string, string> { { "key", $"{_mobile}" } }, _option.Location, _configuration);
  165. if (coreUser != null && coreUser.id != null)
  166. {
  167. (string ip, string region) = await LoginService.LoginIp(HttpContext, _searcher);
  168. Teacher teacher = null;
  169. TeacherInfo teacherInfo = await TeacherService.TeacherInfo(_azureCosmos, teacher, $"{coreUser.name}", $"{coreUser.picture}", coreUser.id, _azureStorage, _option, _azureRedis, ip, _httpTrigger, $"{_lang}",timezone);
  170. return Ok(new
  171. {
  172. teacherInfo.auth_token,
  173. teacherInfo.blob_uri,
  174. teacherInfo.blob_sas,
  175. teacherInfo.schools,
  176. teacherInfo.defaultschool,
  177. });
  178. }
  179. else return Ok(new { state = 404, msg = "未找到关联账号" });
  180. }
  181. } catch (Exception ex) { }
  182. return Ok();
  183. }
  184. /// <summary>
  185. /// 获取学校信息
  186. /// </summary>
  187. /// <param name="json"></param>
  188. /// <returns></returns>
  189. [ProducesDefaultResponseType]
  190. [HttpPost("get-school-info")]
  191. #if !DEBUG
  192. [Authorize(Roles = "AClassONE,IES")]
  193. #endif
  194. [AuthToken(Roles = "teacher,admin")]
  195. public async Task<IActionResult> GetSchoolInfo(JsonElement json) {
  196. (string tmdid, _, _, string school) = HttpContext.GetAuthTokenInfo();
  197. if (!json.TryGetProperty("school_code", out JsonElement _school_code)) return BadRequest();
  198. string school_code = $"{_school_code}";
  199. List<string> roles = new List<string>();
  200. List<string> permissions = new List<string>();
  201. var client = _azureCosmos.GetCosmosClient();
  202. int size = 0;
  203. Teacher teacher = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Teacher>(tmdid, new PartitionKey("Base"));
  204. List<AreaDto> areas = new List<AreaDto>();
  205. HashSet<string> areaIds = new HashSet<string>();
  206. if (teacher.areas.IsNotEmpty())
  207. {
  208. teacher.areas.ForEach(x => {
  209. areaIds.Add(x.areaId);
  210. });
  211. }
  212. if (teacher.schools.IsNotEmpty())
  213. {
  214. teacher.schools.ForEach(x => {
  215. if (!string.IsNullOrEmpty(x.areaId))
  216. {
  217. areaIds.Add(x.areaId);
  218. }
  219. });
  220. }
  221. List<Area> areasDbs = new List<Area>();
  222. List<AreaSetting> areaSettings = new List<AreaSetting>();
  223. if (areaIds.Count > 0)
  224. {
  225. string queryText = $"select value(c) from c where c.id in ({string.Join(",", areaIds.Select(x => $"'{x}'"))})";
  226. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIteratorSql<Area>(queryText: queryText, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base-Area") }))
  227. {
  228. areasDbs.Add(item);
  229. }
  230. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIteratorSql<AreaSetting>(queryText: queryText, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("AreaSetting") }))
  231. {
  232. areaSettings.Add(item);
  233. }
  234. }
  235. if (teacher.areas.IsNotEmpty())
  236. {
  237. foreach (var areat in teacher.areas)
  238. {
  239. Area area = areasDbs.Find(x => x.id.Equals(areat.areaId));
  240. AreaSetting setting = null;
  241. if (area != null)
  242. {
  243. setting = areaSettings.Find(x => x.id.Equals(areat.areaId));
  244. }
  245. int access = 0;
  246. if (setting != null && !string.IsNullOrWhiteSpace(setting.accessConfig))
  247. {
  248. access = 1;
  249. }
  250. //if (setting != null)
  251. //{
  252. // setting.accessConfig = null;
  253. //}
  254. if (!string.IsNullOrWhiteSpace(area?.id)) {
  255. var containerArea = _azureStorage.GetBlobContainerClient(area?.id);
  256. await containerArea.CreateIfNotExistsAsync(PublicAccessType.None); //嘗試創建Teacher私有容器,如存在則不做任何事,保障容器一定存在
  257. var blobArea = _azureStorage.GetBlobContainerSAS(area?.id, blobContainerSasPermissions: BlobContainerSasPermissions.All);
  258. areas.Add(new AreaDto { sas= blobArea.sas, url= blobArea.uri, shortCode=area?.shortCode, areaId = area?.id, name = area?.name, standard = area?.standard, standardName = area?.standardName, setting = setting, access = access });
  259. }
  260. }
  261. }
  262. if (school_code.Equals(teacher.defaultSchool) && teacher.schools.IsNotEmpty() && !teacher.schools.Select(x => x.schoolId).Contains(school_code))
  263. {
  264. school_code = teacher.schools[0].schoolId;
  265. teacher.defaultSchool = school_code;
  266. teacher = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, tmdid, new PartitionKey("Base"));
  267. }
  268. var response = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(tmdid, new PartitionKey($"Teacher-{school_code}"));
  269. string defaultPeriodId = "";
  270. if (response.StatusCode==System.Net.HttpStatusCode.OK)
  271. {
  272. using var jsonData = await JsonDocument.ParseAsync(response.Content);
  273. if (jsonData.RootElement.TryGetProperty("size", out JsonElement _size) && _size.ValueKind == JsonValueKind.Number)
  274. {
  275. size = _size.GetInt32();
  276. }
  277. if (jsonData.RootElement.TryGetProperty("periodId", out JsonElement _periodId))
  278. {
  279. defaultPeriodId =$"{_periodId}";
  280. }
  281. if (jsonData.RootElement.TryGetProperty("roles", out JsonElement _roles) && _roles.ValueKind != JsonValueKind.Null)
  282. {
  283. foreach (var obj in _roles.EnumerateArray())
  284. {
  285. roles.Add(obj.GetString());
  286. }
  287. }
  288. if (jsonData.RootElement.TryGetProperty("permissions", out JsonElement _permissions) && _permissions.ValueKind != JsonValueKind.Null)
  289. {
  290. foreach (var obj in _permissions.EnumerateArray())
  291. {
  292. permissions.Add(obj.GetString());
  293. }
  294. }
  295. var scteacher = jsonData.RootElement.ToObject<SchoolTeacher>();
  296. if (!$"{teacher.name}".Equals($"{scteacher?.name}") || !$"{teacher.picture}".Equals($"{scteacher?.picture}"))
  297. {
  298. scteacher.name=teacher.name;
  299. scteacher.picture=teacher.picture;
  300. await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(scteacher, scteacher.id, new PartitionKey(scteacher.code));
  301. }
  302. }
  303. if (roles.Count == 0)
  304. {
  305. //助理,管家
  306. //roles.Add("assist");
  307. roles.Add("teacher");
  308. }
  309. School school_base = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{school_code}", new PartitionKey("Base"));
  310. string currAreaId = "";
  311. dynamic currArea = new ExpandoObject();
  312. if (!string.IsNullOrEmpty(school_base.areaId))
  313. {
  314. try
  315. {
  316. Area area = areasDbs.Find(x => x.id.Equals(school_base.areaId));
  317. AreaSetting setting = null;
  318. if (area != null)
  319. {
  320. //setting =await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<AreaSetting>(school_base.areaId, new PartitionKey("AreaSetting"));
  321. setting = areaSettings.Find(x => x.id.Equals(school_base.areaId));
  322. }
  323. int access = 0;
  324. AccessConfig accessConfig = null;
  325. if (setting != null && !string.IsNullOrWhiteSpace(setting.accessConfig))
  326. {
  327. access = 1;
  328. accessConfig = setting.accessConfig.ToObject<AccessConfig>();
  329. }
  330. //if (setting!=null&& !string.IsNullOrEmpty(setting.accessConfig)) {
  331. // setting.accessConfig = null;
  332. //}
  333. currArea = new
  334. {
  335. shortCode = area?.shortCode,
  336. areaId = area?.id,
  337. name = area?.name,
  338. standard = area?.standard,
  339. standardName = area?.standardName,
  340. setting = setting,
  341. access = access,
  342. //submitType=accessConfig?.submitType,
  343. homeworkType = accessConfig != null && accessConfig.homeworkType.IsNotEmpty() ? accessConfig.homeworkType : new List<string> { "pdf" },
  344. };
  345. currAreaId = area?.id;
  346. }
  347. catch (CosmosException)
  348. {
  349. //数据库捞不到数据
  350. }
  351. }
  352. if (areas.Count > 0)
  353. {
  354. roles.Add("area");
  355. }
  356. areas.ForEach(x => { { if (x.setting != null) { x.setting.accessConfig = x.setting.accessConfig; } } });
  357. int timezone = 8;
  358. if (HttpContext.Request.Headers.TryGetValue("Time-Zone", out var Time_Zone) && int.TryParse(Time_Zone, out int tz))
  359. {
  360. timezone=tz;
  361. }
  362. if (!string.IsNullOrWhiteSpace(school_base.timeZone?.value))
  363. {
  364. string timeZoneOffsetString = school_base.timeZone.value;
  365. bool plus = true;
  366. if (timeZoneOffsetString.Contains("-"))
  367. {
  368. plus=false;
  369. }
  370. // 去除时区偏移字符串中的正负号
  371. timeZoneOffsetString = timeZoneOffsetString.Replace("+", "").Replace("-", "");
  372. // 尝试解析格式化后的时区偏移字符串
  373. if (TimeSpan.TryParse(timeZoneOffsetString, out TimeSpan timeZoneOffset))
  374. {
  375. // 将时区偏移转换为小时数
  376. timezone = plus ? (int)timeZoneOffset.TotalHours : -(int)timeZoneOffset.TotalHours;
  377. }
  378. }
  379. var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName,teacher. id, teacher.name, teacher.picture, _option.JwtSecretKey, Website: "IES", timezone: timezone, scope: Constant.ScopeTeacher, schoolID: school_code.ToString(), areaId: currAreaId, standard: school_base.standard, roles: roles.ToArray(), permissions: permissions.ToArray(), expire: 1);
  380. string school_code_blob = school_code.ToLower();
  381. var container = _azureStorage.GetBlobContainerClient(school_code_blob);
  382. await container.CreateIfNotExistsAsync(PublicAccessType.None); //嘗試創建School容器,如存在則不做任何事,保障容器一定存在
  383. 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);
  384. return Ok(new {
  385. auth_token,
  386. blob_uri,
  387. blob_sas,
  388. school_base,
  389. areas,
  390. currArea,
  391. });
  392. }
  393. /// <summary>
  394. /// 获取教师的教学信息
  395. /// </summary>
  396. /// <param name="json"></param>
  397. /// <returns></returns>
  398. [ProducesDefaultResponseType]
  399. [HttpPost("get-teach-info")]
  400. #if !DEBUG
  401. [Authorize(Roles = "AClassONE,IES")]
  402. #endif
  403. [AuthToken(Roles = "teacher,admin")]
  404. public async Task<IActionResult> GetTeachInfo(JsonElement json) {
  405. (string tmdid, _, _, string school) = HttpContext.GetAuthTokenInfo();
  406. List<KeyValuePair<string, CourseTask>> schoolTeacherTask = new List<KeyValuePair<string, CourseTask>>();
  407. List<KeyValuePair<string, CourseTask>> schoolAssistantTask = new List<KeyValuePair<string, CourseTask>>();
  408. List<KeyValuePair<string, CourseTask>> privateTeacherTask = new List<KeyValuePair<string, CourseTask>>();
  409. List<KeyValuePair<string, CourseTask>> privateAssistantTask = new List<KeyValuePair<string, CourseTask>>();
  410. List<CourseDto> schoolCourses = new List<CourseDto>();
  411. List<CourseDto> teahcerCourses = new List<CourseDto>();
  412. List<string> groupIds = new List<string>();
  413. HashSet<string> hashGroupIds = new HashSet<string>();
  414. List<Class> classes = new List<Class>();
  415. Period periodSchool = null;
  416. //所有行政版
  417. List<GroupListDto> allClasses = new List<GroupListDto>();
  418. if (!string.IsNullOrWhiteSpace(school))
  419. {
  420. JsonElement year = default, semesterId = default, _periodId = default;
  421. School schoolBase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(school, new PartitionKey("Base"));
  422. if (!json.TryGetProperty("periodId", out _periodId)) return BadRequest();
  423. var period = schoolBase.period.Find(x => x.id.Equals($"{_periodId}"));
  424. allClasses= await GroupListService.GetGroupListByType(_azureCosmos.GetCosmosClient(), "class", schoolBase, period, 0);
  425. //班主任
  426. string sqlClassTeacher = $"select value c from c where c.teacher.id='{tmdid}' and c.periodId='{_periodId}'";
  427. var resultClass = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<Class>(sqlClassTeacher, $"Class-{school}");
  428. if (resultClass.list.IsNotEmpty())
  429. {
  430. classes.AddRange(resultClass.list);
  431. hashGroupIds = new HashSet<string>(resultClass.list.Select(z=>z.id));
  432. }
  433. //执教
  434. //协同
  435. //管理员
  436. string sql = $"SELECT distinct value c FROM c join b in c.schedules where c.pk='CourseTask' and (ARRAY_CONTAINS(b.assistants,'{tmdid}')or b.teacherId ='{tmdid}' )";
  437. int _year = -1;
  438. string _semesterId=string.Empty;
  439. if (json.TryGetProperty("year", out year))
  440. {
  441. _year= int.Parse($"{_year}");
  442. }
  443. if (json.TryGetProperty("semesterId", out semesterId))
  444. {
  445. _semesterId=$"{semesterId}";
  446. }
  447. periodSchool=period;
  448. if (_year==-1 || string.IsNullOrWhiteSpace(_semesterId))
  449. {
  450. var semesterInfo = SchoolService.GetSemester(period, DateTimeOffset.UtcNow.ToUnixTimeMilliseconds());
  451. if (_year==-1) {
  452. _year=semesterInfo.studyYear;
  453. }
  454. if (string.IsNullOrWhiteSpace(_semesterId)) {
  455. _semesterId=semesterInfo.currSemester.id;
  456. }
  457. }
  458. //string date = SchoolService.GetOpensByStudyYearAndSemester(period.semesters, int.Parse($"{_year}"), $"{_semesterId}");
  459. sql = $"{sql} and c.year={_year} and c.semesterId='{_semesterId}'";
  460. HashSet<string> courseIds = new HashSet<string>();
  461. var resultSchool = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<CourseTask>(sql, $"CourseTask-{school}");
  462. if (resultSchool.list.IsNotEmpty())
  463. {
  464. resultSchool.list.ForEach(x => {
  465. var schedulesTeacher = x.schedules.Where(z => !string.IsNullOrWhiteSpace(z.teacherId) && z.teacherId.Equals(tmdid));
  466. if (schedulesTeacher.Any())
  467. {
  468. courseIds.Add(x.courseId);
  469. CourseTask courseTask = x.ToJsonString().ToObject<CourseTask>();
  470. courseTask.schedules=schedulesTeacher.ToList();
  471. schoolTeacherTask.Add(new KeyValuePair<string, CourseTask>(x.courseId, courseTask));
  472. //groupIds.AddRange(schedulesTeacher.Where(z => !string.IsNullOrWhiteSpace(z.groupId)).Select(x => x.groupId));
  473. var gpids= schedulesTeacher.Where(z => !string.IsNullOrWhiteSpace(z.groupId)).Select(x => x.groupId);
  474. if (gpids!=null && gpids.Count()>0)
  475. {
  476. foreach (var gp in gpids) {
  477. hashGroupIds.Add(gp);
  478. }
  479. }
  480. }
  481. var schedulesAssistant = x.schedules.Where(z => z.assistants.Contains(tmdid));
  482. if (schedulesAssistant.Any())
  483. {
  484. courseIds.Add(x.courseId);
  485. CourseTask courseTask = x.ToJsonString().ToObject<CourseTask>();
  486. courseTask.schedules=schedulesAssistant.ToList();
  487. schoolAssistantTask.Add(new KeyValuePair<string, CourseTask>(x.courseId, courseTask));
  488. //groupIds.AddRange(schedulesAssistant.Where(z => !string.IsNullOrWhiteSpace(z.groupId)).Select(x => x.groupId));
  489. var gpids = schedulesAssistant.Where(z => !string.IsNullOrWhiteSpace(z.groupId)).Select(x => x.groupId);
  490. if (gpids!=null && gpids.Count()>0)
  491. {
  492. foreach (var gp in gpids)
  493. {
  494. hashGroupIds.Add(gp);
  495. }
  496. }
  497. }
  498. });
  499. }
  500. if (courseIds.Any())
  501. {
  502. string sqlCourse = $"select value c from c where c.id in ({string.Join(",", courseIds.Select(b => $"'{b}'"))})";
  503. var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<CourseBase>(sqlCourse, $"CourseBase-{school}");
  504. if (result.list.IsNotEmpty())
  505. {
  506. foreach (var item in result.list)
  507. {
  508. List<CourseTaskDto> courseTaskDtos = new List<CourseTaskDto>();
  509. var teacher = schoolTeacherTask.Where(x => x.Key.Equals(item.id)).Select(z => new CourseTaskDto { courseTask=z.Value, type="teacher" });
  510. if (teacher.Any())
  511. {
  512. courseTaskDtos.AddRange(teacher.ToList());
  513. }
  514. var assistant = schoolAssistantTask.Where(x => x.Key.Equals(item.id)).Select(z => new CourseTaskDto { courseTask=z.Value, type="assistant" });
  515. if (assistant.Any())
  516. {
  517. courseTaskDtos.AddRange(assistant.ToList());
  518. }
  519. schoolCourses.Add(new CourseDto { courseBase=item, courseTasks=courseTaskDtos });
  520. }
  521. }
  522. }
  523. }
  524. //个人
  525. {
  526. HashSet<string> courseIds = new HashSet<string>();
  527. string sqlCoursePrivate = $"select value c.id from c where c.creatorId='{tmdid}'";
  528. var resultCourseBasePrivate = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList<string>(sqlCoursePrivate, $"CourseBase");
  529. if (resultCourseBasePrivate.list.IsNotEmpty())
  530. {
  531. courseIds=new HashSet<string>(resultCourseBasePrivate.list);
  532. }
  533. string sqlprivate = $"SELECT distinct value c FROM c join b in c.schedules where c.pk='CourseTask' and (ARRAY_CONTAINS(b.assistants,'{tmdid}')or b.teacherId ='{tmdid}' )";
  534. var resultTeacher = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList<CourseTask>(sqlprivate, $"CourseTask");
  535. if (resultTeacher.list.IsNotEmpty())
  536. {
  537. resultTeacher.list.ForEach(x => {
  538. var schedulesTeacher = x.schedules.Where(z => !string.IsNullOrWhiteSpace(z.teacherId) && z.teacherId.Equals(tmdid));
  539. if (schedulesTeacher.Any())
  540. {
  541. courseIds.Add(x.courseId);
  542. CourseTask courseTask = x.ToJsonString().ToObject<CourseTask>();
  543. courseTask.schedules=schedulesTeacher.ToList();
  544. privateTeacherTask.Add(new KeyValuePair<string, CourseTask>(x.courseId, courseTask));
  545. groupIds.AddRange(schedulesTeacher.Where(z => !string.IsNullOrWhiteSpace(z.groupId)).Select(x => x.groupId));
  546. var gpids = schedulesTeacher.Where(z => !string.IsNullOrWhiteSpace(z.groupId));
  547. if (gpids!=null && gpids.Count()>0)
  548. {
  549. foreach (var gp in gpids)
  550. {
  551. if (!string.IsNullOrWhiteSpace(gp.school))
  552. {
  553. if (!string.IsNullOrWhiteSpace(school) && gp.school.Equals(school))
  554. {
  555. hashGroupIds.Add(gp.groupId);
  556. }
  557. }
  558. else {
  559. hashGroupIds.Add(gp.groupId);
  560. }
  561. }
  562. }
  563. }
  564. var schedulesAssistant = x.schedules.Where(z => z.assistants.Contains(tmdid));
  565. if (schedulesAssistant.Any())
  566. {
  567. courseIds.Add(x.courseId);
  568. CourseTask courseTask = x.ToJsonString().ToObject<CourseTask>();
  569. courseTask.schedules=schedulesAssistant.ToList();
  570. privateAssistantTask.Add(new KeyValuePair<string, CourseTask>(x.courseId, courseTask));
  571. groupIds.AddRange(schedulesAssistant.Where(z => !string.IsNullOrWhiteSpace(z.groupId)).Select(x => x.groupId));
  572. var gpids = schedulesAssistant.Where(z => !string.IsNullOrWhiteSpace(z.groupId));
  573. if (gpids!=null && gpids.Count()>0)
  574. {
  575. foreach (var gp in gpids)
  576. {
  577. if (!string.IsNullOrWhiteSpace(gp.school))
  578. {
  579. if (!string.IsNullOrWhiteSpace(school) && gp.school.Equals(school)) {
  580. hashGroupIds.Add(gp.groupId);
  581. }
  582. }
  583. else
  584. {
  585. hashGroupIds.Add(gp.groupId);
  586. }
  587. }
  588. }
  589. }
  590. });
  591. }
  592. if (courseIds.Any())
  593. {
  594. string sqlCourse = $"select distinct value c from c where c.code='CourseBase' and ( c.creatorId='{tmdid}' or c.id in ({string.Join(",", courseIds.Select(b => $"'{b}'"))}))";
  595. var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList<CourseBase>(sqlCourse, $"CourseBase");
  596. if (result.list.IsNotEmpty())
  597. {
  598. foreach (var item in result.list)
  599. {
  600. List<CourseTaskDto> courseTaskDtos = new List<CourseTaskDto>();
  601. var teacher = privateTeacherTask.Where(x => x.Key.Equals(item.id)).Select(z => new CourseTaskDto { courseTask=z.Value, type="teacher" });
  602. if (teacher.Any())
  603. {
  604. courseTaskDtos.AddRange(teacher.ToList());
  605. }
  606. var assistant = privateAssistantTask.Where(x => x.Key.Equals(item.id)).Select(z => new CourseTaskDto { courseTask=z.Value, type="assistant" });
  607. if (assistant.Any())
  608. {
  609. courseTaskDtos.AddRange(assistant.ToList());
  610. }
  611. teahcerCourses.Add(new CourseDto { courseBase=item, courseTasks=courseTaskDtos });
  612. }
  613. }
  614. }
  615. }
  616. var groupInfo = await GroupListService.GetMemberByListids(_coreAPIHttpService, _azureCosmos.GetCosmosClient(), _dingDing, hashGroupIds.ToList(), school);
  617. var groupIdsRel = groupIds.GroupBy(z => z).Select(z => new { groupId = z.Key, count = z.ToList().Count() });
  618. List<TeacherRoleGrouplist> groupLists= new List<TeacherRoleGrouplist>();
  619. foreach (var item in teahcerCourses)
  620. {
  621. foreach (var z in item.courseTasks) {
  622. var groups = z.courseTask.schedules.Select(z => z.groupId);
  623. if (groups!=null) {
  624. var groupList = groupInfo.groups.Where(z => groups.Contains(z.id));
  625. if (groupList!=null)
  626. {
  627. foreach (var gp in groupList) {
  628. string subjectId = null;
  629. string subjectName = null;
  630. string subjectBindId = null;
  631. TeacherRoleGrouplist roleGrouplist = groupLists.Find(f => f.scope.Equals("private") && f.groupList.id.Equals(gp.id));
  632. if (roleGrouplist!=null)
  633. {
  634. if (roleGrouplist.roles.Contains(z.type)) {
  635. roleGrouplist.roles.Add(z.type);
  636. }
  637. }
  638. else {
  639. groupLists.Add(new TeacherRoleGrouplist { roles = new HashSet<string>() { z.type }, scope= "private", groupList= gp, subjectId= subjectId, subjectName=subjectName, subjectBindId= subjectBindId });
  640. }
  641. }
  642. }
  643. }
  644. }
  645. }
  646. foreach (var item in schoolCourses)
  647. {
  648. string subjectBindId = null;
  649. if (!string.IsNullOrWhiteSpace(school) && periodSchool!=null && item.courseBase.scope.Equals("school") && !string.IsNullOrWhiteSpace(item.courseBase?.subject?.id))
  650. {
  651. subjectBindId=periodSchool.subjects.Find(z => z.id.Equals(item.courseBase.subject.id))?.bindId;
  652. }
  653. foreach (var z in item.courseTasks)
  654. {
  655. var groups = z.courseTask.schedules.Select(z => z.groupId);
  656. if (groups!=null)
  657. {
  658. var groupList = groupInfo.groups.Where(z => groups.Contains(z.id));
  659. if (groupList!=null)
  660. {
  661. foreach (var gp in groupList)
  662. {
  663. TeacherRoleGrouplist roleGrouplist = groupLists.Find(f => f.scope.Equals("school") && f.groupList.id.Equals(gp.id));
  664. if (roleGrouplist!=null)
  665. {
  666. if (roleGrouplist.roles.Contains(z.type))
  667. {
  668. roleGrouplist.roles.Add(z.type);
  669. }
  670. }
  671. else
  672. {
  673. groupLists.Add(new TeacherRoleGrouplist { roles = new HashSet<string>() { z.type }, scope = "school", groupList = gp, subjectId = item.courseBase?.subject?.id, subjectName = item.courseBase?.subject?.name, subjectBindId= subjectBindId });
  674. }
  675. }
  676. }
  677. }
  678. }
  679. }
  680. foreach (var item in classes) {
  681. var groupList = groupInfo.groups.Where(z => item.id.Equals(z.id));
  682. if (groupList!=null)
  683. {
  684. foreach (var gp in groupList)
  685. {
  686. TeacherRoleGrouplist roleGrouplist = groupLists.Find(f => f.scope.Equals("school") && f.groupList.id.Equals(gp.id));
  687. if (roleGrouplist!=null)
  688. {
  689. if (!roleGrouplist.roles.Contains("charge"))
  690. {
  691. roleGrouplist.roles.Add("charge");
  692. }
  693. }
  694. else
  695. {
  696. groupLists.Add(new TeacherRoleGrouplist { roles = new HashSet<string>() { "charge" }, scope = "school", groupList = gp, });
  697. }
  698. }
  699. }
  700. }
  701. //暂时先注释不需要的
  702. return Ok(new {/* teahcerCourses, schoolCourses, groupIdsRel, */groupLists, allClasses });
  703. }
  704. /// <summary>
  705. /// 根据家长手机号获取监护学生的信息
  706. /// </summary>
  707. /// <param name="json"></param>
  708. /// <returns></returns>
  709. [ProducesDefaultResponseType]
  710. [HttpPost("get-children-by-mobile")]
  711. #if !DEBUG
  712. [Authorize(Roles = "AClassONE")]
  713. #endif
  714. public async Task<IActionResult> GetChildrenByPhone(JsonElement json)
  715. {
  716. try
  717. {
  718. if (!json.TryGetProperty("code", out JsonElement _code)) return BadRequest("code is null");
  719. var phoneInfo= await GetWeChatPhoneNumber(_code.ToString());
  720. if (phoneInfo.code==200)
  721. {
  722. string _mobile = phoneInfo.phone.phoneNumber;
  723. string sql = $"select value c from c where c.mobile='{_mobile}'";
  724. List<Guardian> guardians = new List<Guardian>();
  725. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).
  726. GetItemQueryIteratorSql<Guardian>(queryText: sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base-Guardian") }))
  727. {
  728. guardians.Add(item);
  729. }
  730. //没有找到监护人信息时,尝试跨分区搜索,但是不建议。
  731. if (!guardians.IsNotEmpty())
  732. {
  733. List<Student> students = new List<Student>();
  734. string stuSql = $"select distinct value c from c join g in c.guardians where g.mobile='{_mobile}'";
  735. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).
  736. GetItemQueryIteratorSql<Student>(queryText: stuSql, requestOptions: new QueryRequestOptions { }))
  737. {
  738. students.Add(item);
  739. }
  740. if (students.Any())
  741. {
  742. string guardianName = "";
  743. string mobile = $"{_mobile}";
  744. List<GuardianStudent> guardianStudents = new List<GuardianStudent>();
  745. students.ForEach(x =>
  746. {
  747. var studentGuardian = x.guardians.Find(x => !string.IsNullOrWhiteSpace(x.mobile) && x.mobile.Equals(mobile));
  748. if (studentGuardian != null)
  749. {
  750. guardianName = studentGuardian.name;
  751. guardianStudents.Add(new GuardianStudent {relation=studentGuardian.relation, type = 2, id = x.id, code = x.schoolId, name = x.name, picture = x.picture });
  752. }
  753. });
  754. if (guardians.Any())
  755. {
  756. guardians.First().students.AddRange(guardianStudents);
  757. }
  758. else
  759. {
  760. Guardian guardian = new Guardian() { id = Guid.NewGuid().ToString(), name = guardianName, mobile = mobile, students = guardianStudents, code = "Base-Guardian", pk = "Guardian" };
  761. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).CreateItemAsync(guardian, new PartitionKey("Base-Guardian"));
  762. guardians.Add(guardian);
  763. }
  764. }
  765. }
  766. if (guardians.Any())
  767. {
  768. var students = guardians.SelectMany(x => x.students).DistinctBy(x => $"{x.type}-{x.id}{x.code}");
  769. var first = guardians.First();
  770. first.students = students.ToList();
  771. if (guardians.Count > 1)
  772. {
  773. //合并,并移除多余的绑定的手机号。
  774. guardians.Remove(first);
  775. if (guardians.Any() && !guardians.Select(x => x.id).Contains(first.id))
  776. {
  777. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).DeleteItemsStreamAsync(guardians.Select(x => x.id).ToList(), "Base-Guardian");
  778. }
  779. }
  780. first.nickname =first.name;
  781. first.picture = first.picture;
  782. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).ReplaceItemAsync(first, first.id, new PartitionKey(first.code));
  783. var schoolcodes = first.students.Where(s => !string.IsNullOrWhiteSpace(s.code)).Select(x => x.code);
  784. List<School> idSchools = new List<School>();
  785. if (schoolcodes.Any())
  786. {
  787. string sqlschool = $"select c.id,c.name,c.picture,c.period from c where c.id in ({string.Join(",", schoolcodes.Select(s => $"'{s}'"))})";
  788. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).
  789. GetItemQueryIteratorSql<School>(queryText: sqlschool, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base") }))
  790. {
  791. idSchools.Add(item);
  792. }
  793. }
  794. var stus = first.students.GroupBy(x => x.code).Select(x => new { x.Key, list = x.ToList() });
  795. List<Student> studentes = new List<Student>();
  796. List<Class> classes = new List<Class>();
  797. foreach (var stu in stus)
  798. {
  799. HashSet<string> classIds = new HashSet<string>();
  800. string sqlStudent = $"select c.name ,c.periodId ,c.id ,c.schoolId, c.picture, c.classId, c.gender, c.year,c.guardians from c where c.id in ({string.Join(",", stu.list.Select(s => $"'{s.id}'"))})";
  801. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).
  802. GetItemQueryIteratorSql<Student>(queryText: sqlStudent, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Base-{stu.Key}") }))
  803. {
  804. studentes.Add(item);
  805. classIds.Add(item.classId);
  806. }
  807. string sqlClassIds = $" select c.name ,c.periodId ,c.id ,c.school, c.teacher,c.year from c where c.id in ({string.Join(",", classIds.Select(s => $"'{s}'"))})";
  808. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).
  809. GetItemQueryIteratorSql<Class>(queryText: sqlClassIds, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Class-{stu.Key}") }))
  810. {
  811. classes.Add(item);
  812. }
  813. }
  814. List<dynamic> stuData = new List<dynamic>();
  815. List<GuardianStudent> guardianStudents= new List<GuardianStudent>();
  816. foreach (var x in first.students)
  817. {
  818. var stu = studentes.Find(s => s.id.Equals(x.id) && s.schoolId.Equals(x.code));
  819. if (stu== null) {
  820. guardianStudents.Add(x);
  821. continue;
  822. }
  823. var school = idSchools.Find(s => s.id.Equals(x.code));
  824. string periodName = "";
  825. if (school != null && stu != null && !string.IsNullOrWhiteSpace(stu.periodId))
  826. {
  827. var period = school.period.Find(p => p != null && p.id.Equals(stu.periodId));
  828. periodName = period?.name;
  829. }
  830. string className = "";
  831. string teacherTmdid = "";
  832. string teacherName = "";
  833. int? classYear = 0;
  834. if (stu != null && !string.IsNullOrWhiteSpace(stu.classId))
  835. {
  836. var clazz = classes.Find(p => p != null && p.id.Equals(stu.classId));
  837. className = clazz?.name;
  838. teacherTmdid = clazz?.teacher?.id;
  839. teacherName = clazz?.teacher?.name;
  840. classYear = clazz?.year;
  841. }
  842. if (string.IsNullOrWhiteSpace(x.relation)) {
  843. try {
  844. Student student = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).ReadItemAsync<Student>(x.id, new PartitionKey($"Base-{x.code}"));
  845. var guardian = student.guardians.FindAll(x => x.mobile.Equals(_mobile));
  846. if (guardian.IsNotEmpty()) {
  847. x.relation= guardian.First().relation;
  848. if (!string.IsNullOrWhiteSpace(x.relation)) {
  849. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).UpsertItemAsync<Guardian>(first, new PartitionKey(first.code));
  850. }
  851. }
  852. } catch { }
  853. }
  854. stuData.Add(new
  855. {
  856. x.id,
  857. schoolId = x.code,
  858. stu.name,
  859. stu.periodId,
  860. stu.picture,
  861. stu.classId,
  862. stu.gender,
  863. x.type,
  864. x.relation,
  865. stuYear = stu.year,
  866. schoolName = school.name,
  867. schoolPicture = school.picture,
  868. periodName,
  869. className,
  870. teacherTmdid,
  871. teacherName,
  872. classYear
  873. });
  874. }
  875. if (guardianStudents.IsNotEmpty()) {
  876. first.students.RemoveAll(z => guardianStudents.Contains(z));
  877. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).UpsertItemAsync<Guardian>(first, new PartitionKey(first.code));
  878. }
  879. return Ok(new { code =200,guardian = new { first.id, first.name, first.picture, first.nickname, first.mobile, students = stuData } });
  880. }
  881. else
  882. {
  883. return Ok(new { code = 1, msg = "暂未找到学生信息", mobile = _mobile });
  884. }
  885. }
  886. else
  887. {
  888. return BadRequest("手机授权码过期!");
  889. }
  890. }
  891. catch (Exception ex)
  892. {
  893. return BadRequest("500错误");
  894. }
  895. }
  896. /// <summary>
  897. /// 获取当前学生参与的活动列表
  898. /// </summary>
  899. /// <param name="json"></param>
  900. /// <returns></returns>
  901. [ProducesDefaultResponseType]
  902. [HttpPost("find-children-activity")]
  903. #if !DEBUG
  904. [Authorize(Roles = "AClassONE")]
  905. #endif
  906. public async Task<IActionResult> getActivity(JsonElement request) {
  907. try {
  908. if (!request.TryGetProperty("studentId", out JsonElement stuId)) return BadRequest();
  909. if (!request.TryGetProperty("classId", out JsonElement classId)) return BadRequest();
  910. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();//学校编码
  911. var client = _azureCosmos.GetCosmosClient();
  912. StringBuilder stringBuilder = new($"select value(c) from c where (c.status<>404 or IS_DEFINED(c.status) = false )");
  913. string continuationToken = string.Empty;
  914. string token = default;
  915. if (!string.IsNullOrWhiteSpace($"{classId}"))
  916. {
  917. stringBuilder.Append($" and array_contains(c.classes,'{classId}')");
  918. }
  919. stringBuilder.Append("order by c.createTime desc");
  920. //是否需要进行分页查询,默认不分页
  921. if (request.TryGetProperty("token", out JsonElement token_1))
  922. {
  923. token = token_1.GetString();
  924. };
  925. //默认不指定返回大小
  926. int? topcout = null;
  927. if (request.TryGetProperty("count", out JsonElement jcount))
  928. {
  929. if (!jcount.ValueKind.Equals(JsonValueKind.Undefined) && !jcount.ValueKind.Equals(JsonValueKind.Null) && jcount.TryGetInt32(out int data))
  930. {
  931. topcout = data;
  932. }
  933. }
  934. List<ArtEvaluation> arts = new();
  935. var result= await client.GetContainer(Constant.TEAMModelOS, Constant.Common).GetList<ArtEvaluation>(stringBuilder.ToString(), $"Art-{code}", token, 5);
  936. if (result.list.IsNotEmpty()) {
  937. arts = result.list;
  938. token = result.continuationToken;
  939. }
  940. List<string> artIds = new();
  941. artIds = arts.Select(c => c.id).ToList();
  942. List<ArtAttachment> artAttachments = new();
  943. List<StudentArtResult> studentArtResults = new();
  944. if (artIds.Count > 0) {
  945. string sqlTask = $"select value(c) from c where c.studentId = '{stuId}' and c.artId in ({string.Join(",", artIds.Select(s => $"'{s}'"))})";
  946. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).
  947. GetItemQueryIteratorSql<ArtAttachment>(queryText: sqlTask, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"ArtAttachment-{code}") }))
  948. {
  949. artAttachments.Add(item);
  950. }
  951. foreach (var art in arts)
  952. {
  953. StudentArtResult artResult = new();
  954. string stu = string.Format("{0}{1}{2}", code.GetString(), "-", stuId.GetString());
  955. var res = await client.GetContainer(Constant.TEAMModelOS, "Student").ReadItemStreamAsync(stu.ToString(), new PartitionKey($"ArtResult-{art.id}"));
  956. if (res.StatusCode==System.Net.HttpStatusCode.OK)
  957. {
  958. using var json = await JsonDocument.ParseAsync(res.Content);
  959. artResult = json.ToObject<StudentArtResult>();
  960. studentArtResults.Add(artResult);
  961. }
  962. }
  963. }
  964. var quotStus = studentArtResults.Select(c => new {
  965. c.artId,
  966. quotas = c.results.GroupBy(z => (z.quotaId, z.quotaName, z.subjectId)).Select(k => new {
  967. k.Key.quotaId,
  968. k.Key.quotaName,
  969. k.Key.subjectId,
  970. count = artAttachments.Where(p => p.studentId.Equals(stuId.GetString()) && p.artId.Equals(c.artId) && p.quotaId.Equals(k.Key.quotaId) && p.subjectId.Equals(k.Key.subjectId)).ToList().Count > 0 ?
  971. artAttachments.Where(p => p.studentId.Equals(stuId.GetString()) && p.artId.Equals(c.artId) && p.quotaId.Equals(k.Key.quotaId) && p.subjectId.Equals(k.Key.subjectId)).ToList().Count : 0
  972. })
  973. });
  974. var newArts = arts.Select(c => new {
  975. c.id,
  976. c.name,
  977. c.school,
  978. c.createTime,
  979. c.type,
  980. c.classes,
  981. c.progress,
  982. c.scope,
  983. c.areaId,
  984. c.pId,
  985. c.topic,
  986. c.startTime,
  987. c.endTime,
  988. c.uploadSTime,
  989. c.uploadETime,
  990. c.publish,c.subjects,
  991. c.period,
  992. c.periodType,
  993. c.zymusicstds,c.code,
  994. c.examDeadline,
  995. quotStus.Where(z => z.artId.Equals(c.id)).FirstOrDefault().quotas,
  996. count = artAttachments.Where(z => z.artId.Equals(c.id)).ToList().Count
  997. });
  998. return Ok(new { arts = newArts ,token});
  999. } catch (Exception e) {
  1000. await _dingDing.SendBotMsg($"OS,{_option.Location},art/find-children-activity()\n{e.Message}\n{e.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  1001. return BadRequest("500错误");
  1002. }
  1003. }
  1004. /// <summary>
  1005. /// 获取当前老师所在范围的活动列表
  1006. /// </summary>
  1007. /// <param name="json"></param>
  1008. /// <returns></returns>
  1009. [ProducesDefaultResponseType]
  1010. [HttpPost("find-teacher-activity")]
  1011. #if !DEBUG
  1012. [Authorize(Roles = "AClassONE")]
  1013. #endif
  1014. public async Task<IActionResult> getTeacherActivity(JsonElement request)
  1015. {
  1016. try
  1017. {
  1018. if (!request.TryGetProperty("studentId", out JsonElement teacId)) return BadRequest();
  1019. if (!request.TryGetProperty("classIds", out JsonElement classIds)) return BadRequest();
  1020. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();//学校编码
  1021. List<string> cIds = classIds.ToObject<List<string>>();
  1022. var client = _azureCosmos.GetCosmosClient();
  1023. StringBuilder stringBuilder = new($"select value(c) from c where (c.status<>404 or IS_DEFINED(c.status) = false )");
  1024. string continuationToken = string.Empty;
  1025. string token = default;
  1026. stringBuilder.Append("order by c.createTime desc");
  1027. //是否需要进行分页查询,默认不分页
  1028. if (request.TryGetProperty("token", out JsonElement token_1))
  1029. {
  1030. token = token_1.GetString();
  1031. };
  1032. //默认不指定返回大小
  1033. int? topcout = null;
  1034. if (request.TryGetProperty("count", out JsonElement jcount))
  1035. {
  1036. if (!jcount.ValueKind.Equals(JsonValueKind.Undefined) && !jcount.ValueKind.Equals(JsonValueKind.Null) && jcount.TryGetInt32(out int data))
  1037. {
  1038. topcout = data;
  1039. }
  1040. }
  1041. List<ArtEvaluation> arts = new();
  1042. var result = await client.GetContainer(Constant.TEAMModelOS, Constant.Common).GetList<ArtEvaluation>(stringBuilder.ToString(), $"Art-{code}", token, 5);
  1043. if (result.list.IsNotEmpty())
  1044. {
  1045. arts = result.list;
  1046. token = result.continuationToken;
  1047. }
  1048. arts = arts.Where(c => c.classes.Intersect(cIds).Any()).Where((x, i) => arts.FindIndex(z => z.id == x.id) == i).ToList();
  1049. List<string> artIds = new();
  1050. artIds = arts.Select(c => c.id).ToList();
  1051. List<ArtAttachment> artAttachments = new();
  1052. string sqlTask = $"select value(c) from c where c.studentId = '{teacId}' and c.artId in ({string.Join(",", artIds.Select(s => $"'{s}'"))})";
  1053. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).
  1054. GetItemQueryIteratorSql<ArtAttachment>(queryText: sqlTask, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"ArtAttachment-{code}") }))
  1055. {
  1056. artAttachments.Add(item);
  1057. }
  1058. var newArts = arts.Select(c => new {
  1059. c.id,
  1060. c.name,
  1061. c.school,
  1062. c.createTime,
  1063. c.type,
  1064. c.classes,
  1065. c.progress,
  1066. c.scope,
  1067. c.areaId,
  1068. c.pId,
  1069. c.topic,
  1070. c.startTime,
  1071. c.endTime,
  1072. c.uploadSTime,
  1073. c.uploadETime,
  1074. c.publish,
  1075. c.subjects,
  1076. c.period,
  1077. c.periodType,
  1078. c.zymusicstds,
  1079. c.code,
  1080. count = artAttachments.Where(z => z.artId.Equals(c.id)).ToList().Count
  1081. });
  1082. return Ok(new { arts = newArts, token });
  1083. }
  1084. catch (Exception e)
  1085. {
  1086. await _dingDing.SendBotMsg($"OS,{_option.Location},art/find-children-activity()\n{e.Message}\n{e.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  1087. return BadRequest("500错误");
  1088. }
  1089. }
  1090. [ProducesDefaultResponseType]
  1091. [HttpPost("find-summary-activity")]
  1092. #if !DEBUG
  1093. [Authorize(Roles = "AClassONE")]
  1094. #endif
  1095. public async Task<IActionResult> findSummaryActivity(JsonElement request)
  1096. {
  1097. try
  1098. {
  1099. if (!request.TryGetProperty("studentId", out JsonElement stuId)) return BadRequest();
  1100. if (!request.TryGetProperty("artId", out JsonElement artId)) return BadRequest();
  1101. //if (!request.TryGetProperty("acId", out JsonElement taskId)) return BadRequest();
  1102. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();//学校编码
  1103. var client = _azureCosmos.GetCosmosClient();
  1104. StudentArtResult result = new();
  1105. ArtEvaluation art = new();
  1106. string stu = string.Format("{0}{1}{2}", code.GetString(), "-", stuId.GetString());
  1107. var res = await client.GetContainer(Constant.TEAMModelOS, "Student").ReadItemStreamAsync(stu.ToString(), new PartitionKey($"ArtResult-{artId}"));
  1108. if (res.StatusCode==System.Net.HttpStatusCode.OK)
  1109. {
  1110. using var json = await JsonDocument.ParseAsync(res.Content);
  1111. result = json.ToObject<StudentArtResult>();
  1112. }
  1113. List<string> taskIds = new();
  1114. var qut = result.results.Where(c => c.quotaId.Equals("quota_22")).ToList();
  1115. foreach (var quota in qut) {
  1116. result.results.Remove(quota);
  1117. }
  1118. taskIds = result.results.Select(c => c.taskId).ToList();
  1119. List<ArtAttachment> artAttachments = new();
  1120. string sqlTask = $"select value(c) from c where c.studentId = '{stuId}' and c.taskId in ({string.Join(",", taskIds.Select(s => $"'{s}'"))})";
  1121. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).
  1122. GetItemQueryIteratorSql<ArtAttachment>(queryText: sqlTask, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"ArtAttachment-{code}") }))
  1123. {
  1124. artAttachments.Add(item);
  1125. }
  1126. var resArt = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync(artId.ToString(), new PartitionKey($"Art-{code}"));
  1127. if (resArt.StatusCode==System.Net.HttpStatusCode.OK)
  1128. {
  1129. using var json = await JsonDocument.ParseAsync(resArt.Content);
  1130. art = json.ToObject<ArtEvaluation>();
  1131. }
  1132. /* var setting = art.settings.Where(c => c.id.Equals("quota_22")).FirstOrDefault();
  1133. art.settings.Remove(setting);*/
  1134. return Ok(new { result,art, artAttachments });
  1135. }
  1136. catch (Exception e)
  1137. {
  1138. await _dingDing.SendBotMsg($"OS,{_option.Location},art/find-summary-activity()\n{e.Message}\n{e.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  1139. return BadRequest("500错误");
  1140. }
  1141. }
  1142. [ProducesDefaultResponseType]
  1143. [HttpPost("upload-all")]
  1144. #if !DEBUG
  1145. [Authorize(Roles = "AClassONE")]
  1146. #endif
  1147. public async Task<IActionResult> UploadAll(JsonElement element)
  1148. {
  1149. try
  1150. {
  1151. var client = _azureCosmos.GetCosmosClient();
  1152. //if (!element.TryGetProperty("code", out JsonElement school)) return BadRequest();
  1153. if (!element.TryGetProperty("attachments", out JsonElement stus)) return BadRequest();
  1154. stuFiles files = stus.ToObject<stuFiles>();
  1155. List<string> value = new List<string>();
  1156. await foreach (var s in stuTask(files, client))
  1157. {
  1158. if (s.code == 1)
  1159. {
  1160. value.Add(s.value);
  1161. }
  1162. }
  1163. if (value.Count > 0)
  1164. {
  1165. return Ok(new { code = 400, msg = "学生ID上传异常", value });
  1166. }
  1167. else
  1168. {
  1169. return Ok(files);
  1170. }
  1171. }
  1172. catch (Exception ex)
  1173. {
  1174. await _dingDing.SendBotMsg($"OS,{_option.Location},aclassone/uploadAll()\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  1175. return Ok(new { code = 500, msg = ex.Message });
  1176. }
  1177. }
  1178. [ProducesDefaultResponseType]
  1179. [HttpPost("delete")]
  1180. #if !DEBUG
  1181. [Authorize(Roles = "AClassONE")]
  1182. #endif
  1183. public async Task<IActionResult> deleteFiels(JsonElement element)
  1184. {
  1185. try
  1186. {
  1187. var client = _azureCosmos.GetCosmosClient();
  1188. if (!element.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1189. if (!element.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1190. ArtAttachment attachment = new();
  1191. var res = await client.GetContainer(Constant.TEAMModelOS, "Student").ReadItemStreamAsync(id.ToString(), new PartitionKey($"ArtAttachment-{code}"));
  1192. if (res.StatusCode==System.Net.HttpStatusCode.OK)
  1193. {
  1194. using var json = await JsonDocument.ParseAsync(res.Content);
  1195. attachment = json.ToObject<ArtAttachment>();
  1196. }
  1197. List<Attachment> atts = attachment.files;
  1198. foreach (Attachment att in atts) {
  1199. await _azureStorage.GetBlobServiceClient().DeleteBlobs(_dingDing, code.GetString(), new List<string> { $"{att.blob}" });
  1200. }
  1201. await client.GetContainer("TEAMModelOS", "Student").DeleteItemStreamAsync(id.GetString(), new PartitionKey($"ArtAttachment-{code}"));
  1202. return Ok();
  1203. }
  1204. catch (Exception ex)
  1205. {
  1206. await _dingDing.SendBotMsg($"OS,{_option.Location},aclassone/delete()\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  1207. return Ok(new { code = 500, msg = ex.Message });
  1208. }
  1209. }
  1210. private async IAsyncEnumerable<(int code, string value)> stuTask(stuFiles files, CosmosClient client)
  1211. {
  1212. string value = "";
  1213. int code = 0;
  1214. try {
  1215. if (string.IsNullOrEmpty(files.id))
  1216. {
  1217. ArtAttachment attachment = new()
  1218. {
  1219. id = Guid.NewGuid().ToString(),
  1220. artId = files.artId,
  1221. achievement = files.achievement,
  1222. address = files.address,
  1223. studentId = files.studentId,
  1224. taskId = files.taskId,
  1225. subjectId = files.subjectId,
  1226. quotaId = files.quotaId,
  1227. quotaName = files.quotaName,
  1228. uploadName = files.uploadName,
  1229. uploadTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
  1230. duration = files.duration,
  1231. name = files.name,
  1232. des = files.des,
  1233. artType = files.artType,
  1234. level = files.level,
  1235. files = files.files,
  1236. ttl = -1,
  1237. code = "ArtAttachment-" + files.school
  1238. };
  1239. await client.GetContainer("TEAMModelOS", "Student").CreateItemAsync(attachment, new PartitionKey($"{attachment.code}"));
  1240. }
  1241. else
  1242. {
  1243. ArtAttachment attachment = new()
  1244. {
  1245. artId = files.artId,
  1246. achievement = files.achievement,
  1247. address = files.address,
  1248. studentId = files.studentId,
  1249. taskId = files.taskId,
  1250. subjectId = files.subjectId,
  1251. quotaId = files.quotaId,
  1252. quotaName = files.quotaName,
  1253. updateTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
  1254. uploadName = files.uploadName,
  1255. duration = files.duration,
  1256. name = files.name,
  1257. des = files.des,
  1258. artType = files.artType,
  1259. level = files.level,
  1260. files = files.files,
  1261. ttl = -1,
  1262. code = "ArtAttachment-" + files.school
  1263. };
  1264. await client.GetContainer("TEAMModelOS", "Student").ReplaceItemAsync(attachment, attachment.id, new PartitionKey($"{attachment.code}"));
  1265. }
  1266. }
  1267. catch (Exception e) {
  1268. value = files.studentId;
  1269. code = 1;
  1270. }
  1271. yield return (code, value);
  1272. }
  1273. private async Task<(int code, WeChatPhone phone)> GetWeChatPhoneNumber(string phoneCode)
  1274. {
  1275. var wxappid = _configuration.GetValue<string>("HaBookAuth:WXMiniAPP:appid");
  1276. var wxsecret = _configuration.GetValue<string>("HaBookAuth:WXMiniAPP:secret");
  1277. string urlAccessToken = $"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={wxappid}&secret={wxsecret}";
  1278. HttpResponseMessage responseMessage = await _httpClient.CreateClient().GetAsync(urlAccessToken);
  1279. string contentToken = responseMessage.StatusCode == HttpStatusCode.OK ? await responseMessage.Content.ReadAsStringAsync() : "{}";
  1280. JsonElement WeChapToken = contentToken.ToObject<JsonElement>();
  1281. string WeChataccess_token = $"{WeChapToken.GetProperty("access_token")}";
  1282. Dictionary<string, object> dict = new() { { "code", phoneCode } };
  1283. string url = $"https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token={WeChataccess_token}";
  1284. // 将参数转化为HttpContent
  1285. HttpContent contentPhone = new StringContent(dict.ToJsonString(), Encoding.UTF8, "application/json");
  1286. var httpResponse = await _httpClient.CreateClient().PostAsync(url, contentPhone);
  1287. WeChatPhone phone = null;
  1288. int code = 200;
  1289. if (httpResponse.StatusCode == HttpStatusCode.OK)
  1290. {
  1291. string responseContent = await httpResponse.Content.ReadAsStringAsync();
  1292. WeChatPhoneStatus? t = responseContent.ToObject<WeChatPhoneStatus>();
  1293. phone = t.phone_info;
  1294. if (phone==null)
  1295. {
  1296. code = 404;
  1297. }
  1298. else { code = 200; }
  1299. }
  1300. else
  1301. {
  1302. //微信找到。
  1303. code = 404;
  1304. }
  1305. return (code, phone);
  1306. }
  1307. /// <summary>
  1308. /// 查询考试信息
  1309. /// </summary>
  1310. /// <param name="request"></param>
  1311. /// <returns></returns>
  1312. [ProducesDefaultResponseType]
  1313. [Authorize(Roles = "AClassONE")]
  1314. [HttpPost("find-activity")]
  1315. public async Task<IActionResult> FindExam(JsonElement request)
  1316. {
  1317. try
  1318. {
  1319. //var client = _azureCosmos.GetCosmosClient();
  1320. var (id, name, pic, school) = HttpContext.GetAuthTokenInfo();
  1321. (List<StuActivity> datas, string continuationToken) = await ActivityStudentService.FindActivity(request, id, school, _azureCosmos, _azureRedis);
  1322. return Ok(new { datas, continuationToken });
  1323. }
  1324. catch (Exception e)
  1325. {
  1326. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/find-activity()\n{e.Message}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
  1327. return BadRequest("500错误");
  1328. }
  1329. }
  1330. public class TeacherRoleGrouplist
  1331. {
  1332. public HashSet<string> roles { get; set; }
  1333. public string scope { get; set; }
  1334. public RGroupList groupList { get; set; }
  1335. public string subjectId { get; set; }
  1336. public string subjectName { get; set; }
  1337. public string subjectBindId { get; set; }
  1338. }
  1339. public class WeChatPhone
  1340. {
  1341. public string? phoneNumber { get; set; }
  1342. public string? purePhoneNumber { get; set; }
  1343. public string? countryCode { get; set; }
  1344. // public JsonElement watermark { get; set; }
  1345. }
  1346. public class WeChatPhoneStatus
  1347. {
  1348. public int? errcode { get; set; }
  1349. public string? errmsg { get; set; }
  1350. public WeChatPhone? phone_info { get; set; }
  1351. }
  1352. private class stuFiles
  1353. {
  1354. public string id { get; set; }
  1355. public string school { get; set; }
  1356. public string artId { get; set; }
  1357. public string taskId { get; set; }
  1358. public string studentId { get; set; }
  1359. public string quotaId { get; set; }
  1360. public string quotaName { get; set; }
  1361. public string subjectId { get; set; }
  1362. public string address { get; set; }
  1363. public string time { get; set; }
  1364. public string duration { get; set; }
  1365. public string achievement { get; set; }
  1366. public string name { get; set; }
  1367. public string des { get; set; }
  1368. //0 艺术特长 1 艺术体验
  1369. public int artType { get; set; } = -1;
  1370. // 0 校级 1 区级 2 市级 3 省级 4 国家级
  1371. public int level { get; set; } = -1;
  1372. public long uploadTime { get; set; }
  1373. public string uploadName { get; set; }
  1374. public List<Attachment> files { get; set; } = new List<Attachment>();
  1375. }
  1376. }
  1377. }