Procházet zdrojové kódy

Merge remote-tracking branch 'origin/master'

lfx před 3 týdny
rodič
revize
d6a5b89e5b
25 změnil soubory, kde provedl 5764 přidání a 37 odebrání
  1. 8 0
      .idea/.gitignore
  2. 18 0
      .idea/compiler.xml
  3. 6 0
      .idea/encodings.xml
  4. 35 0
      .idea/jarRepositories.xml
  5. 12 0
      .idea/misc.xml
  6. 6 0
      .idea/vcs.xml
  7. 8 1
      src/main/java/com/malk/eastar/conf/EastarParam.java
  8. 230 0
      src/main/java/com/malk/eastar/controller/AitableController.java
  9. 63 0
      src/main/java/com/malk/eastar/controller/EastarDdController.java
  10. 2 1
      src/main/java/com/malk/eastar/controller/EastarTbController.java
  11. 62 0
      src/main/java/com/malk/eastar/controller/EastarYidaController.java
  12. 55 0
      src/main/java/com/malk/eastar/model/AITableParam.java
  13. 49 0
      src/main/java/com/malk/eastar/model/AITableResult.java
  14. 311 24
      src/main/java/com/malk/eastar/schedule/ScheduleTask.java
  15. 1364 0
      src/main/java/com/malk/eastar/schedule/ScheduleTaskNew.java
  16. 49 0
      src/main/java/com/malk/eastar/service/AitableService.java
  17. 56 0
      src/main/java/com/malk/eastar/service/DDCoreClient.java
  18. 47 0
      src/main/java/com/malk/eastar/service/MDTableClient.java
  19. 161 0
      src/main/java/com/malk/eastar/service/YidaService.java
  20. 488 0
      src/main/java/com/malk/eastar/service/impl/AitableServiceImpl.java
  21. 97 0
      src/main/java/com/malk/eastar/service/impl/DDCoreClientImpl.java
  22. 138 10
      src/main/java/com/malk/eastar/service/impl/EastarTbServiceImpl.java
  23. 59 0
      src/main/java/com/malk/eastar/service/impl/MDTableClientImpl.java
  24. 2439 0
      src/main/java/com/malk/eastar/service/impl/YidaServiceImpl.java
  25. 1 1
      src/test/java/TbTest.java

+ 8 - 0
.idea/.gitignore

@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml

+ 18 - 0
.idea/compiler.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="CompilerConfiguration">
+    <annotationProcessing>
+      <profile name="Maven default annotation processors profile" enabled="true">
+        <sourceOutputDir name="target/generated-sources/annotations" />
+        <sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
+        <outputRelativeToContentRoot value="true" />
+        <module name="ltc-eastar" />
+      </profile>
+    </annotationProcessing>
+  </component>
+  <component name="JavacSettings">
+    <option name="ADDITIONAL_OPTIONS_OVERRIDE">
+      <module name="ltc-eastar" options="-parameters" />
+    </option>
+  </component>
+</project>

+ 6 - 0
.idea/encodings.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Encoding">
+    <file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
+  </component>
+</project>

+ 35 - 0
.idea/jarRepositories.xml

@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="RemoteRepositoriesConfiguration">
+    <remote-repository>
+      <option name="id" value="central" />
+      <option name="name" value="central" />
+      <option name="url" value="https://maven.aliyun.com/nexus/content/groups/public" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="central" />
+      <option name="name" value="Central Repository" />
+      <option name="url" value="https://repo.maven.apache.org/maven2" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="central" />
+      <option name="name" value="Maven Central repository" />
+      <option name="url" value="https://repo1.maven.org/maven2" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="jboss.community" />
+      <option name="name" value="JBoss Community repository" />
+      <option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="repo-hfvom" />
+      <option name="name" value="repo-hfvom" />
+      <option name="url" value="https://packages.aliyun.com/68552ca333ca8867a43507dd/maven/repo-hfvom" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="snapshots" />
+      <option name="name" value="snapshots" />
+      <option name="url" value="https://maven.aliyun.com/nexus/content/groups/public" />
+    </remote-repository>
+  </component>
+</project>

+ 12 - 0
.idea/misc.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ExternalStorageConfigurationManager" enabled="true" />
+  <component name="MavenProjectsManager">
+    <option name="originalFiles">
+      <list>
+        <option value="$PROJECT_DIR$/pom.xml" />
+      </list>
+    </option>
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
+</project>

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="" vcs="Git" />
+  </component>
+</project>

+ 8 - 1
src/main/java/com/malk/eastar/conf/EastarParam.java

@@ -9,7 +9,7 @@ public class EastarParam {
     public static Map<String,String> TFNAME_YDKEY=new HashMap<>(); //状态(阶段)对应项目表KEY
     public static String YD_FORMUUID_PROJECT="FORM-D8DFF1F8C07A4869BCC850090F3A3B4EE0AV"; // 立项流程
     public static String YD_FORMUUID_RECOD="FORM-64A758B8173341879B24D612E180BE997E0B"; // TB项目档案
-    public static String YD_FORMUUID_GYS_YW="FORM-3AB247087A81401F87264BFA74944BE3R086"; // 供应商-业务对应表
+    public static String YD_FORMUUID_GYS_YW="FORM-3AB247087A81401F87264BFA74944BE3R086"; // 供应商跟单员档案
     public static String YD_FORMUUID_SKU_TYPE="FORM-17E244F3FB2240EB930E6DD4E22C7F89KXAR"; // 品类表
     public static String YD_FORMUUID_CGTASK="FORM-B9CBFB34DB3249C483415EF641202AC199J9"; // 采购任务表
     public static String YD_FORMUUID_ORDER="FORM-A731443BE0F04467A5D7FC1A82431D6AL2JO"; // 订单表
@@ -18,6 +18,13 @@ public class EastarParam {
 
     public static String TB_PROJECT_TEMP="68d49cdbd17a8ab739a424ce";
 
+    public static String YD_FORMUUID_CUSTOMER = "FORM-9261FABA687B4D1D917617F53B4A5DB7UN16";    //客户,add by Jason 20260414
+    public static String YD_FORMUUID_BUSINESS_USER = "FORM-C940C08329AA47A5814001E52F1665F3XV4P";    //业务小组档案,add by Jason 20260414
+    public static String YD_FORMUUID_CUSTOMER_CONTACT = "FORM-F2217E70844B4836833AB97C56C27BDFRI4Y";    //客户跟进,add by Jason 20260522
+    public static String YD_FORMUUID_ALERT_LOG = "FORM-49E10E54526E42B0925D0C809F4BF5DA8W4S";    //私海客户流出告警日志,add by Jason 20260522
+    public static String YD_FORMUUID_ALERT_DETAIL = "FORM-AAA9AD76E53246B89356B09DEE5262552ZA0";    //私海客户流出风险提示,add by Jason 20260522
+    public static String YD_FORMUUID_PSS_SERIES = "FORM-3598FDFC625D44CD929675B32228BFC7ES87";    //PSS系列,add by Jason 20260529
+
     static {
         CUSTFIELD_ACCE.put("配件名","textField_me2f7tvo");
         CUSTFIELD_ACCE.put("系列名称","selectField_me2f7tw4");

+ 230 - 0
src/main/java/com/malk/eastar/controller/AitableController.java

@@ -0,0 +1,230 @@
+package com.malk.eastar.controller;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.malk.eastar.service.AitableService;
+import com.malk.eastar.service.DDCoreClient;
+import com.malk.eastar.service.YidaService;
+import com.malk.server.common.McException;
+import com.malk.server.common.McR;
+import com.malk.utils.UtilMap;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+@RestController
+@RequestMapping("/aitable")
+public class AitableController {
+
+    @Autowired
+    private AitableService aitableService;
+
+    @Autowired
+    private YidaService yidaService;
+
+    @Autowired
+    private DDCoreClient ddCoreClient;
+
+    /**
+     * 新建客户
+     * @param data
+     * @return
+     */
+    @PostMapping("/newCustomer")
+    McR createNewCustomer(@RequestBody JSONObject data) {
+        log.info("新建客户, {}", data);
+        McException.assertParamException_Null(data, "yidaInstanceId");
+        String yidaInstanceId = UtilMap.getString(data, "yidaInstanceId");  //宜搭实例ID
+        String yidaCustomerName = UtilMap.getString(data, "yidaCustomerName");  //客户公司名(英文名)
+        String yidaBusinessUserId = UtilMap.getString(data, "yidaBusinessUserId");  //业务userId
+        String yidaCustomerLevel = UtilMap.getString(data, "yidaCustomerLevel");    //客户潜在等级
+        String yidaNewOrOld = UtilMap.getString(data, "yidaNewOrOld");    //新老客户
+        String yidaCustomerStatus = UtilMap.getString(data, "yidaCustomerStatus");    //客户情况
+        String yidaCountryOrRegion = UtilMap.getString(data, "yidaCountryOrRegion");    //客户国家/地区
+        List<String> yidaProductTypes = UtilMap.getList(data, "yidaProductTypes");   //主要品类
+        Map<String,Object> fields = new HashMap<>();
+        try {
+            fields.put("20rO7zS",yidaCustomerName);   //客户公司名【基础】
+            fields.put("qgOhsh1",yidaCustomerLevel);   //客户分级【客户】
+            fields.put("3Y796Wb",yidaNewOrOld);  //新老客户?【客户】
+            fields.put("jIS3Gbd",yidaCustomerStatus);  //客户情况
+            fields.put("JjVfpWO",yidaCountryOrRegion);  //客户国家/地区【客户】
+            fields.put("6rCZkSN",yidaProductTypes);  //客户标签【客户】
+            JSONArray user = new JSONArray();
+            JSONObject unionId = new JSONObject();
+            unionId.put("unionId",ddCoreClient.getUnionIdByUserId(yidaBusinessUserId));
+            user.add(unionId);
+            fields.put("ynNC3Kq",JSONObject.toJSONString(user));  //业务【人事】
+            String aitableId = aitableService.querySys1CustomerIdByName(yidaCustomerName);
+            if(aitableId == null || aitableId.isEmpty()){
+                aitableId = aitableService.addSys1CustomerData(fields);
+            }else{
+                log.info("客户["+yidaCustomerName+"]在项目总表已存在,不再新增");
+            }
+            yidaService.updateCustomerRelatedAitableId(yidaInstanceId, aitableId);
+            return McR.success();
+        } catch (Exception e) {
+            return McR.error("400",e.getMessage());
+        }
+    }
+
+    /**
+     * 客户已建联
+     * @param data
+     * @return
+     */
+    @PostMapping("/establishedContact")
+    McR establishedContactCustomer(@RequestBody JSONObject data) {
+        log.info("客户已建联, {}", data);
+        McException.assertParamException_Null(data, "aitableId");
+        String aitableId = UtilMap.getString(data, "aitableId");
+        Map<String,Object> fields = new HashMap<>();
+        try {
+            fields.put("jIS3Gbd","已建联");  //客户情况
+            aitableService.updateSys1CustomerData(aitableId,fields);
+            return McR.success();
+        } catch (Exception e) {
+            return McR.error("400",e.getMessage());
+        }
+    }
+
+    /**
+     * 业务员变更
+     * @param data
+     * @return
+     */
+    @PostMapping("/chanegBusinessUser")
+    McR changeCustomerBusinessUser(@RequestBody JSONObject data) {
+        log.info("业务员变更, {}", data);
+        McException.assertParamException_Null(data, "aitableId");
+        String aitableId = UtilMap.getString(data, "aitableId");
+        String yidaBusinessUserId = UtilMap.getString(data, "yidaBusinessUserId");  //业务userId
+        Map<String,Object> fields = new HashMap<>();
+        try {
+            JSONArray user = new JSONArray();
+            if(yidaBusinessUserId == null || yidaBusinessUserId.isEmpty()){
+                log.info("业务userId为空,将业务置空");
+            }else{
+                JSONObject unionId = new JSONObject();
+                unionId.put("unionId",ddCoreClient.getUnionIdByUserId(yidaBusinessUserId));
+                user.add(unionId);
+            }
+            fields.put("ynNC3Kq",JSONObject.toJSONString(user));  //业务【人事】
+            aitableService.updateSys1CustomerData(aitableId,fields);
+            return McR.success();
+        } catch (Exception e) {
+            return McR.error("400",e.getMessage());
+        }
+    }
+
+    /**
+     * 新建商机
+     * @param data
+     * @return
+     */
+    @PostMapping("/newOpportunity")
+    McR createNewOpportunity(@RequestBody JSONObject data) {
+        log.info("新建商机, {}", data);
+        McException.assertParamException_Null(data, "yidaInstanceId");
+        String yidaInstanceId = UtilMap.getString(data, "yidaInstanceId");  //宜搭实例ID
+        String yidaProjectCode = UtilMap.getString(data, "yidaProjectCode"); //项目编号
+        String yidaProjectName = UtilMap.getString(data, "yidaProjectName"); //项目名称
+        String yidaOrderCompletionRate = UtilMap.getString(data, "yidaOrderCompletionRate"); //成单情况
+        String yidaEstimatedOrderDate = UtilMap.getString(data, "yidaEstimatedOrderDate"); //预计成单日期
+        String yidaOrderAmount = UtilMap.getString(data, "yidaOrderAmount"); //预计项目金额
+        String aiTableCustomerID = UtilMap.getString(data, "aiTableCustomerID");    //客户AI表格映射ID
+        String yidaCustomerName = UtilMap.getString(data, "yidaCustomerName");  //客户公司名
+        String yidaBusinessUserId = UtilMap.getString(data, "yidaBusinessUserId");  //业务
+        Map<String,Object> fields = new HashMap<>();
+        try {
+            fields.put("zP1nHJs",yidaProjectCode);   //项目编号 - S1【基础】
+            fields.put("P3XtfD8",yidaProjectName);   //项目名称 - S1【基础】
+            fields.put("KDAelfq",yidaOrderCompletionRate);  //成单情况【商机进度】
+            fields.put("m34IbuX",Long.parseLong(yidaEstimatedOrderDate));  //预计成单日期 - S1~2【商机进度】
+            fields.put("MYBeHPG",yidaOrderAmount);  //订单金额 - S2~3【销售数据】
+            JSONObject bidirectionalLink = new JSONObject();
+            String[] linkedRecordIds = new String[]{aiTableCustomerID};
+            bidirectionalLink.put("linkedRecordIds",linkedRecordIds);
+            fields.put("F7zdGI6",bidirectionalLink);  //客户公司名 - S1【基础】
+            JSONArray user = new JSONArray();
+            JSONObject unionId = new JSONObject();
+            unionId.put("unionId",ddCoreClient.getUnionIdByUserId(yidaBusinessUserId));
+            user.add(unionId);
+            fields.put("Iz0yaro",JSONObject.toJSONString(user));  //业务 - S1【人事】
+            String aitableId = aitableService.addSys1SaleData(fields);
+            yidaService.updateSaleProjectRelatedAitableId(yidaInstanceId, aitableId);
+            return McR.success();
+        } catch (Exception e) {
+            return McR.error("400",e.getMessage());
+        }
+    }
+
+
+    /**
+     * 销售项目变更
+     * @param data
+     * @return
+     */
+    @PostMapping("/changeOpportunity")
+    McR changeSaleProject(@RequestBody JSONObject data) {
+        log.info("销售项目变更, {}", data);
+        McException.assertParamException_Null(data, "aitableId");
+        String aitableId = UtilMap.getString(data, "aitableId");
+        String yidaSaleProjectStatus = UtilMap.getString(data, "yidaSaleProjectStatus");  //销售项目状态
+        String yidaOrderAmount = UtilMap.getString(data, "yidaOrderAmount"); //预计项目金额
+        String yidaActualOrderDate = UtilMap.getString(data, "yidaActualOrderDate"); //实际成单日期
+        Map<String,Object> fields = new HashMap<>();
+        try {
+            String aiTableOrderStatus = ""; //订单状态 - S1~3【商机进度】
+            String aiTableOpportunityStage = ""; //商机阶段 - S1~3【商机进度】
+            if(yidaSaleProjectStatus != null && !yidaSaleProjectStatus.isEmpty()){
+                if("报价中".equals(yidaSaleProjectStatus)){
+                    aiTableOrderStatus = "2、报价中";
+                    aiTableOpportunityStage = "RFQ";
+                }else if("提前打样 / 修图".equals(yidaSaleProjectStatus)){
+                    aiTableOrderStatus = "3、提前打样 / 修图";
+                }else if("订单确认".equals(yidaSaleProjectStatus)){
+                    aiTableOrderStatus = "4、订单确认";
+                    aiTableOpportunityStage = "已成单";
+
+                }else if("已立项".equals(yidaSaleProjectStatus)){
+                    aiTableOrderStatus = "5、已立项";
+                }else if("暂停".equals(yidaSaleProjectStatus)){
+                    aiTableOrderStatus = "6、暂停";
+                }else if("已完成".equals(yidaSaleProjectStatus)){
+                    aiTableOrderStatus = "7、已完成";
+                }else if("已终止".equals(yidaSaleProjectStatus)){
+                    aiTableOrderStatus = "8、已终止";
+                    aiTableOpportunityStage = "已丢单";
+                }
+                fields.put("31G4UB7",aiTableOrderStatus);   //订单状态 - S1~3【商机进度】
+                if(StringUtils.isNotEmpty(aiTableOpportunityStage)){
+                    fields.put("LQF6OWD",aiTableOpportunityStage);   //商机阶段 - S1~3【商机进度】
+                }
+                if(StringUtils.isNotEmpty(yidaActualOrderDate)){
+                    fields.put("VBsHxPE",Long.parseLong(yidaActualOrderDate));  //实际成单日期 - S3【销售数据】
+                }
+                if(StringUtils.isNotEmpty(yidaOrderAmount)){
+                    fields.put("MYBeHPG",Double.parseDouble(yidaOrderAmount));  //订单金额 - S2~3【销售数据】
+                }
+                aitableService.updateSys1SaleData(aitableId,fields);
+            }else if(yidaOrderAmount != null && !yidaOrderAmount.isEmpty()){    //成单预测
+                fields.put("MYBeHPG",Double.parseDouble(yidaOrderAmount));  //订单金额 - S2~3【销售数据】
+                aitableService.updateSys1SaleData(aitableId,fields);
+            }
+            return McR.success();
+        } catch (Exception e) {
+            return McR.error("400",e.getMessage());
+        }
+    }
+
+}

+ 63 - 0
src/main/java/com/malk/eastar/controller/EastarDdController.java

@@ -1,10 +1,12 @@
 package com.malk.eastar.controller;
 
 import com.alibaba.fastjson.JSONObject;
+import com.malk.eastar.service.DDCoreClient;
 import com.malk.server.common.McException;
 import com.malk.server.common.McR;
 import com.malk.service.dingtalk.DDClient;
 import com.malk.service.dingtalk.DDClient_Report;
+import com.malk.utils.UtilMap;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -22,9 +24,13 @@ public class EastarDdController {
 
     @Autowired
     private DDClient_Report ddClientReport;
+
     @Autowired
     private DDClient ddClient;
 
+    @Autowired
+    private DDCoreClient ddCoreClient;
+
     @PostMapping("/report/create")
     public McR createReport(@RequestBody JSONObject param){
         log.info("创建日志:{}",param);
@@ -39,4 +45,61 @@ public class EastarDdController {
                 list);
         return McR.success(result);
     }
+
+
+    /**
+     * 根据unionId获取userId
+     * @param data
+     * @return
+     */
+//    @PostMapping("/getUserIdByUnionId")
+    McR getUserIdByUnionId(@RequestBody JSONObject data) {
+        log.info("根据unionId获取userId, {}", data);
+        McException.assertParamException_Null(data, "unionid");
+        String unionId = UtilMap.getString(data, "unionid");
+        try {
+            String userId = ddCoreClient.getUserIdByUnionId(unionId);
+            return McR.success(userId);
+        } catch (Exception e) {
+            return McR.error("400",e.getMessage());
+        }
+    }
+
+    /**
+     * 根据userId获取unionId
+     * @param data
+     * @return
+     */
+//    @PostMapping("/getUnionIdByUserId")
+    McR getUnionIdByUserId(@RequestBody JSONObject data) {
+        log.info("根据userId获取unionId, {}", data);
+        McException.assertParamException_Null(data, "userid");
+        String userId = UtilMap.getString(data, "userid");
+        try {
+            String unionId = ddCoreClient.getUnionIdByUserId(userId);
+            return McR.success(unionId);
+        } catch (Exception e) {
+            return McR.error("400",e.getMessage());
+        }
+    }
+
+    /**
+     * 根据userId获取部门ID
+     * @param data
+     * @return
+     */
+//    @PostMapping("/getDeptIdListByUserId")
+    McR getDeptIdListByUserId(@RequestBody JSONObject data) {
+        log.info("根据userId获取部门ID, {}", data);
+        McException.assertParamException_Null(data, "userid");
+        String userId = UtilMap.getString(data, "userid");
+        try {
+            List deptIdList = ddCoreClient.getDeptIdListByUserId(userId);
+            return McR.success(deptIdList);
+        } catch (Exception e) {
+            return McR.error("400",e.getMessage());
+        }
+    }
+
+
 }

+ 2 - 1
src/main/java/com/malk/eastar/controller/EastarTbController.java

@@ -24,8 +24,9 @@ public class EastarTbController {
 
     /**
      * 保存任务,如无项目自动创建
+     * 备注:该接口已停用,已改为不含TB的新接口:/yida/addtask
      */
-    @PostMapping("task/save")
+//    @PostMapping("task/save")
     McR createProject(@RequestBody JSONObject data) {
         log.info("通过模板创建项目, {}", data);
         McException.assertParamException_Null(data, "formInstId");

+ 62 - 0
src/main/java/com/malk/eastar/controller/EastarYidaController.java

@@ -0,0 +1,62 @@
+package com.malk.eastar.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.malk.eastar.service.YidaService;
+import com.malk.server.common.McException;
+import com.malk.server.common.McR;
+import com.malk.utils.UtilMap;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Map;
+
+/**
+ * 专用于宜搭复杂逻辑处理的接口服务
+ * add by Jason 20260317
+ */
+@Slf4j
+@RestController
+@RequestMapping("/yida")
+public class EastarYidaController {
+
+    @Autowired
+    private YidaService yidaService;
+
+    /**
+     * 供宜搭应用检查当前接口服务是否可用
+     * @param data
+     * @return
+     */
+    @PostMapping("/test")
+    McR heartbeatTest(@RequestBody JSONObject data) {
+        log.info("心跳测试, {}", data);
+        McException.assertParamException_Null(data, "param");
+        String param = UtilMap.getString(data, "param");
+        Map result = yidaService.heartbeatTest(param);
+        if(result.get("error") == null){
+            return McR.success(result);
+        }else{
+            return McR.error("400",result.get("error").toString());
+        }
+    }
+
+    /**
+     * 【立项/项目台账】→【配件任务表】数据流转
+     */
+    @PostMapping("/addtask")
+    McR createPartsTask(@RequestBody JSONObject data) {
+        log.info("【立项/项目台账】→【配件任务表】数据流转, {}", data);
+        McException.assertParamException_Null(data, "formInstId");
+        String formInstId = UtilMap.getString(data, "formInstId");
+        Map result=yidaService.createPartsTask(formInstId);
+        if(result.get("error") == null){
+            return McR.success(result);
+        }else{
+            return McR.error("400",result.get("error").toString());
+        }
+    }
+}

+ 55 - 0
src/main/java/com/malk/eastar/model/AITableParam.java

@@ -0,0 +1,55 @@
+package com.malk.eastar.model;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.malk.base.BaseDto;
+
+/**
+ * AI表格数据处理客户端接口参数
+ */
+public class AITableParam extends BaseDto {
+
+    //每页获取的数据量,默认值为100,最小值为1,最大值为100
+    private Integer maxResults;
+
+    //上一次查询返回的游标,首次查询时不需要传
+    private String nextToken;
+
+    //筛选条件,设置后将只返回满足条件的记录
+    private JSONObject filter;
+
+    //操作数据
+    private JSONObject records;
+
+    public Integer getMaxResults() {
+        return maxResults;
+    }
+
+    public void setMaxResults(Integer maxResults) {
+        this.maxResults = maxResults;
+    }
+
+    public String getNextToken() {
+        return nextToken;
+    }
+
+    public void setNextToken(String nextToken) {
+        this.nextToken = nextToken;
+    }
+
+    public JSONObject getFilter() {
+        return filter;
+    }
+
+    public void setFilter(JSONObject filter) {
+        this.filter = filter;
+    }
+
+    public JSONObject getRecords() {
+        return records;
+    }
+
+    public void setRecords(JSONObject records) {
+        this.records = records;
+    }
+}

+ 49 - 0
src/main/java/com/malk/eastar/model/AITableResult.java

@@ -0,0 +1,49 @@
+package com.malk.eastar.model;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.malk.server.common.VenR;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * AI表格数据处理客户端接口返回结果
+ * @param <T>
+ */
+public class AITableResult<T> extends VenR {
+
+    //是否有更多数据
+    private Boolean hasMore;
+
+    //分页游标
+    private String nextToken;
+
+    //记录数据列表
+    private JSONArray records;
+
+
+    public Boolean getHasMore() {
+        return hasMore;
+    }
+
+    public void setHasMore(Boolean hasMore) {
+        this.hasMore = hasMore;
+    }
+
+    public String getNextToken() {
+        return nextToken;
+    }
+
+    public void setNextToken(String nextToken) {
+        this.nextToken = nextToken;
+    }
+
+    public JSONArray getRecords() {
+        return records;
+    }
+
+    public void setRecords(JSONArray records) {
+        this.records = records;
+    }
+}

+ 311 - 24
src/main/java/com/malk/eastar/schedule/ScheduleTask.java

@@ -1,7 +1,13 @@
 package com.malk.eastar.schedule;
 
+import cn.hutool.core.date.DateUtil;
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.malk.eastar.model.AITableParam;
+import com.malk.eastar.model.AITableResult;
+import com.malk.eastar.service.MDTableClient;
 import com.malk.eastar.service.EastarTbService;
+import com.malk.eastar.service.YidaService;
 import com.malk.server.aliwork.YDConf;
 import com.malk.server.aliwork.YDParam;
 import com.malk.server.aliwork.YDSearch;
@@ -11,6 +17,7 @@ import com.malk.utils.PublicUtil;
 import com.malk.utils.UtilDateTime;
 import com.malk.utils.UtilMap;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Configuration;
@@ -18,12 +25,8 @@ import org.springframework.scheduling.annotation.EnableScheduling;
 import org.springframework.scheduling.annotation.Scheduled;
 
 import java.time.LocalDate;
-import java.time.LocalDateTime;
 import java.time.LocalTime;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 /**
  * @EnableScheduling 开启定时任务 [配置参考McScheduleTask]
@@ -41,34 +44,120 @@ public class ScheduleTask {
     @Autowired
     private YDService ydService;
 
+    //add by Jason 20260313 start
+    @Autowired
+    private MDTableClient mdTableClient;
+    //add by Jason 20260313 end
+
+    //add by Jason 20260522 start
+    @Autowired
+    private YidaService yidaService;
+    //add by Jason 20260522 end
+
+
     /**
+     * 私海客户流出
      */
-    @Scheduled(cron = "0 0 8 * * ?")
-    public void syncMer() {
-        log.info("客户公海同步");
+    @Scheduled(cron = "0 0 5 * * ?")
+    public void releasePrivatePoolCustomers() {
+        log.info("私海客户流出定时任务");
         try {
-            long endTime= UtilDateTime.getLocalDateTimeTimeStamp(LocalDate.now().minusDays(30).atTime(LocalTime.MIN));
-            List<Map> list= (List<Map>) ydClient.queryData(YDParam.builder().formUuid("FORM-9261FABA687B4D1D917617F53B4A5DB7UN16").searchCondition(JSONObject.toJSONString(
-                    Arrays.asList(
-                            new YDSearch("radioField_md6q7oxa","私","公私海", YDSearch.Type.TEXT_FIELD,YDSearch.Operator.EQ),
-                            new YDSearch("radioField_md6q7ox8","新","新老客户", YDSearch.Type.TEXT_FIELD,YDSearch.Operator.EQ),
-                            new YDSearch("dateField_l3tw3kfn",endTime,"截至跟进时间",YDSearch.Type.DATE_FIELD,YDSearch.Operator.LT)
-                    )
-            )).build(), YDConf.FORM_QUERY.retrieve_list).getData();
-            for(Map map:list){
-                log.info("客户:{}释放为公海", UtilMap.getMap(map,"formData").get("textField_lqanqe6j"));
-                ydClient.operateData(YDParam.builder().formInstId(UtilMap.getString(map,"formInstanceId")).updateFormDataJson(
-                        JSONObject.toJSONString(UtilMap.map("radioField_md6q7oxa, employeeField_lqanqe6n, employeeField_lqx3act6","公","[]","[]"))
-                ).build(), YDConf.FORM_OPERATION.update);
+            //查询所有已建联客户跟进记录
+            List<Map> establishContactData = yidaService.queryLtcCustomerEstablishContactData();
+            log.info("已建联跟进记录数:"+ establishContactData.size());
+
+            //进入私海时间分界点(2026年5月10日)
+            long enterPrivateTime = UtilDateTime.getLocalDateTimeTimeStamp(LocalDate.of(2026, 5, 10).atStartOfDay());
+
+            //查询超过3天未跟进的私海新客户记录
+            long endTime = UtilDateTime.getLocalDateTimeTimeStamp(LocalDate.now().minusDays(3).atTime(LocalTime.MIN));
+            List ydFilters = Arrays.asList(
+                    new YDSearch("radioField_mnpdkss9","否","测试使用", YDSearch.Type.RADIO_FIELD,YDSearch.Operator.EQ),
+                    new YDSearch("dateField_moxzc25f",enterPrivateTime,"进入私海时间", YDSearch.Type.DATE_FIELD,YDSearch.Operator.GT),
+                    new YDSearch("radioField_md6q7oxa","私","公海or私海", YDSearch.Type.RADIO_FIELD,YDSearch.Operator.EQ),
+                    new YDSearch("radioField_md6q7ox8","新","新老客户", YDSearch.Type.RADIO_FIELD,YDSearch.Operator.EQ),
+                    new YDSearch("dateField_l3tw3kfn",endTime,"最后跟进时间",YDSearch.Type.DATE_FIELD,YDSearch.Operator.LT)
+            );
+            List<Map> ltcCustomerData = yidaService.queryLtcNotFollowedCustomerData(ydFilters);
+            log.info("超过3天未跟进的私海新客户记录数:"+ ltcCustomerData.size());
+            
+            //排除已建联
+            Set<String> contactedCustomerCodes = new HashSet<>();
+            for(Map contactRecord : establishContactData){
+                String customerCode = UtilMap.getString(contactRecord, "customerCode");
+                if(StringUtils.isNotEmpty(customerCode)){
+                    contactedCustomerCodes.add(customerCode);
+                }
             }
+            List<Map> filteredCustomerData = new ArrayList<>();
+            for(Map customerRecord : ltcCustomerData){
+                String customerCode = UtilMap.getString(customerRecord, "customerCode");
+                if(!contactedCustomerCodes.contains(customerCode)){
+                    filteredCustomerData.add(customerRecord);
+                }
+            }
+            log.info("排除已建联后的记录数:"+ filteredCustomerData.size());
+            Map alertDetailRecord;
+            for (Map customerRecord : filteredCustomerData) {
+                alertDetailRecord = new HashMap();
+                alertDetailRecord.put("businessUserId",UtilMap.getString(customerRecord, "userId"));
+                alertDetailRecord.put("formInstId",UtilMap.getString(customerRecord, "formInstId"));
+                alertDetailRecord.put("customerName",UtilMap.getString(customerRecord, "customerName"));
+                alertDetailRecord.put("customerCode",UtilMap.getString(customerRecord, "customerCode"));
+                alertDetailRecord.put("today", UtilDateTime.getLocalDateTimeTimeStamp(LocalDate.now().atStartOfDay()));
+//                alertDetailRecord.put("tomorrow", UtilDateTime.getLocalDateTimeTimeStamp(LocalDate.now().plusDays(1).atStartOfDay()));
+                alertDetailRecord.put("remark","2026年5月10日后进入私海,新客户,未建联,超过3天未跟进");
+                yidaService.addAlertDetail(alertDetailRecord);
+            }
+
+            //按业务员分组,统计客户数量
+            Map<String, List<Map>> customerGroupBySales = new HashMap<>();
+            for (Map customerRecord : filteredCustomerData) {
+                String salesPerson = UtilMap.getString(customerRecord, "userId");
+                if (StringUtils.isEmpty(salesPerson)) {
+                    salesPerson = "未知业务员";
+                }
+                customerGroupBySales.computeIfAbsent(salesPerson, k -> new ArrayList<>()).add(customerRecord);
+            }
+            Map alertLogRecord;
+            for (Map.Entry<String, List<Map>> entry : customerGroupBySales.entrySet()) {
+                log.info("业务员: {}, 可能会流出客户数量: {}", entry.getKey(), entry.getValue().size());
+                //新增私海客户流出告警日志
+                alertLogRecord = new HashMap();
+                alertLogRecord.put("businessUserId",entry.getKey());
+                alertLogRecord.put("customerNum",entry.getValue().size());
+                alertLogRecord.put("today", UtilDateTime.getLocalDateTimeTimeStamp(LocalDate.now().atStartOfDay()));
+                yidaService.addAlertLog(alertLogRecord);
+            }
+
+
+
+            //查询超过30天未跟进的私海新客户记录
+
+
+//            long endTime= UtilDateTime.getLocalDateTimeTimeStamp(LocalDate.now().minusDays(30).atTime(LocalTime.MIN));
+//            List<Map> list= (List<Map>) ydClient.queryData(YDParam.builder().formUuid("FORM-9261FABA687B4D1D917617F53B4A5DB7UN16").searchCondition(JSONObject.toJSONString(
+//                    Arrays.asList(
+//                            new YDSearch("radioField_md6q7oxa","私","公私海", YDSearch.Type.TEXT_FIELD,YDSearch.Operator.EQ),
+//                            new YDSearch("radioField_md6q7ox8","新","新老客户", YDSearch.Type.TEXT_FIELD,YDSearch.Operator.EQ),
+//                            new YDSearch("dateField_l3tw3kfn",endTime,"截至跟进时间",YDSearch.Type.DATE_FIELD,YDSearch.Operator.LT)
+//                    )
+//            )).build(), YDConf.FORM_QUERY.retrieve_list).getData();
+//            for(Map map:list){
+//                log.info("客户:{}释放为公海", UtilMap.getMap(map,"formData").get("textField_lqanqe6j"));
+//                ydClient.operateData(YDParam.builder().formInstId(UtilMap.getString(map,"formInstanceId")).updateFormDataJson(
+//                        JSONObject.toJSONString(UtilMap.map("radioField_md6q7oxa, employeeField_lqanqe6n, employeeField_lqx3act6","公","[]","[]"))
+//                ).build(), YDConf.FORM_OPERATION.update);
+//            }
         }catch (Exception e){
-            e.printStackTrace();
+            log.error("私海客户流出定时任务异常",e);
         }
+        log.info("私海客户流出定时任务执行完成");
     }
 
     /**
      */
-    @Scheduled(cron = "0 30 6 * * ?")
+//    @Scheduled(cron = "0 30 6 * * ?")
     public void syncTaskCount() {
         log.info("同步任务状态数量");
         try {
@@ -98,7 +187,7 @@ public class ScheduleTask {
         }
     }
 
-    @Scheduled(cron = "0 30 1 1 1 ?")
+//    @Scheduled(cron = "0 30 1 1 1 ?")
     public void syncCust(){
         log.info("同步客户上一年等级");
         List<Map> list= ydService.queryAllFormData(YDParam.builder().formUuid("FORM-9261FABA687B4D1D917617F53B4A5DB7UN16").build());
@@ -121,4 +210,202 @@ public class ScheduleTask {
         }
     }
 
+    /**
+     * 项目总表表2未填写完成统计
+     * 每日9点55
+     */
+    @Scheduled(cron = "0 55 9 * * ?")
+    public void table2IncompleteStatistics() {
+        log.info("定时更新项目台账填写情况表");
+        /*
+            查询【表2】项目台账所有项目状态为Pending、Done、Closed的记录
+         */
+        JSONArray table2RecordsFilter = new JSONArray();
+        String baseId = "G53mjyd80pEr5grBfpjmMX6586zbX04v";
+        String sheetIdOrName = "pl6sz00";
+        Map<String,Object> param = new HashMap<>();
+        param.put("operatorId","aj1wcWqKLXITiPDwbMIjUbAiEiE");  //操作人(Jason)的unionId
+        AITableParam aiTableParam = new AITableParam();
+        aiTableParam.setMaxResults(100);
+        JSONObject filter = new JSONObject();
+        filter.put("combination","and");
+        JSONArray conditions = new JSONArray();
+        JSONObject condition = new JSONObject();
+        condition.put("field","项目状态");
+        condition.put("operator","notContain");
+        condition.put("value",new String[]{"Pending","Done","Closed"});
+        conditions.add(condition);
+        filter.put("conditions",conditions);
+        aiTableParam.setFilter(filter);
+        AITableResult aiTableResult;
+        boolean hasMore = true;
+        int pageNo = 1;
+        JSONArray records;
+        log.info("查询【表2】项目台账所有项目状态为Pending、Done、Closed的记录");
+        while(hasMore){
+            aiTableResult = mdTableClient.queryMultiRecords(baseId,sheetIdOrName,param,aiTableParam);
+            hasMore = aiTableResult.getHasMore();
+            log.info("当前第"+pageNo+"页");
+            log.info("记录数="+aiTableResult.getRecords().size());
+            records = aiTableResult.getRecords();
+            for(int i=0;i<records.size();i++){
+                table2RecordsFilter.add(records.getJSONObject(i));
+            }
+            log.info("是否有更多数据:"+hasMore);
+            pageNo++;
+            aiTableParam.setNextToken(aiTableResult.getNextToken());
+        }
+        /*
+            统计计划开始时间和计划结束时间未填的
+         */
+        List<String> checkEmptyRecordList = new ArrayList<>();
+        String[] checkEmptyFieldArr = new String[]{
+                "计划:开始白样【交付进度】",
+                "计划:结束白样【交付进度】",
+                "计划:开始制版【交付进度】",
+                "计划:结束制版【交付进度】",
+                "计划:开始产前样【交付进度】",
+                "计划:结束产前样【交付进度】",
+                "计划:开始大货【交付进度】",
+                "计划:结束大货【交付进度】",
+                "计划:开始包装【交付进度】",
+                "计划:结束包装【交付进度】",
+                "计划:开始出货【交付进度】",
+                "计划:结束出货时间【交付进度】"
+        };
+        JSONObject table2Record;
+        JSONObject fields;
+        String unionIdPM;
+        String checkFailureStr;
+        JSONArray pmJSONArray;
+//        System.out.println("表2PM:");
+        for(int i=0;i<table2RecordsFilter.size();i++){
+            table2Record = table2RecordsFilter.getJSONObject(i);
+            fields = table2Record.getJSONObject("fields");
+            pmJSONArray = fields.getJSONArray("PM(Owner)【人事】");
+            if(pmJSONArray == null){
+                continue;
+            }
+            unionIdPM = pmJSONArray.getJSONObject(0).getString("unionId");
+            for(String checkEmptyField : checkEmptyFieldArr){
+                if(StringUtils.isEmpty(fields.getString(checkEmptyField))){
+                    checkFailureStr = unionIdPM + "_" + checkEmptyField+"未填写";
+//                    System.out.println(checkFailureStr);
+                    checkEmptyRecordList.add(checkFailureStr);
+                }
+            }
+        }
+//        System.out.println("checkEmptyRecordList:");
+//        System.out.println(JSON.toJSONString(checkEmptyRecordList));
+        /*
+            查询【参数表-人事】部门为销售部、客服部的记录
+         */
+        JSONArray empRecordsFilter = new JSONArray();
+        sheetIdOrName = "rtOAveM";
+        aiTableParam = new AITableParam();
+        aiTableParam.setMaxResults(100);
+        filter = new JSONObject();
+        filter.put("combination","and");
+        conditions = new JSONArray();
+        condition = new JSONObject();
+        condition.put("field","部门");
+        condition.put("operator","contain");
+        condition.put("value",new String[]{"销售部","客服部"});
+        conditions.add(condition);
+        filter.put("conditions",conditions);
+        aiTableParam.setFilter(filter);
+        log.info("查询【参数表-人事】部门为销售部、客服部的记录");
+        aiTableResult = mdTableClient.queryMultiRecords(baseId,sheetIdOrName,param,aiTableParam);
+        hasMore = aiTableResult.getHasMore();
+        log.info("是否有更多数据:"+hasMore);
+        log.info("销售和PM人员记录数="+aiTableResult.getRecords().size());
+        records = aiTableResult.getRecords();
+        for(int i=0;i<records.size();i++){
+            empRecordsFilter.add(records.getJSONObject(i));
+        }
+        JSONObject empRecord;
+        String deptId;
+        String unionIdPMLeader;
+//        System.out.println("人员列表:");
+        Map<String,Object> unionIdMap = new HashMap<>();
+        for(int i=0; i<empRecordsFilter.size(); i++){
+            fields = empRecordsFilter.getJSONObject(i).getJSONObject("fields");
+            unionIdPM = fields.getJSONArray("人员").getJSONObject(0).getString("unionId");
+            deptId = fields.getJSONObject("部门").getString("id");
+            if(fields.getJSONArray("销售组长") != null){
+                unionIdPMLeader = fields.getJSONArray("销售组长").getJSONObject(0).getString("unionId");
+            }else{
+                unionIdPMLeader = "U2puyufsTtwvfTXmWQoG0wiEiE";
+            }
+//            System.out.println("unionIdPM="+unionIdPM+",deptId="+deptId+",unionIdPMLeader="+unionIdPMLeader);
+            empRecord = new JSONObject();
+            empRecord.put("deptId",deptId);
+            empRecord.put("unionIdPMLeader",unionIdPMLeader);
+            unionIdMap.put(unionIdPM,empRecord);
+        }
+        /*
+            新增项目台账填写情况表记录
+         */
+        JSONObject insertData = new JSONObject();
+        JSONArray insertRecords = new JSONArray();
+        JSONObject insertRecord;
+        JSONArray pmLeaderJSONArray;
+        JSONObject unionIdJSONObject;
+        for(String str : checkEmptyRecordList){
+            unionIdPM = str.split("_")[0];
+            empRecord = (JSONObject) unionIdMap.get(unionIdPM);
+            fields = new JSONObject();
+            fields.put("日期", DateUtil.today());
+            unionIdJSONObject = new JSONObject();
+            unionIdJSONObject.put("unionId",unionIdPM);
+            pmJSONArray = new JSONArray();
+            pmJSONArray.add(unionIdJSONObject);
+            fields.put("负责人",pmJSONArray);
+            unionIdJSONObject = new JSONObject();
+            unionIdJSONObject.put("unionId",empRecord.getString("unionIdPMLeader"));
+            pmLeaderJSONArray = new JSONArray();
+            pmLeaderJSONArray.add(unionIdJSONObject);
+            fields.put("组长",pmLeaderJSONArray);
+            fields.put("填写情况", str.split("_")[1]);
+            insertRecord = new JSONObject();
+            insertRecord.put("fields",fields);
+//            log.info(JSON.toJSONString(insertRecord));
+            insertRecords.add(insertRecord);
+        }
+        String result;
+        JSONArray newInsertRecords;
+        sheetIdOrName = "OTgxt4G";
+        if(insertRecords.size() > 100){
+            pageNo = 1;
+            while(insertRecords.size() > 100){
+                newInsertRecords = new JSONArray();
+                records = new JSONArray();
+                for (int i = 0; i < insertRecords.size(); i++) {
+                    if(i<100){
+                        newInsertRecords.add(insertRecords.getJSONObject(i));
+                    }else{
+                        records.add(insertRecords.getJSONObject(i));
+                    }
+                }
+                insertData.put("records",newInsertRecords);
+//                log.info(JSON.toJSONString(insertData));
+                result = mdTableClient.createMultiRecords(baseId,sheetIdOrName,param,insertData);
+                log.info("新增项目台账填写情况表记录结果,第"+pageNo+"页:");
+                log.info(result);
+                insertRecords = records;
+                pageNo++;
+            }
+        }
+        if(insertRecords.size() > 0){
+            insertData.put("records",insertRecords);
+//            log.info(JSON.toJSONString(insertData));
+            sheetIdOrName = "OTgxt4G";
+            result = mdTableClient.createMultiRecords(baseId,sheetIdOrName,param,insertData);
+            log.info("新增项目台账填写情况表记录结果,第"+pageNo+"页:");
+            log.info(result);
+        }
+
+
+    }
+
 }

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1364 - 0
src/main/java/com/malk/eastar/schedule/ScheduleTaskNew.java


+ 49 - 0
src/main/java/com/malk/eastar/service/AitableService.java

@@ -0,0 +1,49 @@
+package com.malk.eastar.service;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 专用于AI表格复杂逻辑处理的接口服务
+ * add by Jason 20260409
+ */
+public interface AitableService {
+    /**
+     * 获取项目总表中的多行记录(客户名册)
+     * @return
+     */
+    List<Map> querySys1CustomerData() throws Exception;
+
+    /**
+     * 根据客户名获取客户ID(客户名册)
+     * @param customerName
+     * @return
+     * @throws Exception
+     */
+    String querySys1CustomerIdByName(String customerName) throws Exception;
+
+    /**
+     * 添加客户名册记录
+     * @throws Exception
+     */
+    String addSys1CustomerData(Map<String,Object> fields) throws Exception;
+
+    /**
+     * 更新客户名册记录
+     * @throws Exception
+     */
+    String updateSys1CustomerData(String id,Map<String,Object> fields) throws Exception;
+
+    /**
+     * 添加销售台账记录
+     * @throws Exception
+     */
+    String addSys1SaleData(Map<String,Object> fields) throws Exception;
+
+    /**
+     * 更新销售台账记录
+     * @throws Exception
+     */
+    String updateSys1SaleData(String id,Map<String,Object> fields) throws Exception;
+
+}

+ 56 - 0
src/main/java/com/malk/eastar/service/DDCoreClient.java

@@ -0,0 +1,56 @@
+package com.malk.eastar.service;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 钉钉核心数据处理客户端接口
+ * add by Jason 20260414
+ */
+public interface DDCoreClient {
+
+    /**
+     * 根据userId获取name
+     * @param userId
+     * @return
+     * @throws Exception
+     */
+    String getNameByUserId(String userId) throws Exception;
+
+    /**
+     * 根据userId获取deptId
+     * @param userId
+     * @return
+     * @throws Exception
+     */
+    List getDeptIdListByUserId(String userId) throws Exception;
+
+    /**
+     * 根据userId获取unionId
+     * @param userId
+     * @return
+     * @throws Exception
+     */
+    String getUnionIdByUserId(String userId) throws Exception;
+
+    /**
+     * 根据unionId获取userId
+     * @param unionId
+     * @return
+     * @throws Exception
+     */
+    String getUserIdByUnionId(String unionId) throws Exception;
+
+    /**
+     * 查询离职员工数据
+     * @return
+     */
+    List<Map<String, String>> getLeaveEmployeeData(Date startTime, Date endTime) throws Exception;
+
+    /**
+     * 查询所有离职员工数据
+     * @return
+     */
+    List<Map<String, String>> getAllLeaveEmployeeData() throws Exception;
+}

+ 47 - 0
src/main/java/com/malk/eastar/service/MDTableClient.java

@@ -0,0 +1,47 @@
+package com.malk.eastar.service;
+
+import com.alibaba.fastjson.JSONObject;
+import com.malk.eastar.model.AITableParam;
+import com.malk.eastar.model.AITableResult;
+
+import java.util.Map;
+
+/**
+ * AI表格(多维表 Multi-dimensional Table)数据处理客户端接口
+ * add by Jason 20260313
+ */
+public interface MDTableClient {
+
+    /**
+     * 查询多行记录
+     * @param baseId AI表格ID
+     * @param sheetIdOrName 数据表ID或数据表名称
+     * @param param Query参数
+     * @param aiTableParam Body参数
+     * @return
+     */
+    AITableResult queryMultiRecords(String baseId, String sheetIdOrName, Map<String,Object> param, AITableParam aiTableParam);
+
+
+    /**
+     * 创建多行记录
+     * @param baseId AI表格ID
+     * @param sheetIdOrName 数据表ID或数据表名称
+     * @param param Query参数
+     * @param body Body参数
+     * @return
+     */
+    String createMultiRecords(String baseId, String sheetIdOrName, Map<String,Object> param, JSONObject body);
+
+
+    /**
+     * 修改多行记录
+     * @param baseId AI表格ID
+     * @param sheetIdOrName 数据表ID或数据表名称
+     * @param param Query参数
+     * @param body Body参数
+     * @return
+     */
+    String modifyMultiRecords(String baseId, String sheetIdOrName, Map<String,Object> param, JSONObject body);
+
+}

+ 161 - 0
src/main/java/com/malk/eastar/service/YidaService.java

@@ -0,0 +1,161 @@
+package com.malk.eastar.service;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 专用于宜搭复杂逻辑处理的接口服务
+ * add by Jason 20260317
+ */
+public interface YidaService {
+
+    /**
+     * 供宜搭应用检查当前接口服务是否可用
+     * @param param
+     * @return
+     */
+    Map heartbeatTest(String param);
+
+    /**
+     * 【项目台账】→【采购任务】数据流转
+     * @param formInstId
+     * @return
+     */
+    Map createPartsTask(String formInstId);
+
+
+    /**
+     * 获取易思达系统中的所有记录(业务小组档案)
+     * @return
+     */
+    List<Map> queryLtcAllBusinessUserData() throws Exception;
+
+    /**
+     * 更新业务人员在职状态为已离职(业务小组档案)
+     */
+    void setLtcBusinessUserLeave(String formInstId) throws Exception;
+
+    /**
+     * 获取易思达系统中的所有记录(客户名册)
+     */
+    List<Map> queryLtcAllCustomerData() throws Exception;
+
+    /**
+     * 获取易思达系统中的未跟进客户
+     */
+    List<Map> queryLtcNotFollowedCustomerData(List ydFilters) throws Exception;
+
+
+    /**
+     * 获取易思达系统中的客户建联跟进记录
+     */
+    List<Map> queryLtcCustomerEstablishContactData() throws Exception;
+
+
+    /**
+     * 更新易思达系统客户测试使用标识(客户名册)
+     */
+    void updateLtcCustomerTestFlag(String formInstId) throws Exception;
+
+    /**
+     * 更新易思达系统客户基本信息(客户公司名、业务、公海/私海、测试使用)
+     */
+    void updateLtcCustomerBasicInfo(String formInstId, String customerName, String businessUserId, String seaType, String testUseFlag) throws Exception;
+
+    /**
+     * 更新易思达系统客户基本信息(客户公司名、业务、公海/私海、新老客户、测试使用)
+     */
+    void updateLtcCustomerBasicInfo2(String formInstId, String customerName, String businessUserId, String seaType, String newOrOld, String testUseFlag) throws Exception;
+
+    /**
+     * 更新易思达系统客户基本信息(客户验重、业务userId、业务组长、是否大客户)
+     */
+    void updateLtcCustomerBasicInfo3(String formInstId, String customerNameUpperCase, String businessUserId, String businessLeaderUserId, String isBigCustomer) throws Exception;
+
+    /**
+     * 更新易思达系统客户基本信息(业务userId、负责人文本、业务组长、业务部门)
+     */
+    void updateLtcCustomerBasicInfo4(String formInstId, String businessUserId, String businessName, String businessLeaderUserId, String businessDepartment) throws Exception;
+
+    /**
+     * 更新易思达系统客户基本信息(客户当前分级、客户潜在等级、上一年分级、AI表格映射ID)
+     */
+    void updateLtcCustomerBasicInfo5(String formInstId, String customerLevel1, String customerLevel2, String customerLevel3, String aiTableId) throws Exception;
+
+    /**
+     * 更新易思达系统客户基本信息(客户当前分级、客户潜在等级、新老客户、AI表格映射ID)
+     */
+    void updateLtcCustomerBasicInfo6(String formInstId, String customerLevel1, String customerLevel2, String newOrOld, String aiTableId) throws Exception;
+
+    /**
+     * 更新易思达系统客户基本信息(客户当前分级、客户潜在等级)
+     */
+    void updateLtcCustomerBasicInfo7(String formInstId, String customerLevel, String customerPotentialLevel) throws Exception;
+
+    /**
+     * 更新易思达系统客户基本信息(客户当前分级、客户潜在等级)
+     */
+    void updateLtcCustomerBasicInfo8(String formInstId, long privateSeaTime, long lastContactTime) throws Exception;
+
+    /**
+     * 更新易思达系统客户的AI表格映射ID
+     */
+    void updateCustomerRelatedAitableId(String formInstId, String aitableId) throws Exception;
+
+    /**
+     * 更新易思达系统销售项目的AI表格映射ID
+     */
+    void updateSaleProjectRelatedAitableId(String formInstId, String aitableId) throws Exception;
+
+    /**
+     * 插入易思达系统中的一行记录(客户名册)
+     */
+    void insertCustomerData(Map row) throws Exception;
+
+    /**
+     * 插入易思达系统中的一行记录(私海客户流出风险提示)
+     */
+    void addAlertDetail(Map row) throws Exception;
+
+    /**
+     * 插入易思达系统中的一行记录(私海客户流出告警日志)
+     */
+    void addAlertLog(Map row) throws Exception;
+
+    /**
+     * 获取EASTAR业务数字化中的多行记录(客户名册)
+     * @return
+     */
+    List<Map> querySys2CustomerData() throws Exception;
+
+    /**
+     * 更新客户数据清洗中的多行记录(客户名册part2)
+     */
+    void updateSys1Sys2CustomerPart2Data(List<Map> sys2CustomerData) throws Exception;
+
+    /**
+     * 插入客户数据清洗中的多行记录(客户名册all)
+     */
+    void insertSys1Sys2CustomerAllData(List<Map> sys1Sys2CustomerData) throws Exception;
+
+    /**
+     * 获取客户数据清洗中的多行记录(客户名册all)
+     */
+    List<Map> querySys1Sys2CustomerAllData() throws Exception;
+
+    /**
+     * 获取客户数据清洗中的多行记录(私海客户)
+     */
+    List<Map> querySys1Sys2PrivateCustomerData() throws Exception;
+
+    /**
+     * 获取客户数据清洗中的多行记录(公海客户)
+     */
+    List<Map> querySys1Sys2PublicCustomerData() throws Exception;
+
+    /**
+     * 获取客户数据清洗中的多行记录(不合作客户)
+     */
+    List<Map> querySys1Sys2UncooperativeCustomerData() throws Exception;
+
+}

+ 488 - 0
src/main/java/com/malk/eastar/service/impl/AitableServiceImpl.java

@@ -0,0 +1,488 @@
+package com.malk.eastar.service.impl;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.malk.eastar.model.AITableParam;
+import com.malk.eastar.model.AITableResult;
+import com.malk.eastar.service.MDTableClient;
+import com.malk.eastar.service.AitableService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+
+/**
+ * 专用于AI表格复杂逻辑处理的接口服务
+ * add by Jason 20260409
+ */
+@Slf4j
+@Service
+public class AitableServiceImpl implements AitableService {
+
+    @Autowired
+    private MDTableClient mdTableClient;
+
+    @Override
+    public List<Map> querySys1CustomerData() throws Exception {
+        /*
+            参数定义
+         */
+        List<Map> customerData = new ArrayList<>(); // 客户数据
+        List<Map> customerDataDeduplicate = new ArrayList<>(); // 客户数据(去重)
+        String baseId; //AI表格文档ID
+        String sheetIdOrName;   //数据表ID或数据表名称
+        Map<String,Object> param = new HashMap<>(); //HTTP请求参数
+        AITableParam aiTableParam = new AITableParam(); //HTTP请求体
+        boolean hasMore; //是否还有下一页
+        int pageNo; //当前页码
+        int pageSize;   //每页获取的数据量(上限100)
+        AITableResult aiTableResult;    //请求返回内容
+        JSONArray records;  //每页记录数据
+        JSONArray allRecords = new JSONArray();  //所有记录数据
+        String aiTableId;   //AI表格ID
+        JSONObject fields;  //字段数据
+        String customerName;    //客户名称
+        JSONArray businessUserJSONArray;  //业务【人事】
+        String businessUserUnionId;    //业务员unionId
+        String businessUserName;    //业务员姓名
+        String kp;  //KP
+        boolean isCustomerNameEmpty;    //客户名称是否为空
+        boolean isBusinessUserEmpty;    //业务员是否为空
+        boolean isKpEmpty;  //KP是否为空
+        int customerEmptyCount = 0;  //客户名称为空的记录数
+        Map<String,String> customerRecord;  //客户记录
+        Map<String, Long> customerNameCountMap = new HashMap<>();   //客户名称与出现的次数映射
+        String customerLevel;   //客户分级
+        String newOrOld;    //新老客户
+
+        /*
+            项目总表
+         */
+        baseId = "G53mjyd80pEr5grBfpjmMX6586zbX04v";
+        sheetIdOrName = "E6RcJi3";
+
+        /*
+            项目总表副本-20260409
+         */
+//        baseId = "GZLxjv9VGqBAMDOoHYzrPZzE86EDybno";
+//        sheetIdOrName = "E6RcJi3";
+
+        /*
+            初始化参数值
+         */
+        hasMore = true; //第一页默认有数据
+        pageNo = 1;
+        pageSize = 100;
+        param.put("operatorId","aj1wcWqKLXITiPDwbMIjUbAiEiE");  //操作人(Jason)的unionId
+        aiTableParam.setMaxResults(pageSize);
+
+        /*
+            翻页获取数据
+         */
+        while(hasMore){
+            aiTableResult = mdTableClient.queryMultiRecords(baseId,sheetIdOrName,param,aiTableParam);
+            hasMore = aiTableResult.getHasMore();
+            log.info("当前第"+pageNo+"页");
+            log.info("记录数="+aiTableResult.getRecords().size());
+            records = aiTableResult.getRecords();
+            for(int i=0;i<records.size();i++){
+                allRecords.add(records.getJSONObject(i));
+            }
+            log.info("是否有更多数据:"+hasMore);
+            pageNo++;
+            aiTableParam.setNextToken(aiTableResult.getNextToken());
+        }
+
+        /*
+            请求记录数据处理
+         */
+        log.info("所有记录数量="+allRecords.size());
+        customerName = "";
+        businessUserUnionId = "";
+        businessUserName = "";
+        kp = "";
+        for(int i=0;i<allRecords.size();i++){
+            /*
+                重置是否为空标识
+             */
+            isCustomerNameEmpty = false;
+            isBusinessUserEmpty = false;
+            isKpEmpty = false;
+
+            //获取AI表格ID
+            aiTableId = allRecords.getJSONObject(i).getString("id");
+
+            //解析字段数据
+            fields = allRecords.getJSONObject(i).getJSONObject("fields");
+
+            /*
+                获取客户名称数据
+             */
+            if(fields.get("客户公司名【基础】") == null){
+                isCustomerNameEmpty = true;
+            }else{
+                customerName = fields.getString("客户公司名【基础】");
+                customerName = customerName.replace("\n",""); //去除换行符
+                customerName = customerName.trim(); //去除空格
+                if(StringUtils.isEmpty(customerName)){
+                    isCustomerNameEmpty = true;
+                }
+            }
+            if(isCustomerNameEmpty){
+                customerEmptyCount++;
+//                throw new RuntimeException("客户公司名【基础】字段为空");
+                continue;
+            }else{
+//                System.out.println("客户名称="+customerName);
+            }
+
+            /*
+                获取业务员数据
+             */
+            if(fields.get("业务【人事】") == null){
+                isBusinessUserEmpty = true;
+            }else{
+                businessUserJSONArray = fields.getJSONArray("业务【人事】");
+                if(businessUserJSONArray.isEmpty()){
+                    isBusinessUserEmpty = true;
+                }else{
+                    if(businessUserJSONArray.size()>1){ //一个客户有多个业务员负责对接
+                        log.info("客户名称="+customerName+",业务员数量="+businessUserJSONArray.size());
+                    }
+                    businessUserUnionId = businessUserJSONArray.getJSONObject(0).getString("unionId");
+                    businessUserName = businessUserJSONArray.getJSONObject(0).getString("name");
+                }
+            }
+//            System.out.println("业务员是否为空="+isBusinessUserEmpty);
+            if(isBusinessUserEmpty){
+//                throw new RuntimeException("业务【人事】字段为空");
+            }else{
+//                System.out.println("业务员="+businessUser);
+            }
+
+            /*
+                获取客户分级
+             */
+            customerLevel = "";
+            if(fields.get("客户分级【客户】") != null){
+                customerLevel = fields.getJSONObject("客户分级【客户】").getString("name");
+                if(
+                        "A".equals(customerLevel)
+                                ||"潜A".equals(customerLevel)
+                                ||"B".equals(customerLevel)
+                                ||"潜B".equals(customerLevel)
+                                ||"C".equals(customerLevel)
+                                ||"潜C".equals(customerLevel)
+                                ||"D".equals(customerLevel)
+                                ||"潜D".equals(customerLevel)
+                ){
+                    //不变
+                }else if("E".equals(customerLevel)){
+                    customerLevel = "保稳E";
+                }else{
+                    customerLevel = "";
+                }
+            }
+
+            /*
+                获取新老客户
+             */
+            newOrOld = "";
+            if(fields.get("新老客户?【客户】") != null){
+                newOrOld = fields.getJSONObject("新老客户?【客户】").getString("name");
+                if(newOrOld.contains("新")){
+                    newOrOld = "新";
+                }
+                if(newOrOld.contains("老")){
+                    newOrOld = "老";
+                }
+                if(newOrOld.contains("不合作")){
+                    newOrOld = "不合作";
+                }
+            }
+
+            /*
+                获取KP数据
+             */
+            /*
+            if(fields.get("一把手KP") == null){
+                isKpEmpty = true;
+            }else{
+                kp = fields.getString("一把手KP");
+            }
+//            System.out.println("KP是否为空="+isKpEmpty);
+            if(isKpEmpty){
+//                throw new RuntimeException("一把手KP字段为空");
+            }else{
+//                System.out.println("KP="+kp);
+            }
+             */
+
+            /*
+                汇总客户数据
+             */
+            customerRecord = new HashMap<>();
+            customerRecord.put("aiTableId",aiTableId);
+            customerRecord.put("customerName",customerName);
+            customerRecord.put("businessUserName",businessUserName);
+            customerRecord.put("businessUserUnionId",businessUserUnionId);
+//            customerRecord.put("kp",kp);
+//            System.out.println(JSONObject.toJSONString(customerRecord));
+            customerRecord.put("customerLevel",customerLevel);
+            customerRecord.put("newOrOld",newOrOld);
+//            System.out.println(aiTableId+","+customerLevel+","+newOrOld);
+            customerData.add(customerRecord);
+        }
+        log.info("客户名称为空的记录数="+customerEmptyCount);
+
+        /*
+            排除有重复的客户
+         */
+        for (Map<String, String> record : customerData) {
+            customerName = record.get("customerName");
+            customerNameCountMap.merge(customerName, 1L, Long::sum);
+        }
+        for (Map.Entry<String, Long> entry : customerNameCountMap.entrySet()) {
+            if (entry.getValue() > 1) {
+                System.out.println("客户名称="+entry.getKey()+",重复次数="+ entry.getValue());
+            }
+        }
+        for (Map<String, String> record : customerData) {
+            customerName = record.get("customerName");
+            if(customerNameCountMap.get(customerName)==1){
+                customerDataDeduplicate.add(record);
+            }
+        }
+
+
+        /*
+            返回客户数据(去重)
+         */
+        return customerDataDeduplicate;
+    }
+
+    @Override
+    public String querySys1CustomerIdByName(String customerName) throws Exception {
+        /*
+            参数定义
+         */
+        String baseId; //AI表格文档ID
+        String sheetIdOrName;   //数据表ID或数据表名称
+        Map<String,Object> param = new HashMap<>(); //HTTP请求参数
+        AITableParam aiTableParam = new AITableParam(); //HTTP请求体
+        AITableResult aiTableResult;    //请求返回内容
+        JSONArray records;  //记录数据
+        String customerId = "";  //客户名册记录ID
+
+        /*
+            项目总表
+         */
+        baseId = "G53mjyd80pEr5grBfpjmMX6586zbX04v";
+        sheetIdOrName = "E6RcJi3";
+
+
+        /*
+            项目总表副本-20260409
+         */
+//        baseId = "GZLxjv9VGqBAMDOoHYzrPZzE86EDybno";
+//        sheetIdOrName = "E6RcJi3";
+
+        /*
+            初始化参数值
+         */
+        param.put("operatorId","aj1wcWqKLXITiPDwbMIjUbAiEiE");  //操作人(Jason)的unionId
+        JSONObject filter = new JSONObject();
+        JSONArray conditions = new JSONArray();
+        JSONObject condition = new JSONObject();
+        condition.put("field","20rO7zS");
+        condition.put("operator","equal");
+        condition.put("value",new String[]{customerName});
+        conditions.add( condition);
+        filter.put("conditions",conditions);
+        aiTableParam.setFilter(filter);
+
+        /*
+            获取数据
+         */
+        log.info(JSONObject.toJSONString(aiTableParam));
+        aiTableResult = mdTableClient.queryMultiRecords(baseId,sheetIdOrName,param,aiTableParam);
+        log.info(JSONObject.toJSONString(aiTableResult));
+        records = aiTableResult.getRecords();
+        if(records!=null && !records.isEmpty()){
+            customerId = records.getJSONObject(0).getString("id");
+        }
+        return customerId;
+    }
+
+    @Override
+    public String addSys1CustomerData(Map<String, Object> fields) throws Exception {
+        /*
+            参数定义
+         */
+        String baseId; //AI表格文档ID
+        String sheetIdOrName;   //数据表ID或数据表名称
+        Map<String,Object> param = new HashMap<>(); //HTTP请求参数
+        JSONObject insertData = new JSONObject();   //HTTP请求体
+        JSONArray insertRecords = new JSONArray();  //新增记录集合
+        JSONObject insertRecord = new JSONObject();      //新增记录行数据
+        String result;  //返回结果
+        JSONObject resultJSONObject;
+        JSONArray aitableIdJSONArray;
+        String aitableId = "";   //AI表格记录ID
+
+        /*
+            项目总表
+         */
+        baseId = "G53mjyd80pEr5grBfpjmMX6586zbX04v";
+        sheetIdOrName = "E6RcJi3";
+
+        /*
+            初始化参数值
+         */
+        param.put("operatorId","aj1wcWqKLXITiPDwbMIjUbAiEiE");  //操作人(Jason)的unionId
+        insertRecord.put("fields",fields);
+        insertRecords.add(insertRecord);
+        insertData.put("records",insertRecords);
+
+        /*
+            新增数据
+         */
+        log.info(JSONObject.toJSONString(insertData));
+        result = mdTableClient.createMultiRecords(baseId,sheetIdOrName,param,insertData);
+        log.info(result);
+        resultJSONObject = JSONObject.parseObject(result);
+        aitableIdJSONArray = resultJSONObject.getJSONArray("value");
+        if(aitableIdJSONArray!=null || !aitableIdJSONArray.isEmpty()){
+            aitableId = aitableIdJSONArray.getJSONObject(0).getString("id");
+        }
+        return aitableId;
+    }
+
+    @Override
+    public String updateSys1CustomerData(String id,Map<String, Object> fields) throws Exception {
+        /*
+            参数定义
+         */
+        String baseId; //AI表格文档ID
+        String sheetIdOrName;   //数据表ID或数据表名称
+        Map<String,Object> param = new HashMap<>(); //HTTP请求参数
+        JSONObject updateData = new JSONObject();   //HTTP请求体
+        JSONArray updateRecords = new JSONArray();  //更新记录集合
+        JSONObject updateRecord = new JSONObject();      //更新记录行数据
+        String result;  //返回结果
+
+        /*
+            项目总表
+         */
+        baseId = "G53mjyd80pEr5grBfpjmMX6586zbX04v";
+        sheetIdOrName = "E6RcJi3";
+
+        /*
+            初始化参数值
+         */
+        param.put("operatorId","aj1wcWqKLXITiPDwbMIjUbAiEiE");  //操作人(Jason)的unionId
+        updateRecord.put("id",id);
+        updateRecord.put("fields",fields);
+        updateRecords.add(updateRecord);
+        updateData.put("records",updateRecords);
+
+        /*
+            更新数据
+         */
+        log.info(JSONObject.toJSONString(updateData));
+        result = mdTableClient.modifyMultiRecords(baseId,sheetIdOrName,param,updateData);
+        log.info(result);
+        return result;
+    }
+
+    @Override
+    public String addSys1SaleData(Map<String,Object> fields) throws Exception {
+        /*
+            参数定义
+         */
+        String baseId; //AI表格文档ID
+        String sheetIdOrName;   //数据表ID或数据表名称
+        Map<String,Object> param = new HashMap<>(); //HTTP请求参数
+        JSONObject insertData = new JSONObject();   //HTTP请求体
+        JSONArray insertRecords = new JSONArray();  //新增记录集合
+        JSONObject insertRecord = new JSONObject();      //新增记录行数据
+        String result;  //返回结果
+        JSONObject resultJSONObject;
+        JSONArray aitableIdJSONArray;
+        String aitableId = "";   //AI表格记录ID
+
+        /*
+            项目总表
+         */
+        baseId = "G53mjyd80pEr5grBfpjmMX6586zbX04v";
+        sheetIdOrName = "C1mtX34";
+
+        /*
+            项目总表副本-20260409
+         */
+//        baseId = "GZLxjv9VGqBAMDOoHYzrPZzE86EDybno";
+//        sheetIdOrName = "C1mtX34";  //售前台账
+
+        /*
+            初始化参数值
+         */
+        param.put("operatorId","aj1wcWqKLXITiPDwbMIjUbAiEiE");  //操作人(Jason)的unionId
+        insertRecord.put("fields",fields);
+        insertRecords.add(insertRecord);
+        insertData.put("records",insertRecords);
+
+        /*
+            新增数据
+         */
+        log.info(JSONObject.toJSONString(insertData));
+        result = mdTableClient.createMultiRecords(baseId,sheetIdOrName,param,insertData);
+        log.info(result);
+        resultJSONObject = JSONObject.parseObject(result);
+        aitableIdJSONArray = resultJSONObject.getJSONArray("value");
+        if(aitableIdJSONArray!=null || !aitableIdJSONArray.isEmpty()){
+            aitableId = aitableIdJSONArray.getJSONObject(0).getString("id");
+        }
+        return aitableId;
+    }
+
+    @Override
+    public String updateSys1SaleData(String id,Map<String, Object> fields) throws Exception {
+        /*
+            参数定义
+         */
+        String baseId; //AI表格文档ID
+        String sheetIdOrName;   //数据表ID或数据表名称
+        Map<String,Object> param = new HashMap<>(); //HTTP请求参数
+        JSONObject updateData = new JSONObject();   //HTTP请求体
+        JSONArray updateRecords = new JSONArray();  //更新记录集合
+        JSONObject updateRecord = new JSONObject();      //更新记录行数据
+        String result;  //返回结果
+
+        /*
+            项目总表
+         */
+        baseId = "G53mjyd80pEr5grBfpjmMX6586zbX04v";
+        sheetIdOrName = "C1mtX34";
+
+        /*
+            初始化参数值
+         */
+        param.put("operatorId","aj1wcWqKLXITiPDwbMIjUbAiEiE");  //操作人(Jason)的unionId
+        updateRecord.put("id",id);
+        updateRecord.put("fields",fields);
+        updateRecords.add(updateRecord);
+        updateData.put("records",updateRecords);
+
+        /*
+            更新数据
+         */
+        log.info(JSONObject.toJSONString(updateData));
+        result = mdTableClient.modifyMultiRecords(baseId,sheetIdOrName,param,updateData);
+        log.info(result);
+        return result;
+    }
+
+
+}

+ 97 - 0
src/main/java/com/malk/eastar/service/impl/DDCoreClientImpl.java

@@ -0,0 +1,97 @@
+package com.malk.eastar.service.impl;
+
+import cn.hutool.core.date.DateUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.malk.eastar.service.DDCoreClient;
+import com.malk.server.dingtalk.DDR;
+import com.malk.service.dingtalk.DDClient;
+import com.malk.service.dingtalk.DDClient_Contacts;
+import com.malk.utils.UtilMap;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+
+/**
+ * 钉钉核心数据处理客户端接口实现
+ * add by Jason 20260414
+ */
+@Service
+public class DDCoreClientImpl implements DDCoreClient {
+
+    @Autowired
+    private DDClient ddClient;
+
+    @Autowired
+    private DDClient_Contacts ddClientContacts;
+
+    @Override
+    public String getNameByUserId(String userId) throws Exception {
+        String name = "";
+        Map result = ddClientContacts.getUserInfoById(ddClient.getAccessToken(),userId);
+        if(result != null){
+            name = UtilMap.getString(result, "name");
+        }
+        return name;
+    }
+
+    @Override
+    public List getDeptIdListByUserId(String userId) throws Exception {
+        List deptIdList = new ArrayList();
+        Map result = ddClientContacts.getUserInfoById(ddClient.getAccessToken(),userId);
+        if(result != null){
+            deptIdList = UtilMap.getList(result, "dept_id_list");
+        }
+        return deptIdList;
+    }
+
+    @Override
+    public String getUnionIdByUserId(String userId) throws Exception {
+        String unionid = "";
+        Map result = ddClientContacts.getUserInfoById(ddClient.getAccessToken(),userId);
+        if(result != null){
+            unionid = UtilMap.getString(result, "unionid");
+        }
+        return unionid;
+    }
+
+    @Override
+    public String getUserIdByUnionId(String unionId) throws Exception {
+        String userId = "";
+        String url = "https://oapi.dingtalk.com/topapi/user/getbyunionid";
+        Map param = UtilMap.map("access_token", ddClient.getAccessToken());
+        Map body = UtilMap.map("unionid", unionId);
+        Map result = (Map) DDR.doPost(url, null, param, body).getResult();
+        if(result != null){
+            userId = UtilMap.getString(result, "userid");
+        }
+        return userId;
+    }
+
+    @Override
+    public List<Map<String, String>> getLeaveEmployeeData(Date startTime, Date endTime) throws Exception {
+        Map extInfo = new HashMap();
+        extInfo.put("endTime", endTime);
+        List<Map<String, String>> leaveEmployeeRecords = ddClientContacts.getLeaveEmployeeRecords(ddClient.getAccessToken(), startTime, extInfo);
+        return leaveEmployeeRecords;
+    }
+
+    @Override
+    public List<Map<String, String>> getAllLeaveEmployeeData() throws Exception {
+        List<Map<String, String>> leaveEmployeeData = new ArrayList<>();
+        Date startTime;
+        Date endTime;
+        Map extInfo;
+        List<Map<String, String>> leaveEmployeeRecords;
+        String[] years = new String[]{"2025", "2026"};
+        for(String year:years){
+            startTime = DateUtil.parse(year+"-01-01");
+            extInfo = new HashMap();
+            endTime = DateUtil.parse(year+"-12-31");
+            extInfo.put("endTime", endTime);
+            leaveEmployeeRecords = ddClientContacts.getLeaveEmployeeRecords(ddClient.getAccessToken(), startTime, extInfo);
+            leaveEmployeeData.addAll(leaveEmployeeRecords);
+        }
+        return leaveEmployeeData;
+    }
+}

+ 138 - 10
src/main/java/com/malk/eastar/service/impl/EastarTbServiceImpl.java

@@ -18,6 +18,7 @@ import com.malk.service.teambition.TBClient_User;
 import com.malk.utils.PublicUtil;
 import com.malk.utils.UtilMap;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -98,6 +99,7 @@ public class EastarTbServiceImpl  implements EastarTbService {
         String pMainId= UtilMap.getString(data,"textField_me2hyldb");// 主项目编号
         String pName= UtilMap.getString(data,"textField_me87x1nz"); // 项目名称
         String pId= UtilMap.getString(data,"textField_me2hyldc");// 项目编号
+        String devNumFlag = UtilMap.getString(data,"radioField_mmkb0vkc");  //研发部是否需要留样 add by Jason 20260327
         String orderType= UtilMap.getString(data,"selectField_mdf997wp"); // 订单类型 大货 打样
 //        String pTaskType= UtilMap.getAssFieldValue(data,"associationFormField_me9n24kk_id").get(0).title; // 项目任务类型
         String pTaskType = UtilMap.getString(data,"textField_mfqnsa9d");// 项目任务类型
@@ -136,6 +138,16 @@ public class EastarTbServiceImpl  implements EastarTbService {
         }else {
             tbProjectId = UtilMap.getString(UtilMap.getMap(recodList.get(0),"formData"),"textField_mecmytpo");
         }
+
+        // 获取【立项/项目台账】子表单【语言版本 - 数量拆分】数据 add by Jason 20260320 start
+        List<Map> projectSubDataLang = ydService.queryDetails(
+                YDParam.builder()
+                        .formInstanceId(formInstId)
+                        .formUuid(EastarParam.YD_FORMUUID_PROJECT)
+                        .tableFieldId("tableField_mn6vamoe").build()
+        );
+        // 获取【立项/项目台账】子表单【语言版本 - 数量拆分】数据 add by Jason 20260320 end
+
         // 订单数据
         List<UtilMap.assDetail> projectOrder=UtilMap.getAssFieldValue(data,"associationFormField_me2hylda_id");
         String orderFid= projectOrder.get(0).instanceId; // 项目任务类型
@@ -143,6 +155,7 @@ public class EastarTbServiceImpl  implements EastarTbService {
         List<Map> orderLangConf=UtilMap.getList(orderData,"tableField_meqqj4we");// 语言配置
         List<Map> xlConf=UtilMap.getList(orderData,"tableField_mesc7nvj");// 系列源配置
 
+
         // 子任务拆分数据
         List<Map> sonConfData= ydService.queryDetails(YDParam.builder().formInstanceId("FINST-X1B66Y81IUFY9U417XIUE99I8YV93HGMJ8WEMF").formUuid(EastarParam.YD_FORMUUID_SONCONF).tableFieldId("tableField_mew7d9f3").build());// 全品类配件表
         Map<String,Map<String,List<String>>>  sonConf= ConfigDataProcessor.processConfigData(sonConfData);
@@ -223,12 +236,29 @@ public class EastarTbServiceImpl  implements EastarTbService {
         String sonScenariofieldconfigId=_getTaskType(tbProjectId,"配件-子任务");
         String tasklistId=_getTaskList(tbProjectId,orderType+"项目");
         String stageId= tbTask.queryTaskStage(tbProjectId,tasklistId,"启动阶段");
+
+        /*
+            获取系列语言与研发部订单需求数量映射
+         */
+        Map<String,String> seriesLangDevNumMap = new HashMap<>();  //系列与研发部订单需求数量映射数据 add by Jason 20260320
+        String nameSeries;  //系列 add by Jason 20260320
+        String nameLang;    //语言  add by Jason 20260326
+        String devNum;  //研发部订单需求数量 add by Jason 20260320
+        for(Map projectSubRecordLang : projectSubDataLang) { //遍历【立项/项目台账】子表单【语言版本 - 数量拆分】数据
+            nameSeries = UtilMap.getString(projectSubRecordLang,"textField_mn6vamof");    //系列
+            nameLang = UtilMap.getString(projectSubRecordLang,"textField_mn6vamoh");    //语言
+            if(PublicUtil.isNull(nameLang)){
+                nameLang = "无";
+            }
+            devNum = UtilMap.getString(projectSubRecordLang,"numberField_mn6vamok");   //研发部订单需求数量
+            seriesLangDevNumMap.putIfAbsent(nameSeries + "_" + nameLang, devNum);
+        }
+
         // 全品类任务生成
         List<Map> table= ydService.queryDetails(YDParam.builder().formInstanceId(formInstId).formUuid(EastarParam.YD_FORMUUID_PROJECT).tableFieldId("tableField_mdy8x198").build());// 全品类配件表
         List<Map> recodTable = new ArrayList<>();
         List<String> jds=UtilMap.getList(data,"checkboxField_me9n37rs");
         Map<String,List<Map>> gysOrderData=new HashMap<>(); // 采购需求数据  按照供应商拆分BOM
-
         for(Map map:table){
             Map taskMap=UtilMap.map("projectId, tasklistId, scenariofieldconfigId, stageId",tbProjectId,tasklistId,scenariofieldconfigId,stageId);
             taskMap.put("content",getValue(map,"selectField_me2f7tw4","-")+getValue(map,"textField_me2f7tvo","")); //系列 配件
@@ -252,9 +282,9 @@ public class EastarTbServiceImpl  implements EastarTbService {
                 }
             }
             if(isLang){ // 区分语言
-                result=saveTbTask(taskMap,orderLangConf,map,customfields,isLang,sonconf,sonScenariofieldconfigId,gysName,pId,pMainId,skuIdMap);
+                result=saveTbTask(taskMap,orderLangConf,map,customfields,isLang,sonconf,sonScenariofieldconfigId,gysName,pId,pMainId,skuIdMap,seriesLangDevNumMap);
             }else{
-                result=saveTbTask(taskMap,xlConf,map,customfields,isLang,sonconf,sonScenariofieldconfigId,gysName,pId,pMainId,skuIdMap);
+                result=saveTbTask(taskMap,orderLangConf,map,customfields,isLang,sonconf,sonScenariofieldconfigId,gysName,pId,pMainId,skuIdMap,seriesLangDevNumMap);
             }
             if(gysOrderData.containsKey(gysName)){
                 gysOrderData.get(gysName).addAll(result);
@@ -268,6 +298,8 @@ public class EastarTbServiceImpl  implements EastarTbService {
         List<String> jdList=Arrays.asList("白样", "产前样","大货样", "大货");
         Object demoValue = orderData.get("textField_me2f7tvd");
         //        项目阶段处理
+        String numOfSets;   //工厂采购数量 add by Jason 20260320
+        int allSupplyNum;   //总采购数量 add by Jason 20260320
         for(String jd:jds){
             System.out.println("项目阶段:"+jd);
            if(jdList.contains(jd)){
@@ -291,7 +323,21 @@ public class EastarTbServiceImpl  implements EastarTbService {
                            procuremenType ="配件采购";
                            taskStatus ="待排期";
                            taskType ="大货";
+                           //计算总采购数量 add by Jason 20260320 start
+                           numOfSets = map.get("numberField_mifp03el")==null?null:map.get("numberField_mifp03el").toString();
+                           devNum = map.get("numberField_mmmwu4cg")==null?null:map.get("numberField_mmmwu4cg").toString();
+                           allSupplyNum = 0;
+                           if(StringUtils.isNotEmpty(numOfSets)){
+                               if(StringUtils.isNotEmpty(devNum)){ //研发部订单需求数量是否填写 add by Jason 20260327
+                                   allSupplyNum = Integer.parseInt(devNum) + Integer.parseInt(numOfSets);  //计算总采购数量
+                               }else{
+                                   allSupplyNum = Integer.parseInt(numOfSets); //总采购数量=工厂采购数量
+                               }
+                           }
+                           //计算总采购数量 add by Jason 20260320 end
                            Map<String, Object> copiedMap = new HashMap<>(map); // 关键:创建副本
+                           copiedMap.put("numberField_mmmwu4ci",0);    //总采购数量(废弃) add by Jason 20260320 edit by Jason 20260327
+                           copiedMap.put("numberField_mifp03el",allSupplyNum);   //工厂采购数量 add by Jason 20260327
                            copiedMap.put("dateField_mizvc5oi", planTimestamp);
                            modifiedList.add(copiedMap);
                        } else{
@@ -306,6 +352,8 @@ public class EastarTbServiceImpl  implements EastarTbService {
                            copiedMap.put("dateField_mizvc5oi", planTimestamp);
                            copiedMap.put("numberField_mkosp94h", demoValue);
                            copiedMap.put("numberField_mifp03el", demoValue);
+                           copiedMap.put("numberField_mmmwu4cg",0);    //研发部订单需求数量 add by Jason 20260320
+                           copiedMap.put("numberField_mmmwu4ci",0);    //总采购数量(废弃) add by Jason 20260320 edit by Jason 20260327
                            modifiedList.add(copiedMap);
                        }
                    }
@@ -333,26 +381,89 @@ public class EastarTbServiceImpl  implements EastarTbService {
         }
 //        生成包装任务:打样不需要生成包装
         if("大货".equals(orderType)){
-            savePackTask(tbProjectId, orderLangConf, data, pName, pId, pMainId, projectOrder, mchDDIdMap);
+            //seriesDevNumMap 系列与研发部订单需求数量映射数据 add by Jason 20260320
+            savePackTask(tbProjectId, orderLangConf, data, pName, pId, pMainId, projectOrder, mchDDIdMap, seriesLangDevNumMap);
+        }
+
+        if("是".equals(devNumFlag)) {  //研发部需要留样 add by Jason 20260327
+            //更新【制作新订单】子表单【语言版本 - 数量拆分】的总套数 add by Jason 20260320 start
+            List<Map> orderSubDataLangNew = new ArrayList<>();
+            int numOfSetsSeries;    //套数
+            int numOfSetsAll;   //总套数
+            for(Map orderSubRecordLang : orderLangConf){  //遍历子表单记录
+                nameSeries = UtilMap.getString(orderSubRecordLang,"textField_meqqj4wa");    // 系列【语言版本 - 数量拆分】
+                nameLang = UtilMap.getString(orderSubRecordLang,"textField_meqqj4wb"); // 语言【语言版本 - 数量拆分】 add by Jason 20260326
+                numOfSetsSeries = UtilMap.getInt(orderSubRecordLang,"numberField_meqqj4wd");    // 套数【语言版本 - 数量拆分】
+                numOfSetsAll = 0;
+                if(PublicUtil.isNull(nameLang)){
+                    devNum = seriesLangDevNumMap.get(nameSeries+"_无");   //研发部订单需求数量
+                }else{
+                    devNum = seriesLangDevNumMap.get(nameSeries+"_"+nameLang);   //研发部订单需求数量
+                }
+                if(StringUtils.isNotEmpty(devNum)){
+                    numOfSetsAll = numOfSetsSeries + Integer.parseInt(devNum);    // 总套数【语言版本 - 数量拆分】,总套数=套数+研发部订单数量,立项完成自动更新总套数
+                }
+                orderSubRecordLang.put("numberField_mmtymctd",numOfSetsAll);
+                orderSubDataLangNew.add(orderSubRecordLang);
+            }
+            System.out.println("更新【制作新订单】数据:"+ JSONObject.toJSONString(orderSubDataLangNew));
+            ydClient.operateData(
+                    YDParam.builder()
+                            .formInstId(orderFid)
+                            .updateFormDataJson(
+                                    JSONObject.toJSONString(UtilMap.map("tableField_meqqj4we",orderSubDataLangNew))
+                            ).build(),
+                    YDConf.FORM_OPERATION.update
+            );
+            //更新【制作新订单】子表单【语言版本 - 数量拆分】的总套数 add by Jason 20260320 end
         }
+
         return Collections.emptyMap();
     }
 
 //    生成包装任务
-    private List<Map> savePackTask(String tbProjectId, List <Map> orderLangConf,Map data,String pName,String pId,String pMainId,List projectOrder,Map mchDDIdMap) {
+    //seriesDevNumMap 系列与研发部订单需求数量映射数据 add by Jason 20260320
+    private List<Map> savePackTask(String tbProjectId, List <Map> orderLangConf,Map data,String pName,String pId,String pMainId,List projectOrder,Map mchDDIdMap,Map<String,String> seriesDevNumMap) {
         Map<String, List<Map>> packOrderData = new HashMap<>();
+        String nameSeries;  //系列 add by Jason 20260320
+        String nameLang;    //语言 add by Jason 20260326
+        String devNum;  //研发部订单需求数量 add by Jason 20260320
+        int allSupplyNum;   //总采购数量 add by Jason 20260320
         for (Map orderMap : orderLangConf) {
             String supplier = UtilMap.getString(orderMap, "textField_mkp7yv76");
             String setsValue = UtilMap.getString(orderMap, "numberField_meqqj4wd");
+
+            nameLang = UtilMap.getString(orderMap,"textField_meqqj4wb"); // 语言【语言版本 - 数量拆分】 add by Jason 20260326
+            //计算总采购数量 add by Jason 20260320 start
+            nameSeries = UtilMap.getString(orderMap, "textField_meqqj4wa");   //系列
+            if(PublicUtil.isNull(nameLang)){
+                devNum = seriesDevNumMap.get(nameSeries+"_无");
+            }else{
+                devNum = seriesDevNumMap.get(nameSeries+"_"+nameLang);
+            }
+            allSupplyNum = 0;
+            if(StringUtils.isNotEmpty(setsValue)){
+                if(StringUtils.isNotEmpty(devNum)){ //研发部订单需求数量是否填写 add by Jason 20260327
+                    allSupplyNum = Integer.parseInt(devNum) + Integer.parseInt(setsValue);  //计算总采购数量
+                }else{
+                    allSupplyNum = Integer.parseInt(setsValue);  //总采购数量=工厂采购数量
+                }
+            }
+            //计算总采购数量 add by Jason 20260320 end
+
             Map packTask = UtilMap.map(
-                    "textField_mecmytpr, textField_mifp03eo, textField_mjr129o4, selectField_me2f7tw4, numberField_mkosp94h, numberField_mifp03el, numberField_me2f7tw0",
+                    "textField_mecmytpr, textField_mifp03eo, textField_mjr129o4, selectField_me2f7tw4, numberField_mkosp94h, numberField_mifp03el, " +
+                            "numberField_mmmwu4cg, " + //研发部订单需求数量 add by Jason 20260312
+                            "numberField_mmmwu4ci, ", //总采购数量(废弃) add by Jason 20260312 edit by Jason 20260327
                     UtilMap.getString(orderMap, "textField_mizmmf8k"),
                     UtilMap.getString(orderMap, "textField_mizmmf8j"),
                     UtilMap.getString(orderMap, "textField_meqqj4wb"),
                     UtilMap.getString(orderMap, "textField_meqqj4wa"),
                     setsValue,
-                    setsValue,
-                    UtilMap.getString(orderMap, "numberField_mkf4bc4j")
+                    allSupplyNum,   //工厂采购数量 edit by Jason 20260327
+                    devNum, //研发部订单需求数量 add by Jason 20260320
+                    0 //总采购数量(废弃) add by Jason 20260320 edit by Jason 20260327
+
             );
             packOrderData.computeIfAbsent(supplier, k -> new ArrayList<>()).add(packTask);
         }
@@ -385,12 +496,13 @@ public class EastarTbServiceImpl  implements EastarTbService {
         return value.length()==0?"":value+s;
     }
 
-    private List<Map> saveTbTask(Map taskMap,List<Map> orderConf,Map cgDetail,List<Map> customfields,boolean isLang,List<String> sonconf,String sonScenariofieldconfigId,String gysName,String pId,String pMainId,Map skuIdMap){
+    private List<Map> saveTbTask(Map taskMap,List<Map> orderConf,Map cgDetail,List<Map> customfields,boolean isLang,List<String> sonconf,String sonScenariofieldconfigId,String gysName,String pId,String pMainId,Map skuIdMap,Map<String,String> seriesLangDevNumMap){
         log.info("创建任务:{},是否区分语言{}",taskMap.get("content"),isLang);
         List<Map> recodTable=new ArrayList<>();
         if (PublicUtil.isNull(taskMap,"executorId")){
             taskMap.remove("executorId");
         }
+        String rdNum; //研发部订单需求数量 add by Jason 20260312
         for(Map map: orderConf){
             Map tMap=new HashMap();
             tMap.putAll(taskMap);
@@ -404,6 +516,15 @@ public class EastarTbServiceImpl  implements EastarTbService {
             skuId=PublicUtil.isNull(skuId)?"000":skuId;
             String sku="2"+skuId+UtilMap.getString_first(map,"textField_mizmmf8h","textField_mizmmf8m")+reportId.substring(reportId.length()-2);// sku 添加系列编号及文档编号
             String lang=UtilMap.getString(map,"textField_meqqj4wb"); // 语言
+
+            //获取系列语言对应的研发部订单需求数量 add by Jason 20260326 start
+            if(PublicUtil.isNull(lang)){
+                rdNum = seriesLangDevNumMap.get(confSeries+"_无");   //研发部订单需求数量
+            }else{
+                rdNum = seriesLangDevNumMap.get(confSeries+"_"+lang);   //研发部订单需求数量
+            }
+            //获取系列语言对应的研发部订单需求数量 add by Jason 20260326 end
+
             if(isLang){
                 if(PublicUtil.isNull(lang)){
                     lang="不区分";
@@ -424,7 +545,14 @@ public class EastarTbServiceImpl  implements EastarTbService {
             log.info("最终任务名称:{},详细参数:{}",tMap.get("content"),tMap);
             Map result=tbTask.createTask(tbConf.getOperatorId(), tMap);// 更新任务所属任务列表
             Map recod=new HashMap(cgDetail);
-            recod.putAll(UtilMap.map("textField_mecmytpr, textField_mecmytps, textField_mecmytpt, numberField_mifp03el, textField_mifp03eo, textField_miib17jx, textField_mizvc5oj, textField_mjr129o4, numberField_mkosp94h",result.get("content"),result.get("taskId"),"未开始",value,sku,pId,result.get("taskId"),lang,value));
+            recod.putAll(
+                    UtilMap.map(
+                            "textField_mecmytpr, textField_mecmytps, textField_mecmytpt, numberField_mifp03el, " +
+                                    "numberField_mmmwu4cg, " + //研发部订单需求数量 add by Jason 20260312
+                                    "textField_mifp03eo, textField_miib17jx, textField_mizvc5oj, textField_mjr129o4, numberField_mkosp94h, numberField_me2f7tw0",
+                            result.get("content"),result.get("taskId"),"未开始",value,
+                            rdNum, //研发部订单需求数量 add by Jason 20260312
+                            sku,pId,result.get("taskId"),lang,value,UtilMap.getString(map, "numberField_mkf4bc4j")));
             recodTable.add(recod);
 //            for (String son:sonconf){
 //                Map sonMap=new HashMap();

+ 59 - 0
src/main/java/com/malk/eastar/service/impl/MDTableClientImpl.java

@@ -0,0 +1,59 @@
+package com.malk.eastar.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.malk.eastar.model.AITableParam;
+import com.malk.eastar.model.AITableResult;
+import com.malk.eastar.service.MDTableClient;
+import com.malk.service.dingtalk.DDClient;
+import com.malk.utils.UtilHttp;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * AI表格数据处理客户端接口实现
+ * add by Jason 20260313
+ */
+@Service
+public class MDTableClientImpl implements MDTableClient {
+
+    @Autowired
+    private DDClient ddClient;
+
+    private String getRequestUrl(String uri) {
+        return "https://api.dingtalk.com/v1.0/notable" + uri;
+    }
+
+    private Map initBodyParam(AITableParam aiTableParam) {
+        return (Map) JSONObject.parseObject(JSONObject.toJSONString(aiTableParam), Map.class);
+    }
+
+    @Override
+    public AITableResult queryMultiRecords(String baseId, String sheetIdOrName, Map<String,Object> param, AITableParam aiTableParam) {
+        String url = getRequestUrl("/bases/"+baseId+"/sheets/"+sheetIdOrName+"/records/list");
+        Map header = ddClient.initTokenHeader();
+        Map body = initBodyParam(aiTableParam);
+        AITableResult aiTableResult = (AITableResult) UtilHttp.doPost(url,header,param,body,AITableResult.class);
+        return aiTableResult;
+    }
+
+    @Override
+    public String createMultiRecords(String baseId, String sheetIdOrName, Map<String, Object> param, JSONObject body) {
+        String url = getRequestUrl("/bases/"+baseId+"/sheets/"+sheetIdOrName+"/records");
+        Map header = ddClient.initTokenHeader();
+        Map form = new HashMap();
+        String result = UtilHttp.doPost(url,header,param,body,form);
+        return result;
+    }
+
+    @Override
+    public String modifyMultiRecords(String baseId, String sheetIdOrName, Map<String, Object> param, JSONObject body) {
+        String url = getRequestUrl("/bases/"+baseId+"/sheets/"+sheetIdOrName+"/records");
+        Map header = ddClient.initTokenHeader();
+        String result = UtilHttp.doPut(url,header,param,body);
+        return result;
+    }
+
+}

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 2439 - 0
src/main/java/com/malk/eastar/service/impl/YidaServiceImpl.java


+ 1 - 1
src/test/java/TbTest.java

@@ -57,7 +57,7 @@ public class TbTest {
 
     @Test
     public void createTask() {
-        Map map=eastarTbService.createTask("90552600-4540-4352-88bf-e8377aaafe66");
+        Map map=eastarTbService.createTask("3b83493f-2e4f-429e-a71d-999228e23981");
     }
 
     @Autowired