pruple_boy 8 months ago
parent
commit
807fd8ba99

+ 101 - 0
mjava-mcli/src/main/java/com/malk/mcli/controller/ApprovalMatrixController.java

@@ -0,0 +1,101 @@
+package com.malk.mcli.controller;
+
+
+import com.alibaba.fastjson.JSONObject;
+import com.malk.server.aliwork.YDConf;
+import com.malk.server.aliwork.YDParam;
+import com.malk.server.common.McException;
+import com.malk.server.common.McR;
+import com.malk.service.aliwork.YDClient;
+import com.malk.utils.UtilMap;
+import com.malk.utils.UtilServlet;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 错误抛出与拦截详见CatchException
+ */
+@Slf4j
+@RestController
+@RequestMapping("/matrix")
+public class ApprovalMatrixController {
+
+    /**
+     * 审批矩阵验证说明
+     * 1. 审批预览
+     * - 审批预览会调用矩阵接口, 预览开启若存在超时情况不能发起
+     * - 预览若是节点报错, 则可以正常发起, 预览时该节点不会显示 [ 若是通过预览实现强管控, 可在异常内添加超时机制, 控制不能发起 ]
+     * 2. 超时情况
+     * - 目前官方给到默认 timeout 5s, 且不支持配置
+     * - 审批流程会等待全部节点请求返回后才会显示, 数据提交后若某一个节点超时, 则该节点审批人不显示 [ 可搭配缓存逻辑, 关闭提交预览 ]
+     * 3. 抛出异常
+     * - 触发: 1. 节点返回为空, 且未配置为空自动通过; 2. 节点抛出异常
+     * - 若是第一个节点就异常, 管理员可在管理后台, 数据列表页面点击重试按钮进行重新激活
+     * - 若是中途节点, 该节点审批会发挥接口抛出异常信息, 若是返回空切设置为空不自动通过, 则会抛出审批人不能为空异常提醒, 流程点击同意都不能向下流转
+     * 4. 缓存逻辑
+     * - 原理: 缓存机制基于唯一ID, 自定义或数据实例Id, 否则额若传递矩阵参数会增加矩阵配置复杂度\降低其灵活性
+     * - 1. 若是节点可保障在 timeout 前返回, 可基于自定义 ID 进行数据缓存, 通过预览触发缓存, 节点异常通过超时控制不能发起, 同时解决发起异常问题
+     * - 2. 若节点存在超时情况多, 且可忽略预览效果情况下, 可通过数据实例ID缓存, 首次打开可能显示不全, 缓存成功后直接加载
+     * - 兜底: 缓存成功先返回缓存数据, 后台持续执行更新逻辑, 兼容条件\人员矩阵变更, 未到达审批节点更新. 若是存在退回场景, 可触发新的审批人员修正
+     * 5. 待办推送
+     * - 第一个节点异常重新激活的流程, 待办会正常触发推送
+     * - 未执行到节点, 若人员变更, 会在执行到该节点时触发待办推送 [ 目前转交有api可调用 ]
+     * 6. 补充说明
+     * - 已跳过/审批中节点, 再次打开不会触发调用, 未触发的节点, 每次页面打开都会触发调用 [ 缓存可很好降低并发问题 ]
+     * - 若是设置了为空自动通过, 流程会自动忽略该节点, 自动到下一个节点. 已跳过/审批中节点, 再次打开不会触发调用, 通过退回到该节点前可重新激活
+     * 7. 功能优化
+     * - 目前采用缓存方案2, 后续可考虑切换缓存方案1, 若是存在超时场景, 需要对组织架构\矩阵数据缓存, 解决QPS导致超时问题
+     * - 矩阵审批节点全部配置为空不允许自动通过 (默认配置), 是否为空可配置矩阵逻辑内, 避免审批节点丢失 [ 实现逻辑: 若审批可为空, 且该节点为空, 返回系统审批账号, 再调用自动同意 ]
+     */
+    @SneakyThrows
+    @PostMapping("approval")
+    List<String> approvalMatrix(HttpServletRequest request) {
+
+        Map data = UtilServlet.getParamMap(request);
+        log.info("审批矩阵, {}", data);
+
+        McException.assertAccessException("是".equals(UtilMap.getString(data, "exception")), "抛出异常");
+
+        if (!"是".equals(UtilMap.getString(data, "cache_r"))) {
+            int s = UtilMap.getInt(data, "sleep_s");
+            if (s > 0) {
+                Thread.sleep(s * 1000);
+            }
+        }
+        return (List<String>) JSONObject.parse(String.valueOf(JSONObject.parse(UtilMap.getString(data, "employeeField_"))));
+    }
+
+
+    private static final String appType_Tech = "APP_H3A35LRTTIQZE14NMCIA";
+    private static final String systemToken_Tech = "1IC66671L7UO3SA58DBNM6269FP12LNO9YE1MHA1";
+
+    @Autowired
+    private YDClient ydClient;
+
+    /**
+     * 审批记录接口,会返回未执行的节点. 同时返回 type \ actionExit, 可用于区分 历史 \ 进行中 \ 未到达 状态
+     */
+    @GetMapping("record")
+    McR approvalRecord(@RequestParam String processInstanceId) {
+
+        log.info("审批记录, {}", processInstanceId);
+
+        List<Map> records = (List<Map>) ydClient.queryData(YDParam.builder()
+                .appType(appType_Tech)
+                .systemToken(systemToken_Tech)
+                .processInstanceId(processInstanceId)
+                .build(), YDConf.FORM_QUERY.retrieve_approval_record).getResult();
+        return McR.success(records);
+    }
+
+    /**
+     * 自动化、编辑事件则是只要更新就会执行。通过api 则需要传递更新执行参数,才会触发业务规则
+     */
+
+}

+ 2 - 2
mjava-ruisi/src/main/java/com/malk/ruisi/controller/CosController.java

@@ -26,8 +26,8 @@ import java.util.Map;
 
 @Slf4j
 @RestController
-@RequestMapping
-public class CosController {
+@RequestMapping("dd")
+public class DDController {
 
     @Autowired
     private RSService rsService;

+ 96 - 0
mjava-ruisi/src/main/java/com/malk/ruisi/controller/YDController.java

@@ -0,0 +1,96 @@
+package com.malk.ruisi.controller;
+
+/**
+ * 错误抛出与拦截详见 CatchException
+ */
+
+import com.alibaba.fastjson.JSON;
+import com.malk.server.aliwork.YDConf;
+import com.malk.server.aliwork.YDParam;
+import com.malk.server.common.McException;
+import com.malk.server.common.McR;
+import com.malk.service.aliwork.YDClient;
+import com.malk.utils.UtilMap;
+import com.malk.utils.UtilServlet;
+import lombok.Synchronized;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+@RestController
+@RequestMapping("yd")
+public class YDController {
+
+    @Autowired
+    private YDClient ydClient;
+
+
+    // 接口校验通用逻辑
+
+    @Synchronized
+    @PostMapping("/invokeThird")
+    McR invokeThird(HttpServletRequest request) {
+
+        Map data = UtilServlet.getParamMap(request);
+        log.info("接口校验通用逻辑, {}", JSON.toJSONString(data));
+
+        McException.assertParamException_Null(data, "instanceId");
+
+        // 多人审批场景下, 避免重复推送
+        if ("成功".equals(UtilMap.getString(data, "radioField_m1hmte37"))) {
+            return McR.success();
+        }
+
+        boolean isSuccess = true;
+        String message = "";
+        try {
+            /// 调用服务, 若也存在异常, 抛出
+
+
+        } catch (McException exception) {
+            isSuccess = true;
+            message = exception.getMessage();
+            log.error(exception.getMessage(), exception);
+        }
+
+        ydClient.operateData(YDParam.builder()
+                .formInstId(UtilMap.getString(data, "instanceId"))
+                .updateFormDataJson(JSON.toJSONString(UtilMap.map("radioField_m1hmte37, textareaField_lntocd8u", isSuccess ? "成功" : "失败", message)))
+                .build(), YDConf.FORM_OPERATION.update);
+        McException.assertAccessException(!isSuccess, message); // 抛出异常
+
+        return McR.success();
+    }
+
+    // 重新发起请假流程
+    @GetMapping("/test21")
+    McR test21() {
+        String formInstanceId = "35c8ba1b-2c5b-4581-bf75-a53f9f3b4657";
+        String userId = "1007054";
+        Map formData = (Map) ydClient.queryData(YDParam.builder().formInstId(formInstanceId)
+                .build(), YDConf.FORM_QUERY.retrieve_id).getFormData();
+        List employeeField_lts1mg30_id = (List) formData.get("employeeField_lts1mg30_id");
+        List departmentSelectField_lts1mg2z_id = (List) formData.get("departmentSelectField_lts1mg2z_id");
+        List departmentSelectField_lys0k6qb_id = (List) formData.get("departmentSelectField_lys0k6qb_id");
+        System.out.println("==" + employeeField_lts1mg30_id);
+        formData.put("employeeField_lts1mg30", employeeField_lts1mg30_id);
+        formData.put("departmentSelectField_lts1mg2z", departmentSelectField_lts1mg2z_id);
+        formData.put("departmentSelectField_lys0k6qb", departmentSelectField_lys0k6qb_id);
+
+        System.out.println(formData);
+        ydClient.operateData(YDParam.builder()
+                .formUuid("FORM-A02F7EA3AD6548E59B8E1692AD729C77C5LD")
+                .userId(userId)
+                .formDataJson(JSON.toJSONString(formData))
+                .build(), YDConf.FORM_OPERATION.start).toString();
+        return McR.success(formData);
+    }
+}

+ 5 - 4
mjava/src/main/java/com/malk/server/aliwork/YDConf.java

@@ -67,11 +67,12 @@ public class YDConf {
         retrieve_search_process_id,         // 流程列表
         retrieve_search_form_id,             // 表单列表
 
-        retrieve_details,             // 子表数据[表单]
-        retrieve_changed,    // 变更记录
-        retrieve_definition, // 表单定义
+        retrieve_details,                   // 子表数据[表单]
+        retrieve_changed,               // 变更记录
+        retrieve_definition,        // 表单定义
 
         retrieve_forms, // 表单列表
+        retrieve_approval_record, // 审批记录
     }
 
     /**
@@ -81,7 +82,7 @@ public class YDConf {
         create,
         delete,                     // 传入为body, 文档为param
         update,
-        upsert,                     // fixme: 不支持新增字段更新, 若有可先更新版本后执行 [无版本和更新json参数]
+        upsert,                     // fixme: 不支持新增字段更新, 若有可先更新版本后执行 [无版本和更新json参数]; ppExt: 不会触发消息通知, 需要 start / creat
         multi_create,               // 批量操作
         delete_batch,               // 批量删除
         multi_update,               // 批量更新

+ 4 - 0
mjava/src/main/java/com/malk/service/aliwork/impl/YDClientImpl.java

@@ -130,6 +130,10 @@ public class YDClientImpl implements YDClient {
             case retrieve_forms:
                 ddr_new = DDR_New.doGet(getRequestUrl("/forms"), ddClient.initTokenHeader(), param);
                 break;
+
+            case retrieve_approval_record:
+                ddr_new = DDR_New.doGet(getRequestUrl("/processes/operationRecords"), ddClient.initTokenHeader(), param);
+                break;
         }
         return ddr_new;
     }