浏览代码

增加对评卷轨迹信息对获取,并以水印形式保存到图片上

luoshi 6 年之前
父节点
当前提交
7c6282ea62
共有 3 个文件被更改,包括 91 次插入62 次删除
  1. 5 5
      config.json
  2. 9 6
      source/lib/api.js
  3. 77 51
      source/lib/image.js

+ 5 - 5
config.json

@@ -12,7 +12,7 @@
     },
     },
     "watermark": {
     "watermark": {
         "fontFile": "/Users/luoshi/develop/project/stmms-proxy/font/simsun.ttf",
         "fontFile": "/Users/luoshi/develop/project/stmms-proxy/font/simsun.ttf",
-        "fontSize": 30,
+        "fontSize": 60,
         "color": "#ff0000"
         "color": "#ff0000"
     },
     },
     "logger": {
     "logger": {
@@ -40,9 +40,9 @@
         },
         },
         {
         {
             "name": "局域网",
             "name": "局域网",
-            "host": "192.168.10.42:8080",
-            "bucketPrefix": "gx",
-            "upyunDomain": "192.168.10.42:8080/file"
+            "host": "localhost:8010",
+            "bucketPrefix": "ft",
+            "upyunDomain": ""
         }
         }
     ]
     ]
-}
+}

+ 9 - 6
source/lib/api.js

@@ -16,7 +16,7 @@ async function execute(uri, method, form) {
             maxAttempts: 50,
             maxAttempts: 50,
             retryDelay: 1000,
             retryDelay: 1000,
             retryStrategy: request.RetryStrategies.HTTPOrNetworkError
             retryStrategy: request.RetryStrategies.HTTPOrNetworkError
-        }, function (error, response, body) {
+        }, function(error, response, body) {
             if (response.statusCode == 200) {
             if (response.statusCode == 200) {
                 resolve(body);
                 resolve(body);
             } else {
             } else {
@@ -28,11 +28,11 @@ async function execute(uri, method, form) {
     })
     })
 }
 }
 
 
-module.exports.login = function () {
+module.exports.login = function() {
     return execute('/api/user/login', 'GET');
     return execute('/api/user/login', 'GET');
 }
 }
 
 
-module.exports.getExams = function (pageNumber, pageSize) {
+module.exports.getExams = function(pageNumber, pageSize) {
     let uri = '/api/exams'
     let uri = '/api/exams'
     let param = [];
     let param = [];
     if (pageNumber != undefined) {
     if (pageNumber != undefined) {
@@ -47,7 +47,7 @@ module.exports.getExams = function (pageNumber, pageSize) {
     return execute(uri, 'GET');
     return execute(uri, 'GET');
 }
 }
 
 
-module.exports.getStudents = function (examId, pageNumber, pageSize, upload, absent, withScoreDetail) {
+module.exports.getStudents = function(examId, pageNumber, pageSize, upload, absent, withScoreDetail, withMarkTrack) {
     let form = {
     let form = {
         examId: examId,
         examId: examId,
         pageNumber: pageNumber,
         pageNumber: pageNumber,
@@ -62,10 +62,13 @@ module.exports.getStudents = function (examId, pageNumber, pageSize, upload, abs
     if (withScoreDetail != undefined) {
     if (withScoreDetail != undefined) {
         form.withScoreDetail = withScoreDetail
         form.withScoreDetail = withScoreDetail
     }
     }
+    if (withMarkTrack != undefined) {
+        form.withMarkTrack = withMarkTrack
+    }
     return execute('/api/exam/students', 'POST', form);
     return execute('/api/exam/students', 'POST', form);
 }
 }
 
 
-module.exports.countStudents = function (examId, upload, absent) {
+module.exports.countStudents = function(examId, upload, absent) {
     let uri = '/api/students/count/' + examId
     let uri = '/api/students/count/' + examId
     let param = [];
     let param = [];
     if (upload != undefined) {
     if (upload != undefined) {
@@ -80,7 +83,7 @@ module.exports.countStudents = function (examId, upload, absent) {
     return execute(uri, 'GET');
     return execute(uri, 'GET');
 }
 }
 
 
-module.exports.getPackages = function (examId, upload) {
+module.exports.getPackages = function(examId, upload) {
     let uri = '/api/package/count/' + examId
     let uri = '/api/package/count/' + examId
     if (upload != undefined) {
     if (upload != undefined) {
         uri = uri + '?upload=' + (upload ? 'true' : false)
         uri = uri + '?upload=' + (upload ? 'true' : false)

+ 77 - 51
source/lib/image.js

@@ -38,60 +38,86 @@ class executor extends EventEmitter {
         })
         })
     }
     }
 
 
-    async addWatermark(image, file, student) {
+    async addWatermark(image, file, student, index) {
         let fontSize = config.watermark.fontSize
         let fontSize = config.watermark.fontSize
         let fontFile = config.watermark.fontFile
         let fontFile = config.watermark.fontFile
         let color = config.watermark.color
         let color = config.watermark.color
-        let imgData = gm(image).font(fontFile, fontSize).fill(color)
+        let imgData = gm(image)
         let size = sizeOf(image)
         let size = sizeOf(image)
-        //初始坐标
-        let x = 30
-        let y = 10
-        let height = fontSize + 10
-        //最大宽/高限制
-        let maxX = size.width - x * 2
-        //计算总分
-        let totalScore = (parseFloat(student.objectiveScore) || 0) + (parseFloat(student.subjectiveScore) || 0)
-        //显示总分明细
-        imgData.drawText(x, y += height, '成绩明细')
-        imgData.drawText(x, y += height, '总分=(客观+主观) | ' + totalScore + '=' + student.objectiveScore + '+' + student.subjectiveScore)
-        //显示客观题明细
-        if (student.objectiveScoreDetail && student.objectiveScoreDetail.length > 0) {
-            let lines = []
-            let array = []
-            //前置提示文字的字符数
-            let count = 10
-            lines.push(array)
-            for (let i = 0; i < student.objectiveScoreDetail.length; i++) {
-                let detail = student.objectiveScoreDetail[i]
-                let content = detail.answer + ':' + detail.score
-                //超长后另起一行显示客观题
-                if ((count + content.length) * fontSize * 0.7 > maxX) {
-                    array = []
-                    lines.push(array)
-                    count = 10
+        //添加第一页的得分明细
+        if (index == 1) {
+            //初始坐标
+            let x = 30
+            let y = 10
+            //最大宽/高限制
+            let fontSize = 30
+            let maxX = size.width / 2 - x * 2
+            let height = fontSize + 10
+            //计算总分
+            let totalScore = (parseFloat(student.objectiveScore) || 0) + (parseFloat(student.subjectiveScore) || 0)
+            //显示总分明细
+            imgData.font(fontFile, fontSize).fill(color)
+            imgData.drawText(x, y += height, '成绩明细')
+            imgData.drawText(x, y += height, '总分=(客观+主观) | ' + totalScore + '=' + student.objectiveScore + '+' + student.subjectiveScore)
+            //显示客观题明细
+            if (student.objectiveScoreDetail && student.objectiveScoreDetail.length > 0) {
+                let lines = []
+                let array = []
+                //前置提示文字的字符数
+                let count = 10
+                lines.push(array)
+                for (let i = 0; i < student.objectiveScoreDetail.length; i++) {
+                    let detail = student.objectiveScoreDetail[i]
+                    let content = detail.answer + ':' + detail.score
+                    //超长后另起一行显示客观题
+                    if ((count + content.length) * fontSize * 0.7 > maxX) {
+                        array = []
+                        lines.push(array)
+                        count = 10
+                    }
+                    array.push(content)
+                    count += content.length
+                }
+                //显示所有行的客观题明细
+                for (let l = 0; l < lines.length; l++) {
+                    imgData.drawText(x, y += height, '客观题识别结果 | ' + lines[l].join(';'))
                 }
                 }
-                array.push(content)
-                count += content.length
             }
             }
-            //显示所有行的客观题明细
-            for (let l = 0; l < lines.length; l++) {
-                imgData.drawText(x, y += height, '客观题识别结果 | ' + lines[l].join(';'))
+            //显示主观题明细
+            if (student.subjectiveScoreDetail && student.subjectiveScoreDetail.length > 0) {
+                let startY = y
+                imgData.drawText(x, y += height, '题号 | 分数')
+                for (let i = 0; i < student.subjectiveScoreDetail.length; i++) {
+                    let detail = student.subjectiveScoreDetail[i]
+                    //超过最大高度了则另起一列
+                    if ((y + height + 15) > size.height) {
+                        y = startY
+                        x += 300
+                        imgData.drawText(x, y += height, '题号 | 分数')
+                    }
+                    let content = detail.mainNumber + '-' + detail.subNumber + ' : ' + detail.score
+                    if (detail.marker != undefined) {
+                        content = content + ' ' + detail.marker.join(',')
+                    }
+                    imgData.drawText(x, y += height, content)
+                }
             }
             }
         }
         }
-        //显示主观题明细
-        if (student.subjectiveScoreDetail && student.subjectiveScoreDetail.length > 0) {
-            let startY = y
-            imgData.drawText(x, y += height, '题号 | 分数')
-            for (let i = 0; i < student.subjectiveScoreDetail.length; i++) {
-                let detail = student.subjectiveScoreDetail[i]
-                //超过最大高度了则另起一列
-                if ((y + height + 15) > size.height) {
-                    y = startY
-                    x += 200
-                    imgData.drawText(x, y += height, '题号 | 分数')
+        //显示评卷标记
+        if (student.tags != undefined && student.tags[index] != undefined) {
+            let fontSize = 60
+            let height = fontSize + 10
+            imgData.font(fontFile, fontSize).fill(color)
+            let tags = student.tags[index]
+            for (let i = 0; i < tags.length; i++) {
+                let tag = tags[i]
+                if (tag.content != undefined) {
+                    let top = tag.top
+                    for (let j = 0; j < tag.content.length; j++) {
+                        imgData.drawText(tag.left, top, tag.content[j])
+                        top += height
+                    }
                 }
                 }
-                imgData.drawText(x, y += height, detail.mainNumber + '-' + detail.subNumber + ' : ' + detail.score)
             }
             }
         }
         }
         return new Promise((resolve, reject) => {
         return new Promise((resolve, reject) => {
@@ -105,7 +131,8 @@ class executor extends EventEmitter {
         })
         })
     }
     }
 
 
-    async downloadFile(remoteTemplate, localTemplate, data, dir, client, bucket, watermark) {
+    async downloadFile(remoteTemplate, localTemplate, data, dir, client, bucket, index, watermark) {
+        data.index = index
         let remote = mustache.render(remoteTemplate, data)
         let remote = mustache.render(remoteTemplate, data)
         let local = path.join(dir, mustache.render(localTemplate, data))
         let local = path.join(dir, mustache.render(localTemplate, data))
         mkdirp.sync(path.dirname(local))
         mkdirp.sync(path.dirname(local))
@@ -133,7 +160,7 @@ class executor extends EventEmitter {
         }
         }
         //是否需要添加分数水印
         //是否需要添加分数水印
         if (watermark) {
         if (watermark) {
-            await this.addWatermark(imgData, local, data)
+            await this.addWatermark(imgData, local, data, index)
         } else {
         } else {
             await fs.writeFileSync(local, imgData)
             await fs.writeFileSync(local, imgData)
         }
         }
@@ -166,7 +193,7 @@ class executor extends EventEmitter {
             while (true) {
             while (true) {
                 pageNumber++
                 pageNumber++
 
 
-                let array = await api.getStudents(env.examId, pageNumber, 100, true, undefined, watermark === true)
+                let array = await api.getStudents(env.examId, pageNumber, 10, true, undefined, watermark === true, watermark === true)
                 if (array == undefined || array.length == 0) {
                 if (array == undefined || array.length == 0) {
                     break
                     break
                 }
                 }
@@ -179,8 +206,7 @@ class executor extends EventEmitter {
                     } else {
                     } else {
                         student.examId = env.examId
                         student.examId = env.examId
                         for (let i = 1; i <= student.sheetCount; i++) {
                         for (let i = 1; i <= student.sheetCount; i++) {
-                            student.index = i
-                            promises.push(this.downloadFile(config.imageUrl.sheet, template, student, dir, client, bucket, (i == 1 && watermark)))
+                            promises.push(this.downloadFile(config.imageUrl.sheet, template, student, dir, client, bucket, i, watermark))
                         }
                         }
                         //等待所有图片下载完毕
                         //等待所有图片下载完毕
                         await Promise.all(promises)
                         await Promise.all(promises)
@@ -238,6 +264,6 @@ class executor extends EventEmitter {
     }
     }
 }
 }
 
 
-module.exports = function () {
+module.exports = function() {
     return new executor()
     return new executor()
 }
 }