Bläddra i källkod

學生Login blob位置調整:{學校ID}/student/{學生id},權限:read
HiTeach API調整
get-teacher-info:移除老師個人試題、老師個人試券、老師個人課綱
get-school-info: 移除校本試題、校本試券、校本課綱
新增 get-paper:取得試卷API
新增 get-item:取得試題API

jeff 4 år sedan
förälder
incheckning
2f1410677f

+ 283 - 82
TEAMModelOS/Controllers/Client/HiTeachController.cs

@@ -132,62 +132,12 @@ namespace TEAMModelOS.Controllers.Client
                         }
                     }
                 }
-                //老師個人試題
-                List<object> items = new List<object>();
-                await foreach (var item in client.GetContainer("TEAMModelOSTemp", "Teacher").GetItemQueryStreamIterator(queryText: $"SELECT c.id, c.blob, c.type, c.points, c.field, c.subjectName, c.level, c.useCount, c.createDate from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{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())
-                        {
-                            items.Add(obj.ToObject<object>());
-                        }
-                    }
-                }
-                //老師個人試券
-                List<object> papers = new List<object>();
-                await foreach (var item in client.GetContainer("TEAMModelOSTemp", "Teacher").GetItemQueryStreamIterator(queryText: $"SELECT c.id, c.name, c.blob, c.subjectName, c.score, c.useCount, c.createDate from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Paper-{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())
-                        {
-                            papers.Add(obj.ToObject<object>());
-                        }
-                    }
-                }
-
-                //老師個人課綱
-                List<SyllabusRole> syllabus = new List<SyllabusRole>();
-                await foreach (var item in client.GetContainer("TEAMModelOSTemp", "Teacher").GetItemQueryStreamIterator(queryText: $"SELECT c.id, c.name, c.scope, c.resourceCount, c.itemCount, c.children from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Syllabus-{id}") }))
-                {
-                    var jsons = await JsonDocument.ParseAsync(item.ContentStream);
-                    if (jsons.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
-                    {
-                        foreach (var obj in jsons.RootElement.GetProperty("Documents").EnumerateArray())
-                        {
-                            SyllabusRole syllabusRole = new SyllabusRole();
-                            syllabusRole.id = obj.GetProperty("id").ToString();
-                            syllabusRole.name = obj.GetProperty("name").ToString();
-                            syllabusRole.resourceCount = obj.GetProperty("resourceCount").GetUInt16();
-                            syllabusRole.itemCount = obj.GetProperty("itemCount").GetUInt16();
-                            List<Syllabus> syllabusList = obj.GetProperty("children").ToObject<List<Syllabus>>();
-                            syllabusList.Insert(0, new Syllabus { id = syllabusRole.id, name = syllabusRole.name, pid = "", order = 0 });
-                            syllabusList = syllabusList.OrderBy(x => x.order).ToList();
-                            syllabusRole.structure = CreateSyllabusTree(syllabusList);
-                            syllabus.Add(syllabusRole);
-                        }
-                        //[DEBUG] string jsonString = System.Text.Json.JsonSerializer.Serialize(syllabusRoles);
-                    }
-                }
 
                 //取得Teacher Blob 容器位置及SAS 
                 var container = _azureStorage.GetBlobContainerClient(id);
                 await container.CreateIfNotExistsAsync(PublicAccessType.None); //嘗試創建Teacher私有容器,如存在則不做任何事,保障容器一定存在
                 var (blob_uri, blob_sas) = _azureStorage.GetBlobContainerSAS(id, BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List | BlobContainerSasPermissions.Delete);
-                return Ok(new { blob_uri, blob_sas, schools, defaultschool, courses, syllabus, items, papers });
+                return Ok(new { blob_uri, blob_sas, schools, defaultschool, courses });
 
             }
             catch (Exception ex)
@@ -292,37 +242,243 @@ namespace TEAMModelOS.Controllers.Client
                     }
                 }
             }
-            //校本課綱
-            List<SyllabusRole> syllabus = new List<SyllabusRole>();
-            await foreach (var item in client.GetContainer("TEAMModelOSTemp", "School").GetItemQueryStreamIterator(queryText: $"SELECT c.id, c.name, c.period, c.grade, c.semester, c.subject, c.scope, c.resourceCount, c.itemCount, c.children from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Syllabus-{school_code}") }))
+            
+            //取得School Blob 容器位置及SAS
+            string school_code_blob = school_code.GetString().ToLower();
+            var (blob_uri, blob_sas) = _azureStorage.GetBlobContainerSAS(school_code_blob, BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List);
+
+            return Ok(new { blob_uri, blob_sas, periods, grades, subjects, courses });
+        }
+
+        //取得試卷
+        [ProducesDefaultResponseType]
+        [HttpPost("get-paper")]
+        public async Task<IActionResult> GetPaperList(JsonElement request)
+        {
+            //Header驗證
+            string id_token = HttpContext.GetXAuth("IdToken");
+            if (string.IsNullOrEmpty(id_token)) return BadRequest();
+            var jwt = new JwtSecurityToken(id_token);
+            if (!jwt.Payload.Iss.Equals("account.teammodel", StringComparison.Ordinal)) return BadRequest();
+            var id = jwt.Payload.Sub;
+            var client = _azureCosmos.GetCosmosClient();
+            //參數
+            if (!request.TryGetProperty("grant_type", out JsonElement grant_type)) return BadRequest();
+            string partitionid = string.Empty;
+            string container = string.Empty;
+            if (grant_type.ToString() == "school")
             {
-                var jsons = await JsonDocument.ParseAsync(item.ContentStream);
-                if (jsons.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                if (!request.TryGetProperty("school_code", out JsonElement school_code_json))
                 {
-                    foreach (var obj in jsons.RootElement.GetProperty("Documents").EnumerateArray())
+                    return BadRequest();
+                }
+                else
+                {
+                    partitionid = school_code_json.ToString();
+                    container = "School";
+                }
+            }
+            else
+            {
+                partitionid = id.ToString();
+                container = "Teacher";
+            }
+            //SQL文
+            List<object> papers = new List<object>();
+            string queryWhere = " WHERE 1=1 ";
+            string queryOption = string.Empty;
+            //學段
+            if (request.TryGetProperty("periodId", out JsonElement periodId) && container == "School")
+            {
+                queryWhere += $" AND c.periodId = '{periodId}'";
+            }
+            //年級
+            if (request.TryGetProperty("gradeId", out JsonElement gradeIds) && gradeIds.GetArrayLength() > 0 && container == "School")
+            {
+                string queryOptionForGrade = string.Empty;
+                for (int i = 0; i < gradeIds.GetArrayLength(); i++)
+                {
+                    if(!string.IsNullOrWhiteSpace(queryOptionForGrade))
                     {
-                        SyllabusRole syllabusRole = new SyllabusRole();
-                        syllabusRole.id = obj.GetProperty("id").ToString();
-                        syllabusRole.name = obj.GetProperty("name").ToString();
-                        syllabusRole.period = obj.GetProperty("period");
-                        syllabusRole.grade = obj.GetProperty("grade");
-                        syllabusRole.semester = obj.GetProperty("semester");
-                        syllabusRole.subject = obj.GetProperty("subject");
-                        syllabusRole.resourceCount = obj.GetProperty("resourceCount").GetUInt16();
-                        syllabusRole.itemCount = obj.GetProperty("itemCount").GetUInt16();
-                        List<Syllabus> syllabusList = obj.GetProperty("children").ToObject<List<Syllabus>>();
-                        syllabusList.Insert(0, new Syllabus { id = syllabusRole.id, name = syllabusRole.name, pid = "", order = 0 });
-                        syllabusList = syllabusList.OrderBy(x => x.order).ToList();
-                        syllabusRole.structure = CreateSyllabusTree(syllabusList);
-                        syllabus.Add(syllabusRole);
+                        queryOptionForGrade += " OR ";
                     }
-                    //[DEBUG] string jsonString = System.Text.Json.JsonSerializer.Serialize(syllabusRoles);
+                    queryOptionForGrade += $" ARRAY_CONTAINS(c.gradeIds, '{gradeIds[i]}', true)";
+                }
+                queryWhere += $" AND ( {queryOptionForGrade} )"; 
+            }
+            //科目ID
+            if (request.TryGetProperty("subjectId", out JsonElement subjectId) && container == "School")
+            {
+                queryWhere += $" AND c.subjectId = '{subjectId}'";
+            }
+            //科目名稱
+            if (request.TryGetProperty("subjectName", out JsonElement subjectName))
+            {
+                queryWhere += $" AND c.subjectName = '{subjectName}'";
+            }
+            int perpage = 0; //每頁幾條
+            if (request.TryGetProperty("perpage", out JsonElement perpage_json)) perpage = perpage_json.GetInt32();
+            int page = 0; //目前第幾頁
+            if (request.TryGetProperty("page", out JsonElement page_json))
+            {
+                if(page_json.GetInt32() > 0)
+                {
+                    page = page_json.GetInt32() - 1;
                 }
             }
+            string order = "createDate"; //排序項目
+            if (request.TryGetProperty("order", out JsonElement order_json))
+            {
+                if(order_json.ToString() == "useCount")
+                {
+                    order = order_json.ToString();
+                }
+            }    
+            queryOption += $" Order By c." + order + " DESC ";
+            if(perpage > 0 )
+            {
+                queryOption += $" OFFSET {perpage * page} LIMIT {perpage}";
+            }
 
-            //校本試題
+            //資料取得
+            await foreach (var item in client.GetContainer("TEAMModelOSTemp", container).GetItemQueryStreamIterator(queryText: $"SELECT c.periodId, c.gradeIds, c.subjectId, c.subjectName, c.name, REPLACE(c.blob, 'index.json', '') AS blob, c.score, c.useCount, ARRAY_LENGTH(c.scoring) AS itemCount, c.createDate From c {queryWhere + queryOption}", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Paper-{partitionid}") }))
+            {
+                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())
+                    {
+                        papers.Add(obj.ToObject<object>());
+                    }
+                }
+            }
+
+            //總件數
+            int totalCount = 0;
+            await foreach (var item in client.GetContainer("TEAMModelOSTemp", container).GetItemQueryStreamIterator(queryText: $"SELECT VALUE COUNT(1) From c {queryWhere}", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Paper-{partitionid}") }))
+            {
+                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())
+                    {
+                        totalCount = obj.GetInt32();
+                    }
+                }
+            }
+
+            return Ok(new { papers, totalCount });
+        }
+
+        //取得試題
+        [ProducesDefaultResponseType]
+        [HttpPost("get-item")]
+        public async Task<IActionResult> GetItemList(JsonElement request)
+        {
+            //Header驗證
+            string id_token = HttpContext.GetXAuth("IdToken");
+            if (string.IsNullOrEmpty(id_token)) return BadRequest();
+            var jwt = new JwtSecurityToken(id_token);
+            if (!jwt.Payload.Iss.Equals("account.teammodel", StringComparison.Ordinal)) return BadRequest();
+            var id = jwt.Payload.Sub;
+            var client = _azureCosmos.GetCosmosClient();
+            //參數
+            if (!request.TryGetProperty("grant_type", out JsonElement grant_type)) return BadRequest();
+            string partitionid = string.Empty;
+            string container = string.Empty;
+            if (grant_type.ToString() == "school")
+            {
+                if (!request.TryGetProperty("school_code", out JsonElement school_code_json))
+                {
+                    return BadRequest();
+                }
+                else
+                {
+                    partitionid = school_code_json.ToString();
+                    container = "School";
+                }
+            }
+            else
+            {
+                partitionid = id.ToString();
+                container = "Teacher";
+            }
+            //SQL文
             List<object> items = new List<object>();
-            await foreach (var item in client.GetContainer("TEAMModelOSTemp", "School").GetItemQueryStreamIterator(queryText: $"SELECT c.id, c.blob, c.type, c.points, c.field, c.periodId, c.gradeIds, c.subjectId, c.level, c.useCount, c.createDate from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{school_code}") }))
+            string queryWhere = " WHERE 1=1 ";
+            string queryOption = string.Empty;
+            //學段
+            if (request.TryGetProperty("periodId", out JsonElement periodId) && container == "School")
+            {
+                queryWhere += $" AND c.periodId = '{periodId}'";
+            }
+            //年級
+            if (request.TryGetProperty("gradeId", out JsonElement gradeIds) && gradeIds.GetArrayLength() > 0 && container == "School")
+            {
+                string queryOptionForGrade = string.Empty;
+                for (int i = 0; i < gradeIds.GetArrayLength(); i++)
+                {
+                    if (!string.IsNullOrWhiteSpace(queryOptionForGrade))
+                    {
+                        queryOptionForGrade += " OR ";
+                    }
+                    queryOptionForGrade += $" ARRAY_CONTAINS(c.gradeIds, '{gradeIds[i]}', true)";
+                }
+                queryWhere += $" AND ( {queryOptionForGrade} )";
+            }
+            //科目ID
+            if (request.TryGetProperty("subjectId", out JsonElement subjectId) && container == "School")
+            {
+                queryWhere += $" AND c.subjectId = '{subjectId}'";
+            }
+            //科目名稱
+            if (request.TryGetProperty("subjectName", out JsonElement subjectName))
+            {
+                queryWhere += $" AND c.subjectName = '{subjectName}'";
+            }
+            //題型
+            int dummy = 0;
+            if (request.TryGetProperty("type", out JsonElement type))
+            {
+                queryWhere += $" AND c.type = '{type}'";
+            }
+            //難度
+            dummy = 0;
+            if (request.TryGetProperty("level", out JsonElement level) && int.TryParse(level.ToString(), out dummy))
+            {
+                queryWhere += $" AND c.level = {level}";
+            }
+            //層次
+            if (request.TryGetProperty("field", out JsonElement field) && int.TryParse(field.ToString(), out dummy))
+            {
+                queryWhere += $" AND c.field = {field}";
+            }
+            int perpage = 0; //每頁幾條
+            if (request.TryGetProperty("perpage", out JsonElement perpage_json)) perpage = perpage_json.GetInt32();
+            int page = 0; //目前第幾頁
+            if (request.TryGetProperty("page", out JsonElement page_json))
+            {
+                if (page_json.GetInt32() > 0)
+                {
+                    page = page_json.GetInt32() - 1;
+                }
+            }
+            string order = "createDate"; //排序項目
+            if (request.TryGetProperty("order", out JsonElement order_json))
+            {
+                if (order_json.ToString() == "useCount")
+                {
+                    order = order_json.ToString();
+                }
+            }
+            queryOption += $" Order By c." + order + " DESC ";
+            if (perpage > 0)
+            {
+                queryOption += $" OFFSET {perpage * page} LIMIT {perpage}";
+            }
+
+            //資料取得
+            await foreach (var item in client.GetContainer("TEAMModelOSTemp", container).GetItemQueryStreamIterator(queryText: $"SELECT c.periodId, c.gradeIds, c.subjectId, c.subjectName, c.blob, c.field, c.level, c.type, c.useCount, c.createDate From c {queryWhere + queryOption}", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{partitionid}") }))
             {
                 using var json = await JsonDocument.ParseAsync(item.ContentStream);
                 if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
@@ -333,20 +489,31 @@ namespace TEAMModelOS.Controllers.Client
                     }
                 }
             }
-            //校本試券
-            List<object> papers = new List<object>();
-            await foreach (var item in client.GetContainer("TEAMModelOSTemp", "School").GetItemQueryStreamIterator(queryText: $"SELECT c.id, c.name, c.blob, c.periodId, c.gradeIds, c.subjectId, c.score, c.useCount, c.createDate from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Paper-{school_code}") }))
+
+            //總件數
+            int totalCount = 0;
+            await foreach (var item in client.GetContainer("TEAMModelOSTemp", container).GetItemQueryStreamIterator(queryText: $"SELECT VALUE COUNT(1) From c {queryWhere}", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{partitionid}") }))
             {
                 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())
                     {
-                        papers.Add(obj.ToObject<object>());
+                        totalCount = obj.GetInt32();
                     }
                 }
             }
 
+            return Ok(new { items, totalCount });
+        }
+
+        //取得知識點
+        [ProducesDefaultResponseType]
+        [HttpPost("get-knowledge")]
+        public async Task<IActionResult> GetKnowledgePointList(JsonElement request)
+        {
+            var client = _azureCosmos.GetCosmosClient();
+            if (!request.TryGetProperty("school_code", out JsonElement school_code)) return BadRequest();
             //知識點
             List<object> points = new List<object>();
             await foreach (var item in client.GetContainer("TEAMModelOSTemp", "School").GetItemQueryStreamIterator(queryText: $"SELECT c.id, c.name, c.subjectId FROM c WHERE c.type = 'point'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Knowledge-{school_code}") }))
@@ -361,11 +528,45 @@ namespace TEAMModelOS.Controllers.Client
                 }
             }
 
-            //取得School Blob 容器位置及SAS
-            string school_code_blob = school_code.GetString().ToLower();
-            var (blob_uri, blob_sas) = _azureStorage.GetBlobContainerSAS(school_code_blob, BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List);
+            return Ok(points);
+        }
+
+        //取得課綱
+        [ProducesDefaultResponseType]
+        [HttpPost("get-syllabus")]
+        public async Task<IActionResult> GetSyllabusList(JsonElement request)
+        {
+            var client = _azureCosmos.GetCosmosClient();
+            if (!request.TryGetProperty("school_code", out JsonElement school_code)) return BadRequest();
+            //校本課綱
+            List<SyllabusRole> syllabus = new List<SyllabusRole>();
+            await foreach (var item in client.GetContainer("TEAMModelOSTemp", "School").GetItemQueryStreamIterator(queryText: $"SELECT c.id, c.name, c.period, c.grade, c.semester, c.subject, c.scope, c.resourceCount, c.itemCount, c.children from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Syllabus-{school_code}") }))
+            {
+                var jsons = await JsonDocument.ParseAsync(item.ContentStream);
+                if (jsons.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                {
+                    foreach (var obj in jsons.RootElement.GetProperty("Documents").EnumerateArray())
+                    {
+                        SyllabusRole syllabusRole = new SyllabusRole();
+                        syllabusRole.id = obj.GetProperty("id").ToString();
+                        syllabusRole.name = obj.GetProperty("name").ToString();
+                        syllabusRole.period = obj.GetProperty("period");
+                        syllabusRole.grade = obj.GetProperty("grade");
+                        syllabusRole.semester = obj.GetProperty("semester");
+                        syllabusRole.subject = obj.GetProperty("subject");
+                        syllabusRole.resourceCount = obj.GetProperty("resourceCount").GetUInt16();
+                        syllabusRole.itemCount = obj.GetProperty("itemCount").GetUInt16();
+                        List<Syllabus> syllabusList = obj.GetProperty("children").ToObject<List<Syllabus>>();
+                        syllabusList.Insert(0, new Syllabus { id = syllabusRole.id, name = syllabusRole.name, pid = "", order = 0 });
+                        syllabusList = syllabusList.OrderBy(x => x.order).ToList();
+                        syllabusRole.structure = CreateSyllabusTree(syllabusList);
+                        syllabus.Add(syllabusRole);
+                    }
+                    //[DEBUG] string jsonString = System.Text.Json.JsonSerializer.Serialize(syllabusRoles);
+                }
+            }
 
-            return Ok(new { blob_uri, blob_sas, periods, grades, subjects, courses, syllabus, items, papers, points });
+            return Ok(syllabus);
         }
 
         [ProducesDefaultResponseType]

+ 2 - 1
TEAMModelOS/Controllers/School/StudentController.cs

@@ -1794,7 +1794,8 @@ namespace TEAMModelOS.Controllers
                     auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id.GetString(), name.GetString(), "", _option.JwtSecretKey, roles: new[] { "student" });
                     //BLOB(學校,唯讀)
                     string school_code_blob = school_code.GetString().ToLower();
-                    (blob_uri, blob_sas) = _azureStorage.GetBlobContainerSAS(school_code_blob, BlobContainerSasPermissions.Read);
+                    string blobPath = $"{school_code_blob}/student/{id}";
+                    (blob_uri, blob_sas) = _azureStorage.GetBlobContainerSAS(blobPath, BlobContainerSasPermissions.Read);
                     //所屬班級資訊
                     var query = $"SELECT c.code, c.id, c.name, c.periodId, c.gradeId FROM c JOIN cs IN c.students WHERE cs.id = '{id}'";
                     await foreach (var item in client.GetContainer("TEAMModelOSTemp", "School").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Class-{school_code}") }))