j-roadflow-plus-8.0.9升级日志

1、修改了流程步骤抄送设置为步骤处理人时的异常。

    修改文件:src/main/java/cn/tzsoft/roadflow/service/flow/FlowRunService.java

    image.png

    //步骤处理人
    JsonNode handlerSteps = JSONUtils.getJsonNode(stepCopyForJsonNode, "handlerSteps");
    if (handlerSteps != null) {
        for (JsonNode handlerStep : handlerSteps) {
            long stepId = NumberUtils.toLong(JSONUtils.getText(handlerStep));
            List<FlowTaskModel> flowTaskModels = flowGroupTasks.stream().filter(s -> s.getStepId().equals(stepId) && s.getType() != 5 && s.getType() != 11)
            .collect(Collectors.toList());
            if (flowTaskModels.isEmpty()) {
                continue;
            }
            FlowTaskModel maxReceiveFlowTaskModel = flowTaskModels.stream()
            .max(Comparator.comparing(FlowTaskModel::getReceiveOrder, Comparator.nullsFirst(Integer::compareTo))).orElse(null);
            flowTaskModels.stream().filter(s -> s.getReceiveOrder().equals(maxReceiveFlowTaskModel.getReceiveOrder())).forEach(taskModel -> {
                stringJoiner.add(userService.getPrefixId(taskModel.getReceiverId(), taskModel.getPartTimeId()));
            });
        }
    }

2、修改了流程任务处理后将消息中心对应的消息标记为已读。

    修改文件:src/main/java/cn/tzsoft/roadflow/dao/message/MessageDao.java

    image.png

    修改文件:src/main/java/cn/tzsoft/roadflow/service/message/MessageService.java

    image.png

    修改文件:src/main/java/cn/tzsoft/roadflow/service/flow/FlowExecuteService.java

    image.png

3、应用设计增加了小计合计。

    修改文件:src/web/element/src/roadui-pages/app-design/design/list.vue

    image.png
    image.png

    image.png

    修改文件:src/web/element/src/roadui-pages/app-design/design/design.js

    image.png

    image.png

    修改文件:src/web/element/src/roadui-pages/app-design/run/index.vue

    image.png

    image.png

    image.png

    修改文件:src/main/java/cn/tzsoft/roadflow/service/appdesign/AppDesignRunService.java

    image.png

    image.png

    image.png

 /**
 * 得到运行时列表查询数据
 *
 * @param request       HttpServletRequest
 * @param isExportExcel 是否是导出excel
 * @param selectRowIds  导出excel时选择的行
 * @return Pair-ObjectNode{total:总条数,records:记录列表};AppDesignRunModel
 */
public Pair<ObjectNode, AppDesignRunModel> getListData(HttpServletRequest request, boolean isExportExcel, List<String> selectRowIds) {
    ObjectMapper objectMapper = JSONUtils.getObjectMapper();
    ObjectNode objectNode = objectMapper.createObjectNode();
    ArrayNode arrayNode = objectMapper.createArrayNode();
    //应用id
    Long appDesignId = IdGeneratorUtils.getValue(request.getParameter("appDesignId"));
    AppDesignRunModel appDesignRunModel = get(appDesignId);
    if (appDesignRunModel == null) {
        objectNode.put("total", 0);
        objectNode.set("records", arrayNode);
        return Pair.of(objectNode, null);
    }

    //验证应用授权
    if (isNotAuth(appDesignRunModel, userService.getLoginUserId(request))) {
        objectNode.put("total", 0);
        objectNode.set("records", arrayNode);
        return Pair.of(objectNode, null);
    }

    JsonNode attrJsonNode = JSONUtils.parseJsonNode(appDesignRunModel.getAttrSet());
    Long connId = JSONUtils.getRefLong(attrJsonNode, "connId", IdGeneratorUtils.MIN_VALUE);
    ConnModel connModel = connService.getById(connId);
    if (connModel == null) {
        objectNode.put("total", 0);
        objectNode.set("records", arrayNode);
        return Pair.of(objectNode, null);
    }
    JsonNode leftJsonNode = StringUtils.equals("1", request.getParameter("isLeftQuery")) ? JSONUtils.parseJsonNode(appDesignRunModel.getLeftSet()) : null;//左栏树节点点击的查询
    ArrayNode listJsonNode = JSONUtils.parseArrayNode(appDesignRunModel.getListSet());
    ArrayNode queryJsonNode = JSONUtils.parseArrayNode(appDesignRunModel.getQuerySet());
    int number = NumberUtils.toInt(request.getParameter("number"), 1);
    int size = NumberUtils.toInt(request.getParameter("size"), 10);
    String order = request.getParameter("order");
    if (StringUtils.isBlank(order)) {
        //如果排序为空,则使用应用属性中设置的默认排序。
        order = JSONUtils.getString(attrJsonNode, "defaultSort");
    }
    //是否要转换参数类型,pgSql要转换。
    boolean isSerializable = MybatisPlusConfig.getDbType(connModel.getType()) == DbType.POSTGRE_SQL;
    String fields = "";
    String sql = wildcardService.replace(JSONUtils.getString(attrJsonNode, "sqlString"));
    int total;
    List<LinkedHashMap<String, Object>> records;
    boolean isPager = !isExportExcel && JSONUtils.getInt(attrJsonNode, "isPager", 0) == 1;//是否分页,如果是导出不分页
    Map<String, Object> paramsMap;
    //如果是导出excel又选择了导出列,则只查询选择的列。
    if (isExportExcel && selectRowIds != null && !selectRowIds.isEmpty()) {
        String selectKey = JSONUtils.getString(attrJsonNode, "selectKey");
        paramsMap = new HashMap<>();
        Map<String, Object> wheresInMap = new HashMap<>();
        if (isSerializable) {
            //pgSql要判断主键类型
            List<Object> selectRowObjectList = new ArrayList<>();
            for (String selectId : selectRowIds) {
                selectRowObjectList.add(formService.getObjectValue(selectId));
            }
            wheresInMap.put(" AND " + (StringUtils.isBlank(selectKey) ? "id" : selectKey), selectRowObjectList);
        } else {
            wheresInMap.put(" AND " + (StringUtils.isBlank(selectKey) ? "id" : selectKey), selectRowIds);
        }
        paramsMap.put("wheresIn", wheresInMap);
    } else {
        paramsMap = getQueryParamsMap(queryJsonNode, leftJsonNode, isSerializable, request);
    }
    if (isPager) {
        //分页查询
        PageInfo<LinkedHashMap<String, Object>> pageInfo = connService.getMapPage(connModel, number, size, sql, fields, order, paramsMap);
        total = (int) pageInfo.getTotal();
        records = pageInfo.getList();
    } else {
        //不分页查询所有
        records = connService.getMapPage(connModel, sql, fields, order, paramsMap);
        total = records.size();
    }
    Map<String, Pair<BigDecimal, String>> subTotalMap = new HashMap<>();//小计Map<字段,Pair<小计值,格式字符串>>
    Map<String, Pair<BigDecimal, String>> sumTotalMap = new HashMap<>();//合计Map<字段,Pair<合计值,格式字符串>>
    if (listJsonNode != null) {
        for (JsonNode fJsonNode : listJsonNode) {
            if (JSONUtils.getInt(fJsonNode, "subTotal") == 1) {
                subTotalMap.put(JSONUtils.getString(fJsonNode, "fieldName"), Pair.of(BigDecimal.ZERO, JSONUtils.getString(fJsonNode, "showFormat")));
            }
            if (JSONUtils.getInt(fJsonNode, "sumTotal") == 1) {
                sumTotalMap.put(JSONUtils.getString(fJsonNode, "fieldName"), Pair.of(BigDecimal.ZERO, JSONUtils.getString(fJsonNode, "showFormat")));
            }
        }
    }
    for (LinkedHashMap<String, Object> linkedHashMap : records) {
        ObjectNode rowObjectNode = objectMapper.createObjectNode();
        for (Map.Entry<String, Object> entry : linkedHashMap.entrySet()) {
            Object obj = entry.getValue();
            Object valueObject = obj;
            if (MybatisPlusConfig.getDbType(connModel.getType()) == DbType.ORACLE) {
                if (obj instanceof Clob) {
                    valueObject = StringUtils.getClobString((Clob) obj);
                } else if (obj instanceof Blob) {
                    valueObject = StringUtils.getBlobString((Blob) obj);
                }
            }
            String fieldName = entry.getKey();
            setListObjectNodeValue(objectMapper, rowObjectNode, listJsonNode, fieldName, valueObject, linkedHashMap);
            //计算页小计
            if (subTotalMap.size() > 0 && subTotalMap.containsKey(fieldName)) {
                subTotalMap.put(fieldName, Pair.of(subTotalMap.get(fieldName).getLeft().add(NumberUtils.toBigDecimal(StringUtils.objectToString(valueObject), BigDecimal.ZERO)), subTotalMap.get(fieldName).getRight()));
            }
        }
        arrayNode.add(rowObjectNode);
    }

    //组织小计ObjectNode
    ObjectNode subTotalObjectNode = objectMapper.createObjectNode();
    for (Map.Entry<String, Pair<BigDecimal, String>> entry : subTotalMap.entrySet()) {
        subTotalObjectNode.put(entry.getKey(), StringUtils.isBlank(entry.getValue().getRight())
                ? entry.getValue().getLeft().toPlainString()
                : NumberUtils.formatBigDecimal(entry.getValue().getLeft(), entry.getValue().getRight()));
    }

    //查询合计
    ObjectNode sumTotalObjectNode = objectMapper.createObjectNode();
    if (sumTotalMap.size() > 0) {
        StringJoiner fieldStringJoiner = new StringJoiner(",");
        for (Map.Entry<String, Pair<BigDecimal, String>> entry : sumTotalMap.entrySet()) {
            fieldStringJoiner.add("SUM(" + entry.getKey() + ") AS " + entry.getKey());
        }
        List<LinkedHashMap<String, Object>> sumList = null;
        try {
            sumList = connService.getMapPage(connModel, sql, fieldStringJoiner.toString(), "", paramsMap);
        } catch (Exception e) {
            logService.add(e);
        }
        if (sumList != null && sumList.size() > 0) {
            for (Map.Entry<String, Pair<BigDecimal, String>> entry : sumTotalMap.entrySet()) {
                String sumValue = StringUtils.objectToString(sumList.get(0).get(entry.getKey()));
                String showFormat = entry.getValue().getRight();
                sumTotalObjectNode.put(entry.getKey(), StringUtils.isBlank(showFormat)
                        ? StringUtils.isBlank(sumValue) ? "0" : sumValue
                        : NumberUtils.formatBigDecimal(NumberUtils.toBigDecimal(sumValue, BigDecimal.ZERO), showFormat));
            }
        }
    }
    objectNode.put("total", total);
    objectNode.set("records", arrayNode);
    objectNode.set("subTotal", subTotalObjectNode);
    objectNode.set("sumTotal", sumTotalObjectNode);
    return Pair.of(objectNode, appDesignRunModel);
}

4、增加我的发起流程中可以复制重新发起功能。

    修改文件:src/web/element/src/roadui-pages/flow/run/my-start.vue

    image.png

 <el-button size="small" :disabled="loading" type="success" @click="copyStart(scope.row)" style="vertical-align:middle;">
    <i class="rf_button_icon_in_min icon-edit-line"></i></el-button>

    image.png

    //复制一份表单数据再发起流程
    const copyStart = (task) => {
        utils.confirm('您确定要复制并发起流程吗?', () => {
            loading.value = true;
            ajax.post('/flow/flow/copyMyStart?groupId=' + task.groupId).then((res) => {
                if (res.code === 0) {
                    const newTask = res.data;
                    const menu = {
                        id: 'flow_run_' + newTask.id,
                        name: newTask.title,
                        icon: 'icon-draft-line',
                        url: '/flow/run/index.vue?flowId=' + newTask.flowId + '&flowVersionId=' + newTask.flowVersionId + '&stepId=' + newTask.stepId + '&taskId=' + newTask.id + '&instanceId=' + newTask.instanceId + '&groupId=' + newTask.groupId,
                        openMode: 0
                    };
                    index_openPage(menu);
                } else {
                    let msg = '操作失败!';
                    if (res.code === 1) {
                        msg = '没有找到任务!';
                    } else if (res.code === 2) {
                        msg = '未找到流程运行时实体!';
                    }
                    utils.msg(msg, false);
                }
                loading.value = false;
            }).catch(() => {
                loading.value = false;
            });
        });
    };

    修改文件:src/main/java/cn/tzsoft/roadflow/controller/roadflowwebapi/flow/FlowController.java

    image.png

  /**
 * 复制我的发起流程再次发起流程
 *
 * @param groupId 任务组id
 * @param request HttpServletRequest
 * @return ResponseResult
 */
@PostMapping(value = "copyMyStart")
@UserAuthorize
public ResponseResult copyMyStart(Long groupId, HttpServletRequest request) {
    List<FlowTaskModel> flowTaskGroupList = flowTaskService.getListByGroupId(groupId, -1);
    List<FlowTaskModel> flowTaskFirstList = flowTaskService.getFirstTasks(flowTaskGroupList);
    if (flowTaskFirstList.isEmpty()) {
        return ResponseResult.error(1);
    }
    FlowTaskModel flowTaskModel = flowTaskFirstList.get(0);
    JsonNode flowJsonNode = flowVersionService.getFlowJsonNodeById(flowTaskModel.getFlowVersionId());
    if (flowJsonNode == null) {
        return ResponseResult.error(2);
    }
    JsonNode flowAttrJsonNode = JSONUtils.getJsonNode(flowJsonNode, "attr");
    Long startStepId = JSONUtils.getRefLong(flowAttrJsonNode, "startStepId");
    JsonNode stepSetJsonNode = flowService.getStepSet(startStepId, flowJsonNode);
    JsonNode stepBaseJsonNode = JSONUtils.getJsonNode(stepSetJsonNode, "base");
    Long appId = JSONUtils.getRefLong(stepBaseJsonNode, "appId");
    JsonNode formTemplateJsonNode = formService.getTemplateByAppId(appId);
    JsonNode dbJsonNode = JSONUtils.getJsonNode(formTemplateJsonNode, "db");
    JsonNode fieldsJsonNode = JSONUtils.getJsonNode(formTemplateJsonNode, "fields");
    JsonNode subTablesJsonNode = JSONUtils.getJsonNode(formTemplateJsonNode, "subTables");
    Long formId = JSONUtils.getRefLong(formTemplateJsonNode, "id");

    ObjectNode formData = formService.getFormData(dbJsonNode, fieldsJsonNode, flowTaskModel.getInstanceId(), subTablesJsonNode, null, formId, 0);
    //清空formData中的流水号,保存数据时重新生成。
    JsonNode serialNumberJsonNode = JSONUtils.getJsonNode(formTemplateJsonNode, "serialNumber");
    if (serialNumberJsonNode != null) {
        for (JsonNode serialJsonNode : serialNumberJsonNode) {
            String fieldId = JSONUtils.getString(serialJsonNode, "id");
            if (StringUtils.isNotBlank(fieldId)) {
                formData.put(fieldId, "");
            }
        }
    }
    Pair<Long, String> userPair = userService.getLoginUserIdName(request);
    ObjectMapper objectMapper = JSONUtils.getObjectMapper();
    ObjectNode paramsObjectNode = objectMapper.createObjectNode();
    paramsObjectNode.put("type", "save")
            .put("flowId", NumberUtils.longToString(flowTaskModel.getFlowId()))
            .put("flowVersionId", NumberUtils.longToString(flowTaskModel.getFlowVersionId()))
            .put("stepId", NumberUtils.longToString(startStepId))
            .put("taskId", "")
            .put("groupId", "")
            .put("instanceId", "")
            .put("title", flowTaskModel.getTitle())
            .put("senderId", NumberUtils.longToString(userPair.getLeft()))
            .put("senderName", userPair.getRight());
    ObjectNode resultObjectNode = flowExecuteService.execute(paramsObjectNode, formData);
    int code = JSONUtils.getInt(resultObjectNode, "code");
    if (code != 0) {
        return ResponseResult.error(code);
    }
    JsonNode currentTaskJsonNode = JSONUtils.getJsonNode(resultObjectNode, "currentTask");
    return ResponseResult.success(currentTaskJsonNode);
}

5、增加了应用设计列显示内容过长是否隐藏设置。

    修改文件:src/web/element/src/roadui-pages/app-design/design/list.vue

    image.png

    修改文件:src/web/element/src/roadui-pages/app-design/design/design.js

    image.png

6、增加了应用设计导出时设置导入转换类型。

    表rf_design_export增加字段:

    image.png

    实体类修改:src/main/java/cn/tzsoft/roadflow/model/appdesign/AppDesignExportModel.java

    image.png

    修改文件:src/web/element/src/roadui-pages/app-design/design/export.vue

    image.png

    修改文件:src/web/element/src/roadui-pages/app-design/design/design.js

    image.png

    修改文件:src/main/java/cn/tzsoft/roadflow/controller/roadflowwebapi/appdesign/AppDesignRunController.java

    image.png

    image.png

7、修改了HTML富文本编辑器为Tinymce。

    安装组件:npm install @tinymce/tinymce-vue@6.0.1

    卸载组件:npm uninstall @wangeditor/editor-for-vue

    修改文件:src/web/element/src/roadui-components/rf-editor.vue

    增加目录及文件:src/web/element/public/tinymce

    修改文件:src/web/element/index.html

    image.png

    image.png

    修改文件:src/web/element/src/roadui-pages/form/design/controls/editor-ctl.vue

    image.png

    image.png

    修改文件:src/web/element/src/roadui-pages/form/design/design.js

    image.png

联系QQ:493501010电话:136 0832 5512(微信同号)邮箱:road@roadflow.net
Copyright 2014 - 2024 重庆天知软件技术有限公司 版权所有