Bläddra i källkod

Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd

CrazyIter_Bin 4 år sedan
förälder
incheckning
ae13e89a27

+ 29 - 6
TEAMModelFunction/TriggerExam.cs

@@ -206,11 +206,31 @@ namespace TEAMModelFunction
                                         var sresponse = await client.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(cla, new Azure.Cosmos.PartitionKey($"Class-{info.school}"));
                                         if (sresponse.Status == 200)
                                         {
+
                                             using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
                                             Class classroom = json.ToObject<Class>();
+                                            School sc = await client.GetContainer("TEAMModelOS", "School").ReadItemAsync<School>(info.school, new Azure.Cosmos.PartitionKey("Base"));
+                                            foreach (Period period in sc.period)
+                                            {
+                                                if (period.id.Equals(classroom.periodId))
+                                                {
+                                                    foreach (Semester semester in period.semesters)
+                                                    {
+                                                        if (semester.start == 1)
+                                                        {
+                                                            int year = DateTimeOffset.UtcNow.Year;
+                                                            int month = DateTimeOffset.UtcNow.Month;
+                                                            int day = DateTimeOffset.UtcNow.Day;
+                                                            int time =  month > semester.month ?  0 :  1;
+                                                            int eyear = year - time;
+                                                            result.gradeId = (year - eyear).ToString();
+                                                        }
+                                                    }
+                                                }
+                                            }
                                             //result.info.id = classroom.id;
                                             result.info.name = classroom.name;
-                                            result.gradeId = classroom.gradeId;
+                                            //result.gradeId = classroom.year.ToString();
                                             //处理班级人数
                                             await foreach (var item in client.GetContainer("TEAMModelOS", "Student").GetItemQueryStreamIterator(queryText: $"select c.id from c where c.classId = '{classroom.id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Base-{info.school}") }))
                                             {
@@ -535,7 +555,8 @@ namespace TEAMModelFunction
                 int plcount = 0;
                 //存放并去重知识点
                 HashSet<string> kname = new HashSet<string>();
-                if (info.papers[no].knowledge.Count > 0) {
+                if (info.papers[no].knowledge.Count > 0)
+                {
                     info.papers[no].knowledge.ForEach(kno =>
                     {
                         kno.ForEach(k =>
@@ -631,7 +652,7 @@ namespace TEAMModelFunction
                         //await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(classResult, classResult.id, new Azure.Cosmos.PartitionKey($"{classResult.code}"));
                     }
                 }
-                
+
             }
             catch (Exception ex)
             {
@@ -672,7 +693,8 @@ namespace TEAMModelFunction
                             int phCount = 0;
                             int plCount = 0;
                             int pCount = 0;
-                            if (info.papers[no].field.Count > 0) {
+                            if (info.papers[no].field.Count > 0)
+                            {
                                 foreach (int str in info.papers[no].field)
                                 {
                                     if (str == knowledgeName[i])
@@ -720,7 +742,7 @@ namespace TEAMModelFunction
                                 pl.Add(plCount);
                                 double per = classResult.studentIds.Count > 0 ? Math.Round(score / classResult.studentIds.Count, 2) : 0;
                                 persent.Add(allScore > 0 ? per / allScore : 0);
-                            }                           
+                            }
                         }
                         classResult.fphc = ph;
                         classResult.fplc = pl;
@@ -858,7 +880,8 @@ namespace TEAMModelFunction
                         csRate.Add(classResult.studentIds.Count > 0 ? Math.Round(classSrate * 1.0 / classResult.studentIds.Count, 2) : 0 / allScore);
 
                     }
-                    else {
+                    else
+                    {
                         csRate.Add(0);
                     }
 

+ 0 - 1
TEAMModelOS/ClientApp/src/view/answersheet/BaseEditor.vue

@@ -1,7 +1,6 @@
 <template>
 	<div class="base-editor-wrap">
 		<div :id="ids + 'btn'" class="base-editor-tools" v-show="isShowTools">
-<!-- 		<div :id="ids + 'btn'" class="base-editor-tools" v-show="isShowTools" @mouseenter="isShowTools = true" @mouseleave="isShowTools = false"> -->
 			<span class="select-model" @click="onSelectModal" v-if="type !== '0'">编辑</span>
 			<span class="select-model btn-delete" @click="onDeleteBlock" v-if="!isAutoCreate">删除</span>
 		</div>

+ 8 - 4
TEAMModelOS/ClientApp/src/view/answersheet/SheetBaseInfo.vue

@@ -73,6 +73,7 @@ export default {
       let snap = this.snap;
       this.infoLeftBox = snap.paper.g();
       let gap = INFO_H / (this.showInfoList.length + 1);
+	  let lineWidth = INFO_W - this.idLength * 30
       this.showInfoList.forEach((item, index) => {
         // 考号、座号、姓名等
         let leftInfo1 = snap.text(
@@ -85,7 +86,7 @@ export default {
           .line(
             CONTENT_START_X + 80,
             CONTENT_START_Y + INFO_ITEM_MARGIN + gap * index,
-            CONTENT_START_X + 250,
+            CONTENT_START_X + lineWidth - 40,
             CONTENT_START_Y + INFO_ITEM_MARGIN + gap * index
           )
           .attr({ fill: "none", stroke: "#000", strokeWidth: 1 });
@@ -100,13 +101,16 @@ export default {
       let snap = this.snap;
       this.idNumberBox.remove();
       this.idNumberBox = snap.paper.g();
+	  
+	  const CELL_WIDTH = 30
 
-      const INFO_LEFT_W = 275; // 左侧的宽度
+      const INFO_LEFT_W = INFO_W - CELL_WIDTH * idLength; // 左侧的宽度
       const INFO_LEFT_X =
         INFO_LEFT_W + CONTENT_ML + ANCHORPROP.width + ANCHORPROP.gapX; // 左侧的x坐标
 
       var numbers = new Array(idLength).fill("0");
-      var cellWidth = (INFO_W - INFO_LEFT_W) / idLength; // 计算每个号码的宽度
+      // var cellWidth = (INFO_W - INFO_LEFT_W) / idLength; // 计算每个号码的宽度
+      var cellWidth = CELL_WIDTH; // 计算每个号码的宽度
       const NUMBER_ITEM_MLR =
         ((INFO_W - INFO_LEFT_W) / idLength - NUMBER_ITEM_W) / 2; // 计算号码左右间距
 
@@ -136,7 +140,7 @@ export default {
       // 准考证号
       this.idNumberBox.add(
         snap.text(
-          INFO_LEFT_X + (INFO_LEFT_W - 20) / 2,
+          INFO_LEFT_X + (idLength * CELL_WIDTH - 69) / 2,
           CONTENT_MT + 75,
           "准 考 证 号"
         )

+ 14 - 2
TEAMModelOS/ClientApp/src/view/student-analysis/total-analysis/EvaluationList/TotalIndex.vue

@@ -78,7 +78,7 @@
 								<span class="el-filter-title">{{ $t("totalAnalysis.condition2") }}:</span>
 								<RadioGroup v-model="filterGrade" type="button" @on-change="filterGradeChange">
 									<Radio :label="$t('totalAnalysis.all')">{{ $t('totalAnalysis.all') }}</Radio>
-									<Radio v-for="(item, index) in filterGradeList" :label="item.name" :key="index">{{ item.name }}</Radio>
+									<Radio v-for="(item, index) in filterGradeList" :label="index" :key="index">{{ item }}</Radio>
 								</RadioGroup>
 							</div>
 							<div class="el-filter-item">
@@ -542,7 +542,7 @@
 					return (
 						JSON.stringify(item.period.name).indexOf(this.filterConditions.period || "") >
 						-1 &&
-						JSON.stringify(item.grades).indexOf(this.filterConditions.grade || "") >
+						JSON.stringify(item.grades.map(i => i.id)).indexOf(this.filterConditions.grade || "") >
 						-1 &&
 						JSON.stringify(item.subjects).indexOf(this.filterConditions.subject || "") >
 						-1 &&
@@ -611,6 +611,13 @@
 						});
 						continue
 					}
+					if (key == 'grade') {
+						arr.push({
+							keyName: key,
+							val: this.getGradeName(this.filterGrade),
+						});
+						continue
+					}
 					arr.push({
 						keyName: key,
 						val: obj[key],
@@ -681,6 +688,11 @@
 						2) * 100 + "%";
 				};
 			},
+			getGradeName(){
+				return index => {
+					return this.filterGradeList[index]
+				}
+			},
 			filterGradeList() {
 				let res = this.schoolData.period.find(item => {
 					return item.name == this.filterConditions.period

+ 6 - 3
TEAMModelOS/ClientApp/src/view/task/index.vue

@@ -228,12 +228,14 @@ export default {
                 let stuInfo = this.markData.attr.find(item => {
                     return item.stuId == stuId
                 })
-                answer = stuInfo.info.ans ? JSON.parse(await this.$tools.getFile(`${blobUrl}/exam/${stuInfo.info.ans}?${sas}`)) : []
+                let ansBlob = stuInfo.info.mark || stuInfo.info.ans 
+                answer = ansBlob ? JSON.parse(await this.$tools.getFile(`${blobUrl}/exam/${ansBlob}?${sas}`)) : []
                 score = stuInfo.info.score
                 sId = stuId
             } else {
                 let resData = await this.getNextStu()
-                answer = resData.ans.ans ? JSON.parse(await this.$tools.getFile(`${blobUrl}/exam/${resData.ans.ans}?${sas}`)) : []
+                let ansBlob = resData.info.mark || resData.info.ans 
+                answer = ansBlob ? JSON.parse(await this.$tools.getFile(`${blobUrl}/exam/${ansBlob}?${sas}`)) : []
                 score = resData.ans.score
                 sId = resData.stuId
             }
@@ -262,7 +264,8 @@ export default {
             let blobUrl = JSON.parse(decodeURIComponent(localStorage.school_profile, "utf-8")).blob_uri //目前只有校本评测安排阅卷任务
             // 获取学生作答数据
             this.markData.attr.forEach(async item => {
-                this.$set(item.info, 'answer', item.info.ans ? JSON.parse(await this.$tools.getFile(`${blobUrl}/exam/${item.info.ans}?${sas}`)) : [])
+                let ansBlob = item.info.mark || item.info.ans 
+                this.$set(item.info, 'answer', ansBlob ? JSON.parse(await this.$tools.getFile(`${blobUrl}/exam/${ansBlob}?${sas}`)) : [])
             })
             this.$router.push({
                 name: 'ByQu',

+ 29 - 10
TEAMModelOS/ClientApp/src/view/task/mark/ByQu.vue

@@ -51,7 +51,7 @@
                 <!-- <Icon :custom="isFull ? 'iconfont icon-cancel-full' : 'iconfont icon-full-screen'" class="tool-icon" :title="isFull ? '取消全屏' : '全屏'" @click="togglefull" /> -->
             </div>
             <div class="mark-stage">
-                <MarkCanvas :mouseStatus="mouseStatus" :bgImg="ansImg" :drawImgData="drawImgData"></MarkCanvas>
+                <MarkCanvas ref="markCanvas" :status="mouseStatus" :bgImg="ansImg" :drawImgData="drawImgData"></MarkCanvas>
             </div>
             <!-- 打分部分 -->
             <div class="score-wrap">
@@ -60,7 +60,7 @@
                     <InputNumber style="flex:1" :max="10" :min="1" v-model="score" @on-change="setScore"></InputNumber>
                 </div>
                 <div class="quick-score-box">
-                    <Button size="small" type="info" style="margin-right:8px" ghost @click="score = 10">满分</Button>
+                    <Button size="small" type="info" style="margin-right:8px" ghost @click="score = quScoreArr.length - 1">满分</Button>
                     <Button size="small" type="error" ghost @click="score = 0">零分</Button>
                     <Icon :type="isShowNum ? 'md-eye-off' : 'md-eye'" class="toggle-num-status" @click="isShowNum = !isShowNum" />
                     <div :class="['score-key-box', isShowNum ? '':'hind-key-box']">
@@ -114,7 +114,6 @@ export default {
             autoQu: true,//自动切换下一题
             autoStu: true,//自动获取下一学生
             toggleStatus: false,
-            activeIcon: -1,
             isShowNum: true,
             quIndex: 0,
             childIndex: -1,
@@ -134,15 +133,24 @@ export default {
             this.toggleStatus = false
         },
         drawImg(imgIndex) {
+            let curImg = new Image()
+            curImg.src = this.imgs[imgIndex]
+            curImg.onload = () => {
+                this.mouseStatus = 'img'
+                this.drawImgData = curImg
+            }
         },
         //清除所有批注
         clear() {
+            this.$refs['markCanvas'].clear()
         },
         /**将答案绘制到canvas上 */
         ansToImg() {
             let answerIframe = document.getElementById('markIframe1')
             answerIframe.onload = () => {
                 answerIframe.style.width = '850px'
+                answerIframe.style.margin = '0px'
+                answerIframe.contentWindow.document.body.style.margin = '0px'
                 answerIframe.contentWindow.document.body.style.margin = '0px 20px'
                 answerIframe.contentWindow.document.body.style.padding = '10px'
                 answerIframe.contentWindow.document.body.style.minWidth = '600px'
@@ -176,6 +184,15 @@ export default {
         //提交分数
         submit() {
             if (this.score > -1 && this.score != null) {
+                //保存批注
+                let mark
+                if (this.markImg) {
+                    let img = document.createElement('img')
+                    img.src = this.markImg
+                    this.stuAnswer[this.getScoreIndex(this.quIndex, this.childIndex)] = img.outerHTML
+                    mark = this.stuAnswer
+                    this.markImg = undefined
+                }
                 let requstData = {
                     id: this.taskInfo.id,
                     stuId: this.stusInfo[this.stuIndex].stuId,
@@ -184,7 +201,7 @@ export default {
                     score: this.stusInfo[this.stuIndex].info.score,
                     count: this.taskInfo.count,
                     code: this.taskInfo.ecode.replace('Exam-', ''),
-                    mark: ''
+                    mark
                 }
                 this.$api.mark.saveScore(requstData).then(
                     res => {
@@ -272,11 +289,12 @@ export default {
                 async res => {
                     let sas = this.$store.state.user.schoolProfile.blob_sas //目前只有校本评测安排阅卷任务
                     let blobUrl = JSON.parse(decodeURIComponent(localStorage.school_profile, "utf-8")).blob_uri //目前只有校本评测安排阅卷任务
+                    let ansBlob = res.ans.mark || res.ans.ans 
                     this.stusInfo.push({
                         stuId: res.stuId,
                         info: {
                             ans: res.ans.ans,
-                            answer: res.ans.ans ? await this.$tools.getFile(`${blobUrl}/exam/${res.ans.ans}?${sas}`) : [],
+                            answer: ansBlob ? await this.$tools.getFile(`${blobUrl}/exam/${ansBlob}?${sas}`) : [],
                             score: res.ans.score
                         }
                     })
@@ -310,11 +328,11 @@ export default {
     },
     computed: {
         //当前题目进度
-        curProg(){
-            let index = this.getScoreIndex(this.quIndex,this.childIndex)
+        curProg() {
+            let index = this.getScoreIndex(this.quIndex, this.childIndex)
             let marked = 0
-            this.stusInfo.forEach(item=>{
-                if(item.info.score[index] != -1){
+            this.stusInfo.forEach(item => {
+                if (item.info.score[index] != -1) {
                     marked++
                 }
             })
@@ -322,7 +340,8 @@ export default {
         },
         curAnswer() {
             if (this.stusInfo && this.stusInfo[this.stuIndex]) {
-                this.score = this.stusInfo[this.stuIndex].info.score[this.getScoreIndex(this.quIndex, this.childIndex)]
+                let s = this.stusInfo[this.stuIndex].info.score[this.getScoreIndex(this.quIndex, this.childIndex)]
+                this.score = s == -1 ? null : s
                 if (this.stusInfo[this.stuIndex].info.answer) {
                     return this.stusInfo[this.stuIndex].info.answer[this.getScoreIndex(this.quIndex, this.childIndex)]
                 } else {

+ 29 - 15
TEAMModelOS/ClientApp/src/view/task/mark/ByStu.vue

@@ -51,7 +51,7 @@
                 <!-- <Icon :custom="isFull ? 'iconfont icon-cancel-full' : 'iconfont icon-full-screen'" class="tool-icon" :title="isFull ? '取消全屏' : '全屏'" @click="togglefull" /> -->
             </div>
             <div class="mark-stage">
-                <MarkCanvas :mouseStatus="mouseStatus" :bgImg="ansImg" :drawImgData="drawImgData" style="padding-bottom:85px"></MarkCanvas>
+                <MarkCanvas ref="markCanvas" @getImg="saveMark" :status="mouseStatus" :bgImg="ansImg" :drawImgData="drawImgData" style="padding-bottom:85px"></MarkCanvas>
                 <!-- 题号显示部分 -->
                 <div class="qu-index-box">
                     <div class="qu-tips-box">
@@ -151,31 +151,35 @@ export default {
             stuScore: [],
             taskInfo: {},
             stusData: [],
-            stuId: ''
+            stuId: '',
+            markImg: undefined
         }
     },
     methods: {
+        //保存批注
+        saveMark(data) {
+            console.log(data)
+            this.markImg = data.base64
+        },
         drawImg(imgIndex) {
-            // this.activeIcon = imgIndex
-            // this.curImg = new Image()
-            // this.curImg.src = this.imgs[imgIndex]
-            // this.curImg.onload = () => {
-            //     this.mouseStatus = 'img'
-            //     this.startImg({ x: 100, y: 100 })
-            // }
+            let curImg = new Image()
+            curImg.src = this.imgs[imgIndex]
+            curImg.onload = () => {
+                this.mouseStatus = 'img'
+                this.drawImgData = curImg
+            }
         },
         //清除所有批注
         clear() {
-
-            // this.markLayer.removeChildren()
-            // this.stage.add(this.markLayer)
+            this.$refs['markCanvas'].clear()
         },
         /**将答案绘制到canvas上 */
         ansToImg() {
             let answerIframe = document.getElementById('markIframe')
             answerIframe.onload = () => {
                 answerIframe.style.width = '850px'
-                // answerIframe.contentWindow.document.body.style.margin = '0px 20px'
+                answerIframe.style.margin = '0px'
+                answerIframe.contentWindow.document.body.style.margin = '0px'
                 answerIframe.contentWindow.document.body.style.padding = '10px'
                 answerIframe.contentWindow.document.body.style.minWidth = '600px'
                 answerIframe.contentWindow.document.body.style.minHeight = '240px'
@@ -232,6 +236,15 @@ export default {
         //提交分数
         submit() {
             if (this.score > -1 && this.score != null) {
+                //保存批注
+                let mark
+                if (this.markImg) {
+                    let img = document.createElement('img')
+                    img.src = this.markImg
+                    this.stuAnswer[this.getScoreIndex(this.quIndex, this.childIndex)] = img.outerHTML
+                    mark = this.stuAnswer
+                    this.markImg = undefined
+                }
                 let requstData = {
                     id: this.taskInfo.id,
                     stuId: this.stuId,
@@ -240,7 +253,7 @@ export default {
                     score: this.stuScore,
                     count: this.taskInfo.count,
                     code: this.taskInfo.ecode.replace('Exam-', ''),
-                    mark: ''
+                    mark
                 }
                 this.$api.mark.saveScore(requstData).then(
                     res => {
@@ -379,7 +392,8 @@ export default {
                 if (stuInfo && !stuInfo.info.answer) {
                     let sas = this.$store.state.user.schoolProfile.blob_sas //目前只有校本评测安排阅卷任务
                     let blobUrl = JSON.parse(decodeURIComponent(localStorage.school_profile, "utf-8")).blob_uri //目前只有校本评测安排阅卷任务
-                    stuInfo.info.answer = stuInfo.info.ans ? JSON.parse(await this.$tools.getFile(`${blobUrl}/exam/${stuInfo.info.ans}?${sas}`)) : []
+                    let ansBlob = stuInfo.info.mark || stuInfo.info.ans
+                    stuInfo.info.answer = ansBlob ? JSON.parse(await this.$tools.getFile(`${blobUrl}/exam/${ansBlob}?${sas}`)) : []
                 }
                 this.stuAnswer = stuInfo.info.answer
                 this.stuScore = stuInfo.info.score

+ 53 - 59
TEAMModelOS/ClientApp/src/view/task/mark/MarkCanvas.vue

@@ -16,7 +16,7 @@ export default {
     name: 'MarkCanvas',
     props: {
         // 当前鼠标操作类型
-        mouseStatus: {
+        status: {
             type: String,
             default: 'move',
             required: true
@@ -28,12 +28,13 @@ export default {
         },
         //canvas绘制图片的数据(eg:添加表情包)
         drawImgData: {
-            type: [String, Object],
+            // type: [String, Object],
             default: ''
         }
     },
     data() {
         return {
+            imgData: undefined,
             stage: undefined,
             orgLayer: undefined,
             markLayer: undefined,
@@ -49,7 +50,7 @@ export default {
                 x: 0,
                 y: 0
             },
-            // mouseStatus: 'move', //move:移动  rect:画矩形 resize:调整图形
+            mouseStatus: '', //move:移动  rect:画矩形 resize:调整图形
             resizeBefore: '',
             rect: undefined,
             oval: undefined,
@@ -61,32 +62,20 @@ export default {
         }
     },
     methods: {
-        uuid() {
-            function S4() {
-                return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
-            }
-            return (S4() + S4() + '-' + S4() + '-' + S4() + '-' + S4() + '-' + S4() + S4() + S4())
-        },
-        move(index) {
-            this.activeIcon = index
+        move() {
             this.mouseStatus = 'move'
         },
-        drawImg(imgIndex) {
-            // this.activeIcon = imgIndex
-            // this.curImg = new Image()
-            // this.curImg.src = this.imgs[imgIndex]
-            // this.curImg.onload = () => {
-            //     this.mouseStatus = 'img'
-            //     this.startImg({ x: 100, y: 100 })
-            // }
+        drawImg() {
+            this.mouseStatus = 'img'
+            this.startImg({ x: 100, y: 100 })
         },
         startImg(current) {
             let _this = this
             this.img = new Konva.Image({
-                id: this.uuid(),
+                id: this.$tools.guid(),
                 draggable: false,
                 strokeScaleEnabled: false,
-                image: _this.curImg,
+                image: _this.imgData,
                 width: 80,
                 height: 80,
                 x: current.x,
@@ -113,8 +102,7 @@ export default {
             this.stage.add(this.markLayer)
             this.img = null
         },
-        drawText(index) {
-            this.activeIcon = index
+        drawText() {
             this.mouseStatus = 'text'
         },
         startText(current) {
@@ -123,7 +111,7 @@ export default {
             if (nodes.length > 0) return
             if (!this.text) {
                 this.text = new Konva.Text({
-                    id: this.uuid(),
+                    id: this.$tools.guid(),
                     fontSize: 16,
                     text: '',
                     fill: 'red',
@@ -206,21 +194,19 @@ export default {
                 this.text.x(current.x)
                 this.text.y(current.y)
             }
-            // this.text.zIndex(100)
             this.tr.nodes([this.text])
             this.markLayer.add(this.tr)
             this.markLayer.add(this.text)
             this.stage.add(this.markLayer)
         },
-        drawLine(index) {
-            this.activeIcon = index
+        drawLine() {
             this.mouseStatus = 'line'
         },
         startLine(current) {
             let _this = this
             if (!this.line) {
                 this.line = new Konva.Line({
-                    id: this.uuid(),
+                    id: this.$tools.guid(),
                     stroke: 'red',
                     strokeWidth: 3,
                     draggable: false,
@@ -246,12 +232,10 @@ export default {
             } else {
                 this.line.points(this.line.points().concat([current.x / _this.scaleDefault, current.y / _this.scaleDefault]))
             }
-            // this.line.zIndex(1)
             this.markLayer.add(this.line)
             this.stage.add(this.markLayer)
         },
-        drawArrow(index) {
-            this.activeIcon = index
+        drawArrow() {
             this.mouseStatus = 'arrow'
         },
         // 绘制箭头
@@ -259,7 +243,7 @@ export default {
             let _this = this
             if (!this.arrow) {
                 this.arrow = new Konva.Arrow({
-                    id: this.uuid(),
+                    id: this.$tools.guid(),
                     fill: 'transparent',
                     stroke: 'red',
                     strokeWidth: 4,
@@ -290,12 +274,10 @@ export default {
             } else {
                 this.arrow.points([_this.clickPoint.x / _this.scaleDefault, _this.clickPoint.y / _this.scaleDefault, (current.x) / _this.scaleDefault, (current.y) / _this.scaleDefault])
             }
-            // this.arrow.zIndex(1)
             this.markLayer.add(this.arrow)
             this.stage.add(this.markLayer)
         },
-        drawOval(index) {
-            this.activeIcon = index
+        drawOval() {
             this.mouseStatus = 'oval'
         },
         startOval(current) {
@@ -305,9 +287,7 @@ export default {
             let ry = (_this.clickPoint.y - current.y) / _this.scaleDefault * 0.5
             if (!this.oval) {
                 this.oval = new Konva.Ellipse({
-                    id: this.uuid(),
-                    // x: _this.clickPoint.x / _this.scaleDefault,
-                    // y: _this.clickPoint.y / _this.scaleDefault,
+                    id: this.$tools.guid(),
                     x: _this.clickPoint.x,
                     y: _this.clickPoint.y,
                     radiusX: rx > 0 ? rx : -rx,
@@ -346,18 +326,8 @@ export default {
             this.markLayer.add(this.oval)
             this.stage.add(this.markLayer)
         },
-        drawIcon(index) {
-            this.activeIcon = index
-        },
-        review(index) {
-            this.activeIcon = index
-        },
-        cancelFull(index) {
-            this.activeIcon = index
-        },
         //绘制矩形
-        drawRect(index) {
-            this.activeIcon = index
+        drawRect() {
             this.mouseStatus = 'rect'
         },
         startRect(current) {
@@ -365,7 +335,7 @@ export default {
             //判断rect是否初始化
             if (!this.rect) {
                 this.rect = new Konva.Rect({
-                    id: this.uuid(),
+                    id: this.$tools.guid(),
                     x: _this.clickPoint.x / _this.scaleDefault,
                     y: _this.clickPoint.y / _this.scaleDefault,
                     width: (current.x - _this.clickPoint.x) / _this.scaleDefault,
@@ -444,11 +414,6 @@ export default {
                 this.myScale()
             }
         },
-        //还原比例
-        restore() {
-            this.scaleDefault = 1
-            this.myScale()
-        },
         myScale() {
             this.stage.children.forEach(item => {
                 item.scale({
@@ -522,7 +487,7 @@ export default {
             this.clickPoint = this.getCanvasPoint(e.clientX, e.clientY)
         },
         //鼠标弹起事件
-        canvasMouseUp() {
+        async canvasMouseUp() {
             this.isMouseDown = false
             switch (this.mouseStatus) {
                 case 'move':
@@ -548,6 +513,11 @@ export default {
                 default:
                     break
             }
+            if (this.mouseStatus != 'move') {
+                let img = await this.saveAsImg()
+                this.$emit('getImg', img)
+            }
+
         },
         //鼠标移动事件
         canvasMouseMove(e) {
@@ -582,10 +552,22 @@ export default {
         },
 
         //清除所有批注
-        clear(index) {
-            this.activeIcon = index
+        clear() {
             this.markLayer.removeChildren()
             this.stage.add(this.markLayer)
+        },
+
+        /* 保存批注 */
+        saveAsImg() {
+            return new Promise(async (r, j) => {
+                let compressImg = await this.$editorTools.compressImg(this.stage.toDataURL(),
+                    this.stage.attrs.width, this.stage.attrs.height)
+                r({
+                    base64: compressImg,
+                    width: this.stage.attrs.width,
+                    height: this.stage.attrs.height
+                })
+            })
         }
     },
     mounted() {
@@ -640,7 +622,7 @@ export default {
         bgImg: {
             handler(n, o) {
                 this.$nextTick(() => {
-                    // this.restore()
+                    this.restore()
                     this.orgLayer.removeChildren()
                     this.markLayer.removeChildren()
                     let imageObj = new Image()
@@ -667,6 +649,18 @@ export default {
             },
             immediate: true,
             deep: true
+        },
+        drawImgData: {
+            handler(n, o) {
+                this.imgData = n
+                this.drawImg()
+            }
+        },
+        status: {
+            handler(n, o) {
+                this.mouseStatus = n
+            },
+            immediate: true
         }
     }
 }

+ 2 - 2
TEAMModelOS/ClientApp/src/view/teachcontent/ResBelong.vue

@@ -10,7 +10,7 @@
                 <DropdownItem :name="item.id">{{ item.name }}</DropdownItem>
             </DropdownMenu>
             <DropdownMenu slot="list">
-                <DropdownItem name="public">{{$t('teachContent.publicRes')}}</DropdownItem>
+                <DropdownItem name="public">{{$t('teachContent.public')}}</DropdownItem>
             </DropdownMenu>
         </Dropdown>
     </div>
@@ -71,7 +71,7 @@ export default {
                 if (temp) {
                     name = temp.name
                 }else{
-                    name = this.$t('teachContent.publicRes')
+                    name = this.$t('teachContent.public')
                 }
             }
             return name

+ 8 - 2
TEAMModelOS/Controllers/Common/ExamController.cs

@@ -1700,16 +1700,22 @@ namespace TEAMModelOS.Controllers
                 var stuAns = await redisClient.HashGetAsync($"Exam:Scoring:{id}-{subjectId}", sId.ToString());
                 var value = JsonDocument.Parse(stuAns.ToString());
                 value.RootElement.TryGetProperty("ans", out JsonElement blob);
+                value.RootElement.TryGetProperty("mark", out JsonElement element);
                 StringBuilder builder = new StringBuilder();
-                if (requert.TryGetProperty("mark", out JsonElement mark)) {
+                if (requert.TryGetProperty("mark", out JsonElement mark))
+                {
                     //存放老师批注信息到blob                   
                     builder.Append(id).Append("/");
                     builder.Append(subjectId).Append("/");
                     builder.Append(sId).Append("mark").Append("/");
                     builder.Append("ans.json");
                     await _azureStorage.UploadFileByContainer(code.ToString(), mark.ToJsonString(), "exam", builder.ToString(), false);
+                    await redisClient.HashSetAsync($"Exam:Scoring:{id}-{subjectId}", sId.ToString(), new { ans = blob, score = score, tmdId = tId, mark = builder.ToString() }.ToJsonString());
+                }
+                else {
+                    await redisClient.HashSetAsync($"Exam:Scoring:{id}-{subjectId}", sId.ToString(), new { ans = blob, score = score, tmdId = tId, mark = element }.ToJsonString());
                 }                
-                await redisClient.HashSetAsync($"Exam:Scoring:{id}-{subjectId}", sId.ToString(), new { ans = blob, score = score, tmdId = tId, mark = builder.ToString() }.ToJsonString());
+                
                 if (recs.Count == count.GetInt32())
                 {
                     await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(

+ 23 - 7
TEAMModelOS/Controllers/Teacher/CommentController.cs

@@ -16,6 +16,8 @@ using TEAMModelOS.SDK.Helper.Common.StringHelper;
 using TEAMModelOS.Models;
 using Microsoft.Extensions.Options;
 using System.Text;
+using Azure.Messaging.ServiceBus;
+using Microsoft.Extensions.Configuration;
 
 namespace TEAMModelOS.Controllers
 {
@@ -24,18 +26,22 @@ namespace TEAMModelOS.Controllers
     //[Authorize(Roles = "IES5")]
     [Route("teacher/comment")]
     [ApiController]
-    public class CommentController :ControllerBase
+    public class CommentController : ControllerBase
     {
         private readonly AzureCosmosFactory _azureCosmos;
         private readonly DingDing _dingDing;
         private readonly Option _option;
         private readonly AzureStorageFactory _azureStorage;
-        public CommentController(AzureCosmosFactory azureCosmos, DingDing dingDing, IOptionsSnapshot<Option> option, AzureStorageFactory azureStorage)
+        public IConfiguration _configuration { get; set; }
+        private readonly AzureServiceBusFactory _serviceBus;
+        public CommentController(AzureCosmosFactory azureCosmos, DingDing dingDing, IOptionsSnapshot<Option> option, AzureStorageFactory azureStorage, AzureServiceBusFactory serviceBus, IConfiguration configuration)
         {
             _azureCosmos = azureCosmos;
             _dingDing = dingDing;
             _option = option?.Value;
             _azureStorage = azureStorage;
+            _serviceBus = serviceBus;
+            _configuration = configuration;
         }
 
         /// <summary>
@@ -100,7 +106,7 @@ namespace TEAMModelOS.Controllers
             //    }
             //}
 
-            return Ok();           
+            return Ok();
         }
         /// <summary>
         /// 更新保存教师评语罐头,如果评语列表为空则删除
@@ -126,7 +132,7 @@ namespace TEAMModelOS.Controllers
             //    {
             //        IdPk idPk = await _azureCosmos.DeleteAsync<Comment>(request.id, request.code);
             //    }
-                   
+
             //}
             ////return builder.Data(comment).build();
             return Ok();
@@ -163,7 +169,7 @@ namespace TEAMModelOS.Controllers
                         }
                     }
                 }
-                ExamClassResult classResult = new ExamClassResult();              
+                ExamClassResult classResult = new ExamClassResult();
                 List<List<string>> ans = answer.ToObject<List<List<string>>>();
                 List<List<string>> standard = new List<List<string>>();
                 List<double> points = new List<double>();
@@ -183,9 +189,11 @@ namespace TEAMModelOS.Controllers
                     /*string FileName = result.examId + "/" + result.subjectId + "/" + studentId + "mark";
                     string blob = await _azureStorage.UploadFileByContainer(school.ToString(), ans.ToJsonString(), "exam", FileName + "/" + "ans.json");*/
                     //result.studentAnswers[index].Add(blob);
-                    if (result.mark == null || result.mark.Count == 0) {
+                    if (result.mark == null || result.mark.Count == 0)
+                    {
                         List<string> annotation = new List<string>();
-                        foreach (string ids in result.studentIds) {
+                        foreach (string ids in result.studentIds)
+                        {
                             annotation.Add("");
                         }
                         result.mark = annotation;
@@ -193,7 +201,15 @@ namespace TEAMModelOS.Controllers
                     result.mark[index] = builder.ToString();
                     classResult = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(result, result.id, new PartitionKey($"{result.code}"));
                 }
+                await Task.WhenAll(tasks);
+               /* //变更blob 大小
+                ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new Azure.Cosmos.PartitionKey($"Exam-{school}"));
+                info.size = await _azureStorage.GetBlobContainerClient(school.ToString()).GetBlobsSize($"exam/{id}");
+                var messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "annotation", root = $"exam/{id}", name = school }.ToJsonString());
 
+                messageBlob.ApplicationProperties.Add("name", "BlobRoot");
+                var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
+                await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);*/
                 return Ok(new { classResult });
             }
             catch (Exception e)