派生自 projectDept/qhighschool

EricsHu
2022-12-05 068fc7f2e81178e55fa191a13709af64b1a163f6
src/main/java/com/qxueyou/scc/exercise/service/impl/ExerciseService.java
@@ -87,7 +87,7 @@
import com.qxueyou.scc.user.model.UserRegistration;
/**
 * 练习 实现service  练习后台
 * 练习 实现service  练习后台
 * 
 * @author zhiyong
 *
@@ -122,7 +122,7 @@
   }
   /**
    * 依赖注入
    * 依赖注入
    *
    * @param exerExtendDAO
    */
@@ -143,8 +143,8 @@
      int iCount = 0;
      if (type == 3) {
         // 查询当前class存在的存在的顺序、随机练习或者 章节练习 个数
         // 可能结果:0、 新增三种;1,新增两种(顺序随机),2,新增一种(章节),3的话,不增加
         // 查询当前class存在的存在的顺序、随机练习或者 章节练习 个数
         // 可能结果:0、 新增三种;1,新增两种(顺序随机),2,新增一种(章节),3的话,不增加
         String hsql = "from ExerciseGroup where classId = ? and  case when type = ? then 1 when type = ? then 1 when type = ? and "
               + " attribute1 = ? and attribute2 = ? then 1 else 0 end  = 1 and deleteFlag is false";
         iCount = findCount(hsql, CollectionUtils.newList(ClientUtils.getClassId(), ExerciseGroup.TYPE_EXERCISE_RANDOM, ExerciseGroup.TYPE_EXERCISE_SEQUENCE, ExerciseGroup.TYPE_CHAPTER_ITEM, lessonId, chapterId));
@@ -152,31 +152,31 @@
      Result objResult = saveOrUpdateAll(initExerciseGroupList(name, type, lessonId, chapterId, iCount));
      // 保存
      // 保存
      return objResult;
   }
   /**
    * 新增练习组
    * 新增练习组
    * 
    * @param name
    *            练习组名称
    *            练习组名称
    * @param type
    *            练习组类型
    *            练习组类型
    * @param lessonId
    *            课程id
    *            课程id
    * @param chapterId
    *            章节id
    * @param 模拟考试
    *            时间设置
    *            章节id
    * @param 模拟考试
    *            时间设置
    * @return
    */
   public Result insertExerciseGroup(String groupId,String name, short type, String lessonId, String chapterId, String attribute1, boolean repeatFlag) {
      
      if(StringUtils.isNotBlank(groupId)){ // 更新
      if(StringUtils.isNotBlank(groupId)){ // 更新
         
         return updateExerciseGroup(groupId, name, type, lessonId, chapterId, attribute1, repeatFlag);
      }else{ // 新增
      }else{ // 新增
         
         return saveExerciseGroup(name, type, lessonId, chapterId, attribute1, repeatFlag);
      }
@@ -185,16 +185,16 @@
   public Result updateExerciseGroup(String groupId,String name, short type, String subjectId, String chapterId, String attribute1, boolean repeatFlag) {
      ExerciseGroup group = read(ExerciseGroup.class, groupId);
      
      if(type == ExerciseGroup.TYPE_CHAPTER_ITEM){ // 章节练习
      if(type == ExerciseGroup.TYPE_CHAPTER_ITEM){ // 章节练习
         
         group.setAttribute2(chapterId);
      }
      if (type == ExerciseGroup.TYPE_MOCK_EXAM) {// 模拟考试
         // 添加练习组时间 、是否重做
      if (type == ExerciseGroup.TYPE_MOCK_EXAM) {// 模拟考试
         // 添加练习组时间 、是否重做
         addExerciseGroupExtendTime(groupId, attribute1, repeatFlag);
      }
      if (type == ExerciseGroup.TYPE_HOMEWORK) {// 家庭作业
         // 添加是否重做
      if (type == ExerciseGroup.TYPE_HOMEWORK) {// 家庭作业
         // 添加是否重做
         addExerciseGroupExtendTime(groupId, null, repeatFlag);
      }
      
@@ -208,8 +208,8 @@
   public Result saveExerciseGroup(String name, short type, String lessonId, String chapterId, String attribute1, boolean repeatFlag) {
      int iCount = 0;
      if (type == ExerciseGroup.TYPE_EXERCISE_SEQUENCE) {
         // 查询当前class存在的存在的顺序、随机练习或者 章节练习 个数
         // 可能结果:0、 新增三种;1,新增两种(顺序随机),2,新增一种(章节),3的话,不增加
         // 查询当前class存在的存在的顺序、随机练习或者 章节练习 个数
         // 可能结果:0、 新增三种;1,新增两种(顺序随机),2,新增一种(章节),3的话,不增加
         String hsql = "from ExerciseGroup where classId = ? and  case when type = ? then 1 when type = ? then 1 when type = ? and "
               + " attribute1 = ? and attribute2 = ? then 1 else 0 end  = 1 and deleteFlag is false";
         iCount = findCount(hsql, CollectionUtils.newList(ClientUtils.getClassId(), ExerciseGroup.TYPE_EXERCISE_RANDOM, ExerciseGroup.TYPE_EXERCISE_SEQUENCE, ExerciseGroup.TYPE_CHAPTER_ITEM, lessonId, chapterId));
@@ -217,7 +217,7 @@
      List<ExerciseGroup> lstExeGroup = initExerciseGroupList(name, type, lessonId, chapterId, iCount);
      // 兼容1.0版本 模拟考试时间设置
      // 兼容1.0版本 模拟考试时间设置
      for (ExerciseGroup group : lstExeGroup) {
         
         group.setOrderNum(BigInteger.valueOf(SchCourseware.COURSEWARE_MAX_ORDER));
@@ -231,40 +231,40 @@
      //Result objResult = saveOrUpdateAll(lstExeGroup);
      if (type == ExerciseGroup.TYPE_MOCK_EXAM) {// 模拟考试
         // 添加练习组时间 、是否重做
      if (type == ExerciseGroup.TYPE_MOCK_EXAM) {// 模拟考试
         // 添加练习组时间 、是否重做
         addExerciseGroupExtendTime(lstExeGroup.get(0).getGroupId(), attribute1, repeatFlag);
      }
      if (type == ExerciseGroup.TYPE_HOMEWORK) {// 家庭作业
         // 添加是否重做
      if (type == ExerciseGroup.TYPE_HOMEWORK) {// 家庭作业
         // 添加是否重做
         addExerciseGroupExtendTime(lstExeGroup.get(0).getGroupId(), null, repeatFlag);
      }
      // 保存
      // 保存
      return new Result(true);
   }
   /**
    * 新增题库
    * 新增题库
    * 
    * @param name
    *            练习组名称
    *            练习组名称
    * @param type
    *            练习组类型
    *            练习组类型
    * @param lessonId
    *            课程id
    *            课程id
    * @param chapterId
    *            章节id
    * @param 模拟考试
    *            时间设置
    *            章节id
    * @param 模拟考试
    *            时间设置
    * @return
    */
   public Result insertOrgExercise(ExerciseGroup group, boolean repeatFlag) {
      
      if(StringUtils.isNotBlank(group.getGroupId())){ // 更新
      if(StringUtils.isNotBlank(group.getGroupId())){ // 更新
         
         return updateOrgExerciseGroup(group, repeatFlag);
      }else{ // 新增
      }else{ // 新增
         
         return saveOrgExerciseGroup(group, repeatFlag);
      }
@@ -274,12 +274,12 @@
      
      ExerciseGroup oldGroup = read(ExerciseGroup.class, group.getGroupId());
      
      if (oldGroup.getType() == ExerciseGroup.TYPE_MOCK_EXAM) {// 模拟考试
         // 添加练习组时间 、是否重做
      if (oldGroup.getType() == ExerciseGroup.TYPE_MOCK_EXAM) {// 模拟考试
         // 添加练习组时间 、是否重做
         addExerciseGroupExtendTime(group.getGroupId(), group.getAttribute1(), repeatFlag);
      }
      if (oldGroup.getType() == ExerciseGroup.TYPE_HOMEWORK) {// 家庭作业
         // 添加是否重做
      if (oldGroup.getType() == ExerciseGroup.TYPE_HOMEWORK) {// 家庭作业
         // 添加是否重做
         addExerciseGroupExtendTime(group.getGroupId(), null, repeatFlag);
      }
      
@@ -302,8 +302,8 @@
      if (StringUtils.isNotBlank(group.getAttribute1())) {
         addExerciseGroupExtendTime(group.getGroupId(), group.getAttribute1(), repeatFlag);
      }
      if (group.getType() == ExerciseGroup.TYPE_HOMEWORK) {// 家庭作业
         // 添加是否重做
      if (group.getType() == ExerciseGroup.TYPE_HOMEWORK) {// 家庭作业
         // 添加是否重做
         addExerciseGroupExtendTime(group.getGroupId(), null, repeatFlag);
      }
      
@@ -313,7 +313,7 @@
   }
   
   /**
    * 拷贝练习
    * 拷贝练习
    * 
    * @param id
    * @param subjectId
@@ -348,23 +348,23 @@
      
      this.saveExerciseGroup(newGroup);
      
      //班级拷贝不需要新增关联表
      //班级拷贝不需要新增关联表
      if(StringUtils.isEmpty(ClientUtils.getClassId())){
         newGroup.setOriginExerciseId(newGroup.getGroupId());
         this.saveExerciseGroup(newGroup);
         this.insertReCourse(collegeCourseId, newGroup.getGroupId());
      }
      
      // 扩展表: extend
      // 扩展表: extend
      this.doSaveCopyExtend(oldExercise,newGroup);
      
      this.doCopyExerciseItem(newGroup.getGroupId(), oldExercise.getGroupId(), null, 1);//拷贝
      this.doCopyExerciseItem(newGroup.getGroupId(), oldExercise.getGroupId(), null, 1);//拷贝
      
      return new Result(true);
   }
   
   /**
    * 拷贝练习题
    * 拷贝练习题
    * 
    * @param items
    * @param newGroupId
@@ -385,14 +385,14 @@
         List<ExerciseGroupItemRe> reNew = new ArrayList<>();
         List<ExerciseObjectImg> exerciseObjectImgNew = new ArrayList<>();
         
         // 得到当前组题目的最大题号
         // 得到当前组题目的最大题号
         int maxGroupItemOrder = queryExerciseGroupItemNo(newGroupId);
         
         for(ExerciseItem objExerciseItem : items){
            ExerciseGroupItemRe oldExerciseGroupItemRe = this.findUnique("from ExerciseGroupItemRe where deleteFlag is false and exerciseGroupId = ? and exerciseItemId = ?",
                  CollectionUtils.newList(oldGroupId, objExerciseItem.getExerciseId()), ExerciseGroupItemRe.class);
            
            //临时对象
            //临时对象
            ExerciseItem tem = new ExerciseItem();
            tem = (ExerciseItem) BeanUtils.cloneBean(objExerciseItem);
            List<ExerciseObjectImg> exerciseObjectImg = this.find("from ExerciseObjectImg m where m.deleteFlag is false and m.exerciseObjectId = ?",
@@ -408,7 +408,7 @@
            ExerciseItem objExerciseItemNew = new ExerciseItem();
            BeanUtils.copyProperties(objExerciseItemNew, tem);
            objExerciseItemNew.setExerciseId(null);
            //拷贝的练习不同步
            //拷贝的练习不同步
            objExerciseItemNew.setOrgiExerciseId(type == 1?null:StringUtils.isEmpty(objExerciseItem.getOrgiExerciseId())?objExerciseItem.getExerciseId():objExerciseItem.getOrgiExerciseId());
            TraceUtils.setCreateTrace(objExerciseItemNew);
            
@@ -482,19 +482,19 @@
         this.saveOrUpdateAll(analysisesNew);
         this.saveOrUpdateAll(exerciseObjectImgNew);
         
         //更新统计
         //更新统计
         this.updateGroupUpdateTimeByList(this.find("from ExerciseGroup where groupId = ?", CollectionUtils.newList(newGroupId), ExerciseGroup.class));
      }
   }
   
   /**
    * 插入练习和科目关联
    * 插入练习和科目关联
    * 
    * @param collegeCourseId
    * @param handoutId
    */
   private void insertReCourse(String collegeCourseId, String groupId){
      // 序号
      // 序号
      String hql = "select MAX(c.orderNum) from ExerciseReCourse c where c.deleteFlag is false and c.collegeCourseId = ? and orgId = ? ";
      Integer iMax = this.findUnique(hql, CollectionUtils.newList(collegeCourseId, ClientUtils.getOrgId()), Integer.class);
   
@@ -517,21 +517,21 @@
   public Result insertAppointExercise(String groupIds[], String orgIds[], String classIds[]) {
      if (null == groupIds || groupIds.length == 0) {
         return new Result(false, "参数错误");
         return new Result(false, "参数错误");
      }
      // 一次性查询groupId对应的collegeCourseId
      // 一次性查询groupId对应的collegeCourseId
      String hql = " from ExerciseReCourse where groupId in (:groupIds) and deleteFlag is false";
      Map<String, Object> argsMap = new HashMap<String, Object>();
      argsMap.put("groupIds", groupIds);
      List<ExerciseReCourse> courseList = findByComplexHql(hql, argsMap, ExerciseReCourse.class);
      // 放入map中 KEY:groupId VALUE:collegeCourseId
      // 放入map中 KEY:groupId VALUE:collegeCourseId
      Map<String, String> groupReCourse = new HashMap<String, String>();
      for (ExerciseReCourse exerciseReCourse : courseList) {
         groupReCourse.put(exerciseReCourse.getGroupId(), exerciseReCourse.getCollegeCourseId());
      }
      // 一次性查询classId对应的orgId
      // 一次性查询classId对应的orgId
      Map<String, String> classMap = new HashMap<String, String>();
      if (classIds.length > 0) {
         hql = " from ClsClass where classId in (:classIds) and deleteFlag is false";
@@ -539,14 +539,14 @@
         argsMap.put("classIds", classIds);
         List<ClsClass> classList = findByComplexHql(hql, argsMap, ClsClass.class);
         // 放入map中 KEY:classId VALUE:orgId
         // 放入map中 KEY:classId VALUE:orgId
         for (ClsClass orgClass : classList) {
            classMap.put(orgClass.getClassId(), orgClass.getOrgId());
         }
      }
      
      // 一次性查询groupId对应的orderNum
      // 一次性查询groupId对应的orderNum
      Map<String, Integer> orderMap = new HashMap<String, Integer>();
      
      hql = " from ExerciseReCourse where groupId in (:groupIds) and deleteFlag is false and orgId = :currOrgId";
@@ -555,16 +555,16 @@
      argsMap.put("currOrgId", ClientUtils.getOrgId());
      List<ExerciseReCourse> courseLst = findByComplexHql(hql, argsMap, ExerciseReCourse.class);
      // 放入map中 KEY:classId VALUE:orgId
      // 放入map中 KEY:classId VALUE:orgId
      for (ExerciseReCourse c : courseLst) {
         orderMap.put(c.getGroupId(), c.getOrderNum());
      }
      
      for (String groupId : groupIds) {
         if (orgIds.length > 0) { // 指定给机构
         if (orgIds.length > 0) { // 指定给机构
            insertOrgGroup(groupId, orgIds, groupReCourse.get(groupId),orderMap);
         }
         if (classIds.length > 0) { // 指定给班级
         if (classIds.length > 0) { // 指定给班级
            ExerciseGroup group = read(ExerciseGroup.class, groupId);
            insertClassGroup(groupId, classIds, group, groupReCourse.get(groupId), classMap,orderMap);
         }
@@ -573,7 +573,7 @@
   }
   /**
    * 指定给机构
    * 指定给机构
    * 
    * @param groupId
    * @param orgIds
@@ -581,7 +581,7 @@
    * @return
    */
   public void insertOrgGroup(String groupId, String orgIds[], String collegeCourseId,Map<String, Integer> orderMap) {
      // 查询出所有不符合条件的数据
      // 查询出所有不符合条件的数据
      String hql = "select orgId from ExerciseReCourse where groupId = :groupId and deleteFlag is false and orgId in (:orgIds)";
      Map<String, Object> args = new HashMap<String, Object>();
      args.put("groupId", groupId);
@@ -591,7 +591,7 @@
      for (String orgId : orgIds) {
         orgList.add(orgId);
      }
      // 剔除掉不符合条件的orgId
      // 剔除掉不符合条件的orgId
      orgList.removeAll(strings);
      if(orgList.isEmpty()){
         return;
@@ -613,7 +613,7 @@
   }
   /**
    * 指定给班级
    * 指定给班级
    * @param groupId
    * @param classIds
    * @param group
@@ -621,17 +621,17 @@
    * @param classMap
    */
   public void insertClassGroup(String groupId, String classIds[], ExerciseGroup group, String collegeCourseId, Map<String, String> classMap,Map<String, Integer> orderMap) {
      //章节id
      //章节id
      Map<String,SubjectChapter> origChapterMap = new HashMap<String, SubjectChapter>();
      Map<String, String> subjectMap = new HashMap<String, String>();
      String hql = "from ExerciseGroupExtend where deleteFlag is false and groupId=? ";
      // 查询练习组扩展表
      // 查询练习组扩展表
      ExerciseGroupExtend extend = this.findUnique(hql, CollectionUtils.newList(groupId), ExerciseGroupExtend.class);
      //hql = " from ExerciseGroupItemRe where exerciseGroupId = ? and deleteFlag is false ";
      //List<ExerciseGroupItemRe> lstItem = find(hql, CollectionUtils.newList(groupId), ExerciseGroupItemRe.class);
      // 查询出所有不符合条件的数据
      // 查询出所有不符合条件的数据
      hql = "select classId from ExerciseGroup where classId in (:classIds) and originExerciseId = :groupId and deleteFlag is false";
      Map<String, Object> args = new HashMap<String, Object>();
      args.put("classIds", classIds);
@@ -641,13 +641,13 @@
      for (String classId : classIds) {
         classList.add(classId);
      }
      // 剔除不符合的classId
      // 剔除不符合的classId
      classList.removeAll(strings);
      if(classList.isEmpty()){
         return;
      }
      if(StringUtils.isNotEmpty(group.getSubjectId())){
         // 一次性查询班级ID对应的classSubjectId
         // 一次性查询班级ID对应的classSubjectId
         hql = " from SchClassSubject where classId in(:classIds) and origSubjectId = :subjectId and deleteFlag is false";
         args = new HashMap<String, Object>();
         args.put("classIds", classList.toArray());
@@ -685,8 +685,8 @@
            if (StringUtils.isNotBlank(extend.getExerciseTime())) {
               addExerciseGroupExtendTime(newGroup.getGroupId(), extend.getExerciseTime(), extend.getRepeatFlag());
            }
            if (newGroup.getType() == ExerciseGroup.TYPE_HOMEWORK) {// 家庭作业
               // 添加是否重做
            if (newGroup.getType() == ExerciseGroup.TYPE_HOMEWORK) {// 家庭作业
               // 添加是否重做
               addExerciseGroupExtendTime(newGroup.getGroupId(), null, extend.getRepeatFlag());
            }
         }
@@ -695,13 +695,13 @@
            this.doCopyExerciseItem(newGroup.getGroupId(), groupId, null, 2);
            
         }catch (IllegalAccessException e) {
            log.error("下发练习出错", e);
            log.error("下发练习出错", e);
         } catch (InvocationTargetException e) {
            log.error("下发练习出错", e);
            log.error("下发练习出错", e);
         } catch (InstantiationException e) {
            log.error("下发练习出错", e);
            log.error("下发练习出错", e);
         } catch (NoSuchMethodException e) {
            log.error("下发练习出错", e);
            log.error("下发练习出错", e);
         }
      }
   }
@@ -709,7 +709,7 @@
   /**
    * 添加练习时间
    * 添加练习时间
    * 
    * @param groupId
    * @param exerciseTime
@@ -719,7 +719,7 @@
      String hql = "from ExerciseGroupExtend where deleteFlag is false and groupId=? ";
      // 查询练习组扩展表
      // 查询练习组扩展表
      ExerciseGroupExtend extend = this.findUnique(hql, CollectionUtils.newList(groupId), ExerciseGroupExtend.class);
      if (null == extend) {
@@ -739,7 +739,7 @@
   }
   /**
    * 新增练习扩展表
    * 新增练习扩展表
    * 
    * @param extend
    * @return
@@ -754,7 +754,7 @@
   }
   /**
    * 更新练习扩展表
    * 更新练习扩展表
    * 
    * @param extend
    * @return
@@ -783,7 +783,7 @@
   /*
    * (non-Javadoc)
    * 
    * @see com.iqtogether.qxueyou.exercise.service.IExerciseService#readExerciseItems(java.lang.String) 20150901:增加排序,习题数据和前台app顺序默认一致,题号保持一致。随机练习处理
    * @see com.iqtogether.qxueyou.exercise.service.IExerciseService#readExerciseItems(java.lang.String) 20150901:增加排序,习题数据和前台app顺序默认一致,题号保持一致。随机练习处理
    */
   @Override
   public List<ExerciseItem> readExerciseItemsWithNo(String groupId) {
@@ -793,10 +793,10 @@
         return null;
      }
      // 默认章节练习
      // 默认章节练习
      String hql = "select item,re.docOrder,re.relationId " + "from ExerciseItem item,ExerciseGroupItemRe re " + "where re.exerciseGroupId=? " + "and re.exerciseItemId=item.exerciseId " + "and item.deleteFlag is false " + "and re.deleteFlag is false " + "order by re.itemOrder ";
      // 随机练习,顺序练习
      // 随机练习,顺序练习
      if (ExerciseGroup.TYPE_EXERCISE_RANDOM == group.getType() || ExerciseGroup.TYPE_EXERCISE_SEQUENCE == group.getType()) {
         hql = "select item,re.docOrder,re.relationId " + "from ExerciseItem item,ExerciseGroupItemRe re " + "where re.exerciseGroupId=? and " + "re.exerciseItemId=item.exerciseId " + "and item.deleteFlag is false " + "and re.deleteFlag is false " + "order by item.chapterId, re.itemOrder ";
      }
@@ -826,15 +826,15 @@
               log.error(e, e);
            }
            // 此序号和app一致
            // 此序号和app一致
            item.setItemNo(iNum + 1);
            // 此序号和导入的doc文档一致,如果是导入的习题
            // 此序号和导入的doc文档一致,如果是导入的习题
            if (null != objs.get(iNum)[1]) {
               item.setDocNo((int) objs.get(iNum)[1]);
            }
            // 关联表ID
            // 关联表ID
            if (null != objs.get(iNum)[2]) {
               item.setReId((String) objs.get(iNum)[2]);
            }
@@ -848,12 +848,12 @@
   }
   /**
    * 查看问卷详情
    * 查看问卷详情
    * 
    * @param groupId
    *            问题组id
    *            问题组id
    * @param evaluateTemId
    *            模板id
    *            模板id
    * @return
    */
   @Override
@@ -861,7 +861,7 @@
      ExerciseGroup group = this.read(ExerciseGroup.class, groupId);
      if (null == group) {
         new ResultJson(false, "习题组不存在");
         new ResultJson(false, "习题组不存在");
      }
      QExerciseItem qItem = QExerciseItem.exerciseItem;
@@ -881,7 +881,7 @@
         return lstItems;
      }
      
      // 0.组装参数
      // 0.组装参数
      Map<String, Object> argsMap = new HashMap<String, Object>();
      Object[] args = new Object[lstItems.size()];
      for(int i=0; i<lstItems.size(); i++){
@@ -889,7 +889,7 @@
      }
      argsMap.put("exerciseIds", args);
      
      // 1.查询练习题目全站分析
      // 1.查询练习题目全站分析
      String hql_analisis = "from ExerciseItemAnalisi  where exerciseItemId in (:exerciseIds)  and deleteFlag is false ";
      List<ExerciseItemAnalisi> lstAnalisis = this.findByComplexHql(hql_analisis, argsMap, ExerciseItemAnalisi.class);
      Map<String, ExerciseItemAnalisi> analisiMap = new HashMap<String, ExerciseItemAnalisi>(lstAnalisis.size());
@@ -897,12 +897,12 @@
         analisiMap.put(analisis.getExerciseItemId(), analisis);
      }
      
      // 2.查询练习题目答案选项
      // 2.查询练习题目答案选项
      Map<String, List<ExerciseItemOption>> optionsMap = new HashMap<String, List<ExerciseItemOption>>(lstItems.size());
      Map<String, String> answerMap = new HashMap<String, String>();
      String hql_options = "from ExerciseItemOption where exerciseItemId in (:exerciseIds) and deleteFlag is false order by exerciseItemId, optionOrder ";
      List<ExerciseItemOption> lstAllOptions = this.findByComplexHql(hql_options, argsMap, ExerciseItemOption.class);
      // 2.1.组装参数 用于查询练习选项图片
      // 2.1.组装参数 用于查询练习选项图片
      Map<String, Object> argsImgMap = new HashMap<String, Object>();
      Object[] argImgs = new Object[lstAllOptions.size()];
      for(int i=0; i<lstAllOptions.size(); i++){
@@ -910,38 +910,38 @@
      }
      argsImgMap.put("optionIds", argImgs);
      
      // 2-3-1查询题目是否关联图片
      // 2-3-1查询题目是否关联图片
      String hql_itemImgs = "from ExerciseObjectImg where exerciseObjectId in (:exerciseIds) and deleteFlag is false and objectType=1 order by exerciseObjectId,imgOrder ";
      List<ExerciseObjectImg> lstItemImgs = this.findByComplexHql(hql_itemImgs, argsMap, ExerciseObjectImg.class);
      Map<String, List<ExerciseObjectImg>> imgItemMap = ExerciseUtils.packageExerciseItemImg(lstItemImgs);
      
      Map<String, List<ExerciseObjectImg>> imgOptionMap = null;
      if(argImgs.length > 0) {
         // 2-3-2查询题目选项是否关联图片
         // 2-3-2查询题目选项是否关联图片
         String hql_optionImgs = "from ExerciseObjectImg where exerciseObjectId in (:optionIds) and deleteFlag is false and objectType=2";
         List<ExerciseObjectImg> lstOptionImgs = this.findByComplexHql(hql_optionImgs, argsImgMap, ExerciseObjectImg.class);
         imgOptionMap = ExerciseUtils.packageExerciseItemImg(lstOptionImgs);
      }
      
      // 重新组装练习
      // 重新组装练习
      ExerciseUtils.packageExerciseItem(optionsMap, answerMap, lstAllOptions, imgOptionMap);
      
      
      // 4.重新组装返回结果
      // 4.重新组装返回结果
      String exerciseId = null;
      for(ExerciseItem item:lstItems){
         // 4.0  分析结果
         // 4.0  分析结果
         exerciseId = item.getExerciseId();
         
         // 得到练习组id
         // 得到练习组id
         if(StringUtils.isNotBlank(groupId)){
            item.setExerciseGroupId(groupId);
         }
         
         // 4.3 题目选项
         // 4.3 题目选项
         item.setOptions(optionsMap.get(exerciseId));
         
         // 4.5题目中是否有图片
         // 4.5题目中是否有图片
         if(imgItemMap.get(exerciseId) != null){
            item.setImgs(imgItemMap.get(exerciseId));
         }
@@ -963,27 +963,27 @@
   public Result insertExerciseItem(String groupId, ExerciseItem item, List<ExerciseItemOption> lstOptions, String analysis) {
      TraceUtils.setCreateTrace(lstOptions);
      // 1. 保存习题
      // 1. 保存习题
      ExerciseGroup group = this.read(ExerciseGroup.class, groupId);
      handlerExerciseItem(group, item);
      save(item);
      // 2. 保存习题和习题组关系
      // 获取一个习题需要跟新的关系条数
      // 2. 保存习题和习题组关系
      // 获取一个习题需要跟新的关系条数
      List<ExerciseGroup> result = initExerciseGroup(groupId);
      // 得到当前组题目的最大题号
      // 得到当前组题目的最大题号
      int maxGroupItemOrder = queryExerciseGroupItemNo(groupId);
      List<ExerciseGroupItemRe> groupRes = initExerciseGroupItemRe(result, item.getExerciseId(), getGroupReMaxOrder(groupId), ++maxGroupItemOrder );
      // 得到最大的ORDER
      // 得到最大的ORDER
      saveOrUpdateAll(groupRes);
      
      // 20150618:配合前台app,所有修改同时修改group表最后修改时间
      // 20150618:配合前台app,所有修改同时修改group表最后修改时间
      updateGroupUpdateTimeByList(result);
      // 3. 保存习题解析
      // 3. 保存习题解析
      ExerciseItemAnalisi analysisVO = new ExerciseItemAnalisi();
      analysisVO.setAnalysis(analysis);
      analysisVO.setAccuracy(BigDecimal.ZERO);
@@ -993,19 +993,19 @@
      saveAnalysis(item);
      
      // 4. 保存习题选项
      // 4. 保存习题选项
      for (ExerciseItemOption option : lstOptions) {
         option.setExerciseItemId(item.getExerciseId());
         save(option);
         // 新增习题选项图片
         // 新增习题选项图片
         updateExerOptionObjImgId(option);
      }
      item.setOptions(lstOptions);
      // 新增习题图片
      // 新增习题图片
      updateExerciseObjImgId(item);
      
      //保存题目分数
      //保存题目分数
      List<ExerciseItemScore>  lstExerciseItemScore = item.getScores();
      if(lstExerciseItemScore!=null && lstExerciseItemScore.size()>0){
         for (ExerciseItemScore score : lstExerciseItemScore) {
@@ -1017,7 +1017,7 @@
      }
      
//      if(StringUtils.isEmpty(group.getClassId())){
//         // 同步习题
//         // 同步习题
//         String hql = " from ExerciseGroup where originExerciseId = ?  and deleteFlag is false and groupId != ?";
//         List<ExerciseGroup> lstGroup = find(hql, CollectionUtils.newList(group.getOriginExerciseId(), groupId), ExerciseGroup.class);
//         List<ExerciseItem> items = find("from ExerciseItem where exerciseId = ?", CollectionUtils.newList(item.getExerciseId()), ExerciseItem.class);
@@ -1029,7 +1029,7 @@
//               this.doCopyExerciseItem(exerciseGroup.getGroupId(), groupId, items, 2);
//            } catch (IllegalAccessException | InstantiationException | InvocationTargetException
//                  | NoSuchMethodException e) {
//               log.error("新增练习同步到班级错误", e);
//               log.error("新增练习同步到班级错误", e);
//            }
//         }
//      }
@@ -1045,11 +1045,11 @@
   @Override
   public ResultJson insertExerciseItem4Evaluate(String groupId, ExerciseItem item,
         List<ExerciseItemOption> lstOptions,String analysis,JSONArray titleImgs) {
      // 1. 保存习题
      // 1. 保存习题
      TraceUtils.setCreateTrace(item);
      this.save(item);
      // 2、保存习题关联组
      // 2、保存习题关联组
      QExerciseGroupItemRe qRe =QExerciseGroupItemRe.exerciseGroupItemRe;
      Integer maxGroupItemOrder = 
            this.getQueryFactory().select(qRe.itemOrder.max())
@@ -1067,7 +1067,7 @@
      re.setDeleteFlag(false);
      this.save(re);
      
      // 题目组题目个数+1
      // 题目组题目个数+1
      QExerciseGroup g = QExerciseGroup.exerciseGroup;
      this.getQueryFactory()
      .update(g)
@@ -1076,7 +1076,7 @@
      .execute();
      
      
      // 3. 保存习题选项
      // 3. 保存习题选项
      for (int i = 0; i < lstOptions.size(); i++) {
         ExerciseItemOption option = lstOptions.get(i);
         option.setExerciseItemId(item.getExerciseId());
@@ -1085,7 +1085,7 @@
         TraceUtils.setCreateTrace(option);
         this.save(option);
         
         // 更新选项图片
         // 更新选项图片
         updateEvaExerOptionObjImgId(option);
         
         ExerciseItemScore objExerciseItemScore = new ExerciseItemScore();
@@ -1097,10 +1097,10 @@
         this.save(objExerciseItemScore);
      }
      
      // 更新题目图片
      // 更新题目图片
      this.updateEvaExerciseObjImgId(titleImgs,item.getExerciseId());
      // 4. 保存习题解析
      // 4. 保存习题解析
      ExerciseItemAnalisi analysisVO = new ExerciseItemAnalisi();
      analysisVO.setAnalysis(analysis);
      analysisVO.setAccuracy(BigDecimal.ZERO);
@@ -1115,7 +1115,7 @@
   }
   /**
    * 更新习题选项图片对象结果
    * 更新习题选项图片对象结果
    * 
    * @param optionId
    * @param imgIds
@@ -1139,7 +1139,7 @@
   }
   /**
    * 更新习题选项图片对象结果
    * 更新习题选项图片对象结果
    * 
    * @param optionId
    * @param imgIds
@@ -1163,13 +1163,13 @@
   }
   /**
    * 处理exerciseItem
    * 处理exerciseItem
    * 
    * @param groupId
    * @param item
    */
   private void handlerExerciseItem(ExerciseGroup group, ExerciseItem item) {
      // 如果是章节练习,将章节写到exerciseItem
      // 如果是章节练习,将章节写到exerciseItem
      if (ExerciseGroup.TYPE_CHAPTER_ITEM == group.getType()) {
         item.setChapterId(group.getAttribute2());
      }
@@ -1186,7 +1186,7 @@
   }
   /**
    * 刪除练习关联表数据
    * 刪除练习关联表数据
    * 
    * @param reIds
    * @return
@@ -1201,7 +1201,7 @@
   }
   /**
    * 删除练习题:只删除关系 (统一班级下,顺序随机 同步删除)
    * 删除练习题:只删除关系 (统一班级下,顺序随机 同步删除)
    * 
    * @param exerciceIds
    * @param reIds
@@ -1212,30 +1212,30 @@
   public Result deleteExerciseItems(String[] exerciceIds, String[] reIds, String groupId) {
      ExerciseGroup group = this.read(ExerciseGroup.class, groupId);
      // 1.更新组练习数量值 总量减去本次删除个数
      // 1.更新组练习数量值 总量减去本次删除个数
      group.setAllCount(group.getAllCount().subtract(new BigInteger(String.valueOf(exerciceIds.length))));
      TraceUtils.setUpdateTrace(group);
      this.save(group);
      // 2.删除练习组关联表数据
      // 2.删除练习组关联表数据
      deleteExerciseGroupRe(reIds);
      // 3.重新排序此组的字段
      // 3.重新排序此组的字段
      updateExerciseItemNewNo(groupId);
      
      //清除缓存
      //清除缓存
      redisTemplate.delete(groupId);
      return new Result(true);
   }
   /**
    * 重新排序
    * 重新排序
    * 
    * @param groupId
    * @return
    */
   private Result updateExerciseItemNewNo(String groupId) {
      // 升序排序
      // 升序排序
      String hql = "from ExerciseGroupItemRe re " + "where re.exerciseGroupId=? " + "and re.deleteFlag is false " + "order by re.itemOrder asc ";
      List<ExerciseGroupItemRe> lstRe = this.find(hql, CollectionUtils.newList(groupId), ExerciseGroupItemRe.class);
@@ -1244,7 +1244,7 @@
         return null;
      }
      // 重新排序
      // 重新排序
      for (int i = 0; i < lstRe.size(); i++) {
         lstRe.get(i).setItemOrder(i + 1);
      }
@@ -1255,7 +1255,7 @@
   }
   /**
    * 根据groupId 和 itemId 读取 ExerciseGroupItemRe
    * 根据groupId 和 itemId 读取 ExerciseGroupItemRe
    * 
    * @param groupId
    * @param itemId
@@ -1270,7 +1270,7 @@
    */
   /**
    * 查询最近的记录
    * 查询最近的记录
    * 
    * @param hql
    * @param page
@@ -1291,20 +1291,20 @@
         items = parseFile(file);
      } catch (Exception e) {
         log.error(e, e);
         return new Result(false, "读取文档失败");
         return new Result(false, "读取文档失败");
      }
      insertItems(groupId, items);
      // 4.20150618:配合前台app,所有修改同时修改group表最后修改时间
      // 4.20150618:配合前台app,所有修改同时修改group表最后修改时间
      List<ExerciseGroup> result = initExerciseGroup(groupId);
      updateGroupUpdateTimeByList(result);
      FileUtils.deleteQuietly(file.getParentFile());
      return new Result(true, "已导入" + items.size() + "道习题");
      return new Result(true, "已导入" + items.size() + "道习题");
   }
   /**
    * 插入习题
    * 插入习题
    * 
    * @param items
    */
@@ -1312,12 +1312,12 @@
      int i = 0;
      // 获取一个习题需要跟新的关系条数
      // 获取一个习题需要跟新的关系条数
      List<ExerciseGroup> result = initExerciseGroup(groupId);
      ExerciseGroup group = this.read(ExerciseGroup.class, groupId);
      // 得到当前组题目的最大题号
      // 得到当前组题目的最大题号
      int maxGroupItemOrder = queryExerciseGroupItemNo(groupId);
      /*String hql = " from ExerciseGroup where originExerciseId = ?  and deleteFlag is false and groupId != ?";
@@ -1327,16 +1327,16 @@
         TraceUtils.setCreateTrace(item);
         item.setDeleteFlag(false);
         // 1. 习题
         // 1. 习题
         handlerExerciseItem(group, item);
         save(item);
         // 2. 保存习题组-习题关系(练习和非练习)
         // 2. 保存习题组-习题关系(练习和非练习)
         List<ExerciseGroupItemRe> groupRes = initExerciseGroupItemRe(result, item.getExerciseId(), item.getItemNo() == null ? i++ : item.getItemNo(), ++maxGroupItemOrder );
         saveOrUpdateAll(groupRes);
         if(StringUtils.isEmpty(group.getClassId())){
            // 同步习题
            // 同步习题
            String hql = " from ExerciseGroup where originExerciseId = ?  and deleteFlag is false and groupId != ?";
            List<ExerciseGroup> lstGroup = find(hql, CollectionUtils.newList(group.getOriginExerciseId(), groupId), ExerciseGroup.class);
            List<ExerciseItem> lstItems = find("from ExerciseItem where exerciseId = ?", CollectionUtils.newList(item.getExerciseId()), ExerciseItem.class);
@@ -1348,16 +1348,16 @@
                  this.doCopyExerciseItem(exerciseGroup.getGroupId(), groupId, lstItems, 2);
               } catch (IllegalAccessException | InstantiationException | InvocationTargetException
                     | NoSuchMethodException e) {
                  log.error("新增练习同步到班级错误", e);
                  log.error("新增练习同步到班级错误", e);
               }
            }
         }
         // 3. 保存习题解析
         // 3. 保存习题解析
         if (item.getAnalisis() != null) {
            saveAnalysis(item);
         }
         // 4. 保存习题选项
         // 4. 保存习题选项
         for (ExerciseItemOption option : item.getOptions()) {
            TraceUtils.setCreateTrace(option);
            option.setDeleteFlag(false);
@@ -1369,7 +1369,7 @@
   }
   /**
    * 保存习题解析
    * 保存习题解析
    * 
    * @param item
    */
@@ -1387,12 +1387,12 @@
   }
   /**
    * 解析word
    * 解析word
    * 
    * @param groupId
    *            习题组id
    *            习题组id
    * @param file
    *            word文件绝对路径
    *            word文件绝对路径
    * @return
    * @throws RuntimeException
    */
@@ -1400,7 +1400,7 @@
      Handler handler = new Handler();
      // from office to txt,docx:自带序号无法解析出来,doc可以
      // from office to txt,docx:自带序号无法解析出来,doc可以
      String txtFilePath = transformDocToTxt(file);
@@ -1415,7 +1415,7 @@
            handler.parse(currLine);
         }
      } catch (Exception e) {
         throw new Exception("读取文档失败", e);
         throw new Exception("读取文档失败", e);
      }  finally {
         IOUtils.closeQuietly(br);
         IOUtils.closeQuietly(reader);
@@ -1426,10 +1426,10 @@
   }
   /**
    * 从office转换到txt:2007转换:自带序号格式会丢失;2003会解析出来
    * 从office转换到txt:2007转换:自带序号格式会丢失;2003会解析出来
    * 
    * @param file
    *            office文档
    *            office文档
    * @return
    */
   private String transformDocToTxt(File file) {
@@ -1443,23 +1443,23 @@
         if ("doc".equals(fileExtention)) {
            WordExtractor extractor = new WordExtractor(fis);
            // 获取Word文件中的文本+自带序号
            // 获取Word文件中的文本+自带序号
            strText = extractor.getText();
            extractor.close();
         } else if ("docx".equals(fileExtention)) {
            OPCPackage opcPackage = POIXMLDocument.openPackage(file.getAbsolutePath());
            POIXMLTextExtractor extractor = new XWPFWordExtractor(opcPackage);
            // 只能获取Word文件中的文本,不能取到office序号
            // 只能获取Word文件中的文本,不能取到office序号
            strText = extractor.getText();
            extractor.close();
         } else {
            throw new RuntimeException("文件格式错误, 请上传word文档(.doc及.docx)格式", null);
            throw new RuntimeException("文件格式错误, 请上传word文档(.doc及.docx)格式", null);
         }
         // 将得到的文本全角转半角
         // 将得到的文本全角转半角
         strText = formatFullToHalf(strText);
         // 解决空格保存为txt的时候,乱码为?
         // 解决空格保存为txt的时候,乱码为?
         byte bytes[] = { (byte) 0xC2, (byte) 0xA0 };
         String UTFSpace = new String(bytes, "UTF-8");
         strText = strText.replaceAll(UTFSpace, " ");
@@ -1471,9 +1471,9 @@
         return txtFile.getAbsolutePath();
      } catch (FileNotFoundException e) {
         throw new RuntimeException("office文档未找到", e);
         throw new RuntimeException("office文档未找到", e);
      } catch (IOException e) {
         throw new RuntimeException("office文档读取失败", e);
         throw new RuntimeException("office文档读取失败", e);
      } catch (Exception e) {
         throw new RuntimeException(e.getMessage(), e);
      } finally {
@@ -1483,7 +1483,7 @@
   }
   /**
    * 全角转半角
    * 全角转半角
    * 
    * @param oriText
    * @return
@@ -1494,23 +1494,23 @@
      }
      char[] charArray = oriText.toCharArray();
      // 对全角字符转换的char数组遍历
      // 对全角字符转换的char数组遍历
      for (int i = 0; i < charArray.length; ++i) {
         int charIntValue = (int) charArray[i];
         // 如果符合转换关系,将对应下标之间减掉偏移量65248;如果是空格的话,直接做转换
         // 如果符合转换关系,将对应下标之间减掉偏移量65248;如果是空格的话,直接做转换
         if (charIntValue >= 65281 && charIntValue <= 65374) {
            charArray[i] = (char) (charIntValue - 65248);
         } else if (charIntValue == 12288) {
            charArray[i] = (char) 32;
         } else if (charIntValue == 58033) {
            // 空格
            // 空格
            charArray[i] = (char) 32;
         } else if (charIntValue == 65380) {
            // 顿号
            // 顿号
            charArray[i] = (char) 12289;
         } else if (charIntValue == 65377) {
            // 句号
            // 句号
            charArray[i] = (char) 12290;
         }
      }
@@ -1519,7 +1519,7 @@
   }
   /**
    * 解析文件后缀
    * 解析文件后缀
    * 
    * @param filename
    * @return
@@ -1536,9 +1536,9 @@
    */
   @Override
   public Result updateExerciseItem(ExerciseItem item, List<ExerciseItemOption> lstOptions, String analysis) {
      //先删除所有的option,然后恢复已有的option
      //先删除所有的option,然后恢复已有的option
      this.bulkUpdate("update ExerciseItemOption  set deleteFlag = true where exerciseItemId=?", new String[]{item.getExerciseId()});
      // 保存Option
      // 保存Option
      String answer = "";
      if(lstOptions!=null){
         for (ExerciseItemOption option : lstOptions) {
@@ -1562,20 +1562,20 @@
      }
      
      
      // 保存item
      // 保存item
      if(StringUtils.isNotBlank(answer)){
         item.setAnswer(answer.substring(0,answer.length()-1));
      }
      TraceUtils.setCreateTrace(item);
      save(item);
      // 保存解析
      // 保存解析
      updateItemAnalysis(item, analysis);
      // 配合前台app,所有修改同时修改group表最后修改时间
      // 配合前台app,所有修改同时修改group表最后修改时间
//      updateGroupUpdateTimeByList(initUpdateExerciseGroup(item.getExerciseId()));
      
      //保存题目分数
      //保存题目分数
      List<ExerciseItemScore>  lstExerciseItemScore = item.getScores();
      if(lstExerciseItemScore!=null && lstExerciseItemScore.size()>0){
         for (ExerciseItemScore score : lstExerciseItemScore) {
@@ -1588,7 +1588,7 @@
   }
   /*
    * 评价模块修改题目
    * 评价模块修改题目
    */
   @Override
   public ResultJson updateExerciseItem4Evaluate(ExerciseItem item, 
@@ -1597,7 +1597,7 @@
      TraceUtils.setUpdateTrace(item);
      
      
/*      // 先移除全部习题
/*      // 先移除全部习题
      QExerciseItemOption qOption = QExerciseItemOption.exerciseItemOption;
      this.getQueryFactory()
      .update(qOption)
@@ -1605,7 +1605,7 @@
      .where(qOption.exerciseItemId.eq(item.getExerciseId()))
      .execute();
      
      // 移除全部分数
      // 移除全部分数
      QExerciseItemScore qScore = QExerciseItemScore.exerciseItemScore;
      this.getQueryFactory()
      .update(qScore)
@@ -1613,14 +1613,14 @@
      .where(qScore.exerciseItemId.eq(item.getExerciseId()))
      .execute();*/
      
      // 先移除全部习题
      // 先移除全部习题
      String hql = "update ExerciseItemOption set DELETE_FLAG = 1 where EXERCISE_ITEM_ID = ?";
      super.bulkUpdateInLoop(hql, new String[] { item.getExerciseId() });
      // 移除全部分数
      // 移除全部分数
      String hql2 = "update ExerciseItemScore set DELETE_FLAG = 1 where EXERCISE_ITEM_ID = ?";
      super.bulkUpdateInLoop(hql2, new String[] { item.getExerciseId() });
      
      // 1.保存item
      // 1.保存item
      this.save(item);
      if(lstOptions != null && lstOptions.size() > 0) {
         TraceUtils.setCreateTrace(lstOptions);
@@ -1644,7 +1644,7 @@
         }
      }
      
      // 4. 更新习题解析
      // 4. 更新习题解析
      QExerciseItemAnalisi analysisVO = QExerciseItemAnalisi.exerciseItemAnalisi;
      this.getQueryFactory()
      .update(analysisVO)
@@ -1657,7 +1657,7 @@
   }
   /**
    * 更新解析
    * 更新解析
    * 
    * @param item
    * @param analysis
@@ -1687,17 +1687,17 @@
   }
   /**
    * 组装ExerciseGroup的list,传入一个groupid,得到同时需要修改的一个或者多个group对象
    * 组装ExerciseGroup的list,传入一个groupid,得到同时需要修改的一个或者多个group对象
    * 
    * @param groupId
    *            主键
    *            主键
    * @return
    */
   @Override
   public List<ExerciseGroup> initExerciseGroup(String groupId) {
      // 0.获取groupID对应的type,如果是习题(顺机序、随和章节,需要按不同情况同时更新)
      // 1.如果是章节练习,需要同步修改顺序随机练习
      // 2.如果是顺序,需同步修改随机;如果是随机练习亦然
      // 0.获取groupID对应的type,如果是习题(顺机序、随和章节,需要按不同情况同时更新)
      // 1.如果是章节练习,需要同步修改顺序随机练习
      // 2.如果是顺序,需同步修改随机;如果是随机练习亦然
      ExerciseGroup group = read(ExerciseGroup.class, groupId);
      List<ExerciseGroup> result = new ArrayList<ExerciseGroup>();
      short sType = 0;
@@ -1716,14 +1716,14 @@
   }
   /**
    * 组装ExerciseGroup的list,传入一个groupid,得到同时需要修改的一个或者多个group对象
    * 组装ExerciseGroup的list,传入一个groupid,得到同时需要修改的一个或者多个group对象
    * 
    * @param groupId
    *            主键
    *            主键
    * @return
    */
   public List<ExerciseGroup> initUpdateExerciseGroup(String exerciseId) {
      // 修改关联的exerciseId,deleteflag is false(暂时全部处理)
      // 修改关联的exerciseId,deleteflag is false(暂时全部处理)
      List<ExerciseGroup> lstGroup = new ArrayList<ExerciseGroup>();
      String hql = "select e.exerciseGroupId from ExerciseGroupItemRe e where deleteFlag is false and e.exerciseItemId = ? ";
@@ -1745,25 +1745,25 @@
   }
   /**
    * 批量删除ExerciseGroup,删除逻辑:如果是练习,顺序和随机练习时同步删除的(此处代码)
    * 批量删除ExerciseGroup,删除逻辑:如果是练习,顺序和随机练习时同步删除的(此处代码)
    * 
    * @param groupId
    *            主键,多个id时以","分隔
    *            主键,多个id时以","分隔
    * @return
    */
   public Result deleteExerciseGroup(String groupId) {
      // 逻辑删除,只需要修改exercise_group、exercise_item的删除标识即可
      // 逻辑删除,只需要修改exercise_group、exercise_item的删除标识即可
      if (StringUtils.isNotBlank(groupId)) {
         // 需要删除的练习组
         // 需要删除的练习组
         Object[] arrGroupId = groupId.split(",");
         // 存储顺序练习或者随机练习
         // 存储顺序练习或者随机练习
         List<ExerciseGroup> lstResults = initDeleteExerciseGroup(arrGroupId);
         // 需要删除的练习类型下的练习题
         // 需要删除的练习类型下的练习题
         //List<ExerciseItem> lstItem = initDeleteExerciseItem(lstResults);
         // 删除习题组,修改习题组最后修改时间
         // 删除习题组,修改习题组最后修改时间
         if (lstResults != null) {
            for (ExerciseGroup group : lstResults) {
               group.setDeleteFlag(true);
@@ -1774,37 +1774,37 @@
            }
         }
         /*// 删除习题
         /*// 删除习题
         if (lstItem != null) {
            for (ExerciseItem item : lstItem) {
               item.setDeleteFlag(true);
            }
            saveOrUpdateAll(lstItem);
         }*/
         // 20150618:配合前台app,所有修改同时修改group表最后修改时间
         // 20150618:配合前台app,所有修改同时修改group表最后修改时间
         //updateGroupUpdateTimeByList(lstResults);
      }
      return new Result(true);
   }
   /**
    * 组装练习组
    * 组装练习组
    * 
    * @param name
    *            练习名称
    *            练习名称
    * @param type
    *            练习组类型
    *            练习组类型
    * @param lessonId
    *            课程
    *            课程
    * @param chapterId
    *            章节
    *            章节
    * @return
    */
   private List<ExerciseGroup> initExerciseGroupList(String name, short type, String lessonId, String chapterId, int iCount) {
      List<ExerciseGroup> lstExerciseGroup = new ArrayList<ExerciseGroup>();
      List<Short> lstType = new ArrayList<Short>();
      // iCount:0、 新增三种(选择了章节),增加两种:没有选择章节;1,新增两种(顺序随机),2,新增一种(章节),3的话,不增加
      // iCount:0、 新增三种(选择了章节),增加两种:没有选择章节;1,新增两种(顺序随机),2,新增一种(章节),3的话,不增加
      if (type == ExerciseGroup.TYPE_EXERCISE_SEQUENCE) {
         if (iCount == 0) {
            lstType.add(type);
@@ -1817,7 +1817,7 @@
            lstType.add(ExerciseGroup.TYPE_EXERCISE_RANDOM);
         } else if (iCount == 2) {
            lstType.add(ExerciseGroup.TYPE_CHAPTER_ITEM);
         } else if (iCount == 3 && StringUtils.isNotBlank(chapterId)) {// 等于3,章节练习,顺序练习,随机练习都有,增加章节练习
         } else if (iCount == 3 && StringUtils.isNotBlank(chapterId)) {// 等于3,章节练习,顺序练习,随机练习都有,增加章节练习
            lstType.add(ExerciseGroup.TYPE_CHAPTER_ITEM);
         }
      } else {
@@ -1831,20 +1831,20 @@
   }
   /**
    * 组装练习
    * 组装练习
    * 
    * @param name
    *            练习名称
    *            练习名称
    * @param type
    *            练习类型
    *            练习类型
    * @param lessonId
    *            课程
    *            课程
    * @param chapterId
    *            章节
    *            章节
    * @return
    */
   private ExerciseGroup initExerciseGroup(String name, short type, String lessonId, String chapterId) {
      // 构建实体
      // 构建实体
      ExerciseGroup objExerciseGroup = new ExerciseGroup();
      TraceUtils.setCreateTrace(objExerciseGroup);
@@ -1853,9 +1853,9 @@
      objExerciseGroup.setSubjectId(lessonId);
      objExerciseGroup.setChapterId(chapterId);
      if (ExerciseGroup.TYPE_EXERCISE_RANDOM == type) {
         objExerciseGroup.setName("随机练习");
         objExerciseGroup.setName("随机练习");
      } else if (ExerciseGroup.TYPE_EXERCISE_SEQUENCE == type) {
         objExerciseGroup.setName("顺序练习");
         objExerciseGroup.setName("顺序练习");
      } else {
         objExerciseGroup.setName(name);
      }
@@ -1864,25 +1864,25 @@
      objExerciseGroup.setClassId(ClientUtils.getClassId());
      objExerciseGroup.setOrgId(ClientUtils.getOrgId());
      objExerciseGroup.setCollegeCourseId(ClientUtils.getCourseId());
      // 章节练习需要存储
      // 章节练习需要存储
      if (type == ExerciseGroup.TYPE_CHAPTER_ITEM) {
         // 章节练习存放lessonId
         // 章节练习存放lessonId
         //objExerciseGroup.setAttribute1(lessonId);
         // 章节练习存放chapterID
         // 章节练习存放chapterID
         objExerciseGroup.setAttribute2(chapterId);
      }
      return objExerciseGroup;
   }
   /**
    * 组装关联信息
    * 组装关联信息
    * 
    * @param lstGroup
    *            练习组
    *            练习组
    * @param itemId
    *            练习题id
    *            练习题id
    * @param itemOrder
    *            练习题序号
    *            练习题序号
    * @return
    */
   private List<ExerciseGroupItemRe> initExerciseGroupItemRe(List<ExerciseGroup> lstGroup, String itemId, int docOrder,int maxGroupItemOrder) {
@@ -1904,7 +1904,7 @@
   }
   /**
    * 查询当前组的最大题号
    * 查询当前组的最大题号
    * 
    * @param groupId
    * @return
@@ -1923,14 +1923,14 @@
   }
   /**
    * 组装需要删除的练习组
    * 组装需要删除的练习组
    * 
    * @param lstResult
    *            存储非顺序 练习非随机练习
    *            存储非顺序 练习非随机练习
    * @param lstResults
    *            存储顺序练习或者随机练习
    *            存储顺序练习或者随机练习
    * @param arrGroupId
    *            groupid的数组
    *            groupid的数组
    */
   private List<ExerciseGroup> initDeleteExerciseGroup(Object[] arrGroupId) {
      List<ExerciseGroup> lstResults = new ArrayList<ExerciseGroup>();
@@ -1941,7 +1941,7 @@
      }
      hsql =  hsql.concat("? ) ");
      List<ExerciseGroup> result = find(hsql, CollectionUtils.newList(arrGroupId), ExerciseGroup.class);
      // 一个班级只有一个顺序练习和一个随机练习
      // 一个班级只有一个顺序练习和一个随机练习
      int iNumber = 0;
      for (ExerciseGroup group : result) {
         if (group.getType() == ExerciseGroup.TYPE_EXERCISE_SEQUENCE || group.getType() == ExerciseGroup.TYPE_EXERCISE_RANDOM) {
@@ -1951,7 +1951,7 @@
            lstResult.add(group);
         }
      }
      // 一个班级只选择了顺序或者只选择了随机,两个类型都需要删除
      // 一个班级只选择了顺序或者只选择了随机,两个类型都需要删除
      if (iNumber == 1) {
         hsql = "from ExerciseGroup where type in (?,?) and classId = ? and deleteFlag is false ";
         lstResults = find(hsql, CollectionUtils.newList(ExerciseGroup.TYPE_EXERCISE_SEQUENCE, ExerciseGroup.TYPE_EXERCISE_RANDOM, lstResults.get(0).getClassId()), ExerciseGroup.class);
@@ -1962,10 +1962,10 @@
   }
   /**
    * 获取需要删除的练习题(删除习题组时调用)
    * 获取需要删除的练习题(删除习题组时调用)
    * 
    * @param lstResults
    *            需要删除的练习组
    *            需要删除的练习组
    *//*
   private List<ExerciseItem> initDeleteExerciseItem(List<ExerciseGroup> lstResults) {
      String hsql = "from ExerciseItem where exerciseId in ( select exerciseItemId from ExerciseGroupItemRe " + "  where deleteFlag is false and  exerciseGroupId in ( ";
@@ -1977,14 +1977,14 @@
         arrGroupId.add(lstResults.get(i).getGroupId());
      }
      // 需要删除的练习题(为练习类型时)
      // 需要删除的练习题(为练习类型时)
      hsql = hsql.concat("? )  group by exerciseItemId having count(1) = 3 )");
      // 这个SQL特别慢
      // 这个SQL特别慢
      List<ExerciseItem> lstItem = find(hsql, arrGroupId, ExerciseItem.class);
      List<ExerciseItem> lstItems = new ArrayList<ExerciseItem>();
      // 剔除顺序,随机、章节练习
      // 剔除顺序,随机、章节练习
      List<Object> lstParams = new ArrayList<Object>();
      for (ExerciseGroup group : lstResults) {
         if (group.getType() != ExerciseGroup.TYPE_EXERCISE_SEQUENCE && group.getType() != ExerciseGroup.TYPE_CHAPTER_ITEM && group.getType() != ExerciseGroup.TYPE_EXERCISE_RANDOM) {
@@ -1999,7 +1999,7 @@
         hsql =hsql.concat( "? )  )");
         lstItems = find(hsql, lstParams, ExerciseItem.class);
      }
      // 需要删除的习题
      // 需要删除的习题
      if (lstItem != null) {
         lstItem.addAll(lstItems);
      }
@@ -2007,7 +2007,7 @@
   }*/
   /**
    * :后台 插入评估模板时调用
    * :后台 插入评估模板时调用
    * 
    * @param name
    * @param type
@@ -2023,12 +2023,12 @@
      obj.setOrgId(ClientUtils.getOrgId());
      save(obj);
      // 保存
      // 保存
      return obj;
   }
   /**
    * 查询练习列表,还需查询联系下面习题个数
    * 查询练习列表,还需查询联系下面习题个数
    * 
    * @param hql
    * @param args
@@ -2039,7 +2039,7 @@
   }
   /**
    * 所有练习修改操作需要同时修改group的updateTime
    * 所有练习修改操作需要同时修改group的updateTime
    * 
    * @param lstGroup
    */
@@ -2057,12 +2057,12 @@
   }
   /**
    * 后台:批量删除ExerciseGroup
    * 后台:批量删除ExerciseGroup
    * 
    * @param groupId
    *            主键,多个id时以","分隔
    *            主键,多个id时以","分隔
    * @param type
    *            多个type时以","分隔
    *            多个type时以","分隔
    * @return
    */
   public Result deleteExerciseGroup(String groupId, String type, String deleteType,Integer delAll, String orgIds[], String classIds[]) {
@@ -2075,13 +2075,13 @@
         return new Result(false);
      }
      if ("org".equals(deleteType)) {
         //管理员删除练习
         //管理员删除练习
         deleteOrgGroup(groupIds,delAll,orgIds,classIds);
         return new Result(true);
      }
      // 删除逻辑:练习和其他分开处理(SQL执行简单)
      // 删除练习:随机和顺序是一致的;如果只删除随机或者顺序,只删除章节,则只删除习题组;如果只删除章节:同样只删除组
      // 删除时:顺序或者随机+章节:删除组+章节对应的习题
      // 删除逻辑:练习和其他分开处理(SQL执行简单)
      // 删除练习:随机和顺序是一致的;如果只删除随机或者顺序,只删除章节,则只删除习题组;如果只删除章节:同样只删除组
      // 删除时:顺序或者随机+章节:删除组+章节对应的习题
      boolean randomFlag = false;
      boolean chapterFlag = false;
@@ -2093,7 +2093,7 @@
         chapterFlag = true;
      }
      //  拆除子方法
      //  拆除子方法
      Result  result = deleteChildExerciseGroup(groupIds, types, randomFlag, chapterFlag);
      
      if(!result.isSuccess()){
@@ -2105,7 +2105,7 @@
   }
   
   /**
    * 拆除子方法
    * 拆除子方法
    * @param groupIds
    * @param types
    * @param randomFlag
@@ -2114,15 +2114,15 @@
    */
   private Result deleteChildExerciseGroup(String[] groupIds, String[] types,
         boolean randomFlag, boolean chapterFlag) {
      // 1. 无练习
      // 1. 无练习
      if (!randomFlag && !chapterFlag) {
         return deleteExercise(groupIds, groupIds);
      }
      // 2. 有随机有章节
      // 2. 有随机有章节
      if (randomFlag && chapterFlag) {
         return deleteExerciseAll(groupIds);
      }
      // 3.1. 随机、章节只有一种,删除组:第一种情况:保证顺序随机一致;第二种:删除章节
      // 3.1. 随机、章节只有一种,删除组:第一种情况:保证顺序随机一致;第二种:删除章节
      if (randomFlag) {
         return deleteExerciseSequence(groupIds, types);
      }
@@ -2132,7 +2132,7 @@
   private void deleteOrgGroup(String groupIds[],Integer delAll, String orgIds[], String classIds[]){
      for (String string : groupIds) {
         if ((orgIds != null && orgIds.length != 0)  || (classIds != null && classIds.length != 0)) {
            //删除要回撤的练习
            //删除要回撤的练习
            deleteAppoint(string,orgIds,classIds);
         }else{
            String hql = " from ExerciseReCourse where groupId = ? and deleteFlag is false and orgId = ?";
@@ -2151,7 +2151,7 @@
               this.saveExerciseGroup(group);
            }*/
            if(delAll==1){
               //删除下级
               //删除下级
               deleteSub(string,ClientUtils.getOrgId());
            }
         }
@@ -2162,7 +2162,7 @@
   
   @SuppressWarnings("unchecked")
   private void deleteSub(String groupId,String currOrgId){
      // 机构层级视频是没有重新new ,查询出机构下级ID再删关联表
      // 机构层级视频是没有重新new ,查询出机构下级ID再删关联表
            String sql = " select oa.organization_id from organization as oa,organization ob " +
                  " where " +
                  " ob.ORGANIZATION_ID = ? " +
@@ -2184,7 +2184,7 @@
            this.save(groupCourse);
         }
         
         // 班主任层面视频指定过后都是new 出来的,通过originVideoId 可以查出所有指定过去的视频
         // 班主任层面视频指定过后都是new 出来的,通过originVideoId 可以查出所有指定过去的视频
         hql = "select classId from ClsClass where orgId in (:orgIds) and deleteFlag is false";
         map = new HashMap<String, Object>();
         map.put("orgIds", orgIds.toArray());
@@ -2205,7 +2205,7 @@
   
   private Result deleteAppoint(String groupId,String orgIds[],String classIds[]){
      Map<String, Object> args = new HashMap<String, Object>();
      // 删除需要回撤的机构视频
      // 删除需要回撤的机构视频
      if (orgIds.length != 0) {
         
         String hql = " from ExerciseReCourse where groupId = :groupId and deleteFlag is false and orgId in (:orgIds) and orgId != :currOrgId";
@@ -2223,7 +2223,7 @@
         }
      }
      // 删除需要回撤的班主任视频
      // 删除需要回撤的班主任视频
      if (classIds.length != 0) {
         args = new HashMap<String, Object>();
         args.put("groupId", groupId);
@@ -2242,7 +2242,7 @@
   }
   /**
    * 有顺序和章节练习时的删除逻辑
    * 有顺序和章节练习时的删除逻辑
    * 
    * @param groupIds
    * @param types
@@ -2251,14 +2251,14 @@
   private Result deleteExerciseAll(String[] groupIds) {
      String hql = "select groupId from ExerciseGroup where deleteFlag is false and classId = ? and type in (?,?) ";
      List<String> exeGroupId = find(hql, CollectionUtils.newList(ClientUtils.getClassId(), ExerciseGroup.TYPE_EXERCISE_RANDOM, ExerciseGroup.TYPE_EXERCISE_SEQUENCE), String.class);
      // 组
      // 组
      exeGroupId.addAll(Arrays.asList(groupIds));
      return deleteExercise((String[]) exeGroupId.toArray(new String[exeGroupId.size()]), groupIds);
   }
   /**
    * 只有順序或者随机时删除逻辑
    * 只有順序或者随机时删除逻辑
    * 
    * @param groupIds
    * @param types
@@ -2267,10 +2267,10 @@
   private Result deleteExerciseSequence(String[] groupIds, String[] types) {
      String hql = "select groupId from ExerciseGroup where deleteFlag is false and classId = ? and type in (?,?) ";
      List<String> exeGroupId = find(hql, CollectionUtils.newList(ClientUtils.getClassId(), ExerciseGroup.TYPE_EXERCISE_RANDOM, ExerciseGroup.TYPE_EXERCISE_SEQUENCE), String.class);
      // 1.组
      // 1.组
      exeGroupId.addAll(Arrays.asList(groupIds));
      // 2.删除题,不处理练习
      // 2.删除题,不处理练习
      for (int i = 0; i < types.length; i++) {
         if (types[i] == String.valueOf(ExerciseGroup.TYPE_EXERCISE_RANDOM) || types[i] == String.valueOf(ExerciseGroup.TYPE_EXERCISE_SEQUENCE)) {
            groupIds[i] = "";
@@ -2280,15 +2280,15 @@
   }
   /**
    * 只有章节练习是的删除逻辑
    * 只有章节练习是的删除逻辑
    * 
    * @param groupIds
    * @param types
    * @return
    */
   private Result deleteExerciseChapter(String[] groupIds, String[] types) {
      // 1.组 groupIds
      // 2.删除题,不处理练习
      // 1.组 groupIds
      // 2.删除题,不处理练习
      String[] groupItemIds = new String[groupIds.length];
      for (int i = 0; i < types.length; i++) {
         if (types[i] == String.valueOf(ExerciseGroup.TYPE_CHAPTER_ITEM)) {
@@ -2301,21 +2301,21 @@
   }
   /**
    * 后台:执行删除习题组操作
    * 后台:执行删除习题组操作
    * 
    * @param groupIds
    *            删除组的组id
    *            删除组的组id
    * @param groupItemIds
    *            需要删除题的组id
    *            需要删除题的组id
    * @return
    */
   private Result deleteExercise(String[] groupIds, String[] groupItemIds) {
      // 1.删除组
      // 1.删除组
      bulkUpdateInLoop("update ExerciseGroup set deleteFlag = true where groupId = ? ", groupIds);
      // 1.删除课件
      // 1.删除课件
      bulkUpdateInLoop("update SchCourseware set deleteFlag = true where id = ? ", groupIds);
      
      // 2.删除题
      // 2.删除题
      bulkUpdateInLoop("update ExerciseGroupItemRe set deleteFlag = true "
            + " where exerciseGroupId = ? and deleteFlag = false ", groupItemIds);
      
@@ -2323,7 +2323,7 @@
   }
   /**
    * 发送练习系统通知
    * 发送练习系统通知
    * 
    * @param notice
    * @return
@@ -2346,7 +2346,7 @@
    */
   /**
    * 添加练习图片
    * 添加练习图片
    * 
    * @param imgPath
    * @param imgObjId
@@ -2356,7 +2356,7 @@
   public List<Map<String, Object>> doAddExerciseObjImg(String[] imgPath, String imgObjId, int imgObjType) {
      String hql = "from ExerciseObjectImg where deleteFlag is false and exerciseObjectId=? and objectType=? order by imgOrder desc";
      // 查询此练习是否已经存在记录
      // 查询此练习是否已经存在记录
      List<ExerciseObjectImg> lstObjImg = this.find(hql, CollectionUtils.newList(imgObjId, imgObjType), ExerciseObjectImg.class);
      int imgOrder = 1;
@@ -2394,7 +2394,7 @@
   }
   /**
    * 删除图片
    * 删除图片
    */
   public Result dodelExerciseObjImg(String imgId) {
@@ -2407,10 +2407,10 @@
   }
   /**
    * 导入习题:深度解析word文档
    * 导入习题:深度解析word文档
    * 
    * @param groupId
    *            习题组Id
    *            习题组Id
    * @param file
    * @param uuid
    * @return
@@ -2422,12 +2422,12 @@
   }
   /**
    * 新增深度解析记录
    * 新增深度解析记录
    * 
    * @param destPath
    *            文件路径
    *            文件路径
    * @param groupId
    *            习题组ID
    *            习题组ID
    * @return
    */
   private Result insertDeepAnalysis(String destPath, String groupId) {
@@ -2461,16 +2461,16 @@
   }
   /**
    * 导入习题,将解析结果返回到前台
    * 导入习题,将解析结果返回到前台
    * 
    * @param groupId
    *            习题组ID
    *            习题组ID
    * @param file
    * @return
    */
   public ExerciseParseResult doParseItems(String groupId, String fullPath , String module ) {
      
      //取得当前上传文件类型
      //取得当前上传文件类型
      String filePart[] = fullPath.split("\\.");
      String fileType = filePart[filePart.length -1];
      String uuid =  UUIDUtils.generateUUID();
@@ -2483,13 +2483,13 @@
         objResult = parseWordFile(file);
      } catch (Exception e) {
         log.error(e, e);
         if ("文件格式错误, 请上传word文档(.doc及.docx)格式".equals(e.getMessage())) {
         if ("文件格式错误, 请上传word文档(.doc及.docx)格式".equals(e.getMessage())) {
            return new ExerciseParseResult(false, e.getMessage());
         }
         return new ExerciseParseResult(false, "读取文档失败");
         return new ExerciseParseResult(false, "读取文档失败");
      }
      
      //更新上传文件使用轨迹
      //更新上传文件使用轨迹
      fileUploadService.updateUploadTrace(fullPath, module, SysFileUploadTrace.FILE_USE, groupId);
      
      objResult.setItemCount(objResult.getLstItems().size());
@@ -2504,12 +2504,12 @@
   }
   /**
    * 解析word
    * 解析word
    * 
    * @param groupId
    *            习题组id
    *            习题组id
    * @param file
    *            word文件绝对路径
    *            word文件绝对路径
    * @return
    * @throws RuntimeException
    */
@@ -2521,7 +2521,7 @@
      Handler handler = new Handler();
      // from office to txt,docx:自带序号无法解析出来,doc可以
      // from office to txt,docx:自带序号无法解析出来,doc可以
      String txtFilePath = transformDocToTxt(file);
      FileReader reader = null;
@@ -2548,7 +2548,7 @@
         }
      } catch (Exception e) {
         throw new Exception("读取文档失败", e);
         throw new Exception("读取文档失败", e);
      } finally {
         IOUtils.closeQuietly(br);
         IOUtils.closeQuietly(reader);
@@ -2563,10 +2563,10 @@
   }
   /**
    * 导入习题 校验习题,将解析结果返回到前台
    * 导入习题 校验习题,将解析结果返回到前台
    * 
    * @param content
    *            习题文本内容
    *            习题文本内容
    * @return
    */
   public ExerciseParseResult validateExercise(String content) {
@@ -2579,10 +2579,10 @@
   }
   /**
    * 导入习题:将传回的文本内容解析出来
    * 导入习题:将传回的文本内容解析出来
    * 
    * @param content
    *            习题文本内容
    *            习题文本内容
    * @return
    */
   private ExerciseParseResult parsePlainText(String content) {
@@ -2622,12 +2622,12 @@
   }
   /**
    * 导入习题模块 :导入习题,将解析结果返回到前台
    * 导入习题模块 :导入习题,将解析结果返回到前台
    * 
    * @param content
    *            文本内容
    *            文本内容
    * @param groupId
    *            习题组ID
    *            习题组ID
    * @return
    */
//   public ExerciseParseResult doImportExercise(String content, String groupId) {
@@ -2642,11 +2642,11 @@
//
//      insertItems(groupId, lstItems);
//
//      // 修改习题组最后修改时间
//      // 修改习题组最后修改时间
//      List<ExerciseGroup> result = initExerciseGroup(groupId);
//      updateGroupUpdateTimeByList(result);
//
//      // 减少返回数据
//      // 减少返回数据
//      parseResult.setLstItems(null);
//      ONSMsg msg = new ONSMsg(onsProducer.getTopic());
//      msg.put("msgType", "SYS_EXER_SAVE"); 
@@ -2662,24 +2662,24 @@
//   }
   /**
    * 拷贝练习题
    * 拷贝练习题
    * 
    * @param newGroupId
    * @param oldGroupId
    */
   public void doCopyExerciseItem(String newGroupId, String oldGroupId) {
      //改用存储过程
      //改用存储过程
      Session session = getCommonDAO().getSessionFactory().getCurrentSession();
      SQLQuery query = session.createSQLQuery("{call copy_exercise_item(?,?)}");
      query.setString(0, newGroupId);
      query.setString(1, oldGroupId);
      
      //执行
      //执行
      query.executeUpdate();
   }
   
   /**
    * 复制历史练习
    * 复制历史练习
    * 
    * @param fromClassId
    * @return
@@ -2702,7 +2702,7 @@
   }
   /**
    * 复制习题
    * 复制习题
    * 
    * @param sourceGroup
    * @param sequenceGroup
@@ -2715,13 +2715,13 @@
      ExerciseGroup targetGroup = new ExerciseGroup();
      // 主表:组
      // 主表:组
      doSaveCopyGroup(sourceGroup, targetGroup, subjectId, subjectName, chapterId);
      // 关联表: 组   习题
      // 关联表: 组   习题
      doSaveCopyRe(sourceGroup, targetGroup);
      
      // 扩展表: extend
      // 扩展表: extend
      doSaveCopyExtend(sourceGroup,targetGroup);
      return new Result(true);
@@ -2760,7 +2760,7 @@
   }
   /**
    * 复制习题时,保存习题组
    * 复制习题时,保存习题组
    * 
    * @param sourceGroup
    * @param targetGroup
@@ -2788,7 +2788,7 @@
   }
   /**
    * 复制练习时 保存习题关联
    * 复制练习时 保存习题关联
    * 
    * @param sourceGroup
    * @param targetGroup
@@ -2818,7 +2818,7 @@
   }
   /**
    * 学员得分详情列表
    * 学员得分详情列表
    * 
    * @param groupId
    * @return
@@ -2858,7 +2858,7 @@
         recordMap.put(String.valueOf(obj[2]) , obj);
      }
      
      // 组装为Map
      // 组装为Map
      List<Map<String, Object>> lstMap = new ArrayList<Map<String, Object>>(userRegLst.size());
      Map<String, Object> map = null;
@@ -2899,7 +2899,7 @@
   }
   /**
    * 初始化平均成绩和最高成绩
    * 初始化平均成绩和最高成绩
    * 
    * @param groupId
    * @return
@@ -2934,12 +2934,12 @@
      BigDecimal score = BigDecimal.ZERO;
      // 计算已做学员总分数
      // 计算已做学员总分数
      for (BigDecimal obj : reLst) {
         score = score.add(obj);
      }
      // 计算班级平均成绩
      // 计算班级平均成绩
      Double scoreNew = Double.valueOf(String.valueOf(score)) / userRegLst.size();
      DecimalFormat df = new DecimalFormat("0.00");
@@ -2950,7 +2950,7 @@
   }
   /**
    * 题目得分详情
    * 题目得分详情
    * 
    * @param groupId
    * @return
@@ -2965,28 +2965,28 @@
         return new ArrayList<ExerciseItemStatistics>();
      }
      // 获取组
      // 获取组
      ExerciseGroup group = read(ExerciseGroup.class, groupId);
      if (null == group) {
         return new ArrayList<ExerciseItemStatistics>();
      }
      // 默认章节练习
      // 默认章节练习
      String hql = "select item from ExerciseItem item,ExerciseGroupItemRe re " + "where re.exerciseGroupId=? " + "and re.exerciseItemId=item.exerciseId " + "and item.deleteFlag is false " + "and re.deleteFlag is false " + "order by re.itemOrder ";
      // 随机练习,顺序练习
      // 随机练习,顺序练习
      if (ExerciseGroup.TYPE_EXERCISE_RANDOM == group.getType() || ExerciseGroup.TYPE_EXERCISE_SEQUENCE == group.getType()) {
         hql = "select item from ExerciseItem item,ExerciseGroupItemRe re " + "where re.exerciseGroupId=? and " + "re.exerciseItemId=item.exerciseId " + "and item.deleteFlag is false " + "and re.deleteFlag is false " + "order by item.chapterId, re.itemOrder ";
      }
      // 查询当前组的所有题目
      // 查询当前组的所有题目
      List<ExerciseItem> itemAllLst = this.exerDAO.find(hql, CollectionUtils.newList(groupId), ExerciseItem.class);
      if (itemAllLst.isEmpty()) {
         return new ArrayList<ExerciseItemStatistics>();
      }
      // 同步编号
      // 同步编号
      List<ExerciseItemStatistics> exeItemStatisLst = new ArrayList<ExerciseItemStatistics>(itemStatisLst.size());
      ExerciseItemStatistics obj = null;
      for (int j = 0; j < itemAllLst.size(); j++) {
@@ -2999,7 +2999,7 @@
               obj.setClassAccuracyShow(obj.getClassAccuracy() + "%");
               obj.setOrgAccuracyShow(obj.getOrgAccuracy() + "%");
               // 给类型赋值
               // 给类型赋值
               setExerItemTypeNewName(obj);
               exeItemStatisLst.add(obj);
@@ -3012,20 +3012,20 @@
   }
   private void setExerItemTypeNewName(ExerciseItemStatistics obj) {
      // 判断类型文字显示
      // 判断类型文字显示
      if (obj.getExerciseItemType() == ExerciseItem.TYPE_SINGLE_SELECT) {
         obj.setItemTypeName("单选题");
         obj.setItemTypeName("单选题");
      } else if (obj.getExerciseItemType() == ExerciseItem.TYPE_MULTI_SELECT) {
         obj.setItemTypeName("多选题");
         obj.setItemTypeName("多选题");
      } else if (obj.getExerciseItemType() == ExerciseItem.TYPE_TRUE_OR_FALSE) {
         obj.setItemTypeName("判断题");
         obj.setItemTypeName("判断题");
      } else if (obj.getExerciseItemType() == ExerciseItem.TYPE_ESSAY_QUESTION) {
         obj.setItemTypeName("问答题");
         obj.setItemTypeName("问答题");
      }
   }
   /**
    * 加载题目选项详情 - 班级、机构
    * 加载题目选项详情 - 班级、机构
    * 
    * @param groupId
    * @return
@@ -3055,23 +3055,23 @@
         map.put("exerciseItemTitel", item.getTitle());
         map.put("correctAnswer", item.getAnswer());
         if (optionStatis.getOptionOrder().equals("True")) {// 为True - 正确
            map.put("optionOrder", "正确");
         } else if (optionStatis.getOptionOrder().equals("False")) {// 为False - 错误
            map.put("optionOrder", "错误");
         if (optionStatis.getOptionOrder().equals("True")) {// 为True - 正确
            map.put("optionOrder", "正确");
         } else if (optionStatis.getOptionOrder().equals("False")) {// 为False - 错误
            map.put("optionOrder", "错误");
         } else {
            map.put("optionOrder", optionStatis.getOptionOrder());
         }
         // 判断题目的类型
         // 判断题目的类型
         if ((short) item.getType() == ExerciseItem.TYPE_SINGLE_SELECT) {
            map.put("exerciseItemType", "单选题");
            map.put("exerciseItemType", "单选题");
         } else if ((short) item.getType() == ExerciseItem.TYPE_MULTI_SELECT) {
            map.put("exerciseItemType", "多选题");
            map.put("exerciseItemType", "多选题");
         } else if ((short) item.getType() == ExerciseItem.TYPE_TRUE_OR_FALSE) {
            map.put("exerciseItemType", "判断题");
            map.put("exerciseItemType", "判断题");
         } else if ((short) item.getType() == ExerciseItem.TYPE_ESSAY_QUESTION) {
            map.put("exerciseItemType", "问答题");
            map.put("exerciseItemType", "问答题");
         }
         lstResult.add(map);
@@ -3080,7 +3080,7 @@
   }
   /**
    * 编辑练习保存
    * 编辑练习保存
    */
   @Override
   public Result doSaveEditGroup(String groupId,String groupName) {
@@ -3095,14 +3095,14 @@
   }
   
   /**
    * 排序
    * 排序
    * 
    * @param ids 排序id
    * @param index 序号
    * @param ids 排序id
    * @param index 序号
    * @return
    */
   public Result doOrder(List<String> ids,  List<Integer> index){
      // 循环修改order
      // 循环修改order
      CommonDAO commonDAO = this.getCommonDAO();
      for( int i=0;i< ids.size();i++){
         String id = ids.get(i);
@@ -3113,14 +3113,14 @@
   }
   
   /**
    * 排序
    * 排序
    * 
    * @param ids 排序id
    * @param index 序号
    * @param ids 排序id
    * @param index 序号
    * @return
    */
   public Result doitemOrder(List<String> ids,  List<Integer> index,String groupId){
      // 循环修改order
      // 循环修改order
      CommonDAO commonDAO = this.getCommonDAO();
      for( int i=0;i< ids.size();i++){
         String id = ids.get(i);
@@ -3130,7 +3130,7 @@
   }
   
   /**
    * 保存练习接口
    * 保存练习接口
    * 
    * @param group
    * @return
@@ -3143,7 +3143,7 @@
      
      Map<String, Integer> order = courseWareService.getOrder(!isClass, group.getSubjectId(), group.getChapterId());
      
      //同步排序
      //同步排序
      int subjectOrder = order.get("subjectOrder");
      int chapterOrder = order.get("chapterOrder");
      int partOrder = order.get("partOrder");
@@ -3217,8 +3217,8 @@
   }
   
   /**
    * (后台管理系统)
    *  管理员同步习题到班级
    * (后台管理系统)
    *  管理员同步习题到班级
    * 
    * @param exerciseItemId
    * @return
@@ -3227,11 +3227,11 @@
    */
   public Result doSynExercise(String[] exerciseItemIds) throws IllegalAccessException, InvocationTargetException{
      if(exerciseItemIds == null || exerciseItemIds.length == 0){
         return new Result(false, "参数错误");
         return new Result(false, "参数错误");
      }
      List<Object> lstSaveObject = new ArrayList<>();
      for(String exerciseItemId : exerciseItemIds){
         //待同步的练习
         //待同步的练习
         ExerciseItem sourceItem = this.read(ExerciseItem.class, exerciseItemId);
         if(sourceItem == null){
            continue;
@@ -3242,29 +3242,29 @@
         List<ExerciseObjectImg> lstSourceImg = this.find("from ExerciseObjectImg where exerciseObjectId = ? and deleteFlag is false and objectType = ?",
               CollectionUtils.newList(exerciseItemId, ExerciseObjectImg.OBJECT_TYPE_ITEM), ExerciseObjectImg.class);
         
         //下发的练习
         //下发的练习
         List<ExerciseItem> lstExerciseItem = this.find("from ExerciseItem where deleteFlag is false and orgiExerciseId = ?",
               CollectionUtils.newList(exerciseItemId), ExerciseItem.class);
         if(lstExerciseItem == null || lstExerciseItem.size() == 0){
            continue;
         }
         //同步题目
         //同步题目
         for(ExerciseItem exerciseItem :lstExerciseItem){
            exerciseItem.setTitle(sourceItem.getTitle());
            exerciseItem.setAnswer(sourceItem.getAnswer());
            TraceUtils.setUpdateTrace(exerciseItem);
            
            //同步更新练习组的时间
            //同步更新练习组的时间
            this.bulkUpdate("update ExerciseGroup p set p.updateTime = sysdate() where EXISTS "+
                  " (select 1 from ExerciseGroupItemRe i where i.exerciseItemId = ? and i.deleteFlag is false and i.exerciseGroupId = p.groupId)", new Object[]{exerciseItem.getExerciseId()});
            
            List<ExerciseItemAnalisi> lstExerciseItemAnalisi = exerciseItem.getAnalysises();
            List<ExerciseObjectImg> lstExerciseObjectImg = this.find("from ExerciseObjectImg where exerciseObjectId = ? and deleteFlag is false and objectType = ?",
                  CollectionUtils.newList(exerciseItem.getExerciseId(), ExerciseObjectImg.OBJECT_TYPE_ITEM), ExerciseObjectImg.class);
            //同步选项
            //同步选项
            if(lstSourceOption != null && lstSourceOption.size() > 0){
               ExerciseItemOption option;
               //删除选项的题目
               //删除选项的题目
               this.bulkUpdate("update ExerciseItemOption p set p.deleteFlag = true where  exerciseItemId = ?", new Object[]{exerciseItem.getExerciseId()});
               for(ExerciseItemOption sourceOption : lstSourceOption){
                  ExerciseObjectImg objExerciseObjectImg;
@@ -3281,7 +3281,7 @@
                     
                     TraceUtils.setCreateTrace(option);
                     
                     if(objSourceImg != null){//选项图片
                     if(objSourceImg != null){//选项图片
                        objExerciseObjectImg = new ExerciseObjectImg();
                        BeanUtils.copyProperties(objExerciseObjectImg, objSourceImg);
                        objExerciseObjectImg.setExerciseObjectId(option.getOptionId());
@@ -3320,7 +3320,7 @@
                  lstSaveObject.add(option);
               }
            }
            //同步解析
            //同步解析
            if(lstSourceAnalisi != null && lstSourceAnalisi.size() > 0){
               ExerciseItemAnalisi objExerciseItemAnalisi;
               if(lstExerciseItemAnalisi == null || lstExerciseItemAnalisi.size() == 0){
@@ -3337,7 +3337,7 @@
               }
               lstSaveObject.add(objExerciseItemAnalisi);
            }
            //同步题目图片
            //同步题目图片
            if(lstSourceImg != null && lstSourceImg.size() > 0){
               ExerciseObjectImg objExerciseObjectImg;
               if(lstExerciseObjectImg == null || lstExerciseObjectImg.size() == 0){
@@ -3363,7 +3363,7 @@
   }
   
   /**
    * 数据同步接口,同步下发到班级的数据
    * 数据同步接口,同步下发到班级的数据
    * 
    * @param orgId
    * @param groupId
@@ -3383,11 +3383,11 @@
      }else if(StringUtils.isNotBlank(groupId)){
         lstGroup = this.find("from ExerciseGroup g where g.groupId = ?", CollectionUtils.newList(groupId), ExerciseGroup.class);
      }else{
         return new Result(false, "参数错误");
         return new Result(false, "参数错误");
      }
      
      if(lstGroup == null || lstGroup.size() == 0){
         return new Result(false, "数据为空");
         return new Result(false, "数据为空");
      }
      
      for(ExerciseGroup group : lstGroup){
@@ -3414,14 +3414,14 @@
            
         }
      }
      return new Result(true, "成功");
      return new Result(true, "成功");
   }
   
   @SuppressWarnings("unchecked")
   @Override
   public Result saveExerciseItemBatch(String groupId,List<ExerciseItem> items) {
      if (items == null || items.size() == 0) {
         return new Result(false, "没有要保存或更新的题目数据!");
         return new Result(false, "没有要保存或更新的题目数据!");
      }
   
      ExerciseGroup group = this.read(ExerciseGroup.class, groupId);
@@ -3442,19 +3442,19 @@
      
      this.save(group);
      redisTemplate.delete(groupId);
      return new Result(true, "成功",lstExerciseItemIds.toArray());
      return new Result(true, "成功",lstExerciseItemIds.toArray());
   }
   
   /**
    * 问卷评估  复制练习
    * 问卷评估  复制练习
    * @param groupId
    * @return
    */
   @Override
   public String doCopyExerciseByEvaluate(String groupId) {
      
      // 1、复制练习组
      // 1、复制练习组
      ExerciseGroup group = this.read(ExerciseGroup.class, groupId);
      ExerciseGroup newGroup = new ExerciseGroup();
      try {
@@ -3462,31 +3462,31 @@
         newGroup.setGroupId(null);
         newGroup.setRecords(null);
      } catch (Exception e) {
         log.error("问卷复制:复制练习BeanUtils.copyProperties()方法copy失败", e);
         log.error("问卷复制:复制练习BeanUtils.copyProperties()方法copy失败", e);
      } 
      TraceUtils.setCreateTrace(newGroup);
      this.save(newGroup);
      
      // 2、复制题目
      // 2、复制题目
      this.doCopyEvaExerciseItem(newGroup.getGroupId(), groupId);
      
      return newGroup.getGroupId();
   }
   
   /**
    * 拷贝练习题
    * 拷贝练习题
    * 
    * @param newGroupId
    * @param oldGroupId
    */
   public void doCopyEvaExerciseItem(String newGroupId, String oldGroupId) {
      //改用存储过程
      //执行
      //改用存储过程
      //执行
      this.executeProduce("{call copy_exercise_item(?,?)}", new Object[]{newGroupId, oldGroupId});
   }
   /**
    * 查询问卷用户练习详情
    * 查询问卷用户练习详情
    * @param recordId
    * @param evaluateId
    * @return
@@ -3497,7 +3497,7 @@
      
      QExerciseItem item = QExerciseItem.exerciseItem;
      QExerciseGroupItemRe re = QExerciseGroupItemRe.exerciseGroupItemRe;
      // 查询题目list
      // 查询题目list
      List<ExerciseItem> itemLst = this.getQueryFactory().select(item).from(item,re)
            .where(item.exerciseId.eq(re.exerciseItemId)
                  .and(item.deleteFlag.eq(false))
@@ -3510,7 +3510,7 @@
      SchEvaluate objSchEvaluate = this.read(SchEvaluate.class, evaluateId);
      List<ExerciseObjectImg> lstExerciseObjectImg = null;
      for (ExerciseItem objExerciseItem : itemLst) {
         if(objExerciseItem.getType() == ExerciseItem.TYPE_ATTACHMENT){//附件题读取题目的图片信息
         if(objExerciseItem.getType() == ExerciseItem.TYPE_ATTACHMENT){//附件题读取题目的图片信息
            
            lstExerciseObjectImg = this.getQueryFactory().selectFrom(objImg)
                  .where(objImg.exerciseObjectId.in(
@@ -3523,7 +3523,7 @@
            
         }
         
         //查询用户答题
         //查询用户答题
         List<ExerciseItemAnswerU> lstExerciseItemAnswerU = this.getQueryFactory().selectFrom(answerU)
               .where(answerU.deleteFlag.eq(false)
                  .and(answerU.exerciseRecordId.eq(objExerciseRecord.getRecordId()))
@@ -3533,14 +3533,14 @@
         objExerciseItem.setExerciseItemAnswerU(lstExerciseItemAnswerU);
      }
      
      //拼装前端所需要的数据
      //拼装前端所需要的数据
      Map<String, Object> resultMap =  ExerciseUtils.packageUserExerciseDetail(itemLst, objSchEvaluate, lstExerciseObjectImg);
      
      return new ResultJson(true,"success",resultMap);
   }
   
   /**
    * 删除问卷图片
    * 删除问卷图片
    */
   @Override
   public ResultJson dodelEvaExerciseObjImg(String imgObjId) {
@@ -3550,15 +3550,15 @@
      
      this.save(img);
      return new ResultJson(true,"操作成功");
      return new ResultJson(true,"操作成功");
   }
   /**
    * 新增问卷图片
    * 新增问卷图片
    */
   @Override
   public List<Map<String, Object>> doAddEvaExerciseObjImg(String[] imgPath, String imgObjId, int imgObjType) {
      // 查询此练习是否已经存在记录
      // 查询此练习是否已经存在记录
      QExerciseObjectImg objImg = QExerciseObjectImg.exerciseObjectImg;
      List<ExerciseObjectImg> lstObjImg = this.getQueryFactory()
            .selectFrom(objImg)
@@ -3603,11 +3603,11 @@
   }
   /**
    * 查询问卷图片
    * 查询问卷图片
    */
   @Override
   public List<Map<String, Object>> queryEvaExerciseObjImg(String imgObjId, int imgObjType) {
      // 查询此练习是否已经存在记录
      // 查询此练习是否已经存在记录
      QExerciseObjectImg objImg = QExerciseObjectImg.exerciseObjectImg;
      List<ExerciseObjectImg> lstObjImg = this.getQueryFactory()
            .selectFrom(objImg)
@@ -3632,7 +3632,7 @@
   }
   
   /**
    * 更新习题选项图片对象结果
    * 更新习题选项图片对象结果
    * 
    * @param optionId
    * @param imgIds
@@ -3658,7 +3658,7 @@
   }
   
   /**
    * 更新习题选项图片对象结果
    * 更新习题选项图片对象结果
    * 
    * @param optionId
    * @param imgIds