Browse Source

评卷块手工设置图片遮盖
评卷页面针对新的图片遮盖配置正确拼接评卷图片

ting.yin 6 năm trước cách đây
mục cha
commit
77cad0623d

+ 85 - 5
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/MarkGroupController.java

@@ -5,10 +5,15 @@ import java.util.List;
 
 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;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Controller;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.ui.Model;
@@ -17,10 +22,15 @@ import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.servlet.mvc.support.RedirectAttributes;
 
+import cn.com.qmth.stmms.biz.campus.model.Campus;
+import cn.com.qmth.stmms.biz.campus.service.CampusService;
 import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
+import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
 import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
 import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
+import cn.com.qmth.stmms.biz.exam.query.ExamStudentSearchQuery;
 import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
+import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
 import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
 import cn.com.qmth.stmms.biz.exam.service.MarkGroupService;
 import cn.com.qmth.stmms.biz.exam.service.MarkerService;
@@ -29,9 +39,11 @@ import cn.com.qmth.stmms.biz.mark.service.TaskService;
 import cn.com.qmth.stmms.common.auth.annotation.RoleRequire;
 import cn.com.qmth.stmms.common.domain.WebUser;
 import cn.com.qmth.stmms.common.enums.Role;
+import cn.com.qmth.stmms.common.utils.PictureUrlBuilder;
 import cn.com.qmth.stmms.common.utils.RequestUtils;
-import net.sf.json.JSONArray;
-import net.sf.json.JSONObject;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
 
 @Controller("markGroupController")
 @RequestMapping("/admin/exam/group")
@@ -53,6 +65,15 @@ public class MarkGroupController extends BaseExamController {
 
     @Autowired
     private TaskService taskService;
+    
+    @Autowired
+    private ExamStudentService examStudentService;
+    
+    @Autowired
+    private CampusService campusService;
+    
+    @Value("${slice.image.server}")
+    private String imageServer;
 
     @RequestMapping
     public String list(HttpServletRequest request, Model model, @RequestParam String subjectCode) {
@@ -220,7 +241,10 @@ public class MarkGroupController extends BaseExamController {
                 subjectCode, false, number);
         if (group != null) {
             // quick update
-            List<PictureConfigItem> list = PictureConfigItem.parse(picList);
+        	picList = StringEscapeUtils.unescapeHtml(picList);
+        	JSONArray array = JSONArray.fromObject(picList);
+        	List<PictureConfigItem> list = JSONArray.toList(array, PictureConfigItem.class);
+            //List<PictureConfigItem> list = PictureConfigItem.parse(picList);
             if (list != null && !list.isEmpty()) {
                 groupService.updatePicList(examId, subjectCode, number, list);
             }
@@ -288,8 +312,11 @@ public class MarkGroupController extends BaseExamController {
             return "redirect:/admin/exam/group/add";
         } else {
             // create group
+        	picList = StringEscapeUtils.unescapeHtml(picList);
+        	JSONArray array = JSONArray.fromObject(picList);
+        	List<PictureConfigItem> list = JSONArray.toList(array, PictureConfigItem.class);
             group = new MarkGroup(examId, subjectCode, number, StringUtils.trimToNull(title),
-                    PictureConfigItem.parse(picList), 0d);
+                    list, 0d);
             List<Double> scores = buildDoubleList(scoreList);
             if (group.getTitle() != null && group.getPicList() != null && scores.size() > 0) {
                 // clear and replace exam_question
@@ -343,5 +370,58 @@ public class MarkGroupController extends BaseExamController {
         }
         return list;
     }
-
+    
+    @RequestMapping("/getPictureConfig")
+    @RoleRequire(Role.SCHOOL_ADMIN)
+    public String get(HttpServletRequest request, Model model, RedirectAttributes redirectAttributes,
+            @RequestParam String subjectCode, @RequestParam Integer number,
+            @RequestParam(required = false) String picList) throws JsonProcessingException {
+    	int examId = getSessionExamId(request);
+    	ExamStudentSearchQuery query = new ExamStudentSearchQuery();
+    	query.setExamId(examId);
+    	query.setSubjectCode(subjectCode);
+    	query.setUpload(true);
+    	List<ExamStudent> examStudents = examStudentService.findByQuery(query).getResult();
+        MarkGroup group = null;
+        if(number!=null){
+        	group = groupService.findOne(examId, subjectCode, number);
+        }
+        if (examStudents.size()>0) {
+        	model.addAttribute("picUrls", buildPicUrl(group,examStudents.get(0)));
+        	model.addAttribute("pictureConfig", buildPictureConfig(group));
+        	if(StringUtils.isNotBlank(picList)){
+        		model.addAttribute("pictureConfig", StringEscapeUtils.unescapeHtml(picList));
+        	}
+        	model.addAttribute("imageServer", imageServer);
+        	return "modules/mark/picConfig";
+        } else {
+            addMessage(redirectAttributes, "参数有误");
+            redirectAttributes.addAttribute("subjectCode", subjectCode);
+            return "redirect:/admin/exam/group";
+        }
+    }
+    
+    private String buildPictureConfig(MarkGroup group) throws JsonProcessingException {
+    	if(group!=null){
+    		ObjectMapper mapper = new ObjectMapper();
+    		String json  = mapper.writeValueAsString(group.getPictureConfigList());
+    		return json;
+    	}else{
+    		return "";
+    	}
+    }
+    
+    private String buildPicUrl(MarkGroup group,ExamStudent examStudent) {
+    	List<String> picUrls = null;
+    	Campus campus = campusService.findBySchoolAndName(examStudent.getSchoolId(), examStudent.getCampusName());
+    	if(group == null){
+    		picUrls = PictureUrlBuilder.getSliceUrls(examStudent.getExamId(), campus.getId(), examStudent.getSubjectCode(), examStudent.getExamNumber(), examStudent.getSliceCount());
+    	}else{
+    		List<String> picNumbers = new ArrayList<String>();
+    		picNumbers.add(String.valueOf(group.getNumber()));
+    		picUrls = PictureUrlBuilder.getSliceUrls(examStudent.getExamId(), campus.getId(), examStudent.getSubjectCode(), examStudent.getExamNumber(), picNumbers);
+    	}
+    	
+    	return picUrls.toString();
+    }
 }

+ 13 - 2
stmms-web/src/main/java/cn/com/qmth/stmms/mark/MarkController.java

@@ -7,6 +7,9 @@ import java.util.Set;
 
 import javax.servlet.http.HttpServletRequest;
 
+import net.sf.json.JSONArray;
+import net.sf.json.JSONObject;
+
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -20,9 +23,11 @@ import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.servlet.ModelAndView;
 
+import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
 import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
 import cn.com.qmth.stmms.biz.exam.model.Marker;
 import cn.com.qmth.stmms.biz.exam.model.Tag;
+import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
 import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
 import cn.com.qmth.stmms.biz.exam.service.MarkerService;
 import cn.com.qmth.stmms.biz.exam.service.TagService;
@@ -35,9 +40,8 @@ import cn.com.qmth.stmms.common.controller.BaseController;
 import cn.com.qmth.stmms.common.enums.ExamSubjectStatus;
 import cn.com.qmth.stmms.common.enums.LibraryStatus;
 import cn.com.qmth.stmms.common.session.model.StmmsSession;
+import cn.com.qmth.stmms.common.utils.PictureUrlBuilder;
 import cn.com.qmth.stmms.common.utils.RequestUtils;
-import net.sf.json.JSONArray;
-import net.sf.json.JSONObject;
 
 @Controller
 @RequestMapping("/mark")
@@ -59,6 +63,9 @@ public class MarkController extends BaseController {
 
     @Autowired
     private TagService tagService;
+    
+    @Autowired
+    private ExamStudentService studentService;
 
     @Value("${slice.image.server}")
     private String sliceServer;
@@ -290,6 +297,10 @@ public class MarkController extends BaseController {
         for (Task task : list) {
             task.setPrevious(true);
             setTaskParameter(task, marker);
+            MarkLibrary library = libraryService.findById(task.getLibraryId());
+            ExamStudent student = studentService.findByExamIdAndExamNumber(library.getExamId(), library.getExamNumber());
+            task.setPictureUrls(PictureUrlBuilder.getSliceUrls(library.getExamId(), library.getCampusId(),
+                    library.getSubjectCode(), library.getExamNumber(), student.getSliceCount()));
         }
         return list;
     }

+ 0 - 158
stmms-web/src/main/webapp/WEB-INF/views/include/picConfig.jsp

@@ -1,158 +0,0 @@
-<%@ page language="java" pageEncoding="utf-8"%>
-<link rel="stylesheet" href="${ctxStatic}/jcrop/css/jquery.Jcrop.min.css">
-<link rel="stylesheet" href="${ctxStatic}/pic-config/css/style.css">
-<script type="text/javascript" src="${ctxStatic}/jcrop/js/jquery.Jcrop.min.js"></script>
-<script type="text/javascript" src="${ctxStatic}/jquery/jquery-1.9.1.min.js"></script>
-
-<div class="c-box" style="display:none" id="pic-config-div">
-    <div class="cont-z">
-        <div class="c-top">
-            <!--
-            <div class="c-icon">
-                <div class="iviewer_zoom_in iviewer_common iviewer_button"></div>
-                <div class="iviewer_zoom_out iviewer_common iviewer_button"></div>
-                <div class="iviewer_zoom_zero iviewer_common iviewer_button"></div>
-                <div class="iviewer_zoom_fit iviewer_common iviewer_button"></div>
-            </div>
-            -->
-            <ul class="c-tab cl" id="pic-switch" data-index="">
-            </ul>
-        </div>
-        <div class="c-mn">
-            <div class="imgcont"><img id="pic-content" src=""/></div>
-            <canvas id="pic-canvas" style="display:none"></canvas>
-        </div>
-    </div>
-    <div class="cont-y">
-        <div class="c-mn">
-            <div class="c-preview">
-                <ul id="pic-config-preview">
-                </ul>
-            </div>
-        </div>
-        <div class="c-bottom cl">
-            <a class="c-btn close" id="pic-config-clear" href="javascript:void(0)">清空</a>
-            <a class="c-btn s" id="pic-config-save" href="javascript:void(0)">保存</a>
-            <a class="c-btn" id="pic-config-cancel" href="javascript:void(0)">取消</a>
-        </div>
-    </div>
-</div>
-
-<script type="text/javascript">
-var image_server = '${imageServer}';
-var saveCallback;
-var jcrop_canvas;
-var jcrop_api;
-var image_array = [];
-$(document).ready(function(e) {
-    $('#pic-config-div').css('z-index', 9999);
-    $('#pic-config-div').height($(window).height());
-    $('#pic-config-div').width($(window).width());
-    $('#pic-config-div').offset({top:0, left:0});
-    
-    $('#pic-config-clear').click(function(){
-        $('#pic-config-preview').empty();
-    });
-    $('#pic-config-save').click(function(){
-        var result = [];
-        $('#pic-config-preview').find('li').each(function(){
-            result.push(JSON.parse($(this).attr('data-config')));
-        })
-        if(result.length==0){
-            alert('请至少裁切一张小图后再保存');
-            return;
-        }
-        $('#pic-config-div').hide();
-        if(saveCallback!=undefined){
-            saveCallback(result);
-        }
-    });
-    $('#pic-config-cancel').click(function(){
-        $('#pic-config-div').hide();
-    });
-    $('#pic-content').Jcrop({
-        onDblClick: addPreview
-    }, function() {
-        jcrop_api = this;
-    });
-    jcrop_canvas = $('#pic-canvas')[0];
-});
-
-function initPicConfigPopup(urls, config, onSave) {
-    initImages(urls);
-    initConfigs(config);
-    saveCallback = onSave;
-    $('#pic-config-div').show();
-}
-
-function initImages(urls) {
-    var container = $('#pic-switch');
-    container.empty();
-    container.attr('data-index','');
-    image_array = [];
-    for(var i=1;i<=urls.length;i++) {
-        var img = new Image();
-        img.src = image_server + urls[i-1];
-        image_array.push(img);
-        
-        var dom = $('<li data-index="'+i+'"><a href="javascript:void(0)">'+i+'</a></li>').appendTo(container);
-        dom.find('a').click(function(){
-            var index = parseInt($(this).parent().attr('data-index'));
-            jcrop_api.setImage(image_array[index-1].src);
-            container.attr('data-index', index);
-            container.find('li').removeClass('on');
-            $(this).parent().addClass('on');
-        })
-    }
-    container.find('li:first').trigger('click');
-}
-
-function initConfigs(config) {
-    $('#pic-config-preview').empty();
-
-    if(config!=undefined){
-        for(var i=0;i<config.length;i++){
-            addPreviewByConfig(config[i]);
-        }
-    }
-}
-
-function getCropConfig(c) {
-    var scaleX = jcrop_api.getScaleFactor()[0];
-    var scaleY = jcrop_api.getScaleFactor()[1];
-    config = {
-        x: c.x * scaleX,
-        y: c.y * scaleY,
-        w: c.w * scaleX,
-        h: c.h * scaleY
-    }
-    return config;
-}
-
-function addPreview(c) {
-    if (parseInt(c.w) > 0) {
-        var config = getCropConfig(c);
-        config.i = $('#pic-switch').attr('data-index');
-        if(config.i!='') {
-            config.i = parseInt(config.i);
-            addPreviewByConfig(config);
-        }
-        jcrop_api.release();
-    }
-}
-
-function addPreviewByConfig(config){
-    var container = $('#pic-config-preview');
-    
-    jcrop_canvas.width=config.w;
-    jcrop_canvas.height=config.h;
-    jcrop_canvas.getContext("2d").drawImage(image_array[config.i-1], config.x, config.y, config.w, config.h);
-    
-    var dom = $('<li><span class="order">'+config.i+'</span><div class="m"><img src=""/></div><span class="close">&times;</span></li>').appendTo(container);
-    dom.attr('data-config', JSON.stringify(config));
-    dom.find('img').attr('src', jcrop_canvas.toDataURL());
-    dom.find('span.close').click(function(){
-        $(this).parent().remove();
-    });
-}
-</script>

+ 1 - 1
stmms-web/src/main/webapp/WEB-INF/views/modules/exam/examIndex.jsp

@@ -125,7 +125,7 @@
 					<iframe id="mainFrame" name="mainFrame" src="" style="overflow:auto;"
 						scrolling="yes" frameborder="no" width="100%" height="650"></iframe>
 				</div>
-			    <%@include file="/WEB-INF/views/include/picConfig.jsp" %>
+<%-- 			    <%@include file="/WEB-INF/views/include/picConfig.jsp" %> --%>
 			</div>
 		    <div id="footer" class="row-fluid">
 	            Copyright &copy; 2012-2014 讯飞云阅卷(高校版) - Powered By <a href="http://www.qmth.com.cn" target="_blank">启明软件</a> V1.0

+ 3 - 2
stmms-web/src/main/webapp/WEB-INF/views/modules/exam/groupAdd.jsp

@@ -52,9 +52,10 @@
             </div>
         </div>
         <div class="control-group">
-            <label class="control-label">小图序号</label>
+            <label class="control-label">图片显示</label>
             <div class="controls">
-                <form:input path="picList" htmlEscape="false" maxlength="100" class="required"/>
+                <form:input path="picList" class="required" id="picList"  type="hidden"/>
+                <a href="${ctx}/admin/exam/group/getPictureConfig?subjectCode=${group.subjectCode}&number=${group.number}" target="_blank" class="required" id= "configuration">设置</a>
             </div>
         </div>
         <div class="form-actions">

+ 4 - 3
stmms-web/src/main/webapp/WEB-INF/views/modules/exam/groupEditFull.jsp

@@ -54,9 +54,10 @@
             </div>
         </div>
         <div class="control-group">
-            <label class="control-label">小图序号</label>
-            <div class="controls">
-                <form:input path="picList" htmlEscape="false" maxlength="100" class="required"/>
+            <label class="control-label">图片显示</label>
+            <div class="controls">                
+            	<form:input path="picList" class="required" id="picList"  type="hidden"/>
+                <a href="${ctx}/admin/exam/group/getPictureConfig?subjectCode=${group.subjectCode}&number=${group.number}" target="_blank" class="required" id= "configuration">设置</a>
             </div>
         </div>
         <div class="control-group">

+ 3 - 2
stmms-web/src/main/webapp/WEB-INF/views/modules/exam/groupEditSimple.jsp

@@ -44,9 +44,10 @@
 			</div>
 		</div>
         <div class="control-group">
-            <label class="control-label">小图序号</label>
+            <label class="control-label">图片显示</label>
             <div class="controls">
-                <form:input path="picList" htmlEscape="false" maxlength="100" class="required"/>
+                <form:input path="picList" class="required" id="picList"  type="hidden"/>
+                <a href="${ctx}/admin/exam/group/getPictureConfig?subjectCode=${group.subjectCode}&number=${group.number}" target="_blank" class="required" id= "configuration">设置</a>
             </div>
         </div>
         <c:forEach items="${questions}" var="question">

+ 45 - 25
stmms-web/src/main/webapp/static/mark-track/js/modules/image-builder.js

@@ -19,16 +19,27 @@ ImageBuilder.prototype.init = function() {
 
 ImageBuilder.prototype.build = function(task, callback) {
     var self = this;
+    //初始化图片拼接配置,过滤实际需要加载的图片
+    var config = task.pictureConfig;
+    var indexSet = {};
+    for(var i=0;i<config.length;i++){
+    	indexSet[config[i].i-1] = true;
+    }
     //调用图片预加载函数,实现回调函数
     var imageObjects = [];
-    this.loadImages(imageObjects, task.pictureUrls, 0, function(images) {
+    this.loadImages(imageObjects,indexSet, task.pictureUrls, 0, function(images) {
         var maxWidth = 0;
         var totalHeight = 0;
-        for (var i = 0; i < images.length; i++) {
+        for (var i = 0; i < config.length; i++) {
             //计算最大宽度与合计高度
-            var image = images[i];
-            maxWidth = Math.max(maxWidth, image.width);
-            totalHeight += image.height;
+            if(config[i].w<=0){
+            	config[i].w=images[config[i].i-1].width;
+            }
+            if(config[i].h<=0){
+            	config[i].h=images[config[i].i-1].height;
+            }
+            maxWidth = Math.max(maxWidth, config[i].w);
+            totalHeight += config[i].h;
         }
         if (maxWidth > 0 && totalHeight > 0) {
             //设置画布大小及背景颜色
@@ -38,10 +49,10 @@ ImageBuilder.prototype.build = function(task, callback) {
             self.ctx.fillRect(0, 0, maxWidth, totalHeight);
             //绘画到画布
             var height = 0;
-            for (var i = 0; i < images.length; i++) {
-                var image = images[i];
-                self.ctx.drawImage(image, 0, 0, image.width, image.height, 0, height, image.width, image.height);
-                height += image.height;
+            for (var i = 0; i < config.length; i++) {
+                var image = images[config[i].i-1];
+                self.ctx.drawImage(image,config[i].x, config[i].y, config[i].w, config[i].h, 0, height, config[i].w, config[i].h);
+                height += config[i].h;
             }
             //生成合并后的图像数据
             task.imageData = this.canvas.toDataURL("image/jpeg");
@@ -56,27 +67,36 @@ ImageBuilder.prototype.build = function(task, callback) {
     });
 }
 
-/*实现一系列图片的预加载
-参数urls:图片实际URL数组
+/*
+实现一系列图片的预加载
+参数indexSet:实际需要的图片序号集合
+参数urls:图片URL数组
 参数number:array数组遍历下标
-参数callback:回调函数——图片预加载完成后立即执行此函数。*/
-ImageBuilder.prototype.loadImages = function(images, urls, number, callback, exception) {
+参数callback:回调函数——所有图片加载完成后才执行此函数
+参数exception:回调函数——任一图片加载失败后立即执行此函数
+*/
+ImageBuilder.prototype.loadImages = function(images,indexSet, urls, number, callback, exception) {
     var self = this;
     var imageServer = this.markControl.context.imageServer;
     var defaultServer = this.markControl.option.imageServer;
     if (urls != undefined && number < urls.length) {
-        var img = new Image();
-        img.onload = function() {
-            images.push(img);
-            self.loadImages(images, urls, number + 1, callback, exception);
-        }
-        img.onerror = function() {
-            img.onerror = undefined;
-            //self.loadImages(images, urls, number + 1, callback);
-            exception('load error for: ' + img.src);
-        }
-        img.crossOrigin = '';
-        img.src = imageServer + urls[number] + '?' + new Date().getTime();
+    	if(indexSet[number]==true){
+    		var img = new Image();
+    		img.onload = function() {
+    			images.push(img);
+    			self.loadImages(images, indexSet,urls, number + 1, callback, exception);
+    		}
+    		img.onerror = function() {
+    			img.onerror = undefined;
+    			//self.loadImages(images, urls, number + 1, callback);
+    			exception('load error for: ' + img.src);
+    		}
+    		img.crossOrigin = '';
+    		img.src = imageServer + urls[number] + '?' + new Date().getTime();
+    	}else{
+    		images.push({});
+    		self.loadImages(images, indexSet, urls, number + 1, callback, exception);
+    	}
     } else {
         callback.call(this, images);
     }

+ 1 - 0
stmms-web/src/main/webapp/static/pic-config/css/style.css

@@ -198,6 +198,7 @@ input[type="text"]:focus {
 	-moz-border-radius: 10px;
 	-webkit-border-radius: 10px;
 	border-radius: 10px;
+	margin-right:5px;
 }
 .c-tab li.on a , .c-tab li a:hover {
 	background-color: rgba(108,128,147,.85);