public static MessageDataItem fromJson(JSONObject json) {
    MessageDataItem item = new MessageDataItem();
    item.setSenderId(json.getString("sendId"));
    String[] ct = json.getString("content").split("private");
    item.setContent(ct[0]);
    item.setTitle(ct[1]);
    item.setSendTime(json.getString("sendTime"));
    item.setSendReceiveFlag(json.getBoolean("sendReceiveFlag"));
    item.setReadFlag(json.getBoolean("readFlag"));
    // item.setImage
    item.setReceiveDeleteFlag(json.getBoolean("receiveDeleteFlag"));
    item.setId(json.getString("tid"));
    item.setMessageType(json.getIntValue("messageType"));
    item.setSendDeleteFlag(json.getBoolean("sendDeleteFlag"));

    return item;
  }
  /**
   * 撤回操作:优先取awt.optUserPrev=currUserId, 如果存在: //简单事物,上一步就是该用户做的操作 判断awt.taskIdPrev是否为null:
   * 为null表示已经撤回过,无法再执行撤回操作<END>; 不为null,判断awt.taskIdPrev是否与awt.currTaskId相同, 同:表示要撤回的是forward操作
   * 不同:撤回操作将跨事物节点:新建awt(设置taskIdPrev=null),更新inst.optdUsersPrev:剔除currUserId(防止再转交后的再撤回) 如果不存在:
   * 查看wf_inst.optdUsersPrev是否包含currUserId: 如果没有:直接抛异常,无法撤回<END>; 如果有:判断prevTask是否可撤回: 不可->抛异常<END>;
   * 可->撤回:新建awt(设置taskIdPrev=null), 更新inst.optdUsersPrev:剔除currUserId &
   * 更新prevTaskId,删除currTaskId的awt<END>;
   *
   * @param instId
   * @param currUserId
   * @return
   * @throws Exception
   */
  private boolean renewRecall(WfInstance inst, WfTask nextTask, String currUserId)
      throws BusinessException {
    String instId = inst.getInstId();
    synchronized (instId + "_rc") {
      WfAwt awtParm = new WfAwt();
      awtParm.setInstId(instId);
      awtParm.setOptUsersPre(currUserId);
      WfAwt awt = this.selectOne(awtParm);
      if (awt != null) {
        String prevTaskId = awt.getTaskIdPre();
        if (prevTaskId == null) {
          log.error(
              "renewRecall(): prefTaskId is null for instId="
                  + instId
                  + ", optUsersPre="
                  + currUserId
                  + ", recall is not allowed");
          throw new BusinessException("RECALL-ERROR", "Recall is not allowed");
        }
        if (awt.getTaskIdCurr().equals(awt.getTaskIdPre())) {
          awt.setAssignerId(currUserId);
          awt.setTaskIdPre(null);
          awt.setOptUsersPre(currUserId);
          this.updateById(awt);
        } else {
          awtParm.setOptUsersPre(null);
          this.deleteSelective(awtParm);

          awt.setWfAwtId(null); // 新建一条awt
          awt.setTaskIdCurr(inst.getTaskIdPre());
          awt.setAssignerId(currUserId);
          awt.setOptUsersPre(currUserId);
          awt.setTaskIdPre(null);
          Date beginDate = new Date();
          awt.setAwtBegin(beginDate);
          awt.setAwtEnd(
              calculateDate(beginDate, nextTask.getTimeLimitTp(), nextTask.getTimeLimit()));
          awt.setAwtAlarm(
              nextTask.getAlarmTime() == null
                  ? null
                  : calculateDate(beginDate, nextTask.getAlarmTimeTp(), nextTask.getAlarmTime()));
          this.insert(awt);
          removeUserFromOptUserPrev(inst, currUserId, inst.getTaskIdPre(), true);
        }
      } else {
        String optdUserPre = inst.getOptUsersPre();
        if (optdUserPre == null || !optdUserPre.contains(currUserId)) {
          log.error(
              "renewRecall(): optUsersPre="
                  + optdUserPre
                  + ", not contains currUserId="
                  + currUserId
                  + ", recall is not allowed");
          throw new BusinessException("RECALL-ERROR", "Recall is not allowed");
        }
        String prevTaskId = inst.getTaskIdPre();
        String currTaskId = inst.getTaskIdCurr();
        if (StringUtils.isEmpty(prevTaskId)) {
          log.error("renewRecall(): prevTaskId is empty, recall is not allowed");
          throw new BusinessException("RECALL-ERROR", "Recall is not allowed");
        }
        WfTask recallTask = taskService.selectById(prevTaskId);
        if (recallTask == null) {
          log.error(
              "renewRecall(): no wfTask record found for prevTaskId"
                  + prevTaskId
                  + ", recall is not allowed");
          throw new BusinessException("RECALL-ERROR", "Recall is not allowed");
        }
        JSONObject txChoices = recallTask.getTxChoicesJson();
        Boolean allowReCall = null;
        if (txChoices != null) {
          allowReCall = txChoices.getBoolean("AllowReCall");
        }
        if (allowReCall == null || !allowReCall) {
          log.error(
              "renewRecall(): preTask setting AllowReCall is null or false, recall is not allowed");
          throw new BusinessException("RECALL-ERROR", "Recall is not allowed");
        }
        boolean refreshCurrAssigner = false;
        if (!prevTaskId.equals(currTaskId)) { // 相等的情况,只有会签撤回
          awtParm.setOptUsersPre(null);
          awtParm.setTaskIdCurr(currTaskId);
          this.deleteSelective(awtParm);
          refreshCurrAssigner = true;
        }

        awt = new WfAwt(); // 新建一条awt
        awt.setTaskIdCurr(prevTaskId);
        awt.setInstId(instId);
        awt.setAssignerId(currUserId);
        awt.setOptUsersPre(currUserId);
        awt.setTaskIdPre(null);
        Date beginDate = new Date();
        awt.setAwtBegin(beginDate);
        awt.setAwtEnd(calculateDate(beginDate, nextTask.getTimeLimitTp(), nextTask.getTimeLimit()));
        awt.setAwtAlarm(
            nextTask.getAlarmTime() == null
                ? null
                : calculateDate(beginDate, nextTask.getAlarmTimeTp(), nextTask.getAlarmTime()));
        this.insert(awt);

        removeUserFromOptUserPrev(inst, currUserId, prevTaskId, refreshCurrAssigner);
      }
      return false;
    }
  }
  @Override
  public Object launchAppraisal(JSONObject jsonAppraisalObj) {
    // 判断对象是否有参数
    if (!CollectionUtils.isEmpty(jsonAppraisalObj)) {
      // 获取命令信息
      JSONObject jsonCommandInfo = jsonAppraisalObj.getJSONObject("commandInfo");
      if (CollectionUtils.isEmpty(jsonCommandInfo)) {
        throw new EnergyException("命令信息不能为空!");
      }
      String commandType = jsonCommandInfo.getString("commandType");
      if (StringUtils.isEmpty(commandType)) {
        throw new EnergyException("命令类型不能为空!");
      }
      if (!Constants.CMD_GENERAL.equals(commandType)) {
        throw new EnergyException("无效的命令类型:" + commandType);
      }

      // 获取当前用户
      WeixinUser weixinUser = SystemCacheUtil.getInstance().getCurrentUser();
      // 创建评价对象
      Appraisal appraisal = new Appraisal();

      appraisal.setUserId(weixinUser.getUserid());
      appraisal.setUserName(weixinUser.getName());
      appraisal.setTheme(jsonAppraisalObj.getString("theme"));
      appraisal.setOverallMerit(jsonAppraisalObj.getBoolean("overallMerit"));

      // 评价id
      String id = jsonAppraisalObj.getString("id");
      // 是否存在id 草稿 重新发起 都会存在id
      boolean hasId = false;
      if (StringUtils.isNotEmpty(id)) {
        appraisal.setId(id);
        hasId = true;
        // 清除与审批相关的 人员
        entityAccountService.deleteByEntityId(appraisal.getId());
      } else {
        appraisal.setId(CommonUtil.GeneGUID());
      }
      // 实体关系
      List<EntityAccount> entityAccountList = null;
      // 草稿状态下只存储
      if (Constants.CMD_DRAFT.equalsIgnoreCase(commandType)) {

      } else
      /** 发起审批操作 */
      if (Constants.CMD_GENERAL.equalsIgnoreCase(commandType)) {
        appraisal.setStatus(Status.未评价.value());
        appraisal.setCreateTime(new Date());
        if (hasId) {
          appraisalDao.updateAppraisal(appraisal);
        } else {
          appraisalDao.addAppraisal(appraisal);
        }
        // 问题记录

        List<ProblemTemplate> problemTemplateList =
            generateProblemTemplate(jsonAppraisalObj, appraisal.getId());
        if (!CollectionUtils.isEmpty(problemTemplateList)) {
          if (null != appraisal.getOverallMerit() && appraisal.getOverallMerit()) {
            ProblemTemplate problemTemplate = new ProblemTemplate();
            problemTemplate.setId(CommonUtil.GeneGUID());
            problemTemplate.setAppraisalId(appraisal.getId());
            problemTemplate.setQuota("需要填写综合评价");
            problemTemplateList.add(problemTemplate);
          }
          problemTemplateService.addProblemTemplate(
              problemTemplateList.toArray(new ProblemTemplate[] {}));
        }
        // 被评价人 评价人
        entityAccountList = generateEntityAccount(jsonAppraisalObj, appraisal.getId());
        if (!CollectionUtils.isEmpty(entityAccountList)) {
          StringBuffer shUser = new StringBuffer();
          for (EntityAccount entityAccount : entityAccountList) {
            if (EntityType.PJ.value().equals(entityAccount.getEntityType())) {
              if (PersonType.PJ.value().equals(entityAccount.getPersonType())) {
                shUser.append('|').append(entityAccount.getAccountId());
              }
            } else {
              LOGGER.error("人员列表数据内容非法!" + JSON.toJSONString(entityAccountList));
              throw new EnergyException("人员列表数据内容非法!");
            }
          }
          entityAccountService.addEntityAccount(entityAccountList.toArray(new EntityAccount[] {}));
          if (shUser.length() > 0) {
            shUser.deleteCharAt(0);
          }
          if (StringUtils.isNotEmpty(shUser.toString())) {
            // 给审核人推送消息
            SystemCacheUtil.getInstance()
                .getLinkedQueue()
                .add(
                    new AppraisalMsgExecutor(
                        appraisal.getId(), shUser.toString(), "template_appraisal_sh"));
          }
        } else {
          LOGGER.error("被评价或评价人不能为空!");
          throw new EnergyException("被评价或评价人不能为空!");
        }
      }
      return appraisal.getId();
    } else {
      LOGGER.warn("评价信息为空!");
    }
    return null;
  }