Browse Source

Merge branch 'develop3.0-tmd' of http://106.12.23.251:10080/TEAMMODEL/TEAMModelOS into develop3.0-tmd

OnePsycho 4 years ago
parent
commit
c5bc184a8a

+ 22 - 5
TEAMModelFunction/ExamTrigger.cs

@@ -20,17 +20,34 @@ namespace TEAMModelFunction
             ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(input.Id, new Azure.Cosmos.PartitionKey($"{code}"));
             List<ExamClassResult> examClassResults = new List<ExamClassResult>();
             List<ExamSubject> examSubjects = new List<ExamSubject>();
-            await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: $"select value(c) from c where c.examId = '{info.id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"ExamClassResult-{school}") }))
+            if (info.scope.Equals("teacher", StringComparison.OrdinalIgnoreCase) || info.scope.Equals("private", StringComparison.OrdinalIgnoreCase))
             {
-                using var json = await JsonDocument.ParseAsync(item.ContentStream);
-                if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: $"select value(c) from c where c.examId = '{info.id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"ExamClassResult-{info.creatorId}") }))
                 {
-                    foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                    using var json = await JsonDocument.ParseAsync(item.ContentStream);
+                    if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
                     {
-                        examClassResults.Add(obj.ToObject<ExamClassResult>());
+                        foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                        {
+                            examClassResults.Add(obj.ToObject<ExamClassResult>());
+                        }
+                    }
+                }
+            }
+            else {
+                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: $"select value(c) from c where c.examId = '{info.id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"ExamClassResult-{school}") }))
+                {
+                    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())
+                        {
+                            examClassResults.Add(obj.ToObject<ExamClassResult>());
+                        }
                     }
                 }
             }
+            
 
             List<ChangeRecord> records = await _azureStorage.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", input.Id }, { "PartitionKey", info.progress } });
             //ChangeRecord record = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ChangeRecord>(input.Id, new Azure.Cosmos.PartitionKey($"{info.progress}"));

+ 14 - 7
TEAMModelFunction/MonitorServicesBus.cs

@@ -151,14 +151,21 @@ namespace TEAMModelFunction
         public async Task Blob([ServiceBusTrigger("active-task", "blob", Connection = "Azure:ServiceBus:ConnectionString")] string msg) {
             try
             {
-                await _dingDing.SendBotMsg($"ServiceBus,Blob(){msg}", GroupNames.醍摩豆服務運維群組);
+               // await _dingDing.SendBotMsg($"ServiceBus,Blob(){msg}", GroupNames.醍摩豆服務運維群組);
                 var jsonMsg = JsonDocument.Parse(msg);
-                jsonMsg.RootElement.TryGetProperty("code", out JsonElement name);
-                var client = _azureStorage.GetBlobContainerClient($"{name}");
-                var size = await client.GetBlobsCatalogSize();
-                await _azureRedis.GetRedisClient(8).HashSetAsync($"Blob:Record",new RedisValue($"{name}"),new RedisValue($"{long.Parse($"{size.Item1}")}"));
-                await _dingDing.SendBotMsg($"ServiceBus,Blob() 容器:{name}更新大小:{size.Item1}",
-                        GroupNames.醍摩豆服務運維群組);
+                if(jsonMsg.RootElement.TryGetProperty("name", out JsonElement name)&& name.ValueKind==JsonValueKind.String)
+                {
+                    var client = _azureStorage.GetBlobContainerClient($"{name}");
+                    var size = await client.GetBlobsCatalogSize();
+                    await _azureRedis.GetRedisClient(8).HashSetAsync($"Blob:Record", new RedisValue($"{name}"), new RedisValue($"{long.Parse($"{size.Item1}")}"));
+                    foreach (var key in size.Item2.Keys)
+                    {
+                        await _azureRedis.GetRedisClient(8).SortedSetRemoveAsync($"Blob:Catalog:{name}", key);
+                        await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Blob:Catalog:{name}", key, size.Item2[key].HasValue ? size.Item2[key].Value : 0);
+                    }
+                    await _dingDing.SendBotMsg($"ServiceBus,Blob() 容器:{name}使用:{size.Item1},文件分类:{size.Item2.ToJsonString()}",
+                            GroupNames.醍摩豆服務運維群組);
+                }
             }
             catch (Exception ex)
             {

+ 16 - 7
TEAMModelOS.SDK/DI/AzureStorage/AzureStorageBlobExtensions.cs

@@ -69,30 +69,39 @@ namespace TEAMModelOS.SDK.DI
                 return (size, dict);
             }
         }
+
+        public class OptUrl
+        {
+            public string url { get; set; }
+            public long size { get; set; }
+        }
         /// <summary>
         /// 取得指定前置詞的 Blob 名稱的總大小(Bytes),例如指定目錄名稱為前置詞
         /// </summary>      
         /// <param name="urls">多个文件的连接/param>
         /// <returns>總大小(Bytes),如果為Null代表查無前置詞或者發生錯誤</returns>
-        public static async Task<long?> GetBlobsSize(this BlobContainerClient client, List<string>urls)
+        public static async Task<List<OptUrl>> GetBlobsSize(this BlobContainerClient client, List<string> urls)
         {
-            long? size = 0;
+            List<OptUrl> optUrls = new List<OptUrl>();
             try
             {
+               
                 foreach (var url in urls) {
-                 
-                    var eurl = System.Web.HttpUtility.UrlDecode(url.ToString(), Encoding.UTF8);
+                    OptUrl optUrl = new OptUrl { url = url, size =0};
+                    var eurl = System.Web.HttpUtility.UrlDecode(url, Encoding.UTF8);
                     var blob = client.GetBlobClient(eurl);
                     if (blob.Exists()) {
                         var props = await blob.GetPropertiesAsync();
-                        size += props.Value.ContentLength;
+                        var size= props.Value.ContentLength;
+                        optUrl.size = size;
                     }
+                    optUrls.Add(optUrl);
                 }
-                return size;
+                return optUrls;
             }
             catch
             {
-                return size;
+                return optUrls;
             }
         }
         /// <summary>        

+ 1 - 1
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestReport.vue

@@ -148,7 +148,7 @@
                                 </div>
                                 <div class="TitleRec1"><span style="margin:5px;color:#1472c7">{{$t("studentWeb.exam.report.ansRes")}}:</span></div>
                                 <br />
-                                <div v-if="ansData[index]" style="margin-left:10px" v-html="ansData[index].length > 0 ? ansData[index][0] : $t('studentWeb.exam.report.noScore')"></div>
+                                <div v-if="ansData[index]" style="margin-left:10px" v-html="ansData[index].length > 0 ? ansData[index][0] : '未作答'"></div>
                             </div>
                         </div>
                         <!--<br />-->

+ 15 - 17
TEAMModelOS/ClientApp/src/view/learnactivity/CreateSchoolEva.vue

@@ -23,8 +23,8 @@
                                     <Option v-for="(item,index) in $store.state.user.schoolProfile.periods" :value="item.id" :key="index">{{ item.name }}</Option>
                                 </Select>
                             </FormItem>
-                            <FormItem :label="$t('learnActivity.createEv.evMode')" prop="evaType">
-                                <Select v-model="evaluationInfo.evaType">
+                            <FormItem :label="$t('learnActivity.createEv.evMode')" prop="source">
+                                <Select v-model="evaluationInfo.source">
                                     <Option v-for="(item,index) in $GLOBAL.EV_MODE()" :value="item.value" :key="index">{{ item.label }}</Option>
                                 </Select>
                             </FormItem>
@@ -192,7 +192,7 @@ export default {
                 'type.id': [
                     { required: true, message: this.$t('learnActivity.createEv.errTips2'), trigger: 'change' }
                 ],
-                evaType: [
+                source: [
                     { required: true, message: this.$t('learnActivity.createEv.errTips3'), trigger: 'change' }
                 ],
                 'period.id': [
@@ -228,7 +228,7 @@ export default {
                 targetClassIds: [],
                 grades: [],
                 type: '',  //测试类别
-                evaType: '',
+                source: '',
                 publish: '0',
                 subjects: [],
                 subjectIds: [],
@@ -579,7 +579,7 @@ export default {
                 examType: this.evaluationInfo.examType,
                 year: new Date().getFullYear(),
                 range: this.mode,
-                source: this.evaluationInfo.evaType,
+                source: this.evaluationInfo.source,
                 targetClassIds: this.evaluationInfo.targetClassIds,
                 publish: this.evaluationInfo.publish,
                 startTime: this.evaluationInfo.publish == 0 ? Math.round(new Date()) : this.evaluationInfo.startTime,
@@ -701,23 +701,21 @@ export default {
         if (this.$route.name == 'createSchoolEva') {
             this.mode = 'school'
         }
-        //创建个人和校本已经分开,个人相关逻辑代码可是删除
-        // else {
-        //     this.mode = 'private'
-        //     this.findPrivClass() 
-        // }
 
         //编辑评测逻辑(暂时注释)
-        //let routerData = this.$route.params.evaluationInfo
-        //if (routerData !== undefined) {
-        //    this.evaluationInfo.startTime = new Date(routerData.startTime)
-        //    this.evaluationInfo.endTime = new Date(routerData.endTime)
+        let routerData = this.$route.params.evaluationInfo
+        console.log(routerData)
+        if (routerData !== undefined) {
+           routerData.startTime = new Date(routerData.startTime)
+           routerData.endTime = new Date(routerData.endTime)
+           routerData.paperInfo = []
         //    for (let i = 0; i < routerData.paperInfo.length; i++) {
         //        routerData.paperInfo[i].createType = 'manualPaper'
         //    }
-        //    this.evaluationInfo = routerData
-        //    this.activeTab = 'preview'
-        //}
+           this.evaluationInfo = routerData
+           this.activeTab = 'preview'
+           this.$Message.warning('编辑评测功能尚未完善')
+        }
     },
     mounted() {
         this.startTime = new Date()

+ 6 - 0
TEAMModelOS/ClientApp/src/view/learnactivity/MgtPrivEva.less

@@ -258,3 +258,9 @@
     color: white;
     border-radius: 2px;
 }
+.mock-stu-answer{
+    margin-right: 20px;
+}
+.mock-tea-scoring{
+    margin-right: 40px;
+}

+ 66 - 4
TEAMModelOS/ClientApp/src/view/learnactivity/MgtPrivEva.vue

@@ -54,6 +54,15 @@
                     <span :class="curBarIndex == 1 ? 'evalustion-bar-item line-bottom-active line-bottom':'evalustion-bar-item line-bottom'" @click="selectBar(1)">
                         {{$t('learnActivity.mgtScEv.tab2')}}
                     </span>
+                    <!-- <div style="float:right;" v-show="evaListShow[curEvaIndex] && evaListShow[curEvaIndex].progress == 'going'"> -->
+                    <div style="float:right;">
+                        <Tooltip :content="$t('learnActivity.mgtScEv.autoTips1')" :max-width="240">
+                            <Button type="success" size="small" :loading="answerLoading" class="mock-stu-answer" @click="mockAnswer">{{$t('learnActivity.mgtScEv.autoAnswer')}}</Button>
+                        </Tooltip>
+                        <Tooltip :content="$t('learnActivity.mgtScEv.autoTips2')" :max-width="240">
+                            <Button type="warning" size="small" :loading="scoreLoading" class="mock-tea-scoring" @click="mockScoring">{{$t('learnActivity.mgtScEv.autoScore')}}</Button>
+                        </Tooltip>
+                    </div>
                 </div>
                 <!--试卷信息-->
                 <div :class="curBarIndex == 1 ? 'animated fadeIn evaluation-base-info':'evaluation-base-info animated fadeOutRight'" v-show="curBarIndex == 1">
@@ -86,6 +95,7 @@ export default {
         TestPaper,
         Scoring
     },
+    inject: ['reload'],
     data() {
         return {
             split1: 0.2,
@@ -102,10 +112,56 @@ export default {
             filterPeriod: undefined,
             schoolBase: {
                 period: []
-            }
+            },
+            scoreLoading: false,
+            answerLoading: false
         }
     },
     methods: {
+        // 模拟教师评分数据
+        mockScoring() {
+            this.scoreLoading = true
+            this.$api.learnActivity.mockScoring({
+                id: this.evaListShow[this.curEvaIndex].id,
+                code: this.evaListShow[this.curEvaIndex].code.replace('Exam-', '')
+            }).then(
+                res => {
+                    setTimeout(() => {
+                        this.$Message.success(this.$t('learnActivity.mgtScEv.mockOk'))
+                    }, 500)
+                },
+                err => {
+                    this.$Message.error(this.$t('learnActivity.mgtScEv.mockErr'))
+                }
+            ).finally(() => {
+                setTimeout(() => {
+                    this.scoreLoading = false
+                    this.reload()
+                }, 500)
+            })
+        },
+        // 模拟学生作答数据
+        mockAnswer() {
+            this.answerLoading = true
+            this.$api.learnActivity.mockAnswer({
+                id: this.evaListShow[this.curEvaIndex].id,
+                code: this.evaListShow[this.curEvaIndex].code.replace('Exam-', '')
+            }).then(
+                res => {
+                    setTimeout(() => {
+                        this.$Message.success(this.$t('learnActivity.mgtScEv.mockOk'))
+                    }, 500)
+                },
+                err => {
+                    this.$Message.error(this.$t('learnActivity.mgtScEv.mockErr'))
+                }
+            ).finally(() => {
+                setTimeout(() => {
+                    this.answerLoading = false
+                    this.reload()
+                }, 500)
+            })
+        },
         handleEnd(index) {
             this.$Modal.confirm({
                 title: this.$t('learnActivity.mgtScEv.stopTitle'),
@@ -297,10 +353,16 @@ export default {
                 async res => {
                     if (!res.error) {
                         let resData = res.examInfo[0]
+                        resData.score = 0
                         for (let index in resData.papers) {
-                            resData.papers[index].scope = resData.scope
-                            resData.papers[index].examId = resData.id
-                            resData.papers[index] = await this.$evTools.getFullPaper(resData.papers[index])
+                            resData.score += resData.papers[index].point.reduce((total, item) => {
+                                return total + parseInt(item)
+                            }, 0)
+                            if (resData.papers[index].blob) {
+                                resData.papers[index].scope = resData.scope
+                                resData.papers[index].examId = resData.id
+                                resData.papers[index] = await this.$evTools.getFullPaper(resData.papers[index])
+                            }
                         }
                         this.evaListShow.splice(this.curEvaIndex, 1, resData)
                         this.examDetaiInfo = resData

+ 9 - 17
TEAMModelOS/ClientApp/src/view/learnactivity/MgtSchoolEva.vue

@@ -17,7 +17,7 @@
                     </Dropdown>
                     <Icon type="md-add" class=" to-create-icon" @click="goToCreate" :title="$t('learnActivity.mgtScEv.create')" />
                     <Icon type="md-trash" v-show="evaListShow.length" class="to-create-icon" :title="$t('learnActivity.mgtScEv.delete')" @click="deleteEvaluation" />
-                    <Icon type="md-create" v-show="evaListShow.length" class="to-create-icon" @click="editEvaluation" :title="$t('learnActivity.mgtScEv.edit')" />
+                    <Icon type="md-create" v-show="evaListShow.length && evaListShow[curEvaIndex] && evaListShow[curEvaIndex].progress == 'pending'" class="to-create-icon" @click="editEvaluation" :title="$t('learnActivity.mgtScEv.edit')" />
                 </div>
                 <div class="evaluation-list-main">
                     <vuescroll>
@@ -63,7 +63,7 @@
                     <span :class="curBarIndex == 1 ? 'evalustion-bar-item line-bottom-active line-bottom':'evalustion-bar-item line-bottom'" @click="selectBar(1)">
                         {{$t('learnActivity.mgtScEv.tab2')}}
                     </span>
-                    <div style="float:right;" v-if="$access.ability('admin','mock-eva').validateAll" v-show="evaListShow[curEvaIndex].progress == 'going'">
+                    <div style="float:right;" v-if="$access.ability('admin','mock-eva').validateAll" v-show="evaListShow[curEvaIndex] && evaListShow[curEvaIndex].progress == 'going'">
                         <Tooltip :content="$t('learnActivity.mgtScEv.autoTips1')" :max-width="240">
                             <Button type="success" size="small" :loading="answerLoading" class="mock-stu-answer" @click="mockAnswer">{{$t('learnActivity.mgtScEv.autoAnswer')}}</Button>
                         </Tooltip>
@@ -99,9 +99,6 @@
                 </div>
             </div>
         </Split>
-        <!-- <Modal v-model="editEvaluationStatus" title="编辑" @on-ok="confirmEdit">
-            <p>即将跳转到评测编辑页面?</p>
-        </Modal> -->
     </div>
 </template>
 <script>
@@ -120,7 +117,6 @@ export default {
             split1: 0.2,
             scope: '',//school 校本 private 个人
             showBack: false,
-            editEvaluationStatus: false,
             curSubIndex: 0,
             curBarIndex: 0,
             curEvaIndex: 0,
@@ -193,6 +189,7 @@ export default {
                             if (!res.error) {
                                 this.$Message.success(this.$t('learnActivity.mgtScEv.stopOk'))
                                 this.evaListShow[index].progress = 'finish'
+                                this.reload()
                             } else {
                                 this.$Message.error('API ERROR!')
                             }
@@ -308,19 +305,15 @@ export default {
                 this.$Message.warning(this.$t('learnActivity.mgtScEv.noJoin'))
             }
         },
-        confirmEdit() {
-            let evaluationInfo = this.evaluationList[this.curEvaIndex]
-            evaluationInfo.testPaper = this.examDetaiInfo
+        editEvaluation() {
+            // this.$Message.warning('暂未处理编辑评测功能!')
             this.$router.push({
-                name: 'createEvaluation',
-                params: {
-                    evaluationInfo
+                name:'createSchoolEva',
+                params:{
+                    evaluationInfo: this.examDetaiInfo
                 }
             })
         },
-        editEvaluation() {
-            this.$Message.warning('暂未处理编辑评测功能!')
-        },
         selectSubject(index) {
             this.curSubIndex = index
         },
@@ -391,7 +384,7 @@ export default {
                 this.examDetaiInfo = this.evaListShow[this.curEvaIndex]
             }
         },
-        //查询当前评测的试卷信息
+        //查询当前评测的详细信息
         findExamPaper() {
             let requestData = {
                 id: this.evaListShow[this.curEvaIndex].id,
@@ -404,7 +397,6 @@ export default {
                         let resData = res.examInfo[0]
                         resData.score = 0
                         for (let index in resData.papers) {
-                            
                             resData.papers[index].scope = resData.scope
                             resData.papers[index].examId = resData.id
                             resData.papers[index] = await this.$evTools.getFullPaper(resData.papers[index])

+ 24 - 25
TEAMModelOS/ClientApp/src/view/learnactivity/Scoring.vue

@@ -76,7 +76,7 @@ export default {
     },
     data() {
         return {
-            originData:[],
+            originData: [],
             studentScore: [],
             tableData: [],
             currentPage: 1,
@@ -128,7 +128,7 @@ export default {
                 }
             ],
             tableColumn: [],
-            
+
             quCount: [],
             paperInfo: {},
             students: [],
@@ -155,8 +155,8 @@ export default {
                 default:
                     break
             }
-            console.log('1',this.studentScore[0].name)
-            console.log(2,this.originData[0].name)
+            console.log('1', this.studentScore[0].name)
+            console.log(2, this.originData[0].name)
             this.pageChange(1)
         },
         // 页面size变化
@@ -259,15 +259,18 @@ export default {
             if (!this.chooseClass) return;
             let requestData = {
                 id: this.chooseClass,
-                scope: this.routerScope,
-                school_code: this.routerScope == 'school' ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId,
+                scope: this.examInfo.scope == 'private' ? 'private' : 'school',
+                school_code: this.examInfo.scope == 'private' ? this.$store.state.userInfo.TEAMModelId : this.$store.state.userInfo.schoolCode,
             };
             this.$api.schoolSetting.getClassroomStudent(requestData).then((res) => {
                 if (!res.error) {
                     if (!this.paperInfo[this.chooseClass]) {
                         this.paperInfo[this.chooseClass] = {}
                     }
-                    this.$set(this.paperInfo[this.chooseClass], "students", res.classrooms[0]);
+                    this.$set(this.paperInfo[this.chooseClass], "students", res.classrooms[0])
+                    this.students = []
+                    this.tableData = []
+                    this.studentScore = []
                     this.getStudentAnswer();
                 } else {
                     this.$Message.error("API ERROR!");
@@ -329,29 +332,29 @@ export default {
         },
         //初始化表单数据
         setTableData() {
-            if (this.paperInfo[this.chooseClass]) {
-                let studentData = this.paperInfo[this.chooseClass]["students"];
-                let studentAns = this.paperInfo[this.chooseClass]["studentAns"];
-                this.studentScore = [];
-                this.tableColumn = [...this.scoreList];
-                this.quCount = studentAns.studentScores[0] ? studentAns.studentScores[0].length : 0;
+            if (this.paperInfo[this.chooseClass] && this.paperInfo[this.chooseClass]["students"] && this.paperInfo[this.chooseClass]["studentAns"]) {
+                let studentData = this.paperInfo[this.chooseClass]["students"]
+                let studentAns = this.paperInfo[this.chooseClass]["studentAns"]
+                this.studentScore = []
+                this.tableColumn = [...this.scoreList]
+                this.quCount = studentAns.studentScores[0] ? studentAns.studentScores[0].length : 0
                 for (let i = 0; i < this.quCount; i++) {
                     let data = {
                         title: "Q" + (i + 1),
                         slot: "qu" + i,
                         align: "center",
                         minWidth: 65,
-                    };
+                    }
                     this.tableColumn.push(data);
                 }
-                let ans = [];
+                let ans = []
                 for (let i = 0; i < studentAns.studentIds.length; i++) {
                     for (let k = 0; k < studentData.students.length; k++) {
-                        let score = {};
+                        let score = {}
                         if (studentAns.studentIds[i] == studentData.students[k].id) {
-                            score.name = studentData.students[k].name;
-                            score.id = studentAns.studentIds[i];
-                            score.data = studentAns.studentScores[i];
+                            score.name = studentData.students[k].name
+                            score.id = studentAns.studentIds[i]
+                            score.data = studentAns.studentScores[i]
                             score.total = this.getcount(score.data)
                             if (studentAns.studentAnswers[i].length == 0) {//学生未作答
                                 score.status = 1
@@ -360,7 +363,7 @@ export default {
                             } else {//已批改
                                 score.status = 3
                             }
-                            this.studentScore.push(score);
+                            this.studentScore.push(score)
                         }
                     }
                 }
@@ -368,11 +371,7 @@ export default {
                 this.students = this._.cloneDeep(this.studentScore)
                 this.pageChange(1)
                 if (ans.length) {
-                    for (
-                        let k = 0;
-                        k < this.paperInfo.papers.item.length;
-                        k++
-                    ) {
+                    for (let k = 0; k < this.paperInfo.papers.item.length; k++) {
                         this.$set(
                             this.paperInfo.papers.item[k],
                             "answerData",

+ 36 - 20
TEAMModelOS/ClientApp/src/view/learnactivity/SimpleAnalysis.vue

@@ -78,6 +78,14 @@
                 </span>
             </div>
         </div>
+        <div v-show="calculating">
+            <p style="text-align: center;color: white;margin: 20px 0px;">
+                成绩数据结算中,
+                <span style="text-decoration: underline;color: #1cc0f3;cursor: pointer;" @click="reload()">
+                    点此刷新
+                </span>
+            </p>
+        </div>
     </div>
 </template>
 <script>
@@ -88,6 +96,7 @@ export default {
         AvgCompare,
         ScoreMatrix
     },
+    inject: ['reload'],
     props: {
         examInfo: {
             default: () => {
@@ -114,7 +123,8 @@ export default {
     data() {
         return {
             simpleData: {},
-            allData: {}
+            allData: {},
+            calculating: false
         }
     },
     methods: {
@@ -127,20 +137,26 @@ export default {
             this.$api.learnActivity.simpleAna(requestData).then(
                 res => {
                     if (!res.error) {
-                        for (let i in res.averageMap) {
-                            for (let j in res.averageMap[i].ClassAverage) {
-                                res.averageMap[i].ClassAverage[j] = parseFloat(res.averageMap[i].ClassAverage[j].toFixed(2))
-                            }
-                            let subject = this.examInfo.papers.find(item=>{
-                                return item.subjectId == res.averageMap[i].subjectId
-                            })
-                            if(subject){
-                                res.averageMap[i].subjectId = subject.subjectName
+                        if (res.averageMap.length && res.averageMap.length) {
+                            this.calculating = false
+                            for (let i in res.averageMap) {
+                                for (let j in res.averageMap[i].ClassAverage) {
+                                    res.averageMap[i].ClassAverage[j] = parseFloat(res.averageMap[i].ClassAverage[j].toFixed(2))
+                                }
+                                let subject = this.examInfo.papers.find(item => {
+                                    return item.subjectId == res.averageMap[i].subjectId
+                                })
+                                if (subject) {
+                                    res.averageMap[i].subjectId = subject.subjectName
+                                }
                             }
+                            this.allData[this.examInfo.id] = res
+                            this.simpleData = res
+                        } else {
+                            this.calculating = true
+                            this.$Message.error('数据结算中,请稍后查看')
                         }
 
-                        this.allData[this.examInfo.id] = res
-                        this.simpleData = res
                     } else {
                         this.$Message.error('API ERROR!')
                     }
@@ -156,7 +172,7 @@ export default {
     watch: {
         examInfo: {
             handler() {
-                console.log('评测信息:',this.examInfo)
+                console.log('评测信息:', this.examInfo)
                 if (this.examInfo.progress == 'finish') {
                     if (this.allData[this.examInfo.id]) {
                         this.simpleData = this.allData[this.examInfo.id]
@@ -206,23 +222,23 @@ export default {
             }
         },
         scoreSegment() {
-            if (this.examScore > 0 && this.stuTotalScores.length) {
+            if (this.stuTotalScores.length) {
                 let segment = []
-                let max = Math.max(...this.stuTotalScores)
                 let unit = this.examScore / 10
-                for(let i = 0; i < 10; i++){
+                console.log('unit', unit)
+                for (let i = 0; i < 10; i++) {
                     let startScore = unit * i
                     let endScore = unit * (i + 1)
-                    let s = this.stuTotalScores.filter(item=>{
+                    let s = this.stuTotalScores.filter(item => {
                         return item >= startScore && item < endScore
                     })
                     segment.push({
-                        name:`${startScore}-${endScore}`,
-                        value:s.length
+                        name: `${startScore}-${endScore}`,
+                        value: s.length
                     })
                 }
                 return segment
-            }else{
+            } else {
                 return []
             }
 

+ 1 - 0
TEAMModelOS/ClientApp/src/view/learnactivity/echarts/ScoreMatrix.vue

@@ -92,6 +92,7 @@ export default {
     watch: {
         pieData: {
             handler(n, o) {
+                console.log('新的',this.pieData)
                 this.$nextTick(() => {
                     if (!this.progressPie) {
                         this.progressPie = this.$echarts.init(document.getElementById('ev-score-matrix'))

+ 12 - 3
TEAMModelOS/Controllers/Analysis/AnalysisController.cs

@@ -339,14 +339,23 @@ namespace TEAMModelOS.Controllers.Analysis
                         fieldClassTotal.Add(new KeyValuePair<string, List<double>>(sub, fields));
 
                     });
+
                     classStudents.ForEach(x => {
                         studentIds.Add(x.id);
                         x.classId = classId;
                         x.className = classroom.name;
                         x.gradeId = classroom.gradeId;
-                        var stu = classroom.students.Where(s => s.id == x.id).First();
-                        x.name = stu.name;
-                        x.no = stu.no;
+                        var stu = classroom.students.Where(s => s.id == x.id).FirstOrDefault();
+                        if (stu != null)
+                        {
+                            x.name = stu.name;
+                            x.no = stu.no;
+                        }
+                        else {
+                            x.name =x.id;
+                            x.no = "-";
+                        }
+                       
                         //标准差
                         powSum += Math.Pow(x.total - totalAverage, 2);
                         //进线人数

+ 50 - 9
TEAMModelOS/Controllers/Client/HiTeachController.cs

@@ -170,7 +170,7 @@ namespace TEAMModelOS.Controllers.Client
             {
                 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;
@@ -783,20 +783,56 @@ namespace TEAMModelOS.Controllers.Client
                 if (!jwt.Payload.Iss.Equals("account.teammodel", StringComparison.Ordinal)) return BadRequest();
                 var id = jwt.Payload.Sub;
 
-
                 if (!request.TryGetProperty("exam", out JsonElement exam)) return BadRequest();
-                //if (!request.TryGetProperty("examResult", out JsonElement examResult)) return BadRequest();
                 if (!request.TryGetProperty("examClassResult", out JsonElement examClassResult)) return BadRequest();
 
                 ExamInfo dbExamInfo = exam.ToObject<ExamInfo>();
-                //ExamResult dbExamResult = examResult.ToObject<ExamResult>();
-                List<ExamClassResult> dbExamClassResultList = examClassResult.ToObject<List<ExamClassResult>>();
+                List<ExamClassResultStudentAnswerArray> dbExamClassResultList = examClassResult.ToObject<List<ExamClassResultStudentAnswerArray>>();
 
+                //ExamInfo內容取得、調整
+                string blobContainer = (dbExamInfo.range == "school" && dbExamInfo.scope == "school" && dbExamInfo.school != null) ? dbExamInfo.school : id; //blob容器
+                dbExamInfo.source = "1"; //評測來源固定為  1:課中評量 
+                //UPDATE
                 var examResponse = _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Common").UpsertItemAsync(dbExamInfo, new PartitionKey(dbExamInfo.code)).GetAwaiter().GetResult();
-                //var examResultResponse = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Common").UpsertItemAsync(dbExamResult, new PartitionKey(dbExamResult.code));
-                foreach (ExamClassResult examClassResultRow in dbExamClassResultList)
-                {
-                    var examClassResultResponse = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Common").UpsertItemAsync(examClassResultRow, new PartitionKey(examClassResultRow.code));
+                
+                //ExamClassResult內容調整
+                foreach (ExamClassResultStudentAnswerArray examClassResultRow in dbExamClassResultList)
+                {
+                    ExamClassResult examClassResultUpd = new ExamClassResult();
+                    examClassResultUpd.pk = examClassResultRow.pk;
+                    examClassResultUpd.code = examClassResultRow.code;
+                    examClassResultUpd.id = examClassResultRow.id;
+                    examClassResultUpd.school = examClassResultRow.school;
+                    examClassResultUpd.examId = examClassResultRow.examId;
+                    examClassResultUpd.subjectId = examClassResultRow.subjectId;
+                    examClassResultUpd.gradeId = examClassResultRow.gradeId;
+                    examClassResultUpd.year = examClassResultRow.year;
+                    examClassResultUpd.info = examClassResultRow.info;
+                    examClassResultUpd.progress = examClassResultRow.progress;
+                    examClassResultUpd.studentIds = examClassResultRow.studentIds;
+                    examClassResultUpd.studentAnswers = new List<List<string>>();
+                    examClassResultUpd.studentScores = examClassResultRow.studentScores;
+                    examClassResultUpd.scope = examClassResultRow.scope;
+                    examClassResultUpd.sum = examClassResultRow.sum;
+
+                    string examId = examClassResultRow.examId;
+                    string subjectId = examClassResultRow.subjectId;
+                    //examClassResult.studentAnswers 將學生答案上傳blob後轉換內容為blob路徑
+                    if (examClassResultRow.studentIds != null && examClassResultRow.studentIds.Count > 0 && examClassResultRow.studentAnswersArray != null && examClassResultRow.studentAnswersArray.Count > 0)
+                    {
+                        for (int i = 0; i < examClassResultRow.studentAnswersArray.Count; i++)
+                        {
+                            string studentId = examClassResultRow.studentIds[i];
+                            string fileName = examId + "/" + subjectId + "/" + studentId;
+                            string blob = fileName + "/" + "ans.json";
+                            await _azureStorage.UploadFileByContainer(blobContainer, examClassResultRow.studentAnswersArray[i].ToJsonString(), "exam", blob, false);
+                            List<string> studenrAnswerRow = new List<string>();
+                            studenrAnswerRow.Add(blob);
+                            examClassResultUpd.studentAnswers.Add(studenrAnswerRow);
+                        }
+                    }
+                    //UPDATE
+                    var examClassResultResponse = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Common").UpsertItemAsync(examClassResultUpd, new PartitionKey(examClassResultUpd.code));
                 }
 
                 return Ok(new { error, message });
@@ -874,5 +910,10 @@ namespace TEAMModelOS.Controllers.Client
             }
         }
 
+        public class ExamClassResultStudentAnswerArray : ExamClassResult
+        {
+            public List<List<List<string>>> studentAnswersArray { get; set; }
+        }
+
     }
 }

+ 5 - 1
TEAMModelOS/Controllers/Common/ExamController.cs

@@ -73,7 +73,7 @@ namespace TEAMModelOS.Controllers
                     int count = 0;
                     for (int i = 0; i < request.targetClassIds.Count; i++)
                     {
-                        if (request.scope.Equals("private"))
+                        if (request.scope.Equals("private") || request.scope.Equals("teacher"))
                         {
                              var sresponse = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemStreamAsync(request.targetClassIds[i], new PartitionKey($"Class-{code}"));
                             if (sresponse.Status == 200)
@@ -370,6 +370,10 @@ namespace TEAMModelOS.Controllers
                     int newIndex = result.studentIds.IndexOf(studentId.ToString());
                     /*if (flagCount != standard.Count)
                     {*/
+/*                    StringBuilder builder = new StringBuilder();
+                    builder.Append(result.examId + "/");
+                    builder.Append(result.subjectId + "/");
+                    builder.Append(studentId);*/
                         string FileName = result.examId + "/" + result.subjectId + "/" + studentId;
                         string blob = FileName + "/" + "ans.json";
                         tasks.Add(_azureStorage.UploadFileByContainer(school.ToString(), ans.ToJsonString(), "exam", FileName + "/" + "ans.json", false));

+ 48 - 15
TEAMModelOS/Controllers/Core/BlobController.cs

@@ -18,6 +18,8 @@ using Microsoft.AspNetCore.Authorization;
 using TEAMModelOS.Filter;
 using StackExchange.Redis;
 using Azure.Messaging.ServiceBus;
+using static TEAMModelOS.SDK.DI.AzureStorageBlobExtensions;
+using System.Linq;
 
 namespace TEAMModelOS.Controllers.Core
 {
@@ -235,7 +237,6 @@ namespace TEAMModelOS.Controllers.Core
         [HttpPost("get-blobsize")]
         public async Task<ActionResult> GetBlobsSize(JsonElement request)
         {
-            
             request.TryGetProperty("containerName", out JsonElement containerName);
             request.TryGetProperty("cache", out JsonElement cache);
             var name =containerName.GetString();
@@ -259,24 +260,57 @@ namespace TEAMModelOS.Controllers.Core
                     {
                         foreach (var score in Scores) {
                             double val = score.Score;
-                           // string key= score.Element
+                            string key = score.Element.ToString();
+                            catalog.Add(key, val);
                         }   
                     }
-                    return Ok(new { size = blobsize });
+                    return Ok(new { size = blobsize, catalog= catalog });
                 }
             } catch { }
             var client = _azureStorage.GetBlobContainerClient(name);
             var size = await client.GetBlobsCatalogSize();
-
             await _azureRedis.GetRedisClient(8).HashSetAsync($"Blob:Record", name, size.Item1);
             foreach (var key in size.Item2.Keys) {
+                await _azureRedis.GetRedisClient(8).SortedSetRemoveAsync($"Blob:Catalog:{name}", key);
                 await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Blob:Catalog:{name}", key, size.Item2[key].HasValue?size.Item2[key].Value:0);
             }
             return Ok(new { size = size.Item1, catalog = size.Item2 });
         }
+
         /// <summary>
         /// 测试单个文本内容的上传
-        /// {"containerName":"hbcn","uploadSize":5000,"optUrls":[]}
+        /// {"containerName":"hbcn","urls":["video/xxx.mp4","res/xxx.png"]}
+        /// </summary>
+        /// <param name="azureBlobSASDto"></param>
+        /// <returns></returns>
+        [HttpPost("check-blobsize")]
+        public async Task<ActionResult> checkBlobsSize(JsonElement request)
+        {
+            request.TryGetProperty("containerName", out JsonElement containerName);
+            request.TryGetProperty("urls", out JsonElement optUrls);
+            var name = containerName.GetString();
+            var urls = optUrls.ToObject<List<string>>();
+            var client = _azureStorage.GetBlobContainerClient(name);
+            var urlsSize = await client.GetBlobsSize(urls);
+            return Ok(new {  urlsSize });
+        }
+
+        /*
+         * 
+         {
+            "containerName": "hbcn",
+            "cache": true,
+            "optUrls": [
+                {
+                    "url": "video%2F37Z888piCvm9.mp4",
+                    "size": 1000
+                }
+            ]
+         }
+        */
+        /// <summary>
+        /// 测试单个文本内容的上传
+        /// {"containerName":"hbcn","uploadSize":5000,"optUrls":[{"url":"video/37Z888piCvm9.mp4","size":0},{}]}
         /// </summary>
         /// <param name="azureBlobSASDto"></param>
         /// <returns></returns>
@@ -285,28 +319,27 @@ namespace TEAMModelOS.Controllers.Core
         {
             request.TryGetProperty("containerName", out JsonElement containerName);
             request.TryGetProperty("optUrls", out JsonElement optUrls);
-            request.TryGetProperty("uploadSize", out JsonElement uploadSize);
             var name = containerName.GetString();
-            uploadSize.TryGetInt64(out long size);
-            var urls = optUrls.ToObject<List<string>>();
+            var urls = optUrls.ToObject<List<OptUrl>>();
             var client = _azureStorage.GetBlobContainerClient(name);
-            var urlsSize = await client.GetBlobsSize(urls);
-            long? disSize= size - urlsSize;
+            var disSize = urls.Select(x => x.size).Sum();
             RedisValue value = default;
-            long? useSize = 0;
             long blobSize = 0;
             value = _azureRedis.GetRedisClient(8).HashGet($"Blob:Record", name);
             if (value != default && !value.IsNullOrEmpty)
             {
                 JsonElement record = value.ToString().ToObject<JsonElement>();
-                if (record.TryGetInt64(out   blobSize))
+                if (record.TryGetInt64(out blobSize))
                 {
-                    useSize = blobSize;
                 }
             }
-            useSize = useSize + disSize;
+            long? useSize = blobSize + disSize;
             await _azureRedis.GetRedisClient(8).HashSetAsync($"Blob:Record", name, useSize);
-            var messageBlob = new ServiceBusMessage(new {id=Guid.NewGuid().ToString(), progress = "update",code=name}.ToJsonString());
+             
+            foreach (var x in urls) {
+                await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Blob:Catalog:{name}", System.Web.HttpUtility.UrlDecode(x.url, Encoding.UTF8).Split("/")[0], x.size);
+            }
+            var messageBlob = new ServiceBusMessage(new {id=Guid.NewGuid().ToString(), progress = "update",name=name}.ToJsonString());
             messageBlob.ApplicationProperties.Add("name", "Blob");
             await _serviceBus.GetServiceBusClient().SendMessageAsync("active-task", messageBlob);
             return Ok(new { size=useSize });

+ 0 - 1
TEAMModelOS/TEAMModelOS.csproj

@@ -51,7 +51,6 @@
   <ItemGroup>
     <Folder Include="JwtRsaFile\" />
     <Folder Include="Services\Evaluation\" />
-    <Folder Include="wwwroot\" />
   </ItemGroup>
   
   <ItemGroup>