pruple_boy vor 1 Jahr
Ursprung
Commit
bffe5f1ad0
22 geänderte Dateien mit 430 neuen und 142 gelöschten Zeilen
  1. 1 9
      mjava-aiwei/src/main/java/com/malk/aiwei/controller/TBController.java
  2. 19 3
      mjava-aiwei/src/main/java/com/malk/aiwei/controller/TBxYDController.java
  3. 74 0
      mjava-aiwei/src/main/java/com/malk/aiwei/schedule/AWScheduleTask.java
  4. 3 1
      mjava-aiwei/src/main/java/com/malk/aiwei/server/AWServer.java
  5. 21 0
      mjava-aiwei/src/main/java/com/malk/aiwei/service/AWClint.java
  6. 211 95
      mjava-aiwei/src/main/java/com/malk/aiwei/service/impl/AWImplClient.java
  7. 1 1
      mjava-aiwei/src/main/resources/application-dev.yml
  8. 1 1
      mjava-fengkaili/src/main/java/com/malk/fengkaili/schedule/FKLScheduleTask.java
  9. 2 3
      mjava-hake/src/main/java/com/malk/hake/controller/HKController.java
  10. 2 2
      mjava-hake/src/main/java/com/malk/hake/schedule/HKScheduleTask.java
  11. 3 3
      mjava-hake/src/main/java/com/malk/hake/service/impl/HKImplClient.java
  12. 3 1
      mjava-hake/src/main/resources/static/json/form.json
  13. 1 1
      mjava-hangshi/src/main/java/com/malk/hangshi/schedule/HSScheduleTask.java
  14. 30 16
      mjava-luyi/src/main/java/com/malk/luyi/controller/LYController.java
  15. 3 0
      mjava/src/main/java/com/malk/server/aliwork/YDConf.java
  16. 6 0
      mjava/src/main/java/com/malk/server/aliwork/YDParam.java
  17. 4 0
      mjava/src/main/java/com/malk/server/teambition/TBR.java
  18. 1 1
      mjava/src/main/java/com/malk/service/aliwork/YDService.java
  19. 14 2
      mjava/src/main/java/com/malk/service/teambition/TBClient.java
  20. 3 0
      mjava/src/main/java/com/malk/service/teambition/TBService.java
  21. 14 2
      mjava/src/main/java/com/malk/service/teambition/impl/TBClientImpl.java
  22. 13 1
      mjava/src/main/java/com/malk/utils/UtilMap.java

+ 1 - 9
mjava-aiwei/src/main/java/com/malk/aiwei/controller/TBController.java

@@ -1,7 +1,6 @@
 package com.malk.aiwei.controller;
 
 import com.malk.controller.TBCallBackController;
-import com.malk.utils.UtilEnv;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
@@ -18,12 +17,5 @@ import org.springframework.web.bind.annotation.RestController;
 @RestController
 @RequestMapping("/tb")
 public class TBController extends TBCallBackController {
-
-    // monitor接口ip
-    String _getEnvApi(String path) {
-        if (UtilEnv.getActiveProfile().equals(UtilEnv.ENV_PROD)) {
-            return "http://172.16.20.13:10002/api/public" + path;
-        }
-        return "http://116.228.113.106:10001/api/public" + path;
-    }
+    
 }

+ 19 - 3
mjava-aiwei/src/main/java/com/malk/aiwei/controller/TBxYDController.java

@@ -49,7 +49,7 @@ public class TBxYDController {
     }
 
     /**
-     * * 检查项check回调
+     * 检查项check回调
      */
     @PostMapping("checked")
     McR check(HttpServletRequest request) {
@@ -114,6 +114,24 @@ public class TBxYDController {
         return McR.success();
     }
 
+    /**
+     * 手动触发, 同步预检项
+     */
+    @PostMapping("check/sync")
+    McR syncCheck(int type) {
+        awClint.syncCheckList(type);
+        return McR.success();
+    }
+
+    /**
+     * 手动触发, 同步项目主数据
+     */
+    @PostMapping("project/sync")
+    McR syncProject() {
+        awClint.syncProject(null);
+        return McR.success();
+    }
+
     //////// test ////////
 
     @Autowired
@@ -158,8 +176,6 @@ public class TBxYDController {
 
     @GetMapping("tmp")
     McR tmp() {
-        
-
         return McR.success();
     }
 }

+ 74 - 0
mjava-aiwei/src/main/java/com/malk/aiwei/schedule/AWScheduleTask.java

@@ -0,0 +1,74 @@
+package com.malk.aiwei.schedule;
+
+import com.malk.aiwei.service.AWClint;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+
+/**
+ * @EnableScheduling 开启定时任务 [配置参考McScheduleTask]
+ */
+@Slf4j
+@Configuration
+@EnableScheduling
+@ConditionalOnProperty(name = {"spel.scheduling"})
+public class AWScheduleTask {
+
+    @Autowired
+    private AWClint awClint;
+
+    /**
+     * 每天12.30,00.30点同步, 项目主数据
+     */
+    @Scheduled(cron = "0 30 0,12 * * ? ")
+    public void sync_4() {
+        try {
+            awClint.syncProject(null);
+        } catch (Exception e) {
+            // 记录错误信息
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 每天凌晨1点同步, 预检项
+     */
+    @Scheduled(cron = "0 0 1 * * ? ")
+    public void sync_1() {
+        try {
+            awClint.syncCheckList(0);
+        } catch (Exception e) {
+            // 记录错误信息
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 每天凌晨1.30点同步. 预检项
+     */
+    @Scheduled(cron = "0 30 1 * * ? ")
+    public void sync_2() {
+        try {
+            awClint.syncCheckList(1);
+        } catch (Exception e) {
+            // 记录错误信息
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 每天凌晨2点同步, 预检项
+     */
+    @Scheduled(cron = "0 0 2 * * ? ")
+    public void sync_3() {
+        try {
+            awClint.syncCheckList(2);
+        } catch (Exception e) {
+            // 记录错误信息
+            e.printStackTrace();
+        }
+    }
+}

+ 3 - 1
mjava-aiwei/src/main/java/com/malk/aiwei/server/AWServer.java

@@ -4,7 +4,9 @@ import com.alibaba.fastjson.JSON;
 import com.malk.utils.UtilHttp;
 import com.malk.utils.UtilMap;
 
+import java.util.Arrays;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 public class AWServer {
@@ -18,13 +20,13 @@ public class AWServer {
 
     public static final String TASK_CHECK_LINK = "预检项";
     public static final String TASK_CHECK_STATUS = "预检项检查状态";
-    public static final String TASK_TIPS = "未配置预检项";
 
     public static final String TASK_APPROVE_ATTACHMENT = "交付件";
     public static final String TASK_APPROVE_LINK = "交付件审批流程";
 
     // ppExt: 注意不同任务类型名称唯一性, 如通用已完成不要使用
     public static final String WORKFLOW_APPROVE = "已提交";
+    public static final List<String> WORKFLOW_INITIAL = Arrays.asList("未完成", "待处理");
 
     public static final String PROJECT_PM_ROLE = "项目管理员";
     public static final String PROJECT_PM_NAME = "项目经理";

+ 21 - 0
mjava-aiwei/src/main/java/com/malk/aiwei/service/AWClint.java

@@ -1,5 +1,7 @@
 package com.malk.aiwei.service;
 
+import com.malk.server.aliwork.YDParam;
+
 import java.util.Map;
 
 public interface AWClint {
@@ -38,4 +40,23 @@ public interface AWClint {
      * 分配项目角色 prd 若是一人直接指定, 多人情况下忽略
      */
     void updateProjectRole(String projectId);
+
+    /**
+     * 同步预检项
+     *
+     * @param srcParam          [appType, formUuid, systemToken]
+     * @param compIds           映射表: 当前组件, 来源组件
+     * @param taskCompId        任务号, 忽略为空记录
+     * @param codeCompId        来源表唯一标识
+     * @param checkType         预检项分类(TR评审要素表、经验库、技术评审要素表)
+     * @param associationCompId 预检项分类对应关联组件
+     */
+    void syncCheckList(YDParam srcParam, Map<String, ?> compIds, String taskCompId, String codeCompId, String checkType, String associationCompId);
+
+    /**
+     * 同步预检项
+     *
+     * @param type 预检项分类(0-经验库、1-技术评审要素表, 2-TR评审要素表)
+     */
+    void syncCheckList(int type);
 }

+ 211 - 95
mjava-aiwei/src/main/java/com/malk/aiwei/service/impl/AWImplClient.java

@@ -12,6 +12,7 @@ import com.malk.server.teambition.TBConf;
 import com.malk.service.aliwork.YDClient;
 import com.malk.service.aliwork.YDService;
 import com.malk.service.teambition.TBClient;
+import com.malk.utils.UtilEnv;
 import com.malk.utils.UtilMap;
 import com.malk.utils.UtilString;
 import lombok.extern.slf4j.Slf4j;
@@ -26,13 +27,40 @@ import java.util.stream.Collectors;
 @Slf4j
 public class AWImplClient implements AWClint {
 
-
     @Autowired
     private YDClient ydClient;
 
     @Autowired
     private YDService ydService;
 
+    @Autowired
+    private YDConf ydConf;
+
+    // 项目主数据表
+    String _matchFormUuid(String code) {
+        Map<String, String> formUuid = UtilMap.empty();
+        if (true || UtilEnv.getActiveProfile().equals(UtilEnv.ENV_PROD)) {
+            formUuid.put("REVIEW", "FORM-812FD46AF391449A8F206EDB3221B38840UQ"); // 交付物审批记录
+            formUuid.put("REVIEW_PROCESS", "TPROC--RJC66SC1NEFHXJ0H770K0CF4WN1K21HQ706RL5"); // 交付物审批记录
+            formUuid.put("PROJECT", "FORM-141E21DF183846028E21727CE43CD1C75CLZ"); // 项目主数据
+            formUuid.put("APPROVE", "FORM-A25299893F614A6EAA672514D3A76BB0QDBF"); // 交付物审批矩阵
+            formUuid.put("CHECK", "FORM-1A5D4D7FBF88409B956EBE51F9342A6BKOLP"); // 预检项
+            formUuid.put("RECORD", "FORM-6E2C0D1197264B8AA23EB3FECAE7344B00BN"); // 预检项记录
+            formUuid.put("ROLE", "FORM-3C7396A12ADB48A8833EBD90089C93833R21"); // 项目角色
+            formUuid.put("DOMAIN", "https://yida.awinic.com/"); // 宜搭域名
+        } else {
+            formUuid.put("REVIEW", "FORM-FBC1A390B4C348089020C763938A6F54RUNY");
+            formUuid.put("REVIEW_PROCESS", "TPROC--YU966T91PIDH4XDR82OJC8GVOP7Z19PODTXQL6");
+            formUuid.put("PROJECT", "FORM-84EF78C7DBA047E58A8C8511106F91D5WNVI");
+            formUuid.put("APPROVE", "FORM-AB7263D2A12F4E01A871656F0D995BC96PR1");
+            formUuid.put("CHECK", "FORM-E6CB042D7929448888AE5E2B27631E57IVPM");
+            formUuid.put("RECORD", "FORM-7B63BB056145452F8BC0A2C52492DE00QVBH");
+            formUuid.put("ROLE", "FORM-5BE21392886E46DF955D1EBC100ADA429NON");
+            formUuid.put("DOMAIN", "https://kabom7.aliwork.com/");
+        }
+        return formUuid.get(code);
+    }
+
     /**
      * 交付物审批 [ppExt: 宜搭附件传递 downloadUrl 和 name 即可实现在线预览]
      */
@@ -52,8 +80,7 @@ public class AWImplClient implements AWClint {
         String tCode = UtilMap.getString(taskData, AWServer.TASK_CODE);
         // 工作流tb虽然配置了流转逻辑, 冗余稳定性
         List<Map> formList = (List<Map>) ydClient.queryData(YDParam.builder()
-//                .formUuid("FORM-FBC1A390B4C348089020C763938A6F54RUNY")
-                .formUuid("FORM-812FD46AF391449A8F206EDB3221B38840UQ")
+                .formUuid(_matchFormUuid("REVIEW"))
                 .searchFieldJson(JSON.toJSONString(UtilMap.map("selectField_lqxuswzd, textField_lrncs2fu", tCode, pCode)))
                 .instanceStatus("RUNNING")
                 .build(), YDConf.FORM_QUERY.retrieve_search_process).getData();
@@ -67,14 +94,12 @@ public class AWImplClient implements AWClint {
         if (StringUtils.isBlank(tCode)) {
             result = "无任务编码";
         } else {
-//            tList = ydService.queryDataList_FormData("FORM-AB7263D2A12F4E01A871656F0D995BC96PR1", UtilMap.map("selectField_lrncf4hk, radioField_lrnddfq6", tCode, "启用"));
-            tList = ydService.queryDataList_FormData("FORM-A25299893F614A6EAA672514D3A76BB0QDBF", UtilMap.map("selectField_lrncf4hk, radioField_lrnddfq6", tCode, "启用"));
+            tList = ydService.queryDataList_FormData(_matchFormUuid("APPROVE"), UtilMap.map("selectField_lrncf4hk, radioField_lrnddfq6", tCode, "启用"));
             tList = tList.stream().filter(item -> tCode.equals(item.get("selectField_lrncf4hk"))).collect(Collectors.toList());
             if (tList.size() == 0) {
                 result = "未配置交付物审批";
             } else {
-//                List<Map> pList = ydService.queryDataList_FormData("FORM-84EF78C7DBA047E58A8C8511106F91D5WNVI", UtilMap.map("textField_lqxtykce", pCode));
-                List<Map> pList = ydService.queryDataList_FormData("FORM-141E21DF183846028E21727CE43CD1C75CLZ", UtilMap.map("textField_lqxtykce", pCode));
+                List<Map> pList = ydService.queryDataList_FormData(_matchFormUuid("PROJECT"), UtilMap.map("textField_lqxtykce", pCode));
                 pList = pList.stream().filter(item -> pCode.equals(item.get("textField_lqxtykce"))).collect(Collectors.toList());
                 if (pList.size() == 0) {
                     result = "未匹配到项目主数据";
@@ -123,20 +148,17 @@ public class AWImplClient implements AWClint {
                 Map<String, String> extra = (Map) tbClient.idMapQuery(creatorId, "dingTalk-user", ddConf.getCorpId()).get(0).get("extra");
                 UtilMap.putAll(formData, UtilMap.map("textField_lr3dlwsa, textField_lr3er4qb", taskId, creatorId));
                 String instanceId = (String) ydClient.operateData(YDParam.builder()
-//                        .formUuid("FORM-FBC1A390B4C348089020C763938A6F54RUNY")
-                        .formUuid("FORM-812FD46AF391449A8F206EDB3221B38840UQ")
-//                        .processCode("TPROC--YU966T91PIDH4XDR82OJC8GVOP7Z19PODTXQL6")
-                        .processCode("TPROC--RJC66SC1NEFHXJ0H770K0CF4WN1K21HQ706RL5")
+                        .formUuid(_matchFormUuid("REVIEW"))
+                        .processCode(_matchFormUuid("REVIEW_PROCESS"))
                         .formDataJson(JSON.toJSONString(formData))
                         .userId(extra.get("userId"))
                         .build(), YDConf.FORM_OPERATION.start);
-//                result = "https://kabom7.aliwork.com/APP_H7WUJTKB448F9IBDC6C4/processDetail?procInsId=" + instanceId;
-                result = "https://yida.awinic.com/APP_R5EBUF2FPN3Y8DRF93M4/processDetail?procInsId=" + instanceId;
+                result = _matchFormUuid("DOMAIN") + ydConf.getAppType() + "/processDetail?procInsId=" + instanceId;
             }
         }
         log.info("交付物结果, {}", result);
         Map body = TBConf.assembleCustomFieldName(AWServer.TASK_APPROVE_LINK, result);
-        tbClient.updateTaskCustomField(taskId, creatorId, body);
+        tbClient.updateTaskCustomField(taskId, tbConf.getOperatorId(), body);
     }
 
     /**
@@ -148,7 +170,7 @@ public class AWImplClient implements AWClint {
         log.info("交付物审批回调, {}", data);
         String result = String.valueOf(data.get("approve"));
         String workFlowId = _getWorkFlowStatus(String.valueOf(data.get("projectId")), result);
-        tbClient.updateTaskFlowStatus(String.valueOf(data.get("taskId")), String.valueOf(data.get("creatorId")), workFlowId, String.valueOf(data.get("approve")));
+        tbClient.updateTaskFlowStatus(String.valueOf(data.get("taskId")), tbConf.getOperatorId(), workFlowId, String.valueOf(data.get("approve")));
     }
 
     @Autowired
@@ -180,6 +202,7 @@ public class AWImplClient implements AWClint {
     }
 
     // 匹配工作流名称, 获取ID
+    @Deprecated
     String _getWorkFlowStatus(String projectId, String workFlowStatusName) {
 
         List<Map> customFlowStatus = tbClient.queryProjectCustomFlowStatus(projectId, UtilMap.map("q", workFlowStatusName));
@@ -187,8 +210,27 @@ public class AWImplClient implements AWClint {
         return String.valueOf(customFlowStatus.get(0).get("id"));
     }
 
+    // 前置过滤 todo 提取方法
+    List<String> _getWorkFlowStatusList(String projectId, String... workFlowStatusNames) {
+        List<String> workFlowStatusList = new ArrayList<>();
+        for (String name : workFlowStatusNames) {
+            List<Map> customFlowStatus = tbClient.queryProjectCustomFlowStatus(projectId, UtilMap.map("q", name));
+            workFlowStatusList.addAll(customFlowStatus.stream().map(item -> UtilMap.getString(item, "id")).collect(Collectors.toList()));
+        }
+        return workFlowStatusList;
+    }
+
+    // 后置过滤 todo 提取方法
+    List<String> _getWorkFlowStatusList(String projectId, List<String> workFlowStatusNames) {
+        //List<String> names = Arrays.stream(workFlowStatusNames).collect(Collectors.toList());
+        List<Map> customFlowStatus = tbClient.queryProjectCustomFlowStatus(projectId, null);
+        List<Map> workFlowStatusList = customFlowStatus.stream().filter(item -> workFlowStatusNames.contains(item.get("name"))).collect(Collectors.toList());
+        return workFlowStatusList.stream().map(item -> UtilMap.getString(item, "id")).collect(Collectors.toList());
+    }
+
     /**
-     * 获取知识库附件传递到宜搭 [ppExt]
+     * 获取知识库附件传递到宜搭
+     * - ppExt -
      * 1. 宜搭附件传递 downloadUrl 和 name 即可实现在线预览
      * 2. 知识库绑定没有文件后缀, 宜搭识别目前仅能点击下载跳转预览, 添加统一docx后缀, 文档会自行区分
      */
@@ -216,10 +258,14 @@ public class AWImplClient implements AWClint {
         Map taskData = _getTaskFieldMap(taskId, AWServer.TASK_CODE, AWServer.TASK_CHECK_LINK, AWServer.TASK_ROLE, AWServer.TASK_STAGE, AWServer.TASK_CHECK_STATUS);
         String checkLink = UtilMap.getString(taskData, AWServer.TASK_CHECK_LINK);
         /// prd 预检项持续维护需要重新匹配, 任务号和主数据判定为非法, 无需重新刷新
-        if (isTask && (StringUtils.isNotBlank(checkLink) && !AWServer.TASK_TIPS.equals(checkLink))) {
+        if (isTask && (StringUtils.isNotBlank(checkLink) && !"未配置预检项".equals(checkLink))) {
             return UtilMap.map("result", "链接已加载");
         }
+        // prd 非未完成任务若是未配置预检项状态, 忽略更新
         Map rTask = UtilMap.getMap(taskData, "task");
+        if (isTask && !_getWorkFlowStatusList(UtilMap.getString(rTask, "projectId"), AWServer.WORKFLOW_INITIAL).contains(rTask.get("tfsId"))) {
+            return UtilMap.map("result", "任务已执行");
+        }
         String creatorId = UtilMap.getString(rTask, "creatorId");
         String tCode = UtilMap.getString(taskData, AWServer.TASK_CODE);
         String pCode = UtilMap.getString(rTask, "projectId");
@@ -231,23 +277,20 @@ public class AWImplClient implements AWClint {
             result = "无任务编码";
         } else {
             tList = ydService.queryFormData_all(YDParam.builder()
-//                    .formUuid("FORM-E6CB042D7929448888AE5E2B27631E57IVPM")
-                    .formUuid("FORM-1A5D4D7FBF88409B956EBE51F9342A6BKOLP")
+                    .formUuid(_matchFormUuid("CHECK"))
                     .searchFieldJson(JSON.toJSONString(UtilMap.map("selectField_lrncf4hk, radioField_lrnddfq6", tCode, "启用")))
                     .build());
             tList = tList.stream().filter(item -> tCode.equals(item.get("selectField_lrncf4hk"))).collect(Collectors.toList());
             if (tList.size() == 0) {
-                result = AWServer.TASK_TIPS;
+                result = "未配置预检项";
             } else {
-//                List<Map> pList = ydService.queryDataList_FormData("FORM-84EF78C7DBA047E58A8C8511106F91D5WNVI", UtilMap.map("textField_lqxtykce", pCode));
-                List<Map> pList = ydService.queryDataList_FormData("FORM-141E21DF183846028E21727CE43CD1C75CLZ", UtilMap.map("textField_lqxtykce", pCode));
+                List<Map> pList = ydService.queryDataList_FormData(_matchFormUuid("PROJECT"), UtilMap.map("textField_lqxtykce", pCode));
                 pList = pList.stream().filter(item -> pCode.equals(item.get("textField_lqxtykce"))).collect(Collectors.toList());
                 if (pList.size() == 0) {
                     result = "未匹配到项目主数据";
                 } else {
                     rProject = pList.get(0);
-//                    result = "https://kabom7.aliwork.com/APP_H7WUJTKB448F9IBDC6C4/workbench/FORM-7B63BB056145452F8BC0A2C52492DE00QVBH?taskId=" + taskId;
-                    result = "https://yida.awinic.com/APP_R5EBUF2FPN3Y8DRF93M4/workbench/FORM-6E2C0D1197264B8AA23EB3FECAE7344B00BN?taskId=" + taskId;
+                    result = _matchFormUuid("DOMAIN") + ydConf.getAppType() + "/workbench/" + _matchFormUuid("RECORD") + "?taskId=" + taskId;
                 }
             }
         }
@@ -255,12 +298,12 @@ public class AWImplClient implements AWClint {
         if (isTask) {
             if (!checkLink.equals(result)) {
                 Map body = TBConf.assembleCustomFieldName(AWServer.TASK_CHECK_LINK, result);
-                tbClient.updateTaskCustomField(taskId, creatorId, body);
+                tbClient.updateTaskCustomField(taskId, tbConf.getOperatorId(), body);
             }
             // prd 未配置预检项更新为已检查, 避免完成任务完成触发必填校验 [ppExt 避免重复写入, 重复写入TB会重复记录日志
-            if (AWServer.TASK_TIPS.equals(result) && !taskData.get(AWServer.TASK_CHECK_STATUS).equals("已检查")) {
+            if (!result.startsWith("http") && !taskData.get(AWServer.TASK_CHECK_STATUS).equals("已检查")) {
                 Map body = TBConf.assembleCustomFieldName(AWServer.TASK_CHECK_STATUS, "已检查");
-                tbClient.updateTaskCustomField(taskId, creatorId, body);
+                tbClient.updateTaskCustomField(taskId, tbConf.getOperatorId(), body);
             }
             return UtilMap.map("result", result);
         }
@@ -274,8 +317,7 @@ public class AWImplClient implements AWClint {
         formData.putAll(UtilMap.map("textField_lrndwu09, textField_lrndwu0a, textField_lrndwu0b, employeeField_lrndwu0e", rTask.get("content"), taskData.get(AWServer.TASK_STAGE), taskData.get(AWServer.TASK_ROLE), Arrays.asList(UtilMap.map("value, name", extra.get("userId"), extra.get("userId")))));
         // 返回检查项
         formData.put("tableField_lqxxgj4s", tList.stream().map(item -> {
-//            item.put("associationFormField_lrrsitxu", YDConf.associationForm("APP_H7WUJTKB448F9IBDC6C4", "FORM-7B63BB056145452F8BC0A2C52492DE00QVBH", UtilMap.getString(item, "instanceId"), UtilMap.getString(item, "textField_lrnd3h0r"), "", false));
-            item.put("associationFormField_lrrnem5r", YDConf.associationForm("APP_R5EBUF2FPN3Y8DRF93M4", "FORM-6E2C0D1197264B8AA23EB3FECAE7344B00BN", UtilMap.getString(item, "instanceId"), UtilMap.getString(item, "textField_lrnd3h0r"), "", false));
+            item.put("associationFormField_lrrnem5r", YDConf.associationForm(ydConf.getAppType(), _matchFormUuid("CHECK"), UtilMap.getString(item, "instanceId"), UtilMap.getString(item, "textField_lrnd3h0r"), "", false));
             return item;
         }).collect(Collectors.toList()));
         return formData;
@@ -289,12 +331,10 @@ public class AWImplClient implements AWClint {
 
         log.info("检查项回调, {}", data);
         Map body = TBConf.assembleCustomFieldName(AWServer.TASK_CHECK_STATUS, "已检查");
-        tbClient.updateTaskCustomField(String.valueOf(data.get("taskId")), String.valueOf(data.get("creatorId")), body);
-
-//        String result = "https://kabom7.aliwork.com/APP_H7WUJTKB448F9IBDC6C4/formDetail?formInstId=" + data.get("formInstId");
-        String result = "https://yida.awinic.com/APP_R5EBUF2FPN3Y8DRF93M4/formDetail?formInstId=" + data.get("formInstId");
+        tbClient.updateTaskCustomField(String.valueOf(data.get("taskId")), tbConf.getOperatorId(), body);
+        String result = _matchFormUuid("DOMAIN") + ydConf.getAppType() + "/formDetail?formInstId=" + data.get("formInstId");
         Map body2 = TBConf.assembleCustomFieldName(AWServer.TASK_CHECK_LINK, result);
-        tbClient.updateTaskCustomField(String.valueOf(data.get("taskId")), String.valueOf(data.get("creatorId")), body2);
+        tbClient.updateTaskCustomField(String.valueOf(data.get("taskId")), tbConf.getOperatorId(), body2);
     }
 
     /**
@@ -316,7 +356,8 @@ public class AWImplClient implements AWClint {
         if (StringUtils.isNotBlank(projectCode)) {
             ydParam.setSearchFieldJson(JSON.toJSONString(UtilMap.map("textField_le6o88w0", projectCode)));
         }
-        List<Map> mapBaseList = ydService.queryAllFormData(ydParam);
+        // prd 客户系统主数据, 是全量定时从mdmg更新, 因此不能增量
+        List<Map> mapBaseList = ydService.queryFormData_all(ydParam);
         if (StringUtils.isNotBlank(projectCode)) {
             mapBaseList = mapBaseList.stream().filter(item -> projectCode.equals(item.get("textField_le6o88w0"))).collect(Collectors.toList());
         }
@@ -325,66 +366,49 @@ public class AWImplClient implements AWClint {
 
         // 查询项目角色
         YDParam ydParam1 = YDParam.builder()
-//                .formUuid("FORM-5BE21392886E46DF955D1EBC100ADA429NON")
-                .formUuid("FORM-3C7396A12ADB48A8833EBD90089C93833R21")
+                .formUuid(_matchFormUuid("ROLE"))
                 .build();
         List<Map> mapRool = (List<Map>) ydClient.queryData(ydParam1, YDConf.FORM_QUERY.retrieve_list).getData();
 
         // 匹配数据组件ID
-        for (Map item : mapBaseList) {
-            Map baseFormData = (Map) item.get("formData");
-
+        for (Map baseFormData : mapBaseList) {
             // 项目主数据
             formData = new HashMap();
             formData.put("textField_lqxtykcd", baseFormData.get("textField_lo2c1f0l"));      //项目名称
             formData.put("textField_lrj7vnxb", baseFormData.get("textField_le6o88w0"));      //项目号
             formData.put("textField_lrj7vnxc", baseFormData.get("textField_le6o88w1"));      //项目简称
             formData.put("textareaField_lrj7vnxl", baseFormData.get("textField_le6o88w2"));  //项目描述
-            formData.put("textField_lrj7vnxf", item.get("formInstanceId"));                  //项目实例ID
-
+            formData.put("textField_lrj7vnxf", baseFormData.get("formInstanceId"));          //项目实例ID
             // 项目角色详情
             List<Map> details = new ArrayList<>();
-            mapRool.forEach(rool -> {
-                Map roolFormData = (Map) rool.get("formData");
-                //创建详情的角色名称和成员组件Map
-                Map row = new HashMap();
-//                Object roolItems = baseFormData.get(roolFormData.get("textField_lrj7t5mn"));
-//                Object projectRool = roolFormData.get("textField_lqxu439g");
-                Object roolItems = baseFormData.get(roolFormData.get("textField_lr7bgi76"));
-                Object projectRool = roolFormData.get("textField_lqxu439g");
-
-                if (roolItems != null && projectRool != null) {
-//                    row.put("employeeField_lqxtykch", baseFormData.get(roolFormData.get("textField_lrj7t5mn")));
-//                    row.put("selectField_lqxu6bgf", roolFormData.get("textField_lqxu439g"));
-                    row.put("employeeField_lqxtykch", baseFormData.get(roolFormData.get("textField_lr7bgi76")));
-                    row.put("selectField_lqxu6bgf", roolFormData.get("textField_lqxu439g"));
-                    details.add(row);
+            mapRool.forEach(root -> {
+                Map rootFormData = (Map) root.get("formData");
+                // 创建详情的角色名称和成员组件Map
+                Object rootItems = baseFormData.get(rootFormData.get("textField_lr7bgi76"));
+                Object projectRoot = rootFormData.get("textField_lqxu439g");
+                if (rootItems != null && projectRoot != null) {
+                    details.add(UtilMap.map("employeeField_lqxtykch, selectField_lqxu6bgf", rootItems, projectRoot));
                 }
             });
             formData.put("tableField_lqxtykcf", details);
 
-            //通过项目号获取项目是否已存在
-            YDParam ydParam2 = YDParam.builder()
-//                    .formUuid("FORM-84EF78C7DBA047E58A8C8511106F91D5WNVI")
-                    .formUuid("FORM-141E21DF183846028E21727CE43CD1C75CLZ")
-                    .searchFieldJson(JSON.toJSONString(UtilMap.map("textField_lrj7vnxb", baseFormData.get("textField_le6o88w0"))))
-                    .build();
-            List<Map> projectMaps = (List<Map>) ydClient.queryData(ydParam2, YDConf.FORM_QUERY.retrieve_search_form).getData();
-            projectMaps = projectMaps.stream().filter(sub -> baseFormData.get("textField_le6o88w0").equals(item.get("textField_lrj7vnxb"))).collect(Collectors.toList());
+            // 通过项目号获取项目是否已存在
+            List<Map> projectMaps = ydService.queryDataList_FormData(_matchFormUuid("PROJECT"), UtilMap.map("textField_lrj7vnxb", baseFormData.get("textField_le6o88w0")));
+            projectMaps = projectMaps.stream().filter(sub -> baseFormData.get("textField_le6o88w0").equals(sub.get("textField_lrj7vnxb"))).collect(Collectors.toList());
 
-            YDParam ydParam3 = YDParam.builder()
-//                    .formUuid("FORM-84EF78C7DBA047E58A8C8511106F91D5WNVI")
-                    .formUuid("FORM-141E21DF183846028E21727CE43CD1C75CLZ")
+            YDParam ydParam2 = YDParam.builder()
+                    .formUuid(_matchFormUuid("PROJECT"))
                     .formDataJson(JSON.toJSONString(formData))
                     .updateFormDataJson(JSON.toJSONString(formData))
+                    .useLatestVersion(true)
                     .build();
             if (projectMaps.size() > 0) {
-                ydParam3.setFormInstanceId(String.valueOf(projectMaps.get(0).get("formInstanceId")));
-                ydClient.operateData(ydParam3, YDConf.FORM_OPERATION.update);
+                ydParam2.setFormInstanceId(String.valueOf(projectMaps.get(0).get("instanceId")));
+                ydClient.operateData(ydParam2, YDConf.FORM_OPERATION.update);
                 // 保留tb项目号, 避免冲重复通过模板参加项目
                 formData.put("textField_lqxtykce", UtilMap.getMap(projectMaps.get(0), "formData").get("textField_lqxtykce"));
             } else {
-                String formInstId = (String) ydClient.operateData(ydParam3, YDConf.FORM_OPERATION.create);
+                String formInstId = (String) ydClient.operateData(ydParam2, YDConf.FORM_OPERATION.create);
                 formData.put("formInstanceId", formInstId);
             }
             log.info("同步项目主数据", projectCode);
@@ -459,36 +483,44 @@ public class AWImplClient implements AWClint {
     @Override
     public void updateProjectRole(String projectId) {
 
-        // todo 1000递归查询
-        // 项目档案
-//        List<Map> pList = ydService.queryDataList_FormData("FORM-84EF78C7DBA047E58A8C8511106F91D5WNVI", UtilMap.map("textField_lqxtykce", projectId));
-        List<Map> pList = ydService.queryDataList_FormData("FORM-141E21DF183846028E21727CE43CD1C75CLZ", UtilMap.map("textField_lqxtykce", projectId));
+        // 项目档案 [tb项目号查询, 避免模糊匹配]
+        List<Map> pList = ydService.queryDataList_FormData(_matchFormUuid("PROJECT"), UtilMap.map("textField_lqxtykce", projectId));
         McException.assertAccessException(pList.isEmpty(), "未匹配到项目主数据");
         List<Map> rList = (List<Map>) pList.get(0).get("tableField_lqxtykcf");
 
         // 任务编码字段ID
         List<Map> customField = tbClient.queryProjectCustomField(projectId, null);
-
-        List<Map> taskList = tbClient.queryProjectTaskList(projectId, null);
-        for (Map task : taskList) {
-
-            // 获取资源名称对应的项目角色
-            Optional optional = customField.stream().filter(item -> AWServer.TASK_ROLE.equals(item.get("name"))).findAny();
-            if (!optional.isPresent()) {
-                continue;
-            }
-            List<Map> customfields = (List<Map>) task.get("customfields");
-            String roleName = TBConf.getTaskFieldValue_First(customfields, UtilMap.getString((Map) optional.get(), "id"));
-            // 获取角色在项目主数据对应成员
-            optional = rList.stream().filter(item -> roleName.equals(item.get("selectField_lqxu6bgf"))).findAny();
-            if (!optional.isPresent()) {
-                continue;
-            }
-            List<String> roleIds = (List<String>) UtilMap.getList((Map) optional.get(), "employeeField_lqxtykch_id");
-            if (roleIds.size() == 1) {
-                tbClient.updateTaskExecutor(UtilMap.getString(task, "id"), tbConf.getOperatorId(), _convertUserId(roleIds.get(0), false), false, false);
+        // prd 非未完成任务, 不执行人员匹配更新
+        List<String> workFlowStatusList = _getWorkFlowStatusList(projectId, AWServer.WORKFLOW_INITIAL);
+
+        //List<Map> taskList = tbClient.queryProjectTaskList(projectId, UtilMap.map("pageSize", 10), null);
+        tbClient.queryProjectTaskList(projectId, null, taskList -> {
+            for (Map task : taskList) {
+                if (!workFlowStatusList.contains(task.get("tfsId"))) {
+                    continue;
+                }
+                // 获取资源名称对应的项目角色
+                Optional optional = customField.stream().filter(item -> AWServer.TASK_ROLE.equals(item.get("name"))).findAny();
+                if (!optional.isPresent()) {
+                    continue;
+                }
+                List<Map> customfields = (List<Map>) task.get("customfields");
+                String roleName = TBConf.getTaskFieldValue_First(customfields, UtilMap.getString((Map) optional.get(), "id"));
+                // 获取角色在项目主数据对应成员
+                optional = rList.stream().filter(item -> roleName.equals(item.get("selectField_lqxu6bgf"))).findAny();
+                if (!optional.isPresent()) {
+                    continue;
+                }
+                List<String> roleIds = (List<String>) UtilMap.getList((Map) optional.get(), "employeeField_lqxtykch_id");
+                if (roleIds.size() == 1) {
+                    String tbUserId = _convertUserId(roleIds.get(0), false);
+                    if (StringUtils.isNotBlank(tbUserId)) {
+                        tbClient.updateTaskExecutor(UtilMap.getString(task, "id"), tbConf.getOperatorId(), tbUserId, false, false);
+                    }
+                }
             }
-        }
+            return true;
+        });
     }
 
     // TB与宜搭userId转换 todo 提取 tbService
@@ -496,6 +528,7 @@ public class AWImplClient implements AWClint {
         List<Map> tbMap = tbClient.idMapQuery(userId, isTBID);
         // 过滤未匹配人员信息 [ppExt: TB人员未匹配, 不执行修改也无报错]
         if (tbMap.isEmpty()) {
+            log.warn("TB与宜搭userId转换为空, userId = {}, tbID = {}", userId, isTBID);
             return "";
         }
         if (!isTBID) {
@@ -513,5 +546,88 @@ public class AWImplClient implements AWClint {
                 .filter(id -> StringUtils.isNotBlank(id))
                 .collect(Collectors.toList());
     }
+
+    /**
+     * 同步预检项 [全量同步, 忽略任务号为空记录]
+     */
+    @Override
+    public void syncCheckList(YDParam srcParam, Map<String, ?> compIds, String taskCompId, String codeCompId, String checkType, String associationCompId) {
+
+        String curFormUuid = "FORM-1A5D4D7FBF88409B956EBE51F9342A6BKOLP";
+        // 数据来源表
+        List<Map> srcList = ydService.queryFormData_all(srcParam);
+        // 当前记录表
+        List<Map> curList = ydService.queryFormData_all(YDParam.builder()
+                .formUuid(curFormUuid)
+                .searchFieldJson(JSON.toJSONString(UtilMap.map("selectField_lrnd3h0s", checkType)))
+                .build());
+
+        for (Map item : srcList) {
+            if (StringUtils.isBlank(UtilMap.getString(item, taskCompId))) {
+                continue;
+            }
+            Map formData = UtilMap.map(associationCompId, YDConf.associationForm(srcParam.getAppType(), srcParam.getFormUuid(), UtilMap.getString(item, "formInstanceId"), UtilMap.getString(item, codeCompId), "", false));
+            formData.put("radioField_lrnddfq6", "启用");
+            formData.put("selectField_lrnd3h0s", checkType);
+            for (String compId : compIds.keySet()) {
+                formData.put(compId, item.get(compIds.get(compId)));
+            }
+            YDConf.FORM_OPERATION operate = YDConf.FORM_OPERATION.create;
+            YDParam ydParam = YDParam.builder()
+                    .formUuid(curFormUuid)
+                    .formDataJson(JSON.toJSONString(formData))
+                    .updateFormDataJson(JSON.toJSONString(formData))
+                    .useLatestVersion(true)
+                    .build();
+            // 避免循坏内查询, 也避免了模糊匹配
+            Optional optional = curList.stream().filter(cur -> cur.get("textField_lrnd3h0r").equals(item.get(codeCompId))).findAny();
+            if (optional.isPresent()) {
+                ydParam.setFormInstanceId(UtilMap.getString((Map) optional.get(), "formInstanceId"));
+                operate = YDConf.FORM_OPERATION.update;
+            }
+            ydClient.operateData(ydParam, operate);
+        }
+    }
+
+    @Override
+    public void syncCheckList(int type) {
+
+        switch (type) {
+            case 0:
+                // 经验库
+                YDParam ydParam1 = YDParam.builder()
+                        .appType("APP_D4NPOH9J3KCG5VE1RVN6")
+                        .systemToken("6J8668A1B59FA7SAFTAF89PTKKGP2HY3FP3OLV1")
+                        .formUuid("FORM-D47CCA076DA54F969DF7442D81E4B5A8PC6Q")
+                        .build();
+                // 任务号, 描述, ID(标题)
+                Map<String, ?> compIds1 = UtilMap.map("selectField_lrncf4hk, textField_lrrnqz7w, textField_lrnd3h0r", "selectField_ls9yctsd", "textareaField_lo5eakcv", "serialNumberField_lo5dmyfb");
+                syncCheckList(ydParam1, compIds1, "selectField_ls9yctsd", "serialNumberField_lo5dmyfb", "经验库", "associationFormField_lrrn5csf");
+                break;
+
+            case 1:
+                // 技术评审要素表
+                YDParam ydParam2 = YDParam.builder()
+                        .appType("APP_NOSSCZQ8FFZKHDQOIIDA")
+                        .systemToken("UM6660D1BFTFLFAP7NPJDBJEEAB737FAR1SOLD4")
+                        .formUuid("FORM-B40420AFCDB84AD69FE78D82D6D5CFD2C2D2")
+                        .build();
+                // 任务号, 描述, ID(标题)
+                Map<String, ?> compIds2 = UtilMap.map("selectField_lrncf4hk, textField_lrrnqz7w, textField_lrnd3h0r", "selectField_bclg9y5", "textField_k1e08ji", "textField_96ikaoh");
+                syncCheckList(ydParam2, compIds2, "selectField_bclg9y5", "textField_96ikaoh", "技术评审要素表", "associationFormField_lrrn5csg");
+                break;
+
+            case 2:
+                // TR评审要素表
+                YDParam ydParam3 = YDParam.builder()
+                        .formUuid("FORM-5436DC75BC8347D498DFF2617925BA70O066")
+                        .build();
+                // 任务号, 描述, ID(标题)
+                Map<String, ?> compIds3 = UtilMap.map("selectField_lrncf4hk, textField_lrrnqz7w, textField_lrnd3h0r", "selectField_4gwjfa5", "textField_lryetn3g", "textField_9x1yps6");
+                syncCheckList(ydParam3, compIds3, "selectField_4gwjfa5", "textField_9x1yps6", "TR评审要素表", "associationFormField_lrrn5csa");
+                break;
+        }
+    }
 }
 
+

+ 1 - 1
mjava-aiwei/src/main/resources/application-dev.yml

@@ -57,7 +57,7 @@ dingtalk:
   token:
   operator: ""   # OA管理员账号
 
-# aliwork
+## aliwork
 #aliwork:
 #  appType: "APP_H7WUJTKB448F9IBDC6C4"
 #  systemToken: "DHA66081DN6GRFNC6GTRW5NIJS082ZF0UN9PLLF"

+ 1 - 1
mjava-fengkaili/src/main/java/com/malk/fengkaili/schedule/FKLScheduleTask.java

@@ -23,7 +23,7 @@ public class FKLScheduleTask {
     /**
      * 每天凌晨4点同步
      */
-    @Scheduled(cron = "* * 4 * * ? ")
+    @Scheduled(cron = "0 0 4 * * ? ")
     public void syncDingTalkFailedList() {
         try {
             fklService.syncUserInfo();

+ 2 - 3
mjava-hake/src/main/java/com/malk/hake/controller/HKController.java

@@ -78,11 +78,10 @@ public class HKController {
     }
 
     @PostMapping("monitor/sync")
-    McR pay() {
+    McR pay(String code) {
 
         log.info("手动触发, 拉取Monitor同步");
-//        hkClient.syncMonitor("FKSQ");
-        hkClient.syncMonitor("YFKSQ");
+        hkClient.syncMonitor(code);
         return McR.success();
     }
 

+ 2 - 2
mjava-hake/src/main/java/com/malk/hake/schedule/HKScheduleTask.java

@@ -49,7 +49,7 @@ public class HKScheduleTask {
     @Scheduled(cron = "0 0 1 * * ? ")
     public void timer_3() {
         try {
-            hkClient.syncMonitor("FKSQ");
+//            hkClient.syncMonitor("FKSQ");
         } catch (Exception e) {
             // 记录错误信息
             e.printStackTrace();
@@ -62,7 +62,7 @@ public class HKScheduleTask {
     @Scheduled(cron = "0 0 2 * * ? ")
     public void timer_4() {
         try {
-            hkClient.syncMonitor("YFKSQ");
+//            hkClient.syncMonitor("YFKSQ");
         } catch (Exception e) {
             // 记录错误信息
             e.printStackTrace();

+ 3 - 3
mjava-hake/src/main/java/com/malk/hake/service/impl/HKImplClient.java

@@ -38,7 +38,6 @@ public class HKImplClient implements HKClient {
         return "http://116.228.113.106:10001/api/public" + path;
     }
 
-
     private Map MATE;
 
     private Map _getMeta() {
@@ -58,7 +57,8 @@ public class HKImplClient implements HKClient {
         Map formData = UtilMap.empty();
         for (String key : component.keySet()) {
             if (key.startsWith("employeeField_")) {
-                formData.put(key, Arrays.asList(data.get(component.get(key))));
+                // getString, 避免 [null] 数据类型
+                formData.put(key, Arrays.asList(UtilMap.getString(data, (String) component.get(key))));
             } else if (key.startsWith("tableField_")) {
                 List<Map> rows = (List<Map>) data.get("rows");
                 List<Map> details = new ArrayList<>();
@@ -131,7 +131,7 @@ public class HKImplClient implements HKClient {
                 .formInstanceId(String.valueOf(instanceId))
                 .build(), YDConf.FORM_QUERY.retrieve_id).getFormData();
         String url = "https://pxi03f.aliwork.com/APP_QWUVLI1R6XYUXWAOPF6O/processDetail?procInsId=" + instanceId;
-        return UtilMap.map("ddProcessId, dtNumber, Url", instanceId, form.get(meta.get(code + "_RC")), url);
+        return UtilMap.map("ddProcessId, dtNumber, dtUrl", instanceId, form.get(meta.get(code + "_RC")), url);
     }
 
     @Autowired

+ 3 - 1
mjava-hake/src/main/resources/static/json/form.json

@@ -22,6 +22,7 @@
         "textField_lnmyiqaw": "partName",
         "numberField_lnmyiqax": "quantity",
         "textField_lnmyiqaz": "currency",
+        "textField_lsts7vew": "unit",
         "numberField_lnmyiqb1": "exchangeRate",
         "numberField_lnmyiqb2": "priceInCompanyCurrencyExTax",
         "numberField_lnmyiqb3": "priceInTax",
@@ -220,7 +221,7 @@
         "numberField_lnmzeuoq": "discount"
       },
       "textField_ls3ddkib": "supplierAgentDtId",
-      "textField_ls3ddkib": "employeeField_ls3egxx6",
+      "employeeField_ls3egxx6": "supplierAgentDtId",
       "radioField_ls3ddkie": "status",
       "numberField_ls3ddkif": "payed"
     }
@@ -299,6 +300,7 @@
         "textField_lnmyiqaw": "partName",
         "numberField_lnmyiqax": "quantity",
         "textField_lnmyiqaz": "currency",
+        "textField_lsts7vew": "unit",
         "numberField_lnmyiqb1": "exchangeRate",
         "numberField_lnmyiqb2": "priceInCompanyCurrencyExTax",
         "numberField_lnmyiqb3": "priceInTax",

+ 1 - 1
mjava-hangshi/src/main/java/com/malk/hangshi/schedule/HSScheduleTask.java

@@ -23,7 +23,7 @@ public class HSScheduleTask {
     /**
      * 每天凌晨4点同步
      */
-    @Scheduled(cron = "* * 4 * * ? ")
+    @Scheduled(cron = "0 0 4 * * ? ")
     public void syncDingTalkFailedList() {
         try {
             hsService.getDeptInfo(true);

+ 30 - 16
mjava-luyi/src/main/java/com/malk/luyi/controller/LYController.java

@@ -5,6 +5,7 @@ package com.malk.luyi.controller;
  */
 
 import com.alibaba.fastjson.JSON;
+import com.malk.delegate.McDelegate;
 import com.malk.server.aliwork.YDConf;
 import com.malk.server.aliwork.YDParam;
 import com.malk.server.common.McException;
@@ -113,6 +114,9 @@ public class LYController {
         return McR.success(images);
     }
 
+    @Autowired
+    private McDelegate mcDelegate;
+
     /**
      * 客户关联渠道
      */
@@ -123,22 +127,23 @@ public class LYController {
         Map data = UtilServlet.getParamMap(request);
         log.info("细胞查询, {}", data);
 
-        if ("否".equals(data.get("type"))) {
-            return McR.success();
-        }
-        Thread.sleep(3000); // todo: 公共延迟方法
-        List<Map> dataList = (List<Map>) ydClient.queryData(YDParam.builder()
-                .formUuid("FORM-6YA66WB1BATD2ZPWA2Z2S813SFFC3EGRBHYLLH")
-                .searchFieldJson(JSON.toJSONString(UtilMap.map("textField_lozlyqpb", data.get("code"))))
-                .build(), YDConf.FORM_QUERY.retrieve_search_form).getData();
-        if (dataList.size() == 1) {
-            Map formData = (Map) dataList.get(0).get("formData");
-            String title = String.valueOf(formData.get("textField_llyhc8ca"));
-            List<Map> associations = YDConf.associationForm("APP_I45JU7MQMRRVZ472GS1U", "FORM-6YA66WB1BATD2ZPWA2Z2S813SFFC3EGRBHYLLH", String.valueOf(dataList.get(0).get("formInstanceId")), title, title, false);
-            ydClient.operateData(YDParam.builder()
-                    .formInstanceId(String.valueOf(data.get("instanceId")))
-                    .updateFormDataJson(JSON.toJSONString(UtilMap.map("textField_llkbx3ob, associationFormField_lm4hoevr, textField_lm4hoevs", formData.get("serialNumberField_llyhc8ck"), associations, title)))
-                    .build(), YDConf.FORM_OPERATION.update);
+        if ("是".equals(data.get("type"))) {
+            mcDelegate.setTimeout(() -> {
+
+                List<Map> dataList = (List<Map>) ydClient.queryData(YDParam.builder()
+                        .formUuid("FORM-6YA66WB1BATD2ZPWA2Z2S813SFFC3EGRBHYLLH")
+                        .searchFieldJson(JSON.toJSONString(UtilMap.map("textField_lozlyqpb", data.get("code"))))
+                        .build(), YDConf.FORM_QUERY.retrieve_search_form).getData();
+                if (dataList.size() == 1) {
+                    Map formData = (Map) dataList.get(0).get("formData");
+                    String title = String.valueOf(formData.get("textField_llyhc8ca"));
+                    List<Map> associations = YDConf.associationForm("APP_I45JU7MQMRRVZ472GS1U", "FORM-6YA66WB1BATD2ZPWA2Z2S813SFFC3EGRBHYLLH", String.valueOf(dataList.get(0).get("formInstanceId")), title, title, false);
+                    ydClient.operateData(YDParam.builder()
+                            .formInstanceId(String.valueOf(data.get("instanceId")))
+                            .updateFormDataJson(JSON.toJSONString(UtilMap.map("textField_llkbx3ob, associationFormField_lm4hoevr, textField_lm4hoevs", formData.get("serialNumberField_llyhc8ck"), associations, title)))
+                            .build(), YDConf.FORM_OPERATION.update);
+                }
+            }, 5000);
         }
         return McR.success();
     }
@@ -146,6 +151,15 @@ public class LYController {
     @PostMapping("test")
     McR test() {
 
+        ydClient.queryData(YDParam.builder()
+                .formUuid("FORM-MFA66S91KKJDA2708OHTW6RBOJRK3SVWO7KLL1")
+                .searchFieldJson(JSON.toJSONString(UtilMap.map("textField_llk8hw32", "张少文")))
+                .build(), YDConf.FORM_QUERY.retrieve_search_form);
+
+//        ydClient.queryData(YDParam.builder()
+//                .formUuid("FORM-6YA66WB1BATD2ZPWA2Z2S813SFFC3EGRBHYLLH")
+//                .searchFieldJson(JSON.toJSONString(UtilMap.map("serialNumberField_llyhc8ck", "QD-20240130-0009")))
+//                .build(), YDConf.FORM_QUERY.retrieve_search_form);
         return McR.success();
     }
 }

+ 3 - 0
mjava/src/main/java/com/malk/server/aliwork/YDConf.java

@@ -98,6 +98,9 @@ public class YDConf {
 
     /**
      * 读取关联表单: ppExt 两层解析后才是List, 若是赋值取值转一层, 宜搭也可进行写入
+     * - 赋值说明 -
+     * 若是同一个应用,appType与formUuid为空(不指定下formUuid可为错误,但appType只能为空),点击页面链接会自动匹配;
+     * 若是跨应用实例,则不能通过导入,需要通过接口指定appType
      */
     public List<Map> associationForm(String associations) {
         if (UtilString.isBlankCompatNull(associations)) {

+ 6 - 0
mjava/src/main/java/com/malk/server/aliwork/YDParam.java

@@ -50,6 +50,12 @@ public class YDParam extends BaseDto {
     // 流程暂不支持排序
     private String dynamicOrder;
 
+    // 修改开始时间, ppExt: 需要同时传递开始和就结束才会生效; 其次日期格式yyyy-MM-dd, 但默认是0点, 结束日期j建议加1
+    private String modifiedFromTimeGMT;
+
+    // 修改结束时间, ppExt: 需要同时传递开始和就结束才会生效; 其次日期格式yyyy-MM-dd, 但默认是0点, 结束日期j建议加1
+    private String modifiedToTimeGMT;
+
     @NotNull(message = "实例ID不能为空", groups = {Update.class, Delete.class, Retrieve_FormInstId.class})
     private String formInstId;
 

+ 4 - 0
mjava/src/main/java/com/malk/server/teambition/TBR.java

@@ -24,6 +24,10 @@ public class TBR<T> extends VenR {
     // ppExt: 204为重复修改或tb设置了不允许修改规则
     private final static String NOR_CODE = "204";
 
+    private String nextPageToken;
+
+    private long totalSize;
+
     /**
      * 断言错误信息
      */

+ 1 - 1
mjava/src/main/java/com/malk/service/aliwork/YDService.java

@@ -44,7 +44,7 @@ public interface YDService {
     // todo: 宜搭大数据量处理会有异常, 可结合排序, 或失败记录进行处理 (避免更新后, 数据重新查询排序导致未全量同步)
     List<Map> queryFormData_all(YDParam YDParam);
 
-    // ppExt: 查询100后再进分页, 且转为formData内数据, todo Process待完成
+    // ppExt: 查询100后再进分页, 且转为formData内数据, todo Process待完成 [bug]
     List<Map> queryFormData_all_advance(YDParam ydParam, YDConf.FORM_QUERY type);
 
     /**

+ 14 - 2
mjava/src/main/java/com/malk/service/teambition/TBClient.java

@@ -118,7 +118,7 @@ public interface TBClient {
      *
      * @apiNote https://open.teambition.com/docs/apis/6321c6d1912d20d3b5a49ec1
      */
-    List<Map> queryProjectTaskList(String projectId, Map param);
+    List<Map> queryProjectTaskList(String projectId, Map param, QueryAll lambda);
 
     /**
      * 更新任务截止时间
@@ -167,7 +167,7 @@ public interface TBClient {
     /**
      * 搜索项目工作流状态 [ppExt: 注意不同任务类型名称唯一性, 如通用已完成不要使用]
      *
-     * @apiNote https://open.teambition.com/api/v3/project/{projectId}/taskflowstatus/search
+     * @apiNote https://open.teambition.com/docs/apis/6321c6d1912d20d3b5a4a142
      */
     List<Map> queryProjectCustomFlowStatus(String projectId, Map body);
 
@@ -177,4 +177,16 @@ public interface TBClient {
      * @apiNote https://open.teambition.com/docs/apis/6321c6d1912d20d3b5a49fc3
      */
     List<Map> queryProjectCustomFlow(String projectId, Map body);
+
+    /**
+     * 查询全部数据 [函数回调]
+     * - ppExt -
+     * 1. 若只需查询单页数据, lambda 传入 null 即可
+     * 2. 在回调内独立处理每批数据场景, 若是需要等待全部数据查询完再处理场景, 可以定义集合接收
+     * 2. 若是在回调内已拿到了符合预期的数据, 可返回 null, 触发递归出口 [布尔值 isAll 状态]
+     */
+    @FunctionalInterface
+    interface QueryAll {
+        boolean dataList(List<Map> list);
+    }
 }

+ 3 - 0
mjava/src/main/java/com/malk/service/teambition/TBService.java

@@ -8,15 +8,18 @@ public interface TBService {
     /**
      * 查询操作人在tb的userId
      */
+    @Deprecated
     List<String> convertUserIdWithSearch(String search);
 
     /**
      * 钉钉用户唯一键转同步用户ID
      */
+    @Deprecated
     List<String> convertUserIdWithSearch_bulk(Map<String, Object> data);
 
     /**
      * 更新创建项目: 宜搭创建有延迟
      */
+    @Deprecated
     void updateProject_YD_TB(Map project, String userName);
 }

+ 14 - 2
mjava/src/main/java/com/malk/service/teambition/impl/TBClientImpl.java

@@ -1,5 +1,6 @@
 package com.malk.service.teambition.impl;
 
+import cn.hutool.core.util.ObjectUtil;
 import com.auth0.jwt.algorithms.Algorithm;
 import com.malk.server.dingtalk.DDConf;
 import com.malk.server.teambition.TBConf;
@@ -195,10 +196,21 @@ public class TBClientImpl implements TBClient {
     }
 
     @Override
-    public List<Map> queryProjectTaskList(String projectId, Map param) {
+    public List<Map> queryProjectTaskList(String projectId, Map param, QueryAll lambda) {
         param = UtilMap.put(param, "pageSize", TBConf.PAGE_SIZE_LIMIT);
         TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/v3/project/" + projectId + "/task/query", initHeaderToken(), param, TBR.class);
-        return (List<Map>) tbr.getResult();
+        List<Map> dataList = (List<Map>) tbr.getResult();
+        if (ObjectUtil.isNotNull(lambda)) {
+            boolean isAll = lambda.dataList(dataList);
+            if (!isAll) {
+                return dataList;
+            }
+            if (StringUtils.isNotBlank(tbr.getNextPageToken())) {
+                param.put("pageToken", tbr.getNextPageToken());
+                queryProjectTaskList(projectId, param, lambda);
+            }
+        }
+        return dataList;
     }
 
     @Override

+ 13 - 1
mjava/src/main/java/com/malk/utils/UtilMap.java

@@ -158,7 +158,7 @@ public abstract class UtilMap {
     }
 
     /**
-     * 赋值 [为空赋值默认值]
+     * 赋值 [原值为空赋值默认值]
      */
     public static Map put(Map data, String key, Object defaultValue) {
         data = empty(data);
@@ -170,6 +170,18 @@ public abstract class UtilMap {
         return data;
     }
 
+    /**
+     * 赋值 [赋值为空赋值默认值]
+     */
+    public static Map put(Map data, String key, Object value, Object defaultValue) {
+        data = empty(data);
+        if (ObjectUtil.isNull(value)) {
+            value = defaultValue;
+        }
+        data.put(key, value);
+        return data;
+    }
+
     /************* 取值 ************/
 
     /**