XW 3 år sedan
förälder
incheckning
b6f921325d
29 ändrade filer med 1143 tillägg och 1125 borttagningar
  1. 65 49
      TEAMModelAPI/Controllers/School/TeacherController.cs
  2. 3 3
      TEAMModelBI/Controllers/BISchool/SchoolController.cs
  3. 63 46
      TEAMModelOS.FunctionV4/ServiceBus/ActiveTaskTopic.cs
  4. 3 3
      TEAMModelOS.FunctionV4/TEAMModelOS.FunctionV4.csproj
  5. 6 5
      TEAMModelOS.SDK/Extension/HttpContextExtensions.cs
  6. 4 4
      TEAMModelOS.SDK/Extension/JwtAuthExtension.cs
  7. 5 5
      TEAMModelOS.SDK/Models/Cosmos/School/School.cs
  8. 5 3
      TEAMModelOS.SDK/Models/Cosmos/Student/Student.cs
  9. 6 5
      TEAMModelOS.SDK/Models/Cosmos/Teacher/Teacher.cs
  10. 17 256
      TEAMModelOS.SDK/Models/Service/Common/TeacherService.cs
  11. 39 8
      TEAMModelOS.SDK/Models/Service/LoginService.cs
  12. 15 15
      TEAMModelOS.SDK/Models/Service/StudentService.cs
  13. 6 4
      TEAMModelOS.SDK/Models/Service/Third/Xkw/XkwOAuthModel.cs
  14. 22 16
      TEAMModelOS.SDK/Models/Service/TmdUserService.cs
  15. 83 65
      TEAMModelOS/Controllers/Both/GroupListController.cs
  16. 36 29
      TEAMModelOS/Controllers/Client/HiTAControlller.cs
  17. 81 67
      TEAMModelOS/Controllers/Client/HiTeachController.cs
  18. 73 32
      TEAMModelOS/Controllers/Common/ExamController.cs
  19. 9 7
      TEAMModelOS/Controllers/Common/StudyController.cs
  20. 109 76
      TEAMModelOS/Controllers/School/SchoolController.cs
  21. 69 51
      TEAMModelOS/Controllers/School/SchoolTeacherController.cs
  22. 57 42
      TEAMModelOS/Controllers/Student/StudentController.cs
  23. 18 11
      TEAMModelOS/Controllers/Student/TmdUserController.cs
  24. 154 72
      TEAMModelOS/Controllers/Teacher/InitController.cs
  25. 35 32
      TEAMModelOS/Controllers/Third/OAuth2Controller.cs
  26. 7 5
      TEAMModelOS/Controllers/Third/Sc/ScController.cs
  27. 149 210
      TEAMModelOS/Controllers/XTest/TestController.cs
  28. 1 1
      TEAMModelOS/Filter/AuthTokenAttribute.cs
  29. 3 3
      TEAMModelOS/TEAMModelOS.csproj

+ 65 - 49
TEAMModelAPI/Controllers/School/TeacherController.cs

@@ -64,13 +64,13 @@ namespace TEAMModelAPI.Controllers
         [ApiToken(Auth = "1501", Name = "学校教师列表", RW = "R", Limit = false)]
         public async Task<IActionResult> GetTeacherList(JsonElement json)
         {
-            
+
             json.TryGetProperty("searchKey", out JsonElement _searchKey);
             List<CoreUser> coreUsers = new List<CoreUser>();
-            IEnumerable<string> unexist = null ;
+            IEnumerable<string> unexist = null;
             if (_searchKey.ValueKind.Equals(JsonValueKind.Array))
             {
-                List<string> searchKey= _searchKey.ToObject<List<string>>();
+                List<string> searchKey = _searchKey.ToObject<List<string>>();
                 var keys = searchKey.Where(x => !string.IsNullOrWhiteSpace(x));
                 var content = new StringContent(keys.ToJsonString(), Encoding.UTF8, "application/json");
                 string ujson = await _coreAPIHttpService.GetUserInfos(content);
@@ -82,17 +82,19 @@ namespace TEAMModelAPI.Controllers
                 {
                     unexist = searchKey.Except(coreUsers.Select(x => x.searchKey));
                 }
-                else {
+                else
+                {
                     return Ok(new { error = 1, msg = "没有找到对应的教师信息!" });
                 }
             }
-           
-         
+
+
             var (id, school) = HttpContext.GetApiTokenInfo();
             List<SchoolTeacher> teachers = new List<SchoolTeacher>();
             string insql = "";
-            if (coreUsers.Any()) {
-                 insql = $"   c.id in  ({string.Join(",", coreUsers.Select(x => $"'{ x.id}'"))}) ";
+            if (coreUsers.Any())
+            {
+                insql = $"   c.id in  ({string.Join(",", coreUsers.Select(x => $"'{ x.id}'"))}) ";
             }
             string sql = $"select c.id,c.name ,c.picture,c.job ,c.subjectIds,c.roles from c where   {insql}";
             await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<SchoolTeacher>
@@ -100,21 +102,22 @@ namespace TEAMModelAPI.Controllers
             {
                 teachers.Add(item);
             }
-            var teacherIds=   coreUsers.Select(x => x.id).Except(teachers.Select(x => x.id));
+            var teacherIds = coreUsers.Select(x => x.id).Except(teachers.Select(x => x.id));
             List<CoreUser> unjoined = coreUsers.FindAll(x => teacherIds.Contains(x.id));
-            List<dynamic> tchs= new List<dynamic>(); 
+            List<dynamic> tchs = new List<dynamic>();
             teachers.Select(x => new { x.id, x.name, x.picture, x.job, x.subjectIds, x.roles }).ToList().ForEach(x => {
-                var  coreUser= coreUsers.Find(c=>c.id.Equals(x.id));
-                if (coreUser != null) {
-                    tchs.Add(new {x.id,coreUser.name, coreUser.picture,x.job,x.subjectIds,x.roles,coreUser.searchKey,school });
+                var coreUser = coreUsers.Find(c => c.id.Equals(x.id));
+                if (coreUser != null)
+                {
+                    tchs.Add(new { x.id, coreUser.name, coreUser.picture, x.job, x.subjectIds, x.roles, coreUser.searchKey, school });
                 }
             });
             return Ok(new
             {
                 teachers = tchs,
-                unjoined= unjoined.Select(x => new {x.id,x.name,x.picture,x.searchKey}),
-                unexist= unexist
-            }); 
+                unjoined = unjoined.Select(x => new { x.id, x.name, x.picture, x.searchKey }),
+                unexist = unexist
+            });
         }
         /// <summary>
         /// 获取学校教师信息
@@ -135,7 +138,7 @@ namespace TEAMModelAPI.Controllers
             if (responseTch.Status == 200)
             {
                 teacher = JsonDocument.Parse(responseTch.Content).RootElement.Deserialize<Teacher>();
-                
+
             }
             else
             {
@@ -151,7 +154,7 @@ namespace TEAMModelAPI.Controllers
                 return Ok(new { error = 1, msg = "教师未就职该学校!" });
             }
         }
-        
+
 
 
 
@@ -162,17 +165,19 @@ namespace TEAMModelAPI.Controllers
         [ProducesDefaultResponseType]
         [HttpPost("import-school-teacher")]
         [ApiToken(Auth = "1503", Name = "学校教师信息", RW = "R", Limit = false)]
-        public async Task<IActionResult> ImportSchoolTeacher(ImportTechDto json) {
+        public async Task<IActionResult> ImportSchoolTeacher(ImportTechDto json)
+        {
             //如果需要同时导入学科,则需要填写学段
-           
+
             var (id, school) = HttpContext.GetApiTokenInfo();
             List<ImportTech> teachers = json.teachers;
-            List<string> searchKey = teachers.Select(x=>x.id).ToList();
+            List<string> searchKey = teachers.Select(x => x.id).ToList();
             string ujson = null;
             var keys = searchKey.Where(x => !string.IsNullOrWhiteSpace(x));
-            if (keys.Any()) {
+            if (keys.Any())
+            {
                 var content = new StringContent(keys.ToJsonString(), Encoding.UTF8, "application/json");
-             ujson = await _coreAPIHttpService.GetUserInfos(content);
+                ujson = await _coreAPIHttpService.GetUserInfos(content);
             }
             List<CoreUser> coreUsers = new List<CoreUser>();
             if (!string.IsNullOrWhiteSpace(ujson))
@@ -191,12 +196,13 @@ namespace TEAMModelAPI.Controllers
             var exist = coreUsers.Select(x => x.id);
             //注册了账号的教师
             teachers = teachers.Where(x => exist.Contains(x.id)).ToList();
-           
+
             List<Teacher> teachersList = new List<Teacher>();
-            List<SchoolTeacher>  schoolTeachers = new List<SchoolTeacher>();
-            string sql = $"select value(c) from c where c.id in ({string.Join(",",teachers.Select(x=>$"'{x.id}'"))})";
+            List<SchoolTeacher> schoolTeachers = new List<SchoolTeacher>();
+            string sql = $"select value(c) from c where c.id in ({string.Join(",", teachers.Select(x => $"'{x.id}'"))})";
             await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher)
-                .GetItemQueryIterator<Teacher>(queryText: sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base") })) {
+                .GetItemQueryIterator<Teacher>(queryText: sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base") }))
+            {
                 teachersList.Add(item);
             }
             await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
@@ -209,37 +215,41 @@ namespace TEAMModelAPI.Controllers
             //学校学科发生变化。
             List<SchoolTeacher> schoolTeachersAdd = new List<SchoolTeacher>();
             bool baseChange = false;
-            foreach (var item in teachers) {
+            foreach (var item in teachers)
+            {
                 var teacher = teachersList.Find(x => x.id.Equals(item.id));
                 var coreUser = coreUsers.Find(x => x.id.Equals(item.id));
                 if (teacher != null)
                 {
-                    var sch= teacher.schools?.Find(x => x.schoolId.Equals(school));
-                    if (sch == null) {
+                    var sch = teacher.schools?.Find(x => x.schoolId.Equals(school));
+                    if (sch == null)
+                    {
                         if (teacher.schools.IsNotEmpty())
                         {
-                            teacher.schools.Add(new Teacher.TeacherSchool {schoolId= school,name=data.name,status= "invite", time= now ,picture=data.picture,areaId=data.areaId});
+                            teacher.schools.Add(new Teacher.TeacherSchool { schoolId = school, name = data.name, status = "invite", time = now, picture = data.picture, areaId = data.areaId });
                         }
-                        else {
+                        else
+                        {
                             teacher.defaultSchool = school;
-                            teacher.size = teacher.size + 1 ;
+                            teacher.size = teacher.size + 1;
                             teacher.schools = new List<Teacher.TeacherSchool> { new Teacher.TeacherSchool { schoolId = school, name = data.name, status = "invite", time = now, picture = data.picture, areaId = data.areaId } };
                         }
                     }
-                    await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReplaceItemAsync<Teacher>(teacher,teacher.id, new PartitionKey("Base"));
+                    await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReplaceItemAsync<Teacher>(teacher, teacher.id, new PartitionKey("Base"));
                 }
-                else {
-                
+                else
+                {
+
                     teacher = new Teacher
                     {
-                        createTime= DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
+                        createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
                         id = coreUser.id,
                         name = coreUser.name,
                         picture = coreUser.picture,
-                        defaultSchool=school,
-                        size=2,
-                        code="Base",
-                        pk="Base",
+                        defaultSchool = school,
+                        size = 2,
+                        code = "Base",
+                        pk = "Base",
                         schools = new List<Teacher.TeacherSchool> { new Teacher.TeacherSchool { schoolId = school, name = data.name, status = "invite", time = now, picture = data.picture, areaId = data.areaId } }
                     };
                     await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).CreateItemAsync(teacher, new PartitionKey("Base"));
@@ -291,30 +301,36 @@ namespace TEAMModelAPI.Controllers
                     schoolTeachersAdd.Add(schoolTeacher);
                     await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).CreateItemAsync(schoolTeacher, new PartitionKey(schoolTeacher.code));
                 }
-                else {
-                    if (subjectIds.IsNotEmpty()) {
+                else
+                {
+                    if (subjectIds.IsNotEmpty())
+                    {
                         subjectIds.ForEach(x => {
-                            if (!schoolTeacher.subjectIds.Contains(x)) {
+                            if (!schoolTeacher.subjectIds.Contains(x))
+                            {
                                 schoolTeacher.subjectIds.Add(x);
                             }
                         });
                     }
                     schoolTeacher.job = string.IsNullOrWhiteSpace(item.job) ? schoolTeacher.job : item.job;
                     schoolTeachersAdd.Add(schoolTeacher);
-                    await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(schoolTeacher,schoolTeacher.id, new PartitionKey(schoolTeacher.code));
+                    await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(schoolTeacher, schoolTeacher.id, new PartitionKey(schoolTeacher.code));
                 }
             }
-            if (baseChange) {
+            if (baseChange)
+            {
                 await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(data, data.id, new PartitionKey("Base"));
             }
-            return Ok(new { teachers= schoolTeachersAdd.Select(x => new { x.id, x.name, x.picture, x.job, x.subjectIds, x.roles,school })});
+            return Ok(new { teachers = schoolTeachersAdd.Select(x => new { x.id, x.name, x.picture, x.job, x.subjectIds, x.roles, school }) });
         }
     }
 
-    public class ImportTechDto {
+    public class ImportTechDto
+    {
         public List<ImportTech> teachers { get; set; } = new List<ImportTech>();
     }
-    public class ImportTech {
+    public class ImportTech
+    {
         [Required(ErrorMessage = "教师id必须设置")]
         public string id { get; set; }
         public List<ImportTechSubject> subjects { get; set; }

+ 3 - 3
TEAMModelBI/Controllers/BISchool/SchoolController.cs

@@ -483,7 +483,7 @@ namespace TEAMModelBI.Controllers.BISchool
         [ProducesDefaultResponseType]
         [AuthToken(Roles = "admin")]
         [HttpPost("set-aistschool")]
-        public async Task<IActionResult> SetAssistSchool(JsonElement jsonElement) 
+        public async Task<IActionResult> SetAssistSchool(JsonElement jsonElement)
         {
             try
             {
@@ -503,7 +503,7 @@ namespace TEAMModelBI.Controllers.BISchool
                 {
                     dic.Add("userId", $"{userId}");
                 }
-                if (string.IsNullOrEmpty($"{userId}") && string.IsNullOrEmpty($"{tmdId}")) 
+                if (string.IsNullOrEmpty($"{userId}") && string.IsNullOrEmpty($"{tmdId}"))
                 {
                     return Ok(new { state = 400, msg = "钉钉账户或醍摩豆账户需要至少要传一个!" });
                 }
@@ -518,7 +518,7 @@ namespace TEAMModelBI.Controllers.BISchool
                     {
                         if (schoolIds.Count > 0)
                         {
-                            if (string.IsNullOrEmpty(ddInfo.tmdId)) 
+                            if (string.IsNullOrEmpty(ddInfo.tmdId))
                             {
                                 List<string> moblie = new() { $"{ddInfo.mobile}" };
 

+ 63 - 46
TEAMModelOS.FunctionV4/ServiceBus/ActiveTaskTopic.cs

@@ -39,7 +39,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
         private readonly NotificationService _notificationService;
         private readonly CoreAPIHttpService _coreAPIHttpService;
         private readonly IConfiguration _configuration;
-        public ActiveTaskTopic(CoreAPIHttpService  coreAPIHttpService,AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, AzureServiceBusFactory serviceBus, IOptionsSnapshot<Option> option, NotificationService notificationService, IConfiguration configuration)
+        public ActiveTaskTopic(CoreAPIHttpService coreAPIHttpService, AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, AzureServiceBusFactory serviceBus, IOptionsSnapshot<Option> option, NotificationService notificationService, IConfiguration configuration)
         {
             _azureCosmos = azureCosmos;
             _dingDing = dingDing;
@@ -337,7 +337,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
             await _azureRedis.GetRedisClient(8).HashSetAsync($"Blob:Record", new RedisValue(name), new RedisValue($"{blobsize}"));
             long end = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
             long dis = (end - statr) / 1000;
-            long timeout = 60*5;
+            long timeout = 60 * 5;
             if (dis > timeout)
             {
                 await _dingDing.SendBotMsg($"ServiceBus,RefreshBlob:空间计算已经超过{timeout}秒\n容器名:{name}\n文件夹:{u}\n计算时长:{dis}", GroupNames.醍摩豆服務運維群組);
@@ -347,10 +347,10 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
         /// <returns></returns>
         [Function("TeacherTrainChange")]
         public async Task TeacherTrainChangeFunc([ServiceBusTrigger("%Azure:ServiceBus:ActiveTask%", "teacher-train-change", Connection = "Azure:ServiceBus:ConnectionString")] string msg)
-        { 
-        
+        {
+
         }
-        
+
         /// <param name="msg"></param>
         /// <returns></returns>
         //[Function("TeacherTrainChange")]
@@ -700,7 +700,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                             }
                         }
                     }
-                    if(chgSchSizeCnt.Equals(0) && !school.size.Equals(schoolDefaultSize))
+                    if (chgSchSizeCnt.Equals(0) && !school.size.Equals(schoolDefaultSize))
                     {
                         school.size = schoolDefaultSize;
                         //updSchool = true; //關於學校空間初始式樣未定,目前暫定:若需要Reset空間,則先維持原空間數不更動
@@ -708,7 +708,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                     }
                 }
                 //變更學校基本資料
-                if(updSchool)
+                if (updSchool)
                 {
                     await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<School>(school, $"{schoolId}", new PartitionKey("Base"));
                 }
@@ -916,22 +916,26 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                 var duration = double.Parse($"{update.data}");
                                 lessonRecord.duration = duration;
                                 msgs.Add(update);
-                                try {
+                                try
+                                {
                                     BlobDownloadResult Recording = await _azureStorage.GetBlobContainerClient(blobname).GetBlobClient($"records/{_lessonId}/Record/.Recording.json").DownloadContentAsync();
                                     var RecordingJson = JsonDocument.Parse(new MemoryStream(Encoding.UTF8.GetBytes(Recording.Content.ToString()))).RootElement;
-                                    if (RecordingJson.TryGetProperty("duration",out JsonElement _duration) && _duration.ValueKind.Equals(JsonValueKind.Number)) {
+                                    if (RecordingJson.TryGetProperty("duration", out JsonElement _duration) && _duration.ValueKind.Equals(JsonValueKind.Number))
+                                    {
                                         var durationFile = double.Parse($"{_duration}");
-                                        if (duration < durationFile) {
+                                        if (duration < durationFile)
+                                        {
                                             lessonRecord.duration = durationFile;
                                         }
                                     }
-                                    if (RecordingJson.TryGetProperty("streamUrl", out JsonElement _streamUrl) &&!string.IsNullOrWhiteSpace($"{_streamUrl}"))
+                                    if (RecordingJson.TryGetProperty("streamUrl", out JsonElement _streamUrl) && !string.IsNullOrWhiteSpace($"{_streamUrl}"))
                                     {
                                         lessonRecord.hasVideo = 1;
                                     }
                                 }
-                                catch (Exception ex ) {
-                                  // await _dingDing.SendBotMsg($"{_option.Location}/LessonRecordEvent/课堂记录更新课堂时长出错records/{_lessonId}/Record/.Recording.json\n{ex.Message}{ex.StackTrace}{msg}", GroupNames.醍摩豆服務運維群組);
+                                catch (Exception ex)
+                                {
+                                    // await _dingDing.SendBotMsg($"{_option.Location}/LessonRecordEvent/课堂记录更新课堂时长出错records/{_lessonId}/Record/.Recording.json\n{ex.Message}{ex.StackTrace}{msg}", GroupNames.醍摩豆服務運維群組);
                                 }
                                 isReplace = true;
                                 break;
@@ -964,10 +968,10 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                 //如果有更新 则去读取/{_lessonId}/IES/base.json
                                 try
                                 {
-                                   // await _dingDing.SendBotMsg($"{_option.Location},课堂id:{_lessonId} 收到更新", GroupNames.醍摩豆服務運維群組);
+                                    // await _dingDing.SendBotMsg($"{_option.Location},课堂id:{_lessonId} 收到更新", GroupNames.醍摩豆服務運維群組);
                                     BlobDownloadResult baseblobDownload = await _azureStorage.GetBlobContainerClient(blobname).GetBlobClient($"/records/{_lessonId}/IES/base.json").DownloadContentAsync();
                                     LessonBase lessonBase = baseblobDownload.Content.ToObjectFromJson<LessonBase>();
-                                    if (lessonBase != null  && lessonBase.summary!=null)
+                                    if (lessonBase != null && lessonBase.summary != null)
                                     {
                                         //lessonRecord.name = lessonBase.summary.activityName;
                                         lessonRecord.attendCount = lessonBase.summary.attendCount;
@@ -986,8 +990,8 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                         lessonRecord.examCount = lessonBase.summary.examCount;
                                         lessonRecord.totalInteractPoint = lessonBase.summary.totalInteractPoint;
                                     }
-                                   // await _dingDing.SendBotMsg($"{_option.Location},课堂id:{_lessonId} 更新完成", GroupNames.醍摩豆服務運維群組);
-                                    long? size = await  _azureStorage.GetBlobContainerClient(blobname).GetBlobsSize($"records/{_lessonId}");
+                                    // await _dingDing.SendBotMsg($"{_option.Location},课堂id:{_lessonId} 更新完成", GroupNames.醍摩豆服務運維群組);
+                                    long? size = await _azureStorage.GetBlobContainerClient(blobname).GetBlobsSize($"records/{_lessonId}");
                                     Bloblog bloblog = new Bloblog
                                     {
                                         id = lessonRecord.id,
@@ -997,11 +1001,11 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                         time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
                                         type = "records",
                                         url = $"records/{_lessonId}",
-                                        subjectId =string.IsNullOrWhiteSpace(lessonRecord.subjectId)?new List<string>(): new List<string> { lessonRecord.subjectId },
+                                        subjectId = string.IsNullOrWhiteSpace(lessonRecord.subjectId) ? new List<string>() : new List<string> { lessonRecord.subjectId },
                                         periodId = string.IsNullOrWhiteSpace(lessonRecord.periodId) ? new List<string>() : new List<string> { lessonRecord.periodId },
                                         size = size.HasValue ? size.Value : 0,
                                     };
-                                    await client.GetContainer(Constant.TEAMModelOS,tbname).UpsertItemAsync(bloblog);
+                                    await client.GetContainer(Constant.TEAMModelOS, tbname).UpsertItemAsync(bloblog);
                                     var messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "update", root = "records", name = $"{blobname}" }.ToJsonString()); ;
                                     messageBlob.ApplicationProperties.Add("name", "BlobRoot");
                                     var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
@@ -1011,7 +1015,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                 }
                                 catch (Exception ex)
                                 {
-                                   // await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}课程读取base.json,{_lessonId}\n{ex.Message}\n{ex.StackTrace}\n{lessonRecord.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
+                                    // await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}课程读取base.json,{_lessonId}\n{ex.Message}\n{ex.StackTrace}\n{lessonRecord.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
                                 }
                                 break;
                             //更新 时间线
@@ -1031,7 +1035,8 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                 msgs.Add(update);
                                 break;
                             case "up-expire"://消除过期时间,消除后需要取消已经排程的通知订阅
-                                try {
+                                try
+                                {
                                     var table = _azureStorage.GetCloudTableClient().GetTableReference("ChangeRecord");
                                     List<ChangeRecord> records = await table.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", lessonRecord.id } });
                                     foreach (var record in records)
@@ -1046,7 +1051,9 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                             continue;
                                         }
                                     }
-                                } catch (Exception) {
+                                }
+                                catch (Exception)
+                                {
                                     break;
                                 }
                                 isReplace = true;
@@ -1055,7 +1062,8 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                             case "delete":
                                 try
                                 {
-                                    if (lessonRecord.expire > 0) {
+                                    if (lessonRecord.expire > 0)
+                                    {
                                         var table = _azureStorage.GetCloudTableClient().GetTableReference("ChangeRecord");
                                         List<ChangeRecord> records = await table.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", lessonRecord.id } });
                                         foreach (var record in records)
@@ -1072,7 +1080,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                         }
                                     }
                                     await _azureStorage.GetBlobServiceClient().DeleteBlobs(_dingDing, blobname, new List<string> { $"records/{_lessonId}" });
-                                    await client.GetContainer(Constant.TEAMModelOS, tbname).DeleteItemStreamAsync(lessonRecord.id,new PartitionKey ($"Bloblog-{blobname}"));
+                                    await client.GetContainer(Constant.TEAMModelOS, tbname).DeleteItemStreamAsync(lessonRecord.id, new PartitionKey($"Bloblog-{blobname}"));
                                     var messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "update", root = "records", name = $"{blobname}" }.ToJsonString()); ;
                                     messageBlob.ApplicationProperties.Add("name", "BlobRoot");
                                     var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
@@ -1116,7 +1124,8 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                             }
                                         }
                                     }
-                                    catch (Exception ex) {
+                                    catch (Exception ex)
+                                    {
                                         await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-查询课程-CosmosDB异常{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
                                     }
                                     /*catch (CosmosException ex) when (ex.Status != 404)
@@ -1141,7 +1150,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                 {
                                     HashSet<string> grades = new HashSet<string>();
                                     List<GroupListDto> groups = await GroupListService.GetGroupListListids(client, _dingDing, lessonRecord.groupIds, lessonRecord.school);
-                                     
+
                                     List<GroupListDto> groupLists = groups?.FindAll(x => !string.IsNullOrEmpty(x.periodId) && x.year > 0 && !string.IsNullOrEmpty(x.school));
                                     if (groupLists.IsNotEmpty() && !string.IsNullOrWhiteSpace(lessonRecord.periodId))
                                     {
@@ -1193,23 +1202,25 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                         {
 
                                         }
-                                        catch (Exception ex) {
+                                        catch (Exception ex)
+                                        {
                                             await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-处理课堂记录的-年级处理异常{ex.Message}\n{ex.StackTrace}\n{lessonRecord.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
                                         }
                                     }
-                                    lessonRecord.grade= grades.ToList();
+                                    lessonRecord.grade = grades.ToList();
                                 }
                                 //个人课例保存规则
-                                try {
+                                try
+                                {
                                     if (scope.Equals("private"))
                                     {
-                                       
+
                                         if (teacher.lessonLimit != -1)
                                         {
 
                                             HashSet<string> ids = new HashSet<string>();
                                             //未定义的 以及过期时间小于等于0 的 课例
-                                            string private_count_sql = "select value(c.id) from  c where ( c.expire<=0 or IS_DEFINED(c.expire) = false  )  ";
+                                            string private_count_sql = $"select value(c.id) from  c where  ( c.expire<=0 or IS_DEFINED(c.expire) = false  ) and c.tmdid='{tmdid}'  ";
                                             await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetItemQueryIterator<string>(
                                                 queryText: private_count_sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey(code) }))
                                             {
@@ -1217,7 +1228,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                                 ids.Add(item);
                                             }
                                             //包含收藏的本人的个人课例
-                                            string favorite_count_sql = $"select value(c.id) from  c where c.type='LessonRecord'    and c.scope='private' ";
+                                            string favorite_count_sql = $"select value(c.id) from  c where c.type='LessonRecord' and c.owner='{tmdid}'   and c.scope='private' ";
                                             await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetItemQueryIterator<string>(
                                                 queryText: favorite_count_sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Favorite-{tmdid}") }))
                                             {
@@ -1240,7 +1251,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                                 //var day3= now.AddDays(Constant.private_lesson_expire - 3).ToUnixTimeMilliseconds();
                                                 //result.Add(3, day3);
                                                 //剩余1天的通知
-                                                var day1 = now.AddDays(Constant.private_lesson_expire -6).ToUnixTimeMilliseconds();
+                                                var day1 = now.AddDays(Constant.private_lesson_expire - 6).ToUnixTimeMilliseconds();
                                                 result.Add(1, day1);
                                                 //到期通知
                                                 lessonRecord.expire = now.AddDays(Constant.private_lesson_expire).ToUnixTimeMilliseconds();
@@ -1253,7 +1264,8 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                                     from = $"ies5:{ Environment.GetEnvironmentVariable("Option:Location")}:private",
                                                     to = new List<string> { tmdid },
                                                     label = $"{biz}_lessonRecord",
-                                                    body = new {
+                                                    body = new
+                                                    {
                                                         location = $"{Environment.GetEnvironmentVariable("Option:Location")}",
                                                         biz = biz,
                                                         tmdid = teacher.id,
@@ -1273,7 +1285,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                                 var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
                                                 var location = $"{Environment.GetEnvironmentVariable("Option:Location")}";
                                                 await _notificationService.SendNotification(clientID, clientSecret, location, url, notification); //站内发送消息
-                                               
+
                                                 var table = _azureStorage.GetCloudTableClient().GetTableReference("ChangeRecord");
                                                 List<ChangeRecord> records = await table.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", lessonRecord.id } });
                                                 if (records.Count <= 0)
@@ -1316,10 +1328,12 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                             //=-1 则表示不限制上传数量
                                         }
                                     }
-                                } catch (Exception e) {
+                                }
+                                catch (Exception e)
+                                {
                                     await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-处理课堂记录的-CosmosDB异常{e.Message}\n{e.StackTrace}\n{lessonRecord.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
                                 }
-                                
+
                                 msgs.Add(update);
                                 break;
                             default:
@@ -1327,7 +1341,8 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                         }
                     }
                     //如果被删除则不能再被更新
-                    if (isReplace) {
+                    if (isReplace)
+                    {
                         await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname).ReplaceItemAsync<LessonRecord>(lessonRecord, lessonId, new PartitionKey(code));
                     }
                     //计算课堂更新前后的差值
@@ -1347,7 +1362,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
         [Function("LessonRecordExpire")]
         public async Task LessonRecordExpireFunc([ServiceBusTrigger("%Azure:ServiceBus:ActiveTask%", "lesson-record-expire", Connection = "Azure:ServiceBus:ConnectionString")] string msg)
         {
-            
+
             try
             {
                 var jsonMsg = JsonDocument.Parse(msg).RootElement;
@@ -1363,10 +1378,11 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                 jsonMsg.TryGetProperty("school", out JsonElement _school);
                 var client = _azureCosmos.GetCosmosClient();
                 //处理到期删除
-                if ($"{progress}".Equals($"{Constant.private_lesson_expire}")) {
+                if ($"{progress}".Equals($"{Constant.private_lesson_expire}"))
+                {
                     string lessonId = $"{id}";
                     string tbname;
-                    string school=$"{_school}";
+                    string school = $"{_school}";
                     string code = "";
                     if ($"{scope}".Equals("school") && !string.IsNullOrEmpty($"{school}"))
                     {
@@ -1391,7 +1407,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                         lessonRecord.status = 404;
                         await client.GetContainer(Constant.TEAMModelOS, tbname).ReplaceItemAsync(lessonRecord, lessonRecord.id, new PartitionKey(lessonRecord.code));
                         var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
-                        var messageChange = new ServiceBusMessage(new   { delete_id =lessonId, tmdid =tmdid,scope=scope,opt="delete",school=school}.ToJsonString());
+                        var messageChange = new ServiceBusMessage(new { delete_id = lessonId, tmdid = tmdid, scope = scope, opt = "delete", school = school }.ToJsonString());
                         messageChange.ApplicationProperties.Add("name", "LessonRecordEvent");
                         await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageChange);
                         await _dingDing.SendBotMsg($"课例:【{lessonRecord.name}】\n课例ID:【{lessonRecord.id}】\n因时间到期,即将被自动删除,到期时间:" +
@@ -1406,12 +1422,13 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                     from = $"ies5:{_option.Location}:private",
                     to = new List<string> { $"{tmdid}" },
                     label = $"{biz}_lessonRecord",
-                    body = new {
+                    body = new
+                    {
                         location = $"{Environment.GetEnvironmentVariable("Option:Location")}",
                         biz = biz,
                         tmdid = $"{tmdid}",
                         tmdname = tmdname,
-                        sid =$"{id}",
+                        sid = $"{id}",
                         sname = $"{name}",
                         stime = long.Parse($"{startTime}"),
                         expire = long.Parse($"{expire}"),
@@ -1424,7 +1441,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                 var url = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
                 var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
                 var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
-                var location =$"{Environment.GetEnvironmentVariable("Option:Location")}";
+                var location = $"{Environment.GetEnvironmentVariable("Option:Location")}";
                 await _notificationService.SendNotification(clientID, clientSecret, location, url, notification); //站内发送消息
             }
             catch (Exception ex)
@@ -1708,7 +1725,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                         catch (CosmosException ex)
                         {
                             continue;
-                           // await _dingDing.SendBotMsg($"OS,{ Environment.GetEnvironmentVariable("Option:Location")},CourseServiceBus -CosmosDB异常\n{ex.Message}{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
+                            // await _dingDing.SendBotMsg($"OS,{ Environment.GetEnvironmentVariable("Option:Location")},CourseServiceBus -CosmosDB异常\n{ex.Message}{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
                         }
                     }
                     foreach (var tmd in delTmdidsCls)

+ 3 - 3
TEAMModelOS.FunctionV4/TEAMModelOS.FunctionV4.csproj

@@ -5,9 +5,9 @@
 		<OutputType>Exe</OutputType>
 		<_FunctionsSkipCleanOutput>true</_FunctionsSkipCleanOutput>
 		<SignAssembly>true</SignAssembly>
-		<AssemblyVersion>5.2204.29.1</AssemblyVersion>
-		<FileVersion>5.2204.29.1</FileVersion>
-		<Version>5.2204.29</Version>
+		<AssemblyVersion>5.2205.6.1</AssemblyVersion>
+		<FileVersion>5.2205.6.1</FileVersion>
+		<Version>5.2205.6</Version>
 		<PackageId>TEAMModelOS.FunctionV4</PackageId>
 		<Authors>teammodel</Authors>
 		<Company>醍摩豆(成都)信息技术有限公司</Company>

+ 6 - 5
TEAMModelOS.SDK/Extension/HttpContextExtensions.cs

@@ -66,10 +66,10 @@ namespace TEAMModelOS.SDK.Extension
         /// <returns></returns>
         public static (string id, string school) GetApiTokenInfo(this HttpContext httpContext, string key = null)
         {
-            object id = null,  school = null;
+            object id = null, school = null;
             httpContext?.Items.TryGetValue("ID", out id);
             httpContext?.Items.TryGetValue("School", out school);
-            return (id?.ToString(),  school?.ToString());
+            return (id?.ToString(), school?.ToString());
         }
         /// <summary>
         /// 取得AuthToken權杖資訊
@@ -91,15 +91,16 @@ namespace TEAMModelOS.SDK.Extension
         /// </summary>        
         /// <param name="key">Key Name</param>
         /// <returns></returns>
-        public static (string id, string name, string picture, string school,string area ,string keyData) GetAuthTokenKey(this HttpContext httpContext, string key = null)
+        public static (string id, string name, string picture, string school, string area, string keyData) GetAuthTokenKey(this HttpContext httpContext, string key = null)
         {
-            object id = null, name = null, picture = null, school = null,area= null, keyData = null;
+            object id = null, name = null, picture = null, school = null, area = null, keyData = null;
             httpContext?.Items.TryGetValue("ID", out id);
             httpContext?.Items.TryGetValue("Name", out name);
             httpContext?.Items.TryGetValue("Picture", out picture);
             httpContext?.Items.TryGetValue("School", out school);
             httpContext?.Items.TryGetValue("Area", out area);
-            if (!string.IsNullOrWhiteSpace(key)) {
+            if (!string.IsNullOrWhiteSpace(key))
+            {
                 httpContext?.Items.TryGetValue(key, out keyData);
             }
             return (id?.ToString(), name?.ToString(), picture?.ToString(), school?.ToString(), area?.ToString(), keyData?.ToString());

+ 4 - 4
TEAMModelOS.SDK/Extension/JwtAuthExtension.cs

@@ -14,7 +14,7 @@ namespace TEAMModelOS.SDK.Extension
 {
     public static class JwtAuthExtension
     {
-        public static string CreateAuthToken(string issuer, string id, string name, string picture, string salt, string scope,string Website,string areaId="", string schoolID = "", string standard = "", string[] roles = null, string[] permissions = null, int expire = 1)
+        public static string CreateAuthToken(string issuer, string id, string name, string picture, string salt, string scope, string Website, string areaId = "", string schoolID = "", string standard = "", string[] roles = null, string[] permissions = null, int expire = 1)
         {
             // 設定要加入到 JWT Token 中的聲明資訊(Claims)  
             var payload = new JwtPayload {
@@ -29,7 +29,7 @@ namespace TEAMModelOS.SDK.Extension
                 { "standard",standard} ,//登入者的能力点标准
                 { "scope",scope},  //登入者的入口类型。 (teacher 教师端登录的醍摩豆ID、tmduser学生端登录的醍摩豆ID、student学生端登录校内账号的学生ID)
                 { "area",areaId==null?"":areaId},
-                { JwtRegisteredClaimNames.Website,Website},  
+                { JwtRegisteredClaimNames.Website,Website},
             };
 
             // 建立一組對稱式加密的金鑰,主要用於 JWT 簽章之用
@@ -46,9 +46,9 @@ namespace TEAMModelOS.SDK.Extension
 
             return serializeToken;
         }
-        public static string CreateApiToken(string issuer, string id,  string salt,string  name,List<int> auth , string schoolID = "", int expire = 1)
+        public static string CreateApiToken(string issuer, string id, string salt, string name, List<int> auth, string schoolID = "", int expire = 1)
         {
-           
+
             // 設定要加入到 JWT Token 中的聲明資訊(Claims)  
             var payload = new JwtPayload {
                 { JwtRegisteredClaimNames.Iss, issuer }, //發行者 iss: jwt签发者

+ 5 - 5
TEAMModelOS.SDK/Models/Cosmos/School/School.cs

@@ -42,9 +42,9 @@ namespace TEAMModelOS.SDK.Models
         /// 省份
         /// </summary>
         public string province { get; set; }
-       /// <summary>
-       /// 城市
-       /// </summary>
+        /// <summary>
+        /// 城市
+        /// </summary>
         public string city { get; set; }
         //县,区,郡
         public string dist { get; set; }
@@ -71,11 +71,11 @@ namespace TEAMModelOS.SDK.Models
         /// 1 普教,2 高职教
         /// </summary>
         public int type { get; set; }
-        public string standard { get; set; } 
+        public string standard { get; set; }
         /// <summary>
         /// 开启互评
         /// </summary>
-        public int hpappraise { get; set; }=0;
+        public int hpappraise { get; set; } = 0;
         /// <summary>
         /// 规模数量
         /// </summary>

+ 5 - 3
TEAMModelOS.SDK/Models/Cosmos/Student/Student.cs

@@ -5,7 +5,7 @@ using System.Threading.Tasks;
 using static TEAMModelOS.SDK.Models.Teacher;
 
 namespace TEAMModelOS.SDK.Models
-{  
+{
     public class Student : CosmosEntity
     {
         public string mail { get; set; }
@@ -43,7 +43,8 @@ namespace TEAMModelOS.SDK.Models
         public long createTime { get; set; }
         //public List<StudentParent> parents { get; set; }= new List<StudentParent>();
     }
-    public class StudentParent {
+    public class StudentParent
+    {
         //绑定信息的key(手机号,邮箱,醍摩豆id)
         public List<BindKey> bindKey { get; set; } = new List<BindKey>();
         //姓名 姓名
@@ -55,7 +56,8 @@ namespace TEAMModelOS.SDK.Models
         /// </summary>
         public string picture { get; set; }
     }
-    public class BindKey {
+    public class BindKey
+    {
         // key(手机号,邮箱,醍摩豆id,Line,Google等信息)
         public string key { get; set; }
         public string type { get; set; }

+ 6 - 5
TEAMModelOS.SDK/Models/Cosmos/Teacher/Teacher.cs

@@ -19,13 +19,14 @@ namespace TEAMModelOS.SDK.Models
         /// <summary>
         /// 创建时间  十位 时间戳
         /// </summary>
-        public long  createTime { get; set; } 
+        public long createTime { get; set; }
         /// <summary>
         /// 保留当天的登录信息
         /// </summary>
         public List<LoginInfo> loginInfos { get; set; } = new List<LoginInfo>();
 
-        public class LoginInfo {
+        public class LoginInfo
+        {
             /// <summary>
             /// 时间戳 毫秒
             /// </summary>
@@ -37,7 +38,7 @@ namespace TEAMModelOS.SDK.Models
             /// <summary>
             /// token到期时间
             /// </summary>
-            public long expire { get; set;}
+            public long expire { get; set; }
         }
         public class TeacherSchool
         {
@@ -69,8 +70,8 @@ namespace TEAMModelOS.SDK.Models
             public string username { get; set; }
             public string account { get; set; }
             // public HashSet<string> pxid { get; set; } = new HashSet<string>();
-            public List<string> data { get; set; }= new List<string>();
+            public List<string> data { get; set; } = new List<string>();
         }
-        
+
     }
 }

+ 17 - 256
TEAMModelOS.SDK/Models/Service/Common/TeacherService.cs

@@ -65,7 +65,7 @@ namespace TEAMModelOS.Services
                     teacher.areas.ForEach(x => {
                         areaIds.Add(x.areaId);
                     });
-                   
+
                 }
                 if (teacher.schools.IsNotEmpty())
                 {
@@ -149,11 +149,12 @@ namespace TEAMModelOS.Services
                                 schoolExtobj.area = area;
                             }
                             var sctch = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(id, new PartitionKey($"Teacher-{sc.schoolId}"));
-                            if (sctch.Status == 200  && sctch!= null  && sctch.ContentStream!=null)
+                            if (sctch.Status == 200 && sctch != null && sctch.ContentStream != null)
                             {
                                 var jsonDoc = await JsonDocument.ParseAsync(sctch.ContentStream);
                                 SchoolTeacher schoolTeacher = jsonDoc.RootElement.ToObject<SchoolTeacher>();
-                                if (schoolTeacher.name==null  || schoolTeacher.picture==null ||!schoolTeacher.name.Equals($"{name}") || !schoolTeacher.picture.Equals($"{picture}")) {
+                                if (schoolTeacher.name == null || schoolTeacher.picture == null || !schoolTeacher.name.Equals($"{name}") || !schoolTeacher.picture.Equals($"{picture}"))
+                                {
                                     schoolTeacher.name = $"{name}";
                                     schoolTeacher.picture = $"{picture}";
                                     await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync(schoolTeacher, id, new PartitionKey($"Teacher-{sc.schoolId}"));
@@ -195,7 +196,8 @@ namespace TEAMModelOS.Services
                         teacher.defaultSchool = teacher.schools[0].schoolId;
                     }
                 }
-                if (!string.IsNullOrEmpty(teacher.defaultSchool)) {
+                if (!string.IsNullOrEmpty(teacher.defaultSchool))
+                {
                     if (teacher.schools.IsNotEmpty())
                     {
                         var tech = teacher.schools.FindAll(x => x.status.Equals("join") && x.schoolId.Equals(teacher.defaultSchool));
@@ -206,15 +208,17 @@ namespace TEAMModelOS.Services
                             {
                                 teacher.defaultSchool = techde[0].schoolId;
                             }
-                            else {
+                            else
+                            {
                                 teacher.defaultSchool = null;
                             }
                         }
                     }
-                    else {
+                    else
+                    {
                         teacher.defaultSchool = null;
                     }
-                } 
+                }
                 //預設學校ID
                 defaultschool = teacher.defaultSchool;
             }
@@ -271,7 +275,7 @@ namespace TEAMModelOS.Services
                 }
             }
             //換取AuthToken,提供給前端
-            var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id, name?.ToString(), picture?.ToString(), _option.JwtSecretKey, Website: "IES", scope: Constant.ScopeTeacher, standard: areaa != null ? areaa.standard : "", roles: roles.ToArray(),expire:1);
+            var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id, name?.ToString(), picture?.ToString(), _option.JwtSecretKey, Website: "IES", scope: Constant.ScopeTeacher, standard: areaa != null ? areaa.standard : "", roles: roles.ToArray(), expire: 1);
 
             await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, id, new PartitionKey("Base"));
             //取得Teacher Blob 容器位置及SAS 
@@ -295,251 +299,7 @@ namespace TEAMModelOS.Services
             };
         }
 
-        public static async Task<TeacherInfo> GetTeacherInfo (AzureCosmosFactory _azureCosmos,Teacher teacher,string name,string picture,string id , AzureStorageFactory _azureStorage, Option _option)
-        {
-            List<object> schools = new List<object>();
-            List<AreaDto> areas = new List<AreaDto>();
-            List<Area> areasd = new List<Area>();
-            string defaultschool = null;
-            //TODO 取得Teacher 個人相關數據(課程清單、虛擬教室清單、歷史紀錄清單等),學校數據另外API處理,多校切換時不同
-            var client = _azureCosmos.GetCosmosClient();
-            int total = 0;
-            int tsize = 0;
-            try
-            {
-                if (teacher == null)
-                {
-                    teacher = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Teacher>(id, new PartitionKey("Base"));
-                    teacher.name = $"{name}";
-                    teacher.picture = $"{picture}";
-                }
-                else {
-                    name = teacher.name;
-                    picture = teacher.picture;
-                    id = teacher.id;
-                }
-                ///教师的个人空间
-                tsize = teacher.size;
-                ///教师的总空间 包含 个人空间和学校赠送的空间累加
-                total = teacher.size;
-                //areas = teacher.areas;
-                if (teacher.areas.IsNotEmpty())
-                {
-                    foreach (var areat in teacher.areas)
-                    {
-                        try
-                        {
-                            Area area = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<Area>($"{areat.areaId}", new PartitionKey("Base-Area"));
-                            areasd.Add(area);
-                            AreaSetting  setting= null;
-                            try 
-                            {
-                                setting= await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<AreaSetting>($"{areat.areaId}", new PartitionKey("AreaSetting"));
-                            } catch (CosmosException ex) {
-                                setting = null;
-                            }
-                            int access = 0;
-                            if (setting != null && !string.IsNullOrWhiteSpace(setting.accessConfig)) {
-                                access = 1;
-                            }
-                            if (setting != null) {
-                                setting.accessConfig = null;
-                            }
-                            areas.Add(new AreaDto { areaId = area.id, name = area.name,standard= area.standard,standardName= area.standardName,setting=setting, access= access });
-                        }
-                        catch (CosmosException)
-                        {
-                            //数据库捞不到数据
-                            continue;
-                        }
-                    }
-                }
-                //检查是否有加入学校,如果加入学校,则当个人空间size是0G的时候,则免费获得一个G空间,但无论加入多少个学校,只能获取一次 1G的免费空间。没有加入学校则默认0G空间,除非自己购买空间
-                if (teacher.schools.IsNotEmpty())
-                {
-                    foreach (var sc in teacher.schools)
-                    {
-                        string statusNow = sc.status != null ? sc.status : "";
-                        if (statusNow.Equals("join") || statusNow.Equals("invite") || statusNow.Equals("request"))
-                        {
-                            dynamic schoolExtobj = new ExpandoObject();
-                            // var schoolJson = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{sc.schoolId}", new PartitionKey("Base"));
-                            //var school = await JsonDocument.ParseAsync(schoolJson.ContentStream);
-                            schoolExtobj.schoolId = sc.schoolId;
-                            schoolExtobj.name = sc.name;
-                            schoolExtobj.status = sc.status;
-                            schoolExtobj.time = sc.time;
-                            schoolExtobj.picture = sc.picture;
-                            schoolExtobj.areaId = $"{sc.areaId}";
-                            Area area = null;
-                            int access = 0;
-                            if (!string.IsNullOrEmpty($"{sc.areaId}"))
-                            {
-                                
-                                try
-                                {
-                                    
-                                    area = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<Area>($"{sc.areaId}", new PartitionKey("Base-Area"));
-                                    AreaSetting setting = null;
-                                    try
-                                    {
-                                        setting = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<AreaSetting>($"{area.id}", new PartitionKey("AreaSetting"));
-                                    }
-                                    catch (CosmosException ex)
-                                    {
-                                        setting = null;
-                                    }
-                                      
-                                    if (setting != null && !string.IsNullOrWhiteSpace(setting.accessConfig))
-                                    {
-                                        access = 1;
-                                    }
-                                    areasd.Add(area);
-                                     
-                                }
-                                catch (CosmosException)
-                                {
-                                    area = null;
-                                }
-                            }
-                            if (area != null)
-                            {
-                                schoolExtobj.area = new {area.name, area.id, area.institution, area.provName, area.code, area.cityCode, area.cityName, area.standard, area.provCode, area.pk, access };
-
-                            }
-                            else {
-                                schoolExtobj.area = area;
-                            }
-                            var sctch = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(id, new PartitionKey($"Teacher-{sc.schoolId}"));
-                            if (sctch.Status == 200)
-                            {
-                                var jsonDoc = await JsonDocument.ParseAsync(sctch.ContentStream);
-                                SchoolTeacher schoolTeacher = jsonDoc.RootElement.ToObject<SchoolTeacher>();
-                                schoolTeacher.name = $"{name}";
-                                schoolTeacher.picture = $"{picture}";
-                                await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync(schoolTeacher, id, new PartitionKey($"Teacher-{sc.schoolId}"));
-                                if (jsonDoc.RootElement.TryGetProperty("size", out JsonElement _size) && _size.ValueKind.Equals(JsonValueKind.Number))
-                                {
-                                    total += _size.GetInt32();
-                                    schoolExtobj.size = _size.GetInt32();
-                                }
-                                else { schoolExtobj.size = 0; }
-                            }
-                            else
-                            {
-                                schoolExtobj.size = 0;
-                            }
-                            if (statusNow.Equals("join"))
-                            {
-                                //初始化
-                                await TmdUserService.JoinSchool(client, teacher.id, teacher.picture, teacher.name, sc.schoolId, sc.name);
-                            }
-                            schools.Add(schoolExtobj);
-                        }
-                    }
-                    //如果包含任何申请,邀请,加入学校的记录 且个人空间未分配2G  则默认分配个人空间至2G.
-                    if (teacher.size < 2 && teacher.schools.Count > 0)
-                    {
-                        teacher.size = 2;
-                    }
-                    //如果未包含任何申请,邀请,加入学校的记录 且 个人空间没有分配1G 则默认赠送一个G 
-                    if (teacher.schools.Count == 0 && teacher.size < 1)
-                    {
-                        teacher.size = 1;
-                    }
-                }
-                if (string.IsNullOrEmpty(teacher.defaultSchool) && teacher.schools.IsNotEmpty())
-                {
-                    var tech = teacher.schools.FindAll(x => x.status.Equals("join"));
-                    if (tech.IsNotEmpty())
-                    {
-                        teacher.defaultSchool = teacher.schools[0].schoolId;
-                    }
-                }
-                await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, id, new PartitionKey("Base"));
-                //預設學校ID
-                defaultschool = teacher.defaultSchool;
-            }
-            catch (CosmosException ex)
-            {
-                if (ex.Status == 404)
-                {
-                    //如果沒有,則初始化Teacher基本資料到Cosmos
-                      teacher = new Teacher
-                      {
-                          createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
-                          id = id,
-                        pk = "Base",
-                        code = "Base",
-                        name = name?.ToString(),
-                        picture = picture?.ToString(),
-                        //创建账号并第一次登录IES5则默认赠送1G
-                        size = 1,
-                        defaultSchool = null,
-                        schools = new List<Teacher.TeacherSchool>(),
-                    };
-                    var container = _azureStorage.GetBlobContainerClient(id);
-                    await container.CreateIfNotExistsAsync(PublicAccessType.None); //嘗試創建Teacher私有容器,如存在則不做任何事,保障容器一定存在
-                    teacher = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync<Teacher>(teacher, new PartitionKey("Base"));
-                    total = teacher.size;
-                    tsize = teacher.size;
-                }
-            }
-            //私人課程
-            List<object> courses = new List<object>();
-            await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIterator(queryText: $"select value(c) from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Course-{id}") }))
-            {
-                using var json = await JsonDocument.ParseAsync(item.ContentStream);
-                if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
-                {
-                    foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
-                    {
-                        courses.Add(obj.ToObject<object>());
-                    }
-                }
-            }
-
-             
-            List<string> roles = new List<string>() { "teacher" };
-            Area areaa = null;
-            if (areas.Count > 0)
-            {
-                roles.Add("area");
-                if (!string.IsNullOrEmpty($"{areas[0]}"))
-                {
-
-                    try
-                    {
-                        areaa = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<Area>($"{areas[0].areaId}", new PartitionKey("Base-Area"));
-                    }
-                    catch (CosmosException)
-                    {
-                        areaa = null;
-                    }
-                }
-            }
-            //換取AuthToken,提供給前端
-            var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id, name?.ToString(), picture?.ToString(), _option.JwtSecretKey, Website: "IES", scope: Constant.ScopeTeacher, standard: areaa != null ? areaa.standard : "", roles: roles.ToArray(),expire: 1);
-            //取得Teacher Blob 容器位置及SAS 
-            await _azureStorage.GetBlobContainerClient(id).CreateIfNotExistsAsync(PublicAccessType.None); //嘗試創建Teacher私有容器,如存在則不做任何事,保障容器一定存在
-            var (blob_uri, blob_sas) = _azureStorage.GetBlobContainerSAS(id, BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List | BlobContainerSasPermissions.Delete);
-            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);
-            return new TeacherInfo {
-                auth_token = auth_token,
-                blob_uri = blob_uri,
-                blob_sas = blob_sas,
-                schools = schools,
-                defaultschool = defaultschool,
-                courses = courses,
-                total=total,
-                osblob_sas=osblob_sas,
-                osblob_uri = osblob_uri,
-                tsize=tsize,
-                areas= areas,
-                teacher=teacher
-            };
-        }
-    }
+       }
     public record AreaDto
     {
         //areaId = area.id, name = area.name, area.standard, area.standardName
@@ -551,13 +311,14 @@ namespace TEAMModelOS.Services
         public AreaSetting setting { get; set; }
         public int access { get; set; } = 0;
     }
-    public record TeacherInfo { 
+    public record TeacherInfo
+    {
         public string auth_token { get; set; }
         public string blob_uri { get; set; }
         public string blob_sas { get; set; }
-        public List<object> schools { get; set; }= new List<object> ();
+        public List<object> schools { get; set; } = new List<object>();
         public string defaultschool { get; set; }
-        public List<object> courses { get; set; }= new List<object>();
+        public List<object> courses { get; set; } = new List<object>();
         public int total { get; set; }
         public string osblob_uri { get; set; }
         public string osblob_sas { get; set; }

+ 39 - 8
TEAMModelOS.SDK/Models/Service/LoginService.cs

@@ -13,23 +13,54 @@ namespace TEAMModelOS.SDK.Models.Service
 {
     public static class LoginService
     {
-
-        public static List<LoginInfo> DoLoginInfo(List<LoginInfo> loginInfos,long  expire, long now ,string school,string scope, string id , string ip, string region) {
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="loginInfos"></param>
+        /// <param name="expire"></param>
+        /// <param name="now"></param>
+        /// <param name="school"></param>
+        /// <param name="scope">Teacher Student  TmdUser</param>
+        /// <param name="id"></param>
+        /// <param name="ip"></param>
+        /// <param name="region"></param>
+        /// <returns></returns>
+        public static async Task<List<LoginInfo>> DoLoginInfo(List<LoginInfo> loginInfos, long expire, long now, string school, string scope, string id, string ip, string region)
+        {
             if (loginInfos.Any())
             {
-                if (loginInfos.Count() >=5) {
-                    loginInfos= loginInfos.OrderBy(x => x.expire).ToList();
+                if (loginInfos.Count() >= 5)
+                {
+                    loginInfos = loginInfos.OrderBy(x => x.expire).ToList();
                     loginInfos.RemoveRange(4, loginInfos.Count() - 4);
                 }
                 loginInfos.Add(new LoginInfo { expire = expire, ip = ip, time = now });
             }
-            else {
-                loginInfos = new List<LoginInfo> { new LoginInfo { expire = expire,ip=ip,time= now } };
+            else
+            {
+                loginInfos = new List<LoginInfo> { new LoginInfo { expire = expire, ip = ip, time = now } };
             }
+            if (!string.IsNullOrWhiteSpace(school)) {
+                //Login:School:School_ID:Teacher:20220506   value 15   1
+                //await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:School:{school}:20220506", "15",1);
+
+                //await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:School:{school}:20220506", "15", 1);
+            }
+            //Login:IES:20220506
+
+            //var counts = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Vote:Count:{vote.id}");
+            //List<dynamic> countcds = new List<dynamic>();
+            //if (counts != null && counts.Length > 0)
+            //{
+            //    foreach (var count in counts)
+            //    {
+            //        countcds.Add(new { code = count.Element.ToString(), count = (int)count.Score });
+            //    }
+            //}
             return loginInfos;
         }
 
-        public static async Task<(string ip, string region)> LoginIp(HttpContext httpContext,IPSearcher _searcher)
+        public static async Task<(string ip, string region)> LoginIp(HttpContext httpContext, IPSearcher _searcher)
         {
 
             var IpPort = httpContext.Request.Headers["X-Forwarded-For"].FirstOrDefault();
@@ -46,7 +77,7 @@ namespace TEAMModelOS.SDK.Models.Service
             return (ip, region);
         }
 
-        public static   void LoginLog(HttpContext httpContext, Option _option, ILogger _logger, DingDing _dingDing,    string ip, string region, string id, string name, int status)
+        public static void LoginLog(HttpContext httpContext, Option _option, ILogger _logger, DingDing _dingDing, string ip, string region, string id, string name, int status)
         {
             httpContext.Request.Headers.TryGetValue("referer", out var referer);
             httpContext.Request.Headers.TryGetValue("sec-ch-ua", out var chua);

+ 15 - 15
TEAMModelOS.SDK/Models/Service/StudentService.cs

@@ -26,7 +26,7 @@ namespace TEAMModelOS.SDK
         /// <param name="schoolId"></param>
         /// <param name="students"></param>
         /// <returns></returns>
-        public static async Task<List<Student>> GeStudentData(AzureCosmosFactory _azureCosmos ,string schoolId, IEnumerable<string> students)
+        public static async Task<List<Student>> GeStudentData(AzureCosmosFactory _azureCosmos, string schoolId, IEnumerable<string> students)
         {
             List<Student> studentDatas = new List<Student>();
             if (students.Any())
@@ -49,7 +49,7 @@ namespace TEAMModelOS.SDK
         /// <param name="opt">操作</param>
         /// <param name="prestudents">变更前的学生</param>
         /// <returns></returns>
-        public static async Task<Dictionary<string, GroupChange>> CheckStudent(AzureServiceBusFactory _serviceBus,IConfiguration _configuration,AzureCosmosFactory _azureCosmos, string schoolId, List<Student> students, List<Student> prestudents)
+        public static async Task<Dictionary<string, GroupChange>> CheckStudent(AzureServiceBusFactory _serviceBus, IConfiguration _configuration, AzureCosmosFactory _azureCosmos, string schoolId, List<Student> students, List<Student> prestudents)
         {
             List<Student> aftstudents = await StudentService.GeStudentData(_azureCosmos, schoolId, students?.Select(x => x.id));
             Dictionary<string, GroupChange> dictChange = new Dictionary<string, GroupChange>();
@@ -602,7 +602,7 @@ namespace TEAMModelOS.SDK
 
                 //var   classNos = sortedImpData.classInfo.Select(o => new {key= o.Key, periodId=o.Value.periodId,index= o.Value.gradeIndex,year = o.Value.year }).ToList();
                 //抓到教室資訊
-                var classInfos = await getClassInfoUseNo( _azureCosmos, _dingDing, _option, schoolId, sortedImpData.classInfo);
+                var classInfos = await getClassInfoUseNo(_azureCosmos, _dingDing, _option, schoolId, sortedImpData.classInfo);
                 //取出已存在教室的classId,後面查座號要用。
 
                 List<Task> tasks = new List<Task>();
@@ -663,7 +663,7 @@ namespace TEAMModelOS.SDK
                         //}
                         //建立新教室
                         (string classId, string classNo, string className, string periodId, string gradeId, int classYear) retCreateClassInfo =
-                        await createClassInfo(_azureCosmos,_dingDing,_option,
+                        await createClassInfo(_azureCosmos, _dingDing, _option,
                             schoolId,
                             null,
                             sortedImpData.classInfo[item.Key].className,
@@ -694,7 +694,7 @@ namespace TEAMModelOS.SDK
 
                 CosmosContainer cosmosContainer = _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Student");
 
-                long now= DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                 //並行處理
                 foreach (var stud in sortedImpData.studs)
                 {
@@ -760,7 +760,7 @@ namespace TEAMModelOS.SDK
                     writerNew.WriteNull("mail");
                     writerNew.WriteNull("mobile");
                     writerNew.WriteNull("country");
-                
+
                     if (!string.IsNullOrWhiteSpace(stud.Value.periodId))
                     {
                         writerNew.WriteString("periodId", stud.Value.periodId);
@@ -861,8 +861,8 @@ namespace TEAMModelOS.SDK
                             tmpStudInfo.classId,
                             tmpStudInfo.classNo,
                             tmpStudInfo.className,
-                           // tmpStudInfo.gradeId,
-                           // tmpStudInfo.periodId
+                            // tmpStudInfo.gradeId,
+                            // tmpStudInfo.periodId
                         });
                 }
                 return (retStuds, duplNos.Where(o => o.Value.Count != 0).ToDictionary(o => o.Key, o => o.Value), errorIds);
@@ -932,7 +932,7 @@ namespace TEAMModelOS.SDK
 
                 writer.WriteEndObject();
                 writer.Flush();
-             
+
                 var response = await _azureCosmos
                                 .GetCosmosClient()
                                 .GetContainer(Constant.TEAMModelOS, "Student")
@@ -1051,7 +1051,7 @@ namespace TEAMModelOS.SDK
                 List<string> searchId = new List<string>();
                 if (!string.IsNullOrWhiteSpace(byClassId))
                 {
-                    var classInfos = await getClassInfoUseId(_azureCosmos,_dingDing,_option, schoolId, new List<string>() { byClassId });
+                    var classInfos = await getClassInfoUseId(_azureCosmos, _dingDing, _option, schoolId, new List<string>() { byClassId });
                     foreach (var classInfo in classInfos)
                     {
                         var students = classInfo.Value.GetProperty("students").EnumerateArray();
@@ -1265,7 +1265,7 @@ namespace TEAMModelOS.SDK
                 List<object> ret = new List<object>();
 
                 //查教室的資訊,用以取得gradeId,periodId資訊。
-                var classInfos = await getClassInfoUseId(_azureCosmos,_dingDing,_option, schoolId, dicClassStuds.Keys.ToList());
+                var classInfos = await getClassInfoUseId(_azureCosmos, _dingDing, _option, schoolId, dicClassStuds.Keys.ToList());
 
                 //輪循所有教室學生的資料
                 foreach (var classStud in dicClassStuds)
@@ -1379,7 +1379,7 @@ namespace TEAMModelOS.SDK
         /// <param name="schoolId"></param>
         /// <param name="students"></param>
         /// <returns></returns>
-        public  static  async Task<List<string>> deleteStudents(AzureCosmosFactory _azureCosmos, DingDing _dingDing, Option _option, string schoolId, JsonElement.ArrayEnumerator students)
+        public static async Task<List<string>> deleteStudents(AzureCosmosFactory _azureCosmos, DingDing _dingDing, Option _option, string schoolId, JsonElement.ArrayEnumerator students)
         {
             List<string> sucIds = new List<string>();
             try
@@ -1468,7 +1468,7 @@ namespace TEAMModelOS.SDK
         /// <param name="schoolId"></param>
         /// <param name="students">["id1","id2",...]</param>
         /// <returns></returns>
-        public static  async Task<(List<string> studs, List<string> nonexistentIds, List<string> errorIds)> removeStudentClassInfo(AzureCosmosFactory _azureCosmos, DingDing _dingDing, Option _option, string schoolId, JsonElement.ArrayEnumerator students)
+        public static async Task<(List<string> studs, List<string> nonexistentIds, List<string> errorIds)> removeStudentClassInfo(AzureCosmosFactory _azureCosmos, DingDing _dingDing, Option _option, string schoolId, JsonElement.ArrayEnumerator students)
         {
             //紀錄輸入的學生
             List<string> impStuds = new List<string>();
@@ -1783,7 +1783,7 @@ namespace TEAMModelOS.SDK
                 }
 
                 //查詢欲加入的教室資訊。
-                var classInfo = await getClassInfoUseId(_azureCosmos,_dingDing,_option, schoolId, classStuds.Keys.ToList());
+                var classInfo = await getClassInfoUseId(_azureCosmos, _dingDing, _option, schoolId, classStuds.Keys.ToList());
 
                 //準備查詢db資料
                 CosmosContainer cosmosContainer = _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Student");
@@ -1821,7 +1821,7 @@ namespace TEAMModelOS.SDK
                     //檢查座號是否有重複
                     //若只是改基本資料,該處還是會查到相同的座號。
                     var sutdNos = item.Value.Select(o => o.no).ToList();
-                    var existNos = await checkStudNo(_azureCosmos,_dingDing,_option, schoolId, item.Key, sutdNos);
+                    var existNos = await checkStudNo(_azureCosmos, _dingDing, _option, schoolId, item.Key, sutdNos);
 
                     //更新並寫入學生資料
                     if (item.Value.Count != 0)

+ 6 - 4
TEAMModelOS.SDK/Models/Service/Third/Xkw/XkwOAuthModel.cs

@@ -9,7 +9,7 @@ using TEAMModelOS.SDK.Context.Attributes.Azure;
 namespace TEAMModelOS.SDK.Models
 {
 
-    public class XkwOAuthModel 
+    public class XkwOAuthModel
     {
     }
     [TableName(Name = "IESOAuth")]
@@ -50,7 +50,8 @@ namespace TEAMModelOS.SDK.Models
     }
 
     [TableName(Name = "IESOAuth")]
-    public class OAuthUser : TableEntity {
+    public class OAuthUser : TableEntity
+    {
         //PartitionKey OAuthUser-xkw, OAuthUser-axy , 单点配置
         //RowKey  tmdid
         public string OpenId { get; set; }
@@ -97,8 +98,9 @@ namespace TEAMModelOS.SDK.Models
         public string userId { get; set; }
         public string domain { get; set; }
     }
-    
-    public record OAuthCode {
+
+    public record OAuthCode
+    {
         public string code { get; set; }
         public string state { get; set; }
         //模块,res,item,paper

+ 22 - 16
TEAMModelOS.SDK/Models/Service/TmdUserService.cs

@@ -10,39 +10,45 @@ namespace TEAMModelOS.SDK
 {
     public class TmdUserService
     {
-        public static async Task<TmdUser> JoinSchool(CosmosClient client, string tmdid,string picture,string name , string schoolId, string schoolName) {
+        public static async Task<TmdUser> JoinSchool(CosmosClient client, string tmdid, string picture, string name, string schoolId, string schoolName)
+        {
             TmdUser tmdUser = null;
-            try {
-                tmdUser= await client.GetContainer(Constant.TEAMModelOS, "Student").ReadItemAsync<TmdUser>(tmdid, partitionKey: new PartitionKey("Base"));
-                tmdUser.picture = string.IsNullOrEmpty(picture) ? picture:tmdUser.picture;
+            try
+            {
+                tmdUser = await client.GetContainer(Constant.TEAMModelOS, "Student").ReadItemAsync<TmdUser>(tmdid, partitionKey: new PartitionKey("Base"));
+                tmdUser.picture = string.IsNullOrEmpty(picture) ? picture : tmdUser.picture;
                 tmdUser.name = string.IsNullOrEmpty(name) ? name : tmdUser.name;
-                var school= tmdUser.schools.Find(x => x.schoolId.Equals(schoolId));
+                var school = tmdUser.schools.Find(x => x.schoolId.Equals(schoolId));
                 if (school == null)
                 {
 
                     tmdUser.schools.Add(new TmdUser.School { schoolId = schoolId, name = schoolName, status = "join", time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() });
                     await client.GetContainer(Constant.TEAMModelOS, "Student").ReplaceItemAsync<TmdUser>(tmdUser, tmdid, partitionKey: new PartitionKey("Base"));
                 }
-                else {
+                else
+                {
                     school.name = schoolName;
                     await client.GetContainer(Constant.TEAMModelOS, "Student").ReplaceItemAsync<TmdUser>(tmdUser, tmdid, partitionKey: new PartitionKey("Base"));
                 }
-            } catch (CosmosException ex) {
-                if (ex.Status == 404) {
+            }
+            catch (CosmosException ex)
+            {
+                if (ex.Status == 404)
+                {
                     tmdUser = new TmdUser()
                     {
-                        createTime=DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
+                        createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
                         id = tmdid,
                         code = "Base",
-                        schools = new List<TmdUser.School>() { 
-                            new TmdUser.School { 
+                        schools = new List<TmdUser.School>() {
+                            new TmdUser.School {
                                 schoolId = schoolId, status = "join", name = schoolName, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
-                            } 
+                            }
                         },
-                        defaultSchool=schoolId,
-                        picture=picture,
-                        name=name,
-                        ttl=-1
+                        defaultSchool = schoolId,
+                        picture = picture,
+                        name = name,
+                        ttl = -1
                     };
                     await client.GetContainer(Constant.TEAMModelOS, "Student").CreateItemAsync(tmdUser, partitionKey: new PartitionKey(tmdUser.code));
                 }

+ 83 - 65
TEAMModelOS/Controllers/Both/GroupListController.cs

@@ -27,7 +27,7 @@ namespace TEAMModelOS.Controllers
 {
     [ProducesResponseType(StatusCodes.Status200OK)]
     [ProducesResponseType(StatusCodes.Status400BadRequest)]
-    
+
     [Route("grouplist")]
     [ApiController]
     public class GroupListController : ControllerBase
@@ -41,14 +41,14 @@ namespace TEAMModelOS.Controllers
         private readonly CoreAPIHttpService _coreAPIHttpService;
         private const string SummarySql = " 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 ";
         public IConfiguration _configuration { get; set; }
-        public GroupListController(CoreAPIHttpService coreAPIHttpService,AzureCosmosFactory azureCosmos, DingDing dingDing, IOptionsSnapshot<Option> option, AzureServiceBusFactory serviceBus, AzureStorageFactory azureStorage, IConfiguration configuration, NotificationService notificationService)
+        public GroupListController(CoreAPIHttpService coreAPIHttpService, AzureCosmosFactory azureCosmos, DingDing dingDing, IOptionsSnapshot<Option> option, AzureServiceBusFactory serviceBus, AzureStorageFactory azureStorage, IConfiguration configuration, NotificationService notificationService)
         {
             _azureCosmos = azureCosmos;
             _dingDing = dingDing;
             _option = option?.Value;
             _serviceBus = serviceBus;
             _configuration = configuration;
-            _azureStorage = azureStorage; 
+            _azureStorage = azureStorage;
             _notificationService = notificationService;
             _coreAPIHttpService = coreAPIHttpService;
         }
@@ -120,11 +120,11 @@ namespace TEAMModelOS.Controllers
                     await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Student").CreateItemAsync<TmdUser>(tmduser, new PartitionKey("Base"));
                 }
             }
-            (int status, GroupList stuList) data = await GroupListService.CodeJoinList(client, $"{_stuListNo}", id,   type: 1,   $"{school}");
+            (int status, GroupList stuList) data = await GroupListService.CodeJoinList(client, $"{_stuListNo}", id, type: 1, $"{school}");
             //没有TmdUser时
             if (data.status == 0)
             {
-                await GroupListService.UpsertList(data.stuList, _azureCosmos,  _configuration, _serviceBus);
+                await GroupListService.UpsertList(data.stuList, _azureCosmos, _configuration, _serviceBus);
 
                 List<string> ids = new List<string>();
                 if (data.stuList.scope.Equals("private") && !string.IsNullOrEmpty(data.stuList.creatorId))
@@ -168,7 +168,7 @@ namespace TEAMModelOS.Controllers
             }
 
         }
-      
+
         /// <summary>
         /// 根据邀请码加入名单
         /// </summary>
@@ -192,7 +192,7 @@ namespace TEAMModelOS.Controllers
                 type = 2;
                 Student student = await client.GetContainer(Constant.TEAMModelOS, "Student").ReadItemAsync<Student>(userid, new PartitionKey($"Base-{school}"));
                 no = student.no;
-                
+
             }
             if ($"{scope}".Equals(Constant.ScopeTmdUser))
             {
@@ -202,10 +202,10 @@ namespace TEAMModelOS.Controllers
             {
                 type = 1;
             }
-            (int status, GroupList stuList) data = await GroupListService.CodeJoinList(client, $"{_stuListNo}", userid,   type, school);
+            (int status, GroupList stuList) data = await GroupListService.CodeJoinList(client, $"{_stuListNo}", userid, type, school);
             if (data.status == 0)
             {
-              
+
                 await GroupListService.UpsertList(data.stuList, _azureCosmos, _configuration, _serviceBus);
 
                 List<string> ids = new List<string>();
@@ -213,7 +213,7 @@ namespace TEAMModelOS.Controllers
                 {
                     ids.Add(data.stuList.creatorId);
                 }
-               else if (data.stuList.scope.Equals("school") && !string.IsNullOrEmpty(data.stuList.school)) 
+                else if (data.stuList.scope.Equals("school") && !string.IsNullOrEmpty(data.stuList.school))
                 {
                     //通知管理员
                     string sql = "select distinct  value(c.id) from c where array_contains(c.roles,'admin')";
@@ -223,7 +223,8 @@ namespace TEAMModelOS.Controllers
                         ids.Add(item);
                     }
                 }
-                if (ids.IsNotEmpty()) {
+                if (ids.IsNotEmpty())
+                {
                     string bizcode = "scan-join";
                     Notification notification = new Notification
                     {
@@ -266,7 +267,8 @@ namespace TEAMModelOS.Controllers
             StringBuilder sql = new StringBuilder($"SELECT  {SummarySql} ,A1.tag FROM c " +
                 $" join A1 in  c. members where A1.id='{id}' and A1.tag<>null  ");
             HttpContext?.Items.TryGetValue("Scope", out scope);
-            if (!string.IsNullOrEmpty(school)&& $"{scope}".Equals(Constant.ScopeStudent)) {
+            if (!string.IsNullOrEmpty(school) && $"{scope}".Equals(Constant.ScopeStudent))
+            {
                 sql.Append($" and  A1.code='{school}'");
             }
             List<dynamic> groupLists = new List<dynamic>();
@@ -298,7 +300,7 @@ namespace TEAMModelOS.Controllers
             json.TryGetProperty("schoolId", out JsonElement schoolId);
             if (!json.TryGetProperty("opt", out JsonElement opt)) { return BadRequest(); }
             json.TryGetProperty("periodId", out JsonElement periodId);
-           
+
             List<GroupListGrp> groupLists = new List<GroupListGrp>();
             switch (true)
             {
@@ -306,15 +308,16 @@ namespace TEAMModelOS.Controllers
                 case bool when $"{opt}".Equals("manage", StringComparison.OrdinalIgnoreCase):
                     //包含,学校的行政班,教学班
                     json.TryGetProperty("type", out JsonElement _type);
-                    List<string> types = null ;
+                    List<string> types = null;
                     if (_type.ValueKind.Equals(JsonValueKind.Array))
                     {
                         types = _type.ToObject<List<string>>();
                     }
-                    else if (_type.ValueKind.Equals(JsonValueKind.String)) {
+                    else if (_type.ValueKind.Equals(JsonValueKind.String))
+                    {
                         types = new List<string> { $"{types}" };
                     }
-                    if (types.IsEmpty() ||  types.Contains("class")  )
+                    if (types.IsEmpty() || types.Contains("class"))
                     {
                         StringBuilder classsql = new StringBuilder($"SELECT c.id,c.name,c.periodId ,c.year  FROM c ");
                         if (!string.IsNullOrEmpty($"{periodId}"))
@@ -348,7 +351,7 @@ namespace TEAMModelOS.Controllers
                         }
                     }
 
-                    if (types.IsEmpty() || types.Contains("teach") )
+                    if (types.IsEmpty() || types.Contains("teach"))
                     {
                         //教学班
                         StringBuilder teachsql = new StringBuilder($" SELECT distinct value(c) FROM c  where c.type='teach'");
@@ -364,7 +367,7 @@ namespace TEAMModelOS.Controllers
                         }
                     }
 
-                    if (types.IsEmpty() || types.Contains("research")  )
+                    if (types.IsEmpty() || types.Contains("research"))
                     {
                         //教研组
                         StringBuilder researchsql = new StringBuilder($"SELECT distinct value(c) FROM c   where c.type='research'");
@@ -376,7 +379,7 @@ namespace TEAMModelOS.Controllers
                         }
                     }
 
-                    if (types.IsEmpty()||types.Contains("yxtrain") )
+                    if (types.IsEmpty() || types.Contains("yxtrain"))
                     {
                         //研修名单
                         StringBuilder yxtrainsql = new StringBuilder($"SELECT distinct value(c) FROM c    where c.type='yxtrain'");
@@ -441,7 +444,7 @@ namespace TEAMModelOS.Controllers
                                 year = item.year,
                                 groupName = groupNames
                             };
-                           groupLists.Add(group);
+                            groupLists.Add(group);
                         }
                     }
                     if (schedule.IsNotEmpty())
@@ -455,7 +458,7 @@ namespace TEAMModelOS.Controllers
                             {
                                 HashSet<string> groupName = item.members.Where(x => !string.IsNullOrEmpty(x.groupName)).Select(y => y.groupName).ToHashSet();
                                 groupLists.Add(new GroupListGrp(item, groupName));
-                               
+
                             }
                         }
                         var schoolList = schedule.Where(x => x.scope.Equals("school")).Select(x => x.schedule.stulist).Distinct();
@@ -473,7 +476,7 @@ namespace TEAMModelOS.Controllers
                     }
                     List<CourseGroupList> courseGroups = new List<CourseGroupList>();
                     teachCourses.GroupBy(y => (y.id, y.name, y.scope, y.period.name, y.period.id, y.subject.name, y.subject.id)).ToList().ForEach(x => {
-                        List<GroupListGrp> classIds = groupLists.Where(n => x.Where(m => !string.IsNullOrEmpty(m.schedule.classId)).Select(b=>b.schedule.classId).Contains(n.id)).ToList();
+                        List<GroupListGrp> classIds = groupLists.Where(n => x.Where(m => !string.IsNullOrEmpty(m.schedule.classId)).Select(b => b.schedule.classId).Contains(n.id)).ToList();
                         List<GroupListGrp> stulists = groupLists.Where(n => x.Where(m => !string.IsNullOrEmpty(m.schedule.stulist)).Select(b => b.schedule.stulist).Contains(n.id)).ToList();
                         if (classIds == null)
                         {
@@ -503,7 +506,7 @@ namespace TEAMModelOS.Controllers
             }
             return Ok(new { error = 1, msg = "参数异常" });
         }
-        
+
         /// <summary>
         /// 根据任意名单id获取成员信息。
         /// </summary>
@@ -519,12 +522,13 @@ namespace TEAMModelOS.Controllers
             if (!json.TryGetProperty("ids", out JsonElement ids)) return BadRequest();
             json.TryGetProperty("schoolId", out JsonElement schoolId);
             json.TryGetProperty("groupNames", out JsonElement groupNames);
-            List<Dictionary<string, List<string>>> groupLists = new List<Dictionary<string, List<string>>>() ;
-            if (groupNames.ValueKind.Equals(JsonValueKind.Array)) {
+            List<Dictionary<string, List<string>>> groupLists = new List<Dictionary<string, List<string>>>();
+            if (groupNames.ValueKind.Equals(JsonValueKind.Array))
+            {
                 groupLists = groupNames.ToObject<List<Dictionary<string, List<string>>>>();
             }
             List<(string pId, List<string> gid)> ps = new List<(string pId, List<string> gid)>();
-            if ( groupLists.Count > 0)
+            if (groupLists.Count > 0)
             {
                 foreach (var gp in groupLists)
                 {
@@ -535,7 +539,7 @@ namespace TEAMModelOS.Controllers
                 }
             }
             List<string> listids = ids.ToObject<List<string>>();
-            (List < RMember > members,List < RGroupList > groups) = await GroupListService.GetStutmdidListids(_coreAPIHttpService, client, _dingDing, listids, $"{schoolId}", ps);
+            (List<RMember> members, List<RGroupList> groups) = await GroupListService.GetStutmdidListids(_coreAPIHttpService, client, _dingDing, listids, $"{schoolId}", ps);
             return Ok(new { groups, members });
         }
         /// <summary>
@@ -602,7 +606,7 @@ namespace TEAMModelOS.Controllers
                 {
                     groups.Add(item);
                 }
-                (List<RGroupList> groupsData, List<RMember> members) = await GroupListService.GetGroupListMemberInfo(_coreAPIHttpService, client, $"{type}", groups, tbname,_dingDing,$"{_schoolId}");
+                (List<RGroupList> groupsData, List<RMember> members) = await GroupListService.GetGroupListMemberInfo(_coreAPIHttpService, client, $"{type}", groups, tbname, _dingDing, $"{_schoolId}");
                 return Ok(new { groups = groupsData, members });
             }
             catch (CosmosException ex)
@@ -683,10 +687,12 @@ namespace TEAMModelOS.Controllers
         [AuthToken(Roles = "teacher,admin")]
         [HttpPost("get-classstudents-idcode")]
         [Authorize(Roles = "IES")]
-        public async Task<IActionResult> GetClassStudentsIdcode(JsonElement json) {
+        public async Task<IActionResult> GetClassStudentsIdcode(JsonElement json)
+        {
             if (!json.TryGetProperty("id", out JsonElement id)) return BadRequest();
             if (!json.TryGetProperty("code", out JsonElement _code)) return BadRequest();
-            try {
+            try
+            {
                 var client = _azureCosmos.GetCosmosClient();
                 Class clazz = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<Class>($"{id}", new PartitionKey($"Class-{_code}"));
                 List<Student> students = new List<Student>();
@@ -697,11 +703,13 @@ namespace TEAMModelOS.Controllers
                     item.pw = null;
                     students.Add(item);
                 }
-                return Ok(new { classInfo= clazz, students= students });
-            } catch (Exception ex) {
-                return Ok(new { error = 404,msg="班级不存在!" });
+                return Ok(new { classInfo = clazz, students = students });
             }
-            
+            catch (Exception ex)
+            {
+                return Ok(new { error = 404, msg = "班级不存在!" });
+            }
+
         }
         //处理通用名单
         [ProducesDefaultResponseType]
@@ -734,42 +742,47 @@ namespace TEAMModelOS.Controllers
                     }
                     groupList = await client.GetContainer(Constant.TEAMModelOS, tbname).ReadItemAsync<RGroupList>($"{id}", new PartitionKey($"{code}"));
                 }
-                else if($"{_type}".Equals("class")) {
-                    try {
+                else if ($"{_type}".Equals("class"))
+                {
+                    try
+                    {
                         code = $"Class-{_code}";
                         Class clazz = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<Class>($"{id}", new PartitionKey($"{code}"));
-                        if (clazz != null) {
+                        if (clazz != null)
+                        {
                             List<Student> students = new List<Student>();
                             await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Student").GetItemQueryIterator<Student>(queryText: $"select value(c) from c where c.classId = '{clazz.id}'",
                                 requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Base-{_code}") }))
                             {
                                 students.Add(item);
-                            }     
+                            }
                             ///行政班(学生搜寻classId动态返回)class
-                            List<RMember> smembers = students.Where(x => x.classId.Equals(clazz.id)).Select(y => new RMember {  id = y.id, code = $"{_code}", name = y.name, type = 2, picture = y.picture, no = y.no,classId=y.classId, groupId = y.groupId, groupName = y.groupName }).ToList();
+                            List<RMember> smembers = students.Where(x => x.classId.Equals(clazz.id)).Select(y => new RMember { id = y.id, code = $"{_code}", name = y.name, type = 2, picture = y.picture, no = y.no, classId = y.classId, groupId = y.groupId, groupName = y.groupName }).ToList();
                             groupList = new RGroupList
                             {
-                                id=clazz.id,
-                                code=$"GroupList-{clazz.school}",
-                                name=clazz.name,
-                                periodId=clazz.periodId,
-                                pk= "GroupList",
-                                year=clazz.year,
-                                school=clazz.school ,
+                                id = clazz.id,
+                                code = $"GroupList-{clazz.school}",
+                                name = clazz.name,
+                                periodId = clazz.periodId,
+                                pk = "GroupList",
+                                year = clazz.year,
+                                school = clazz.school,
                                 scope = "school",
                                 type = "class",
                                 scount = smembers.Count,
-                                no=clazz.no,
-                                leader=clazz.teacher?.id,
-                                members= smembers,
+                                no = clazz.no,
+                                leader = clazz.teacher?.id,
+                                members = smembers,
                             };
                         }
-                    }catch (CosmosException ex) {
+                    }
+                    catch (CosmosException ex)
+                    {
                         await _dingDing.SendBotMsg($"OS,{_option.Location},grouplist/get-grouplist-idcode()\n{ex.Message}{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
                         return Ok(new { groupList });
                     }
                 }
-                (List<RGroupList> groupsData, List<RMember> members) = await GroupListService.GetGroupListMemberInfo(_coreAPIHttpService, client, $"{groupList.type}", new List<RGroupList> { groupList }, tbname,_dingDing, $"{_code}");
+                (List<RGroupList> groupsData, List<RMember> members) = await GroupListService.GetGroupListMemberInfo(_coreAPIHttpService, client, $"{groupList.type}", new List<RGroupList> { groupList }, tbname, _dingDing, $"{_code}");
                 groupList = groupsData.FirstOrDefault();
             }
             catch (CosmosException ex)
@@ -783,7 +796,7 @@ namespace TEAMModelOS.Controllers
             }
             return Ok(new { groupList });
         }
-       
+
         /// <summary>
         /// 保存或更新通用名单
         /// </summary>
@@ -836,7 +849,7 @@ namespace TEAMModelOS.Controllers
                     case bool when $"{list.type}".Equals("friend", StringComparison.OrdinalIgnoreCase):
                         list.type = "friend";
                         list.scope = "private";
-                        list = await GroupListService.UpsertList(list, _azureCosmos,_configuration, _serviceBus);
+                        list = await GroupListService.UpsertList(list, _azureCosmos, _configuration, _serviceBus);
                         break;
                     //社交群组类型(包含学校交流群组,个人交流群组),成员账号类型可以是学校学生账号和醍摩豆ID,,分区键为GroupList-hbcn 
                     case bool when $"{list.type}".Equals("group", StringComparison.OrdinalIgnoreCase):
@@ -878,12 +891,12 @@ namespace TEAMModelOS.Controllers
                 GroupChange change = new GroupChange();
                 string tbname = "";
                 string datacode = "";
-                if (scope.ToString().Equals("school", StringComparison.OrdinalIgnoreCase)) 
+                if (scope.ToString().Equals("school", StringComparison.OrdinalIgnoreCase))
                 {
                     tbname = "School";
                     datacode = $"GroupList-{code}";
                 }
-                else 
+                else
                 {
                     tbname = "Teacher";
                     datacode = $"GroupList";
@@ -892,7 +905,7 @@ namespace TEAMModelOS.Controllers
                 var tleave = groupList.members.FindAll(x => x.type == 1);
                 if (tleave.IsNotEmpty())
                 {
-                    if (groupList.type.Equals("research")||groupList.type.Equals("yxtrain"))
+                    if (groupList.type.Equals("research") || groupList.type.Equals("yxtrain"))
                     {
                         change.tchleave.AddRange(tleave);
                     }
@@ -913,7 +926,8 @@ namespace TEAMModelOS.Controllers
                 change.creatorId = groupList.creatorId;
                 change.type = groupList.type;
                 change.status = "delete";
-                if (change.tmdleave.IsNotEmpty() || change.tchleave.IsNotEmpty() || change.stuleave.IsNotEmpty()) {
+                if (change.tmdleave.IsNotEmpty() || change.tchleave.IsNotEmpty() || change.stuleave.IsNotEmpty())
+                {
                     var messageChange = new ServiceBusMessage(change.ToJsonString());
                     messageChange.ApplicationProperties.Add("name", "GroupChange");
                     var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
@@ -925,7 +939,7 @@ namespace TEAMModelOS.Controllers
             catch (Exception ex)
             {
                 await _dingDing.SendBotMsg($"OS,{_option.Location},grouplist/delete-grouplist()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
-                return Ok(new { error=400 });
+                return Ok(new { error = 400 });
             }
         }
 
@@ -945,7 +959,8 @@ namespace TEAMModelOS.Controllers
             if (!json.TryGetProperty("id", out JsonElement _id)) { return BadRequest(); }
             if (!json.TryGetProperty("code", out JsonElement _code)) { return BadRequest(); }
             if (!json.TryGetProperty("type", out JsonElement _type)) { return BadRequest(); }
-            try {
+            try
+            {
                 GroupList groupList = null;
                 string tbname = $"{_scope}".Equals("private") ? "Teacher" : "School";
                 string code = "";
@@ -966,7 +981,7 @@ namespace TEAMModelOS.Controllers
                 switch (true)
                 {
                     case bool when $"{_opt}".Equals("up-nickname", StringComparison.OrdinalIgnoreCase) && json.TryGetProperty("members", out JsonElement _members):
-                        var members=   _members.ToObject<List<Member>>();
+                        var members = _members.ToObject<List<Member>>();
                         List<Member> updateSuccess = new List<Member>();
                         List<Member> updateFailed = new List<Member>();
                         members.ForEach(x => {
@@ -976,18 +991,21 @@ namespace TEAMModelOS.Controllers
                                 member.nickname = x.nickname;
                                 updateSuccess.Add(member);
                             }
-                            else {
+                            else
+                            {
                                 updateFailed.Add(x);
                             }
                         });
-                        await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname).ReplaceItemAsync<GroupList>(groupList,$"{_id}", new PartitionKey(code));
+                        await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname).ReplaceItemAsync<GroupList>(groupList, $"{_id}", new PartitionKey(code));
                         return Ok(new { updateSuccess, updateFailed });
                 }
-            } catch (Exception ex){
-               await _dingDing.SendBotMsg($"{_option.Location},更新名单成员信息异常{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"{_option.Location},更新名单成员信息异常{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
                 return BadRequest();
             }
-            
+
             return Ok();
         }
     }

+ 36 - 29
TEAMModelOS/Controllers/Client/HiTAControlller.cs

@@ -42,14 +42,14 @@ namespace TEAMModelOS.Controllers.Client
             AzureCosmosFactory azureCosmos,
             DingDing dingDing,
             SnowflakeId snowflakeId,
-            IOptionsSnapshot<Option> option,IConfiguration configuration, NotificationService notificationService)
+            IOptionsSnapshot<Option> option, IConfiguration configuration, NotificationService notificationService)
         {
             _azureStorage = azureStorage;
             _azureRedis = azureRedis;
             _azureCosmos = azureCosmos;
             _dingDing = dingDing;
             _snowflakeId = snowflakeId;
-            _option = option?.Value; 
+            _option = option?.Value;
             _configuration = configuration;
             _notificationService = notificationService;
         }
@@ -57,14 +57,14 @@ namespace TEAMModelOS.Controllers.Client
         public class HiTAJoinSchool
         {
             [Required(ErrorMessage = "{0} 必须填写")]
-            public string id{ get; set; }
+            public string id { get; set; }
             [Required(ErrorMessage = "{0} 必须填写")]
             public string name { get; set; }
             //[Required(ErrorMessage = "{0} 必须填写")]
             public string pic { get; set; }
             [Required(ErrorMessage = "{0} 必须填写")]
             public string school { get; set; }
-            public long  ts { get; set; }
+            public long ts { get; set; }
         }
 
         /// <summary>
@@ -75,8 +75,9 @@ namespace TEAMModelOS.Controllers.Client
         [ProducesDefaultResponseType]
         [HttpGet("join-school")]
         //[Authorize(Roles = "HiTA")]
-        public async Task<IActionResult> ScanCodeJoinSchool([FromQuery] HiTAJoinSchool join) {
-            string school=join.school;
+        public async Task<IActionResult> ScanCodeJoinSchool([FromQuery] HiTAJoinSchool join)
+        {
+            string school = join.school;
             string id = join.id;
             string name = join.name;
             string picture = join.pic;
@@ -84,14 +85,18 @@ namespace TEAMModelOS.Controllers.Client
             long nowTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
             if (nowTime - ts > 3600000)
             {
-                return Ok(new { error=1,msg="超时!"});
+                return Ok(new { error = 1, msg = "超时!" });
             }
             var client = _azureCosmos.GetCosmosClient();
-            School schoolInfo = null; 
-            try {
-                 schoolInfo = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{school}", new PartitionKey("Base"));
-            } catch (CosmosException ex) {
-                if (ex.Status == 404) {
+            School schoolInfo = null;
+            try
+            {
+                schoolInfo = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{school}", new PartitionKey("Base"));
+            }
+            catch (CosmosException ex)
+            {
+                if (ex.Status == 404)
+                {
                     return Ok(new { error = 2, msg = "该学校不存在!" });
                 }
             }
@@ -99,7 +104,7 @@ namespace TEAMModelOS.Controllers.Client
             try
             {
                 teacher = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Teacher>($"{id}", new PartitionKey("Base"));
-                var sch= teacher.schools.Find(x => x.schoolId.Equals($"{school}"));
+                var sch = teacher.schools.Find(x => x.schoolId.Equals($"{school}"));
                 if (sch != null)
                 {
                     if (sch.status.Equals("join"))
@@ -115,11 +120,13 @@ namespace TEAMModelOS.Controllers.Client
                         sch.areaId = schoolInfo?.areaId;
                     }
                 }
-                else {
+                else
+                {
                     teacher.schools.Add(new Teacher.TeacherSchool { areaId = schoolInfo?.areaId, schoolId = schoolInfo.id, status = "join", name = schoolInfo.name, picture = schoolInfo.picture, time = nowTime });
                 }
-                if (teacher.size < 2) { 
-                    teacher.size=2;
+                if (teacher.size < 2)
+                {
+                    teacher.size = 2;
                 }
                 await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, teacher.id, new PartitionKey($"Base"));
             }
@@ -128,10 +135,10 @@ namespace TEAMModelOS.Controllers.Client
                 if (ex.Status == 404)
                 {
                     //如果沒有,則初始化Teacher基本資料到Cosmos
-                   teacher = new Teacher
-                   {
-                       createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
-                       id = id,
+                    teacher = new Teacher
+                    {
+                        createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
+                        id = id,
                         pk = "Base",
                         code = "Base",
                         name = name?.ToString(),
@@ -139,7 +146,7 @@ namespace TEAMModelOS.Controllers.Client
                         //创建账号并第一次登录IES5则默认赠送1G
                         defaultSchool = null,
                         size = 2,
-                        schools = new List<Teacher.TeacherSchool>() { new Teacher.TeacherSchool { areaId=schoolInfo?.areaId,schoolId=schoolInfo.id,status="join",name=schoolInfo.name,picture=schoolInfo.picture,time= nowTime } } 
+                        schools = new List<Teacher.TeacherSchool>() { new Teacher.TeacherSchool { areaId = schoolInfo?.areaId, schoolId = schoolInfo.id, status = "join", name = schoolInfo.name, picture = schoolInfo.picture, time = nowTime } }
                     };
                     var container = _azureStorage.GetBlobContainerClient(id);
                     await container.CreateIfNotExistsAsync(PublicAccessType.None); //嘗試創建Teacher私有容器,如存在則不做任何事,保障容器一定存在
@@ -150,7 +157,7 @@ namespace TEAMModelOS.Controllers.Client
             Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(teacher.id, new PartitionKey($"Teacher-{schoolInfo.id}"));
             if (response.Status != 200)
             {
-                  schoolTeacher = new SchoolTeacher
+                schoolTeacher = new SchoolTeacher
                 {
                     id = teacher.id,
                     name = teacher.name,
@@ -199,7 +206,7 @@ namespace TEAMModelOS.Controllers.Client
             var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
             var location = _option.Location;
             var code = await _notificationService.SendNotification(clientID, clientSecret, location, url, notification);
-            return Ok(new { schoolTeacher.roles, schoolTeacher.status,   school =$"{school}",   schoolInfo.name,   schoolInfo.picture });
+            return Ok(new { schoolTeacher.roles, schoolTeacher.status, school = $"{school}", schoolInfo.name, schoolInfo.picture });
         }
 
         //[Authorize(Roles = "HiTA")]
@@ -217,7 +224,7 @@ namespace TEAMModelOS.Controllers.Client
                 if (!jwt.Payload.Iss.Equals("account.teammodel", StringComparison.OrdinalIgnoreCase)) return BadRequest();
                 var id = jwt.Payload.Sub;
 
-                
+
                 var clientc = _azureCosmos.GetCosmosClient();
                 var clientr = _azureRedis.GetRedisClient(8);
                 var response = await clientc.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemStreamAsync(id, new PartitionKey("Base"));
@@ -269,7 +276,7 @@ namespace TEAMModelOS.Controllers.Client
                                     }
                                 }
                             }
-                           
+
                             //學校資料生成
                             dynamic schoolExtobj = new ExpandoObject();
                             var schoolJson = await clientc.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{obj.GetProperty("schoolId")}", new PartitionKey("Base"));
@@ -294,7 +301,7 @@ namespace TEAMModelOS.Controllers.Client
                     }
                     //預設學校
                     string defaultschool = null;
-                    if(jsonsc.RootElement.TryGetProperty("defaultSchool", out JsonElement defaultSchoolJson) && !defaultSchoolJson.ValueKind.Equals(JsonValueKind.Null))
+                    if (jsonsc.RootElement.TryGetProperty("defaultSchool", out JsonElement defaultSchoolJson) && !defaultSchoolJson.ValueKind.Equals(JsonValueKind.Null))
                     {
                         defaultschool = defaultSchoolJson.GetString();
                     }
@@ -350,7 +357,7 @@ namespace TEAMModelOS.Controllers.Client
                     size.used = teacherUsedBlob.size;
                     foreach (KeyValuePair<string, double?> blobCatalog in teacherUsedBlob.catalog)
                     {
-                        if(blobCatalog.Key.Equals("records"))
+                        if (blobCatalog.Key.Equals("records"))
                         {
                             size.records = blobCatalog.Value;
                         }
@@ -359,7 +366,7 @@ namespace TEAMModelOS.Controllers.Client
                             size.resource += blobCatalog.Value;
                         }
                     }
-                    
+
 
                     //資源數
                     int resCount = 0; //教材數
@@ -392,7 +399,7 @@ namespace TEAMModelOS.Controllers.Client
 
 
                     List<BlobCount> blogCountList = await BloblogCount(clientc, "private", id, "", "");
-                    foreach(BlobCount blobCountRow in blogCountList)
+                    foreach (BlobCount blobCountRow in blogCountList)
                     {
                         switch (blobCountRow.type)
                         {

+ 81 - 67
TEAMModelOS/Controllers/Client/HiTeachController.cs

@@ -36,7 +36,7 @@ namespace TEAMModelOS.Controllers.Client
     //[Authorize(Roles = "HiTeach")]
     [Route("hiteach")]
     [ApiController]
-    
+
     public class HiTeachController : ControllerBase
     {
         private readonly AzureStorageFactory _azureStorage;
@@ -77,7 +77,8 @@ namespace TEAMModelOS.Controllers.Client
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("update-lesson-record")]
-        public async Task<IActionResult> UpdateLessonRecord(JsonElement request) {
+        public async Task<IActionResult> UpdateLessonRecord(JsonElement request)
+        {
             var client = _azureCosmos.GetCosmosClient();
             if (!request.TryGetProperty("lesson_id", out JsonElement _lessonId)) return BadRequest();
             if (!request.TryGetProperty("tmdid", out JsonElement _tmdid)) return BadRequest();
@@ -85,34 +86,38 @@ namespace TEAMModelOS.Controllers.Client
             request.TryGetProperty("school", out JsonElement _school);
             if (!request.TryGetProperty("scope", out JsonElement _scope)) return BadRequest();
             request.TryGetProperty("grant_types", out JsonElement _grant_types);
-            string tbname ;
-            string code ;
+            string tbname;
+            string code;
 
             if (_scope.GetString().Equals("school") && !string.IsNullOrWhiteSpace(_school.GetString()))
-            {               
+            {
                 code = $"LessonRecord-{_school}";
                 tbname = "School";
             }
             else if ($"{_scope}".Equals("private"))
             {
-               
+
                 code = $"LessonRecord";
                 tbname = "Teacher";
             }
-            else {
+            else
+            {
                 return BadRequest();
             }
             try
             {
                 LessonRecord lessonRecord = await client.GetContainer(Constant.TEAMModelOS, tbname).ReadItemAsync<LessonRecord>($"{_lessonId}", new PartitionKey(code));
-                List<LessonUpdate> updates= new List<LessonUpdate>() { new LessonUpdate { grant_type= "up-base" } };
-                if (_grant_types.ValueKind.Equals(JsonValueKind.Array)) {
+                List<LessonUpdate> updates = new List<LessonUpdate>() { new LessonUpdate { grant_type = "up-base" } };
+                if (_grant_types.ValueKind.Equals(JsonValueKind.Array))
+                {
                     updates = _grant_types.ToObject<List<LessonUpdate>>();
-                    if (!updates.Select(x => x.grant_type).Contains("up-base")) {
+                    if (!updates.Select(x => x.grant_type).Contains("up-base"))
+                    {
                         updates.Add(new LessonUpdate { grant_type = "up-base" });
                     }
                 }
-                if (!string.IsNullOrWhiteSpace($"{name}")) {
+                if (!string.IsNullOrWhiteSpace($"{name}"))
+                {
                     lessonRecord.name = $"{name}";
                     await client.GetContainer(Constant.TEAMModelOS, tbname).ReplaceItemAsync<LessonRecord>(lessonRecord, $"{_lessonId}", new PartitionKey(code));
                 }
@@ -125,7 +130,8 @@ namespace TEAMModelOS.Controllers.Client
                 await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageChange);
                 return Ok(new { status = 200 });
             }
-            catch (CosmosException ex) when (ex.Status==404 ) {
+            catch (CosmosException ex) when (ex.Status == 404)
+            {
                 return BadRequest("课堂记录不存在");
             }
             catch (Exception ex)
@@ -133,21 +139,21 @@ namespace TEAMModelOS.Controllers.Client
                 return BadRequest();
             }
         }
-        
+
         /// <summary>
         /// 创建课堂开课记录
         /// </summary>
         /// <param name="request"></param>
         /// <returns></returns>
         [ProducesDefaultResponseType]
-       // [AuthToken(Roles = "teacher,admin")]
+        // [AuthToken(Roles = "teacher,admin")]
         [HttpPost("create-lesson-record")]
         public async Task<IActionResult> CreateLessonRecord(JsonElement request)
         {
             if (!request.TryGetProperty("lesson", out JsonElement _lesson)) return BadRequest();
             var client = _azureCosmos.GetCosmosClient();
             LessonRecord lessonRecord = _lesson.ToObject<LessonRecord>();
-            if (!string.IsNullOrEmpty(lessonRecord.scope) && !string.IsNullOrEmpty(lessonRecord.tmdid)&& !string.IsNullOrEmpty(lessonRecord.id))
+            if (!string.IsNullOrEmpty(lessonRecord.scope) && !string.IsNullOrEmpty(lessonRecord.tmdid) && !string.IsNullOrEmpty(lessonRecord.id))
             {
                 string tbname = null;
                 if (lessonRecord.scope.Equals("school") && !string.IsNullOrEmpty(lessonRecord.school))
@@ -160,27 +166,33 @@ namespace TEAMModelOS.Controllers.Client
                     lessonRecord.code = $"LessonRecord";
                     tbname = "Teacher";
                 }
-                if (tbname == null) {
-                    return BadRequest("参数异常:scope应为school或private,scope=school  ,school字段不能为空"); 
+                if (tbname == null)
+                {
+                    return BadRequest("参数异常:scope应为school或private,scope=school  ,school字段不能为空");
                 }
-                if (lessonRecord.startTime == 0) {
-                    lessonRecord.startTime=DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                if (lessonRecord.startTime == 0)
+                {
+                    lessonRecord.startTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                 }
                 lessonRecord.pk = "LessonRecord";
                 //处理课堂选用的名单
-                try {
+                try
+                {
                     await client.GetContainer(Constant.TEAMModelOS, tbname).CreateItemAsync(lessonRecord, new PartitionKey(lessonRecord.code));
                     var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
                     var messageChange = new ServiceBusMessage(lessonRecord.ToJsonString());
                     messageChange.ApplicationProperties.Add("name", "LessonRecordEvent");
                     await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageChange);
                     return Ok(new { status = 200 });
-                } catch (Exception ex) {
+                }
+                catch (Exception ex)
+                {
                     await _dingDing.SendBotMsg($"IES5,{_option.Location}, hiteach/create-lesson-record:()\n{ex.Message}{ex.StackTrace}{request.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
                     return BadRequest();
                 }
             }
-            else {
+            else
+            {
                 return BadRequest();
             }
         }
@@ -193,7 +205,7 @@ namespace TEAMModelOS.Controllers.Client
             try
             {
                 string id_token = HttpContext.GetXAuth("IdToken");
-                if(string.IsNullOrEmpty(id_token)) return BadRequest();
+                if (string.IsNullOrEmpty(id_token)) return BadRequest();
                 var jwt = new JwtSecurityToken(id_token);
                 if (!jwt.Payload.Iss.Equals("account.teammodel", StringComparison.OrdinalIgnoreCase)) return BadRequest();
                 var id = jwt.Payload.Sub;
@@ -213,7 +225,7 @@ namespace TEAMModelOS.Controllers.Client
                         foreach (var obj in value.EnumerateArray())
                         {
                             string statusNow = obj.GetProperty("status").ToString();
-                            if(statusNow.Equals("join")) //成為老師的才放入
+                            if (statusNow.Equals("join")) //成為老師的才放入
                             {
                                 dynamic schoolExtobj = new ExpandoObject();
                                 var schoolJson = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{obj.GetProperty("schoolId")}", new PartitionKey("Base"));
@@ -265,7 +277,7 @@ namespace TEAMModelOS.Controllers.Client
                             courseExtobj.name = Convert.ToString(obj.GetProperty("name"));
                             courseExtobj.scope = Convert.ToString(obj.GetProperty("scope"));
                             List<object> classes = new List<object>();
-                            if(obj.TryGetProperty("schedule", out JsonElement schedule))
+                            if (obj.TryGetProperty("schedule", out JsonElement schedule))
                             {
                                 foreach (var scheduleobj in schedule.EnumerateArray())
                                 {
@@ -401,21 +413,21 @@ namespace TEAMModelOS.Controllers.Client
             }
             catch (Exception ex)
             {
-               // await _dingDing.SendBotMsg($"CoreAPI2,{_option.Location},hiteach/GetTeacherInfo()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
+                // await _dingDing.SendBotMsg($"CoreAPI2,{_option.Location},hiteach/GetTeacherInfo()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
                 return BadRequest();
             }
         }
 
-                
+
         [ProducesDefaultResponseType]
-        [HttpPost("get-school-info")]       
+        [HttpPost("get-school-info")]
         public async Task<IActionResult> GetSchoolInfo(JsonElement requert)
         {
             try
             {
                 string id_token = HttpContext.GetXAuth("IdToken");
                 if (string.IsNullOrEmpty(id_token)) return BadRequest();
-                if (!requert.TryGetProperty("school_code", out JsonElement school_code)) return BadRequest();       
+                if (!requert.TryGetProperty("school_code", out JsonElement school_code)) return BadRequest();
                 var jwt = new JwtSecurityToken(id_token);
                 if (!jwt.Payload.Iss.Equals("account.teammodel", StringComparison.Ordinal)) return BadRequest();
                 var id = jwt.Payload.Sub;
@@ -496,7 +508,7 @@ namespace TEAMModelOS.Controllers.Client
                         {
                             //班級
                             string classIdNow = string.Empty;
-                            if(obj.TryGetProperty("scheduleClassId", out JsonElement scheduleClassId))
+                            if (obj.TryGetProperty("scheduleClassId", out JsonElement scheduleClassId))
                             {
                                 classIdNow = Convert.ToString(scheduleClassId);
                             }
@@ -506,7 +518,7 @@ namespace TEAMModelOS.Controllers.Client
                             classExtobj.name = null;
                             classExtobj.scope = null;
                             classExtobj.gradeId = null;
-                            classExtobj.year =0;
+                            classExtobj.year = 0;
                             classExtobj.teacher = null;
                             classExtobj.stuListId = null;
                             classExtobj.stuCnt = 0;
@@ -584,7 +596,7 @@ namespace TEAMModelOS.Controllers.Client
                                 courseExtobj.classes = new List<object>();
                                 courseExtobj.subject = obj.GetProperty("subject");
                                 //classExtobj.teacher = scheduleTeacherInfo;
-                                if(!string.IsNullOrWhiteSpace(classExtobj.id))
+                                if (!string.IsNullOrWhiteSpace(classExtobj.id))
                                 {
                                     courseExtobj.classes.Add(classExtobj);
                                 }
@@ -607,7 +619,8 @@ namespace TEAMModelOS.Controllers.Client
                 string classSqlString = "";
                 if (classIds.Count > 0 || groupIds.Count > 0)
                 {
-                    if(classIds.Count > 0) {
+                    if (classIds.Count > 0)
+                    {
                         foreach (string classId in classIds)
                         {
                             if (!string.IsNullOrWhiteSpace(classSqlString))
@@ -713,7 +726,7 @@ namespace TEAMModelOS.Controllers.Client
                 var (blob_uri_read, blob_sas_read) = _azureStorage.GetBlobContainerSAS(school_code_blob, BlobContainerSasPermissions.Read); //讀
                 var (blob_uri_write, blob_sas_write) = _azureStorage.GetBlobContainerSAS(school_code_blob, BlobContainerSasPermissions.Write); //寫
 
-                return Ok(new { blob_uri, blob_sas, blob_sas_read, blob_sas_write,  periods, grades, subjects, courses, examTypes, exams });
+                return Ok(new { blob_uri, blob_sas, blob_sas_read, blob_sas_write, periods, grades, subjects, courses, examTypes, exams });
             }
             catch (Exception ex)
             {
@@ -740,7 +753,7 @@ namespace TEAMModelOS.Controllers.Client
                 if (!request.TryGetProperty("grant_type", out JsonElement grant_type)) return BadRequest();
                 string partitionid = string.Empty;
                 string container = string.Empty;
-                if (grant_type.ToString() .Equals("school"))
+                if (grant_type.ToString().Equals("school"))
                 {
                     if (!request.TryGetProperty("school_code", out JsonElement school_code_json))
                     {
@@ -762,26 +775,26 @@ namespace TEAMModelOS.Controllers.Client
                 string queryWhere = " WHERE 1=1 ";
                 string queryOption = string.Empty;
                 //學段
-                if (request.TryGetProperty("periodId", out JsonElement periodId) && container .Equals("School") )
+                if (request.TryGetProperty("periodId", out JsonElement periodId) && container.Equals("School"))
                 {
                     queryWhere += $" AND c.periodId = '{periodId}'";
                 }
                 //年級
-                if (request.TryGetProperty("gradeId", out JsonElement gradeIds) && gradeIds.GetArrayLength() > 0 && container .Equals("School"))
+                if (request.TryGetProperty("gradeId", out JsonElement gradeIds) && gradeIds.GetArrayLength() > 0 && container.Equals("School"))
                 {
                     string queryOptionForGrade = string.Empty;
                     for (int i = 0; i < gradeIds.GetArrayLength(); i++)
                     {
-                        if(!string.IsNullOrWhiteSpace(queryOptionForGrade))
+                        if (!string.IsNullOrWhiteSpace(queryOptionForGrade))
                         {
                             queryOptionForGrade += " OR ";
                         }
                         queryOptionForGrade += $" ARRAY_CONTAINS(c.gradeIds, '{gradeIds[i]}', true)";
                     }
-                    queryWhere += $" AND ( {queryOptionForGrade} )"; 
+                    queryWhere += $" AND ( {queryOptionForGrade} )";
                 }
                 //科目ID
-                if (request.TryGetProperty("subjectId", out JsonElement subjectId) && container .Equals("School"))
+                if (request.TryGetProperty("subjectId", out JsonElement subjectId) && container.Equals("School"))
                 {
                     queryWhere += $" AND c.subjectId = '{subjectId}'";
                 }
@@ -800,7 +813,7 @@ namespace TEAMModelOS.Controllers.Client
                 int page = 0; //目前第幾頁
                 if (request.TryGetProperty("page", out JsonElement page_json))
                 {
-                    if(page_json.GetInt32() > 0)
+                    if (page_json.GetInt32() > 0)
                     {
                         page = page_json.GetInt32() - 1;
                     }
@@ -808,13 +821,13 @@ namespace TEAMModelOS.Controllers.Client
                 string order = "createTime"; //排序項目
                 if (request.TryGetProperty("order", out JsonElement order_json))
                 {
-                    if(order_json.ToString().Equals("useCount"))
+                    if (order_json.ToString().Equals("useCount"))
                     {
                         order = order_json.ToString();
                     }
-                }    
+                }
                 queryOption += $" Order By c." + order + " DESC ";
-                if(perpage > 0 )
+                if (perpage > 0)
                 {
                     queryOption += $" OFFSET {perpage * page} LIMIT {perpage}";
                 }
@@ -894,12 +907,12 @@ namespace TEAMModelOS.Controllers.Client
                 string queryWhere = " WHERE 1=1 ";
                 string queryOption = string.Empty;
                 //學段
-                if (request.TryGetProperty("periodId", out JsonElement periodId) && container .Equals("School"))
+                if (request.TryGetProperty("periodId", out JsonElement periodId) && container.Equals("School"))
                 {
                     queryWhere += $" AND c.periodId = '{periodId}'";
                 }
                 //年級
-                if (request.TryGetProperty("gradeId", out JsonElement gradeIds) && gradeIds.GetArrayLength() > 0 && container .Equals("School"))
+                if (request.TryGetProperty("gradeId", out JsonElement gradeIds) && gradeIds.GetArrayLength() > 0 && container.Equals("School"))
                 {
                     string queryOptionForGrade = string.Empty;
                     for (int i = 0; i < gradeIds.GetArrayLength(); i++)
@@ -913,7 +926,7 @@ namespace TEAMModelOS.Controllers.Client
                     queryWhere += $" AND ( {queryOptionForGrade} )";
                 }
                 //科目ID
-                if (request.TryGetProperty("subjectId", out JsonElement subjectId) && container .Equals("school"))
+                if (request.TryGetProperty("subjectId", out JsonElement subjectId) && container.Equals("school"))
                 {
                     queryWhere += $" AND c.subjectId = '{subjectId}'";
                 }
@@ -952,7 +965,7 @@ namespace TEAMModelOS.Controllers.Client
                 string order = "createTime"; //排序項目
                 if (request.TryGetProperty("order", out JsonElement order_json))
                 {
-                    if (order_json.ToString() .Equals("useCount"))
+                    if (order_json.ToString().Equals("useCount"))
                     {
                         order = order_json.ToString();
                     }
@@ -1043,7 +1056,7 @@ namespace TEAMModelOS.Controllers.Client
 
             var client = _azureCosmos.GetCosmosClient();
             List<object> volumes = new List<object>();
-            List <Volume> volumeList = new List<Volume>();
+            List<Volume> volumeList = new List<Volume>();
             List<string> volumeIdList = new List<string>();
             await foreach (var itemv in client.GetContainer(Constant.TEAMModelOS, container).GetItemQueryStreamIterator(queryText: $"SELECT * from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Volume-{dataId}") }))
             {
@@ -1105,28 +1118,28 @@ namespace TEAMModelOS.Controllers.Client
             request.TryGetProperty("stulist_id", out JsonElement stulist_id);
             string classId = Convert.ToString(class_code);
             string stulist = Convert.ToString(stulist_id);
-            if(string.IsNullOrWhiteSpace(classId) && string.IsNullOrWhiteSpace(stulist)) return BadRequest();
+            if (string.IsNullOrWhiteSpace(classId) && string.IsNullOrWhiteSpace(stulist)) return BadRequest();
             request.TryGetProperty("school_code", out JsonElement school_code);
-            if (grant_type.GetString() .Equals("school") && string.IsNullOrWhiteSpace(Convert.ToString(school_code))) return BadRequest();
+            if (grant_type.GetString().Equals("school") && string.IsNullOrWhiteSpace(Convert.ToString(school_code))) return BadRequest();
 
             var client = _azureCosmos.GetCosmosClient();
             List<ClassStudents> students = new List<ClassStudents>();
             Dictionary<string, string> irsDic = new Dictionary<string, string>(); //key:學生ID或TMID value:irs號碼
-            string container = (grant_type.GetString() .Equals("school")) ? "School" : "Teacher";
+            string container = (grant_type.GetString().Equals("school")) ? "School" : "Teacher";
 
             List<string> listids = new List<string>();
-            if(!string.IsNullOrWhiteSpace(stulist))
+            if (!string.IsNullOrWhiteSpace(stulist))
             {
                 listids.Add(stulist);
             }
-            else if(!string.IsNullOrWhiteSpace(classId))
+            else if (!string.IsNullOrWhiteSpace(classId))
             {
                 listids.Add(classId);
             }
             (List<RMember> memberList, List<RGroupList> groupList) = await GroupListService.GetStutmdidListids(_coreAPIHttpService, client, _dingDing, listids, $"{school_code}");
-            if(memberList.IsNotEmpty())
+            if (memberList.IsNotEmpty())
             {
-                foreach(RMember member in memberList)
+                foreach (RMember member in memberList)
                 {
                     ClassStudents strdentRow = new ClassStudents();
                     strdentRow.nickname = member.nickname;
@@ -1270,14 +1283,14 @@ namespace TEAMModelOS.Controllers.Client
 
             //取得分組資訊
             List<ClassGroups> groups = new List<ClassGroups>();
-            foreach(ClassStudents studentInfo in students)
+            foreach (ClassStudents studentInfo in students)
             {
-                if(!string.IsNullOrWhiteSpace(studentInfo.groupId))
+                if (!string.IsNullOrWhiteSpace(studentInfo.groupId))
                 {
                     ClassGroups groupRow = groups.Where(g => g.id == studentInfo.groupId).FirstOrDefault();
-                    if(groupRow != null) //已有此group資訊 => 追加學生ID
+                    if (groupRow != null) //已有此group資訊 => 追加學生ID
                     {
-                        if(!groupRow.studentIds.Contains(studentInfo.id))
+                        if (!groupRow.studentIds.Contains(studentInfo.id))
                         {
                             groupRow.studentIds.Add(studentInfo.id);
                         }
@@ -1371,7 +1384,7 @@ namespace TEAMModelOS.Controllers.Client
                         }
                     }
                 }
-                if(string.IsNullOrWhiteSpace(dbExamInfo.id))
+                if (string.IsNullOrWhiteSpace(dbExamInfo.id))
                 {
                     dbExamInfo = ExamInfoFromReq;
                 }
@@ -1381,7 +1394,7 @@ namespace TEAMModelOS.Controllers.Client
                 //※規則  owner:"school" => 校園評測  "teacher" => 個人評測 
                 //※規則  scope:"school" => 校本班級  "private" => 個人班級 
                 //※規則  BLOB容器: scope:"school" => {學校ID}下   scope:"private" => {個人ID}下
-                string blobContainer = (!string.IsNullOrWhiteSpace(dbExamInfo.school) && dbExamInfo.scope .Equals("school")) ? dbExamInfo.school : id; //blob容器
+                string blobContainer = (!string.IsNullOrWhiteSpace(dbExamInfo.school) && dbExamInfo.scope.Equals("school")) ? dbExamInfo.school : id; //blob容器
                 //dbExamInfo.source = "1"; //評測來源固定為  1:課中評量(不應由API擅自變更)
 
                 //試卷List
@@ -1596,7 +1609,7 @@ namespace TEAMModelOS.Controllers.Client
                             examClassResultUpd.sum = examClassResultRow.sum;
                         }
                         //學生作答Blob位置[2021-7-13 不再對Blob做搬運 學生答案直接寫入DB]
-                        examClassResultUpd.studentAnswers = examClassResultRow.studentAnswersArray; 
+                        examClassResultUpd.studentAnswers = examClassResultRow.studentAnswersArray;
                         //學生作答答案 (從blob取得學生答案、放入ans欄位)
                         string targetScope = dbExamInfo.scope; //評測對象 school:校本班級  private:私人課程
                         var targetBlobContainer = _azureStorage.GetBlobContainerClient(id);
@@ -1609,7 +1622,7 @@ namespace TEAMModelOS.Controllers.Client
                         targetBlobContainer = _azureStorage.GetBlobContainerClient(blobCntr);
                         if (examClassResultRow.studentAnswersArray.Count > 0)
                         {
-                            foreach(List<string> studentAnswerBlobPath in examClassResultRow.studentAnswersArray)
+                            foreach (List<string> studentAnswerBlobPath in examClassResultRow.studentAnswersArray)
                             {
                                 string stuAnswerBlobPath = studentAnswerBlobPath.FirstOrDefault();
                                 if (stuAnswerBlobPath != null)
@@ -1636,16 +1649,17 @@ namespace TEAMModelOS.Controllers.Client
                         var examClassResultResponse = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Common").UpsertItemAsync(examClassResultUpd, new PartitionKey(examClassResultUpd.code));
                     }
                 }
-                
+
                 //UPDATE Exam
                 await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Common").UpsertItemAsync(dbExamInfo, new PartitionKey(dbExamInfo.code));
 
                 //錯誤處理
-                if(paperDataCopyErrFlg)  //試卷Blob拷貝失敗
+                if (paperDataCopyErrFlg)  //試卷Blob拷貝失敗
                 {
                     error = 1001;
                     message = "Paper blob copy failure.";
-                } else if(studentAnswerCopyErrFlg)  //學生作答資料上傳blob失敗
+                }
+                else if (studentAnswerCopyErrFlg)  //學生作答資料上傳blob失敗
                 {
                     error = 1002;
                     message = "Student answers blob upload failure.";

+ 73 - 32
TEAMModelOS/Controllers/Common/ExamController.cs

@@ -449,19 +449,19 @@ namespace TEAMModelOS.Controllers
                     string ss = string.Join(" or ", strs);
                     stringBuilder.Append($" and {ss}");
                 };
-                if (requert.TryGetProperty("period", out JsonElement period))
+                if (requert.TryGetProperty("period", out JsonElement period) && !string.IsNullOrWhiteSpace($"{period}"))
                 {
                     stringBuilder.Append($" and c.period.id = '{period}' ");
                 }
-                if (requert.TryGetProperty("name", out JsonElement name))
+                if (requert.TryGetProperty("name", out JsonElement name) && !string.IsNullOrWhiteSpace($"{name}"))
                 {
                     stringBuilder.Append($" and Contains( c.name , '{name}') =  true ");
                 }
-                if (requert.TryGetProperty("progress", out JsonElement progress))
+                if (requert.TryGetProperty("progress", out JsonElement progress) && !string.IsNullOrWhiteSpace($"{progress}"))
                 {
                     stringBuilder.Append($" and c.progress = '{progress}' ");
                 }
-                if (requert.TryGetProperty("source", out JsonElement source))
+                if (requert.TryGetProperty("source", out JsonElement source) && !string.IsNullOrWhiteSpace($"{source}"))
                 {
                     stringBuilder.Append($" and c.source = '{source}' ");
                 }
@@ -587,37 +587,61 @@ namespace TEAMModelOS.Controllers
                     };
                     await table.Save<SchoolYear>(sy);
                 }
-                var query = $"select c.id,c.name,c.code,c.period,c.startTime,c.endTime,c.stuCount,c.type,c.progress,c.examType,c.createTime,c.source, c.subjects, c.grades,c.owner, c.scope,c.classes,c.sRate,c.lostStu,c.sStatus,c.qamode,c.school from c " +
-                    $"where (c.status<>404 or IS_DEFINED(c.status) = false) and c.scope = 'school' and c.school = '{code}' and c.pk = 'Exam'";
-                if (requert.TryGetProperty("classIds", out JsonElement classIds))
+                string sub = string.Empty;
+                string subject = string.Empty;
+                if (requert.TryGetProperty("subjectId", out JsonElement subjectId) && !string.IsNullOrWhiteSpace($"{subjectId}"))
                 {
-                    List<string> ids = classIds.ToObject<List<string>>();
-                    HashSet<string> strs = new HashSet<string>();
-                    if (ids.Count > 1)
-                    {
-                        foreach (string id in ids)
-                        {
-                            strs.Add($"array_contains(c.classes,'{id}')");
-                        }
-                    }
-                    else
-                    {
-                        string ssr = ids.Count > 0 ? ids[0] : "";
-                        strs.Add($"array_contains(c.classes,'{ssr}')");
-                    }
-                    string ss = string.Join(" or ", strs);
-                    query = $"select c.id,c.name,c.code,c.period,c.startTime,c.endTime,c.stuCount,c.type,c.progress,c.examType,c.createTime, c.source,c.subjects, c.grades,c.owner, c.scope,c.classes,c.sRate,c.lostStu,c.sStatus,c.qamode,c.school from c " +
-                        $"where ({ss}) and (c.status<>404 or IS_DEFINED(c.status) = false) and c.scope = 'school' and c.school = '{code}' and c.pk = 'Exam'";
-                };
-
-                string continuationToken = string.Empty;
+                    sub = $" join A0 in c.subjects ";
+                    subject = $" and A0.id = '{subjectId}'";
+                }
+                string grade = string.Empty;
+                string grades = string.Empty;
+                if (requert.TryGetProperty("grades", out JsonElement gs) && !string.IsNullOrWhiteSpace($"{gs}"))
+                {
+                    grade = $" join A1 in c.grades ";
+                    grades = $" and A1.id = '{gs}'";
+                }
+                StringBuilder stringBuilder = new StringBuilder($"select c.id,c.name,c.code,c.period,c.startTime,c.endTime,c.stuCount,c.type,c.progress,c.examType,c.createTime,c.source, c.subjects, c.grades,c.owner, c.scope,c.classes,c.sRate,c.lostStu,c.sStatus,c.qamode,c.school from c {sub} {grade}" +
+                    $"where (c.status<>404 or IS_DEFINED(c.status) = false) and c.scope = 'school' and c.school = '{code}' and c.pk = 'Exam' {subject} {grades}");
+                if (requert.TryGetProperty("period", out JsonElement period) && !string.IsNullOrWhiteSpace($"{period}"))
+                {
+                    stringBuilder.Append($" and c.period.id = '{period}' ");
+                }
+                if (requert.TryGetProperty("owner", out JsonElement owner) && !string.IsNullOrWhiteSpace($"{owner}"))
+                {
+                    stringBuilder.Append($" and c.owner= '{owner}' ");
+                }
+                
+                if (requert.TryGetProperty("year", out JsonElement yy) && !string.IsNullOrWhiteSpace($"{yy}"))
+                {
+                    int end = yy.GetInt32() + 1;
+                    long stime = DateTimeOffset.Parse($"{yy.GetInt32()}-1-1").ToUnixTimeMilliseconds();
+                    long etime = DateTimeOffset.Parse($"{end}-1-1").ToUnixTimeMilliseconds();
+                    stringBuilder.Append($" and (c.startTime >= {stime} && c.startTime < {etime})");
+                }
+                if (requert.TryGetProperty("name", out JsonElement name) && !string.IsNullOrWhiteSpace($"{name}"))
+                {
+                    stringBuilder.Append($" and Contains( c.name , '{name}') =  true ");
+                }
+                if (requert.TryGetProperty("examType", out JsonElement examType) && !string.IsNullOrWhiteSpace($"{examType}"))
+                {
+                    stringBuilder.Append($" and c.examType.id = '{examType}' ");
+                }
+                if (requert.TryGetProperty("progress", out JsonElement progress) && !string.IsNullOrWhiteSpace($"{progress}"))
+                {
+                    stringBuilder.Append($" and c.progress = '{progress}' ");
+                }
+                if (requert.TryGetProperty("source", out JsonElement source) && !string.IsNullOrWhiteSpace($"{source}"))
+                {
+                    stringBuilder.Append($" and c.source = '{source}' ");
+                }
+                stringBuilder.Append("order by c.createTime desc");
                 string token = default;
                 //是否需要进行分页查询,默认不分页
                 bool iscontinuation = false;
                 if (requert.TryGetProperty("token", out JsonElement token_1))
                 {
                     token = token_1.GetString();
-                    iscontinuation = true;
                 };
                 //默认不指定返回大小
                 int? topcout = null;
@@ -628,9 +652,12 @@ namespace TEAMModelOS.Controllers
                         topcout = data;
                     }
                 }
-
+                if (topcout != null && topcout.Value > 0)
+                {
+                    iscontinuation = true;
+                }
                 List<ExamInfo> examInfo = new List<ExamInfo>();
-                await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(queryText: query, continuationToken: token, requestOptions: new QueryRequestOptions() { MaxItemCount = topcout }))
+                await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(queryText: stringBuilder.ToString(), continuationToken: token, requestOptions: new QueryRequestOptions() { MaxItemCount = topcout }))
                 {
 
                     using var json = await JsonDocument.ParseAsync(item.ContentStream);
@@ -644,12 +671,26 @@ namespace TEAMModelOS.Controllers
                     }
                     if (iscontinuation)
                     {
-                        continuationToken = item.GetContinuationToken();
+                        token = item.GetContinuationToken();
                         break;
                     }
 
                 }
-                return Ok(new { examInfo, token = continuationToken, year });
+                List<ExamInfo> exams = new List<ExamInfo>();
+                await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(queryText: stringBuilder.ToString()))
+                {
+
+                    using var json = await JsonDocument.ParseAsync(item.ContentStream);
+                    if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                    {
+                        foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                        {
+                            exams.Add(obj.ToObject<ExamInfo>());
+                        }
+                    }                   
+                }
+                var groups = exams.Where(e => !string.IsNullOrEmpty(e.examType.id)).GroupBy(x =>x.examType).Select(y => new { key = y.Key.name,count = y.ToList().Count}).ToList();
+                return Ok(new { examInfo, token = token, year,count = exams.Count, groups });
             }
             catch (Exception e)
             {

+ 9 - 7
TEAMModelOS/Controllers/Common/StudyController.cs

@@ -136,7 +136,7 @@ namespace TEAMModelOS.Controllers.Common
         [HttpPost("sign-in")]
         public async Task<IActionResult> Sign(JsonElement request)
         {
-          
+
             try
             {
                 if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
@@ -161,7 +161,7 @@ namespace TEAMModelOS.Controllers.Common
                         {
                             tmdid = coreUser.id;
                         }
-                       
+
                     }
                 }
                 if (string.IsNullOrWhiteSpace(tmdid))
@@ -226,7 +226,7 @@ namespace TEAMModelOS.Controllers.Common
             {
                 await _dingDing.SendBotMsg($"OS,{_option.Location},study/sign-in()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
                 return BadRequest();
-            }          
+            }
 
         }
 
@@ -351,14 +351,16 @@ namespace TEAMModelOS.Controllers.Common
                     {
                         await _dingDing.SendBotMsg($"OS,{_option.Location},study/delete()ex\n{ex.Message},\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
                     }
-                    if (flag) {
-                       
+                    if (flag)
+                    {
+
                         study.status = 404;
                         if (!string.IsNullOrEmpty(study.examId))
                         {
                             Azure.Response response = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(study.examId, new PartitionKey($"ExamLite-{code}"));
-                            if (response.Status == 200) {
-                                ExamLite data= JsonDocument.Parse(response.Content).RootElement.Deserialize<ExamLite>();
+                            if (response.Status == 200)
+                            {
+                                ExamLite data = JsonDocument.Parse(response.Content).RootElement.Deserialize<ExamLite>();
                                 data.status = 404;
                                 await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(data, data.id, new PartitionKey($"ExamLite-{code}"));
                             }

+ 109 - 76
TEAMModelOS/Controllers/School/SchoolController.cs

@@ -13,7 +13,7 @@ using Azure.Cosmos;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.Options;
 using System.IO;
-using System.Dynamic; 
+using System.Dynamic;
 using System.Net.Http;
 using System.Net;
 using Newtonsoft.Json;
@@ -32,7 +32,7 @@ namespace TEAMModelOS.Controllers
 {
     [ProducesResponseType(StatusCodes.Status200OK)]
     [ProducesResponseType(StatusCodes.Status400BadRequest)]
-    
+
     [Route("school/init")]
     [ApiController]
     public class SchoolController : ControllerBase
@@ -86,10 +86,11 @@ namespace TEAMModelOS.Controllers
                 switch (true)
                 {
                     //修改互评开关
-                    case bool when $"{_opt}".Equals("modify-hpappraise", StringComparison.OrdinalIgnoreCase) :
-                        int hpappraise =-1;
-                        if (request.TryGetProperty("hpappraise", out JsonElement _hpappraise)) {
-                            int.TryParse($"{_hpappraise}",out    hpappraise);
+                    case bool when $"{_opt}".Equals("modify-hpappraise", StringComparison.OrdinalIgnoreCase):
+                        int hpappraise = -1;
+                        if (request.TryGetProperty("hpappraise", out JsonElement _hpappraise))
+                        {
+                            int.TryParse($"{_hpappraise}", out hpappraise);
                         }
                         if (hpappraise != -1)
                         {
@@ -98,10 +99,11 @@ namespace TEAMModelOS.Controllers
                             await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<School>(schoolData, school, new PartitionKey("Base"));
                             return Ok(new { status = 200 });
                         }
-                        else {
+                        else
+                        {
                             return Ok(new { error = 1, msg = "参数异常!" });
                         }
-                        
+
                     default:
                         return Ok(new { error = 1, msg = "参数异常!" });
 
@@ -110,7 +112,7 @@ namespace TEAMModelOS.Controllers
             catch (Exception ex)
             {
                 await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/init/set-teacher-info()\n{ex.Message}{ex.StackTrace}{request.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
-                return Ok(new { error=1,msg="参数异常!"});
+                return Ok(new { error = 1, msg = "参数异常!" });
 
             }
         }
@@ -126,7 +128,7 @@ namespace TEAMModelOS.Controllers
 
         public async Task<IActionResult> Upsert(TEAMModelOS.SDK.Models.School school)
         {
-            var (_, _, _,_school) = HttpContext.GetAuthTokenInfo();
+            var (_, _, _, _school) = HttpContext.GetAuthTokenInfo();
             try
             {
                 TEAMModelOS.SDK.Models.School schoolInfo = new TEAMModelOS.SDK.Models.School();
@@ -137,12 +139,15 @@ namespace TEAMModelOS.Controllers
                 {
                     string sql = $"SELECT distinct value(c) FROM c join A1 in c.schools where A1.schoolId='{school.id}'";
                     List<Teacher> teachers = new List<Teacher>();
-                    await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<Teacher>(sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base") })) {
+                    await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<Teacher>(sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base") }))
+                    {
                         teachers.Add(item);
                     }
-                    foreach (var item in teachers) {
+                    foreach (var item in teachers)
+                    {
                         TeacherSchool teacherSchool = item.schools.Find(x => x.schoolId.Equals(school.id));
-                        if (teacherSchool != null) {
+                        if (teacherSchool != null)
+                        {
                             teacherSchool.name = school.name;
                             teacherSchool.picture = school.picture;
                             teacherSchool.areaId = school.areaId;
@@ -427,7 +432,7 @@ namespace TEAMModelOS.Controllers
                     {
                         double val = score.Score;
                         string key = score.Element.ToString();
-                        spaceinfo[key]=val;
+                        spaceinfo[key] = val;
                     }
                 }
 
@@ -498,11 +503,11 @@ namespace TEAMModelOS.Controllers
                             //學校空間特別處理:取得起始結束時間
                             if (serviceProductRow.code.Equals("IPALJ6NY"))
                             {
-                                if(serviceProductRow.startDate < UTCNow && UTCNow < serviceProductRow.endDate)
+                                if (serviceProductRow.startDate < UTCNow && UTCNow < serviceProductRow.endDate)
                                 {
                                     spaceinfo["startDate"] = serviceProductRow.startDate;
-                                    spaceinfo["endDate"]  = serviceProductRow.endDate;
-                                   // spaceinfo.startDate = serviceProductRow.startDate;
+                                    spaceinfo["endDate"] = serviceProductRow.endDate;
+                                    // spaceinfo.startDate = serviceProductRow.startDate;
                                     //spaceinfo.endDate = serviceProductRow.endDate;
                                 }
                             }
@@ -511,14 +516,14 @@ namespace TEAMModelOS.Controllers
                 }
                 ////(服務)產品購買履歷整形
                 IEnumerable<SchoolProductService> serviceProductOrder = serviceProduct.OrderBy(sp => sp.startDate);
-                foreach(SchoolProductService serviceProductRow in serviceProduct)
+                foreach (SchoolProductService serviceProductRow in serviceProduct)
                 {
                     //取得此產品現在可用數
                     SchoolProductSumData serviceSumNow = serviceSum.Where(ss => ss.prodCode.Equals(serviceProductRow.prodCode)).FirstOrDefault();
                     int serviceAvaliableNow = (serviceSumNow != null) ? serviceSumNow.avaliable : 0;
                     //取得此產品購買履歷
                     SchoolProductOrder serviceOrderNow = serviceOrder.Where(so => so.prodCode == serviceProductRow.prodCode).FirstOrDefault();
-                    if(serviceOrderNow == null) //無此產品項
+                    if (serviceOrderNow == null) //無此產品項
                     {
                         SchoolProductOrder serviceOrderRow = new SchoolProductOrder();
                         serviceOrderRow.prodCode = serviceProductRow.prodCode;
@@ -798,7 +803,7 @@ namespace TEAMModelOS.Controllers
             List<deviceFromCoreService> result = new List<deviceFromCoreService>();
             try
             {
-                string url = _configuration.GetValue<string>("HaBookAuth:CoreService:deviceinfo"); 
+                string url = _configuration.GetValue<string>("HaBookAuth:CoreService:deviceinfo");
                 HttpClient client = new HttpClient();
                 string AccessToken = await getCoreAccessToken();
                 client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
@@ -1144,7 +1149,7 @@ namespace TEAMModelOS.Controllers
         /// [測試用]放入某學校的AClassOne動態學生ID 
         /// </summary>
         [ProducesDefaultResponseType]
-        [HttpPost("set-school-aclassone-dync")] 
+        [HttpPost("set-school-aclassone-dync")]
         public IActionResult SetSchoolAclassoneDync(JsonElement request)
         {
             if (!request.TryGetProperty("school_code", out JsonElement school_code)) return BadRequest();
@@ -1221,7 +1226,7 @@ namespace TEAMModelOS.Controllers
                                 //STEP3更新Redis.hbcn:AclassOne:dynamic ※註:只更新動態ID可用數,不更動動態ID列表,所以若可用數為0,當天被動態分配到的學生仍可使用至今日0時才會被清掉
                                 int dynamicAclassCount = totalInDB - studentIds.Count; //動態可使用數
                                 dyncNum = (int)GetSchoolDynamicAclassOneIDCount(school_code.GetString()); //動態ID已使用數
-                                var redisClient = _azureRedis.GetRedisClient(redisAclassoneDbNum);                        
+                                var redisClient = _azureRedis.GetRedisClient(redisAclassoneDbNum);
                                 string keys = school_code.GetString() + ":" + "AclassOne" + ":" + "dynamic";
                                 int updDynAclassCount = (dynamicAclassCount - dyncNum > 0) ? dynamicAclassCount - dyncNum : 0;
                                 redisClient.StringSet(keys, updDynAclassCount);
@@ -1264,7 +1269,7 @@ namespace TEAMModelOS.Controllers
             string action = "all"; //預設回收:固定及動態均回收  sta:回收固定 dync:回收動態
             if (request.TryGetProperty("mode", out JsonElement mode))
             {
-                if(mode.GetString().Equals("sta") || mode.GetString().Equals("dync"))
+                if (mode.GetString().Equals("sta") || mode.GetString().Equals("dync"))
                 {
                     action = mode.GetString();
                 }
@@ -1370,7 +1375,8 @@ namespace TEAMModelOS.Controllers
                     }
                     usedSpace = Convert.ToInt64(Math.Ceiling(usedSpace / bytes));
                 }
-                else {
+                else
+                {
                     //[學校空間]
                     var blobClient = _azureStorage.GetBlobContainerClient(school_code.ToString());
                     long? docSize = await blobClient.GetBlobsSize("doc");
@@ -1402,12 +1408,13 @@ namespace TEAMModelOS.Controllers
                     thumSize = thumSize != null ? thumSize : 0;
                     syllabusSize = syllabusSize != null ? syllabusSize : 0;
                     examSize = examSize != null ? examSize : 0;
-                    usedSpace = Convert.ToInt64(Math.Ceiling((double)((docSize + videoSize + imageSize + paperSize + itemSize + otherSize+ voteSize+audioSize+resSize+tempSize+thumSize+syllabusSize+examSize) / bytes)));
+                    usedSpace = Convert.ToInt64(Math.Ceiling((double)((docSize + videoSize + imageSize + paperSize + itemSize + otherSize + voteSize + audioSize + resSize + tempSize + thumSize + syllabusSize + examSize) / bytes)));
                 }
-                long  avaliable = this.baseSpaceSize; // (G) 目前學校申請空間總數
+                long avaliable = this.baseSpaceSize; // (G) 目前學校申請空間總數
                 long teacherSpace = 0; // 教師可設定的空間量(G)
                 School school = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(school_code, new PartitionKey("Base"));
-                if (school.size <= 0) {
+                if (school.size <= 0)
+                {
                     school.size = baseSpaceSize;
                 }
                 avaliable = school.size;
@@ -1433,8 +1440,8 @@ namespace TEAMModelOS.Controllers
                         int setSpaceTotal = 0;
 
                         // 教師List
-                         
-                        var ids = teachers.Select(x=>x.id);
+
+                        var ids = teachers.Select(x => x.id);
                         int notInSpaceTotal = 0;
                         string notinsql = $"select value(sum(c.size)) from c ";
                         if (ids.Any())
@@ -1447,7 +1454,7 @@ namespace TEAMModelOS.Controllers
                             notInSpaceTotal = item;
                             break;
                         }
-                        setSpaceTotal = notInSpaceTotal+ teachers.Select(x => x.size).Sum();
+                        setSpaceTotal = notInSpaceTotal + teachers.Select(x => x.size).Sum();
                         // 檢核總數是否超過
                         if (setSpaceTotal > teacherSpace)
                         {
@@ -1456,7 +1463,7 @@ namespace TEAMModelOS.Controllers
                             return Ok(new { status, err });
                         }
                         queryText = $"select * from c where c.id in ({string.Join(",", ids.Select(o => $"'{o}'"))})";
-                        
+
                         await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: queryText, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Teacher-{school_code}") }))
                         {
                             using var jsoncm = await JsonDocument.ParseAsync(item.ContentStream);
@@ -1502,11 +1509,11 @@ namespace TEAMModelOS.Controllers
                                     var response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemStreamAsync(teacher.id, new PartitionKey("Base"));
                                     if (response.Status == 200)
                                     {
-                                       // var json = await JsonDocument.ParseAsync(response.ContentStream);
+                                        // var json = await JsonDocument.ParseAsync(response.ContentStream);
 
                                         //軟體
-                                       // Teacher teacherHimself = json.ToObject<Teacher>();
-                                       // teacherHimself.size -= teacherSizeInSchool;
+                                        // Teacher teacherHimself = json.ToObject<Teacher>();
+                                        // teacherHimself.size -= teacherSizeInSchool;
 
                                         // 最後一起修改
 
@@ -1530,7 +1537,8 @@ namespace TEAMModelOS.Controllers
                         return BadRequest(); // 不存在的功能BadRequest
                 }
             }
-            catch (CosmosException ex) {
+            catch (CosmosException ex)
+            {
                 await _dingDing.SendBotMsg($"OS,{_option.Location},schoool/teacher-space\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
                 return BadRequest();
             }
@@ -1544,15 +1552,17 @@ namespace TEAMModelOS.Controllers
         [HttpPost("teacher-import-manage")]
         [Authorize(Roles = "IES")]
         [AuthToken(Roles = "admin,teacher")]
-        public async Task<IActionResult> TeacherImportManage(JsonElement request) {
-          (string adminId,string adminName,string pic ,string schoolId)=  HttpContext.GetAuthTokenInfo();
+        public async Task<IActionResult> TeacherImportManage(JsonElement request)
+        {
+            (string adminId, string adminName, string pic, string schoolId) = HttpContext.GetAuthTokenInfo();
             if (!request.TryGetProperty("opt", out JsonElement _opt)) { return BadRequest(); }
             if (!request.TryGetProperty("schoolId", out JsonElement _schoolId)) { return BadRequest(); }
             long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
             TeacherImport teacherImport = null;
             List<SchoolTeacher> idsInSchool = new List<SchoolTeacher>();
             List<CoreUser> coreUsers = new List<CoreUser>();
-            switch ($"{_opt}") {
+            switch ($"{_opt}")
+            {
                 case "upsert":
                     if (!request.TryGetProperty("teachers", out JsonElement _teachers) || !_teachers.ValueKind.Equals(JsonValueKind.Array)) { return BadRequest(); }
                     List<ImportTeacher> teachers = _teachers.ToObject<List<ImportTeacher>>();
@@ -1560,7 +1570,8 @@ namespace TEAMModelOS.Controllers
                     var phones = teachers.Where(x => !string.IsNullOrWhiteSpace(x.phone)).Select(z => z.phone);
                     var emails = teachers.Where(x => !string.IsNullOrWhiteSpace(x.email)).Select(z => z.email);
                     List<string> keys = new List<string>();
-                    if (tmdids.Any()) {
+                    if (tmdids.Any())
+                    {
                         keys.AddRange(tmdids);
                     }
                     if (phones.Any())
@@ -1571,8 +1582,9 @@ namespace TEAMModelOS.Controllers
                     {
                         keys.AddRange(emails);
                     }
-                    teachers.ForEach(x => { x.status = "import";x.time = now;x.iname = x.name;x.name = null; });
-                    if (keys.Any()) {
+                    teachers.ForEach(x => { x.status = "import"; x.time = now; x.iname = x.name; x.name = null; });
+                    if (keys.Any())
+                    {
                         try
                         {
                             var content = new StringContent(keys.ToJsonString(), Encoding.UTF8, "application/json");
@@ -1584,10 +1596,11 @@ namespace TEAMModelOS.Controllers
                         }
                         catch (Exception ex)
                         {
-                           await _dingDing.SendBotMsg($"{_option.Location},导入名单时,查验key信息错误{ex.Message}\n{ex.StackTrace}\n{keys.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
+                            await _dingDing.SendBotMsg($"{_option.Location},导入名单时,查验key信息错误{ex.Message}\n{ex.StackTrace}\n{keys.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
                         }
                     }
-                    if (coreUsers.Any()) {
+                    if (coreUsers.Any())
+                    {
                         string sql = $"select c.id,c.status from c where c.id in ({string.Join(",", coreUsers.Select(x => $"'{x.id}'"))}) ";
 
                         await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
@@ -1601,7 +1614,8 @@ namespace TEAMModelOS.Controllers
                     School schoolBase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>($"{_schoolId}", new PartitionKey("Base"));
                     if (coreUsers.Any())
                     {
-                        foreach (var t in teachers) {
+                        foreach (var t in teachers)
+                        {
                             if (!string.IsNullOrWhiteSpace(t.tmdid))
                             {
                                 CoreUser coreUser = coreUsers.Find(x => x.id.Equals(t.tmdid));
@@ -1609,9 +1623,10 @@ namespace TEAMModelOS.Controllers
                                 {
                                     t.id = coreUser.id;
                                     t.name = coreUser.name;
-                                    t.picture=coreUser.picture;
-                                    t.tmdid=coreUser.id;
-                                    if (!string.IsNullOrWhiteSpace(coreUser.mobile)) { 
+                                    t.picture = coreUser.picture;
+                                    t.tmdid = coreUser.id;
+                                    if (!string.IsNullOrWhiteSpace(coreUser.mobile))
+                                    {
                                         t.phone = coreUser.mobile;
                                     }
                                     if (!string.IsNullOrWhiteSpace(coreUser.mail))
@@ -1627,7 +1642,7 @@ namespace TEAMModelOS.Controllers
                                     CoreUser coreUser = coreUsers.Find(x => x.mobile.Equals(t.phone));
                                     if (coreUser != null)
                                     {
-                                        t.id = coreUser.id; 
+                                        t.id = coreUser.id;
                                         t.name = coreUser.name;
                                         t.picture = coreUser.picture;
                                         t.tmdid = coreUser.id;
@@ -1646,7 +1661,7 @@ namespace TEAMModelOS.Controllers
                             {
                                 if (!string.IsNullOrWhiteSpace(t.email))
                                 {
-                                    CoreUser coreUser = coreUsers.Find(x =>!string.IsNullOrWhiteSpace(x.mail)&&  x.mail.Equals(t.email));
+                                    CoreUser coreUser = coreUsers.Find(x => !string.IsNullOrWhiteSpace(x.mail) && x.mail.Equals(t.email));
                                     if (coreUser != null)
                                     {
                                         t.id = coreUser.id;
@@ -1671,9 +1686,11 @@ namespace TEAMModelOS.Controllers
                                 {
                                     t.status = teacher.status;
                                 }
-                                else {
+                                else
+                                {
                                     t.status = "invite";
-                                    teacher = new SchoolTeacher {
+                                    teacher = new SchoolTeacher
+                                    {
                                         id = t.id,
                                         name = t.name,
                                         permissions = new List<string>(),
@@ -1681,37 +1698,47 @@ namespace TEAMModelOS.Controllers
                                         job = null,
                                         roles = new List<string> { "teacher" },
                                         status = "invite",
-                                        createTime= now,
+                                        createTime = now,
                                         size = 0,
-                                        subjectIds= new List<string>(),
-                                        pk= "Teacher",
-                                        code=$"Teacher-{_schoolId}"
+                                        subjectIds = new List<string>(),
+                                        pk = "Teacher",
+                                        code = $"Teacher-{_schoolId}"
                                     };
                                     inviteids.Add(t.id);
-                                    await  _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).CreateItemAsync(teacher, new PartitionKey (teacher.code));
-                                    Azure.Response responseTeacher = await  _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemStreamAsync(t.id, new PartitionKey("Base"));
+                                    await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).CreateItemAsync(teacher, new PartitionKey(teacher.code));
+                                    Azure.Response responseTeacher = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemStreamAsync(t.id, new PartitionKey("Base"));
                                     if (responseTeacher.Status == 200)
                                     {
-                                        Teacher teacherBase= JsonDocument.Parse(responseTeacher.Content).RootElement.Deserialize<Teacher>();
-                                        var school= teacherBase.schools?.Find(x => x.schoolId.Equals($"{_schoolId}"));
+                                        Teacher teacherBase = JsonDocument.Parse(responseTeacher.Content).RootElement.Deserialize<Teacher>();
+                                        var school = teacherBase.schools?.Find(x => x.schoolId.Equals($"{_schoolId}"));
                                         if (teacherBase.schools.IsNotEmpty())
                                         {
-                                            if (school == null) {
+                                            if (school == null)
+                                            {
                                                 teacherBase.schools.Add(new TeacherSchool { schoolId = schoolBase.id, name = schoolBase.name, picture = schoolBase.picture, areaId = schoolBase.areaId, time = now, status = "invite" });
                                             }
                                         }
-                                        else {
-                                            teacherBase.schools = new List<TeacherSchool> { new TeacherSchool {schoolId= schoolBase.id,name= schoolBase.name,picture= schoolBase.picture, areaId= schoolBase.areaId,time=now,status= "invite" } };
+                                        else
+                                        {
+                                            teacherBase.schools = new List<TeacherSchool> { new TeacherSchool { schoolId = schoolBase.id, name = schoolBase.name, picture = schoolBase.picture, areaId = schoolBase.areaId, time = now, status = "invite" } };
                                         }
                                         await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReplaceItemAsync(teacherBase, teacherBase.id, new PartitionKey("Base"));
                                     }
-                                    else {
+                                    else
+                                    {
                                         Teacher teacherBase = new Teacher
                                         {
                                             createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
-                                            id = t.id, name = t.name, picture = t.picture, size = 2,code="Base",pk="Base", schools = new List<TeacherSchool> {
+                                            id = t.id,
+                                            name = t.name,
+                                            picture = t.picture,
+                                            size = 2,
+                                            code = "Base",
+                                            pk = "Base",
+                                            schools = new List<TeacherSchool> {
                                             new TeacherSchool {schoolId= schoolBase.id,name= schoolBase.name,picture= schoolBase.picture, areaId= schoolBase.areaId,time=now,status= "invite" },
-                                        } };
+                                        }
+                                        };
                                         await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).CreateItemAsync(teacherBase, new PartitionKey("Base"));
                                     }
 
@@ -1720,7 +1747,7 @@ namespace TEAMModelOS.Controllers
                         }
                     }
 
-                    Azure .Response response=  await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemStreamAsync($"{_schoolId}", new PartitionKey("TeacherImport"));
+                    Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemStreamAsync($"{_schoolId}", new PartitionKey("TeacherImport"));
                     if (response.Status == 200)
                     {
                         teacherImport = JsonDocument.Parse(response.Content).RootElement.Deserialize<TeacherImport>();
@@ -1732,7 +1759,8 @@ namespace TEAMModelOS.Controllers
                                 {
                                     tch = teacherImport.teachers.Find(t => t.iname.Equals(x.iname));
                                 }
-                                else {
+                                else
+                                {
                                     tch = teacherImport.teachers.Find(t => t.id.Equals(x.id));
                                 }
                                 if (tch != null)
@@ -1746,10 +1774,12 @@ namespace TEAMModelOS.Controllers
                                     tch.tmdid = x.tmdid;
                                     tch.email = x.email;
                                     tch.note = x.note;
-                                    tch.id=x.id;
+                                    tch.id = x.id;
                                 }
-                                else {
-                                    teacherImport.teachers.Add(new ImportTeacher {
+                                else
+                                {
+                                    teacherImport.teachers.Add(new ImportTeacher
+                                    {
                                         time = now,
                                         status = x.status,
                                         name = x.name,
@@ -1765,18 +1795,21 @@ namespace TEAMModelOS.Controllers
                             });
                             await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(teacherImport, $"{_schoolId}", new PartitionKey("TeacherImport"));
                         }
-                        else {
+                        else
+                        {
                             teacherImport = new TeacherImport { id = $"{_schoolId}", code = "TeacherImport", pk = "TeacherImport", teachers = teachers };
-                            await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(teacherImport,$"{_schoolId}", new PartitionKey("TeacherImport"));
+                            await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(teacherImport, $"{_schoolId}", new PartitionKey("TeacherImport"));
                         }
                     }
-                    else {
+                    else
+                    {
                         teacherImport = new TeacherImport { id = $"{_schoolId}", code = "TeacherImport", pk = "TeacherImport", teachers = teachers };
                         await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).CreateItemAsync(teacherImport, new PartitionKey("TeacherImport"));
                     }
 
-                   
-                    if (inviteids.Any()) {
+
+                    if (inviteids.Any())
+                    {
                         string bizcode = "invite";
                         Notification notification = new Notification
                         {
@@ -1797,7 +1830,7 @@ namespace TEAMModelOS.Controllers
                     break;
             }
             return Ok(new { teacherImport });
-        
+
         }
     }
 }

+ 69 - 51
TEAMModelOS/Controllers/School/SchoolTeacherController.cs

@@ -15,7 +15,7 @@ using System.IdentityModel.Tokens.Jwt;
 using System.IO;
 using System.Linq;
 using Microsoft.Extensions.Options;
-using System.Net.Http; 
+using System.Net.Http;
 using System.Net;
 using Microsoft.Extensions.Configuration;
 using TEAMModelOS.SDK.Models.Service;
@@ -27,7 +27,7 @@ namespace TEAMModelOS.Controllers
 {
     [ProducesResponseType(StatusCodes.Status200OK)]
     [ProducesResponseType(StatusCodes.Status400BadRequest)]
- 
+
     [Route("school/teacher")]
     [ApiController]
     public class SchoolTeacherController : Controller
@@ -42,10 +42,10 @@ namespace TEAMModelOS.Controllers
         private readonly CoreAPIHttpService _coreAPIHttpService;
 
         private readonly DingDing _dingDing;
-        public SchoolTeacherController(DingDing dingDing,CoreAPIHttpService coreAPIHttpService,AzureServiceBusFactory azureServiceBus,AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, IConfiguration configuration, NotificationService notificationService)
+        public SchoolTeacherController(DingDing dingDing, CoreAPIHttpService coreAPIHttpService, AzureServiceBusFactory azureServiceBus, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, IConfiguration configuration, NotificationService notificationService)
         {
-            _dingDing=dingDing; 
-               _azureCosmos = azureCosmos;
+            _dingDing = dingDing;
+            _azureCosmos = azureCosmos;
             _azureStorage = azureStorage;
             _option = option?.Value;
             _configuration = configuration;
@@ -70,7 +70,8 @@ namespace TEAMModelOS.Controllers
             //string status_str = (request.TryGetProperty("join_status", out JsonElement status_json)) ? status_json.ToString() : "join";
             //資料取得
             List<ScTeacher> teachers = new List<ScTeacher>();
-            try {
+            try
+            {
                 await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<ScTeacher>
                 (queryText: $"SELECT c.subjectIds, c.id, c.name,   c.picture ,c.status, c.job, c.createTime, ARRAY_LENGTH(c.permissions) as permissionCount,c.permissions,c.roles , c.size FROM c",
                 requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Teacher-{school_code}") }))
@@ -362,8 +363,10 @@ namespace TEAMModelOS.Controllers
                         }
                     });
                 }
-            } catch (Exception ex) {
-               await _dingDing.SendBotMsg($"{_option.Location},{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"{_option.Location},{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
             }
             return Ok(new { teachers });
         }
@@ -424,7 +427,7 @@ namespace TEAMModelOS.Controllers
 
         public async Task<IActionResult> GetSchoolAuthorityList()
         {
-             
+
             Dictionary<string, object> dict = new Dictionary<string, object>
             {
                 { "PartitionKey",  "authority"}
@@ -454,8 +457,9 @@ namespace TEAMModelOS.Controllers
                 request.TryGetProperty("permission", out JsonElement _permission);
                 request.TryGetProperty("pmAdd", out JsonElement _pmAdd);
                 request.TryGetProperty("pmRmv", out JsonElement _pmRmv);
-                List<string> rmvPm = null ;
-                if (_pmRmv.ValueKind.Equals(JsonValueKind.Array)){
+                List<string> rmvPm = null;
+                if (_pmRmv.ValueKind.Equals(JsonValueKind.Array))
+                {
                     rmvPm = _pmRmv.ToObject<List<string>>();
                 }
                 List<string> addPm = null;
@@ -466,43 +470,49 @@ namespace TEAMModelOS.Controllers
                 List<string> permission = null;
                 if (_permission.ValueKind.Equals(JsonValueKind.Array))
                 {
-                     permission = _permission.ToObject<List<string>>();
+                    permission = _permission.ToObject<List<string>>();
                 }
-                if (!_ids.ValueKind.Equals(JsonValueKind.Array)) {
+                if (!_ids.ValueKind.Equals(JsonValueKind.Array))
+                {
                     return BadRequest();
                 }
                 List<string> ids = _ids.ToObject<List<string>>();
                 //更新權限
                 List<SchoolTeacher> schoolTeachers = new List<SchoolTeacher>();
-                bool hasjob =false;
+                bool hasjob = false;
                 if (ids.Count > 1 && !string.IsNullOrWhiteSpace($"{_job}"))
                 {
                     hasjob = true;
                 }
-                else if(ids.Count==1  && permission.IsNotEmpty()) {
+                else if (ids.Count == 1 && permission.IsNotEmpty())
+                {
                     hasjob = true;
                 }
                 foreach (var id in ids)
                 {
                     SchoolTeacher st = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<SchoolTeacher>(id, new PartitionKey($"Teacher-{school_code}"));
-                    if (permission.IsNotEmpty()) {
+                    if (permission.IsNotEmpty())
+                    {
                         st.permissions = permission;
                     }
-                    if (addPm.IsNotEmpty()) {
+                    if (addPm.IsNotEmpty())
+                    {
                         st.permissions.AddRange(addPm);
                     }
-                    if (rmvPm.IsNotEmpty()) {
+                    if (rmvPm.IsNotEmpty())
+                    {
                         st.permissions.RemoveAll(x => rmvPm.Contains(x));
                     }
-                    if (hasjob) {
+                    if (hasjob)
+                    {
                         st.job = $"{_job}";
                     }
                     await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(st, id, new PartitionKey($"Teacher-{school_code}"));
-                    schoolTeachers.Add(st); 
+                    schoolTeachers.Add(st);
                 }
-                return Ok(new {teachers= schoolTeachers });
+                return Ok(new { teachers = schoolTeachers });
             }
-            catch (Exception )
+            catch (Exception)
             {
                 return BadRequest();
             }
@@ -559,7 +569,7 @@ namespace TEAMModelOS.Controllers
                     ids.Add(tmd);
                     //老師個人資料
                     var tresponse = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemStreamAsync(id.ToString(), new PartitionKey("Base"));
-                    if(tresponse.Status == 200)
+                    if (tresponse.Status == 200)
                     {
                         using var json = await JsonDocument.ParseAsync(tresponse.ContentStream);
                         Teacher teacher = json.ToObject<Teacher>();
@@ -584,7 +594,7 @@ namespace TEAMModelOS.Controllers
                             school.status = grant_type.GetString();
                         }
                         else
-                            teacher.schools.Add(new Teacher.TeacherSchool() {areaId=schareaId,picture=schpic, schoolId = school_code.GetString(), name = schname, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), status = grant_type.GetString() });
+                            teacher.schools.Add(new Teacher.TeacherSchool() { areaId = schareaId, picture = schpic, schoolId = school_code.GetString(), name = schname, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), status = grant_type.GetString() });
                         if (teacher.schools.Count > 0 && teacher.size <= 1)
                         {
                             teacher.size = 2;
@@ -601,7 +611,7 @@ namespace TEAMModelOS.Controllers
                         writer.WriteString("id", id.ToString());
                         writer.WriteString("name", name.ToString());
                         writer.WriteString("picture", picture.ToString());
-                        writer.WriteNumber("size", 1); 
+                        writer.WriteNumber("size", 1);
                         writer.WriteString("groupId", "default");
                         writer.WriteString("groupName", "默认组别");
                         writer.WriteNull("defaultSchool");
@@ -617,14 +627,15 @@ namespace TEAMModelOS.Controllers
                         await client.GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemStreamAsync(stream, new PartitionKey("Base"));
                     }
                     //學校老師資料
-                      
+
                     var sresponse = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(id.ToString(), new PartitionKey($"Teacher-{school_code}"));
                     //SchoolTeacher schteacher = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<SchoolTeacher>(id.ToString(), new PartitionKey($"Teacher-{school_code}"));
                     if (sresponse.Status == 200)
                     {
                         using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
                         SchoolTeacher schteacher = json.ToObject<SchoolTeacher>();
-                        if (schteacher.status.Equals("invite") && grant_type.ToString().Equals("invite")) {
+                        if (schteacher.status.Equals("invite") && grant_type.ToString().Equals("invite"))
+                        {
                             keys.Add(new KeyValuePair<string, int>($"{id}", 1));
                             continue;
                         }
@@ -634,7 +645,7 @@ namespace TEAMModelOS.Controllers
                             continue;
                         }
                         schteacher.status = grant_type.ToString();
-                        schteacher.createTime =   DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                        schteacher.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                         await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(schteacher, id.ToString(), new PartitionKey($"Teacher-{school_code}"));
                     }
                     else
@@ -674,14 +685,14 @@ namespace TEAMModelOS.Controllers
                         await TmdUserService.JoinSchool(client, $"{id}", $"{picture}", $"{name}", $"{school_code}", $"{schname}");
                     }
                 }
-               
+
                 string bizcode = grant_type.GetString();
-                if (grant_type.GetString() .Equals("join"))
+                if (grant_type.GetString().Equals("join"))
                 {
                     bizcode = "request-join";
                 }
 
-               
+
                 Notification notification = new Notification
                 {
                     hubName = "hita",
@@ -697,9 +708,9 @@ namespace TEAMModelOS.Controllers
                 var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
                 var location = _option.Location;
                 var code = await _notificationService.SendNotification(clientID, clientSecret, location, url, notification);
-                return Ok(new { exist = keys }) ;
+                return Ok(new { exist = keys });
             }
-            catch(Exception ex)
+            catch (Exception ex)
             {
                 return BadRequest();
             }
@@ -711,7 +722,7 @@ namespace TEAMModelOS.Controllers
         /// <param name="request"></param>
         /// <returns></returns>
         [ProducesDefaultResponseType]
-        [AuthToken(Roles = "admin",Permissions = "schoolSetting-upd,auth-upd,schoolAc-upd,teacher-upd")]
+        [AuthToken(Roles = "admin", Permissions = "schoolSetting-upd,auth-upd,schoolAc-upd,teacher-upd")]
         [HttpPost("upd-teacher-status")]
         [Authorize(Roles = "IES")]
         public async Task<IActionResult> UpdSchoolTeacherStatus(JsonElement request)
@@ -755,9 +766,10 @@ namespace TEAMModelOS.Controllers
                     school.time = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
                 }
                 else
-                    teacher.schools.Add(new Teacher.TeacherSchool() { areaId = schareaId, picture = schpic, schoolId = school_code.GetString(), name = schname,time =  DateTimeOffset.UtcNow.ToUnixTimeSeconds(), status = grant_type.GetString() });
+                    teacher.schools.Add(new Teacher.TeacherSchool() { areaId = schareaId, picture = schpic, schoolId = school_code.GetString(), name = schname, time = DateTimeOffset.UtcNow.ToUnixTimeSeconds(), status = grant_type.GetString() });
                 var dft = new List<string>() { "content-read", "exercise-read", "knowledge-read", "syllabus-read" };
-                if (teacher.schools.Count > 0 && teacher.size<=1) {
+                if (teacher.schools.Count > 0 && teacher.size <= 1)
+                {
                     teacher.size = 2;
                 }
                 await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, id.ToString(), new PartitionKey("Base"));
@@ -799,7 +811,7 @@ namespace TEAMModelOS.Controllers
                         picture = teacher.picture,
                         roles = new List<string>(new string[] { "teacher" }),
                         /// 只是申请加入就需要开放 这几个权限吗
-                        permissions = grant_type.GetString().Equals("join")? dft:null,
+                        permissions = grant_type.GetString().Equals("join") ? dft : null,
                         size = 0,
                         status = grant_type.GetString()
                     };
@@ -810,10 +822,11 @@ namespace TEAMModelOS.Controllers
                     await TmdUserService.JoinSchool(client, $"{teacher.id}", $"{teacher.picture}", $"{teacher.name}", $"{school_code}", $"{schname}");
                 }
                 string bizcode = grant_type.GetString();
-                if (grant_type.GetString() .Equals("join"))
+                if (grant_type.GetString().Equals("join"))
                 {
                     bizcode = "request-join";
-                    if (!string.IsNullOrWhiteSpace($"{_importName}")) {
+                    if (!string.IsNullOrWhiteSpace($"{_importName}"))
+                    {
                         Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemStreamAsync($"{school_code}", new PartitionKey("TeacherImport"));
                         TeacherImport teacherImport = null;
                         if (response.Status == 200)
@@ -852,9 +865,9 @@ namespace TEAMModelOS.Controllers
                     hubName = "hita",
                     type = "msg",
                     from = $"ies5:{_option.Location}:private",
-                    to =new List<string> { teacher.id },
+                    to = new List<string> { teacher.id },
                     label = $"{bizcode}_school",
-                    body = new { location = _option.Location, biz = bizcode, tmdid = tid, tmdname =tname, schoolcode = $"{school_code}", schoolname = $"{schname}", status = 1, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }.ToJsonString(),
+                    body = new { location = _option.Location, biz = bizcode, tmdid = tid, tmdname = tname, schoolcode = $"{school_code}", schoolname = $"{schname}", status = 1, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }.ToJsonString(),
                     expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
                 };
                 var url = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
@@ -886,28 +899,33 @@ namespace TEAMModelOS.Controllers
                 var (tid, tname, _, tschool) = HttpContext.GetAuthTokenInfo();
                 if (!request.TryGetProperty("school_code", out JsonElement school_code)) return BadRequest();
                 request.TryGetProperty("id", out JsonElement id);
-                request.TryGetProperty("name", out JsonElement name); 
+                request.TryGetProperty("name", out JsonElement name);
                 var client = _azureCosmos.GetCosmosClient();
                 //在老師表找出老師,刪除該學校 (老師基本資料應該要存在)
                 Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemStreamAsync($"{school_code}", new PartitionKey("TeacherImport"));
                 TeacherImport teacherImport = null;
                 if (response.Status == 200)
                 {
-                    teacherImport= JsonDocument.Parse(response.Content).RootElement.Deserialize<TeacherImport>();
+                    teacherImport = JsonDocument.Parse(response.Content).RootElement.Deserialize<TeacherImport>();
                 }
-                if (!string.IsNullOrWhiteSpace($"{name}")  && teacherImport!= null) {
+                if (!string.IsNullOrWhiteSpace($"{name}") && teacherImport != null)
+                {
                     //移除同名的、其中一个
-                    var ts=  teacherImport.teachers.FindAll(x => string.IsNullOrWhiteSpace(x.id)  &&  !string.IsNullOrWhiteSpace(x.iname ) &&  x.iname.Equals($"{name}"));
-                    if (ts.IsNotEmpty()) {
+                    var ts = teacherImport.teachers.FindAll(x => string.IsNullOrWhiteSpace(x.id) && !string.IsNullOrWhiteSpace(x.iname) && x.iname.Equals($"{name}"));
+                    if (ts.IsNotEmpty())
+                    {
                         teacherImport.teachers.Remove(ts.First());
                         await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(teacherImport, $"{school_code}", new PartitionKey("TeacherImport"));
                     }
                 }
-                if (!string.IsNullOrWhiteSpace($"{id}")) {
+                if (!string.IsNullOrWhiteSpace($"{id}"))
+                {
 
-                    if (teacherImport != null) {
-                        int count= teacherImport.teachers.RemoveAll(x => !string.IsNullOrWhiteSpace(x.id)  &&  x.id.Equals($"{id}"));
-                        if (count > 0) {
+                    if (teacherImport != null)
+                    {
+                        int count = teacherImport.teachers.RemoveAll(x => !string.IsNullOrWhiteSpace(x.id) && x.id.Equals($"{id}"));
+                        if (count > 0)
+                        {
                             await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(teacherImport, $"{school_code}", new PartitionKey("TeacherImport"));
                         }
                     }
@@ -991,7 +1009,7 @@ namespace TEAMModelOS.Controllers
         public async Task<IActionResult> GetUserFromCoreID(JsonElement request)
         {
             var content = new StringContent(request.ToString(), Encoding.UTF8, "application/json");
-            string json = await  _coreAPIHttpService.GetUserInfos(content);
+            string json = await _coreAPIHttpService.GetUserInfos(content);
             return Ok(json.ToObject<JsonElement>());
         }
     }

+ 57 - 42
TEAMModelOS/Controllers/Student/StudentController.cs

@@ -96,14 +96,15 @@ namespace TEAMModelOS.Controllers
                             if (currStud.TryGetProperty("no", out var tmpNo)) no = tmpNo.GetString();
                             if (currStud.TryGetProperty("classId", out var tmpClassId)) classId = tmpClassId.GetString();
                             //要檢查座號使否已被使用
-                            var existNo = await StudentService.checkStudNo( _azureCosmos, _dingDing, _option,  schoolId.GetString(), classId, new List<string>() { id });
+                            var existNo = await StudentService.checkStudNo(_azureCosmos, _dingDing, _option, schoolId.GetString(), classId, new List<string>() { id });
                             if (existNo.Count != 0) return this.Ok(new { code = $"Base-{schoolId.GetString()}", existNo = existNo.Select(o => o.id).ToList() });
                             if (currStud.TryGetProperty("periodId", out var tempPeriodId)) periodId = tempPeriodId.GetString();
                             //建立學生
                             studCreateInfo studCreateInfo = new studCreateInfo(id, name, "M", year, pw, classId, no, periodId);
-                            var isCreateSuc = await createStudent( _azureCosmos, _dingDing, _option, schoolId.GetString(), studCreateInfo);
+                            var isCreateSuc = await createStudent(_azureCosmos, _dingDing, _option, schoolId.GetString(), studCreateInfo);
 
-                            if (isCreateSuc) {
+                            if (isCreateSuc)
+                            {
                                 if (dictChange.ContainsKey(classId))
                                 {
                                     dictChange[classId].stujoin.Add(
@@ -111,10 +112,11 @@ namespace TEAMModelOS.Controllers
                                         {
                                             id = id,
                                             code = $"{schoolId.GetString()}",
-                                            type=2,
+                                            type = 2,
                                         });
                                 }
-                                else {
+                                else
+                                {
                                     GroupChange change = new GroupChange
                                     {
                                         scope = "school",
@@ -122,14 +124,14 @@ namespace TEAMModelOS.Controllers
                                         type = "student",
                                         originCode = schoolId.GetString(),
                                         listid = classId,
-                                        stujoin = new List<Member> 
-                                        { 
+                                        stujoin = new List<Member>
+                                        {
                                             new Member
-                                            { 
+                                            {
                                                 id= id,
                                                 code=schoolId.GetString(),
                                                 type=2,
-                                            } 
+                                            }
                                         }
                                     };
                                     dictChange.Add(classId, change);
@@ -149,45 +151,46 @@ namespace TEAMModelOS.Controllers
                             }
                             else return this.Ok(new { code = $"Base-{schoolId.GetString()}", errorId = id });
                         }
-                          
+
                         break;
                     case "import":
                         //只有ClassNo可以比對
                         webStudents = request.GetProperty("students").ToObject<List<Student>>();
-                        preStudents= await StudentService.GeStudentData(_azureCosmos, schoolId.GetString(), webStudents?.Select(x => x.id));
-                        var retUpsert = await StudentService.upsertStudents( _azureCosmos, _dingDing, _option, schoolId.GetString(), request.GetProperty("students").EnumerateArray());
-                        await CheckStudent( _serviceBus, _configuration, _azureCosmos, schoolId.GetString(), webStudents, preStudents);
+                        preStudents = await StudentService.GeStudentData(_azureCosmos, schoolId.GetString(), webStudents?.Select(x => x.id));
+                        var retUpsert = await StudentService.upsertStudents(_azureCosmos, _dingDing, _option, schoolId.GetString(), request.GetProperty("students").EnumerateArray());
+                        await CheckStudent(_serviceBus, _configuration, _azureCosmos, schoolId.GetString(), webStudents, preStudents);
                         return this.Ok(new { code = $"Base-{schoolId.GetString()}", students = retUpsert.studs, retUpsert.classDuplNos, retUpsert.errorIds });
                     case "read":
                         //讀取該間學校所有的學生資訊
-                        var students = await StudentService.getAllStudent( _azureCosmos, _dingDing, _option,schoolId.GetString());
+                        var students = await StudentService.getAllStudent(_azureCosmos, _dingDing, _option, schoolId.GetString());
                         return this.Ok(new { code = $"Base-{schoolId.GetString()}", students });
                     case "update":
                         //更新學生資料,批量密碼重置,基本資訊更新(姓名、教室ID、性別、學年及座號)
                         webStudents = request.GetProperty("students").ToObject<List<Student>>();
                         preStudents = await StudentService.GeStudentData(_azureCosmos, schoolId.GetString(), webStudents?.Select(x => x.id));
-                        var retUpdate = await   StudentService.updateStudents( _azureCosmos, _dingDing, _option, schoolId.GetString(), request.GetProperty("students").EnumerateArray());
-                        await StudentService.CheckStudent( _serviceBus, _configuration, _azureCosmos, schoolId.GetString(), webStudents,  preStudents);
+                        var retUpdate = await StudentService.updateStudents(_azureCosmos, _dingDing, _option, schoolId.GetString(), request.GetProperty("students").EnumerateArray());
+                        await StudentService.CheckStudent(_serviceBus, _configuration, _azureCosmos, schoolId.GetString(), webStudents, preStudents);
                         return this.Ok(new { code = $"Base-{schoolId.GetString()}", students = retUpdate.studs, retUpdate.classDuplNos, retUpdate.nonexistentIds, retUpdate.errorNos, retUpdate.errorClassId });
                     case "delete":
                         //刪除學生資料及從教室學生名單內移除該學生
                         webStudents = request.GetProperty("students").ToObject<List<Student>>();
                         preStudents = await StudentService.GeStudentData(_azureCosmos, schoolId.GetString(), webStudents?.Select(x => x.id));
-                        var sucDelIds = await StudentService.deleteStudents( _azureCosmos, _dingDing, _option, schoolId.GetString(), request.GetProperty("students").EnumerateArray());
-                        await StudentService.CheckStudent( _serviceBus, _configuration, _azureCosmos,schoolId.GetString(), webStudents,  preStudents);
+                        var sucDelIds = await StudentService.deleteStudents(_azureCosmos, _dingDing, _option, schoolId.GetString(), request.GetProperty("students").EnumerateArray());
+                        await StudentService.CheckStudent(_serviceBus, _configuration, _azureCosmos, schoolId.GetString(), webStudents, preStudents);
                         return this.Ok(new { code = $"Base-{schoolId.GetString()}", ids = sucDelIds });
                     case "remove":
                         //將學生基本資料內的classId、no、groupId及groupName寫入null
                         List<string> stus = request.GetProperty("students").ToObject<List<string>>();
                         webStudents = new List<Student>();
-                        foreach (string idstu in stus) {
-                            webStudents.Add(new Student { id= idstu, code=$"Base-{schoolId}"});
+                        foreach (string idstu in stus)
+                        {
+                            webStudents.Add(new Student { id = idstu, code = $"Base-{schoolId}" });
                         }
                         preStudents = await StudentService.GeStudentData(_azureCosmos, schoolId.GetString(), webStudents?.Select(x => x.id));
                         (List<string> studs, List<string> nonexistentIds, List<string> errorIds) retRemove = await StudentService.removeStudentClassInfo(
-                             _azureCosmos, _dingDing, _option, 
+                             _azureCosmos, _dingDing, _option,
                             schoolId.GetString(), request.GetProperty("students").EnumerateArray());
-                        await StudentService.CheckStudent(  _serviceBus, _configuration, _azureCosmos,  schoolId.GetString(), webStudents, preStudents);
+                        await StudentService.CheckStudent(_serviceBus, _configuration, _azureCosmos, schoolId.GetString(), webStudents, preStudents);
                         return Ok(new { code = $"Base-{schoolId.GetString()}", ids = retRemove.studs, retRemove.nonexistentIds, retRemove.errorIds });
                     case "avatar":
                         if (request.TryGetProperty("avatar", out JsonElement _avatar) && _avatar.ValueKind.Equals(JsonValueKind.Array))
@@ -226,33 +229,39 @@ namespace TEAMModelOS.Controllers
                         {
                             var studentInfo = _studentInfo.ToObject<StudentInfo>();
 
-                            if (studentInfo.studentId.Equals(stuid) && school .Equals($"{schoolId}")) {
+                            if (studentInfo.studentId.Equals(stuid) && school.Equals($"{schoolId}"))
+                            {
                                 Student student = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Student")
                                 .ReadItemAsync<Student>(studentInfo.studentId, new PartitionKey($"Base-{schoolId}"));
                                 student.mail = string.IsNullOrEmpty(studentInfo.mail) ? student.mail : studentInfo.mail;
                                 student.mobile = string.IsNullOrEmpty(studentInfo.mobile) ? student.mobile : studentInfo.mobile;
                                 student.name = string.IsNullOrEmpty(studentInfo.name) ? student.name : studentInfo.name;
                                 (string url, string sas) = _azureStorage.GetBlobContainerSAS99Year($"{schoolId}", BlobContainerSasPermissions.Read);
-                                student.picture = string.IsNullOrEmpty(studentInfo.picture) ? student.picture :  $"{studentInfo.picture}?{sas}";
+                                student.picture = string.IsNullOrEmpty(studentInfo.picture) ? student.picture : $"{studentInfo.picture}?{sas}";
                                 student.gender = string.IsNullOrEmpty(studentInfo.gender) ? student.gender : studentInfo.gender;
                                 await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Student")
                                     .ReplaceItemAsync<Student>(student, studentInfo.studentId, new PartitionKey($"Base-{schoolId}"));
                                 return Ok(new { studentInfo });
                             }
-                            else {
+                            else
+                            {
                                 return Ok(new { error = false, status = false, msg = "修改的不是自己的信息" });
                             }
-                            
+
                         }
-                        else {
+                        else
+                        {
                             return BadRequest();
                         }
                     case "update-self-password":
-                        if (request.TryGetProperty("newpwd", out JsonElement _newpwd)&& 
-                            request.TryGetProperty("oldpwd", out JsonElement _oldpwd) && 
-                            request.TryGetProperty("studentId", out JsonElement _studentId)) {
-                            if ($"{_studentId}".Equals(stuid) && school.Equals($"{schoolId}")) {
-                                try {
+                        if (request.TryGetProperty("newpwd", out JsonElement _newpwd) &&
+                            request.TryGetProperty("oldpwd", out JsonElement _oldpwd) &&
+                            request.TryGetProperty("studentId", out JsonElement _studentId))
+                        {
+                            if ($"{_studentId}".Equals(stuid) && school.Equals($"{schoolId}"))
+                            {
+                                try
+                                {
                                     Student student = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Student")
                                    .ReadItemAsync<Student>($"{_studentId}", new PartitionKey($"Base-{schoolId}"));
                                     var HashedPW = Utils.HashedPassword($"{_oldpwd}", student.salt);
@@ -267,7 +276,9 @@ namespace TEAMModelOS.Controllers
                                     {
                                         return Ok(new { error = false, status = false, msg = "密码不一致" });
                                     }
-                                } catch (Exception ex) {
+                                }
+                                catch (Exception ex)
+                                {
                                     await _dingDing.SendBotMsg($"IES5,{_option.Location},StudentController/StudentManage()\n{ex.Message}{ex.StackTrace}\n{request.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
                                     return Ok(new { error = false, status = false, msg = "账号不存在" });
                                 }
@@ -285,13 +296,15 @@ namespace TEAMModelOS.Controllers
                     case "read-self-info":
                         if (request.TryGetProperty("studentId", out JsonElement __studentId))
                         {
-                            try {
+                            try
+                            {
                                 Student student = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Student")
                                     .ReadItemAsync<Student>($"{__studentId}", new PartitionKey($"Base-{schoolId}"));
                                 return Ok(new { student.mail, student.mobile, student.name, student.picture, student.gender, student.id, student.schoolId, student.year, student.no, student.classId, student.periodId, irs = student.irs });
 
                             }
-                            catch (Exception ex) {
+                            catch (Exception ex)
+                            {
                                 await _dingDing.SendBotMsg($"IES5,{_option.Location},StudentController/StudentManage()\n{ex.Message}{ex.StackTrace}\n{request.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
                             }
                             return Ok();
@@ -312,7 +325,8 @@ namespace TEAMModelOS.Controllers
         }
         [HttpPost("get-student-info")]
         [Authorize(Roles = "IES")]
-        public async Task<IActionResult> GetStudentInfo(JsonElement request) {
+        public async Task<IActionResult> GetStudentInfo(JsonElement request)
+        {
             var client = _azureCosmos.GetCosmosClient();
             var schoolClient = client.GetContainer(Constant.TEAMModelOS, "School");
             var teacherClient = client.GetContainer(Constant.TEAMModelOS, "Teacher");
@@ -365,7 +379,7 @@ namespace TEAMModelOS.Controllers
                 if (!request.TryGetProperty("school_code", out JsonElement school_code)) return BadRequest();
                 if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
                 if (!request.TryGetProperty("pw", out JsonElement pw)) return BadRequest();
-                School  school  = await schoolClient.ReadItemAsync<School>($"{school_code}", new PartitionKey("Base"));
+                School school = await schoolClient.ReadItemAsync<School>($"{school_code}", new PartitionKey("Base"));
                 var response = await studentClient.ReadItemStreamAsync(id.GetString(), new PartitionKey($"Base-{school_code.GetString().ToLower()}"));
                 if (response.Status == 200)
                 {
@@ -382,8 +396,8 @@ namespace TEAMModelOS.Controllers
                     var HashedPW = Utils.HashedPassword(pw.ToString(), salt.ToString());
                     if (HashedPW.Equals(dbpw.GetString()))
                     {
-                        (string auth_token, string blob_uri, string blob_sas, object classinfo, List<object> courses, AuthenticationResult token) =await StudentCheck($"{id}", $"{classId}", $"{school_code}", $"{picture}", $"{name}", schoolClient, teacherClient ,school.areaId);
-                        return Ok(new { location = _option.Location, error = 0, auth_token, blob_uri, blob_sas, classinfo, courses,token =new { access_token = token.AccessToken, expires_in = token.ExpiresOn, id_token = auth_token, token_type = token.TokenType }  });
+                        (string auth_token, string blob_uri, string blob_sas, object classinfo, List<object> courses, AuthenticationResult token) = await StudentCheck($"{id}", $"{classId}", $"{school_code}", $"{picture}", $"{name}", schoolClient, teacherClient, school.areaId);
+                        return Ok(new { location = _option.Location, error = 0, auth_token, blob_uri, blob_sas, classinfo, courses, token = new { access_token = token.AccessToken, expires_in = token.ExpiresOn, id_token = auth_token, token_type = token.TokenType } });
                     }
                     else
                     {
@@ -401,7 +415,8 @@ namespace TEAMModelOS.Controllers
                 return BadRequest();
             }
         }
-        private async Task<(string auth_token,string blob_uri,string blob_sas, object classinfo, List<object>  courses, AuthenticationResult token)> StudentCheck(string id ,string classId,string school_code ,string picture,string name , CosmosContainer schoolClient, CosmosContainer teacherClient, string  areaId) {
+        private async Task<(string auth_token, string blob_uri, string blob_sas, object classinfo, List<object> courses, AuthenticationResult token)> StudentCheck(string id, string classId, string school_code, string picture, string name, CosmosContainer schoolClient, CosmosContainer teacherClient, string areaId)
+        {
             //班級課程
             object classinfo = null;
             List<object> courses = new List<object>();
@@ -529,7 +544,7 @@ namespace TEAMModelOS.Controllers
             var (blob_uri, blob_sas) = _azureStorage.GetBlobContainerSAS(school_code.ToLower(), BlobContainerSasPermissions.Read);
 
             //換取AuthToken,提供給前端
-            var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id, name, picture, _option.JwtSecretKey, scope: Constant.ScopeStudent, Website: "IES",areaId: areaId, schoolID: school_code, roles: new[] { "student" },expire: 1);
+            var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id, name, picture, _option.JwtSecretKey, scope: Constant.ScopeStudent, Website: "IES", areaId: areaId, schoolID: school_code, roles: new[] { "student" }, expire: 1);
             var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
             var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
             var token = await CoreTokenExtensions.CreateAccessToken(clientID, clientSecret, _option.Location.Replace("-Dep", "").Replace("-Test", ""));
@@ -654,7 +669,7 @@ namespace TEAMModelOS.Controllers
                             }
                         }
                         //換取AuthToken,提供給前端
-                        var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id.GetString(), name.GetString(), picture.GetString(), _option.JwtSecretKey, Website: "IES",areaId: schoolInfo.areaId, scope: Constant.ScopeStudent, schoolID: school_code.GetString(), roles: new[] { "student" }, expire: 1);
+                        var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id.GetString(), name.GetString(), picture.GetString(), _option.JwtSecretKey, Website: "IES", areaId: schoolInfo.areaId, scope: Constant.ScopeStudent, schoolID: school_code.GetString(), roles: new[] { "student" }, expire: 1);
                         //其他訊息
                         dynamic school = new ExpandoObject();
                         //回傳

+ 18 - 11
TEAMModelOS/Controllers/Student/TmdUserController.cs

@@ -33,7 +33,7 @@ namespace TEAMModelOS.Controllers
     //
     [Route("tmduser/init")]
     [ApiController]
-    public class TmdUserController: ControllerBase
+    public class TmdUserController : ControllerBase
     {
         private readonly AzureCosmosFactory _azureCosmos;
         private readonly AzureStorageFactory _azureStorage;
@@ -42,7 +42,7 @@ namespace TEAMModelOS.Controllers
         private readonly IConfiguration _configuration;
         private readonly CoreAPIHttpService _coreAPIHttpService;
 
-        public TmdUserController(CoreAPIHttpService coreAPIHttpService,AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration)
+        public TmdUserController(CoreAPIHttpService coreAPIHttpService, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration)
         {
             _azureCosmos = azureCosmos;
             _azureStorage = azureStorage;
@@ -54,7 +54,8 @@ namespace TEAMModelOS.Controllers
         [ProducesDefaultResponseType]
         [HttpPost("get-school-info")]
         [Authorize(Roles = "IES")]
-        public async Task<IActionResult> GetSchoolInfo(JsonElement request) {
+        public async Task<IActionResult> GetSchoolInfo(JsonElement request)
+        {
 
             if (!request.TryGetProperty("id_token", out JsonElement id_token)) return BadRequest();
             if (!request.TryGetProperty("school_code", out JsonElement school_code)) return BadRequest();
@@ -107,7 +108,8 @@ namespace TEAMModelOS.Controllers
                                 schoolExtobj.picture = school.RootElement.GetProperty("picture");
                                 sc.name = $"{school.RootElement.GetProperty("name")}";
                             }
-                            else {
+                            else
+                            {
                                 rm.Add(sc);
                             }
                         }
@@ -141,13 +143,14 @@ namespace TEAMModelOS.Controllers
                 }
                 //換取AuthToken,提供給前端
                 var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id, name?.ToString(), picture?.ToString(), _option.JwtSecretKey, Website: "IES", scope: Constant.ScopeTmdUser, roles: new[] { "student" }, expire: 1);
-                if (!string.IsNullOrEmpty(defaultschool)) { 
+                if (!string.IsNullOrEmpty(defaultschool))
+                {
 
                 }
                 var (blob_uri, blob_sas) = _azureStorage.GetBlobContainerSAS(id, BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List);
                 blob_uri = blob_uri.Replace(id, "");
                 blob_sas = "";
-                return Ok(new { location=_option.Location ,auth_token,  schools, defaultschool , blob_uri, blob_sas, status = 200 });
+                return Ok(new { location = _option.Location, auth_token, schools, defaultschool, blob_uri, blob_sas, status = 200 });
 
             }
             catch (CosmosException ex)
@@ -162,8 +165,9 @@ namespace TEAMModelOS.Controllers
                 return BadRequest();
             }
         }
-    
-        private  async Task<(string uri,string  sas)> GetSchoolData(string shool) {
+
+        private async Task<(string uri, string sas)> GetSchoolData(string shool)
+        {
 
             // BLOB(學校,唯讀)
             var (blob_uri, blob_sas) = _azureStorage.GetBlobContainerSAS(shool, BlobContainerSasPermissions.Read);
@@ -178,7 +182,8 @@ namespace TEAMModelOS.Controllers
             if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
             List<string> ids = id.ToObject<List<string>>();
             List<ufo> tmds = new List<ufo>();
-            try {
+            try
+            {
                 var content = new StringContent(ids.ToJsonString(), Encoding.UTF8, "application/json");
                 string json = await _coreAPIHttpService.GetUserInfos(content);
 
@@ -186,14 +191,16 @@ namespace TEAMModelOS.Controllers
                 {
                     try
                     {
-                        tmds = json.ToObject<List<ufo>>();                     
+                        tmds = json.ToObject<List<ufo>>();
                     }
                     catch (Exception ex)
                     {
                         await _dingDing.SendBotMsg($"{_coreAPIHttpService.options.Get("Default").location}用户转换失败:{_coreAPIHttpService.options.Get("Default").url}{json}\n {ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
                     }
                 }
-            } catch (Exception e) {
+            }
+            catch (Exception e)
+            {
                 await _dingDing.SendBotMsg($"IES5,{_option.Location},tmduser/init/getTmdInfo()\n{e.Message}{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
             }
             return Ok(tmds);

+ 154 - 72
TEAMModelOS/Controllers/Teacher/InitController.cs

@@ -29,12 +29,13 @@ using Microsoft.AspNetCore.Authorization;
 using System.Diagnostics;
 using Microsoft.Extensions.Logging;
 using System.Text;
+using Microsoft.Azure.Cosmos.Table;
 
 namespace TEAMModelOS.Controllers
 {
     [ProducesResponseType(StatusCodes.Status200OK)]
     [ProducesResponseType(StatusCodes.Status400BadRequest)]
-  
+
     [Route("teacher/init")]
     [ApiController]
     public class InitController : ControllerBase
@@ -49,7 +50,7 @@ namespace TEAMModelOS.Controllers
         private readonly IPSearcher _searcher;
         private readonly ILogger<InitController> _logger;
 
-        public InitController(ILogger<InitController> logger,IPSearcher searcher, CoreAPIHttpService coreAPIHttpService,AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration, NotificationService notificationService)
+        public InitController(ILogger<InitController> logger, IPSearcher searcher, CoreAPIHttpService coreAPIHttpService, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration, NotificationService notificationService)
         {
             _searcher = searcher;
             _azureCosmos = azureCosmos;
@@ -69,16 +70,18 @@ namespace TEAMModelOS.Controllers
         [ProducesDefaultResponseType]
         [HttpPost("GetUserInfo")]
         //[Authorize(Roles = "IES")]
-        public async Task<IActionResult> GetUserInfo(JsonElement request) {
+        public async Task<IActionResult> GetUserInfo(JsonElement request)
+        {
             if (!request.TryGetProperty("key", out JsonElement key)) return BadRequest();
-           
+
             var location = _option.Location;
             //https://api2-rc.teammodel.cn
-           CoreUser core = await _coreAPIHttpService.GetUserInfo(new Dictionary<string, string>()
+            CoreUser core = await _coreAPIHttpService.GetUserInfo(new Dictionary<string, string>()
                 {      { "key",$"{key}" }
-                }, location,_configuration
-               );
-            if (core != null) {
+                }, location, _configuration
+                );
+            if (core != null)
+            {
                 var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
                 TmdidImplicit tmdidImplicit = await _coreAPIHttpService.Implicit(new Dictionary<string, string> {   { "grant_type", "implicit" },
                                         { "client_id",clientID },
@@ -90,9 +93,9 @@ namespace TEAMModelOS.Controllers
                 }
             }
             return Ok(new { coreUser = core });
-           
+
         }
-        
+
 
 
         /// <summary>
@@ -118,7 +121,7 @@ namespace TEAMModelOS.Controllers
                 Teacher teacher = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Teacher>(userid, new PartitionKey("Base"));
                 switch (true)
                 {
-                        //修改默认学校
+                    //修改默认学校
                     case bool when $"{_opt}".Equals("UpdateDefaultSchool", StringComparison.OrdinalIgnoreCase) && (request.TryGetProperty("defaultSchool", out JsonElement _defaultSchool)):
                         if (teacher.schools.Select(x => x.schoolId).Contains($"{_defaultSchool}") && !string.IsNullOrEmpty($"{_defaultSchool}"))
                         {
@@ -141,7 +144,7 @@ namespace TEAMModelOS.Controllers
                         await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, userid, new PartitionKey("Base"));
                         return Ok(new { teacher, status = 1 });
                     //设置教师的科目信息
-                    case bool when $"{_opt}".Equals("SetTeacherSubject", StringComparison.OrdinalIgnoreCase) && request.TryGetProperty("targerTecher", out JsonElement _targetTecher) 
+                    case bool when $"{_opt}".Equals("SetTeacherSubject", StringComparison.OrdinalIgnoreCase) && request.TryGetProperty("targerTecher", out JsonElement _targetTecher)
                         && request.TryGetProperty("subjectIds", out JsonElement _subjectIds):
                         if (_subjectIds.ValueKind.Equals(JsonValueKind.Array))
                         {
@@ -150,7 +153,8 @@ namespace TEAMModelOS.Controllers
                             {
                                 List<string> targetTechers = _targetTecher.ToObject<List<string>>();
                                 List<SchoolTeacher> schoolTeachers = new List<SchoolTeacher>();
-                                foreach (string targetTecher in targetTechers) {
+                                foreach (string targetTecher in targetTechers)
+                                {
                                     try
                                     {
                                         SchoolTeacher schoolTeacher = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<SchoolTeacher>($"{targetTecher}", new PartitionKey($"Teacher-{school}"));
@@ -158,13 +162,15 @@ namespace TEAMModelOS.Controllers
                                         await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(schoolTeacher, $"{targetTecher}", new PartitionKey($"Teacher-{school}"));
                                         schoolTeachers.Add(schoolTeacher);
                                     }
-                                    catch (Exception ex) {
+                                    catch (Exception ex)
+                                    {
                                         await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/init/set-teacher-info:SetTeacherSubject()\n{ex.Message}{ex.StackTrace}{request.ToJsonString()}-{targetTecher}", GroupNames.醍摩豆服務運維群組);
                                     }
                                 }
                                 return Ok(new { status = 1, schoolTeachers });
                             }
-                            else {
+                            else
+                            {
                                 try
                                 {
                                     SchoolTeacher schoolTeacher = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<SchoolTeacher>($"{_targetTecher}", new PartitionKey($"Teacher-{school}"));
@@ -180,10 +186,11 @@ namespace TEAMModelOS.Controllers
 
                             }
                         }
-                        else {
+                        else
+                        {
                             return Ok(new { error = -1, msg = "设置失败" });
                         }
-                        ///移交管理员
+                    ///移交管理员
                     case bool when $"{_opt}".Equals("TransferAdminRole", StringComparison.OrdinalIgnoreCase) && (request.TryGetProperty("targerTecher", out JsonElement _targetTecher)):
                         if (!string.IsNullOrEmpty(school) && !string.IsNullOrEmpty($"{_targetTecher}"))
                         {
@@ -219,7 +226,7 @@ namespace TEAMModelOS.Controllers
                                     var location = _option.Location;
                                     await _notificationService.SendNotification(clientID, clientSecret, location, url, notification);
                                 }
-                                _ = _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");
+                                _ = _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");
                                 return Ok(new { status = 1 });
                             }
                             else
@@ -249,6 +256,7 @@ namespace TEAMModelOS.Controllers
         [HttpPost("get-teacher-info")]
         public async Task<IActionResult> GetTeacherInfo(JsonElement request)
         {
+            string domain = HttpContext?.Request?.Host.Host;
             if (!request.TryGetProperty("id_token", out JsonElement id_token)) return BadRequest();
             var jwt = new JwtSecurityToken(id_token.GetString());
             //TODO 此驗證IdToken先簡單檢查,後面需向Core ID新API,驗證Token
@@ -258,23 +266,43 @@ namespace TEAMModelOS.Controllers
             (string ip, string region) = await LoginService.LoginIp(HttpContext, _searcher);
             try
             {
-               
+
                 Teacher teacher = null;
-                TeacherInfo teacherInfo= await TeacherService.TeacherInfo(_azureCosmos, teacher, $"{name}", $"{picture}", id, _azureStorage, _option);
-                teacherInfo.areas.ForEach(x => { if (x.setting != null) { x.setting.accessConfig=x.setting.accessConfig; } });
-                LoginService.LoginLog(HttpContext,_option,_logger,_dingDing,ip,region, id, $"{name}", 200);
+                TeacherInfo teacherInfo = await TeacherService.TeacherInfo(_azureCosmos, teacher, $"{name}", $"{picture}", id, _azureStorage, _option);
+                teacherInfo.areas.ForEach(x => { if (x.setting != null) { x.setting.accessConfig = x.setting.accessConfig; } });
+                LoginService.LoginLog(HttpContext, _option, _logger, _dingDing, ip, region, id, $"{name}", 200);
                 int lessonLimit = teacherInfo.teacher.lessonLimit;
                 if (teacherInfo.teacher.lessonLimit == 0)
                 {
                     //未设置的的采用系统设置的默认值30
                     lessonLimit = Constant.private_lesson_limit;
                 }
-                return Ok(new { location = _option.Location, teacherInfo. auth_token, teacherInfo. blob_uri, teacherInfo.blob_sas, teacherInfo.schools, teacherInfo.defaultschool, teacherInfo. courses,
+                var table = _azureStorage.GetCloudTableClient().GetTableReference("IESOAuth");
+                List<string> Codes = new List<string>();
+                if (!string.IsNullOrWhiteSpace(id))
+                {
+                    Codes.Add($" Code {QueryComparisons.Equal} '{id}' ");
+                }
+                string qurey = $"PartitionKey {QueryComparisons.Equal} 'OAuthShow' and Domain {QueryComparisons.Equal} '{domain}' and ( { string.Join(" or ", Codes)} )  ";
+                var result = await table.ExecuteQuerySegmentedAsync(new TableQuery<OAuthShow>().Where(qurey), null);
+                List<OAuthShow> shows = result.Results;
+
+                return Ok(new
+                {
+                    privateShows = shows?.FindAll(x => x.Scope.Equals("private")).Select(x => new { x.Type, x.Status, x.Scope, x.Code }),
+                    location = _option.Location,
+                    teacherInfo.auth_token,
+                    teacherInfo.blob_uri,
+                    teacherInfo.blob_sas,
+                    teacherInfo.schools,
+                    teacherInfo.defaultschool,
+                    teacherInfo.courses,
                     teacherInfo.total,
                     teacherInfo.osblob_uri,
                     teacherInfo.osblob_sas,
-                    teacherInfo.tsize, status = 200,
-                    teacherInfo. areas ,
+                    teacherInfo.tsize,
+                    status = 200,
+                    teacherInfo.areas,
                     lessonLimit,
                     teacherInfo.teacher.lessonShow
                 });
@@ -292,13 +320,14 @@ namespace TEAMModelOS.Controllers
                 return BadRequest();
             }
         }
-      
+
         //TODO 此API需處理對應前端返回的相關數據
         [ProducesDefaultResponseType]
         [Authorize(Roles = "IES")]
         [HttpPost("get-school-info")]
         public async Task<IActionResult> GetSchoolInfo(JsonElement request)
         {
+            string domain = HttpContext?.Request?.Host.Host;
             try
             {
                 if (!request.TryGetProperty("id_token", out JsonElement id_token)) return BadRequest();
@@ -327,10 +356,11 @@ namespace TEAMModelOS.Controllers
                 if (teacher.schools.IsNotEmpty())
                 {
                     teacher.schools.ForEach(x => {
-                        if (!string.IsNullOrEmpty(x.areaId)) {
+                        if (!string.IsNullOrEmpty(x.areaId))
+                        {
                             areaIds.Add(x.areaId);
                         }
-                        
+
                     });
                 }
                 List<Area> areasDbs = new List<Area>();
@@ -347,10 +377,11 @@ namespace TEAMModelOS.Controllers
                         areaSettings.Add(item);
                     }
                 }
-                if (teacher.areas.IsNotEmpty()) {
+                if (teacher.areas.IsNotEmpty())
+                {
                     foreach (var areat in teacher.areas)
                     {
-                         
+
                         Area area = areasDbs.Find(x => x.id.Equals(areat.areaId));
                         AreaSetting setting = null;
                         if (area != null)
@@ -367,7 +398,7 @@ namespace TEAMModelOS.Controllers
                         //{
                         //    setting.accessConfig = null;
                         //}
-                        areas.Add(new AreaDto { areaId = area.id, name = area.name, standard = area.standard, standardName = area.standardName, setting= setting, access = access });
+                        areas.Add(new AreaDto { areaId = area.id, name = area.name, standard = area.standard, standardName = area.standardName, setting = setting, access = access });
                     }
                 }
                 if (school_code.Equals(teacher.defaultSchool) && teacher.schools.IsNotEmpty() && !teacher.schools.Select(x => x.schoolId).Contains(school_code))
@@ -427,52 +458,57 @@ namespace TEAMModelOS.Controllers
                             code = $"ItemCond-{school_code}",
                             ttl = -1,
                         };
-                        try {
+                        try
+                        {
                             await client.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<ItemCond>(itemCond, new PartitionKey($"ItemCond-{school_code}"));
-                        } catch (CosmosException ex) when(ex.Status==409) {
+                        }
+                        catch (CosmosException ex) when (ex.Status == 409)
+                        {
                             continue;
                         }
                     }
                 }
                 string currAreaId = "";
                 dynamic currArea = new ExpandoObject();
-                if (!string.IsNullOrEmpty(school_base.areaId)) {
+                if (!string.IsNullOrEmpty(school_base.areaId))
+                {
                     try
                     {
                         Area area = areasDbs.Find(x => x.id.Equals(school_base.areaId));
                         AreaSetting setting = null;
-                        if (area != null) {
+                        if (area != null)
+                        {
                             //setting =await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<AreaSetting>(school_base.areaId, new PartitionKey("AreaSetting"));
                             setting = areaSettings.Find(x => x.id.Equals(school_base.areaId));
                         }
-                        
+
                         int access = 0;
                         AccessConfig accessConfig = null;
                         if (setting != null && !string.IsNullOrWhiteSpace(setting.accessConfig))
                         {
                             access = 1;
-                            accessConfig =setting.accessConfig.ToObject<AccessConfig>();
+                            accessConfig = setting.accessConfig.ToObject<AccessConfig>();
                         }
                         //if (setting!=null&& !string.IsNullOrEmpty(setting.accessConfig)) {
                         //    setting.accessConfig = null;
                         //}
-                        currArea = new   
+                        currArea = new
                         {
-                            areaId = area?.id, 
-                            name = area?.name, 
-                            standard = area?.standard, 
-                            standardName = area?.standardName, 
-                            setting = setting, 
+                            areaId = area?.id,
+                            name = area?.name,
+                            standard = area?.standard,
+                            standardName = area?.standardName,
+                            setting = setting,
                             access = access,
                             //submitType=accessConfig?.submitType,
-                            homeworkType = accessConfig!=null && accessConfig.homeworkType.IsNotEmpty()?accessConfig.homeworkType:new List<string> { "pdf"}, 
+                            homeworkType = accessConfig != null && accessConfig.homeworkType.IsNotEmpty() ? accessConfig.homeworkType : new List<string> { "pdf" },
                         };
                         currAreaId = area?.id;
                     }
                     catch (CosmosException)
                     {
                         //数据库捞不到数据
-                        
+
                     }
                 }
                 if (areas.Count > 0)
@@ -480,12 +516,12 @@ namespace TEAMModelOS.Controllers
                     roles.Add("area");
                 }
                 //TODO JJ,更新Token时,在取得学校资讯时,没有传入schoolId
-                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);
+                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);
 
                 //取得班级
                 List<object> school_classes = new List<object>();
                 await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator
-                    (queryText: $"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, ARRAY_LENGTH(c.students) AS studCount FROM c", 
+                    (queryText: $"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, ARRAY_LENGTH(c.students) AS studCount FROM c",
                     requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Class-{school_code}") }))
                 {
                     var jsonc = await JsonDocument.ParseAsync(item.ContentStream);
@@ -518,10 +554,12 @@ namespace TEAMModelOS.Controllers
                 List<SchoolProductSumData> serials = new List<SchoolProductSumData>();
                 List<SchoolProductSumData> services = new List<SchoolProductSumData>();
                 Azure.Response productSumResponse = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(school_code, new PartitionKey("ProductSum"));
-                if (productSumResponse.Status == 200) {
-                    var doc= JsonDocument.Parse(productSumResponse.Content);
-                    if (doc.RootElement.TryGetProperty("serial", out JsonElement serial)) {
-                        serials = serial.ToObject<List<SchoolProductSumData>>();                  
+                if (productSumResponse.Status == 200)
+                {
+                    var doc = JsonDocument.Parse(productSumResponse.Content);
+                    if (doc.RootElement.TryGetProperty("serial", out JsonElement serial))
+                    {
+                        serials = serial.ToObject<List<SchoolProductSumData>>();
                     }
                     if (doc.RootElement.TryGetProperty("service", out JsonElement service))
                     {
@@ -529,7 +567,7 @@ namespace TEAMModelOS.Controllers
                     }
                 }
                 //校本課綱 [式樣未定 先不取]
-                
+
                 //取得School Blob 容器位置及SAS
                 string school_code_blob = school_code.ToLower();
                 var container = _azureStorage.GetBlobContainerClient(school_code_blob);
@@ -539,21 +577,63 @@ namespace TEAMModelOS.Controllers
                 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);
                 areas.ForEach(x => { { if (x.setting != null) { x.setting.accessConfig = x.setting.accessConfig; } } });
 
-                int lessonLimit =teacher.lessonLimit;
+                int lessonLimit = teacher.lessonLimit;
                 if (teacher.lessonLimit == 0)
                 {
                     //未设置的的采用系统设置的默认值30
                     lessonLimit = Constant.private_lesson_limit;
                 }
-                return Ok(new { auth_token, blob_uri, blob_sas, school_base, 
-                    school_courses,  school_classes, school_rooms, size, 
-                    osblob_uri, osblob_sas, status = 200, areas , currArea , 
+                var table = _azureStorage.GetCloudTableClient().GetTableReference("IESOAuth");
+                List<string> Codes = new List<string>();
+                if (!string.IsNullOrWhiteSpace(id))
+                {
+                    Codes.Add($" Code {QueryComparisons.Equal} '{id}' ");
+                }
+                if (!string.IsNullOrWhiteSpace(school_code))
+                {
+                    Codes.Add($" Code {QueryComparisons.Equal} '{school_code}' ");
+                }
+                if (!string.IsNullOrWhiteSpace(currAreaId))
+                {
+                    Codes.Add($" Code {QueryComparisons.Equal} '{currAreaId}' ");
+                }
+                string qurey = $"PartitionKey {QueryComparisons.Equal} 'OAuthShow' and Domain {QueryComparisons.Equal} '{domain}' and ( { string.Join(" or ", Codes)} )  ";
+                var result = await table.ExecuteQuerySegmentedAsync(new TableQuery<OAuthShow>().Where(qurey), null);
+                List<OAuthShow> shows = result.Results;
+                List<OAuthShow> schoolShow = new List<OAuthShow>();
+                var schoolShows = shows?.Where(y => !y.Scope.Equals("private"));
+                if (schoolShows.Any())
+                {
+                    schoolShows.ToList().ForEach(y => { y.Scope = "school"; y.Code = school_code; });
+                    schoolShows.GroupBy(x => $"{x.Type}{x.Scope}").Select(s => new { key = s.Key, list = s.ToList() }).ToList().ForEach(z => {
+                        schoolShow.Add(z.list.First());
+                    });
+                }
+                return Ok(new
+                {
+                    privateShows = shows?.FindAll(x => x.Scope.Equals("private")).Select(x => new { x.Type, x.Status, x.Scope, x.Code }),
+                    schoolShows = schoolShow.Select(x => new { x.Type, x.Status, x.Scope, x.Code }),
+                    auth_token,
+                    blob_uri,
+                    blob_sas,
+                    school_base,
+                    school_courses,
+                    school_classes,
+                    school_rooms,
+                    size,
+                    osblob_uri,
+                    osblob_sas,
+                    status = 200,
+                    areas,
+                    currArea,
                     lessonLimit,
                     teacher.lessonShow,
-                    productSum = new {
+                    productSum = new
+                    {
                         serial = serials,
-                        service= services
-                    } });
+                        service = services
+                    }
+                });
             }
             catch (CosmosException ex)
             {
@@ -730,7 +810,7 @@ namespace TEAMModelOS.Controllers
                 else
                 {
                     long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
-                    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 });
+                    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 });
                 }
                 if (grant_type.GetString().Equals("leave") || grant_type.GetString().Equals("cancel"))
                 {
@@ -767,7 +847,7 @@ namespace TEAMModelOS.Controllers
                     if (response.Status == 200)
                     {
                         teacherImport = JsonDocument.Parse(response.Content).RootElement.Deserialize<TeacherImport>();
-                        var tchs = teacherImport?.teachers?.RemoveAll(x => !string.IsNullOrWhiteSpace(x.id)  && x.id.Equals(id));
+                        var tchs = teacherImport?.teachers?.RemoveAll(x => !string.IsNullOrWhiteSpace(x.id) && x.id.Equals(id));
                         await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(teacherImport, $"{school_code}", new PartitionKey("TeacherImport"));
                     }
 
@@ -828,17 +908,18 @@ namespace TEAMModelOS.Controllers
                     }
                     Azure.Response responseImport = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemStreamAsync($"{school_code}", new PartitionKey("TeacherImport"));
                     TeacherImport teacherImport = null;
-                    if ($"{grant_type}".Equals("request")) {
-                       
+                    if ($"{grant_type}".Equals("request"))
+                    {
+
                         if (responseImport.Status == 200)
                         {
                             teacherImport = JsonDocument.Parse(responseImport.Content).RootElement.Deserialize<TeacherImport>();
-                            var tchs = teacherImport?.teachers?.FindAll(x =>  string.IsNullOrWhiteSpace(x.iname) && x.iname.Equals($"{name}") && string.IsNullOrWhiteSpace(x.id));
+                            var tchs = teacherImport?.teachers?.FindAll(x => string.IsNullOrWhiteSpace(x.iname) && x.iname.Equals($"{name}") && string.IsNullOrWhiteSpace(x.id));
                             if (tchs.IsNotEmpty())
                             {
-                                var tch  = tchs[0];
-                                string ujson = null; 
-                                var content = new StringContent(new List<string> { $"{id}"}.ToJsonString(), Encoding.UTF8, "application/json");
+                                var tch = tchs[0];
+                                string ujson = null;
+                                var content = new StringContent(new List<string> { $"{id}" }.ToJsonString(), Encoding.UTF8, "application/json");
                                 ujson = await _coreAPIHttpService.GetUserInfos(content);
                                 List<CoreUser> coreUsers = new List<CoreUser>();
                                 if (!string.IsNullOrWhiteSpace(ujson))
@@ -866,17 +947,18 @@ namespace TEAMModelOS.Controllers
                         {
                             teacherImport = JsonDocument.Parse(responseImport.Content).RootElement.Deserialize<TeacherImport>();
                             teacherImport?.teachers.ForEach(x => {
-                                if (x.id.Equals(teacher.id)) { 
-                                    x.name=teacher.name;
+                                if (x.id.Equals(teacher.id))
+                                {
+                                    x.name = teacher.name;
                                     x.status = "join";
-                                    x.time=DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
-                                    x.picture=teacher.picture;
+                                    x.time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                                    x.picture = teacher.picture;
                                 }
                             });
                             await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(teacherImport, $"{school_code}", new PartitionKey("TeacherImport"));
                             await TmdUserService.JoinSchool(client, teacher.id, teacher.picture, teacher.name, school.schoolId, school.name);
                         }
-                            
+
                     }
                     Notification notification = null;
 

+ 35 - 32
TEAMModelOS/Controllers/Third/OAuth2Controller.cs

@@ -37,8 +37,8 @@ using Microsoft.Azure.Cosmos.Table;
 
 namespace TEAMModelOS.Controllers.Third
 {
-    
-    
+
+
     // <summary>
     ///  标准OAuth2
     /// </summary>
@@ -101,40 +101,43 @@ namespace TEAMModelOS.Controllers.Third
         public async Task<IActionResult> CheckBind(JsonElement json)
         {
             string domain = HttpContext?.Request?.Host.Host;
-            var (tmdid, _, _, school,area,keyData) = HttpContext.GetAuthTokenKey();
+            var (tmdid, _, _, school, area, keyData) = HttpContext.GetAuthTokenKey();
             var table = _azureStorage.GetCloudTableClient().GetTableReference("IESOAuth");
 
-            
-            List<string> RowKeys = new List<string>();
-            if (!string.IsNullOrWhiteSpace(tmdid)) {
-                RowKeys.Add($" Code {QueryComparisons.Equal} '{tmdid}' ");
-            }
-            if (!string.IsNullOrWhiteSpace(school))
-            {
-                RowKeys.Add($" Code {QueryComparisons.Equal} '{school}' ");
-            }
-            if (!string.IsNullOrWhiteSpace(area))
-            {
-                RowKeys.Add($" Code {QueryComparisons.Equal} '{area}' ");
-            }
-         
-            string qurey = $"PartitionKey {QueryComparisons.Equal} 'OAuthShow'  and ( { string.Join(" or ", RowKeys)} )  ";
 
-            var result=  await table.ExecuteQuerySegmentedAsync(new TableQuery<OAuthShow>().Where(qurey),null) ;
-            List<OAuthShow> shows = result.Results;
-            List<OAuthShow> schoolShow = new List<OAuthShow>();
-            var schoolShows = shows?.Where(y => !y.Scope.Equals("private"));
-            if (schoolShows.Any()) {
-                schoolShows.ToList().ForEach(y => { y.Scope = "school";y.Code = school; });
-                schoolShows.GroupBy(x => $"{x.Type}{x.Scope}").Select(s => new { key = s.Key, list = s.ToList() }).ToList().ForEach(z => {
-                    schoolShow.Add(z.list.First());
-                });
-            }
-            List<OAuthUser> authUsers = await table.FindListByDict<OAuthUser>(new Dictionary<string, object>() { { "RowKey", tmdid },{ "Domain" ,domain} });
-            return Ok(new { 
+            //List<string> Codes = new List<string>();
+            //if (!string.IsNullOrWhiteSpace(tmdid))
+            //{
+            //    Codes.Add($" Code {QueryComparisons.Equal} '{tmdid}' ");
+            //}
+            //if (!string.IsNullOrWhiteSpace(school))
+            //{
+            //    Codes.Add($" Code {QueryComparisons.Equal} '{school}' ");
+            //}
+            //if (!string.IsNullOrWhiteSpace(area))
+            //{
+            //    Codes.Add($" Code {QueryComparisons.Equal} '{area}' ");
+            //}
+
+            //string qurey = $"PartitionKey {QueryComparisons.Equal} 'OAuthShow' and Domain {QueryComparisons.Equal} '{domain}' and ( { string.Join(" or ", Codes)} )  ";
+
+            //var result = await table.ExecuteQuerySegmentedAsync(new TableQuery<OAuthShow>().Where(qurey), null);
+            //List<OAuthShow> shows = result.Results;
+            //List<OAuthShow> schoolShow = new List<OAuthShow>();
+            //var schoolShows = shows?.Where(y => !y.Scope.Equals("private"));
+            //if (schoolShows.Any())
+            //{
+            //    schoolShows.ToList().ForEach(y => { y.Scope = "school"; y.Code = school; });
+            //    schoolShows.GroupBy(x => $"{x.Type}{x.Scope}").Select(s => new { key = s.Key, list = s.ToList() }).ToList().ForEach(z => {
+            //        schoolShow.Add(z.list.First());
+            //    });
+            //}
+            List<OAuthUser> authUsers = await table.FindListByDict<OAuthUser>(new Dictionary<string, object>() { { "RowKey", tmdid }, { "Domain", domain } });
+            return Ok(new
+            {
                 auth = authUsers.Select(x => new { type = x.Type, tmdid = x.RowKey, time = x.Time }),
-                privateShows = shows?.FindAll(x=>x.Scope.Equals("private")).Select(x=>new { x.Type,x.Status,x.Scope,x.Code}),
-                schoolShows= schoolShow.Select(x => new { x.Type, x.Status, x.Scope, x.Code })
+                //privateShows = shows?.FindAll(x => x.Scope.Equals("private")).Select(x => new { x.Type, x.Status, x.Scope, x.Code }),
+                //schoolShows = schoolShow.Select(x => new { x.Type, x.Status, x.Scope, x.Code })
             });
         }
     }

+ 7 - 5
TEAMModelOS/Controllers/Third/Sc/ScController.cs

@@ -100,7 +100,7 @@ namespace TEAMModelOS.Controllers
                 return Ok();
             }
         }
-       
+
         /// <summary>
         /// 检查醍摩豆id存在多个学校的情况
         /// </summary>
@@ -316,15 +316,16 @@ namespace TEAMModelOS.Controllers
                 jwt.Payload.TryGetValue("picture", out object picture);
                 ScSSOData scsso = HttpUtility.UrlDecode(sso.param, Encoding.UTF8).ToObject<ScSSOData>();
                 var table = _azureStorage.GetCloudTableClient().GetTableReference("ScYxpt");
-                List<ScTeacher> scTeachers=  await  table.FindListByDict<ScTeacher>(new Dictionary<string, object> { { Constant.PartitionKey, "ScTeacher" }, {"tmdid",id } });
-                if (scTeachers.Count > 0 && !string.IsNullOrWhiteSpace(scTeachers[0].RowKey) && !scTeachers[0].RowKey.Equals(scsso.Pxid)) {
+                List<ScTeacher> scTeachers = await table.FindListByDict<ScTeacher>(new Dictionary<string, object> { { Constant.PartitionKey, "ScTeacher" }, { "tmdid", id } });
+                if (scTeachers.Count > 0 && !string.IsNullOrWhiteSpace(scTeachers[0].RowKey) && !scTeachers[0].RowKey.Equals(scsso.Pxid))
+                {
                     return Ok(new
                     {
                         location = _option.Location,
                         //账号已被别的醍摩豆id绑定
                         status = 3,
                         tmdid = $"{id}",
-                        name =name.Equals(scTeachers[0].TeacherName) ?$"{name}":$"{name}({scTeachers[0].TeacherName})",
+                        name = name.Equals(scTeachers[0].TeacherName) ? $"{name}" : $"{name}({scTeachers[0].TeacherName})",
                         tid = scsso.tid
                     });
                 }
@@ -475,7 +476,8 @@ namespace TEAMModelOS.Controllers
         {
             string HostName = HttpContext.GetHostName();
 
-            if (!string.IsNullOrWhiteSpace(_option.HostName)) {
+            if (!string.IsNullOrWhiteSpace(_option.HostName))
+            {
                 HostName = _option.HostName;
             }
             if (path.Equals("jinniu"))

+ 149 - 210
TEAMModelOS/Controllers/XTest/TestController.cs

@@ -53,7 +53,7 @@ namespace TEAMModelOS.Controllers
         private readonly Option _option;
         private readonly IPSearcher _searcher;
         public IConfiguration _configuration { get; set; }
-        public TestController(IPSearcher searcher,IOptionsSnapshot<Option> option, CoreAPIHttpService coreAPIHttpService, HttpClient httpClient,IWebHostEnvironment environment, AzureCosmosFactory azureCosmos, AzureRedisFactory azureRedis, AzureStorageFactory azureStorage, IConfiguration configuration, AzureServiceBusFactory serviceBus, DingDing dingDing)
+        public TestController(IPSearcher searcher, IOptionsSnapshot<Option> option, CoreAPIHttpService coreAPIHttpService, HttpClient httpClient, IWebHostEnvironment environment, AzureCosmosFactory azureCosmos, AzureRedisFactory azureRedis, AzureStorageFactory azureStorage, IConfiguration configuration, AzureServiceBusFactory serviceBus, DingDing dingDing)
         {
             _azureCosmos = azureCosmos;
             _azureRedis = azureRedis;
@@ -61,13 +61,13 @@ namespace TEAMModelOS.Controllers
             _dingDing = dingDing;
             _serviceBus = serviceBus; _configuration = configuration;
             _environment = environment;
-            _httpClient= httpClient;
-            _option= option.Value;
-            _coreAPIHttpService= coreAPIHttpService;
-            _searcher= searcher;
+            _httpClient = httpClient;
+            _option = option.Value;
+            _coreAPIHttpService = coreAPIHttpService;
+            _searcher = searcher;
         }
-         
-      
+
+
         /*
 [
 {"method":"台北市","params":{"CountryId":"TW","CityId":"30"}},1
@@ -101,13 +101,14 @@ namespace TEAMModelOS.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("get-schools")]
-        public async Task<IActionResult> GetSchools(JsonElement json) {
+        public async Task<IActionResult> GetSchools(JsonElement json)
+        {
 
             string msg = "{\"standard\":\"standard3\",\"tmdids\":[\"1635136038\"],\"school\":\"pbjyey\",\"update\":[\"TeacherAbility\"],\"statistics\":0}";
             try
             {
                 TeacherTrainChange change = msg.ToObject<TeacherTrainChange>();
-                
+
                 var client = _azureCosmos.GetCosmosClient();
                 string insql = $"where c.id in ({string.Join(",", change.tmdids.Select(x => $"'{x}'"))})";
                 string selsql = $"select value(c) from c {insql} ";
@@ -285,10 +286,12 @@ namespace TEAMModelOS.Controllers
             return Ok();
         }
 
-        public   async Task<(List<SchoolInfo> schoolInfos,List<string> nodata)> GetSchoolAsync(List<string> regions) {
-            List < SchoolInfo > schools= new List<SchoolInfo>();
+        public async Task<(List<SchoolInfo> schoolInfos, List<string> nodata)> GetSchoolAsync(List<string> regions)
+        {
+            List<SchoolInfo> schools = new List<SchoolInfo>();
             List<string> nodata = new List<string>();
-            foreach (var region in regions) {
+            foreach (var region in regions)
+            {
                 Dictionary<string, object> data = new Dictionary<string, object>();
                 data.Add("method", "api/School/getSchool");
                 data.Add("params", new { CountryId = "CN", CityId = region });
@@ -296,9 +299,10 @@ namespace TEAMModelOS.Controllers
                 if (responseMessage.StatusCode == HttpStatusCode.OK)
                 {
                     string Content = await responseMessage.Content.ReadAsStringAsync();
-                    try {
+                    try
+                    {
                         Content.ToObject<JsonElement>().TryGetProperty("result", out JsonElement content);
-                        if (content.ValueKind.Equals(JsonValueKind.Object) &&  content.TryGetProperty("data", out JsonElement _data))
+                        if (content.ValueKind.Equals(JsonValueKind.Object) && content.TryGetProperty("data", out JsonElement _data))
                         {
                             if (_data.ValueKind.Equals(JsonValueKind.Array))
                             {
@@ -308,21 +312,27 @@ namespace TEAMModelOS.Controllers
                                     schools.AddRange(infos.Where(x => x.name != null && x.cityName != null).ToList());
                                 }
                             }
-                            else {
+                            else
+                            {
                                 nodata.Add(data.ToJsonString());
                                 continue;
                             }
                         }
-                        else { nodata.Add(data.ToJsonString()); 
-                            continue; }
-                    } catch (Exception ex) {
+                        else
+                        {
+                            nodata.Add(data.ToJsonString());
+                            continue;
+                        }
+                    }
+                    catch (Exception ex)
+                    {
                         nodata.Add(data.ToJsonString());
-                        throw new Exception(ex.Message,ex.InnerException);
+                        throw new Exception(ex.Message, ex.InnerException);
                     }
                 }
             }
-            return (schools, nodata); 
-        
+            return (schools, nodata);
+
         }
         public class SchoolInfo
         {
@@ -349,7 +359,7 @@ namespace TEAMModelOS.Controllers
         public async Task<IActionResult> GenerateSchoolCodes(JsonElement json)
         {
             List<SchoolData> schoolss = json.GetProperty("schools").ToObject<List<SchoolData>>();
-            dynamic data = await  SchoolService.GenerateSchoolCode(schoolss, _dingDing, _environment);
+            dynamic data = await SchoolService.GenerateSchoolCode(schoolss, _dingDing, _environment);
             return Ok(data);
         }
 
@@ -383,7 +393,7 @@ namespace TEAMModelOS.Controllers
                 }
                 await _azureRedis.GetRedisClient(8).HashSetAsync($"Blob:Record", new RedisValue($"{name}"), new RedisValue($"{blobsize}"));
 
-                await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,Blob() 容器:{name}使用:{root},文件分类:{list.ToJsonString()}",GroupNames.成都开发測試群組);
+                await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,Blob() 容器:{name}使用:{root},文件分类:{list.ToJsonString()}", GroupNames.成都开发測試群組);
                 return Ok(list);
             }
             else
@@ -590,15 +600,18 @@ namespace TEAMModelOS.Controllers
         public async Task<IActionResult> DownloadContentItem(JsonElement request)
         {
             ItemBlob itemBlob = null;
-            try {
+            try
+            {
                 BlobDownloadInfo blobDownloadResult = await _azureStorage.GetBlobContainerClient($"hbcn").GetBlobClient($"/item/12b865c9-a223-278a-2be1-e336b9ead99e/12b865c9-a223-278a-2be1-e336b9ead99e.json")
                     .DownloadAsync();
                 if (blobDownloadResult != null)
                 {
                     var json = JsonDocument.Parse(blobDownloadResult.Content);
-                     itemBlob = json.RootElement.ToObject<ItemBlob>();
+                    itemBlob = json.RootElement.ToObject<ItemBlob>();
                 }
-            } catch (Exception ex) {
+            }
+            catch (Exception ex)
+            {
                 itemBlob = null;
             }
             return Ok(new { itemBlob });
@@ -615,11 +628,11 @@ namespace TEAMModelOS.Controllers
         [HttpPost("get-bind-data")]
         public async Task<IActionResult> GetData(JsonElement request)
         {
-           
-            var areaId =request.GetProperty("areaId");
+
+            var areaId = request.GetProperty("areaId");
             var table = _azureStorage.GetCloudTableClient().GetTableReference("ScYxpt");
             List<ScTeacher> teachers = await table.FindListByDict<ScTeacher>(new Dictionary<string, object> { { "PartitionKey", "ScTeacher" }, { "areaId", $"{areaId}" } });
-            return Ok(teachers.Select(x =>new  {x.areaId,x.PXID,x.TID,x.TeacherName,x.tmdid,x.SchoolName,x.DisName }));
+            return Ok(teachers.Select(x => new { x.areaId, x.PXID, x.TID, x.TeacherName, x.tmdid, x.SchoolName, x.DisName }));
         }
 
         /// 删除
@@ -633,13 +646,13 @@ namespace TEAMModelOS.Controllers
         {
 
             BlobDownloadResult Recording = await _azureStorage.GetBlobContainerClient("1595321354").GetBlobClient($"records/271528531841781760/Record/.Recording.json").DownloadContentAsync();
-            var   json =   Recording.Content.ToString();
+            var json = Recording.Content.ToString();
             var jsonByte = Encoding.UTF8.GetBytes(json);
             Stream stream = new MemoryStream(jsonByte);
-            var doc= JsonDocument.Parse(stream);
+            var doc = JsonDocument.Parse(stream);
             School school = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>("hbcn", new PartitionKey("Base"));
-            _=  _azureStorage.SaveLog("find-school", school.ToJsonString(),httpContext:HttpContext,dingDing:_dingDing,scope:"school");
-            return Ok(new { doc, school,  });
+            _ = _azureStorage.SaveLog("find-school", school.ToJsonString(), httpContext: HttpContext, dingDing: _dingDing, scope: "school");
+            return Ok(new { doc, school, });
         }
 
         /// <summary>
@@ -654,12 +667,15 @@ namespace TEAMModelOS.Controllers
         {
 
 
-            try {
+            try
+            {
                 BlobDownloadResult baseblobDownload = await _azureStorage.GetBlobContainerClient("habook").GetBlobClient($"/records/299813002894381056/IES/Base.json").DownloadContentAsync();
                 LessonBase lessonBase = baseblobDownload.Content.ToObjectFromJson<LessonBase>();
                 return Ok(lessonBase);
 
-            } catch (RequestFailedException ex)when(ex.Status==404) {
+            }
+            catch (RequestFailedException ex) when (ex.Status == 404)
+            {
                 return BadRequest("文件不存在!");
             }
             LessonBase lessonBases = request.ToObject<LessonBase>();
@@ -687,23 +703,29 @@ namespace TEAMModelOS.Controllers
         {
             string sql = $"select c.id,c.name ,b.schoolId as code   from c join b in c.schools where b.areaId='9ae614ba-0771-4502-a56e-0537bc5207c3'";
             List<IdNameCode> codes = new List<IdNameCode>();
-            await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetItemQueryIterator<IdNameCode>(sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base") })) {
+            await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetItemQueryIterator<IdNameCode>(sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base") }))
+            {
                 codes.Add(item);
             }
             List<dynamic> data = new List<dynamic>(); ;
-            foreach (IdNameCode code in codes) {
-                try {
+            foreach (IdNameCode code in codes)
+            {
+                try
+                {
                     TeacherTrain train = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemAsync<TeacherTrain>(code.id, new PartitionKey($"TeacherTrain-{code.code}"));
-                    data.Add(new { code.id,code.name,code.code, train.totalTime, train.onlineTime, train.classTime, train.offlineTime });
-                } catch (Exception ex) {
-                    data.Add(new { code.id, code.name, code.code, totalTime=0, onlineTime=0,classTime=0, offlineTime=0 });
+                    data.Add(new { code.id, code.name, code.code, train.totalTime, train.onlineTime, train.classTime, train.offlineTime });
+                }
+                catch (Exception ex)
+                {
+                    data.Add(new { code.id, code.name, code.code, totalTime = 0, onlineTime = 0, classTime = 0, offlineTime = 0 });
                 }
             }
             return Ok(new { data });
         }
 
         [HttpPost("test-scteacher-dn")]
-        public async Task<IActionResult> TestScteacherDn(JsonElement json) {
+        public async Task<IActionResult> TestScteacherDn(JsonElement json)
+        {
             var table = _azureStorage.GetCloudTableClient().GetTableReference("ScYxpt");
             string sqls = "select distinct value(c.id )from c where c.code='Base' and  IS_DEFINED(c.finalScore)=true  ";
             //https://teammodelos.blob.core.chinacloudapi.cn/teammodelos
@@ -711,48 +733,52 @@ namespace TEAMModelOS.Controllers
             List<ScTeacher> teachers = await table.FindListByDict<ScTeacher>(new Dictionary<string, object>() { { "PartitionKey", "ScTeacher" }, { "areaId", "870a5a6b-1ab3-461a-bdeb-baec19780ddb" } });
             List<string> ids = new List<string>();
             await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher)
-                .GetItemQueryIterator<string>(sqls, requestOptions: new QueryRequestOptions {PartitionKey= new PartitionKey("Base") }))
+                .GetItemQueryIterator<string>(sqls, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base") }))
             {
                 ids.Add(item);
             }
             long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
             List<string> erorr = new List<string>();
             List<ScTeacher> teachersUp = new List<ScTeacher>();
-            foreach (var id in ids) {
-                try {
+            foreach (var id in ids)
+            {
+                try
+                {
                     BlobDownloadResult baseblobDownload = await _azureStorage.GetBlobContainerClient("teammodelos").GetBlobClient($"/yxpt/jinniu/scbind/{id}.json").DownloadContentAsync();
                     ScBindData scBindData = baseblobDownload.Content.ToObjectFromJson<ScBindData>();
-                    var tcd=  teachers.Find(x => x.RowKey.Equals(scBindData.pxid));
+                    var tcd = teachers.Find(x => x.RowKey.Equals(scBindData.pxid));
                     if (tcd != null)
                     {
                         Teacher teacher = new Teacher
                         {
                             createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
-                            pk ="Base",
+                            pk = "Base",
                             code = "Base",
                             id = id,
                             name = scBindData.username,
                             size = 2,
                             defaultSchool = tcd.schoolCode,
                             schools = new List<TeacherSchool> {
-                                new TeacherSchool 
+                                new TeacherSchool
                                 {
                                     schoolId = tcd.schoolCode, status = "join", time = now, name = scBindData.sn, areaId = tcd.areaId
                                 }
                             },
-                            binds = new List<ThirdBind> { 
-                                new ThirdBind 
-                                { 
+                            binds = new List<ThirdBind> {
+                                new ThirdBind
+                                {
                                     type= "scsyxpt",userid=scBindData.userid,username= scBindData.username,account=scBindData.account,data=new List<string>{ scBindData.ToJsonString()}
                                 }
                             }
                         };
-                        await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS,Constant.Teacher).UpsertItemAsync(teacher,new PartitionKey("Base"));
+                        await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).UpsertItemAsync(teacher, new PartitionKey("Base"));
                         tcd.tmdid = id;
                         teachersUp.Add(tcd);
                     }
-                    
-                } catch (Exception ) {
+
+                }
+                catch (Exception)
+                {
                     erorr.Add(id);
                 }
             }
@@ -760,10 +786,11 @@ namespace TEAMModelOS.Controllers
             return Ok();
         }
         [HttpPost("fix-jinniupujiang-teacher-videotime")]
-        public async Task<IActionResult> GetScteacher(JsonElement json) {
+        public async Task<IActionResult> GetScteacher(JsonElement json)
+        {
             if (!json.TryGetProperty("areaId", out JsonElement _areaId)) { return BadRequest(); }
-            Area area= await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Normal).ReadItemAsync<Area>($"{_areaId}", new PartitionKey("Base-Area"));
-            AreaSetting  setting = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Normal).ReadItemAsync<AreaSetting>($"{_areaId}", new PartitionKey("AreaSetting"));
+            Area area = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Normal).ReadItemAsync<Area>($"{_areaId}", new PartitionKey("Base-Area"));
+            AreaSetting setting = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Normal).ReadItemAsync<AreaSetting>($"{_areaId}", new PartitionKey("AreaSetting"));
             List<string> teachers = new List<string>();
             //获取这个区的教师
             string schoolSql = $"SELECT value  c.id FROM c join a in c.schools where a.areaId='{_areaId}' and c.code='Base' ";
@@ -773,12 +800,13 @@ namespace TEAMModelOS.Controllers
                 teachers.Add(item);
             }
             //获取这些老师的研修记录
-            string tr =$"SELECT distinct value(c) FROM c join a in c.currency.teacherAilities  where c.id in ({string.Join(",", teachers.Select(x=>$"'{x}'"))}) and  c.pk='TeacherTrain' and a.videoTime<300  ";
+            string tr = $"SELECT distinct value(c) FROM c join a in c.currency.teacherAilities  where c.id in ({string.Join(",", teachers.Select(x => $"'{x}'"))}) and  c.pk='TeacherTrain' and a.videoTime<300  ";
             List<TeacherTrain> teacherTrains = new List<TeacherTrain>();
             await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher)
-                .GetItemQueryIterator<TeacherTrain>(tr, requestOptions: new QueryRequestOptions {  }))
+                .GetItemQueryIterator<TeacherTrain>(tr, requestOptions: new QueryRequestOptions { }))
             {
-                if (!item.tmdid.Equals("1528783259") || !item.tmdid.Equals("1530606136")  ) {
+                if (!item.tmdid.Equals("1528783259") || !item.tmdid.Equals("1530606136"))
+                {
                     teacherTrains.Add(item);
                 }
             }
@@ -791,7 +819,7 @@ namespace TEAMModelOS.Controllers
                 nodeIdsDB.Add(y);
             }
             List<AbilitySub> abilitySubs = new List<AbilitySub>();
-            List< TeacherVideoTime > teacherVideoTimes= new List<TeacherVideoTime>();
+            List<TeacherVideoTime> teacherVideoTimes = new List<TeacherVideoTime>();
             string ids = teacherTrains.Select(x => x.id).ToJsonString();
             string sqls = $" select value(c) from c  where   c.code='AbilityTask-{area.standard}'";
             List<AbilityTask> abilityTasks = new List<AbilityTask>();
@@ -807,25 +835,28 @@ namespace TEAMModelOS.Controllers
                 if (item.currency.teacherAilities.Count() > 3)
                 {
                     //如果选择了大于三个能力点的教师,则优先获取上传了认证材料的的能力点,
-                    var uploadHas=  item.currency.teacherAilities.FindAll(x => x.uploadHas == 1  && x.videoTime<300);
-                    if (uploadHas.Any()) {
+                    var uploadHas = item.currency.teacherAilities.FindAll(x => x.uploadHas == 1 && x.videoTime < 300);
+                    if (uploadHas.Any())
+                    {
                         teacherAbility.AddRange(uploadHas);
                     }
 
-                    if (teacherAbility.Count < 3) {
+                    if (teacherAbility.Count < 3)
+                    {
                         // 如果仍然未满足数量。则再去获取 没有上传认证材料,但是又有学习时间长的能力点。
-                        var hasVideoTime = item.currency.teacherAilities.FindAll(x => x.uploadHas != 1 && x.videoTime < 300).OrderByDescending(o=>o.videoTime);
+                        var hasVideoTime = item.currency.teacherAilities.FindAll(x => x.uploadHas != 1 && x.videoTime < 300).OrderByDescending(o => o.videoTime);
                         var disCount = 3 - teacherAbility.Count;
                         teacherAbility.AddRange(hasVideoTime.Take(disCount));
                     }
                 }
-                else {
-                    teacherAbility.AddRange(item.currency.teacherAilities.Where(ab=>ab.videoTime<300));
+                else
+                {
+                    teacherAbility.AddRange(item.currency.teacherAilities.Where(ab => ab.videoTime < 300));
                 }
                 TeacherFile teacherFile = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemAsync<TeacherFile>(item.id, new PartitionKey($"TeacherFile-{item.code.Replace("TeacherTrain-", "")}"));
                 foreach (var ability in teacherAbility)
                 {
-                    TeacherVideoTime teacherVideoTime = new TeacherVideoTime { code= item.code.Replace("TeacherTrain-", ""), id = item.id, abilityId = ability.id, no = ability.no, train_time = ability.videoTime };
+                    TeacherVideoTime teacherVideoTime = new TeacherVideoTime { code = item.code.Replace("TeacherTrain-", ""), id = item.id, abilityId = ability.id, no = ability.no, train_time = ability.videoTime };
                     double fileview = 0;
                     var filerecord = teacherFile.fileRecords.FindAll(x => x.files.Where(y => y.abilityId.Equals(ability.id)).Count() > 0);
                     filerecord.ForEach(x => {
@@ -871,9 +902,10 @@ namespace TEAMModelOS.Controllers
                     HashSet<string> childIds = new HashSet<string>();
                     foreach (var ps in valuePairs)
                     {
-                        HashSet<string> abilityIds = teacherFile.fileRecords.SelectMany(x => x.files).Select(x => x.abilityId).Where(abid=>abid.Equals(ability.id)).ToHashSet();
+                        HashSet<string> abilityIds = teacherFile.fileRecords.SelectMany(x => x.files).Select(x => x.abilityId).Where(abid => abid.Equals(ability.id)).ToHashSet();
                         double view = 0;
-                        foreach (var abid in abilityIds) {
+                        foreach (var abid in abilityIds)
+                        {
                             var record = teacherFile.fileRecords.FindAll(x => x.files.Where(y => y.abilityId.Equals(abid)).Count() > 0);
                             record.ForEach(x => {
                                 var file = x.files.FindAll(y => y.abilityId.Equals($"{abid}"));
@@ -884,7 +916,7 @@ namespace TEAMModelOS.Controllers
                             });
                         }
                         double minut = view / 60;
-                        teacherVideoTime.after_time= minut;
+                        teacherVideoTime.after_time = minut;
                         if (minut < 300)
                         {
                             var fils = teacherFile.fileRecords.Find(x => x.hash.Equals(ps.Key));
@@ -918,37 +950,45 @@ namespace TEAMModelOS.Controllers
                                 });
                             }
                         }
-                        else { 
+                        else
+                        {
                             break;
                         }
                     }
-                    if (childIds.Any()) {
-                       string code = teacherFile.code.Replace("TeacherFile-", "");
-                        if (!string.IsNullOrWhiteSpace(code)) {
-                            try {
+                    if (childIds.Any())
+                    {
+                        string code = teacherFile.code.Replace("TeacherFile-", "");
+                        if (!string.IsNullOrWhiteSpace(code))
+                        {
+                            try
+                            {
                                 AbilitySub abilitySub = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemAsync<AbilitySub>(ability.id, new PartitionKey($"AbilitySub-{code}-{teacherFile.id}"));
-                                var taskIds= abilitySub.taskRcds.Select(x => x.id);
-                                var notin= childIds.Except(taskIds);
-                                if (notin.Any()) {
-                                    abilitySub.taskRcds.AddRange(notin.Select(x => new AbilityTaskRcd { id=x,done=true}));
+                                var taskIds = abilitySub.taskRcds.Select(x => x.id);
+                                var notin = childIds.Except(taskIds);
+                                if (notin.Any())
+                                {
+                                    abilitySub.taskRcds.AddRange(notin.Select(x => new AbilityTaskRcd { id = x, done = true }));
                                     abilitySubs.Add(abilitySub);
                                 }
-                            } catch (Exception ex) {
+                            }
+                            catch (Exception ex)
+                            {
                             }
                         }
                     }
                     teacherVideoTimes.Add(teacherVideoTime);
                 }
-               // teacherFile = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReplaceItemAsync<TeacherFile>(teacherFile, teacherFile.id, new PartitionKey(teacherFile.code));
-               // item.update.Add(StatisticsService.TeacherAbility);
-               // await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReplaceItemAsync<TeacherTrain>(item, item.id, new PartitionKey(item.code));
+                // teacherFile = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReplaceItemAsync<TeacherFile>(teacherFile, teacherFile.id, new PartitionKey(teacherFile.code));
+                // item.update.Add(StatisticsService.TeacherAbility);
+                // await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReplaceItemAsync<TeacherTrain>(item, item.id, new PartitionKey(item.code));
             }
 
-            var data =  teacherVideoTimes.GroupBy(x => x.code).Select(x=>new { x.Key,count= x.ToList().Count,list =x.ToList()}).OrderByDescending(x=>x.count);
+            var data = teacherVideoTimes.GroupBy(x => x.code).Select(x => new { x.Key, count = x.ToList().Count, list = x.ToList() }).OrderByDescending(x => x.count);
             return Ok(new { data, abilitySubs });
         }
 
-        public class TeacherVideoTime{
+        public class TeacherVideoTime
+        {
             public string code { get; set; }
             public string id { get; set; }
             public string abilityId { get; set; }
@@ -967,7 +1007,8 @@ namespace TEAMModelOS.Controllers
             {
                 idNameCodes.Add(item);
             }
-            foreach (var item in idNameCodes) {
+            foreach (var item in idNameCodes)
+            {
                 try
                 {
                     TeacherTrain teacherTrain = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemAsync<TeacherTrain>(item.id, new PartitionKey($"TeacherTrain-{item.code}"));
@@ -976,162 +1017,60 @@ namespace TEAMModelOS.Controllers
                         teacherTrain.update.Add("TeacherClass");
                         await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReplaceItemAsync<TeacherTrain>(teacherTrain, teacherTrain.id, new PartitionKey($"TeacherTrain-{item.code}"));
                     }
-                } catch (Exception ex) {
+                }
+                catch (Exception ex)
+                {
                     continue;
                 }
             }
-            
+
             return Ok();
         }
 
 
 
-        [HttpPost("fix-teacher-ability-files")]
-        public async Task<IActionResult> TestScteacher(JsonElement json) {
-            if (!json.TryGetProperty("ids", out JsonElement _ids)) return BadRequest();
-            List<string> idss = _ids.Deserialize<List<string>>();
-            if (!idss.Any()) {
-                return BadRequest();
-            }
-            var table = _azureStorage.GetCloudTableClient().GetTableReference("ScYxpt");
+        [HttpPost("delete-error-data")]
+        public async Task<IActionResult> TestScteacher(JsonElement json)
+        {
 
-            List<string> schools = new List<string>();
-            string schoolSql = " select value(c.id) from c where c.areaId='870a5a6b-1ab3-461a-bdeb-baec19780ddb' ";
-            await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetItemQueryIterator<string>(schoolSql, requestOptions: new QueryRequestOptions { PartitionKey=new PartitionKey("Base")}))
-            {
-                schools.Add(item);
-            }
-            List<TeacherFile> teacherFiles = new List<TeacherFile>();
-            string sqls = $"select distinct c.id,c.code from c where c.pk='TeacherFile' and  c.id in ({string.Join(",", idss.Select(x => $"'{x}'"))}) ";
-            List<IdNameCode> ids = new List<IdNameCode>();
-            await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetItemQueryIterator<IdNameCode>(sqls, requestOptions: new QueryRequestOptions {  }))
-            {
-                item.code= item.code.Replace("TeacherFile-", "");
-                if (schools.Contains(item.code)) {
-                    ids.Add(item);
-                }
-            }
-            var grp = ids.GroupBy(g => g.code).Select(x => new { key = x.Key, list = x.ToList() });
-          
-            //foreach (var gp in grp) {
-            //    foreach (var tch in gp.list) {
-            //        if (!string.IsNullOrWhiteSpace(tch.id)) {
-            //           var id  =  ids.Find(x => x.id.Equals(tch.id))?.id;
-            //            if (id != null) {
-            //                TeacherFile teacherFile = new TeacherFile { id = id,pk= "TeacherFile",code= $"TeacherFile-{gp.key}",ttl=-1 };
-            //                try {
-            //                    TeacherTrain teacherTrain = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemAsync<TeacherTrain>(id, new PartitionKey($"TeacherTrain-{gp.key}"));
-            //                    teacherTrain.update.Add("TeacherAbility");
-            //                    await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReplaceItemAsync<TeacherTrain>(teacherTrain,id, new PartitionKey($"TeacherTrain-{gp.key}"));
-            //                } catch (Exception) { 
-            //                }
-            //                List<AbilitySub> abilitySubs = new List<AbilitySub>();
-            //                string sql = "select value(c) from c ";
-            //                try 
-            //                {
-            //                    await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetItemQueryIterator<AbilitySub>
-            //                        (sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"AbilitySub-{gp.key}-{id}") }))
-            //                    {
-            //                        abilitySubs.Add(item);
-            //                    }
-                           
-            //                    Dictionary<string, RecordFileAbility> valuePairs = new Dictionary<string, RecordFileAbility>();
-            //                    var taskids=  abilitySubs.SelectMany(x => x.taskRcds).Select(x => x.id).ToHashSet();
-            //                    if (taskids.Any()) 
-            //                    {
-
-            //                        List<AbilityTask> abilityTasks = new List<AbilityTask>();
-            //                        string taskSql = $"select distinct value(c) from c  join b in c.children where c.code='AbilityTask-standard10' and b.id in ({string.Join(",", taskids.Select(m=>$"'{m}'"))})";
-            //                        await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Normal).GetItemQueryIterator<AbilityTask>
-            //                            (taskSql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"AbilityTask-standard10") }))
-            //                        {
-            //                            abilityTasks.Add(item);
-            //                        }
-            //                        abilityTasks.ForEach(x => {
-            //                            x.children.ForEach(y => {
-            //                                var di= taskids.ToList().Find(z => z.Equals(y.id));
-            //                                if (!string.IsNullOrWhiteSpace(di)) {
-            //                                    y.rnodes.ForEach(r => {
-            //                                        if (valuePairs.ContainsKey(r.hash))
-            //                                        {
-            //                                            valuePairs.TryGetValue(r.hash, out var value);
-            //                                            value.fileAbilities.Add(new FileAbility { url = r.link, abilityId = x.abilityId, taskId = x.id, nodeId = di });
-            //                                        }
-            //                                        else {
-            //                                            valuePairs.Add(r.hash, new RecordFileAbility
-            //                                            {
-            //                                                fileRecord =
-            //                                                new FileRecord { hash = r.hash, size = r.size.Value, duration = r.duration, view = (int)r.duration, type = r.type, done = true },
-            //                                                fileAbilities = new List<FileAbility> { new FileAbility { url=r.link,abilityId=x.abilityId,taskId=x.id,nodeId=di } }
-            //                                            });
-            //                                        }
-            //                                    });
-            //                                }
-            //                            });
-            //                        });
-            //                    }
-            //                    foreach (var item in valuePairs)
-            //                    {
-            //                        teacherFile.fileRecords.Add(new FileRecord
-            //                        {
-            //                            hash = item.Value.fileRecord.hash,
-            //                            size = item.Value.fileRecord.size,
-            //                            duration = item.Value.fileRecord.duration,
-            //                            view = (int)item.Value.fileRecord.view,
-            //                            type = item.Value.fileRecord.type,
-            //                            done = true,
-            //                            files = item.Value.fileAbilities
-            //                        });
-            //                    }
-            //                }
-            //                catch (Exception ex)
-            //                {
-            //                    return BadRequest(new { ex = ex.Message, ms = ex.StackTrace });
-
-            //                }
-            //                teacherFiles.Add(teacherFile);
-            //                await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).UpsertItemAsync(teacherFile, new PartitionKey(teacherFile.code));
-            //            }
-            //        }
-            //    }
-            //}
-            
-            return Ok(teacherFiles);
+            return Ok();
         }
 
 
         public class RecordFileAbility
         {
 
-           public FileRecord fileRecord { get; set; }
+            public FileRecord fileRecord { get; set; }
             public List<FileAbility> fileAbilities { get; set; }
         }
         [HttpPost("test-blob-folder")]
         public async Task<IActionResult> TestBlobFolder(JsonElement json)
         {
-            var client =  _azureStorage.GetBlobContainerClient("1595321354") ;
+            var client = _azureStorage.GetBlobContainerClient("1595321354");
             List<BlobItem> blobItems = new List<BlobItem>();
             HashSet<string> ids = new HashSet<string>();
             string path = $"records";
-            await foreach (BlobItem item in client.GetBlobsAsync(BlobTraits.None, BlobStates.None, path)) {
-                var p=   item.Name.Split("/");
-                if (p.Length > 2) {
+            await foreach (BlobItem item in client.GetBlobsAsync(BlobTraits.None, BlobStates.None, path))
+            {
+                var p = item.Name.Split("/");
+                if (p.Length > 2)
+                {
                     ids.Add(p[1]);
                 }
             }
             List<string> lessonIds = new List<string>();
             string sql = "select value(c.id) from c ";
-            await foreach(var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher)
-                .GetItemQueryIterator<string>(queryText:sql ,requestOptions:new QueryRequestOptions { PartitionKey= new PartitionKey("LessonRecord-1595321354") }))
+            await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher)
+                .GetItemQueryIterator<string>(queryText: sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("LessonRecord-1595321354") }))
             {
                 lessonIds.Add(item);
             }
-            var notdata =  ids.Except(lessonIds);
-            var notblob = lessonIds.Except(ids).ToList() ;
-            List<string> paths = notdata.Select(x => $"records/{x}").ToList() ;
+            var notdata = ids.Except(lessonIds);
+            var notblob = lessonIds.Except(ids).ToList();
+            List<string> paths = notdata.Select(x => $"records/{x}").ToList();
             await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).DeleteItemsStreamAsync(notblob, "LessonRecord-1595321354");
             await _azureStorage.GetBlobServiceClient().DeleteBlobs(_dingDing, "1595321354", paths);
-            return Ok(new { lessonIds , ids , notdata, notblob });
+            return Ok(new { lessonIds, ids, notdata, notblob });
         }
     }
 }

+ 1 - 1
TEAMModelOS/Filter/AuthTokenAttribute.cs

@@ -38,7 +38,7 @@ namespace TEAMModelOS.Filter
             public void OnResourceExecuting(ResourceExecutingContext context)
             {
                 bool pass = false;
-                string id = string.Empty, name = string.Empty, picture = string.Empty, school = string.Empty, standard = string.Empty,scope=string.Empty,  website=string.Empty, area=string.Empty;
+                string id = string.Empty, name = string.Empty, picture = string.Empty, school = string.Empty, standard = string.Empty, scope = string.Empty, website = string.Empty, area = string.Empty;
                 List<string> _role = new List<string>();
                 var authtoken = context.HttpContext.GetXAuth("AuthToken");
                 if (!string.IsNullOrWhiteSpace(authtoken) && JwtAuthExtension.ValidateAuthToken(authtoken, _option.JwtSecretKey))

+ 3 - 3
TEAMModelOS/TEAMModelOS.csproj

@@ -32,9 +32,9 @@
     <SpaRoot>ClientApp\</SpaRoot>
     <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
     <UserSecretsId>078b5d89-7d90-4f6a-88fc-7d96025990a8</UserSecretsId>
-    <Version>5.2204.29</Version>
-    <AssemblyVersion>5.2204.29.1</AssemblyVersion>
-    <FileVersion>5.2204.29.1</FileVersion>
+    <Version>5.2205.6</Version>
+    <AssemblyVersion>5.2205.6.1</AssemblyVersion>
+    <FileVersion>5.2205.6.1</FileVersion>
     <Description>TEAMModelOS(IES5)</Description>
     <PackageReleaseNotes>6.0版本说明</PackageReleaseNotes>
     <PackageId>TEAMModelOS</PackageId>