1
0
Эх сурвалжийг харах

增加评卷个性化参数设置记忆功能

1.mark-control增加参数初始化与保存功能
2.图片缩放、侧边栏、缩略图、鼠标给分板四大功能的切换能自动记忆
3.服务端marker表增加字段记录个性化参数设置
4.MarkController增加保存接口
ting.yin 6 жил өмнө
parent
commit
8a2ea79a50

+ 6 - 2
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/MarkerDao.java

@@ -35,11 +35,15 @@ public interface MarkerDao extends PagingAndSortingRepository<Marker, Integer>,
     @Modifying
     @Query("delete from Marker m where m.examId=?1")
     public void deleteByExamId(int examId);
-    
-    @Query(value="select e.* from eb_marker e,m_library m where 1=1 and e.id = m.marker_id and m.student_id =?1",nativeQuery=true)
+
+    @Query(value = "select e.* from eb_marker e,m_library m where 1=1 and e.id = m.marker_id and m.student_id =?1", nativeQuery = true)
     public Marker findByStudentId(int studentId);
 
     @Query("select count(m) from Marker m where m.loginName=?1")
     public long countByLoginName(String loginName);
 
+    @Modifying
+    @Query("update Marker m set m.markSetting=?2 where m.id=?1")
+    public void updateMarkSettingById(Integer id, String setting);
+
 }

+ 14 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/Marker.java

@@ -92,6 +92,12 @@ public class Marker implements Serializable {
             @JoinColumn(name = "exam_id", referencedColumnName = "exam_id") })
     private Set<ExamSubject> examSubjects = new HashSet<>();
 
+    /**
+     * 个性化评卷参数设置
+     */
+    @Column(name = "mark_setting", nullable = true, columnDefinition = "text")
+    private String markSetting;
+
     public Integer getId() {
         return id;
     }
@@ -254,4 +260,12 @@ public class Marker implements Serializable {
     public void setExamSubjects(Set<ExamSubject> examSubjects) {
         this.examSubjects = examSubjects;
     }
+
+    public String getMarkSetting() {
+        return markSetting;
+    }
+
+    public void setMarkSetting(String markSetting) {
+        this.markSetting = markSetting;
+    }
 }

+ 3 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/MarkerService.java

@@ -36,10 +36,12 @@ public interface MarkerService {
 
     List<Marker> getMarkCount(int examId);
 
-	public Marker findByStudentId(int studentId);
+    public Marker findByStudentId(int studentId);
 
     public int batchSave(List<Marker> list);
 
     long countByLoginName(String loginName);
 
+    void updateMarkSetting(Integer id, String setting);
+
 }

+ 73 - 65
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/MarkerServiceImpl.java

@@ -39,7 +39,7 @@ public class MarkerServiceImpl extends BaseQueryService<Marker> implements Marke
 
     @Autowired
     private MarkLibraryDao libraryDao;
-    
+
     @Autowired
     private ExamSubjectService subjectService;
 
@@ -108,37 +108,37 @@ public class MarkerServiceImpl extends BaseQueryService<Marker> implements Marke
     @Override
     public int batchCreateCommon(int examId, int count, String password) {
         int result = 0;
-//        if (count > 0) {
-//            int start = 1;
-//            Marker previous = findLastCommonMarker(examId);
-//            if (previous != null) {
-//                start = previous.getNumber() + 1;
-//            }
-//            int end = start + count - 1;
-//            for (; start <= end; start++) {
-//                Marker marker = new Marker();
-////                marker.setCommon(true);
-//                marker.setExamId(examId);
-//                marker.setSubjectCode("");
-//                if(StringUtils.isEmpty(password)){
-//                    Random random = new Random();
-//                    for (int i=0;i<6;i++)
-//                    {
-//                        password+=random.nextInt(10);
-//                    }
-//                    marker.setPassword(password);
-//                    password = "";//随机码生产后将密码置空
-//                }else {
-//                    marker.setPassword(password);
-//                }
-//                marker.setEnable(true);
-//                marker.buildLoginName(start);
-//                marker.setName(marker.getLoginName());
-//                if (save(marker) != null) {
-//                    result++;
-//                }
-//            }
-//        }
+        // if (count > 0) {
+        // int start = 1;
+        // Marker previous = findLastCommonMarker(examId);
+        // if (previous != null) {
+        // start = previous.getNumber() + 1;
+        // }
+        // int end = start + count - 1;
+        // for (; start <= end; start++) {
+        // Marker marker = new Marker();
+        // // marker.setCommon(true);
+        // marker.setExamId(examId);
+        // marker.setSubjectCode("");
+        // if(StringUtils.isEmpty(password)){
+        // Random random = new Random();
+        // for (int i=0;i<6;i++)
+        // {
+        // password+=random.nextInt(10);
+        // }
+        // marker.setPassword(password);
+        // password = "";//随机码生产后将密码置空
+        // }else {
+        // marker.setPassword(password);
+        // }
+        // marker.setEnable(true);
+        // marker.buildLoginName(start);
+        // marker.setName(marker.getLoginName());
+        // if (save(marker) != null) {
+        // result++;
+        // }
+        // }
+        // }
         return result;
     }
 
@@ -163,18 +163,18 @@ public class MarkerServiceImpl extends BaseQueryService<Marker> implements Marke
                 Marker marker = new Marker();
                 marker.setExamId(subject.getExamId());
                 marker.setSubjectCode(subject.getCode());
-                if(StringUtils.isEmpty(password)){
+                if (StringUtils.isEmpty(password)) {
                     marker.setPassword(getRandom());
-                }else {
+                } else {
                     marker.setPassword(password);
                 }
                 marker.setEnable(true);
-                marker.buildLoginName(start,randomStr);
+                marker.buildLoginName(start, randomStr);
                 randomStr = checkLoginName(start, randomStr, marker);
                 marker.setName(marker.getLoginName());
                 if (save(marker) != null) {
-                	result++;
-                	markers.add(marker);
+                    result++;
+                    markers.add(marker);
                 }
             }
             subject.setMarkers(markers);
@@ -183,25 +183,24 @@ public class MarkerServiceImpl extends BaseQueryService<Marker> implements Marke
         return result;
     }
 
-	private String checkLoginName(int start, String randomStr, Marker marker) {
-		if(countByLoginName(marker.getLoginName())>0){
-			randomStr = getRandom();
-			marker.buildLoginName(start,randomStr);
-			return checkLoginName(start, randomStr, marker);
-		}else{
-			return randomStr;
-		}
-	}
+    private String checkLoginName(int start, String randomStr, Marker marker) {
+        if (countByLoginName(marker.getLoginName()) > 0) {
+            randomStr = getRandom();
+            marker.buildLoginName(start, randomStr);
+            return checkLoginName(start, randomStr, marker);
+        } else {
+            return randomStr;
+        }
+    }
 
-	private String getRandom() {
-		String randomStr = "";
-		Random random = new Random();
-		for (int i=0;i<6;i++)
-		{
-			randomStr+=random.nextInt(10);
-		}
-		return randomStr;
-	}
+    private String getRandom() {
+        String randomStr = "";
+        Random random = new Random();
+        for (int i = 0; i < 6; i++) {
+            randomStr += random.nextInt(10);
+        }
+        return randomStr;
+    }
 
     @Override
     public List<Marker> getMarkCount(int examId) {
@@ -238,8 +237,10 @@ public class MarkerServiceImpl extends BaseQueryService<Marker> implements Marke
                     predicates.add(cb.equal(root.get("examId"), query.getExamId()));
                 }
                 if (StringUtils.isNotBlank(query.getSubjectCode())) {
-//                    predicates.add(cb.equal(root.get("subjectCode"), query.getSubjectCode()));
-                	Join<Marker,ExamSubject> join= root.join(root.getModel().getSet("examSubjects",ExamSubject.class),JoinType.LEFT);
+                    // predicates.add(cb.equal(root.get("subjectCode"),
+                    // query.getSubjectCode()));
+                    Join<Marker, ExamSubject> join = root.join(root.getModel()
+                            .getSet("examSubjects", ExamSubject.class), JoinType.LEFT);
                     Predicate p2 = cb.equal(join.get("pk").get("code"), query.getSubjectCode());
                     predicates.add(p2);
                 }
@@ -256,19 +257,26 @@ public class MarkerServiceImpl extends BaseQueryService<Marker> implements Marke
         };
     }
 
-	@Override
-	public Marker findByStudentId(int studentId){
-	    return  markerDao.findByStudentId(studentId);
-	}
+    @Override
+    public Marker findByStudentId(int studentId) {
+        return markerDao.findByStudentId(studentId);
+    }
 
-	@Override
-    public int batchSave(List<Marker> list){
+    @Override
+    public int batchSave(List<Marker> list) {
         markerDao.save(list);
-        return  list.size();
+        return list.size();
     }
+
     @Override
-    public long countByLoginName(String loginName){
+    public long countByLoginName(String loginName) {
         return markerDao.countByLoginName(loginName);
     }
 
+    @Transactional
+    @Override
+    public void updateMarkSetting(Integer id, String setting) {
+        markerDao.updateMarkSettingById(id, setting);
+    }
+
 }

+ 23 - 9
stmms-web/src/main/java/cn/com/qmth/stmms/mark/MarkController.java

@@ -9,6 +9,7 @@ import javax.servlet.http.HttpServletRequest;
 import net.sf.json.JSONArray;
 import net.sf.json.JSONObject;
 
+import org.apache.commons.lang.StringEscapeUtils;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -216,6 +217,8 @@ public class MarkController extends BaseController {
         String end = exam.getEndTime() == null ? "---" : sdf.format(exam.getEndTime());
         modelAndView.addObject("markTime", start + " ~ " + end);
         clearCurrentTask(marker);
+        modelAndView.addObject("defaultSetting", StringUtils.trimToNull(marker.getMarkSetting()));
+
     }
 
     @RequestMapping("/clear")
@@ -347,19 +350,19 @@ public class MarkController extends BaseController {
         query.setPageSize(pageSize);
         query.setTagNotNull(isTag);
         Direction d = Direction.DESC;
-        if(sort.equals("asc")){
+        if (sort.equals("asc")) {
             d = Direction.ASC;
         }
-        if(order.equals("time")){
-            query.setSort(new Sort(d,"markerTime"));
-        }else if(order.equals("studentId")){
-            query.setSort(new Sort(d,"studentId"));
-        }else if(order.equals("score")){
-            query.setSort(new Sort(d,"markerScore"));
-        }else{
+        if (order.equals("time")) {
+            query.setSort(new Sort(d, "markerTime"));
+        } else if (order.equals("studentId")) {
+            query.setSort(new Sort(d, "studentId"));
+        } else if (order.equals("score")) {
+            query.setSort(new Sort(d, "markerScore"));
+        } else {
             query.orderByMarkerTimeDesc();
         }
-        if(studentId!=null){
+        if (studentId != null) {
             query.setStudentId(studentId);
         }
         List<Task> list = taskService.findByQuery(query);
@@ -388,6 +391,17 @@ public class MarkController extends BaseController {
         return result;
     }
 
+    @RequestMapping("/update-setting")
+    @ResponseBody
+    public JSONObject updateSetting(HttpServletRequest request, @RequestParam String setting) {
+        Marker marker = RequestUtils.getWebUser(request).getMarker();
+        JSONObject result = new JSONObject();
+        markerService
+                .updateMarkSetting(marker.getId(), StringEscapeUtils.unescapeHtml(StringUtils.trimToNull(setting)));
+        result.accumulate("success", true);
+        return result;
+    }
+
     @RequestMapping("/tags")
     @ResponseBody
     public JSONArray getTags(HttpServletRequest request) {

+ 5 - 0
stmms-web/src/main/webapp/WEB-INF/views/modules/mark/markNew.jsp

@@ -45,6 +45,7 @@
 				staticServer : '${ctxStatic}',
 				imageServer : '${sliceServer}',
 				userName : '${web_user.name}',
+				userId: '${marker.id}',
 				logoutUrl: '${ctx}/mark/logout',
 				clearUrl: '${ctx}/mark/clear',
 				<c:if test="${forceMode==false}">
@@ -52,6 +53,10 @@
 				</c:if>
 				forceSpecialTag : eval('${exam.forceSpecialTag}'.toLowerCase()),
 				markTime : "${markTime}",
+				<c:if test="${defaultSetting!=null}">
+				defaultSetting: '${defaultSetting}',
+				</c:if>
+				settingSyncUrl: '${ctx}/mark/update-setting',
 				modules : {
 					'single-image-view' : {},
 					'image-builder': {},

+ 5 - 0
stmms-web/src/main/webapp/WEB-INF/views/modules/mark/markTrack.jsp

@@ -37,6 +37,7 @@
 				container : $('#container'),
 				staticServer : '${ctxStatic}',
 				imageServer : '${sliceServer}',
+				userId: '${marker.id}',
 				userName : '${web_user.name}',
 				logoutUrl: '${ctx}/mark/logout',
 				clearUrl: '${ctx}/mark/clear',
@@ -45,6 +46,10 @@
 				</c:if>
 				forceSpecialTag : eval('${exam.forceSpecialTag}'.toLowerCase()),
 				markTime : "${markTime}",
+				<c:if test="${defaultSetting!=null}">
+                defaultSetting: '${defaultSetting}',
+                </c:if>
+                settingSyncUrl: '${ctx}/mark/update-setting',
 				modules : {
 					'single-image-view' : {},
 					'image-builder': {},

+ 15 - 19
stmms-web/src/main/webapp/static/mark-new/css/style.css

@@ -792,19 +792,14 @@ i,em {
 }
 
 .center-content .header {
-	background: #5d6d7d;
-	color: #fff;
-	height: 21px;
-	padding: 10px;
+    background: #5d6d7d;
+    color: #fff;
+    padding: 0 10px;
 }
 
 .center-content .header .text {
-	color: #fff;
-	font-size: 16px;
-	font-weight: bold;
-	text-overflow: ellipsis;
-	white-space: nowrap;
 	float: left;
+    padding: 10px 0;
 }
 
 .center-content .header .text i {
@@ -822,12 +817,12 @@ i,em {
 }
 
 .center-content .header .btn {
-	background: #cbd0d3;
-	padding: 3px 6px 3px 6px;
-	margin: -3px 2px 2px 1px;
-	color: #4b555e;
-	font-weight: bold;
-	float: left;
+    background: #cbd0d3;
+    padding: 3px 6px 3px 6px;
+    margin: 0px 3px 0 0;   
+    color: #4b555e;
+    font-weight: bold;
+    float: left;
 }
 /*.center-content .header .fraction{ font-size:36px; font-family:Arial, Helvetica, sans-serif; font-weight:bold; color:#008f58; text-align:right; float:right;}
 */
@@ -837,9 +832,10 @@ i,em {
 }
 
 .center-content .tips {
-	word-wrap: break-word;
-	text-align: left;
-	float: right;
+    word-wrap: break-word;
+    text-align: left;
+    float: right;
+    margin-top: 6px;
 }
 /*.center-content .tips .help{ width:25%;color:#fff; padding:0 5px 0 5px; float:left;}
 */
@@ -1383,4 +1379,4 @@ a.button.all-zero-button {
 }
 .c-table .loding tr:hover td {
 	background: none;
-}
+}

+ 54 - 6
stmms-web/src/main/webapp/static/mark-new/js/mark-control.js

@@ -18,6 +18,8 @@ function MarkControl(option) {
     this.initTriggers(option);
     //初始化功能模块
     this.initModules(option);
+    //初始化评卷配置
+    this.initSetting(option);
     //初始化成功回调方法
     //console.log('MarkControl init success!');
     //if (option.success != undefined && typeof(option.success) == 'function') {
@@ -91,7 +93,6 @@ MarkControl.prototype.initHeaderAndAssistant = function() {
     });
 
 }
-
 MarkControl.prototype.initMarkFunction = function() {
     var functionList = this.container.assistant.functionList;
     if (functionList == undefined) {
@@ -99,7 +100,55 @@ MarkControl.prototype.initMarkFunction = function() {
         this.container.assistant.functionList = functionList;
     }
 }
-
+MarkControl.prototype.initSetting = function(option) {
+    this.userId = option.userId;
+    this.settingSyncUrl = option.settingSyncUrl;
+    this.settingSyncing = false;
+    this.localStore = window.localStorage;
+    this.setting = {};
+    if (option.defaultSetting != undefined) {
+        //读取外部初始化配置
+        this.setting = JSON.parse(option.defaultSetting);
+    } else if (this.localStore != undefined) {
+        //读取本地存储并判断用户标识
+        var store = JSON.parse(this.localStore.getItem('mark.setting'));
+        if (store != undefined && store.userId != undefined && store.userId == this.userId) {
+            this.setting = store.setting;
+        }
+    }
+    //强制刷新本地存储
+    this.localSettingSave();
+    //广播通知所有模块初始化设置
+    this.trigger('mark.setting.init', this.setting);
+}
+MarkControl.prototype.localSettingSave = function() {
+    if (this.localStore != undefined) {
+        this.localStore.setItem('mark.setting', JSON.stringify({
+            userId: this.userId,
+            setting: this.setting
+        }));
+    }
+}
+MarkControl.prototype.updateSetting = function(item) {
+    if (item == undefined) {
+        return;
+    }
+    for (var key in item) {
+        this.setting[key] = item[key];
+    }
+    this.localSettingSave();
+    if (this.settingSyncUrl != undefined && this.settingSyncing == false) {
+        this.settingSyncing = true;
+        var self = this;
+        setTimeout(function() {
+            //同步个性化设置
+            $.post(self.settingSyncUrl, {
+                setting: JSON.stringify(self.setting)
+            });
+            self.settingSyncing = false;
+        }, 1000);
+    }
+}
 //增加某个事件的监听方法
 MarkControl.prototype.on = function(eventName, caller, callback, async) {
     if (eventName && callback && eventName.length > 0 && typeof(callback) == 'function') {
@@ -258,11 +307,10 @@ MarkControl.prototype.initTriggers = function(option) {
         var timestamp = new Date().getTime();
         context.task.spent = timestamp;
     });
-    
-    this.on('task.submit.forceSpecialTag', this, function(event, context, eventObject) {
-        
+    this.on('task.submit.forceSpecialTag', this, function(event, context, eventObject) { });
+    this.on('mark.setting.change', this, function(event, context, eventObject) {
+        self.updateSetting(eventObject);
     });
-
     $(document).keypress(this, function(event) {
         if (self.context.listenKeyboard != false) {
             return self.trigger('key.press', event);

+ 15 - 3
stmms-web/src/main/webapp/static/mark-new/js/modules/mark-board.js

@@ -5,6 +5,7 @@ var mark_board = function(option, success) {
     return object;
 }
 function MarkBoard(option) {
+    var self = this;
     this.markControl = option.markControl;
     this.needConfirm = option.needConfirm === true ? true : false;
     this.autoSubmit = option.autoSubmit === false ? false : true;
@@ -12,7 +13,6 @@ function MarkBoard(option) {
     this.enableSkip = option.enableSkip === true ? true : false;
     //显分板上是否显示合分样式
     this.showObjectScoreAndSubjectScore = option.showTotalScore === true ? true : false;
-    
     this.init();
     this.markControl.on('task.get.before', this, function(event, context, eventObject) {
         this.task = undefined;
@@ -105,9 +105,15 @@ function MarkBoard(option) {
             }
         }
     });
+    this.markControl.on('mark.setting.init', this, function(event, context, setting) {
+        var show = setting['score.board.show'];
+        if (show != undefined && show == true) {
+            self.showScoreBoard = true;
+        }
+    });
 }
-
 MarkBoard.prototype.init = function() {
+    var self = this;
     this.stepBoard = getDom(this.step_board_dom, this.markControl).appendTo(this.markControl.container.centerContent);
     this.stepBoard.height(this.markControl.container.centerContent.height());
     this.stepBoard.selectiveHeader = this.stepBoard.find('#step-board-selective-header');
@@ -180,10 +186,16 @@ MarkBoard.prototype.init = function() {
         });
     }
     this.scoreBoard.find('#score-board-close-button').click(this, function(event) {
-        event.data.toggleScoreBoard(false);
+    	event.data.toggleScoreBoard(false);
+        self.markControl.trigger('mark.setting.change', {
+            'score.board.show': false
+        });
     });
     this.stepBoard.find('#show-score-board-button').click(this, function(event) {
         event.data.toggleScoreBoard(true);
+        self.markControl.trigger('mark.setting.change', {
+            'score.board.show': true
+        });
     });
     this.scoreBoard.find('.all-zero-button').click(this, function(event) {
         event.data.allZeroSubmit();

+ 55 - 41
stmms-web/src/main/webapp/static/mark-new/js/modules/single-image-view.js

@@ -39,12 +39,12 @@ function SingleImageView(option) {
         this.image = undefined;
         this.render();
     });
-    this.markControl.on('mark.tag.show', this, function(event, context, tag){
-        if(this.task != undefined && tag != undefined){
-        	this.drawTag(tag);
+    this.markControl.on('mark.tag.show', this, function(event, context, tag) {
+        if (this.task != undefined && tag != undefined) {
+            this.drawTag(tag);
         }
     });
-    this.markControl.on('mark.tag.clear', this, function(event, context, track){
+    this.markControl.on('mark.tag.clear', this, function(event, context, track) {
         this.reloadImage();
         this.markControl.trigger('image.reload.event');
     });
@@ -53,37 +53,45 @@ function SingleImageView(option) {
             this.updateScrollTop(topPercent);
         }
     });
+    this.markControl.on('mark.setting.init', this, function(event, context, setting) {
+        var scale = setting['image.view.scale'];
+        if (scale != undefined) {
+            this.scale = Number(scale);
+        }
+    });
 }
 
 SingleImageView.prototype.init = function() {
     var self = this;
     this.container = this.markControl.container.imageContent;
     this.container.height(this.markControl.container.centerContent.height());
-    this.container.css('overflow','scroll');
-    
+    this.container.css('overflow', 'scroll');
+
     this.canvas = $('<canvas></canvas>').appendTo(this.container)[0];
     this.ctx = this.canvas.getContext("2d");
-    
-    $(this.canvas).click(function(event){
-        if(self.task != undefined){
-        	self.markControl.trigger('image.click.event', {
-        		positionX: ((event.pageX - $(self.canvas).offset().left)/$(self.canvas).width()).toFixed(3),
-                positionY: ((event.pageY - $(self.canvas).offset().top)/$(self.canvas).height()).toFixed(3)
-        	});
+    this.ctx.fillStyle = "#FFFFFF";
+    this.scale = 1.0;
+
+    $(this.canvas).click(function(event) {
+        if (self.task != undefined) {
+            self.markControl.trigger('image.click.event', {
+                positionX: ((event.pageX - $(self.canvas).offset().left) / $(self.canvas).width()).toFixed(3),
+                positionY: ((event.pageY - $(self.canvas).offset().top) / $(self.canvas).height()).toFixed(3)
+            });
         }
     });
-    
+
     this.imageControl = getDom(this.image_control_dom, this.markControl).insertBefore(this.markControl.container.assistantButton.parent());
     this.imageControl.find('.zoom-out-button').click(this, function(event) {
-    	self.reloadImage(0.2);
+        self.reloadImage(0.2);
         self.markControl.trigger('image.reload.event');
     });
     this.imageControl.find('.zoom-in-button').click(this, function(event) {
-    	self.reloadImage(-0.2);
+        self.reloadImage(-0.2);
         self.markControl.trigger('image.reload.event');
     });
     this.imageControl.find('.zoom-fit-button').click(this, function(event) {
-    	self.reloadImage();
+        self.reloadImage('fit');
         self.markControl.trigger('image.reload.event');
     });
 }
@@ -95,42 +103,48 @@ SingleImageView.prototype.render = function() {
         //设置画布大小及背景颜色
         this.image = new Image();
         this.image.src = this.task.imageData;
-        this.image.scale = 1.0;
-        this.image.onload = function(){
-            self.canvas.width = Math.min(self.container.width(), self.image.width);
-            self.canvas.height = self.canvas.width * self.image.height / self.image.width;
-            self.ctx.fillStyle = "#FFFFFF";
-            self.ctx.drawImage(self.image, 0, 0, self.image.width, self.image.height, 0, 0, self.canvas.width, self.canvas.height);
+        this.image.onload = function() {
+            self.reloadImage();
             $(self.canvas).show();
-            
+
             self.markControl.trigger('task.load.finish');
         }
     }
 }
 
-SingleImageView.prototype.reloadImage = function(scale) {
-    if(this.image != undefined){
-    	if(scale != undefined){
-    		this.image.scale = this.image.scale + scale;
-    		if(this.image.scale < 0.2){
-    			this.image.scale = 0.2;
-    		}else if(this.image.scale > 3){
-    			this.image.scale = 3;
-    		}
-    	}else{
-    		this.image.scale = 1.0;
-    	}
-    	this.canvas.width = Math.min(this.container.width(), this.image.width) * this.image.scale;
+SingleImageView.prototype.reloadImage = function(scaleAddon) {
+    if (this.image != undefined) {
+        var scale = this.scale;
+        if (scaleAddon != undefined) {
+        	if (scaleAddon=='fit') {
+        		scale = 1.0;
+        	} else {
+            	scale += scaleAddon;
+            }
+        }
+        if (scale < 0.2) {
+            scale = 0.2;
+        } else if (scale > 3) {
+            scale = 3;
+        }
+        if (scale != this.scale) {
+            this.markControl.trigger('mark.setting.change', {
+                'image.view.scale': scale
+            });
+            this.scale = scale;
+        }
+
+        this.canvas.width = Math.min(this.container.width(), this.image.width) * this.scale;
         this.canvas.height = this.canvas.width * this.image.height / this.image.width;
         this.ctx.drawImage(this.image, 0, 0, this.image.width, this.image.height, 0, 0, this.canvas.width, this.canvas.height);
     }
 }
 
-SingleImageView.prototype.drawTag = function(tag){
-    if(tag!=undefined && tag.positionX>0 && tag.positionY>0 && this.image!=undefined){
-        this.ctx.font = parseInt(60 * this.image.scale) + "px Arial";
+SingleImageView.prototype.drawTag = function(tag) {
+    if (tag != undefined && tag.positionX > 0 && tag.positionY > 0 && this.image != undefined) {
+        this.ctx.font = parseInt(60 * this.scale) + "px Arial";
         this.ctx.fillStyle = 'red';
-        this.ctx.fillText(tag.content, tag.positionX*this.canvas.width, tag.positionY*this.canvas.height);
+        this.ctx.fillText(tag.content, tag.positionX * this.canvas.width, tag.positionY * this.canvas.height);
     }
 }
 

+ 119 - 90
stmms-web/src/main/webapp/static/mark-new/js/modules/thumbnail.js

@@ -1,110 +1,139 @@
 //给分板模块
-var thumbnail = function (option, success) {
-    var object = new Thumbnail(option);
-    success();
-    return object;
+var thumbnail = function(option, success) {
+	var object = new Thumbnail(option);
+	success();
+	return object;
 }
 
 function Thumbnail(option) {
-    this.markControl = option.markControl;
-    this.maxWidth = option.width != undefined ? option.width : 100;
-    this.show = false;
-    this.loading = false;
-    this.imageHeight = undefined;
-    this.mousePosition = undefined;
+	var self = this;
 
-    this.init();
-    this.markControl.on('task.get.before', this, function (event, context, eventObject) {
-        this.task = undefined;
-        this.render();
-    });
-    this.markControl.on('task.get.success', this, function (event, context, eventObject) {
-        this.task = context.task;
-        this.render();
-    });
+	this.markControl = option.markControl;
+	this.maxWidth = option.width != undefined ? option.width : 100;
+	this.show = false;
+	this.loading = false;
+	this.imageHeight = undefined;
+	this.mousePosition = undefined;
+
+	this.init();
+	this.markControl.on('task.get.before', this, function(event, context,
+			eventObject) {
+		this.task = undefined;
+		this.render();
+	});
+	this.markControl.on('task.get.success', this, function(event, context,
+			eventObject) {
+		this.task = context.task;
+		this.render();
+	});
+	this.markControl.on('mark.setting.init', this, function(event, context,
+			setting) {
+		var show = setting['thumbnail.show'];
+		if (show != undefined && show == true) {
+			self.toggle(true);
+		}
+	});
 }
 
-Thumbnail.prototype.init = function () {
-    var self = this;
-    this.container = getDom(this.container_dom, this.markControl).appendTo(this.markControl.container);
-    this.container.width(this.maxWidth);
-    this.container.offset({
-        top: 60,
-        left: 0
-    });
+Thumbnail.prototype.init = function() {
+	var self = this;
+	this.container = getDom(this.container_dom, this.markControl).appendTo(
+			this.markControl.container);
+	this.container.width(this.maxWidth);
+	this.container.offset({
+		top : 60,
+		left : 0
+	});
 
-    this.container.header = getDom(this.container_header_dom, this.markControl).appendTo(this.container);
-    this.container.header.width('100%');
+	this.container.header = getDom(this.container_header_dom, this.markControl)
+			.appendTo(this.container);
+	this.container.header.width('100%');
 
-    this.container.content = getDom(this.container_content_dom, this.markControl).appendTo(this.container);
-    this.container.content.width('100%');
-    this.imageObject = this.container.content.find('img');
-    this.imageObject.width('100%');
-    this.imageObject.bind('mouseover', function (e) {
-        self.updatePosition(e);
-    }).bind('mousemove', function (e) {
-        self.updatePosition(e);
-    }).bind('mouseout', function (e) {
-        self.updatePosition();
-    }).bind('click', function () {
-        if (self.show == true && self.task != undefined && self.mousePosition != undefined) {
-            self.markControl.trigger('image.position.change', self.mousePosition.y / self.imageObject.height())
-        }
-    });
+	this.container.content = getDom(this.container_content_dom,
+			this.markControl).appendTo(this.container);
+	this.container.content.width('100%');
+	this.imageObject = this.container.content.find('img');
+	this.imageObject.width('100%');
+	this.imageObject.bind('mouseover', function(e) {
+		self.updatePosition(e);
+	}).bind('mousemove', function(e) {
+		self.updatePosition(e);
+	}).bind('mouseout', function(e) {
+		self.updatePosition();
+	}).bind(
+			'click',
+			function() {
+				if (self.show == true && self.task != undefined
+						&& self.mousePosition != undefined) {
+					self.markControl.trigger('image.position.change',
+							self.mousePosition.y / self.imageObject.height())
+				}
+			});
 
-    this.container.draggable({
-        containment: "window"
-    });
-    this.container.header.find('#close-button').click(function () {
-        self.toggle(false);
-    });
+	this.container.draggable({
+		containment : "window"
+	});
+	this.container.header.find('#close-button').click(function() {
+		self.toggle(false);
+        self.markControl.trigger('mark.setting.change', {
+            'thumbnail.show': false
+        });
+	});
 
-    this.control = getDom(this.control_dom, this.markControl).appendTo(this.markControl.container.assistant);
-    this.control.find('#show-thumbnail-button').click(function () {
-        self.markControl.container.assistant.hide();
-        self.toggle(true);
-    });
-    this.control.find('#hide-thumbnail-button').click(function () {
-        self.markControl.container.assistant.hide();
-        self.toggle(false);
-    });
+	this.control = getDom(this.control_dom, this.markControl).appendTo(
+			this.markControl.container.assistant);
+	this.control.find('#show-thumbnail-button').click(function() {
+		self.markControl.container.assistant.hide();
+		self.toggle(true);
+		self.markControl.trigger('mark.setting.change', {
+			'thumbnail.show' : true
+		});
+	});
+	this.control.find('#hide-thumbnail-button').click(function() {
+		self.markControl.container.assistant.hide();
+		self.toggle(false);
+		self.markControl.trigger('mark.setting.change', {
+			'thumbnail.show' : false
+		});
+	});
 }
 
-Thumbnail.prototype.render = function () {
-    var self = this;
-    var imageObject = this.imageObject;
-    if (this.task != undefined) {
-        imageObject[0].src = this.task.imageData;
-        imageObject[0].onload = function () {
-            if (imageObject[0].height > (self.markControl.container.height() * 0.8)) {
-                self.container.content.height(self.markControl.container.height() * 0.8);
-            } else {
-                self.container.content.height(imageObject[0].height);
-            }
-            imageObject.show();
-        }
-    } else {
-        imageObject[0].src = '';
-        imageObject.hide();
-    }
+Thumbnail.prototype.render = function() {
+	var self = this;
+	var imageObject = this.imageObject;
+	if (this.task != undefined) {
+		imageObject[0].src = this.task.imageData;
+		imageObject[0].onload = function() {
+			if (imageObject[0].height > (self.markControl.container.height() * 0.8)) {
+				self.container.content.height(self.markControl.container
+						.height() * 0.8);
+			} else {
+				self.container.content.height(imageObject[0].height);
+			}
+			imageObject.show();
+		}
+	} else {
+		imageObject[0].src = '';
+		imageObject.hide();
+	}
 }
 
-Thumbnail.prototype.toggle = function (show) {
-    if (show == true) {
-        this.show = true;
-        this.container.show();
-    } else {
-        this.show = false;
-        this.container.hide();
-    }
+Thumbnail.prototype.toggle = function(show) {
+	if (show == true) {
+		this.show = true;
+		this.container.show();
+	} else {
+		this.show = false;
+		this.container.hide();
+	}
 }
 
-Thumbnail.prototype.updatePosition = function (e) {
-    var position = this.imageObject.offset();
-    this.mousePosition = e != undefined ? {
-        x: e.pageX - position.left,
-        y: e.pageY - position.top
-    } : undefined;
+Thumbnail.prototype.updatePosition = function(e) {
+	var position = this.imageObject.offset();
+	this.mousePosition = e != undefined ? {
+		x : e.pageX - position.left,
+		y : e.pageY - position.top
+	} : undefined;
 }
 
 Thumbnail.prototype.container_dom = '<div class="score-board score-board-popover" style="display:none"></div>';

+ 12 - 0
stmms-web/src/main/webapp/static/mark-new/js/modules/view-sidebar.js

@@ -39,11 +39,23 @@ ViewSidebar.prototype.init = function() {
         this.toggleButton = getDom(this.toggle_button_dom, this.markControl).appendTo(this.markControl.container.assistant.functionList);
         this.toggleButton.click(this, function(event) {
             self.toggle(true);
+            self.markControl.trigger('mark.setting.change', {
+                'view.sidebar.open': true
+            });
         });
     }
 
     this.container.find('#view-close-button').click(this, function(event) {
         self.toggle(false);
+        self.markControl.trigger('mark.setting.change', {
+            'view.sidebar.open': false
+        });
+    });
+    this.markControl.on('mark.setting.init', this, function(event, context, setting) {
+        var open = setting['view.sidebar.open'];
+        if (open != undefined && open == true) {
+            self.toggle(true);
+        }
     });
 }
 

+ 14 - 18
stmms-web/src/main/webapp/static/mark-track/css/style.css

@@ -832,19 +832,14 @@ i,em {
 }
 
 .center-content .header {
-	background: #5d6d7d;
-	color: #fff;
-	height: 21px;
-	padding: 10px;
+    background: #5d6d7d;
+    color: #fff;
+    padding: 0 10px;
 }
 
 .center-content .header .text {
-	color: #fff;
-	font-size: 16px;
-	font-weight: bold;
-	text-overflow: ellipsis;
-	white-space: nowrap;
 	float: left;
+    padding: 10px 0;
 }
 
 .center-content .header .text i {
@@ -862,12 +857,12 @@ i,em {
 }
 
 .center-content .header .btn {
-	background: #cbd0d3;
-	padding: 3px 6px 3px 6px;
-	margin: -3px 2px 2px 1px;
-	color: #4b555e;
-	font-weight: bold;
-	float: left;
+    background: #cbd0d3;
+    padding: 3px 6px 3px 6px;
+    margin: 0px 3px 0 0;   
+    color: #4b555e;
+    font-weight: bold;
+    float: left;
 }
 /*.center-content .header .fraction{ font-size:36px; font-family:Arial, Helvetica, sans-serif; font-weight:bold; color:#008f58; text-align:right; float:right;}
 */
@@ -877,9 +872,10 @@ i,em {
 }
 
 .center-content .tips {
-	word-wrap: break-word;
-	text-align: left;
-	float: right;
+    word-wrap: break-word;
+    text-align: left;
+    float: right;
+    margin-top: 6px;
 }
 /*.center-content .tips .help{ width:25%;color:#fff; padding:0 5px 0 5px; float:left;}
 */

+ 55 - 2
stmms-web/src/main/webapp/static/mark-track/js/mark-control.js

@@ -18,6 +18,8 @@ function MarkControl(option) {
     this.initTriggers(option);
     // 初始化功能模块
     this.initModules(option);
+    //初始化评卷配置
+    this.initSetting(option);
     // 初始化成功回调方法
     // console.log('MarkControl init success!');
     // if (option.success != undefined && typeof(option.success) == 'function')
@@ -125,7 +127,56 @@ MarkControl.prototype.addNavGroup = function(title, content){
     self.container.centerList.push(content);
     return nav;
 }
-
+MarkControl.prototype.initSetting = function(option) {
+    this.userId = option.userId;
+    this.settingSyncUrl = option.settingSyncUrl;
+    this.settingSyncing = false;
+    this.localStore = window.localStorage;
+    this.setting = {};
+
+    if (option.defaultSetting != undefined) {
+        //读取外部初始化配置
+        this.setting = JSON.parse(option.defaultSetting);
+    } else if (this.localStore != undefined) {
+        //读取本地存储并判断用户标识
+        var store = JSON.parse(this.localStore.getItem('mark.setting'));
+        if (store != undefined && store.userId != undefined && store.userId == this.userId) {
+            this.setting = store.setting;
+        }
+    }
+    //强制刷新本地存储
+    this.localSettingSave();
+    //广播通知所有模块初始化设置
+    this.trigger('mark.setting.init', this.setting);
+}
+MarkControl.prototype.localSettingSave = function() {
+    if (this.localStore != undefined) {
+        this.localStore.setItem('mark.setting', JSON.stringify({
+            userId: this.userId,
+            setting: this.setting
+        }));
+    }
+}
+MarkControl.prototype.updateSetting = function(item) {
+    if (item == undefined) {
+        return;
+    }
+    for (var key in item) {
+        this.setting[key] = item[key];
+    }
+    this.localSettingSave();
+    if (this.settingSyncUrl != undefined && this.settingSyncing == false) {
+        this.settingSyncing = true;
+        var self = this;
+        setTimeout(function() {
+            //同步个性化设置
+            $.post(self.settingSyncUrl, {
+                setting: JSON.stringify(self.setting)
+            });
+            self.settingSyncing = false;
+        }, 1000);
+    }
+}
 // 增加某个事件的监听方法
 MarkControl.prototype.on = function(eventName, caller, callback, async) {
     if (eventName && callback && eventName.length > 0 && typeof(callback) == 'function') {
@@ -265,7 +316,9 @@ MarkControl.prototype.initTriggers = function(option) {
         var timestamp = new Date().getTime();
         context.task.spent = timestamp;
     });
-
+    this.on('mark.setting.change', this, function(event, context, eventObject) {
+        self.updateSetting(eventObject);
+    });
     $(document).keypress(this, function(event) {
         if (self.context.listenKeyboard != false) {
             return self.trigger('key.press', event);

+ 54 - 40
stmms-web/src/main/webapp/static/mark-track/js/modules/single-image-view.js

@@ -26,15 +26,21 @@ function SingleImageView(option) {
         this.image = undefined;
         this.render();
     });
-    this.markControl.on('mark.tag.show', this, function(event, context, tag){
-        if(this.task != undefined && tag != undefined){
-        	this.drawTag(tag);
+    this.markControl.on('mark.tag.show', this, function(event, context, tag) {
+        if (this.task != undefined && tag != undefined) {
+            this.drawTag(tag);
         }
     });
-    this.markControl.on('mark.tag.clear', this, function(event, context, track){
+    this.markControl.on('mark.tag.clear', this, function(event, context, track) {
         this.reloadImage();
         this.markControl.trigger('image.reload.event');
     });
+    this.markControl.on('mark.setting.init', this, function(event, context, setting) {
+        var scale = setting['image.view.scale'];
+        if (scale != undefined) {
+            this.scale = Number(scale);
+        }
+    });
 }
 
 SingleImageView.prototype.init = function() {
@@ -45,30 +51,32 @@ SingleImageView.prototype.init = function() {
     //    wheelSpeed: 20
     //});
     this.markControl.addNavGroup('答卷', this.container);
-    
+
     this.canvas = this.container.find('canvas')[0];
     this.ctx = this.canvas.getContext("2d");
-    
-    $(this.canvas).click(function(event){
-        if(self.task != undefined){
-        	self.markControl.trigger('image.click.event', {
-        		positionX: ((event.pageX - $(self.canvas).offset().left)/$(self.canvas).width()).toFixed(3),
-                positionY: ((event.pageY - $(self.canvas).offset().top)/$(self.canvas).height()).toFixed(3)
-        	});
+    this.ctx.fillStyle = "#FFFFFF";
+    this.scale = 1.0;
+
+    $(this.canvas).click(function(event) {
+        if (self.task != undefined) {
+            self.markControl.trigger('image.click.event', {
+                positionX: ((event.pageX - $(self.canvas).offset().left) / $(self.canvas).width()).toFixed(3),
+                positionY: ((event.pageY - $(self.canvas).offset().top) / $(self.canvas).height()).toFixed(3)
+            });
         }
     });
-    
+
     this.imageControl = getDom(this.image_control_dom, this.markControl).insertBefore(this.markControl.container.assistantButton.parent());
     this.imageControl.find('.zoom-out-button').click(this, function(event) {
-    	self.reloadImage(0.2);
+        self.reloadImage(0.2);
         self.markControl.trigger('image.reload.event');
     });
     this.imageControl.find('.zoom-in-button').click(this, function(event) {
-    	self.reloadImage(-0.2);
+        self.reloadImage(-0.2);
         self.markControl.trigger('image.reload.event');
     });
     this.imageControl.find('.zoom-fit-button').click(this, function(event) {
-    	self.reloadImage();
+        self.reloadImage('fit');
         self.markControl.trigger('image.reload.event');
     });
 }
@@ -80,42 +88,48 @@ SingleImageView.prototype.render = function() {
         //设置画布大小及背景颜色
         this.image = new Image();
         this.image.src = this.task.imageData;
-        this.image.scale = 1.0;
-        this.image.onload = function(){
-            self.canvas.width = Math.min(self.container.width(), self.image.width);
-            self.canvas.height = self.canvas.width * self.image.height / self.image.width;
-            self.ctx.fillStyle = "#FFFFFF";
-            self.ctx.drawImage(self.image, 0, 0, self.image.width, self.image.height, 0, 0, self.canvas.width, self.canvas.height);
+        this.image.onload = function() {
+            self.reloadImage();
             $(self.canvas).show();
-            
+
             self.markControl.trigger('task.load.finish');
         }
     }
 }
 
-SingleImageView.prototype.reloadImage = function(scale) {
-    if(this.image != undefined){
-    	if(scale != undefined){
-    		this.image.scale = this.image.scale + scale;
-    		if(this.image.scale < 0.2){
-    			this.image.scale = 0.2;
-    		}else if(this.image.scale > 3){
-    			this.image.scale = 3;
-    		}
-    	}else{
-    		this.image.scale = 1.0;
-    	}
-    	this.canvas.width = Math.min(this.container.width(), this.image.width) * this.image.scale;
+SingleImageView.prototype.reloadImage = function(scaleAddon) {
+    if (this.image != undefined) {
+        var scale = this.scale;
+        if (scaleAddon != undefined) {
+        	if (scaleAddon == 'fit') {
+        		scale = 1.0;
+        	} else {
+        		scale += scaleAddon;
+        	}
+        }
+        if (scale < 0.2) {
+            scale = 0.2;
+        } else if (scale > 3) {
+            scale = 3;
+        }
+        if (scale != this.scale) {
+            this.markControl.trigger('mark.setting.change', {
+                'image.view.scale': scale
+            });
+            this.scale = scale;
+        }
+
+        this.canvas.width = Math.min(this.container.width(), this.image.width) * this.scale;
         this.canvas.height = this.canvas.width * this.image.height / this.image.width;
         this.ctx.drawImage(this.image, 0, 0, this.image.width, this.image.height, 0, 0, this.canvas.width, this.canvas.height);
     }
 }
 
-SingleImageView.prototype.drawTag = function(tag){
-    if(tag != undefined && tag.positionX > 0 && tag.positionY > 0 && this.image!=undefined){
-        this.ctx.font = parseInt(60 * this.image.scale) + "px Arial";
+SingleImageView.prototype.drawTag = function(tag) {
+    if (tag != undefined && tag.positionX > 0 && tag.positionY > 0 && this.image != undefined) {
+        this.ctx.font = parseInt(60 * this.scale) + "px Arial";
         this.ctx.fillStyle = 'red';
-        this.ctx.fillText(tag.content, tag.positionX*this.canvas.width, tag.positionY*this.canvas.height);
+        this.ctx.fillText(tag.content, tag.positionX * this.canvas.width, tag.positionY * this.canvas.height);
     }
 }