|
@@ -124,6 +124,12 @@ namespace TEAMModelOS.Controllers
|
|
|
[RequestSizeLimit(102_400_000_00)] //最大10000m左右
|
|
|
public async Task<IActionResult> RemoveStuCourse(JsonElement json)
|
|
|
{
|
|
|
+ json.TryGetProperty("am", out JsonElement _am);
|
|
|
+ json.TryGetProperty("pm", out JsonElement _pm);
|
|
|
+ int am = 0;
|
|
|
+ int pm = 0;
|
|
|
+ _am.TryGetInt32(out am);
|
|
|
+ _pm.TryGetInt32(out pm);
|
|
|
var url = _configuration.GetValue<string>("HaBookAuth:CoreAPI");
|
|
|
var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
|
|
|
var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
|
|
@@ -147,7 +153,7 @@ namespace TEAMModelOS.Controllers
|
|
|
{
|
|
|
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token.AccessToken}");
|
|
|
}
|
|
|
- List<CodeValue> notifys= await SystemService.AccumulateDaily( _azureRedis,_azureCosmos, _coreAPIHttpService,_dingDing,client, _snowflakeId, url,_mailFactory);
|
|
|
+ List<CodeValue> notifys= await SystemService.AccumulateDaily(_configuration, _azureRedis,_azureCosmos, _coreAPIHttpService,_dingDing,client, _snowflakeId, url,_mailFactory,am ,pm );
|
|
|
return Ok(new { notifys });
|
|
|
}
|
|
|
|
|
@@ -3089,6 +3095,7 @@ namespace TEAMModelOS.Controllers
|
|
|
jointExam.id = "daaa3965-db28-49ae-8074-c9d4865b62ad";
|
|
|
jointExam.creatorId = "1595321354";
|
|
|
jointExam.name = "統測測試(一)";
|
|
|
+ jointExam.scope = "private";
|
|
|
//課程列表
|
|
|
////課程1: [1595321354]"courseId": "e1d817e5-71b3-bc50-52ac-fa828e5f38d6", "groupId": "4dd434a8-a94a-4373-9a05-1a1add533a71",
|
|
|
JointExam.JointExamGroup jointExamGroup1 = new JointExam.JointExamGroup();
|
|
@@ -3109,21 +3116,51 @@ namespace TEAMModelOS.Controllers
|
|
|
jointExamGroup2.courseLists.Add(jointExamGroupCourse2);
|
|
|
jointExam.groupLists.Add(jointExamGroup2);
|
|
|
//試卷
|
|
|
- string paperJson = "{\"id\": \"a30bb6e7-f10a-7adf-0d88-a36c718f6d80\",\"code\": \"Paper-hbgl\",\"name\": \"英聽測試\",\"blob\": \"/exam/b8376136-e797-487b-862f-db04326c8757/paper/a30bb6e7-f10a-7adf-0d88-a36c718f6d80\",\"scope\": \"school\",\"multipleRule\": 1,\"point\": [100],\"answers\": [[\"A\"]],\"knowledge\": [[]],\"type\": [],\"field\": [2],\"sheet\": null,\"sheetNo\": null,\"time\": 0}";
|
|
|
- PaperSimple paper = JsonConvert.DeserializeObject<PaperSimple>(paperJson);
|
|
|
+ ///STEP1 Blob拷貝 ※此步驟由前端做
|
|
|
+ ///拷貝目標:{TMID/SchoolId}/jointexam/{jointExam.id}/paper/{paperId}
|
|
|
+ string paperSourceBlobPath = "paper/語文理解";
|
|
|
+ string paperSourceBlobContainer = "tbslgb";
|
|
|
+ string paperSourceScope = "school";
|
|
|
+ var paperSourceBlobContainerClient = _azureStorage.GetBlobContainerClient(paperSourceBlobContainer);
|
|
|
+ string paperId = "1c6a1e85-4b34-b8af-00de-a379bc47a26c";
|
|
|
+ string paperTargetBlobPath = $"jointexam/{jointExam.id}/paper/{paperId}";
|
|
|
+ string paperTargetBlobContainer = jointExam.creatorId;
|
|
|
+ var paperTargetBlobContainerClient = _azureStorage.GetBlobContainerClient(paperTargetBlobContainer);
|
|
|
+ Pageable<BlobItem> sourceBlobs = paperSourceBlobContainerClient.GetBlobs(prefix: paperSourceBlobPath);
|
|
|
+ if (sourceBlobs.Count() > 0)
|
|
|
+ {
|
|
|
+ foreach (var blob in sourceBlobs)
|
|
|
+ {
|
|
|
+ var sourceFileBlob = paperSourceBlobContainerClient.GetBlobClient(blob.Name);
|
|
|
+ if (sourceFileBlob.Exists())
|
|
|
+ {
|
|
|
+ var sourceFileUri = paperSourceBlobContainerClient.GetBlobClient(blob.Name).Uri;
|
|
|
+ string fileName = blob.Name.Replace(paperSourceBlobPath, "");
|
|
|
+ string destBlobFilePath = $"{paperTargetBlobPath}{fileName}";
|
|
|
+ await paperTargetBlobContainerClient.GetBlobClient(destBlobFilePath).StartCopyFromUriAsync(sourceFileUri);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ bool paperDataCopyErrFlg = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ///STEP2 document製作
|
|
|
+ PaperSimple paper = new PaperSimple() { id= paperId , code = "Paper-tbslgb", name = "語文理解", blob = $"/{paperTargetBlobPath}", scope = "school", multipleRule = 1, point = new List<double>() { 50, 50}, answers = new List<List<string>>() { new List<string>() { "D" }, new List<string>() { "D" } }, knowledge = new List<List<string>>(), type = new List<string>() { "single","single"}, field=new List<int>() { 2, 2 } };
|
|
|
jointExam.papers.Add(paper);
|
|
|
//時間
|
|
|
jointExam.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
|
|
jointExam.startTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
|
|
jointExam.endTime = DateTimeOffset.UtcNow.AddDays(2).ToUnixTimeMilliseconds();
|
|
|
jointExam.progress = "going";
|
|
|
-
|
|
|
await client.GetContainer(Constant.TEAMModelOS, "Common").UpsertItemAsync<JointExam>(jointExam, new PartitionKey("JointExam"));
|
|
|
return Ok();
|
|
|
}
|
|
|
*/
|
|
|
+
|
|
|
//評量統一生成測試
|
|
|
/*
|
|
|
+ [HttpPost("add-exam-byJoint")]
|
|
|
public async Task<IActionResult> AddExamByJointExam(JsonElement json)
|
|
|
{
|
|
|
if (!json.TryGetProperty("jointExamId", out JsonElement _jointExamId)) return BadRequest();
|
|
@@ -3145,7 +3182,7 @@ namespace TEAMModelOS.Controllers
|
|
|
List<ExamInfo> examList = new List<ExamInfo>();
|
|
|
if(jointExam.groupLists.Count > 0)
|
|
|
{
|
|
|
- foreach(JointExam.JointExamGroup jointExamGroup in jointExam.groupLists)
|
|
|
+ foreach (JointExam.JointExamGroup jointExamGroup in jointExam.groupLists)
|
|
|
{
|
|
|
string actExamCreatorId = jointExamGroup.creatorId;
|
|
|
foreach(JointExam.JointExamGroup.JointExamGroupCourse jointExamGroupCourse in jointExamGroup.courseLists)
|
|
@@ -3154,37 +3191,171 @@ namespace TEAMModelOS.Controllers
|
|
|
string actExamCourseName = jointExamGroupCourse.courseName;
|
|
|
//評量資料生成
|
|
|
ExamInfo actExamInfo = new ExamInfo();
|
|
|
+ actExamInfo.code = $"Exam-{jointExamGroup.creatorId}";
|
|
|
actExamInfo.owner = "teacher";
|
|
|
+ actExamInfo.scope = jointExam.scope;
|
|
|
actExamInfo.creatorId = actExamCreatorId;
|
|
|
actExamInfo.id = Guid.NewGuid().ToString();
|
|
|
actExamInfo.source = "1"; //目前先設定為"智慧教室評量",實際上應讓老師選擇
|
|
|
actExamInfo.name = jointExam.name;
|
|
|
+ actExamInfo.jointExamId = jointExam.id;
|
|
|
///評量stuLists
|
|
|
- foreach(string actGroupId in jointExamGroupCourse.groupListIds)
|
|
|
+ foreach (string actGroupId in jointExamGroupCourse.groupListIds)
|
|
|
{
|
|
|
actExamInfo.stuLists.Add(actGroupId);
|
|
|
List<string> targetRow = new List<string>() { actExamCourseId, actGroupId };
|
|
|
actExamInfo.targets.Add(System.Text.Json.JsonSerializer.SerializeToElement(targetRow));
|
|
|
actExamInfo.subjects.Add(new ExamSubject() { id = actExamCourseId, name = actExamCourseName });
|
|
|
}
|
|
|
- ///試卷
|
|
|
- actExamInfo.papers = jointExam.papers;
|
|
|
-
|
|
|
-
|
|
|
+ ///試卷 ※先用統購的試卷記入,生成評量(generateExam)時會做blob的路徑修正
|
|
|
+ actExamInfo.papers = JsonConvert.DeserializeObject<List<PaperSimple>>(JsonConvert.SerializeObject(jointExam.papers));
|
|
|
///時間
|
|
|
actExamInfo.year = DateTimeOffset.UtcNow.Year;
|
|
|
-
|
|
|
+ actExamInfo.startTime = jointExam.startTime;
|
|
|
+ actExamInfo.endTime = jointExam.endTime;
|
|
|
|
|
|
examList.Add(actExamInfo);
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
+ //生成評量
|
|
|
+ if(examList.Count > 0)
|
|
|
+ {
|
|
|
+ foreach(ExamInfo exam in examList)
|
|
|
+ {
|
|
|
+ await generateExam(jointExam, exam);
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
return Ok();
|
|
|
}
|
|
|
*/
|
|
|
+ //生成評量(單)
|
|
|
+ /*
|
|
|
+ private async Task<string> generateExam(JointExam jointExam, ExamInfo exam)
|
|
|
+ {
|
|
|
+ var client = _azureCosmos.GetCosmosClient();
|
|
|
+ long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
|
|
+ string Result = string.Empty;
|
|
|
+ exam.createTime = now;
|
|
|
+ if (exam.startTime <= 0) exam.startTime = now;
|
|
|
+ List<(string pId, List<string> gid)> ps = new();
|
|
|
+ var group = exam.groupLists;
|
|
|
+ if (group.Count > 0)
|
|
|
+ {
|
|
|
+ foreach (var keys in group)
|
|
|
+ {
|
|
|
+ foreach (KeyValuePair<string, List<string>> pp in keys)
|
|
|
+ {
|
|
|
+ ps.Add((pp.Key, pp.Value));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ List<string> classes = ExamService.getClasses(exam.classes, exam.stuLists);
|
|
|
+ (List<RMember> tchList, List<RGroupList> classLists) = await GroupListService.GetMemberByListids(_coreAPIHttpService, client, _dingDing, classes, exam.school, ps);
|
|
|
+ exam.stuCount = tchList.Count;
|
|
|
+ string mode = string.Empty;
|
|
|
+ Response response = null;
|
|
|
+ if (string.IsNullOrEmpty(exam.id))
|
|
|
+ {
|
|
|
+ mode = "add";
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ response = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(exam.id, new PartitionKey($"{exam.code}"));
|
|
|
+ if (response.Status == 200) mode = "upd";
|
|
|
+ else mode = "add";
|
|
|
+ }
|
|
|
+ //DB操作
|
|
|
+ if (mode.Equals("add")) //新建
|
|
|
+ {
|
|
|
+ if(string.IsNullOrWhiteSpace(exam.id)) exam.id = Guid.NewGuid().ToString();
|
|
|
+ exam.progress = (exam.startTime > now) ? "pending" : "going";
|
|
|
+ var messageBlob = new ServiceBusMessage();
|
|
|
+ exam.size = await _azureStorage.GetBlobContainerClient(exam.creatorId).GetBlobsSize($"exam/{exam.id}"); //統測只允許老師個人,Blob只指向creatorId
|
|
|
+ await BlobService.RefreshBlobRoot(new BlobRefreshMessage { progress = "insert", root = $"exam", name = exam.creatorId }, _serviceBus, _configuration, _azureRedis);
|
|
|
+ int n = 0;
|
|
|
+ List<string> sheetIds = new List<string>();
|
|
|
+ foreach (PaperSimple simple in exam.papers)
|
|
|
+ {
|
|
|
+ simple.blob = $"/exam/{exam.id}/paper/{exam.subjects[n].id}";
|
|
|
+ n++;
|
|
|
+ simple.sheet = null;
|
|
|
+ }
|
|
|
+ exam = await client.GetContainer(Constant.TEAMModelOS, "Common").CreateItemAsync(exam, new PartitionKey($"{exam.code}"));
|
|
|
+ await BIStats.SetTypeAddStats(client, _dingDing, exam.school, "Exam", 1);//BI统计增/减量
|
|
|
+ }
|
|
|
+ else if(response != null) //更新
|
|
|
+ {
|
|
|
+ using var json = await JsonDocument.ParseAsync(response.ContentStream);
|
|
|
+ ExamInfo info = json.ToObject<ExamInfo>();
|
|
|
+ if (info.progress.Equals("going"))
|
|
|
+ {
|
|
|
+ Result = "活动正在进行中,无法修改";
|
|
|
+ }
|
|
|
+ var messageBlob = new ServiceBusMessage();
|
|
|
+ exam.size = await _azureStorage.GetBlobContainerClient(exam.creatorId).GetBlobsSize($"exam/{exam.id}");
|
|
|
+ await BlobService.RefreshBlobRoot(new BlobRefreshMessage { progress = "update", root = $"exam", name = exam.creatorId }, _serviceBus, _configuration, _azureRedis);
|
|
|
+ exam.progress = info.progress;
|
|
|
+ int n = 0;
|
|
|
+ foreach (PaperSimple simple in exam.papers)
|
|
|
+ {
|
|
|
+ simple.blob = "/exam/" + exam.id + "/paper/" + exam.subjects[n].id;
|
|
|
+ n++;
|
|
|
+ }
|
|
|
+ exam = await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(exam, exam.id, new PartitionKey($"{exam.code}"));
|
|
|
+ }
|
|
|
+ //Blob操作 ※取得試卷源(blob)、複製到評測紀錄下
|
|
|
+ ///試卷源字典
|
|
|
+ List<Dictionary<string, string>> sourcePaperInfo = new List<Dictionary<string, string>>();
|
|
|
+ foreach (PaperSimple paperInfo in jointExam.papers)
|
|
|
+ {
|
|
|
+ string paperBlobPath = (!paperInfo.blob.EndsWith("/")) ? paperInfo.blob + "/" : paperInfo.blob;
|
|
|
+ paperBlobPath = (paperInfo.blob.StartsWith("/")) ? paperBlobPath.Remove(0, 1) : paperBlobPath;
|
|
|
+ sourcePaperInfo.Add(new Dictionary<string, string>() { { "id", paperInfo.id }, { "blob", paperBlobPath }, { "itemcount", paperInfo.point.Count.ToString() } });
|
|
|
+ }
|
|
|
+ bool paperDataCopyErrFlg = false; //試卷資料拷貝錯誤Flag true:拷貝錯誤
|
|
|
+ //Blob拷貝程序
|
|
|
+ int paperIndex = 0;
|
|
|
+ foreach (Dictionary<string, string> sourcePaperInfoDic in sourcePaperInfo)
|
|
|
+ {
|
|
|
+ //拷貝源:Container => jointExam.creatorId Path:papers.blob
|
|
|
+ //拷貝對象:Container => exam.creatorId, Path:exam/{exam.id}/paper/{exam.subjects[paperIndex].id}/
|
|
|
+ string targetScope = exam.scope; //評測對象 school:校本班級 private:私人課程
|
|
|
+ var sourceBlobContainer = _azureStorage.GetBlobContainerClient(jointExam.creatorId);
|
|
|
+ var blobPrivateContainer = _azureStorage.GetBlobContainerClient(exam.creatorId);
|
|
|
+ string sourceBlobPath = sourcePaperInfoDic["blob"];
|
|
|
+ string subjectId = exam.subjects[paperIndex].id;
|
|
|
+ string destBlobPath = $"exam/{exam.id}/paper/{subjectId}/"; //拷貝對象路徑 path:exam/{評測ID}/paper/{subjectID}/
|
|
|
+ Pageable<BlobItem> sourceBlobs = sourceBlobContainer.GetBlobs(prefix: sourceBlobPath);
|
|
|
+ if (sourceBlobs.Count() > 0)
|
|
|
+ {
|
|
|
+ foreach (var blob in sourceBlobs)
|
|
|
+ {
|
|
|
+ var sourceFileBlob = sourceBlobContainer.GetBlobClient(blob.Name);
|
|
|
+ if (sourceFileBlob.Exists())
|
|
|
+ {
|
|
|
+ var sourceFileUri = sourceBlobContainer.GetBlobClient(blob.Name).Uri;
|
|
|
+ string fileName = blob.Name.Replace(sourceBlobPath, "");
|
|
|
+ string destBlobFilePath = $"{destBlobPath}{fileName}";
|
|
|
+ await blobPrivateContainer.GetBlobClient(destBlobFilePath).StartCopyFromUriAsync(sourceFileUri);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ paperDataCopyErrFlg = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ paperIndex++;
|
|
|
+ }
|
|
|
+
|
|
|
+ return Result;
|
|
|
+ }
|
|
|
+ */
|
|
|
+ //統測資料架構
|
|
|
/*
|
|
|
- public class JointExam : CosmosEntity //統測架構
|
|
|
+ public class JointExam : CosmosEntity
|
|
|
{
|
|
|
public string creatorId { get; set; }
|
|
|
public string name { get; set; }
|
|
@@ -3196,6 +3367,7 @@ namespace TEAMModelOS.Controllers
|
|
|
public long updateTime { get; set; }
|
|
|
public long startTime { get; set; }
|
|
|
public long endTime { get; set; }
|
|
|
+ public string scope { get; set; }
|
|
|
|
|
|
public class JointExamClass
|
|
|
{
|