pruple_boy hace 2 años
padre
commit
b2814e7092
Se han modificado 100 ficheros con 2800 adiciones y 1675 borrados
  1. 60 0
      mjava-guyuan/pom.xml
  2. 1 1
      mjava-minjiaoyuan/src/main/java/com/malk/minjiaoyuan/Boot.java
  3. 149 0
      mjava-guyuan/src/main/java/com.malk.guyuan/controller/GuYuanController.java
  4. 32 0
      mjava-guyuan/src/main/java/com.malk.guyuan/controller/IVController.java
  5. 64 0
      mjava-guyuan/src/main/resources/application-dev.yml
  6. 38 0
      mjava-guyuan/src/main/resources/application-prod.yml
  7. 64 0
      mjava-guyuan/target/classes/application-dev.yml
  8. 38 0
      mjava-guyuan/target/classes/application-prod.yml
  9. 41 5
      mjava-hangshi/pom.xml
  10. 66 66
      mjava-hangshi/src/main/java/com/malk/hangshi/config/CxfConfig.java
  11. 40 40
      mjava-hangshi/src/main/java/com/malk/hangshi/config/WsInInterceptor.java
  12. 71 71
      mjava-hangshi/src/main/java/com/malk/hangshi/config/WsOutInterceptor.java
  13. 114 0
      mjava-hangshi/src/main/java/com/malk/hangshi/controller/HSController.java
  14. 41 41
      mjava-hangshi/src/main/java/com/malk/hangshi/service/IH3yunWebService.java
  15. 46 46
      mjava-hangshi/src/main/java/com/malk/hangshi/service/impl/H3yunWebServiceImpl.java
  16. 5 5
      mjava-hangshi/src/main/resources/application-dev.yml
  17. 1 1
      mjava-hangshi/src/main/resources/application-prod.yml
  18. 5 5
      mjava-hangshi/target/classes/application-dev.yml
  19. 1 1
      mjava-hangshi/target/classes/application-prod.yml
  20. 5 5
      mjava-jisuanji/src/main/resources/application-dev.yml
  21. 5 5
      mjava-jisuanji/target/classes/application-dev.yml
  22. 5 5
      mjava-lichen/src/main/resources/application-dev.yml
  23. 1 1
      mjava-lichen/src/test/resources/server.sh
  24. 5 5
      mjava-lichen/target/classes/application-dev.yml
  25. 1 1
      mjava-lichen/target/test-classes/server.sh
  26. 0 98
      mjava-minjiaoyuan/src/main/java/com/malk/minjiaoyuan/controller/InviteControl.java
  27. 0 442
      mjava-minjiaoyuan/src/main/java/com/malk/minjiaoyuan/controller/MJYController.java
  28. 0 161
      mjava-minjiaoyuan/src/main/java/com/malk/minjiaoyuan/controller/TestControl.java
  29. 0 36
      mjava-minjiaoyuan/src/main/java/com/malk/minjiaoyuan/schedule/MJYScheduleTask.java
  30. 0 27
      mjava-minjiaoyuan/src/main/java/com/malk/minjiaoyuan/service/MJYService.java
  31. 0 169
      mjava-minjiaoyuan/src/main/java/com/malk/minjiaoyuan/service/impl/MJYImplService.java
  32. 0 65
      mjava-minjiaoyuan/src/main/resources/application-dev.yml
  33. 0 47
      mjava-minjiaoyuan/src/main/resources/application-prod.yml
  34. 0 65
      mjava-minjiaoyuan/target/classes/application-dev.yml
  35. 0 47
      mjava-minjiaoyuan/target/classes/application-prod.yml
  36. 11 2
      mjava-rongzhi/src/main/java/com/malk/rongzhi/controller/RongZhiController.java
  37. 1 1
      mjava-rongzhi/src/main/java/com/malk/rongzhi/schedule/RZScheduleTask.java
  38. 14 4
      mjava-rongzhi/src/main/java/com/malk/rongzhi/service/impl/RZServiceImpl.java
  39. 6 6
      mjava-rongzhi/src/main/resources/application-dev.yml
  40. 1 1
      mjava-rongzhi/src/main/resources/application-prod.yml
  41. 6 6
      mjava-rongzhi/target/classes/application-dev.yml
  42. 1 1
      mjava-rongzhi/target/classes/application-prod.yml
  43. 2 2
      mjava-minjiaoyuan/pom.xml
  44. 32 0
      mjava-shanghaishiwei/src/main/java/com/malk/shanghaishiwei/Boot.java
  45. 142 0
      mjava-shanghaishiwei/src/main/java/com/malk/shanghaishiwei/controller/SHHWController.java
  46. 26 0
      mjava-shanghaishiwei/src/main/java/com/malk/shanghaishiwei/server/HTConf.java
  47. 49 0
      mjava-shanghaishiwei/src/main/java/com/malk/shanghaishiwei/server/HTR.java
  48. 44 0
      mjava-shanghaishiwei/src/main/java/com/malk/shanghaishiwei/service/HTClient.java
  49. 18 0
      mjava-shanghaishiwei/src/main/java/com/malk/shanghaishiwei/service/HTService.java
  50. 87 0
      mjava-shanghaishiwei/src/main/java/com/malk/shanghaishiwei/service/impl/HTImplClient.java
  51. 107 0
      mjava-shanghaishiwei/src/main/java/com/malk/shanghaishiwei/service/impl/HTImplService.java
  52. 45 0
      mjava-shanghaishiwei/src/main/resources/application-dev.yml
  53. 28 0
      mjava-shanghaishiwei/src/main/resources/application-prod.yml
  54. 35 0
      mjava-shanghaishiwei/src/test/resources/server.sh
  55. 45 0
      mjava-shanghaishiwei/target/classes/application-dev.yml
  56. 28 0
      mjava-shanghaishiwei/target/classes/application-prod.yml
  57. 35 0
      mjava-shanghaishiwei/target/test-classes/server.sh
  58. 70 5
      mjava-xiding/src/main/java/com/malk/xiding/controller/XDController.java
  59. 3 1
      mjava-xiding/src/main/java/com/malk/xiding/repository/dao/XdDdApproveRecordDao2.java
  60. 2 0
      mjava-xiding/src/main/java/com/malk/xiding/repository/dao/XdDdFxkRelationDao.java
  61. 2 0
      mjava-xiding/src/main/java/com/malk/xiding/repository/dao/XdFxkDdAttendanceDao.java
  62. 10 4
      mjava-xiding/src/main/java/com/malk/xiding/repository/entity/XdFxkDdAttendancePo.java
  63. 10 19
      mjava-xiding/src/main/java/com/malk/xiding/schedule/XDScheduleTask.java
  64. 7 1
      mjava-xiding/src/main/java/com/malk/xiding/service/XDService.java
  65. 50 22
      mjava-xiding/src/main/java/com/malk/xiding/service/impl/XDImplService.java
  66. 7 7
      mjava-xiding/src/main/resources/application-dev.yml
  67. 1 1
      mjava-minjiaoyuan/src/test/resources/server.sh
  68. 55 0
      mjava-xiding/src/test/resources/winsw.xml
  69. 7 7
      mjava-xiding/target/classes/application-dev.yml
  70. 1 1
      mjava-minjiaoyuan/target/test-classes/server.sh
  71. 55 0
      mjava-xiding/target/test-classes/winsw.xml
  72. 18 0
      mjava-xintianlong/src/main/java/com/malk/xintianlong/controller/DDController.java
  73. 175 17
      mjava-xintianlong/src/main/java/com/malk/xintianlong/controller/HSController.java
  74. 64 0
      mjava-xintianlong/src/main/java/com/malk/xintianlong/delegate/DDDelegate.java
  75. 1 1
      mjava-xintianlong/src/main/java/com/malk/xintianlong/repository/dao/HSApproveRecordDao.java
  76. 47 0
      mjava-xintianlong/src/main/java/com/malk/xintianlong/repository/dao/HSViewDao.java
  77. 1 2
      mjava-xintianlong/src/main/java/com/malk/xintianlong/repository/entity/HSApproveRecordPo.java
  78. 19 2
      mjava-xintianlong/src/main/java/com/malk/xintianlong/schedule/HSScheduleTask.java
  79. 5 1
      mjava-xintianlong/src/main/java/com/malk/xintianlong/server/HSConf.java
  80. 1 1
      mjava-xintianlong/src/main/java/com/malk/xintianlong/service/HSService.java
  81. 2 2
      mjava-xintianlong/src/main/java/com/malk/xintianlong/service/impl/HSServiceImpl.java
  82. 35 16
      mjava-xintianlong/src/main/resources/application-dev.yml
  83. 33 11
      mjava-xintianlong/src/main/resources/application-prod.yml
  84. 55 0
      mjava-xintianlong/src/test/resources/winsw.xml
  85. 35 16
      mjava-xintianlong/target/classes/application-dev.yml
  86. 33 11
      mjava-xintianlong/target/classes/application-prod.yml
  87. 62 0
      mjava-xintianlong/target/generated-sources/java/com/malk/xintianlong/repository/entity/QHSApproveRecordPo.java
  88. 5 0
      mjava-xintianlong/target/maven-archiver/pom.properties
  89. 0 0
      mjava-xintianlong/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
  90. 12 0
      mjava-xintianlong/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
  91. BIN
      mjava-xintianlong/target/mjava-xintianlong.jar.original
  92. 55 0
      mjava-xintianlong/target/test-classes/winsw.xml
  93. 9 0
      mjava/src/main/java/com/malk/Filter/CatchException.java
  94. 8 3
      mjava/src/main/java/com/malk/Util/UtilDateTime.java
  95. 24 0
      mjava/src/main/java/com/malk/Util/UtilFile.java
  96. 99 36
      mjava/src/main/java/com/malk/Util/UtilMap.java
  97. 41 0
      mjava/src/main/java/com/malk/Util/UtilMc.java
  98. 2 2
      mjava/src/main/java/com/malk/base/BaseDao.java
  99. 17 2
      mjava/src/main/java/com/malk/base/BaseDto.java
  100. 0 0
      mjava/src/main/java/com/malk/base/BasePo.java

+ 60 - 0
mjava-guyuan/pom.xml

@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>java-mcli</artifactId>
+        <groupId>com.malk</groupId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>mjava-guyuan</artifactId>
+    <description>谷元发票功能开发, 查重验真, 混票识别</description>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+    </properties>
+
+    <dependencies>
+        <!-- 核心模块-->
+        <dependency>
+            <groupId>com.malk</groupId>
+            <artifactId>mjava</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <!-- go to https://search.maven.org/search?q=tencentcloud-sdk-java and get the latest version. -->
+        <dependency>
+            <groupId>com.tencentcloudapi</groupId>
+            <artifactId>tencentcloud-sdk-java</artifactId>
+            <version>3.1.322</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>2.1.1.RELEASE</version>
+                <configuration>
+                    <includeSystemScope>true</includeSystemScope>
+                    <!-- 如果没有该配置,devtools不会生效: 打包时关闭 -->
+                    <fork>false</fork>
+                    <!-- 避免中文乱码 -->
+                    <jvmArguments>-Dfile.encoding=UTF-8</jvmArguments>
+                </configuration>
+                <!-- 允许生成可运行jar -->
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+        <finalName>${project.artifactId}</finalName>
+    </build>
+</project>

+ 1 - 1
mjava-minjiaoyuan/src/main/java/com/malk/minjiaoyuan/Boot.java

@@ -1,4 +1,4 @@
-package com.malk.minjiaoyuan;
+package com.malk.guyuan;
 
 import com.querydsl.jpa.impl.JPAQueryFactory;
 import org.springframework.boot.SpringApplication;

+ 149 - 0
mjava-guyuan/src/main/java/com.malk.guyuan/controller/GuYuanController.java

@@ -0,0 +1,149 @@
+package com.malk.guyuan.controller;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.fastjson.JSON;
+import com.malk.Util.UtilServlet;
+import com.malk.server.aliwork.YDConf;
+import com.malk.server.aliwork.YDParam;
+import com.malk.server.common.McException;
+import com.malk.server.common.McR;
+import com.malk.server.dingtalk.DDR_New;
+import com.malk.service.aliwork.YDClient;
+import com.malk.service.aliyun.ALYInvoice;
+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 javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 错误抛出与拦截详见CatchException
+ */
+@Slf4j
+@RestController
+@RequestMapping("/")
+public class GuYuanController {
+
+    @Autowired
+    private ALYInvoice invoice;
+
+    @Autowired
+    private YDClient ydClient;
+
+    /**
+     * 阿里发票验真
+     */
+    @PostMapping("/invoice/check")
+    McR invoiceCheckPDF(@RequestBody Map<String, String> param) {
+        log.info("阿里发票验真, 文件, {}", param);
+        McException.assertParamException_Null(param, "url");
+        return McR.success(invoice.invoiceCheckPDF("4e2c048bfe1d4feea7354a66c7944fd1", param.get("url")));
+    }
+
+    /**
+     * 阿里发票验真: image
+     */
+    @PostMapping("invoice/ocr")
+    McR invoiceCheckImage(@RequestBody Map<String, String> param) {
+        log.info("阿里发票验真, 图片, {}", param);
+        return McR.success(invoice.invoiceCheckOCR("4e2c048bfe1d4feea7354a66c7944fd1", param.get("url")));
+    }
+
+    /**
+     * 宜搭临时免登地址: 钉钉平台
+     */
+    @PostMapping("openUrl")
+    McR openUrl(@RequestBody Map<String, String> param) {
+        McException.assertParamException_Null(param, "url");
+        return McR.success(ydClient.convertTemporaryUrl(param.get("url")));
+    }
+
+
+    /**
+     * 全局查询子表单
+     */
+    @PostMapping("queryAll")
+    McR queryAll(@RequestBody YDParam ydParam) {
+        return McR.success(ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_list_all));
+    }
+
+    /**
+     * 全局查询(不匹配子表单)
+     */
+    @PostMapping("validate")
+    McR queryAll(HttpServletRequest request) {
+        Map<String, ?> param = UtilServlet.getParamMap(request);
+        log.info("全局查询(不匹配子表单), {}", param);
+        if (ObjectUtil.isNull(param.get("uniques"))) {
+            return McR.success();
+        }
+        McException.assertParamException_Null(param, "uniques", "formUuid", "compId");
+        // 容错 - 尾部分号的空格会被输入框忽略
+        String[] uniques = String.valueOf(param.get("uniques")).replace("; ", ";").split(";");
+        for (String val : uniques) {
+            // 查重校验: 单张发票唯一标识 + 审批已通过 / 审批中
+            List<Map> conditions = new ArrayList<>();
+            Map unique = new HashMap();
+            unique.put("key", param.get("compId"));
+            unique.put("value", val.split(": ")[1]);
+            unique.put("type", "TEXT");
+            unique.put("operator", "like");
+            unique.put("componentName", "TextField");
+            conditions.add(unique);
+
+            Map approve = new HashMap();
+            approve.put("key", "processApprovedResult");
+            approve.put("value", new String[]{"agree"});
+            approve.put("type", "ARRAY");
+            approve.put("operator", "in");
+            approve.put("componentName", "SelectField");
+            conditions.add(approve);
+            YDParam ydParam = YDParam.builder()
+                    .appType("APP_FKRK7Y94DPI1S9DV1605")
+                    .systemToken("FN7666A1ZD0STZZ75W4CKD1GD07X3PUW2FBRKT")
+                    .formUuid(String.valueOf(param.get("formUuid")))
+                    .searchCondition(JSON.toJSONString(conditions))
+                    .build();
+            DDR_New ddr_new = ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_list);
+            log.info("审批通过匹配结果, {}, {}", ddr_new.getTotalCount(), ddr_new.getData());
+            if (ddr_new.getTotalCount() > 0) {
+                return McR.errorAccess("发票已被使用, 请勿重复提交!");
+            }
+
+            conditions.remove(approve);
+            Map status = new HashMap();
+            status.put("key", "processInstanceStatus");
+            status.put("value", new String[]{"RUNNING"});
+            status.put("type", "ARRAY");
+            status.put("operator", "in");
+            status.put("componentName", "SelectField");
+            conditions.add(status);
+            ydParam.setSearchCondition(JSON.toJSONString(conditions));
+            ddr_new = ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_list);
+            log.info("审批通过匹配结果, {}, {}", ddr_new.getTotalCount(), ddr_new.getData());
+            if (ddr_new.getTotalCount() > 0) {
+                return McR.errorAccess("发票已在流程中, 请勿重复提交!");
+            }
+        }
+        return McR.success();
+    }
+
+    /**
+     * 服务状态返回
+     */
+    @PostMapping("validateTips")
+    McR validateTaxNo(HttpServletRequest request) {
+        Map data = UtilServlet.getParamMap(request);
+        if (!data.get("status").equals(1)) {
+            return McR.errorAccess("error");
+        }
+        return McR.success(data);
+    }
+}

+ 32 - 0
mjava-guyuan/src/main/java/com.malk.guyuan/controller/IVController.java

@@ -0,0 +1,32 @@
+package com.malk.guyuan.controller;
+
+import com.malk.server.common.McR;
+import com.malk.service.tencent.TXYInvoice;
+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.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 错误抛出与拦截详见CatchException
+ */
+@Slf4j
+@RestController
+@RequestMapping("")
+public class IVController {
+
+
+    @Autowired
+    private TXYInvoice txyInvoice;
+
+    @PostMapping("test-iv")
+    McR test() {
+
+//        String url = "https://mc.cloudpure.cn/mjs/wget/2111686298289_.pic_hd.jpg";
+        String url = "https://mc.cloudpure.cn/mjs/wget/2121686298291_.pic_hd.jpg";
+
+        return McR.success(txyInvoice.doMixedInvoiceOCR(url));
+    }
+
+}

+ 64 - 0
mjava-guyuan/src/main/resources/application-dev.yml

@@ -0,0 +1,64 @@
+# 环境配置
+server:
+  port: 9001
+  servlet:
+    context-path: /api/guyuan
+
+# condition
+spel:
+  scheduling: false        # 定时任务是否执行
+  multiSource: false       # 是否多数据源配置
+
+spring:
+  # database
+  datasource:
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    username: root
+    password: mu123
+    url: jdbc:mysql://127.0.0.1:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+  jpa:
+    hibernate:
+      ddl-auto: none      # JPA对表没有任何操作
+    show-sql: true
+    database: MYSQL
+    database-platform: org.hibernate.dialect.MySQL57Dialect
+  flyway:
+    enabled: false        #  需要配置 jpa.hibernate.ddl-auto 为 none. 否则 flyway.enabled 配置会无效, 在没有数库连接情况下程序无法启动
+
+# swagger3
+swagger:
+  enable: true
+
+# filepath
+file:
+  path:
+    file: /Users/malk/server/_Tool/var/mjava/tmp/file
+    image: /Users/malk/server/_Tool/var/mjava/tmp/image
+    tmp: /Users/malk/server/_Tool/var/mjava/tmp
+  source:
+    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
+logging:
+  file:
+    path: /Users/malk/server/_Tool/var/mjava/log
+
+# dingtalk
+dingtalk:
+  agentId: 2356105659
+  appKey: dinghov5fyfjlhzk1ej1
+  appSecret: QR_1_7D0UUYtfdtMlDlmnjNSkvU2Uo3gOyabo2h09rmvj5_x0uk0Lw7N9pCy7sf-
+  corpId: dinge281bf50c488ebfd35c2f4657eb6378f
+  aesKey:
+  token:
+  operator: ""   # OA管理员账号
+
+# aliwork
+aliwork:
+  appType: APP_FKRK7Y94DPI1S9DV1605
+  systemToken: FN7666A1ZD0STZZ75W4CKD1GD07X3PUW2FBRKT
+
+# tencent [腾讯云]
+tencent:
+  APPID: 1309939821
+  SecretId: AKID2uqoryukbO2XuBThuxzdEpnmnmoocuCH
+  SecretKey: wnmgYHo8wrmjlldKoHnIkDZlqvrVDpOz
+  Region: ap-shanghai

+ 38 - 0
mjava-guyuan/src/main/resources/application-prod.yml

@@ -0,0 +1,38 @@
+# 环境配置
+server:
+  port: 9004
+  servlet:
+    context-path: /api/guyuan
+
+# condition
+spel:
+  scheduling: true        # 定时任务是否执行
+  multiSource: false      # 是否多数据源配置
+
+spring:
+  # database
+  datasource:
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    username: root
+    password: cp-root@2022++
+    url: jdbc:mysql://47.97.181.40:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+  jpa:
+    database: MYSQL
+    database-platform: org.hibernate.dialect.MySQL57Dialect
+  flyway:
+    enabled: false      #  需要配置 jpa.hibernate.ddl-auto 为 none. 否则 flyway.enabled 配置会无效, 在没有数库连接情况下程序无法启动
+
+# dingtalk
+dingtalk:
+  agentId: 2356105659
+  appKey: dinghov5fyfjlhzk1ej1
+  appSecret: QR_1_7D0UUYtfdtMlDlmnjNSkvU2Uo3gOyabo2h09rmvj5_x0uk0Lw7N9pCy7sf-
+  corpId: dinge281bf50c488ebfd35c2f4657eb6378f
+  aesKey:
+  token:
+  operator: ""   # OA管理员账号
+
+# aliwork
+aliwork:
+  appType: APP_FKRK7Y94DPI1S9DV1605
+  systemToken: FN7666A1ZD0STZZ75W4CKD1GD07X3PUW2FBRKT

+ 64 - 0
mjava-guyuan/target/classes/application-dev.yml

@@ -0,0 +1,64 @@
+# 环境配置
+server:
+  port: 9001
+  servlet:
+    context-path: /api/guyuan
+
+# condition
+spel:
+  scheduling: false        # 定时任务是否执行
+  multiSource: false       # 是否多数据源配置
+
+spring:
+  # database
+  datasource:
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    username: root
+    password: mu123
+    url: jdbc:mysql://127.0.0.1:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+  jpa:
+    hibernate:
+      ddl-auto: none      # JPA对表没有任何操作
+    show-sql: true
+    database: MYSQL
+    database-platform: org.hibernate.dialect.MySQL57Dialect
+  flyway:
+    enabled: false        #  需要配置 jpa.hibernate.ddl-auto 为 none. 否则 flyway.enabled 配置会无效, 在没有数库连接情况下程序无法启动
+
+# swagger3
+swagger:
+  enable: true
+
+# filepath
+file:
+  path:
+    file: /Users/malk/server/_Tool/var/mjava/tmp/file
+    image: /Users/malk/server/_Tool/var/mjava/tmp/image
+    tmp: /Users/malk/server/_Tool/var/mjava/tmp
+  source:
+    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
+logging:
+  file:
+    path: /Users/malk/server/_Tool/var/mjava/log
+
+# dingtalk
+dingtalk:
+  agentId: 2356105659
+  appKey: dinghov5fyfjlhzk1ej1
+  appSecret: QR_1_7D0UUYtfdtMlDlmnjNSkvU2Uo3gOyabo2h09rmvj5_x0uk0Lw7N9pCy7sf-
+  corpId: dinge281bf50c488ebfd35c2f4657eb6378f
+  aesKey:
+  token:
+  operator: ""   # OA管理员账号
+
+# aliwork
+aliwork:
+  appType: APP_FKRK7Y94DPI1S9DV1605
+  systemToken: FN7666A1ZD0STZZ75W4CKD1GD07X3PUW2FBRKT
+
+# tencent [腾讯云]
+tencent:
+  APPID: 1309939821
+  SecretId: AKID2uqoryukbO2XuBThuxzdEpnmnmoocuCH
+  SecretKey: wnmgYHo8wrmjlldKoHnIkDZlqvrVDpOz
+  Region: ap-shanghai

+ 38 - 0
mjava-guyuan/target/classes/application-prod.yml

@@ -0,0 +1,38 @@
+# 环境配置
+server:
+  port: 9004
+  servlet:
+    context-path: /api/guyuan
+
+# condition
+spel:
+  scheduling: true        # 定时任务是否执行
+  multiSource: false      # 是否多数据源配置
+
+spring:
+  # database
+  datasource:
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    username: root
+    password: cp-root@2022++
+    url: jdbc:mysql://47.97.181.40:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+  jpa:
+    database: MYSQL
+    database-platform: org.hibernate.dialect.MySQL57Dialect
+  flyway:
+    enabled: false      #  需要配置 jpa.hibernate.ddl-auto 为 none. 否则 flyway.enabled 配置会无效, 在没有数库连接情况下程序无法启动
+
+# dingtalk
+dingtalk:
+  agentId: 2356105659
+  appKey: dinghov5fyfjlhzk1ej1
+  appSecret: QR_1_7D0UUYtfdtMlDlmnjNSkvU2Uo3gOyabo2h09rmvj5_x0uk0Lw7N9pCy7sf-
+  corpId: dinge281bf50c488ebfd35c2f4657eb6378f
+  aesKey:
+  token:
+  operator: ""   # OA管理员账号
+
+# aliwork
+aliwork:
+  appType: APP_FKRK7Y94DPI1S9DV1605
+  systemToken: FN7666A1ZD0STZZ75W4CKD1GD07X3PUW2FBRKT

+ 41 - 5
mjava-hangshi/pom.xml

@@ -17,6 +17,20 @@
         <maven.compiler.target>8</maven.compiler.target>
     </properties>
 
+    <repositories>
+        <!--        <repository>-->
+        <!--            <id>com.e-iceblue</id>-->
+        <!--            <name>e-iceblue</name>-->
+        <!--            <url>http://repo.e-iceblue.cn/repository/maven-public/</url>-->
+        <!--        </repository>-->
+
+        <!--        <repository>-->
+        <!--            <id>GroupDocsJavaAPI</id>-->
+        <!--            <name>GroupDocs Java API</name>-->
+        <!--            <url>http://repository.groupdocs.com/repo/</url>-->
+        <!--        </repository>-->
+    </repositories>
+
     <dependencies>
         <!-- 核心模块-->
         <dependency>
@@ -25,11 +39,33 @@
             <version>1.0-SNAPSHOT</version>
         </dependency>
         <!-- CXF webservice -->
-        <dependency>
-            <groupId>org.apache.cxf</groupId>
-            <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
-            <version>3.4.0</version>
-        </dependency>
+        <!--        <dependency>-->
+        <!--            <groupId>org.apache.cxf</groupId>-->
+        <!--            <artifactId>cxf-spring-boot-starter-jaxws</artifactId>-->
+        <!--            <version>3.4.0</version>-->
+        <!--        </dependency>-->
+
+        <!--        <dependency>-->
+        <!--            <groupId>e-iceblue</groupId>-->
+        <!--            <artifactId>spire.doc.free</artifactId>-->
+        <!--            <version>3.9.0</version>-->
+        <!--        </dependency>-->
+        <!--        <dependency>-->
+        <!--            <groupId>com.groupdocs</groupId>-->
+        <!--            <artifactId>groupdocs-comparison</artifactId>-->
+        <!--            <version>20.4</version>-->
+        <!--        </dependency>-->
+
+        <!--        <dependency>-->
+        <!--            <groupId>e-iceblue</groupId>-->
+        <!--            <artifactId>spire.pdf.free</artifactId>-->
+        <!--            <version>3.9.0</version>-->
+        <!--        </dependency>-->
+        <!--        <dependency>-->
+        <!--            <groupId>e-iceblue</groupId>-->
+        <!--            <artifactId>spire.pdf</artifactId>-->
+        <!--            &lt;!&ndash;            <version>9.5.4</version>&ndash;&gt;-->
+        <!--        </dependency>-->
     </dependencies>
 
     <build>

+ 66 - 66
mjava-hangshi/src/main/java/com/malk/hangshi/config/CxfConfig.java

@@ -1,68 +1,68 @@
-package com.malk.hangshi.config;
-
-import com.malk.hangshi.service.IH3yunWebService;
-import com.malk.hangshi.service.impl.H3yunWebServiceImpl;
-import org.apache.cxf.Bus;
-import org.apache.cxf.bus.spring.SpringBus;
-import org.apache.cxf.jaxws.EndpointImpl;
-import org.apache.cxf.phase.Phase;
-import org.apache.cxf.transport.servlet.CXFServlet;
-import org.springframework.boot.web.servlet.ServletRegistrationBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import javax.xml.ws.Endpoint;
-
-
-@Configuration
-public class CxfConfig {
-
-    /**
-     * 访问路径: http://localhost:9001/api/webService/api?wsdl
-     * -
-     * invoke: mc可自定义, test为方法名称, arg0第一次参数
-     * -
-     * <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:mc="http://service.hangshi.malk.com">
-     *   <soap:Body>
-     *     <mc:test>
-     *       <arg0>[{"assetNo":"1","barCode":"1","belongDept":"1","boxBarCode":"1","cap":"1","chkDate"madeDate":158688000000}]</arg0>
-     *     </mc:test>
-     *   </soap:Body>
-     * </soap:Envelope>
-     * -
-     *
-     * @WebParam 自定义参数名称, 否则就是 arg0, arg1, ...
-     */
-
-    @Bean
-    public ServletRegistrationBean disServlet() {
-        return new ServletRegistrationBean(new CXFServlet(), "/hangshi/ws/*");
-    }
-
-    @Bean(name = Bus.DEFAULT_BUS_ID)
-    public SpringBus springBus() {
-        return new SpringBus();
-    }
-
+//package com.malk.hangshi.config;
+//
+//import com.malk.hangshi.service.IH3yunWebService;
+//import com.malk.hangshi.service.impl.H3yunWebServiceImpl;
+//import org.apache.cxf.Bus;
+//import org.apache.cxf.bus.spring.SpringBus;
+//import org.apache.cxf.jaxws.EndpointImpl;
+//import org.apache.cxf.phase.Phase;
+//import org.apache.cxf.transport.servlet.CXFServlet;
+//import org.springframework.boot.web.servlet.ServletRegistrationBean;
+//import org.springframework.context.annotation.Bean;
+//import org.springframework.context.annotation.Configuration;
+//
+//import javax.xml.ws.Endpoint;
+//
+//
+//@Configuration
+//public class CxfConfig {
+//
+//    /**
+//     * 访问路径: http://localhost:9001/api/webService/api?wsdl
+//     * -
+//     * invoke: mc可自定义, test为方法名称, arg0第一次参数
+//     * -
+//     * <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:mc="http://service.hangshi.malk.com">
+//     *   <soap:Body>
+//     *     <mc:test>
+//     *       <arg0>[{"assetNo":"1","barCode":"1","belongDept":"1","boxBarCode":"1","cap":"1","chkDate"madeDate":158688000000}]</arg0>
+//     *     </mc:test>
+//     *   </soap:Body>
+//     * </soap:Envelope>
+//     * -
+//     *
+//     * @WebParam 自定义参数名称, 否则就是 arg0, arg1, ...
+//     */
+//
 //    @Bean
-//    public InvoiceWebService demoService() {
-//        return new InvoiceWebServiceImpl();
+//    public ServletRegistrationBean disServlet() {
+//        return new ServletRegistrationBean(new CXFServlet(), "/hangshi/ws/*");
 //    }
-
-    @Bean
-    public IH3yunWebService demoService() {
-        return new H3yunWebServiceImpl();
-    }
-
-    @Bean
-    public Endpoint endpoint() {
-        EndpointImpl endpoint = new EndpointImpl(springBus(), demoService());
-        // 请求拦截器
-        endpoint.getInInterceptors().add(new WsInInterceptor(Phase.RECEIVE));
-        // 响应拦截器
-//        endpoint.getOutInterceptors().add(new WsOutInterceptor(Phase.PRE_STREAM));
-        endpoint.publish("/invoke.asmx");
-        return endpoint;
-    }
-
-}
+//
+//    @Bean(name = Bus.DEFAULT_BUS_ID)
+//    public SpringBus springBus() {
+//        return new SpringBus();
+//    }
+//
+////    @Bean
+////    public InvoiceWebService demoService() {
+////        return new InvoiceWebServiceImpl();
+////    }
+//
+//    @Bean
+//    public IH3yunWebService demoService() {
+//        return new H3yunWebServiceImpl();
+//    }
+//
+//    @Bean
+//    public Endpoint endpoint() {
+//        EndpointImpl endpoint = new EndpointImpl(springBus(), demoService());
+//        // 请求拦截器
+//        endpoint.getInInterceptors().add(new WsInInterceptor(Phase.RECEIVE));
+//        // 响应拦截器
+////        endpoint.getOutInterceptors().add(new WsOutInterceptor(Phase.PRE_STREAM));
+//        endpoint.publish("/invoke.asmx");
+//        return endpoint;
+//    }
+//
+//}

+ 40 - 40
mjava-hangshi/src/main/java/com/malk/hangshi/config/WsInInterceptor.java

@@ -1,40 +1,40 @@
-package com.malk.hangshi.config;
-
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.cxf.binding.soap.SoapMessage;
-import org.apache.cxf.helpers.IOUtils;
-import org.apache.cxf.interceptor.Fault;
-import org.apache.cxf.phase.AbstractPhaseInterceptor;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-
-@Slf4j
-public class WsInInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
-
-    public WsInInterceptor(String phase) {
-        super(phase);
-    }
-
-    @Override
-    public void handleMessage(SoapMessage message) throws Fault {
-        try {
-            // 从流中获取请求消息体并以字符串形式输出,注意IOUtils是cxf的包;
-            String input = IOUtils.toString(message.getContent(InputStream.class), "UTF-8");
-            // 如果内容不为空(第一次连接也会被拦截,此时input为空)
-            if (StringUtils.isNotBlank(input)) {
-                // 修改请求消息体为webservice服务要求的格式
-                input = input.replace("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">", "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ser=\"http://server.dandelion.com\">")
-                        .replace("<esb:getData xmlns:esb=\"mdm.stardand.com\">", "<ser:getData>")
-                        .replace("</esb:getData>", "</ser:getData>").replace("ns2:InvokeResponse", "InvokeResponse");
-                log.info("ns2:InvokeResponse, {}", input);
-            }
-
-            // 重新写入
-            message.setContent(InputStream.class, new ByteArrayInputStream(input.getBytes()));
-        } catch (Exception e) {
-            System.out.println(String.format("解析报文异常: %s", e.getMessage()));
-        }
-    }
-}
+//package com.malk.hangshi.config;
+//
+//import lombok.extern.slf4j.Slf4j;
+//import org.apache.commons.lang3.StringUtils;
+//import org.apache.cxf.binding.soap.SoapMessage;
+//import org.apache.cxf.helpers.IOUtils;
+//import org.apache.cxf.interceptor.Fault;
+//import org.apache.cxf.phase.AbstractPhaseInterceptor;
+//
+//import java.io.ByteArrayInputStream;
+//import java.io.InputStream;
+//
+//@Slf4j
+//public class WsInInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
+//
+//    public WsInInterceptor(String phase) {
+//        super(phase);
+//    }
+//
+//    @Override
+//    public void handleMessage(SoapMessage message) throws Fault {
+//        try {
+//            // 从流中获取请求消息体并以字符串形式输出,注意IOUtils是cxf的包;
+//            String input = IOUtils.toString(message.getContent(InputStream.class), "UTF-8");
+//            // 如果内容不为空(第一次连接也会被拦截,此时input为空)
+//            if (StringUtils.isNotBlank(input)) {
+//                // 修改请求消息体为webservice服务要求的格式
+//                input = input.replace("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">", "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ser=\"http://server.dandelion.com\">")
+//                        .replace("<esb:getData xmlns:esb=\"mdm.stardand.com\">", "<ser:getData>")
+//                        .replace("</esb:getData>", "</ser:getData>").replace("ns2:InvokeResponse", "InvokeResponse");
+//                log.info("ns2:InvokeResponse, {}", input);
+//            }
+//
+//            // 重新写入
+//            message.setContent(InputStream.class, new ByteArrayInputStream(input.getBytes()));
+//        } catch (Exception e) {
+//            System.out.println(String.format("解析报文异常: %s", e.getMessage()));
+//        }
+//    }
+//}

+ 71 - 71
mjava-hangshi/src/main/java/com/malk/hangshi/config/WsOutInterceptor.java

@@ -1,71 +1,71 @@
-package com.malk.hangshi.config;
-
-import lombok.extern.slf4j.Slf4j;
-import org.apache.cxf.binding.soap.SoapMessage;
-import org.apache.cxf.helpers.IOUtils;
-import org.apache.cxf.interceptor.Fault;
-import org.apache.cxf.io.CachedOutputStream;
-import org.apache.cxf.phase.AbstractPhaseInterceptor;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-@Slf4j
-public class WsOutInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
-
-    public WsOutInterceptor(String phase) {
-        super(phase);
-    }
-
-    @Override
-    public void handleMessage(SoapMessage message) throws Fault {
-        try {
-            // 从流中获取返回内容
-            OutputStream os = message.getContent(OutputStream.class);
-            CachedStream cs = new CachedStream();
-            message.setContent(OutputStream.class, cs);
-            message.getInterceptorChain().doIntercept(message);
-            CachedOutputStream cachedOutputStream = (CachedOutputStream) message.getContent(OutputStream.class);
-            InputStream in = cachedOutputStream.getInputStream();
-            String output = IOUtils.toString(in, "UTF-8");
-            // 修改内容为集成平台要求的格式
-            output = output.replace("<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">", "<soapenv:Envelope xmlns:soapenv=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\">")
-                    .replace("</soap:Envelope>", "</soapenv:Envelope>")
-                    .replace("<soap:Body>", "<soapenv:Body>")
-                    .replace("</soap:Body>", "</soapenv:Body>")
-                    .replace("<ns2:getDataResponse xmlns:ns2=\"http://server.dandelion.com\">", "")
-                    .replace("</ns2:getDataResponse>", "").replace("ns2:InvokeResponse", "InvokeResponse");
-            ;
-            log.info("ns2:InvokeResponse, {}", output);
-            output = "<string xmlns=\"http://tempuri.org/\">{\"ResultCode\":\"0\",\"Message\":\"\",\"Schema\":{\"Code\":\"Student\",\"Items\":[]},\"Data\":{}}</string>";
-            // 处理完后写回流中
-            IOUtils.copy(new ByteArrayInputStream(output.getBytes()), os);
-            cs.close();
-            os.flush();
-            message.setContent(OutputStream.class, os);
-        } catch (Exception e) {
-            System.out.println(String.format("解析报文异常: %s", e.getMessage()));
-        }
-    }
-
-    private static class CachedStream extends CachedOutputStream {
-        public CachedStream() {
-            super();
-        }
-
-        @Override
-        protected void doFlush() throws IOException {
-            currentStream.flush();
-        }
-
-        @Override
-        protected void doClose() throws IOException {
-        }
-
-        @Override
-        protected void onWrite() throws IOException {
-        }
-    }
-}
+//package com.malk.hangshi.config;
+//
+//import lombok.extern.slf4j.Slf4j;
+//import org.apache.cxf.binding.soap.SoapMessage;
+//import org.apache.cxf.helpers.IOUtils;
+//import org.apache.cxf.interceptor.Fault;
+//import org.apache.cxf.io.CachedOutputStream;
+//import org.apache.cxf.phase.AbstractPhaseInterceptor;
+//
+//import java.io.ByteArrayInputStream;
+//import java.io.IOException;
+//import java.io.InputStream;
+//import java.io.OutputStream;
+//
+//@Slf4j
+//public class WsOutInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
+//
+//    public WsOutInterceptor(String phase) {
+//        super(phase);
+//    }
+//
+//    @Override
+//    public void handleMessage(SoapMessage message) throws Fault {
+//        try {
+//            // 从流中获取返回内容
+//            OutputStream os = message.getContent(OutputStream.class);
+//            CachedStream cs = new CachedStream();
+//            message.setContent(OutputStream.class, cs);
+//            message.getInterceptorChain().doIntercept(message);
+//            CachedOutputStream cachedOutputStream = (CachedOutputStream) message.getContent(OutputStream.class);
+//            InputStream in = cachedOutputStream.getInputStream();
+//            String output = IOUtils.toString(in, "UTF-8");
+//            // 修改内容为集成平台要求的格式
+//            output = output.replace("<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">", "<soapenv:Envelope xmlns:soapenv=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\">")
+//                    .replace("</soap:Envelope>", "</soapenv:Envelope>")
+//                    .replace("<soap:Body>", "<soapenv:Body>")
+//                    .replace("</soap:Body>", "</soapenv:Body>")
+//                    .replace("<ns2:getDataResponse xmlns:ns2=\"http://server.dandelion.com\">", "")
+//                    .replace("</ns2:getDataResponse>", "").replace("ns2:InvokeResponse", "InvokeResponse");
+//            ;
+//            log.info("ns2:InvokeResponse, {}", output);
+//            output = "<string xmlns=\"http://tempuri.org/\">{\"ResultCode\":\"0\",\"Message\":\"\",\"Schema\":{\"Code\":\"Student\",\"Items\":[]},\"Data\":{}}</string>";
+//            // 处理完后写回流中
+//            IOUtils.copy(new ByteArrayInputStream(output.getBytes()), os);
+//            cs.close();
+//            os.flush();
+//            message.setContent(OutputStream.class, os);
+//        } catch (Exception e) {
+//            System.out.println(String.format("解析报文异常: %s", e.getMessage()));
+//        }
+//    }
+//
+//    private static class CachedStream extends CachedOutputStream {
+//        public CachedStream() {
+//            super();
+//        }
+//
+//        @Override
+//        protected void doFlush() throws IOException {
+//            currentStream.flush();
+//        }
+//
+//        @Override
+//        protected void doClose() throws IOException {
+//        }
+//
+//        @Override
+//        protected void onWrite() throws IOException {
+//        }
+//    }
+//}

+ 114 - 0
mjava-hangshi/src/main/java/com/malk/hangshi/controller/HSController.java

@@ -8,6 +8,8 @@ import com.malk.server.common.McException;
 import com.malk.server.common.McR;
 import com.malk.server.dingtalk.DDR_New;
 import com.malk.service.aliwork.YDClient;
+import com.malk.service.dingtalk.DDClient;
+import com.malk.service.dingtalk.DDClient_Contacts;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -48,4 +50,116 @@ public class HSController {
         DDR_New ddr_new = ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_list_all);
         return McR.success(ddr_new);
     }
+
+    @Autowired
+    private DDClient ddClient;
+
+    @Autowired
+    private DDClient_Contacts ddClient_contacts;
+
+    /**
+     * 获取员工人数
+     */
+    @PostMapping("user/count")
+    McR queryCount() {
+        return McR.success(ddClient_contacts.getUserCount(ddClient.getAccessToken(), true));
+    }
+
+//    @Autowired
+//    private FilePath filePath;
+//
+//    @PostMapping("doc")
+//    McR doc() {
+//
+//        //创建Document实例,加载第一个Word示例文档
+//        com.spire.doc.Document doc1 = new com.spire.doc.Document();
+////        doc1.loadFromFile(filePath.getPath().getFile() + "工作确认单.docx");
+//        doc1.loadFromFile(filePath.getPath().getFile() + "杉泰-太医管家产品购销合同(实体卡)V2.0.docx");
+//
+//        //创建Document实例,加载第二个Word示例文档
+//        com.spire.doc.Document doc2 = new Document();
+////        doc2.loadFromFile(filePath.getPath().getFile() + "工作确认单(1).docx");
+//        doc2.loadFromFile(filePath.getPath().getFile() + "杉泰-太医管家产品购销合同(实体卡)V2.0 2.docx");
+////        doc2.loadFromFile(filePath.getPath().getFile() + "杉泰-太医管家产品购销合同(实体卡)V2.0 2.pdf", FileFormat.PDF);
+//
+//        //比较两个示例文档的内容差异
+////        doc1.compare(doc2, "Host");
+//        doc1.compare(doc2, "宁静");
+//
+//        //保存结果文档
+//        doc1.saveToFile(filePath.getPath().getFile() + "diff-衫泰.docx");
+//
+//        return McR.success();
+//    }
+//
+//    @PostMapping("doc2")
+//    McR doc2() {
+//
+//        //加载PDF
+//        PdfDocument pdf = new PdfDocument();
+//        pdf.loadFromFile(filePath.getPath().getFile() + "杉泰-太医管家产品购销合同(实体卡)V2.0 2.pdf");
+//
+//        //保存为Word格式
+//        pdf.saveToFile(filePath.getPath().getFile() + "杉泰-太医管家产品购销合同(实体卡)V2.0 pdf.docx", FileFormat.DOCX);
+//
+//        com.spire.doc.Document doc1 = new com.spire.doc.Document();
+//        doc1.loadFromFile(filePath.getPath().getFile() + "杉泰-太医管家产品购销合同(实体卡)V2.0.docx");
+//
+//        //创建Document实例,加载第二个Word示例文档
+//        com.spire.doc.Document doc2 = new Document();
+//        doc2.loadFromFile(filePath.getPath().getFile() + "杉泰-太医管家产品购销合同(实体卡)V2.0 pdf.docx");
+//
+//        // 比对位置错乱
+//        //比较两个示例文档的内容差异
+////        doc1.compare(doc2, "Host");
+//        doc1.compare(doc2, "宁静");
+////
+////        //保存结果文档
+//        doc1.saveToFile(filePath.getPath().getFile() + "diff-衫泰-pdf.docx");
+//
+//
+////        Comparer comparer = new Comparer(filePath.getPath().getFile() + "杉泰-太医管家产品购销合同(实体卡)V2.0.docx");
+////        try {
+////            comparer.add(filePath.getPath().getFile() + "杉泰-太医管家产品购销合同(实体卡)V2.0 2.docx");
+////            comparer.compare("grou-衫泰.docx");
+////        } finally {
+////            comparer.dispose();
+////        }
+//        return McR.success();
+//    }
+//
+//    @PostMapping("doc3")
+//    McR doc3() {
+//
+//
+//        // 乱码
+////        com.spire.doc.Document doc = new com.spire.doc.Document();
+////        doc.loadFromFile(filePath.getPath().getFile() + "杉泰-太医管家产品购销合同(实体卡)V2.0.docx");
+////        doc.saveToFile(filePath.getPath().getFile() + "WordToPDF.pdf", com.spire.doc.FileFormat.PDF);
+//
+//        com.spire.doc.Document doc1 = new com.spire.doc.Document();
+//        doc1.loadFromFile(filePath.getPath().getFile() + "杉泰-太医管家产品购销合同(实体卡)V2.0.pdf", com.spire.doc.FileFormat.PDF);
+//
+//        //创建Document实例,加载第二个Word示例文档
+//        com.spire.doc.Document doc2 = new Document();
+//        doc2.loadFromFile(filePath.getPath().getFile() + "杉泰-太医管家产品购销合同(实体卡)V2.0 2.pdf", com.spire.doc.FileFormat.PDF);
+//
+//        //比较两个示例文档的内容差异
+////        doc1.compare(doc2, "Host");
+//        doc1.compare(doc2, "宁静");
+////
+////        //保存结果文档
+//        doc1.saveToFile(filePath.getPath().getFile() + "diff-衫泰-pdf-pdf.pdf");
+//
+//
+////        Comparer comparer = new Comparer(filePath.getPath().getFile() + "杉泰-太医管家产品购销合同(实体卡)V2.0.docx");
+////        try {
+////            comparer.add(filePath.getPath().getFile() + "杉泰-太医管家产品购销合同(实体卡)V2.0 2.docx");
+////            comparer.compare("grou-衫泰.docx");
+////        } finally {
+////            comparer.dispose();
+////        }
+//        return McR.success();
+//    }
 }
+

+ 41 - 41
mjava-hangshi/src/main/java/com/malk/hangshi/service/IH3yunWebService.java

@@ -1,41 +1,41 @@
-package com.malk.hangshi.service;
-
-import javax.jws.WebMethod;
-import javax.jws.WebParam;
-import javax.jws.WebResult;
-import javax.jws.WebService;
-
-/**
- * @author shinka
- * @date 2021/03/26
- */
-
-@WebService(name = "IH3yunWebService", // 暴露服务名称
-        targetNamespace = "http://service.example.com/h3yun" // 命名空间,一般是接口的包名倒序
-)
-// @BindingType(value = SOAPBinding.SOAP12HTTP_BINDING) // soap1.1
-public interface IH3yunWebService {
-
-    public static final String NAMESPACE = "http://service.example.com/h3yun";
-
-    @WebMethod(operationName = "GetSchema", action = NAMESPACE + "/GetSchema")
-    @WebResult(name = "GetSchemaResult")
-    public String GetSchema(@WebParam(name = "schemaCode", targetNamespace = NAMESPACE) String schemaCode);
-
-    @WebMethod(operationName = "GetSchemaList", action = NAMESPACE + "/GetSchemaList")
-    @WebResult(name = "GetSchemaListResult")
-    public String GetSchemaList();
-
-    @WebMethod(operationName = "GetList", action = NAMESPACE + "/GetList")
-    @WebResult(name = "GetListResult")
-    public String GetList(@WebParam(name = "userCode", targetNamespace = NAMESPACE) String userCode,
-                          @WebParam(name = "schemaCode", targetNamespace = NAMESPACE) String schemaCode,
-                          @WebParam(name = "filter", targetNamespace = NAMESPACE) String filter);
-
-    @WebMethod(operationName = "Invoke", action = NAMESPACE + "/Invoke")
-    @WebResult(name = "InvokeResult")
-    public String Invoke(@WebParam(name = "userCode", targetNamespace = NAMESPACE) String userCode,
-                         @WebParam(name = "schemaCode", targetNamespace = NAMESPACE) String schemaCode,
-                         @WebParam(name = "methodName", targetNamespace = NAMESPACE) String methodName,
-                         @WebParam(name = "param", targetNamespace = NAMESPACE) String param);
-}
+//package com.malk.hangshi.service;
+//
+//import javax.jws.WebMethod;
+//import javax.jws.WebParam;
+//import javax.jws.WebResult;
+//import javax.jws.WebService;
+//
+///**
+// * @author shinka
+// * @date 2021/03/26
+// */
+//
+//@WebService(name = "IH3yunWebService", // 暴露服务名称
+//        targetNamespace = "http://service.example.com/h3yun" // 命名空间,一般是接口的包名倒序
+//)
+//// @BindingType(value = SOAPBinding.SOAP12HTTP_BINDING) // soap1.1
+//public interface IH3yunWebService {
+//
+//    public static final String NAMESPACE = "http://service.example.com/h3yun";
+//
+//    @WebMethod(operationName = "GetSchema", action = NAMESPACE + "/GetSchema")
+//    @WebResult(name = "GetSchemaResult")
+//    public String GetSchema(@WebParam(name = "schemaCode", targetNamespace = NAMESPACE) String schemaCode);
+//
+//    @WebMethod(operationName = "GetSchemaList", action = NAMESPACE + "/GetSchemaList")
+//    @WebResult(name = "GetSchemaListResult")
+//    public String GetSchemaList();
+//
+//    @WebMethod(operationName = "GetList", action = NAMESPACE + "/GetList")
+//    @WebResult(name = "GetListResult")
+//    public String GetList(@WebParam(name = "userCode", targetNamespace = NAMESPACE) String userCode,
+//                          @WebParam(name = "schemaCode", targetNamespace = NAMESPACE) String schemaCode,
+//                          @WebParam(name = "filter", targetNamespace = NAMESPACE) String filter);
+//
+//    @WebMethod(operationName = "Invoke", action = NAMESPACE + "/Invoke")
+//    @WebResult(name = "InvokeResult")
+//    public String Invoke(@WebParam(name = "userCode", targetNamespace = NAMESPACE) String userCode,
+//                         @WebParam(name = "schemaCode", targetNamespace = NAMESPACE) String schemaCode,
+//                         @WebParam(name = "methodName", targetNamespace = NAMESPACE) String methodName,
+//                         @WebParam(name = "param", targetNamespace = NAMESPACE) String param);
+//}

+ 46 - 46
mjava-hangshi/src/main/java/com/malk/hangshi/service/impl/H3yunWebServiceImpl.java

@@ -1,46 +1,46 @@
-package com.malk.hangshi.service.impl;
-
-import com.malk.hangshi.service.IH3yunWebService;
-import org.springframework.stereotype.Component;
-
-import javax.jws.WebService;
-import javax.xml.ws.BindingType;
-import javax.xml.ws.soap.SOAPBinding;
-
-/**
- * @author shinka
- * @date 2021/03/26
- */
-@WebService(serviceName = "H3yunWebService", // 与接口中指定的name一致
-        targetNamespace = "http://service.example.com/h3yun", // 与接口中的命名空间一致,一般是接口的包名倒
-        endpointInterface = "com.malk.hangshi.service.IH3yunWebService" // 接口地址
-)
-@BindingType(value = SOAPBinding.SOAP12HTTP_BINDING)
-@Component
-public class H3yunWebServiceImpl implements IH3yunWebService {
-
-    @Override
-    public String GetSchema(String schemaCode) {
-        // 氚云在集成的时候会调用GetSchema方法,该方法返回值仅支持如下两种,业务逻辑请写在其它方法上
-        return "{\"code\":\"\"}";
-        // return "";
-    }
-
-    @Override
-    public String GetSchemaList() {
-        return "{\"schemaCode\":\"D001062ceshi2\"}";
-    }
-
-    @Override
-    public String GetList(String userCode, String schemaCode, String filter) {
-        return "{\"userCode\":\"" + userCode + "\",\"schemaCode\":\"" + schemaCode + "\",\"filter\":\"" + filter
-                + "\"}";
-    }
-
-    @Override
-    public String Invoke(String userCode, String schemaCode, String methodName, String param) {
-        return "{\"userCode\":\"" + userCode + "\",\"schemaCode\":\"" + schemaCode + "\",\"methodName\":\"" + methodName
-                + "\",\"param\":\"" + methodName + "\"}";
-    }
-
-}
+//package com.malk.hangshi.service.impl;
+//
+//import com.malk.hangshi.service.IH3yunWebService;
+//import org.springframework.stereotype.Component;
+//
+//import javax.jws.WebService;
+//import javax.xml.ws.BindingType;
+//import javax.xml.ws.soap.SOAPBinding;
+//
+///**
+// * @author shinka
+// * @date 2021/03/26
+// */
+//@WebService(serviceName = "H3yunWebService", // 与接口中指定的name一致
+//        targetNamespace = "http://service.example.com/h3yun", // 与接口中的命名空间一致,一般是接口的包名倒
+//        endpointInterface = "com.malk.hangshi.service.IH3yunWebService" // 接口地址
+//)
+//@BindingType(value = SOAPBinding.SOAP12HTTP_BINDING)
+//@Component
+//public class H3yunWebServiceImpl implements IH3yunWebService {
+//
+//    @Override
+//    public String GetSchema(String schemaCode) {
+//        // 氚云在集成的时候会调用GetSchema方法,该方法返回值仅支持如下两种,业务逻辑请写在其它方法上
+//        return "{\"code\":\"\"}";
+//        // return "";
+//    }
+//
+//    @Override
+//    public String GetSchemaList() {
+//        return "{\"schemaCode\":\"D001062ceshi2\"}";
+//    }
+//
+//    @Override
+//    public String GetList(String userCode, String schemaCode, String filter) {
+//        return "{\"userCode\":\"" + userCode + "\",\"schemaCode\":\"" + schemaCode + "\",\"filter\":\"" + filter
+//                + "\"}";
+//    }
+//
+//    @Override
+//    public String Invoke(String userCode, String schemaCode, String methodName, String param) {
+//        return "{\"userCode\":\"" + userCode + "\",\"schemaCode\":\"" + schemaCode + "\",\"methodName\":\"" + methodName
+//                + "\",\"param\":\"" + methodName + "\"}";
+//    }
+//
+//}

+ 5 - 5
mjava-hangshi/src/main/resources/application-dev.yml

@@ -26,14 +26,14 @@ spring:
 # filepath
 file:
   path:
-    file: /Users/malk/service/_Tool/var/mjava/tmp//file/
-    image: /Users/malk/service/_Tool/var/mjava/tmp//image/
-    tmp: /Users/malk/service/_Tool/var/mjava/tmp/
+    file: /Users/malk/server/_Tool/var/mjava/tmp//file/
+    image: /Users/malk/server/_Tool/var/mjava/tmp//image/
+    tmp: /Users/malk/server/_Tool/var/mjava/tmp/
   source:
-    fonts: /Users/malk/service/_Tool/fonts/simsun.ttc
+    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
 logging:
   file:
-    path: /Users/malk/service/_Tool/var/mjava/log
+    path: /Users/malk/server/_Tool/var/mjava/log
 
 # dingtalk
 dingtalk:

+ 1 - 1
mjava-hangshi/src/main/resources/application-prod.yml

@@ -1,6 +1,6 @@
 # 环境配置
 server:
-  port: 9008
+  port: 9009
 
 # condition
 spel:

+ 5 - 5
mjava-hangshi/target/classes/application-dev.yml

@@ -26,14 +26,14 @@ spring:
 # filepath
 file:
   path:
-    file: /Users/malk/service/_Tool/var/mjava/tmp//file/
-    image: /Users/malk/service/_Tool/var/mjava/tmp//image/
-    tmp: /Users/malk/service/_Tool/var/mjava/tmp/
+    file: /Users/malk/server/_Tool/var/mjava/tmp//file/
+    image: /Users/malk/server/_Tool/var/mjava/tmp//image/
+    tmp: /Users/malk/server/_Tool/var/mjava/tmp/
   source:
-    fonts: /Users/malk/service/_Tool/fonts/simsun.ttc
+    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
 logging:
   file:
-    path: /Users/malk/service/_Tool/var/mjava/log
+    path: /Users/malk/server/_Tool/var/mjava/log
 
 # dingtalk
 dingtalk:

+ 1 - 1
mjava-hangshi/target/classes/application-prod.yml

@@ -1,6 +1,6 @@
 # 环境配置
 server:
-  port: 9008
+  port: 9009
 
 # condition
 spel:

+ 5 - 5
mjava-jisuanji/src/main/resources/application-dev.yml

@@ -26,14 +26,14 @@ spring:
 # filepath
 file:
   path:
-    file: /Users/malk/service/_Tool/var/mjava/tmp//file/
-    image: /Users/malk/service/_Tool/var/mjava/tmp//image/
-    tmp: /Users/malk/service/_Tool/var/mjava/tmp/
+    file: /Users/malk/server/_Tool/var/mjava/tmp//file/
+    image: /Users/malk/server/_Tool/var/mjava/tmp//image/
+    tmp: /Users/malk/server/_Tool/var/mjava/tmp/
   source:
-    fonts: /Users/malk/service/_Tool/fonts/simsun.ttc
+    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
 logging:
   file:
-    path: /Users/malk/service/_Tool/var/mjava/log
+    path: /Users/malk/server/_Tool/var/mjava/log
 
 # dingtalk
 dingtalk:

+ 5 - 5
mjava-jisuanji/target/classes/application-dev.yml

@@ -26,14 +26,14 @@ spring:
 # filepath
 file:
   path:
-    file: /Users/malk/service/_Tool/var/mjava/tmp//file/
-    image: /Users/malk/service/_Tool/var/mjava/tmp//image/
-    tmp: /Users/malk/service/_Tool/var/mjava/tmp/
+    file: /Users/malk/server/_Tool/var/mjava/tmp//file/
+    image: /Users/malk/server/_Tool/var/mjava/tmp//image/
+    tmp: /Users/malk/server/_Tool/var/mjava/tmp/
   source:
-    fonts: /Users/malk/service/_Tool/fonts/simsun.ttc
+    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
 logging:
   file:
-    path: /Users/malk/service/_Tool/var/mjava/log
+    path: /Users/malk/server/_Tool/var/mjava/log
 
 # dingtalk
 dingtalk:

+ 5 - 5
mjava-lichen/src/main/resources/application-dev.yml

@@ -26,14 +26,14 @@ spring:
 # filepath
 file:
   path:
-    file: /Users/malk/service/_Tool/var/mjava/tmp//file/
-    image: /Users/malk/service/_Tool/var/mjava/tmp//image/
-    tmp: /Users/malk/service/_Tool/var/mjava/tmp/
+    file: /Users/malk/server/_Tool/var/mjava/tmp//file/
+    image: /Users/malk/server/_Tool/var/mjava/tmp//image/
+    tmp: /Users/malk/server/_Tool/var/mjava/tmp/
   source:
-    fonts: /Users/malk/service/_Tool/fonts/simsun.ttc
+    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
 logging:
   file:
-    path: /Users/malk/service/_Tool/var/mjava/log
+    path: /Users/malk/server/_Tool/var/mjava/log
 
 # dingtalk
 dingtalk:

+ 1 - 1
mjava-lichen/src/test/resources/server.sh

@@ -1,5 +1,5 @@
 #!/bin/bash
-appname='mjava-minjiaoyuan'
+appname='mjava-lichen'
 if [ "$1" == "dev" ]; then
   java -Xms256m -Xmx256m -jar $appname.jar --spring.profiles.active=dev
 else

+ 5 - 5
mjava-lichen/target/classes/application-dev.yml

@@ -26,14 +26,14 @@ spring:
 # filepath
 file:
   path:
-    file: /Users/malk/service/_Tool/var/mjava/tmp//file/
-    image: /Users/malk/service/_Tool/var/mjava/tmp//image/
-    tmp: /Users/malk/service/_Tool/var/mjava/tmp/
+    file: /Users/malk/server/_Tool/var/mjava/tmp//file/
+    image: /Users/malk/server/_Tool/var/mjava/tmp//image/
+    tmp: /Users/malk/server/_Tool/var/mjava/tmp/
   source:
-    fonts: /Users/malk/service/_Tool/fonts/simsun.ttc
+    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
 logging:
   file:
-    path: /Users/malk/service/_Tool/var/mjava/log
+    path: /Users/malk/server/_Tool/var/mjava/log
 
 # dingtalk
 dingtalk:

+ 1 - 1
mjava-lichen/target/test-classes/server.sh

@@ -1,5 +1,5 @@
 #!/bin/bash
-appname='mjava-minjiaoyuan'
+appname='mjava-lichen'
 if [ "$1" == "dev" ]; then
   java -Xms256m -Xmx256m -jar $appname.jar --spring.profiles.active=dev
 else

+ 0 - 98
mjava-minjiaoyuan/src/main/java/com/malk/minjiaoyuan/controller/InviteControl.java

@@ -1,98 +0,0 @@
-package com.malk.minjiaoyuan.controller;
-
-import com.alibaba.fastjson.JSON;
-import com.malk.Util.UtilMap;
-import com.malk.minjiaoyuan.service.MJYService;
-import com.malk.server.aliwork.YDConf;
-import com.malk.server.aliwork.YDParam;
-import com.malk.server.common.McException;
-import com.malk.server.common.McR;
-import com.malk.server.dingtalk.DDR_New;
-import com.malk.service.aliwork.YDClient;
-import com.malk.service.dingtalk.DDClient;
-import com.malk.service.dingtalk.DDClient_Contacts;
-import lombok.SneakyThrows;
-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.Arrays;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 错误抛出与拦截详见CatchException
- */
-@Slf4j
-@RestController
-@RequestMapping("/minjiaoyuan")
-public class InviteControl {
-
-
-    @Autowired
-    private YDClient ydClient;
-
-    @Autowired
-    private DDClient ddClient;
-
-    @Autowired
-    private DDClient_Contacts ddClient_contacts;
-
-    @Autowired
-    private MJYService mjyService;
-
-    /**
-     * 同步学校 & 钉钉通讯录
-     */
-    @SneakyThrows
-    @PostMapping("sync/department")
-    McR department() {
-        log.info("同步学校 & 钉钉通讯录");
-        List<Map> deptList = ddClient.getDepartmentDetail_all(ddClient.getAccessToken());
-        for (Map dept : deptList) {
-            YDParam ydParam = YDParam.builder()
-                    .formUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLUE")
-                    .searchFieldJson(JSON.toJSONString(UtilMap.map("selectField_lgf41nj4", dept.get("name"))))
-                    .pageSize(1)
-                    .build();
-            DDR_New ddr_new = ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_search_form);
-            if (ddr_new.getTotalCount() == 0) {
-                continue;
-            }
-            Map formData = ((List<Map>) ddr_new.getData()).get(0);
-            if (StringUtils.isNotBlank(String.valueOf(((Map) formData.get("formData")).get("textField_lhldcchn")))) {
-                continue;
-            }
-            Thread.sleep(100); // 避免限流
-            ydParam.setFormInstanceId(formData.get("formInstanceId").toString());
-            ydParam.setUpdateFormDataJson(JSON.toJSONString(UtilMap.map("textField_lhldcchn", dept.get("dept_id"))));
-            ydClient.operateData(ydParam, YDConf.FORM_OPERATION.update);
-        }
-        return McR.success();
-    }
-
-    /**
-     * 创建人员: 邀请到架构 [配置提交校验, 无需更新宜搭单据]
-     */
-    @PostMapping("invite/user")
-    McR createUser(@RequestBody Map data) {
-        log.info("创建员工, {}", data);
-        McException.assertParamException_Null(data, "userId", "name", "mobile", "deptId");
-        Map bodyInfo = UtilMap.map("userid", data.get("userId"));
-        ddClient_contacts.createUser(ddClient.getAccessToken(), String.valueOf(data.get("name")), String.valueOf(data.get("mobile")), Arrays.asList(String.valueOf(data.get("deptId"))), bodyInfo);
-        return McR.success();
-    }
-
-    /**
-     * 同步教师档案 [已邀请], 定时同步后更新为已同步
-     */
-    @PostMapping("sync/teacher")
-    McR syncTeacherStatus() {
-        mjyService.syncTeacherStatus();
-        return McR.success();
-    }
-}

+ 0 - 442
mjava-minjiaoyuan/src/main/java/com/malk/minjiaoyuan/controller/MJYController.java

@@ -1,442 +0,0 @@
-package com.malk.minjiaoyuan.controller;
-
-import com.alibaba.fastjson.JSON;
-import com.malk.Util.UtilList;
-import com.malk.Util.UtilMap;
-import com.malk.Util.UtilServlet;
-import com.malk.minjiaoyuan.service.MJYService;
-import com.malk.server.aliwork.YDConf;
-import com.malk.server.aliwork.YDParam;
-import com.malk.server.common.McException;
-import com.malk.server.common.McR;
-import com.malk.service.aliwork.YDClient;
-import com.malk.service.aliwork.YDService;
-import lombok.Synchronized;
-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 javax.servlet.http.HttpServletRequest;
-import java.util.*;
-import java.util.stream.Collectors;
-
-/**
- * 错误抛出与拦截详见CatchException
- */
-@Slf4j
-@RestController
-@RequestMapping("/minjiaoyuan")
-public class MJYController {
-
-    @Autowired
-    private YDConf ydConf;
-
-    @Autowired
-    private YDClient ydClient;
-
-    @Autowired
-    private MJYService mjyService;
-
-    /**
-     * 同步名额数据
-     */
-    @Synchronized
-    @PostMapping("sync/quota")
-    McR quotaSync(@RequestBody Map<String, String> data) {
-
-        log.info("###### 同步名额数据 #####");
-
-        // 参数合法校验
-        McException.assertParamException_Null(data, "period");
-        String period = data.get("period");
-
-        // 是否重新计算
-        YDParam ydParam = YDParam.builder()
-                .formUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLLE")
-                .pageSize(1)
-                .searchCondition(JSON.toJSONString(UtilMap.map("selectField_lggd61a7", period)))
-                .build();
-        long totalCount = ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_list).getTotalCount();
-        McException.assertAccessException(totalCount > 0, period + "名额已计算, 若需重置请删除后台数据后重试");
-
-        // 查询教师档案
-        ydParam.setSearchCondition(null);
-        ydParam.setFormUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLAE");
-        List<Map> teacherList = mjyService.queryAllBySync(ydParam);
-        log.info("教师档案数据, {}", teacherList.size());
-
-        // 学校档案去重
-        List<Map> schoolList = new ArrayList<>();
-        for (Map teacher : teacherList) {
-            Map formData = (Map) teacher.get("formData");
-            // 条件: 学校全称
-            Optional matchData = schoolList.stream().filter(school -> formData.get("textField_lgeyihed").equals(school.get("textField_lgezb8r7"))).findAny();
-            Map schoolMap;
-            if (!matchData.isPresent()) {
-                schoolMap = UtilMap.map("selectField_lggd61a7, radioField_lgf7zdi5", period, "未开始");
-                schoolMap.put("textField_lgezb8r7", formData.get("textField_lgeyihed")); // 学校全称
-                schoolMap.put("textField_lggdp94o", formData.get("textField_lgeyihe8")); // 学校简称
-                schoolMap.put("selectField_lggdghio", formData.get("selectField_lggdghio")); // 所属学段
-                schoolMap.put("numberField_lgf2au4s", 0); // 在编在岗人数
-                schoolList.add(schoolMap);
-            } else {
-                schoolMap = (Map) matchData.get();
-            }
-            // prd: 档案教师计算比例都是在编在岗
-            if (formData.get("radioField_lgezgr8l").equals("是")) {
-                schoolMap.put("numberField_lgf2au4s", (int) schoolMap.get("numberField_lgf2au4s") + 1);
-            }
-            log.debug("教师档案处理, {}", formData);
-        }
-        log.info("学校档案数据, {}, {}", schoolList.size(), schoolList);
-
-        // 学校名额计算
-        for (Map schoolData : schoolList) {
-            String schoolName = String.valueOf(schoolData.get("textField_lgezb8r7"));
-            int numZBZG = Integer.valueOf(String.valueOf(schoolData.get("numberField_lgf2au4s")));
-            // 骨干系列: prd 骨干比例拆分比例分项计算, 合计数不一定匹配, 因此不计算骨干系列名额
-            int ratioGDXT = mjyService.getSchoolRatio(schoolName, "骨干系列");
-            schoolData.put("numberField_lgf2au4t", ratioGDXT);
-            // 学科带头人和骨干教师
-            int ratioXDGG = mjyService.getSchoolRatio(schoolName, "学科带头人和骨干教师");
-            schoolData.put("numberField_lgf2au51", ratioXDGG);
-            schoolData.put("numberField_lgf2au52", Math.round(numZBZG * ratioXDGG / 100));
-            // 骨干后备
-            int numGGHB = Math.round(numZBZG * (ratioGDXT - ratioXDGG) / 100);
-            schoolData.put("numberField_lghpgjyk", ratioGDXT - ratioXDGG);
-            schoolData.put("numberField_lgf2au4z", numGGHB);
-            // 写入学校档案
-            log.info("学校名额计算, {}", schoolData);
-            ydParam.setFormDataJson(JSON.toJSONString(schoolData));
-            ydParam.setFormUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLLE");
-            ydClient.operateData(ydParam, YDConf.FORM_OPERATION.create);
-        }
-        return McR.success(mjyService.matchQuery(schoolList));
-    }
-
-    /**
-     * 查询学校名额
-     */
-    @PostMapping("query/quota")
-    McR quotaQuery(@RequestBody Map<String, String> data) {
-        McException.assertParamException_Null(data, "period");
-        String period = data.get("period");
-        YDParam ydParam = YDParam.builder()
-                .formUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLLE")
-                .searchCondition(JSON.toJSONString(UtilMap.map("selectField_lggd61a7", period)))
-                .build();
-        List<Map> schoolList = mjyService.queryAllBySync(ydParam);
-        log.info("学校名额数据, {}", schoolList.size());
-        List list = schoolList.stream().map(item -> (Map) item.get("formData")).collect(Collectors.toList());
-        return McR.success(mjyService.matchQuery(list));
-    }
-
-    /**
-     * 推送学校名额确认
-     */
-    @PostMapping("confirm/quota")
-    McR quotaConfirm(HttpServletRequest request) {
-        Map data = UtilServlet.getParamMap(request);
-        McException.assertParamException_Null(data, "formInstanceId");
-        YDParam ydParam = YDParam.builder()
-                .formInstanceId(String.valueOf(data.get("formInstanceId")))
-                .build();
-        Map formData = ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_id).getFormData();
-        List<Map> details = (List<Map>) formData.get("tableField_lgf41nj3");
-        // 创建学校确认流程: src - cur, 发起流程 - 学校确认; 明细内: 全称, 简称, 在编在岗, 学带 + 骨干教师, 后备, 学校负责人
-        Map<String, String> keyMap = UtilMap.map("selectField_lgf41nj4, selectField_lgi7oaqo, numberField_lgf2au4s, numberField_lgi7oaqq, numberField_lgi7oaqr, employeeField_lgf7ky0h",
-                "selectField_lgf41nj4, selectField_lgi7oaqo, numberField_lgf2au4s, numberField_lgi7oaqq, numberField_lgi7oaqr, employeeField_lgf7m9s4");
-        for (Map detail : details) {
-            // 主表读取: 届别, 提交人
-            Map formJson = UtilMap.map("selectField_lggd61a7, employeeField_lgf7ky0i", formData.get("selectField_lggd61a7"), formData.get("employeeField_lgf6dzrv_id"));
-            for (String key : keyMap.keySet()) {
-                if (key.contains("employeeField_")) {
-                    formJson.put(key, detail.get(keyMap.get(key) + "_id"));
-                } else {
-                    formJson.put(key, detail.get(keyMap.get(key)));
-                }
-            }
-            log.info("名额确认记录, {}, {}", formJson, detail);
-            ydParam.setFormDataJson(JSON.toJSONString(formJson));
-            ydParam.setFormUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLYD");
-            ydParam.setProcessCode("TPROC--G2666871DH3AGJ52BWGGY62N9HGV39Y1TRTGLL6");
-            ydClient.operateData(ydParam, YDConf.FORM_OPERATION.start);
-        }
-        return McR.success();
-    }
-
-    /**
-     * 汇总学校复核数据
-     */
-    @Synchronized
-    @PostMapping("approve/quota")
-    McR quotaApprove(HttpServletRequest request) {
-        Map data = UtilServlet.getParamMap(request);
-        McException.assertParamException_Null(data, "formInstanceId");
-        log.info("学校汇总, {}", data);
-
-        // 查询教师申请数据
-        YDParam ydParam = YDParam.builder()
-                .formInstanceId(String.valueOf(data.get("formInstanceId")))
-                .build();
-        Map teacherData = ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_id).getFormData();
-
-        // 匹配学校汇总数据: 届别 + 学校全称
-        Map formData = UtilMap.map("selectField_lggd61a7, selectField_lgf41nj4", teacherData.get("selectField_lgs5yclt"), teacherData.get("textField_lgf4ppaw"));
-        ydParam.setFormUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLWD");
-        ydParam.setSearchCondition(JSON.toJSONString(formData));
-        List<Map> schoolApprove = (List<Map>) ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_list_all).getData();
-
-        // 组装评审明细数据: 关联评选记录, 教师进修编号, 教师成员, 手机号, 评选类型, 行政职务
-        formData.put("selectField_lgi7oaqo", teacherData.get("textField_lgib58q3")); // 学校简称
-        formData.put("employeeField_lgf7ky0h", teacherData.get("employeeField_lgf7ky0h_id")); // 学校负责人
-        formData.put("radioField_lggd61a8", "进行中"); // 届别评选状态
-        List<Map> details = new ArrayList<>();
-        if (UtilList.isNotEmpty(schoolApprove)) {
-            Map recordData = schoolApprove.get(0);
-            details = (List<Map>) (((Map) recordData.get("formData"))).get("tableField_lgiacs44");
-            // 成员组件 && 关联表单数据处理
-            details.forEach(item -> {
-                item.put("employeeField_lgialujd", item.get("employeeField_lgialujd_id"));
-                item.put("associationFormField_lgiacs47", JSON.parse(String.valueOf(item.get("associationFormField_lgiacs47_id"))));
-            });
-            ydParam.setFormInstanceId(String.valueOf(recordData.get("formInstanceId")));
-        }
-        Map detail = UtilMap.map("textField_lgialujb, employeeField_lgialujd, numberField_lgeyihee, selectField_lgf4ppa6, textField_lgt9sb8f", teacherData.get("textField_lgf4ppax"), teacherData.get("employeeField_lgf4ppa7_id"), teacherData.get("numberField_lgeyihee"), teacherData.get("selectField_lgf4ppa6"), teacherData.get("textField_lgt9sb8f"));
-        detail.put("associationFormField_lgiacs47", Arrays.asList(UtilMap.map("appType, formUuid, instanceId, title, formType, subTitle", ydConf.getAppType(), "FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLVD", data.get("formInstanceId"), teacherData.get("textField_lgs8ej3g"), "receipt", teacherData.get("textField_lgf4ppax"))));
-        details.add(detail);
-        // prd 按照评选类型, 排序: 学带, 骨干, 特色, 后备
-        Map sortRule = UtilMap.map("学科带头人, 骨干教师, 骨干后备, 特色骨干", 1, 2, 3, 4);
-        details.forEach(item -> item.put("sort", sortRule.get(item.get("selectField_lgf4ppa6"))));
-        Collections.sort(details, Comparator.comparingInt(o -> Integer.parseInt(String.valueOf(o.get("sort")))));
-        formData.put("tableField_lgiacs44", details);
-        log.info("学校汇总记录, {}", JSON.toJSONString(formData));
-        ydParam.setFormDataJson(JSON.toJSONString(formData));
-        ydParam.setFormUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLWD");
-        ydParam.setProcessCode("TPROC--G2666871DH3AGJ52BWGGY62N9HGV39Y1TRTGLN6");
-        if (UtilList.isNotEmpty(schoolApprove)) {
-            ydParam.setUpdateFormDataJson(ydParam.getFormDataJson());
-            ydClient.operateData(ydParam, YDConf.FORM_OPERATION.update);
-            return McR.success();
-        }
-        ydClient.operateData(ydParam, YDConf.FORM_OPERATION.start);
-
-        return McR.success();
-    }
-
-    @Autowired
-    private YDService ydService;
-
-    /**
-     * 学校申报区里, 名额校验
-     */
-    @PostMapping("validate/quota")
-    McR quotaValidate(HttpServletRequest request) {
-        Map data = UtilServlet.getParamMap(request);
-        McException.assertParamException_Null(data, "formInstanceId");
-        log.info("名额校验, {}", data);
-
-        List usersZRMD = mjyService.getDirectList(); // 直入名单
-        // 学校申报数据
-        YDParam ydParam = YDParam.builder()
-                .formInstanceId(String.valueOf(data.get("formInstanceId")))
-                .build();
-        Map approveData = ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_id).getFormData();
-        List<Map> details = (List<Map>) approveData.get("tableField_lgiacs44");
-        // 储存排名并进行排序
-        List arrSort = (List) JSON.parse(String.valueOf(data.get("details_sort")));
-        for (int i = 0; i < arrSort.size(); i++) {
-            details.get(i).put("numberField_lh8monwb", arrSort.get(i));
-        }
-        Collections.sort(details, Comparator.comparingInt(o -> Integer.parseInt(String.valueOf(o.get("numberField_lh8monwb")))));
-
-        // 匹配通过数据 & 未在直入名单 [进修编号]
-        List arrStatus = (List) JSON.parse(String.valueOf(data.get("details_status")));
-        List arrType = (List) JSON.parse(String.valueOf(data.get("details_type")));
-        List arrPeerRatio = (List) JSON.parse(String.valueOf(data.get("details_peer_ratio")));
-        List<Integer> approveList = new ArrayList();
-        int appXKDTR = 0, appGGJS = 0, appGGHB = 0, appTSGG = 0;
-        for (int i = 0; i < arrStatus.size(); i++) {
-            // prd 直入名单通过人员匹配, 不占用名额, 教师信息报区里
-            if (usersZRMD.contains(details.get(i).get("textField_lgialujb"))) {
-                details.get(i).put("isDirect", "直入名单");
-                approveList.add(i);
-                log.info("直入名单, {}", details.get(i));
-            } else if (arrStatus.get(i).equals("通过")) {
-                if (arrType.get(i).equals("学科带头人")) appXKDTR += 1;
-                if (arrType.get(i).equals("骨干教师")) appGGJS += 1;
-                if (arrType.get(i).equals("骨干后备")) appGGHB += 1;
-                if (arrType.get(i).equals("特色骨干")) appTSGG += 1;
-                approveList.add(i);
-            }
-            // 记录前台填写同职比
-            details.get(i).put("textField_lgst1j31", arrPeerRatio.get(i));
-        }
-        log.info("申报数量, appXKDTR = {}, appGGJS = {}, appGGHB = {}, appTSGG = {}", appXKDTR, appGGJS, appGGHB, appTSGG);
-
-        // 学校名额信息: 届别 + 学校全称
-        ydParam.setFormInstanceId(null);
-        ydParam.setFormUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLLE");
-        ydParam.setSearchCondition(JSON.toJSONString(UtilMap.map("selectField_lggd61a7, textField_lgezb8r7", approveData.get("selectField_lggd61a7"), approveData.get("selectField_lgf41nj4"))));
-        ydParam.setPageSize(1);
-        Map schoolData = (Map) ((List<Map>) ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_list).getData()).get(0).get("formData");
-        int numXDGG = Integer.valueOf(String.valueOf(schoolData.get("numberField_lgf2au52")));
-        int numGGHB = Integer.valueOf(String.valueOf(schoolData.get("numberField_lgf2au4z")));
-        // 学带 + 骨干教师名额校验
-        McException.assertAccessException((appXKDTR + appGGJS) > numXDGG, "申报名额校验未通过,请核查!");
-        // 名额降级逻辑,骨干后备可以占骨干教师 + 学带名额 [prd 申报名额未用完或超标均不能上报]
-        McException.assertAccessException((appGGHB + appXKDTR + appGGJS) != (numGGHB + numXDGG), "申报名额校验未通过,请核查!");
-
-        // 更新申报信息: 进修编号, 评选类型, 同职比, 手机号
-        Map updateJson = UtilMap.map("numberField_lgstol7i, numberField_lgstol7k, numberField_lgstol7j, numberField_lgstol7l", appXKDTR, appGGJS, appGGHB, appTSGG);
-        List<Map> appDetails = approveList.stream().map(index -> {
-            Map item = details.get(index); // 记录索引
-            Map row = UtilMap.map("textField_lgst1j33, selectField_lgst1j35, textField_lgst1j3g, numberField_lgst1j37", item.get("textField_lgialujb"), item.get("selectField_lgf4ppa6"), item.get("textField_lgst1j31"), item.get("numberField_lgeyihee"));
-            row.put("textField_lgt59zeb", item.get("isDirect"));
-            row.put("employeeField_lgst1j34", item.get("employeeField_lgialujd_id"));
-            row.put("associationFormField_lgst1j32", JSON.parse(String.valueOf(item.get("associationFormField_lgiacs47_id"))));
-            return row;
-        }).collect(Collectors.toList());
-        updateJson.put("tableField_lgst1j3e", appDetails);
-        updateJson.put("tableField_lgiacs44", details); // 更新学校排序
-        ydParam.setFormInstanceId(String.valueOf(data.get("formInstanceId")));
-        ydParam.setUpdateFormDataJson(JSON.toJSONString(updateJson));
-        // 操作数据 [异步] - 审批通过立即更新, 会无效
-        ydService.operateData(ydParam, YDConf.FORM_OPERATION.update);
-        log.info("更新申报信息, {}", appDetails);
-
-        return McR.success();
-    }
-
-    // 宜搭审批页面弱校验提示框会被覆盖, 或另一个校验冲销. 添加记录, 第二次请求放行
-    private Map checkMap = new HashMap();
-
-    /**
-     * 学校申报区里, 学校中层或校级副职干部, 弱校验
-     */
-    @PostMapping("check/quota")
-    McR quotaCheck(HttpServletRequest request) {
-        Map data = UtilServlet.getParamMap(request);
-        McException.assertParamException_Null(data, "formInstanceId");
-        log.info("名额验证, {}", data);
-
-        List usersZRMD = mjyService.getDirectList(); // 直入名单
-        // 学校申报数据
-        YDParam ydParam = YDParam.builder()
-                .formInstanceId(String.valueOf(data.get("formInstanceId")))
-                .build();
-        Map approveData = ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_id).getFormData();
-        List<Map> details = (List<Map>) approveData.get("tableField_lgiacs44");
-        // 匹配通过数据 & 未在直入名单 [进修编号]
-        List arrStatus = (List) JSON.parse(String.valueOf(data.get("details_status")));
-        List arrType = (List) JSON.parse(String.valueOf(data.get("details_type")));
-        List<Map> approveList = new ArrayList();
-        int appGGHB = 0;
-        for (int i = 0; i < arrStatus.size(); i++) {
-            // prd 直入名单通过人员匹配, 不占用名额, 教师信息报区里
-            if (usersZRMD.contains(details.get(i).get("textField_lgialujb"))) {
-                approveList.add(details.get(i));
-                details.get(i).put("isDirect", "直入名单");
-                log.info("直入名单, {}", details.get(i));
-            } else if (arrStatus.get(i).equals("通过")) {
-                approveList.add(details.get(i));
-                if (arrType.get(i).equals("骨干后备")) appGGHB += 1;
-            }
-        }
-        float numZCXF = approveList.stream().filter(item -> Arrays.asList("学校副职", "中层副职", "中层正职").contains(item.get("textField_lgt9sb8f"))).collect(Collectors.toList()).size();
-        log.info("学校中层或校级副职干部, 弱校验, appGGHB = {}, nunZCXF = {}", appGGHB, numZCXF);
-
-        // 学校名额信息: 届别 + 学校全称
-        ydParam.setFormInstanceId(null);
-        ydParam.setFormUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLLE");
-        ydParam.setSearchCondition(JSON.toJSONString(UtilMap.map("selectField_lggd61a7, textField_lgezb8r7", approveData.get("selectField_lggd61a7"), approveData.get("selectField_lgf41nj4"))));
-        ydParam.setPageSize(1);
-        Map schoolData = (Map) ((List<Map>) ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_list).getData()).get(0).get("formData");
-        // prd 学校中层或校级副职干部,每周兼课时数需达到教育局规定课时量,比例不超过学校申报骨干后备教师人选的20%。(学校教师人在编在岗数不满30人,比例不超过学校申报骨干后备教师人选的25%)
-        float numZBZG = Integer.valueOf(String.valueOf(schoolData.get("numberField_lgf2au4s")));
-        int ratio = numZBZG >= 30 ? 25 : 20;
-        log.info("学校中层或校级副职干部, 弱校验, check = {}, ratio = {}", appGGHB / numZBZG, ratio / 100F);
-        if (!checkMap.containsKey(data.get("formInstanceId"))) {
-            checkMap.put(data.get("formInstanceId"), true);
-            McException.assertAccessException((appGGHB / numZBZG) > (ratio / 100F), "学校中层或校级副职干部, 占比骨干后备超标准");
-        }
-        return McR.success();
-    }
-
-    /**
-     * 是否直入名单
-     */
-    @PostMapping("direct/quota")
-    McR directQuota(@RequestBody Map data) {
-        log.info("是否直入名单", data);
-        McException.assertParamException_Null(data, "code");
-        List usersZRMD = mjyService.getDirectList(); // 直入名单
-        return McR.success(UtilMap.map("isDirect", usersZRMD.contains(data.get("code"))));
-    }
-
-    /**
-     * 退回卡片通知
-     * 被学校退回:某某老师,您的骨干系列评选材料已被学校退回。
-     * 被区级退回:某某老师,您的骨干系列评选材料已被区级退回;某某学校,您校某某老师的评选资料已被区级退回。
-     */
-    @PostMapping("notice/sendback")
-    McR sendBackNotice(HttpServletRequest request) {
-        Map data = UtilServlet.getParamMap(request);
-        log.info("退回卡片通知, {}", data);
-        McException.assertParamException_Null(data, "teachers, administrator, results, associations, createUserId, schoolName");
-        List<String> teachers = (List<String>) JSON.parse(String.valueOf(data.get("teachers")));
-        List<String> associations = (List<String>) JSON.parse(String.valueOf(data.get("associations")));
-        List<String> results = (List<String>) JSON.parse(String.valueOf(data.get("results")));
-        String createUserId = String.valueOf(data.get("createUserId"));
-        String schoolName = String.valueOf(data.get("schoolName"));
-        for (int i = 0; i < results.size(); i++) {
-            String status = results.get(i);
-            if (!Arrays.asList("不通过", "退回").contains(status)) {
-                continue;
-            }
-            List<Map> associationForm = (List<Map>) JSON.parse(associations.get(i));
-            String notice = associationForm.get(0).get("title") + "老师[" + associationForm.get(0).get("subTitle") + "]";
-            Map formData = UtilMap.map("employeeField_lhgj6tc7, employeeField_lhgj6tc9, associationFormField_lgiacs47", JSON.parse(teachers.get(i)), data.get("administrator"), associationForm);
-            if ("不通过".equals(status)) {
-                notice += ", 您好: \n您的骨干系列评选材料已被学校退回。";
-            }
-            if ("退回".equals(status)) {
-                notice += ", 您好: \n您的骨干系列评选材料已被区级退回。";
-                // 通知学校
-                String new_notice = schoolName + ", 管理员您好: \n您校" + associationForm.get(0).get("title") + "老师[" + associationForm.get(0).get("subTitle") + "]";
-                new_notice += "的评选资料已被区级退回。";
-                formData.put("textareaField_lhgj6tcu", new_notice);
-                mjyService.triggerNotice("FORM-NC966W81139A3Y5QEEXT5AZ6BU7M3TB0C9LHLO", createUserId, formData);
-            }
-            // 通知老师
-            formData.put("textareaField_lhgj6tcu", notice);
-            mjyService.triggerNotice("FORM-NT766881D48AF5W78VL7L6VLZTAJ2TOE6JGHL92", createUserId, formData);
-        }
-        return McR.success();
-    }
-
-    /**
-     * 评选信息变更
-     */
-    @PostMapping("update/details")
-    McR updateDetails(HttpServletRequest request) {
-        Map data = UtilServlet.getParamMap(request);
-        McException.assertParamException_Null(data, "formInstanceId");
-        log.info("信息变更, {}", data);
-
-        YDParam ydParam = YDParam.builder()
-                .formInstanceId(String.valueOf(data.get("formInstanceId")))
-                .build();
-        Map formData = ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_id).getFormData();
-        List<Map> details = (List<Map>) formData.get("tableField_lgs5ycm5");
-
-        List<Map> association = (List<Map>) JSON.parse(String.valueOf(data.get("associationComp")));
-        ydParam.setFormInstanceId(String.valueOf(association.get(0).get("instanceId")));
-        ydParam.setUpdateFormDataJson(JSON.toJSONString(UtilMap.map("tableField_lgs5ycm5", details)));
-        ydClient.operateData(ydParam, YDConf.FORM_OPERATION.update);
-        return McR.success();
-    }
-}

+ 0 - 161
mjava-minjiaoyuan/src/main/java/com/malk/minjiaoyuan/controller/TestControl.java

@@ -1,161 +0,0 @@
-package com.malk.minjiaoyuan.controller;
-
-import com.alibaba.fastjson.JSON;
-import com.malk.Util.UtilMap;
-import com.malk.minjiaoyuan.service.MJYService;
-import com.malk.server.aliwork.YDConf;
-import com.malk.server.aliwork.YDParam;
-import com.malk.server.common.McException;
-import com.malk.server.common.McR;
-import com.malk.server.dingtalk.DDR_New;
-import com.malk.service.aliwork.YDClient;
-import com.malk.service.dingtalk.DDClient;
-import com.malk.service.dingtalk.DDClient_Contacts;
-import lombok.SneakyThrows;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Profile;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 指定运行环境
- *
- * @Profile("prod"):一般添加于方法和类,标注该方法为指定环境运行 —>  若未找到指定环境会报错,多个环境与 @ActiveProfiles 一致
- */
-@Profile({"dev"})
-@Slf4j
-@RestController
-@RequestMapping("/minjiaoyuan")
-public class TestControl {
-
-
-    @Autowired
-    private YDClient ydClient;
-
-    @Autowired
-    private YDConf ydConf;
-
-    @Autowired
-    private MJYService mjyService;
-
-    @PostMapping("test2")
-    McR test2() {
-        // 修改评选进修编号
-        String formInstanceId = "cefb90d5-9e8d-4cad-9fad-ac66d8f06362";
-        YDParam ydParam = YDParam.builder()
-                .formInstanceId(formInstanceId)
-                .build();
-        ydParam.setUpdateFormDataJson(JSON.toJSONString(UtilMap.map("selectField_lgf4ppa6", "骨干后备")));
-        ydClient.operateData(ydParam, YDConf.FORM_OPERATION.update);
-        return McR.success();
-    }
-
-    @PostMapping("test")
-    McR test() {
-
-        String formInstanceId = "98c7a6c9-bbbb-49e8-9838-f9f670e07859"; // 上海市金汇高级中学
-//        String formInstanceId = "9c256687-cdee-4ce8-bca6-99f574d81a97"; // 闵行区七宝中心幼儿园
-//        String formInstanceId = "60e7008a-6f11-410a-8019-d24be8c36abe"; // 上海市闵行区七宝幼儿园
-//        String formInstanceId = "808370ff-dfc3-44f0-960e-da5b7c77defb"; // 上海市七宝中学附属鑫都实验中学
-//        String formInstanceId = "86f436ae-0d19-4d6b-a909-346e1c30139e"; // 闵行区实验小学
-//        String formInstanceId = "11c6fb7b-0a8e-4595-b1cf-0a7648316eff"; // 上海市七宝实验小学
-//        String formInstanceId = "6f813646-d2c3-40f3-a72b-bf4fd2175724"; // 上海市民办文绮中学
-//        String formInstanceId = "4808e60e-d645-4ca3-895a-8bf9b582aa3a"; // 上海师范大学康城实验学校
-//        String formInstanceId = "616b546b-a41b-47df-8283-a6c719ca317c"; // 上海市闵行区爱博果果幼儿园
-//        String formInstanceId = "9e380af2-da2d-493e-8a37-39a685e952b1"; // 上海市闵行区颛桥中学
-//        String formInstanceId = "44b0a12d-b10f-4081-bbd7-2107427c675e"; // 上海市七宝中学
-
-
-        // 学校申报数据
-        YDParam ydParam = YDParam.builder()
-                .formInstanceId(formInstanceId)
-                .build();
-        Map approveData = ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_id).getFormData();
-        List<Map> details = (List<Map>) approveData.get("tableField_lgiacs44");
-        // 匹配申报数据
-        ydParam.setFormInstanceId("");
-        for (Map detail : details) {
-            ydParam.setSearchFieldJson(JSON.toJSONString(UtilMap.map("textField_lgf4ppax", detail.get("textField_lgialujb"))));
-//            if (String.valueOf(detail.get("employeeField_lgialujd")).contains("刘欣")) {
-//                detail.put("textField_lgialujb", "120111015278");
-//                ydParam.setSearchFieldJson(JSON.toJSONString(UtilMap.map("textField_lgf4ppax", "120111015278")));
-//            }
-            ydParam.setApprovedResult("agree");
-            ydParam.setFormUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLVD");
-            DDR_New ddr_new = ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_search_process);
-            Map data = ((List<Map>) ddr_new.getData()).get(0);
-            Map formData = (Map) data.get("data");
-            detail.put("associationFormField_lgiacs47", Arrays.asList(UtilMap.map("appType, formUuid, instanceId, title, formType, subTitle", ydConf.getAppType(), "FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLVD", data.get("processInstanceId"), formData.get("textField_lgs8ej3g"), "receipt", formData.get("textField_lgf4ppax"))));
-            detail.put("employeeField_lgialujd", formData.get("employeeField_lgf4ppa7_id"));
-//            detail.put("textField_lgivbkar", detail.get("radioField_lgialujc").equals("通过") ? "内通过" : "内拒绝");
-            log.info("xxx, {}, {}", detail.get("employeeField_lgialujd"), ddr_new.getTotalCount());
-            McException.assertAccessException(ddr_new.getTotalCount() != 1, "数据匹配异常");
-        }
-
-        Map update = UtilMap.map("tableField_lgiacs44", details);
-        ydParam.setFormInstanceId(formInstanceId);
-        ydParam.setUpdateFormDataJson(JSON.toJSONString(update));
-        log.info("update, {}, {}", formInstanceId, JSON.toJSONString(update));
-        ydClient.operateData(ydParam, YDConf.FORM_OPERATION.update);
-
-        return McR.success();
-    }
-
-    // 清理数据 [教师档案]
-    @PostMapping("delete")
-    McR delete() {
-//        YDParam ydParam = YDParam.builder()
-//                .formUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLAE")
-//                .build();
-//        List<Map> list = mjyService.queryAllBySync(ydParam);
-//        list.forEach(item -> {
-//            ydParam.setFormInstanceId(String.valueOf(item.get("formInstanceId")));
-//            ydClient.operateData(ydParam, YDConf.FORM_OPERATION.delete);
-//        });
-        return McR.success();
-    }
-
-    @Autowired
-    private DDClient ddClient;
-
-    @Autowired
-    private DDClient_Contacts ddClient_contacts;
-
-    // 清理数据 [通讯录]
-    @SneakyThrows
-    @PostMapping("delete2")
-    McR delete2() {
-
-//        List<Long> deptList = ddClient.getDepartmentId_all(ddClient.getAccessToken());
-//        for (Long deptId : deptList) {
-//            List<String> userList = ddClient_contacts.listDepartmentUserId(ddClient.getAccessToken(), deptId.longValue());
-//            for (String userId : userList) {
-//                if (Arrays.asList("244859276337982323", "011063125337883469").contains(userId)) {
-//                    continue;
-//                }
-//                YDParam ydParam = YDParam.builder()
-//                        .formUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLAE")
-//                        .searchFieldJson(JSON.toJSONString(UtilMap.map("textField_lftczqr5", userId)))
-//                        .build();
-//                DDR_New ddr_new = ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_search_form);
-//                if (ddr_new.getTotalCount() == 0) {
-//                    ddClient_contacts.deleteUser(ddClient.getAccessToken(), userId);
-//                    log.info("xxx, {}, {}, {}", userId, ddr_new.getTotalCount(), ddr_new.getData());
-//                }
-//                Thread.sleep(100); // 避免限流
-//            }
-//        }
-        return McR.success();
-    }
-
-
-    @PostMapping("h3yun-http")
-    McR http(@RequestBody Map data, @RequestParam("code") String code) {
-        log.info("氚云http调试, code = {}, body = {}", code, data);
-        return McR.success(UtilMap.map("name", "氚云http调试"));
-    }
-}

+ 0 - 36
mjava-minjiaoyuan/src/main/java/com/malk/minjiaoyuan/schedule/MJYScheduleTask.java

@@ -1,36 +0,0 @@
-package com.malk.minjiaoyuan.schedule;
-
-import com.malk.minjiaoyuan.service.MJYService;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.scheduling.annotation.EnableScheduling;
-import org.springframework.scheduling.annotation.Scheduled;
-
-/**
- * @EnableScheduling 开启桑诺定时任务 [配置参考McScheduleTask]
- */
-@Slf4j
-@Configuration
-@EnableScheduling
-@ConditionalOnProperty(name = {"spel.scheduling"})
-public class MJYScheduleTask {
-
-    @Autowired
-    private MJYService mjyService;
-
-    /**
-     * 定时同步后更新为已同步 [0...5分钟/次]
-     */
-    @Scheduled(cron = "0 0/5 6-23 * * ?")
-    public void Time_Period_1() {
-        try {
-            log.info("###### [MJY]同步教师档案开始 [已邀请] ######");
-            mjyService.syncTeacherStatus();
-        } catch (Exception e) {
-            log.error(e.getMessage(), e); // 记录错误日志
-        }
-        log.info("###### [MJY]同步教师档案结束 [已邀请] ######");
-    }
-}

+ 0 - 27
mjava-minjiaoyuan/src/main/java/com/malk/minjiaoyuan/service/MJYService.java

@@ -1,27 +0,0 @@
-package com.malk.minjiaoyuan.service;
-
-import com.malk.server.aliwork.YDParam;
-
-import java.util.List;
-import java.util.Map;
-
-public interface MJYService {
-
-    // 获取学校与类型比例
-    int getSchoolRatio(String schoolName, String typeName);
-
-    // 查询全部数据
-    List<Map> queryAllBySync(YDParam param);
-
-    // 获取直入名单
-    List<String> getDirectList();
-
-    // 触发通知 [宜搭平台账号不会触发通知]
-    void triggerNotice(String formUuid, String createUserId, Map formData);
-
-    // 匹配学校负责人
-    List<Map> matchQuery(List<Map> schoolQuotaList);
-
-    // 同步教师档案 [已邀请]
-    void syncTeacherStatus();
-}

+ 0 - 169
mjava-minjiaoyuan/src/main/java/com/malk/minjiaoyuan/service/impl/MJYImplService.java

@@ -1,169 +0,0 @@
-package com.malk.minjiaoyuan.service.impl;
-
-import com.alibaba.fastjson.JSON;
-import com.malk.Util.UtilMap;
-import com.malk.minjiaoyuan.service.MJYService;
-import com.malk.server.aliwork.YDConf;
-import com.malk.server.aliwork.YDParam;
-import com.malk.server.common.McException;
-import com.malk.service.aliwork.YDClient;
-import com.malk.service.aliwork.YDService;
-import com.malk.service.dingtalk.DDClient;
-import com.malk.service.dingtalk.DDClient_Contacts;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import java.util.*;
-import java.util.stream.Collectors;
-
-@Service
-@Slf4j
-public class MJYImplService implements MJYService {
-
-    @Autowired
-    private YDClient ydClient;
-
-    @Autowired
-    private YDService ydService;
-
-    // 名额配置
-    private List<Map> quotaList = new ArrayList<>();
-
-    // 获取学校与类型比例
-    @Override
-    public int getSchoolRatio(String schoolName, String typeName) {
-        if (quotaList.isEmpty()) {
-            List<Map> list = (List<Map>) ydClient.queryData(YDParam.builder()
-                    .formUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLKE")
-                    .pageSize(YDConf.PAGE_SIZE_LIMIT)
-                    .build(), YDConf.FORM_QUERY.retrieve_list_all).getData();
-            quotaList = list.stream().map(item -> (Map) item.get("formData")).collect(Collectors.toList());
-            log.info("名额配置数据, {}", quotaList.size());
-        }
-        Map formData = quotaList.stream().filter(item -> typeName.equals(item.get("selectField_lgf306u6"))).findAny().get();
-        int ratio = Integer.valueOf(String.valueOf(formData.get("numberField_lgezizyl")));
-        List<Map<String, ?>> details = (List<Map<String, ?>>) formData.get("tableField_lgezizyn");
-        Optional detail = details.stream().filter(item -> item.get("selectField_lgezizyo").equals(schoolName)).findAny();
-        if (detail.isPresent()) {
-            ratio = Integer.valueOf(String.valueOf(((Map) detail.get()).get("numberField_lgezizyq")));
-        }
-        return ratio;
-    }
-
-    // 查询全部数据
-    @Override
-    public List<Map> queryAllBySync(YDParam param) {
-        param.setPageSize(1);
-        long totalCount = ydClient.queryData(param, YDConf.FORM_QUERY.retrieve_list).getTotalCount();
-        List<Map> dataList = new ArrayList<>();
-        // Math.ceil 需要有浮点数, 否则转 int 类型忽略掉, 向上取整就会是当前值
-        for (int index = 1; index <= (int) Math.ceil(totalCount * 1.0 / YDConf.PAGE_SIZE_LIMIT); index++) {
-            // 对象拷贝: 避免并发下分页条件被修改导致数据混乱
-            YDParam ydParam = (YDParam) param.copyParam();
-            ydParam.setPageNumber(index);
-            ydParam.setPageSize(YDConf.PAGE_SIZE_LIMIT);
-            dataList.addAll((List) ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_list).getData());
-        }
-        return dataList;
-    }
-
-    // 获取直入名单
-    @Override
-    public List<String> getDirectList() {
-        YDParam ydParam = YDParam.builder()
-                .formUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLKE")
-                .searchCondition(JSON.toJSONString(UtilMap.map("selectField_lgf306u6", "直入名单")))
-                .pageSize(1)
-                .build();
-        String formInstanceId = (String) ((List<Map>) ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_search_form).getData()).get(0).get("formInstanceId");
-        ydParam.setFormInstanceId(formInstanceId);
-        ydParam.setTableFieldId("tableField_lgf2p2jm");
-        List<Map> details = ydService.queryDetails(ydParam);
-        log.info("直入名单, {}", details.size());
-        return details.stream().map(item -> (String) item.get("textField_lgt5j83x")).collect(Collectors.toList());
-    }
-
-    // 触发通知
-    @Override
-    public void triggerNotice(String formUuid, String createUserId, Map formData) {
-        YDParam ydParam = YDParam.builder()
-                .formUuid(formUuid)
-                .formDataJson(JSON.toJSONString(formData))
-                .userId(createUserId) // 触发通知
-                .build();
-        ydClient.operateData(ydParam, YDConf.FORM_OPERATION.create);
-    }
-
-    // 匹配学校负责人
-    @Override
-    public List<Map> matchQuery(List<Map> schoolQuotaList) {
-        YDParam ydParam = YDParam.builder()
-                .formUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLUE")
-                .build();
-        List<Map> schoolAuthList = queryAllBySync(ydParam);
-        List list = schoolQuotaList.stream().map(item -> {
-            // 条件: 学校全称
-            Optional optional = schoolAuthList.stream().filter(row -> ((Map) row.get("formData")).get("selectField_lgf41nj4").equals(item.get("textField_lgezb8r7"))).findAny();
-            if (optional.isPresent()) {
-                Map data = (Map) ((Map) optional.get()).get("formData");
-                // 前端展示格式: prd 学校负责人单选
-                List<String> empsName = (List<String>) data.get("employeeField_lgf7h60y");
-                List<String> empsId = (List<String>) data.get("employeeField_lgf7h60y_id");
-                List<Map> managers = new ArrayList<>();
-                for (int i = 0; i < empsName.size(); i++) {
-                    managers.add(UtilMap.map("name, value", empsName.get(i), empsId.get(i)));
-                }
-                item.put("employeeField_lgf7m9s4", managers);
-                log.info("匹配学校负责人, {}", data);
-            }
-            return item;
-        }).collect(Collectors.toList());
-        return list;
-    }
-
-    @Autowired
-    private DDClient ddClient;
-
-    @Autowired
-    private DDClient_Contacts ddClient_contacts;
-
-    // 同步教师档案 [已邀请]
-    @Override
-    public void syncTeacherStatus() {
-        // 查询已邀请教师档案数据
-        YDParam ydParam = YDParam.builder()
-                .formUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLAE")
-                .searchFieldJson(JSON.toJSONString(UtilMap.map("radioField_lhlhshbc", "已邀请")))
-                .build();
-        List<Map> dataList = queryAllBySync(ydParam);
-        log.info("同步教师数量, {}", dataList.size());
-        for (Map formData : dataList) {
-            Map dataForm = (Map) formData.get("formData");
-            String userId = dataForm.get("textField_lftczqr5").toString();
-            String remark;
-            String status = "已邀请";
-            // 是否进入架构
-            try {
-                ddClient_contacts.getUserInfoById(ddClient.getAccessToken(), userId);
-                remark = "已同步";
-                status = "已同步";
-            } catch (McException e) {
-                remark = e.getMessage();
-                log.error(e.getMessage(), e);
-            }
-            // 发送同步通知
-            if ("已同步".equals(remark)) {
-                String notice = dataForm.get("textField_lghs4pmx") + "老师[" + userId + "]";
-                notice += ", 您好: \n欢迎加入【闵行区教师梯队管理】架构, 您的档案已同步, 可发起骨干系列评选报名";
-                Map data = UtilMap.map("employeeField_lhgj6tc7, textField_lhlj3dgb, textareaField_lhgj6tcu", Arrays.asList(userId), userId, notice);
-                triggerNotice("FORM-8Y866XB1FGHAB037F4F7054SZMHI2RFZ1JLHLP", userId, data);
-            }
-            // 同步邀请状态
-            ydParam.setFormInstanceId(formData.get("formInstanceId").toString());
-            ydParam.setUpdateFormDataJson(JSON.toJSONString(UtilMap.map("textareaField_lhlqrv31, radioField_lhlhshbc, employeeField_lgeyfc4d", remark, status, Arrays.asList(userId))));
-            ydClient.operateData(ydParam, YDConf.FORM_OPERATION.update);
-            log.info("同步教师状态, {}, {}", userId, remark);
-        }
-    }
-}

+ 0 - 65
mjava-minjiaoyuan/src/main/resources/application-dev.yml

@@ -1,65 +0,0 @@
-# 环境配置
-server:
-  port: 9001
-  servlet:
-    context-path: /api
-
-# condition
-spel:
-  scheduling: false        # 定时任务是否执行
-  multiSource: false       # 是否多数据源配置
-
-spring:
-  # database
-  datasource:
-    driver-class-name: com.mysql.cj.jdbc.Driver
-    username: root
-    password: mu123
-    url: jdbc:mysql://127.0.0.1:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
-  jpa:
-    hibernate:
-      ddl-auto: none      # JPA对表没有任何操作
-    show-sql: true
-    database: MYSQL
-    database-platform: org.hibernate.dialect.MySQL57Dialect
-
-# filepath
-file:
-  path:
-    file: /Users/malk/service/_Tool/var/mjava/tmp//file/
-    image: /Users/malk/service/_Tool/var/mjava/tmp//image/
-    tmp: /Users/malk/service/_Tool/var/mjava/tmp/
-  source:
-    fonts: /Users/malk/service/_Tool/fonts/simsun.ttc
-logging:
-  file:
-    path: /Users/malk/service/_Tool/var/mjava/log
-
-## dingtalk
-#dingtalk:
-#  agentId: 2550726809
-#  appKey: dingtift81fcga4rmrmk
-#  appSecret: Oa_S7CYYAfa3CurDbaTk1CBlSvfpcFs6ROjt8OTS8fDsjnS45X1CmxGgWbpJ8lI0
-#  corpId: dingcc1b1ffad0d5ca1d
-#  aesKey:
-#  token:
-#
-## aliwork
-#aliwork:
-#  appType: APP_GHMWTMHNZFEX24QOUC63
-#  systemToken: 4A9667B1NXM9XUSBDNR208ZMA2UQ20A99XEGLIC
-
-
-# dingtalk
-dingtalk:
-  agentId: 2559056539
-  appKey: dingpd6ukkzzcbsczp0n
-  appSecret: 7tTurS8akT9OYegOIe9sBpqdLXOxNCtlNgIwqdolH3VkTxupXzN_fQwASzBQHE6A
-  corpId: ding0f12f2ed788f674ef5bf40eda33b7ba0
-  aesKey:
-  token:
-
-# aliwork
-aliwork:
-  appType: APP_AD5T4ITVLW40MKR7V3LM
-  systemToken: 7N5664D1GX5A9VWICV06RCOARNMW273ZSRTGL7N7

+ 0 - 47
mjava-minjiaoyuan/src/main/resources/application-prod.yml

@@ -1,47 +0,0 @@
-# 环境配置
-server:
-  port: 9007
-
-# condition
-spel:
-  scheduling: true        # 定时任务是否执行
-  multiSource: false      # 是否多数据源配置
-
-spring:
-  # database
-  datasource:
-    driver-class-name: com.mysql.cj.jdbc.Driver
-    username: root
-    password: cp-root@2022++
-    url: jdbc:mysql://47.97.181.40:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
-  jpa:
-    database: MYSQL
-    database-platform: org.hibernate.dialect.MySQL57Dialect
-
-## dingtalk
-#dingtalk:
-#  agentId: 2550726809
-#  appKey: dingtift81fcga4rmrmk
-#  appSecret: Oa_S7CYYAfa3CurDbaTk1CBlSvfpcFs6ROjt8OTS8fDsjnS45X1CmxGgWbpJ8lI0
-#  corpId: dingcc1b1ffad0d5ca1d
-#  aesKey:
-#  token:
-#
-## aliwork
-#aliwork:
-#  appType: APP_GHMWTMHNZFEX24QOUC63
-#  systemToken: 4A9667B1NXM9XUSBDNR208ZMA2UQ20A99XEGLIC
-
-# dingtalk
-dingtalk:
-  agentId: 2559056539
-  appKey: dingpd6ukkzzcbsczp0n
-  appSecret: 7tTurS8akT9OYegOIe9sBpqdLXOxNCtlNgIwqdolH3VkTxupXzN_fQwASzBQHE6A
-  corpId: ding0f12f2ed788f674ef5bf40eda33b7ba0
-  aesKey:
-  token:
-
-# aliwork
-aliwork:
-  appType: APP_AD5T4ITVLW40MKR7V3LM
-  systemToken: 7N5664D1GX5A9VWICV06RCOARNMW273ZSRTGL7N7

+ 0 - 65
mjava-minjiaoyuan/target/classes/application-dev.yml

@@ -1,65 +0,0 @@
-# 环境配置
-server:
-  port: 9001
-  servlet:
-    context-path: /api
-
-# condition
-spel:
-  scheduling: false        # 定时任务是否执行
-  multiSource: false       # 是否多数据源配置
-
-spring:
-  # database
-  datasource:
-    driver-class-name: com.mysql.cj.jdbc.Driver
-    username: root
-    password: mu123
-    url: jdbc:mysql://127.0.0.1:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
-  jpa:
-    hibernate:
-      ddl-auto: none      # JPA对表没有任何操作
-    show-sql: true
-    database: MYSQL
-    database-platform: org.hibernate.dialect.MySQL57Dialect
-
-# filepath
-file:
-  path:
-    file: /Users/malk/service/_Tool/var/mjava/tmp//file/
-    image: /Users/malk/service/_Tool/var/mjava/tmp//image/
-    tmp: /Users/malk/service/_Tool/var/mjava/tmp/
-  source:
-    fonts: /Users/malk/service/_Tool/fonts/simsun.ttc
-logging:
-  file:
-    path: /Users/malk/service/_Tool/var/mjava/log
-
-## dingtalk
-#dingtalk:
-#  agentId: 2550726809
-#  appKey: dingtift81fcga4rmrmk
-#  appSecret: Oa_S7CYYAfa3CurDbaTk1CBlSvfpcFs6ROjt8OTS8fDsjnS45X1CmxGgWbpJ8lI0
-#  corpId: dingcc1b1ffad0d5ca1d
-#  aesKey:
-#  token:
-#
-## aliwork
-#aliwork:
-#  appType: APP_GHMWTMHNZFEX24QOUC63
-#  systemToken: 4A9667B1NXM9XUSBDNR208ZMA2UQ20A99XEGLIC
-
-
-# dingtalk
-dingtalk:
-  agentId: 2559056539
-  appKey: dingpd6ukkzzcbsczp0n
-  appSecret: 7tTurS8akT9OYegOIe9sBpqdLXOxNCtlNgIwqdolH3VkTxupXzN_fQwASzBQHE6A
-  corpId: ding0f12f2ed788f674ef5bf40eda33b7ba0
-  aesKey:
-  token:
-
-# aliwork
-aliwork:
-  appType: APP_AD5T4ITVLW40MKR7V3LM
-  systemToken: 7N5664D1GX5A9VWICV06RCOARNMW273ZSRTGL7N7

+ 0 - 47
mjava-minjiaoyuan/target/classes/application-prod.yml

@@ -1,47 +0,0 @@
-# 环境配置
-server:
-  port: 9007
-
-# condition
-spel:
-  scheduling: true        # 定时任务是否执行
-  multiSource: false      # 是否多数据源配置
-
-spring:
-  # database
-  datasource:
-    driver-class-name: com.mysql.cj.jdbc.Driver
-    username: root
-    password: cp-root@2022++
-    url: jdbc:mysql://47.97.181.40:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
-  jpa:
-    database: MYSQL
-    database-platform: org.hibernate.dialect.MySQL57Dialect
-
-## dingtalk
-#dingtalk:
-#  agentId: 2550726809
-#  appKey: dingtift81fcga4rmrmk
-#  appSecret: Oa_S7CYYAfa3CurDbaTk1CBlSvfpcFs6ROjt8OTS8fDsjnS45X1CmxGgWbpJ8lI0
-#  corpId: dingcc1b1ffad0d5ca1d
-#  aesKey:
-#  token:
-#
-## aliwork
-#aliwork:
-#  appType: APP_GHMWTMHNZFEX24QOUC63
-#  systemToken: 4A9667B1NXM9XUSBDNR208ZMA2UQ20A99XEGLIC
-
-# dingtalk
-dingtalk:
-  agentId: 2559056539
-  appKey: dingpd6ukkzzcbsczp0n
-  appSecret: 7tTurS8akT9OYegOIe9sBpqdLXOxNCtlNgIwqdolH3VkTxupXzN_fQwASzBQHE6A
-  corpId: ding0f12f2ed788f674ef5bf40eda33b7ba0
-  aesKey:
-  token:
-
-# aliwork
-aliwork:
-  appType: APP_AD5T4ITVLW40MKR7V3LM
-  systemToken: 7N5664D1GX5A9VWICV06RCOARNMW273ZSRTGL7N7

+ 11 - 2
mjava-rongzhi/src/main/java/com/malk/rongzhi/controller/RongZhiController.java

@@ -1,5 +1,6 @@
 package com.malk.rongzhi.controller;
 
+import com.malk.Util.UtilDateTime;
 import com.malk.rongzhi.server.RZConf;
 import com.malk.rongzhi.service.RZService;
 import com.malk.server.common.McR;
@@ -10,6 +11,7 @@ import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.time.LocalDateTime;
 import java.util.Map;
 
 /**
@@ -17,7 +19,7 @@ import java.util.Map;
  */
 @Slf4j
 @RestController
-@RequestMapping("/shijianguan")
+@RequestMapping("/rongzhi")
 public class RongZhiController {
 
     @Autowired
@@ -31,7 +33,7 @@ public class RongZhiController {
         rzService.uploadTravelData();
         return McR.success();
     }
-    
+
     /**
      * 推送易快报
      */
@@ -39,4 +41,11 @@ public class RongZhiController {
     McR formPush(@RequestBody Map<String, String> param) {
         return McR.success(rzService.getAccessToken(RZConf.TYPE.ekuaibao));
     }
+
+    @PostMapping("/test")
+    McR test() {
+        LocalDateTime finish = UtilDateTime.getLocalDateTimeFromTimestamp(1685461901000L + 1 * 60 * 60 * 1000L);
+        log.info("xxx, {}", finish);
+        return McR.success(finish.getHour());
+    }
 }

+ 1 - 1
mjava-rongzhi/src/main/java/com/malk/rongzhi/schedule/RZScheduleTask.java

@@ -9,7 +9,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
 import org.springframework.scheduling.annotation.Scheduled;
 
 /**
- * @EnableScheduling 开启桑诺定时任务 [配置参考McScheduleTask]
+ * @EnableScheduling 开启定时任务 [配置参考McScheduleTask]
  */
 @Slf4j
 @Configuration

+ 14 - 4
mjava-rongzhi/src/main/java/com/malk/rongzhi/service/impl/RZServiceImpl.java

@@ -63,12 +63,18 @@ public class RZServiceImpl implements RZService {
         for (int i = 0; i < userIds.size(); i += 50) {
             int to = (i + 50) > userIds.size() ? userIds.size() : i + 50;
             // 考勤范围从当日 7.30 到次日 7.30
-            String from = UtilDateTime.formatDate(new Date()) + " 07:30:00";
-            String end = UtilDateTime.formatDate(new Date(System.currentTimeMillis() + 24 * 60 * 60 * 1000)) + " 07:30:00";
+            Date now = new Date();
+            String from = UtilDateTime.formatDate(now) + " 07:30:00";
+            String end = UtilDateTime.formatDate(now) + " 23:59:59";
+            // fixme: [凌晨以后同步新的考勤时段]
+            if (LocalDateTime.now().getHour() <= 7) {
+                from = UtilDateTime.formatDate(now) + " 00:00:00";
+                end = UtilDateTime.formatDate(now) + " 07:30:00";
+            }
 //            String from = "2023-04-18 07:30:00";
 //            String end = "2023-04-19 07:30:00";
             List<String> users = userIds.subList(i, to);
-            List<Map> list = ddClient_attendance.listAttendanceRecord(getAccessToken(RZConf.TYPE.dingtalk), users, from, end, false);
+            List<Map> list = ddClient_attendance.listAttendanceRecord(getAccessToken(RZConf.TYPE.dingtalk), users, from, end);
             // 匹配数据考勤
             users.forEach(user -> {
                 List<Map> records = list.stream().filter(item -> user.equals(item.get("userId"))).collect(Collectors.toList());
@@ -81,10 +87,14 @@ public class RZServiceImpl implements RZService {
                     LocalDateTime finish = UtilDateTime.getLocalDateTimeFromTimestamp(checkOut);
                     // 下班超过22点, 且当天考勤超过11小时
                     float hour = UtilDateTime.betweenHour(begin, finish);
-                    if (hour > 11.0f && finish.getHour() > 22) {
+                    if (hour > 11.0f && finish.getHour() >= 22) {
                         String checkDate = UtilDateTime.formatLocalDate(begin.toLocalDate());
                         if (!rzEkbRecordDao.existsByUserIdAndCheckDate(userId, checkDate)) {
                             log.info("匹配符合数据, {}, {}, {}", userId, UtilDateTime.formatLocalDateTime(begin), UtilDateTime.formatLocalDateTime(finish));
+                            // 易快报同步默认是打卡结束时间, 若是23点以后下班, 第二天可打车, 结束传递+1天
+                            if (finish.getHour() == 23) {
+                                checkOut += 24 * 60 * 60 * 1000L;
+                            }
                             pushTemplateByRecord(userId, checkIn, checkOut, checkDate);
                         } else {
                             log.info("数据已经推送, {}, {}, {}", userId, UtilDateTime.formatLocalDateTime(begin), UtilDateTime.formatLocalDateTime(finish));

+ 6 - 6
mjava-rongzhi/src/main/resources/application-dev.yml

@@ -6,7 +6,7 @@ server:
 
 # condition
 spel:
-  scheduling: true        # 定时任务是否执行
+  scheduling: false        # 定时任务是否执行
   multiSource: false       # 是否多数据源配置
 
 spring:
@@ -26,14 +26,14 @@ spring:
 # filepath
 file:
   path:
-    file: /Users/malk/service/_Tool/var/mjava/tmp//file/
-    image: /Users/malk/service/_Tool/var/mjava/tmp//image/
-    tmp: /Users/malk/service/_Tool/var/mjava/tmp/
+    file: /Users/malk/server/_Tool/var/mjava/tmp//file/
+    image: /Users/malk/server/_Tool/var/mjava/tmp//image/
+    tmp: /Users/malk/server/_Tool/var/mjava/tmp/
   source:
-    fonts: /Users/malk/service/_Tool/fonts/simsun.ttc
+    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
 logging:
   file:
-    path: /Users/malk/service/_Tool/var/mjava/log
+    path: /Users/malk/server/_Tool/var/mjava/log
 
 # ekuaibao - 榕智
 ekuaibao:

+ 1 - 1
mjava-rongzhi/src/main/resources/application-prod.yml

@@ -4,7 +4,7 @@ server:
 
 # condition
 spel:
-  scheduling: false       # 定时任务是否执行
+  scheduling: true        # 定时任务是否执行
   multiSource: false      # 是否多数据源配置
 
 spring:

+ 6 - 6
mjava-rongzhi/target/classes/application-dev.yml

@@ -6,7 +6,7 @@ server:
 
 # condition
 spel:
-  scheduling: true        # 定时任务是否执行
+  scheduling: false        # 定时任务是否执行
   multiSource: false       # 是否多数据源配置
 
 spring:
@@ -26,14 +26,14 @@ spring:
 # filepath
 file:
   path:
-    file: /Users/malk/service/_Tool/var/mjava/tmp//file/
-    image: /Users/malk/service/_Tool/var/mjava/tmp//image/
-    tmp: /Users/malk/service/_Tool/var/mjava/tmp/
+    file: /Users/malk/server/_Tool/var/mjava/tmp//file/
+    image: /Users/malk/server/_Tool/var/mjava/tmp//image/
+    tmp: /Users/malk/server/_Tool/var/mjava/tmp/
   source:
-    fonts: /Users/malk/service/_Tool/fonts/simsun.ttc
+    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
 logging:
   file:
-    path: /Users/malk/service/_Tool/var/mjava/log
+    path: /Users/malk/server/_Tool/var/mjava/log
 
 # ekuaibao - 榕智
 ekuaibao:

+ 1 - 1
mjava-rongzhi/target/classes/application-prod.yml

@@ -4,7 +4,7 @@ server:
 
 # condition
 spel:
-  scheduling: false       # 定时任务是否执行
+  scheduling: true        # 定时任务是否执行
   multiSource: false      # 是否多数据源配置
 
 spring:

+ 2 - 2
mjava-minjiaoyuan/pom.xml

@@ -9,8 +9,8 @@
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
-    <artifactId>mjava-minjiaoyuan</artifactId>
-    <description>闵教院宜搭对接服务</description>
+    <artifactId>mjava-shanghaishiwei</artifactId>
+    <description>上海市委氚云审批, 对接合同管理系统</description>
 
     <properties>
         <maven.compiler.source>8</maven.compiler.source>

+ 32 - 0
mjava-shanghaishiwei/src/main/java/com/malk/shanghaishiwei/Boot.java

@@ -0,0 +1,32 @@
+package com.malk.shanghaishiwei;
+
+import com.querydsl.jpa.impl.JPAQueryFactory;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
+
+import javax.persistence.EntityManager;
+
+/**
+ * corp项目: 扫描公共模块
+ * -
+ * 若是无需数据库模块, 配置无效地址也可启动, 引入mjava不支持直接 @SpringBootApplication(exclude = DataSourceAutoConfiguration.class) 配置
+ * 需要配置 jpa.hibernate.ddl-auto 为 none. 标识对表没有任何操作. 若不设置为 non, flyway.enabled 配置会无效, 在没有数库连接情况下程序无法启动
+ */
+@EnableJpaAuditing
+@SpringBootApplication(scanBasePackages = {"com.malk"})
+public class Boot {
+
+    public static void main(String... args) {
+        SpringApplication.run(Boot.class, args);
+    }
+
+    /**
+     * 让Spring管理JPAQueryFactory [不使用Qualifier详见mjava-Boot]
+     */
+    @Bean
+    public JPAQueryFactory jpaQueryFactory(EntityManager entityManager) {
+        return new JPAQueryFactory(entityManager);
+    }
+}

+ 142 - 0
mjava-shanghaishiwei/src/main/java/com/malk/shanghaishiwei/controller/SHHWController.java

@@ -0,0 +1,142 @@
+package com.malk.shanghaishiwei.controller;
+
+import com.alibaba.fastjson.JSON;
+import com.malk.Util.UtilFile;
+import com.malk.Util.UtilHttp;
+import com.malk.Util.UtilMap;
+import com.malk.Util.UtilServlet;
+import com.malk.server.common.FilePath;
+import com.malk.server.common.McException;
+import com.malk.server.common.McR;
+import com.malk.shanghaishiwei.service.HTClient;
+import com.malk.shanghaishiwei.service.HTService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.File;
+import java.util.Map;
+
+/**
+ * 错误抛出与拦截详见CatchException
+ */
+@Slf4j
+@RestController
+@RequestMapping("/shanghaishiwei")
+public class SHHWController {
+
+    @Autowired
+    private HTClient htClient;
+
+    @Autowired
+    private HTService htService;
+
+    @PostMapping("h3yun-http")
+    McR http(@RequestBody Map<String, String> data, @RequestParam("code") String code) {
+
+        log.info("氚云http请求, code = {}, body = {}", code, JSON.toJSONString(data));
+        switch (code) {
+            case "approve":
+                String fileNames = htService.approveContract(data);
+                return McR.success(UtilMap.map("fileNames", fileNames));
+            // 对象响应【氚云自定义字段,需要通过[]直接取值才有效,序列化后返回前端,仅会保留结构】
+            case "types":
+                return McR.success(UtilMap.map("types", JSON.toJSONString(htClient.listContractType())));
+
+            case "delete":
+                htService.deleteContract(data);
+                break;
+            default:
+                McException.exceptionAccess("code 不合法");
+                break;
+        }
+
+
+        return McR.success();
+    }
+
+
+    ////// test //////
+
+    /**
+     * 采购合同类型
+     */
+    @PostMapping("listContractType")
+    McR listContractType() {
+        return McR.success(htClient.listContractType());
+    }
+
+    /**
+     * 添加采购合同
+     */
+    @PostMapping("addPurchaseContact")
+    McR test(@RequestBody Map data) {
+        McException.assertParamException_Null(UtilServlet.isNull(data, "origionContractCode"));
+        return McR.success(htClient.addPurchaseContact(data));
+    }
+
+    /**
+     * 删除采购合同
+     */
+
+    @PostMapping("deletePurchaseContract")
+    McR test2(@RequestBody Map<String, String> data) {
+        McException.assertParamException_Null(UtilServlet.isNull(data, "origionContractCode"));
+        return McR.success(htClient.deletePurchaseContract(data.get("origionContractCode")));
+    }
+
+    /**
+     * 添加采购合同条款
+     */
+    @PostMapping("addTermsContract")
+    McR addTermsContract(@RequestBody Map data) {
+        McException.assertParamException_Null(UtilServlet.isNull(data, "origionContractCode"));
+        return McR.success(htClient.addTermsContract(data));
+    }
+
+    /**
+     * 删除采购合同条款
+     */
+    @PostMapping("deleteTermsContract")
+    McR deleteTermsContract(@RequestBody Map<String, String> data) {
+        McException.assertParamException_Null(UtilServlet.isNull(data, "origionContractCode", "datetime", "agreementType"));
+        return McR.success(htClient.deleteTermsContract(data.get("origionContractCode"), data.get("datetime"), UtilMap.getInt(data, "agreementType")));
+    }
+
+    @Autowired
+    private FilePath filePath;
+
+    /**
+     * 添加采购合同附件
+     */
+    @PostMapping("addAttachmentContract")
+    McR addAttachmentContract(@RequestBody Map data) {
+        McException.assertParamException_Null(UtilServlet.isNull(data, "origionContractCode, attachmentUrl"));
+        // 拼接与氚云记录 [删除]
+        String urlFile = data.get("attachmentUrl").toString();
+//        String fileType = urlFile.substring(urlFile.lastIndexOf(".")).toLowerCase();
+//        String fileName = data.get("origionContractCode") + fileType;
+
+        String fileType = "xlsx";
+        String fileName = "cc.xlsx";
+        File file = UtilFile.mkdirIfNot(fileName, filePath.getPath().getFile());
+        UtilHttp.doDownload(urlFile, file);
+        data.put("fileType", fileType);
+        data.put("fileName", fileName);
+        data.put("contractType", 1); // 采购合同
+//        data.put("Scanning", UtilFile.fileConvertToByteArray(new File("/Users/malk/Desktop/api.pdf")));
+        data.put("Scanning", UtilFile.fileConvertToByteArray(file));
+        return McR.success(htClient.addAttachmentContract(data));
+    }
+
+    /**
+     * 删除采购合同附件
+     */
+    @PostMapping("deleteAttachmentContract")
+    McR deleteAttachmentContract(@RequestBody Map<String, String> data) {
+        McException.assertParamException_Null(UtilServlet.isNull(data, "origionContractCode"));
+        String fileType = "pdf";
+        String fileName = "origionContractCode.pdf";
+        return McR.success(htClient.deleteAttachmentContract(data.get("origionContractCode"), fileType, fileName));
+    }
+}

+ 26 - 0
mjava-shanghaishiwei/src/main/java/com/malk/shanghaishiwei/server/HTConf.java

@@ -0,0 +1,26 @@
+package com.malk.shanghaishiwei.server;
+
+import com.malk.Util.UtilMap;
+import org.apache.commons.codec.digest.DigestUtils;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Map;
+
+public class HTConf {
+
+    public static final String SYSTEM_ID = "6CBAC3D3-F055-6150-E3C9-142FB65524B5";
+    public static final String SECRET = "c2Vhc2t5Y29udHJhY3RhcGk=";
+    public final static String PATTERN = "yyyy-MM-dd-HH";
+
+    // 条款性质
+    public static final int getAgreementType(Map term) {
+        Map types = UtilMap.map("对方押金质保金, 暂缓支付质保金, 普通支付条款", 1, 2, 3);
+        return UtilMap.getInt(types, UtilMap.getString(term, "agreementType"));
+    }
+
+    public static final String getToken() {
+        String fDate = new SimpleDateFormat(PATTERN).format(new Date());
+        return DigestUtils.md5Hex(SYSTEM_ID + "|" + fDate + "|" + SECRET);
+    }
+}

+ 49 - 0
mjava-shanghaishiwei/src/main/java/com/malk/shanghaishiwei/server/HTR.java

@@ -0,0 +1,49 @@
+package com.malk.shanghaishiwei.server;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.malk.Util.UtilHttp;
+import com.malk.server.common.McException;
+import com.malk.server.common.VenR;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Map;
+
+/**
+ * 返回值配置参考McR
+ */
+@Data
+@NoArgsConstructor
+public class HTR extends VenR {
+
+    private boolean isSuccess;
+
+    private String errorCode;
+
+    private String errorMessage;
+
+    private String data;
+
+    /**
+     * 断言错误信息
+     */
+    @Override
+    public void assertSuccess() {
+        McException.assertException(ObjectUtil.isNotNull(errorCode) || !isSuccess, errorCode, errorMessage, "SHHT");
+    }
+
+    /**
+     * 通用post请求
+     */
+    public static HTR doPost(String url, Map header, Map param, Map body) {
+        return (HTR) UtilHttp.doPost(url, header, param, body, HTR.class);
+    }
+
+    /**
+     * 通用get请求
+     */
+    public static HTR doGet(String url, Map header, Map param) {
+        return (HTR) UtilHttp.doGet(url, header, param, HTR.class);
+    }
+}
+

+ 44 - 0
mjava-shanghaishiwei/src/main/java/com/malk/shanghaishiwei/service/HTClient.java

@@ -0,0 +1,44 @@
+package com.malk.shanghaishiwei.service;
+
+import java.util.List;
+import java.util.Map;
+
+public interface HTClient {
+
+    /**
+     * 获取采购合同类型列表
+     */
+    List<Map> listContractType();
+
+    /**
+     * 添加采购合同
+     */
+    boolean addPurchaseContact(Map body);
+
+    /**
+     * 删除采购合同合同信息
+     */
+    boolean deletePurchaseContract(String origionContractcode);
+
+    /**
+     * 添加采购合同条款信息
+     */
+    boolean addTermsContract(Map body);
+
+    /**
+     * 删除采购合同条款信息
+     *
+     * @param agreementType 对方押金质保金 = 1, 暂缓支付质保金 = 2, 普通条款 = 3
+     */
+    boolean deleteTermsContract(String origionContractCode, String datetime, int agreementType);
+
+    /**
+     * 添加采购合同附件信息
+     */
+    boolean addAttachmentContract(Map body);
+
+    /**
+     * 删除采购合同附件 [合同类型 1采购合同,2销售合同] - 默认采购合同
+     */
+    boolean deleteAttachmentContract(String origionContractCode, String fileType, String fileName);
+}

+ 18 - 0
mjava-shanghaishiwei/src/main/java/com/malk/shanghaishiwei/service/HTService.java

@@ -0,0 +1,18 @@
+package com.malk.shanghaishiwei.service;
+
+import java.util.Map;
+
+public interface HTService {
+
+    /**
+     * 审批通过 [新增合同, 多个条款, 多个附件]
+     *
+     * @return 返回拼接附件: 名称.类型, 用于操删除逻辑
+     */
+    String approveContract(Map<String, String> data);
+
+    /**
+     * 批量删除 [删除附件, 全部条款, 合同主体]
+     */
+    void deleteContract(Map<String, String> data);
+}

+ 87 - 0
mjava-shanghaishiwei/src/main/java/com/malk/shanghaishiwei/service/impl/HTImplClient.java

@@ -0,0 +1,87 @@
+package com.malk.shanghaishiwei.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.malk.Util.UtilMap;
+import com.malk.shanghaishiwei.server.HTConf;
+import com.malk.shanghaishiwei.server.HTR;
+import com.malk.shanghaishiwei.service.HTClient;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 上海市委_合同接口 [参数大写不敏感]
+ */
+@Service
+@Slf4j
+public class HTImplClient implements HTClient {
+
+    /**
+     * 获取采购合同类型列表
+     */
+    @Override
+    public List<Map> listContractType() {
+        Map body = UtilMap.map("SystemId, token", HTConf.SYSTEM_ID, HTConf.getToken());
+        HTR htr = HTR.doPost("http://cw-shmecsfa.shec.edu.cn/CZZX/SFP_ContractApi/Contract/ListContractType", null, null, body);
+        return (List<Map>) JSON.parse(htr.getData());
+    }
+
+    /**
+     * 添加采购合同
+     */
+    @Override
+    public boolean addPurchaseContact(Map body) {
+        body.put("SystemId", HTConf.SYSTEM_ID);
+        body.put("token", HTConf.getToken());
+        return HTR.doPost("http://cw-shmecsfa.shec.edu.cn/CZZX/SFP_ContractApi/Contract/AddVenContract", null, null, body).isSuccess();
+    }
+
+    /**
+     * 删除采购合同合同信息
+     */
+    @Override
+    public boolean deletePurchaseContract(String origionContractcode) {
+        Map body = UtilMap.map("SystemId, token, OrigionContractcode", HTConf.SYSTEM_ID, HTConf.getToken(), origionContractcode);
+        return HTR.doPost("http://cw-shmecsfa.shec.edu.cn/CZZX/SFP_ContractApi/Contract/DelVenContract", null, null, body).isSuccess();
+    }
+
+    /**
+     * 添加采购合同条款信息
+     */
+    @Override
+    public boolean addTermsContract(Map body) {
+        body.put("SystemId", HTConf.SYSTEM_ID);
+        body.put("token", HTConf.getToken());
+        return HTR.doPost("http://cw-shmecsfa.shec.edu.cn/CZZX/SFP_ContractApi/Contract/AddVenAgreement", null, null, body).isSuccess();
+    }
+
+    /**
+     * 删除采购合同条款信息
+     */
+    @Override
+    public boolean deleteTermsContract(String origionContractCode, String datetime, int agreementType) {
+        Map body = UtilMap.map("SystemId, token, origionContractCode, datetime, agreementType", HTConf.SYSTEM_ID, HTConf.getToken(), origionContractCode, datetime, agreementType);
+        return HTR.doPost("http://cw-shmecsfa.shec.edu.cn/CZZX/SFP_ContractApi/Contract/DelVenAgreement", null, null, body).isSuccess();
+    }
+
+    /**
+     * 添加采购合同附件信息
+     */
+    @Override
+    public boolean addAttachmentContract(Map body) {
+        body.put("SystemId", HTConf.SYSTEM_ID);
+        body.put("token", HTConf.getToken());
+        return HTR.doPost("http://cw-shmecsfa.shec.edu.cn/CZZX/SFP_ContractApi/Contract/AddScanning", null, null, body).isSuccess();
+    }
+
+    /**
+     * 删除采购合同附件
+     */
+    @Override
+    public boolean deleteAttachmentContract(String origionContractCode, String fileType, String fileName) {
+        Map body = UtilMap.map("SystemId, token, OrigionContractcode, fileType, fileName, contractType", HTConf.SYSTEM_ID, HTConf.getToken(), origionContractCode, fileType, fileName, 1);
+        return HTR.doPost("http://cw-shmecsfa.shec.edu.cn/CZZX/SFP_ContractApi/Contract/DelScanning", null, null, body).isSuccess();
+    }
+}

+ 107 - 0
mjava-shanghaishiwei/src/main/java/com/malk/shanghaishiwei/service/impl/HTImplService.java

@@ -0,0 +1,107 @@
+package com.malk.shanghaishiwei.service.impl;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.fastjson.JSON;
+import com.malk.Util.UtilFile;
+import com.malk.Util.UtilMap;
+import com.malk.Util.UtilString;
+import com.malk.service.dingtalk.DDClient;
+import com.malk.service.h3yun.CYClient;
+import com.malk.shanghaishiwei.server.HTConf;
+import com.malk.shanghaishiwei.service.HTClient;
+import com.malk.shanghaishiwei.service.HTService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+@Service
+@Slf4j
+public class HTImplService implements HTService {
+
+    @Autowired
+    private HTClient htClient;
+
+    @Autowired
+    private CYClient cyClient;
+
+    @Autowired
+    private DDClient ddClient;
+
+    /**
+     * 审批通过
+     */
+    @Override
+    public String approveContract(Map<String, String> data) {
+
+        Map bizObject = ((List<Map>) JSON.parse(data.get("bizObject"))).get(0);
+
+        // prd: 非政采合同, 使用流水号
+        String origionContractCode = UtilMap.getString(bizObject, "origionContractCode", UtilMap.getString(bizObject, "SeqNo"));
+        bizObject.put("origionContractCode", origionContractCode);
+        htClient.addPurchaseContact(bizObject); // 新增合同
+        // 同步条款
+        List<Map> termsObject = (List<Map>) JSON.parse(data.get("termsObject"));
+        for (Map term : termsObject) {
+            term.put("origionContractCode", origionContractCode);
+            term.put("agreementType", HTConf.getAgreementType(term));
+            htClient.addTermsContract(term);
+        }
+        // 同步附件
+        List<Map> attachments = (List<Map>) JSON.parse(data.get("attachments"));
+        if (ObjectUtil.isNull(attachments)) {
+            return "";
+        }
+        List<String> fileNames = new ArrayList<>();
+        for (Map attachment : attachments) {
+            File file = cyClient.saveFromTemporaryUrl(ddClient.getAccessToken(), attachment);
+            String fileName = UtilMap.getString(attachment, "FileName");
+            String fileType = fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
+            fileName = origionContractCode + "_" + fileName;
+            Map body = UtilMap.map("origionContractCode, fileType, fileName", origionContractCode, fileType, fileName);
+            body.put("contractType", 1); // 采购合同
+            body.put("Scanning", UtilFile.fileConvertToByteArray(file));
+            htClient.addAttachmentContract(body);
+            fileNames.add(fileName); // 拼接与氚云记录, 服务删除逻辑
+        }
+        return String.join("; ", fileNames);
+    }
+
+    /**
+     * 批量删除
+     */
+    @Override
+    public void deleteContract(Map<String, String> data) {
+
+        List<Map> bizObjects = ((List<Map>) JSON.parse(data.get("bizObjects")));
+        for (Map bizObject : bizObjects) {
+
+            // 审批通过生效数据
+            if (UtilMap.getInt(bizObject, "Status") != 1) {
+                log.info("未审批通过数据, {}", bizObject);
+                continue;
+            }
+            // prd: 非政采合同, 使用流水号
+            String origionContractCode = UtilMap.getString(bizObject, "origionContractCode", UtilMap.getString(bizObject, "SeqNo"));
+            // 删除附件
+            if (UtilString.isNotBlankCompatNull(UtilMap.getString(bizObject, "fileNames"))) {
+                String[] fileNames = UtilMap.getString(bizObject, "fileNames").split("; ");
+                for (String fileName : fileNames) {
+                    String fileType = fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
+                    htClient.deleteAttachmentContract(origionContractCode, fileType, fileName);
+                }
+            }
+            // 删除条款
+            List<Map> termsObject = (List<Map>) JSON.parse(data.get("termsObject"));
+            for (Map term : termsObject) {
+                htClient.deleteTermsContract(origionContractCode, UtilMap.getString(term, "dateTime"), HTConf.getAgreementType(term));
+            }
+            // 删除合同
+            htClient.deletePurchaseContract(origionContractCode);
+        }
+    }
+}

+ 45 - 0
mjava-shanghaishiwei/src/main/resources/application-dev.yml

@@ -0,0 +1,45 @@
+# 环境配置
+server:
+  port: 9001
+  servlet:
+    context-path: /api
+
+# condition
+spel:
+  scheduling: false        # 定时任务是否执行
+  multiSource: false       # 是否多数据源配置
+
+spring:
+  # database
+  datasource:
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    username: root
+    password: mu123
+    url: jdbc:mysql://127.0.0.1:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+  jpa:
+    hibernate:
+      ddl-auto: none      # JPA对表没有任何操作
+    show-sql: true
+    database: MYSQL
+    database-platform: org.hibernate.dialect.MySQL57Dialect
+
+# filepath
+file:
+  path:
+    file: /Users/malk/server/_Tool/var/mjava/tmp//file/
+    image: /Users/malk/server/_Tool/var/mjava/tmp//image/
+    tmp: /Users/malk/server/_Tool/var/mjava/tmp/
+  source:
+    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
+logging:
+  file:
+    path: /Users/malk/server/_Tool/var/mjava/log
+
+# dingtalk
+dingtalk:
+  agentId: 2610297348
+  appKey: dingwbo8kupwkbg9ahaf
+  appSecret: _uLjrlVW0HUK2PMGvsTcr-Ffs6rDSw2SCMaSgUmr6EpJvag9AxJwJzr9NOGr_Ral
+  corpId: ding7c84ac0578e7257235c2f4657eb6378f
+  aesKey:
+  token:

+ 28 - 0
mjava-shanghaishiwei/src/main/resources/application-prod.yml

@@ -0,0 +1,28 @@
+# 环境配置
+server:
+  port: 9008
+
+# condition
+spel:
+  scheduling: true        # 定时任务是否执行
+  multiSource: false      # 是否多数据源配置
+
+spring:
+  # database
+  datasource:
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    username: root
+    password: cp-root@2022++
+    url: jdbc:mysql://47.97.181.40:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+  jpa:
+    database: MYSQL
+    database-platformw: org.hibernate.dialect.MySQL57Dialect
+
+# dingtalk
+dingtalk:
+  agentId: 2610297348
+  appKey: dingwbo8kupwkbg9ahaf
+  appSecret: _uLjrlVW0HUK2PMGvsTcr-Ffs6rDSw2SCMaSgUmr6EpJvag9AxJwJzr9NOGr_Ral
+  corpId: ding7c84ac0578e7257235c2f4657eb6378f
+  aesKey:
+  token:

+ 35 - 0
mjava-shanghaishiwei/src/test/resources/server.sh

@@ -0,0 +1,35 @@
+#!/bin/bash
+appname='mjava-shanghaishiwei'
+if [ "$1" == "dev" ]; then
+  java -Xms256m -Xmx256m -jar $appname.jar --spring.profiles.active=dev
+else
+  if [ "$1" == "start" ]; then
+    nohup java -Xms256m -Xmx256m -jar $appname.jar &
+    echo "server prod is starting"
+  else
+    if [ "$1" == "test" ]; then
+      nohup java -Xms256m -Xmx256m -jar $appname.jar --spring.profiles.active=test &
+      echo "server test is starting"
+    else
+      if [ "$1" == "stop" ]; then
+        PID=$(ps -ef | grep $appname.jar | grep -v grep | awk '{ print $2 }')
+        if [ -z "$PID" ]; then
+          echo "server is already stopped"
+        else
+          echo kill $PID
+          kill $PID
+        fi
+      else
+        if [ "$1" == "status" ]; then
+          PID=$(ps -ef | grep $appname.jar | grep -v grep | awk '{ print $2 }')
+          if [ -z "$PID" ]; then
+            echo "server is stopped"
+          else
+            echo "server is running"
+            echo $PID
+          fi
+        fi
+      fi
+    fi
+  fi
+fi

+ 45 - 0
mjava-shanghaishiwei/target/classes/application-dev.yml

@@ -0,0 +1,45 @@
+# 环境配置
+server:
+  port: 9001
+  servlet:
+    context-path: /api
+
+# condition
+spel:
+  scheduling: false        # 定时任务是否执行
+  multiSource: false       # 是否多数据源配置
+
+spring:
+  # database
+  datasource:
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    username: root
+    password: mu123
+    url: jdbc:mysql://127.0.0.1:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+  jpa:
+    hibernate:
+      ddl-auto: none      # JPA对表没有任何操作
+    show-sql: true
+    database: MYSQL
+    database-platform: org.hibernate.dialect.MySQL57Dialect
+
+# filepath
+file:
+  path:
+    file: /Users/malk/server/_Tool/var/mjava/tmp//file/
+    image: /Users/malk/server/_Tool/var/mjava/tmp//image/
+    tmp: /Users/malk/server/_Tool/var/mjava/tmp/
+  source:
+    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
+logging:
+  file:
+    path: /Users/malk/server/_Tool/var/mjava/log
+
+# dingtalk
+dingtalk:
+  agentId: 2610297348
+  appKey: dingwbo8kupwkbg9ahaf
+  appSecret: _uLjrlVW0HUK2PMGvsTcr-Ffs6rDSw2SCMaSgUmr6EpJvag9AxJwJzr9NOGr_Ral
+  corpId: ding7c84ac0578e7257235c2f4657eb6378f
+  aesKey:
+  token:

+ 28 - 0
mjava-shanghaishiwei/target/classes/application-prod.yml

@@ -0,0 +1,28 @@
+# 环境配置
+server:
+  port: 9008
+
+# condition
+spel:
+  scheduling: true        # 定时任务是否执行
+  multiSource: false      # 是否多数据源配置
+
+spring:
+  # database
+  datasource:
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    username: root
+    password: cp-root@2022++
+    url: jdbc:mysql://47.97.181.40:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+  jpa:
+    database: MYSQL
+    database-platformw: org.hibernate.dialect.MySQL57Dialect
+
+# dingtalk
+dingtalk:
+  agentId: 2610297348
+  appKey: dingwbo8kupwkbg9ahaf
+  appSecret: _uLjrlVW0HUK2PMGvsTcr-Ffs6rDSw2SCMaSgUmr6EpJvag9AxJwJzr9NOGr_Ral
+  corpId: ding7c84ac0578e7257235c2f4657eb6378f
+  aesKey:
+  token:

+ 35 - 0
mjava-shanghaishiwei/target/test-classes/server.sh

@@ -0,0 +1,35 @@
+#!/bin/bash
+appname='mjava-shanghaishiwei'
+if [ "$1" == "dev" ]; then
+  java -Xms256m -Xmx256m -jar $appname.jar --spring.profiles.active=dev
+else
+  if [ "$1" == "start" ]; then
+    nohup java -Xms256m -Xmx256m -jar $appname.jar &
+    echo "server prod is starting"
+  else
+    if [ "$1" == "test" ]; then
+      nohup java -Xms256m -Xmx256m -jar $appname.jar --spring.profiles.active=test &
+      echo "server test is starting"
+    else
+      if [ "$1" == "stop" ]; then
+        PID=$(ps -ef | grep $appname.jar | grep -v grep | awk '{ print $2 }')
+        if [ -z "$PID" ]; then
+          echo "server is already stopped"
+        else
+          echo kill $PID
+          kill $PID
+        fi
+      else
+        if [ "$1" == "status" ]; then
+          PID=$(ps -ef | grep $appname.jar | grep -v grep | awk '{ print $2 }')
+          if [ -z "$PID" ]; then
+            echo "server is stopped"
+          else
+            echo "server is running"
+            echo $PID
+          fi
+        fi
+      fi
+    fi
+  fi
+fi

+ 70 - 5
mjava-xiding/src/main/java/com/malk/xiding/controller/XDController.java

@@ -1,16 +1,28 @@
 package com.malk.xiding.controller;
 
+import com.alibaba.fastjson.JSON;
 import com.malk.Util.UtilDateTime;
 import com.malk.server.common.McR;
+import com.malk.server.fxiaoke.FXKConf;
+import com.malk.service.dingtalk.DDClient;
+import com.malk.service.dingtalk.DDClient_Attendance;
+import com.malk.service.fxiaoke.FXKClient;
+import com.malk.xiding.repository.dao.XdDdApproveRecordDao2;
+import com.malk.xiding.repository.dao.XdDdFxkRelationDao;
+import com.malk.xiding.repository.entity.XdFxkDdAttendancePo;
 import com.malk.xiding.server.XDConf;
 import com.malk.xiding.service.XDService;
 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.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.Arrays;
 import java.util.Date;
+import java.util.List;
+import java.util.Map;
 
 /**
  * 错误抛出与拦截详见CatchException
@@ -23,19 +35,72 @@ public class XDController {
     @Autowired
     private XDService xdService;
 
+    @Autowired
+    private DDClient_Attendance ddClient_attendance;
+
+    @Autowired
+    private DDClient ddClient;
+
+    @Autowired
+    private XdDdApproveRecordDao2 approveRecordDao2;
+
+    @Autowired
+    private FXKClient fxkClient;
+
+    @Autowired
+    private FXKConf fxkConf;
+
+    @Autowired
+    private XdDdFxkRelationDao relationDao;
+
+
+    @PostMapping("test3")
+    McR test3(@RequestParam String name) {
+        Date sTime = UtilDateTime.parseDateTime("2023-05-04" + " 00:00:00");
+        Date eTime = UtilDateTime.parseDateTime("2023-05-31" + " 23:59:59");
+
+        List<Map> records = fxkClient.getAttendance_All(fxkClient.getAccessToken(), fxkConf.getCorpId(), sTime.getTime(), eTime.getTime(), Arrays.asList(relationDao.findByName(name).getIdFxxk()));
+//        log.info("xxxx, {}", records.size());
+//
+//        Date tTime = UtilDateTime.parseDateTime("2023-05-04" + " 04:11:00");
+//
+//        // 时区测试 @Temporal & @JsonFormat
+//        Date check = UtilDateTime.parseDateTime(UtilDateTime.formatDate(new Date(tTime.getTime() - (tTime.getHours() + 1) * 60 * 60 * 1000)) + " 18:00:00");
+//        log.error("xxxx, {}", JSON.parseObject(JSON.toJSONString(records.get(0)), XdFxkDdAttendancePo.class));
+//
+//        log.info("xxxx, {}, {}", check, UtilDateTime.formatDateTime(new Date(tTime.getTime() - (tTime.getHours() + 1) * 60 * 60 * 1000)));
+        return McR.success(JSON.parseArray(JSON.toJSONString(records), XdFxkDdAttendancePo.class));
+//        return McR.success(JSON.parseObject(JSON.toJSONString(records.get(0)), XdFxkDdAttendancePo.class));
+    }
+
+    @PostMapping("test1")
+    McR test1() {
+        Date eTime = UtilDateTime.parseDateTime(UtilDateTime.formatDate(new Date()) + " 23:59:59");
+        Date sTime = UtilDateTime.parseDateTime(UtilDateTime.formatDate(new Date()) + " 11:00:00");
+
+        String Time = UtilDateTime.formatLocalDate(UtilDateTime.convertToLocalDateTimeFromDate(sTime).plusDays(1).toLocalDate()) + " 05:00:00";
+
+        log.info("xxxx, {}, {}", sTime, Time);
+//        ddClient_attendance.listAttendanceRecord(ddClient.getAccessToken(), Arrays.asList("1007515542693640"), "2023-05-17 00:00:00", "2023-05-24 23:59:59");
+
+//        return McR.success(ddClient_attendance.uploadAttendanceRecord(ddClient.getAccessToken(), "1111", "纷享销客同步", "纷享销客同步", null, new Date().getTime()));
+//        return McR.success(approveRecordDao2.findAllByEndTimeAfter(UtilDateTime.parseDateTime("2023-05-18 00:00:00"), PageRequest.of(0, 50)));
+        return McR.success();
+    }
+
     @PostMapping("test")
     McR test() {
-        long startTime = UtilDateTime.parseDateTime("2023-03-01" + " 00:00:00").getTime();
-        long endTime = UtilDateTime.parseDateTime("2023-04-30" + " 23:59:59").getTime();
-//        xdService.syncApprove(startTime, endTime, XDConf.TMP_CODE_CC, "出差");
+        long startTime = UtilDateTime.parseDateTime("2023-05-01" + " 00:00:00").getTime();
+        long endTime = UtilDateTime.parseDateTime("2023-05-31" + " 23:59:59").getTime();
+        xdService.syncApprove(startTime, endTime, XDConf.TMP_CODE_CC, "出差");
         xdService.syncApprove(startTime, endTime, XDConf.TMP_CODE_WC, "外出");
         return McR.success();
     }
 
     @PostMapping("test2")
     McR test2() {
-        Date eTime = UtilDateTime.parseDateTime("2023-04-30" + " 23:59:59");
-        Date sTime = UtilDateTime.parseDateTime("2023-04-01" + " 00:00:00");
+        Date eTime = UtilDateTime.parseDateTime("2023-05-31" + " 23:59:59");
+        Date sTime = UtilDateTime.parseDateTime("2023-05-04" + " 00:00:00");
         xdService.syncAttendance(0, sTime, eTime);
         return McR.success();
     }

+ 3 - 1
mjava-xiding/src/main/java/com/malk/xiding/repository/dao/XdDdApproveRecordDao2.java

@@ -16,7 +16,9 @@ import java.util.Date;
 public interface XdDdApproveRecordDao2 extends CrudRepository<XdDdApproveRecordPo, ID> {
 
     // 查询范围, 匹配考勤表
-    Page<XdDdApproveRecordPo> findAllByStartTimeBeforeAndEndTimeAfter(Date now1, Date now2, Pageable page);
+    Page<XdDdApproveRecordPo> findAllByEndTimeAfter(Date nowMin, Pageable page);
 
     Page<XdDdApproveRecordPo> findAll(Pageable page);
+    
+    Page<XdDdApproveRecordPo> findAllByOpenUserId(String userId, Pageable page);
 }

+ 2 - 0
mjava-xiding/src/main/java/com/malk/xiding/repository/dao/XdDdFxkRelationDao.java

@@ -12,4 +12,6 @@ import javax.transaction.Transactional;
 public interface XdDdFxkRelationDao extends JpaRepository<XdDdFxkRelationPo, Long> {
 
     XdDdFxkRelationPo findByIdDd(String userId);
+
+    XdDdFxkRelationPo findByName(String userName);
 }

+ 2 - 0
mjava-xiding/src/main/java/com/malk/xiding/repository/dao/XdFxkDdAttendanceDao.java

@@ -4,6 +4,7 @@ import com.malk.xiding.repository.entity.XdFxkDdAttendancePo;
 import org.springframework.data.jpa.repository.JpaRepository;
 
 import javax.transaction.Transactional;
+import java.util.Date;
 
 /**
  * 纷享销客外勤记录, 写入钉钉考勤记录
@@ -11,4 +12,5 @@ import javax.transaction.Transactional;
 @Transactional
 public interface XdFxkDdAttendanceDao extends JpaRepository<XdFxkDdAttendancePo, Long> {
 
+    boolean existsByIdDdAndCheckTimeEquals(String ddUserId, Date checkTime);
 }

+ 10 - 4
mjava-xiding/src/main/java/com/malk/xiding/repository/entity/XdFxkDdAttendancePo.java

@@ -1,14 +1,13 @@
 package com.malk.xiding.repository.entity;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.malk.base.BasePo;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.Table;
+import javax.persistence.*;
 import java.util.Date;
 
 @Entity
@@ -37,8 +36,10 @@ public class XdFxkDdAttendancePo extends BasePo {
     private String openUserId;
 
     /**
-     * 外勤时间
+     * 外勤时间 [fixme: 指定时区, new Date 会默认当前系统时区, 不添加 json 时区注解, 会出现序列化后的对象时间不是 GMT 时区]
      */
+    @Temporal(TemporalType.TIMESTAMP)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private Date checkTime;
 
     /**
@@ -50,4 +51,9 @@ public class XdFxkDdAttendancePo extends BasePo {
      * 同步备注
      */
     private String remark;
+
+    /**
+     * 外勤备注
+     */
+    private String outside;
 }

+ 10 - 19
mjava-xiding/src/main/java/com/malk/xiding/schedule/XDScheduleTask.java

@@ -1,5 +1,6 @@
 package com.malk.xiding.schedule;
 
+import com.malk.Util.UtilDateTime;
 import com.malk.xiding.server.XDConf;
 import com.malk.xiding.service.XDService;
 import lombok.extern.slf4j.Slf4j;
@@ -12,7 +13,7 @@ import org.springframework.scheduling.annotation.Scheduled;
 import java.util.Date;
 
 /**
- * @EnableScheduling 开启桑诺定时任务 [配置参考McScheduleTask]
+ * @EnableScheduling 开启定时任务 [配置参考McScheduleTask]
  */
 @Slf4j
 @Configuration
@@ -25,9 +26,9 @@ public class XDScheduleTask {
 
     /**
      * [定时同步审批单]
-     * 每天8点, 流程搜索按照发起和结束时间, 兼容性同步15内审批单
+     * 每天8点, 15点: 流程搜索按照发起和结束时间, 兼容性同步15内审批单
      */
-    @Scheduled(cron = "0 0 8 1/1 * ?")
+    @Scheduled(cron = "0 0 8,15 1/1 * ?")
     public void Time_Period_1() {
         try {
             log.info("###### [XD]同步审批单开始 ######");
@@ -41,25 +42,15 @@ public class XDScheduleTask {
         log.info("###### [XD]同步审批单结束 ######");
     }
 
-    @Scheduled(cron = "0 5/10 9,10,15 1/1 * ?")
-    public void Time_Period_2() {
-        syncAttendance2DD();
-    }
-
-    @Scheduled(cron = "0 5/10 16-23 1/1 * ?")
-    public void Time_Period_3() {
-        syncAttendance2DD();
-    }
-
     /**
-     * [频率为每10分钟查询一次]
-     * 09:00~11:00同步签到数据: 11点前纷享销客签到同步钉钉上班, 打卡为09:00
-     * 16:00 -23:59 同步签退数据: 下午4点前纷享销容签退, 同步钉钉打卡为18:00
+     * [频率为每10分钟查询一次, 同步当天全量时候, 过滤重复考勤, 避免钉钉调用次数过高]
      */
-    private void syncAttendance2DD() {
+    @Scheduled(cron = "0 9/10 9-10,16-23,0-4  1/1 * ?")
+    public void Time_Period_2() {
         log.info("###### [XD]同步考勤开始 ######");
-        Date eTime = new Date();
-        Date sTime = new Date(eTime.getTime() - 11 * 60 * 1000L);
+        Date now = new Date();
+        Date sTime = UtilDateTime.parseDateTime(UtilDateTime.formatDate(now) + " 00:00:00");
+        Date eTime = UtilDateTime.parseDateTime(UtilDateTime.formatDate(now) + " 23:59:59");
         try {
             xdService.syncAttendance(0, sTime, eTime);
         } catch (Exception e) {

+ 7 - 1
mjava-xiding/src/main/java/com/malk/xiding/service/XDService.java

@@ -6,11 +6,17 @@ public interface XDService {
 
     /**
      * 同步审批单
+     *
+     * @param tmpCode 审批单编码
+     * @param type    审批单描述
      */
     void syncApprove(long beginTime, long finishTime, String tmpCode, String type);
 
     /**
-     * 同步考勤记录
+     * 同步考勤记录 [50人考勤记录部分接近1000]
+     *
+     * @param sTime 考勤同步开始时间 & 读取结束时间大于sTime的申请单
+     * @param eTime 考勤同步结束时间
      */
     void syncAttendance(int page, Date sTime, Date eTime);
 }

+ 50 - 22
mjava-xiding/src/main/java/com/malk/xiding/service/impl/XDImplService.java

@@ -4,6 +4,7 @@ import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSON;
 import com.malk.Util.UtilDateTime;
 import com.malk.Util.UtilMap;
+import com.malk.Util.UtilMc;
 import com.malk.server.common.McException;
 import com.malk.server.fxiaoke.FXKConf;
 import com.malk.service.dingtalk.DDClient;
@@ -63,6 +64,8 @@ public class XDImplService implements XDService {
 
     /**
      * 同步审批单
+     * -
+     * 审批通过: 外出 + 出差. 后补审批自动同步当月
      */
     @Override
     public void syncApprove(long beginTime, long finishTime, String tmpCode, String type) {
@@ -70,7 +73,7 @@ public class XDImplService implements XDService {
         log.info("同步{}审批单: {} ~ {}", type, new Date(beginTime), new Date(finishTime));
         // 同步审批通过审批单 & 人员信息 [差集]
         Map extInfo = UtilMap.map("statuses", Arrays.asList("COMPLETED"));
-        List<String> dataList = ddClient.getInstanceIds_all(ddClient.getAccessToken(), tmpCode, beginTime, finishTime, extInfo);
+        List<String> dataList = ddClient_workflow.getInstanceIds_all(ddClient.getAccessToken(), tmpCode, beginTime, finishTime, extInfo);
         List<String> poList = ddApproveRecordDao.findAllByInstanceIdIn(dataList).stream().map(item -> item.getInstanceId()).collect(Collectors.toList());
         List<String> syncList = dataList.stream().filter(item -> !poList.contains(item)).collect(Collectors.toList());
         log.info("[{}] 实例列表, dataList = {}, poList = {}, syncList = {}", type, dataList.size(), poList.size(), syncList.size());
@@ -112,7 +115,7 @@ public class XDImplService implements XDService {
                     .build();
             ddApproveRecordDao.save(approveRecordPo);
             log.info("同步出差和人员信息, {}, {}", userPo, approveRecordPo);
-//            _attendanceSync(sTime, eTime, userPo.getIdFxxk(), userId);  // 兼容后补审批记录
+            _attendanceSync(sTime, eTime, userPo.getIdFxxk(), userId);  // 兼容后补审批记录
         });
     }
 
@@ -164,19 +167,28 @@ public class XDImplService implements XDService {
 
     /**
      * 同步考勤记录
+     * -
+     * 11点前,同步到钉钉9点
+     * 16点后,同步到钉钉18点
+     * 11-16点之间,同步真实打卡时间,但不影响考勤结果
+     * 0-5点的打卡记为前一天18点
      */
     @Override
     public void syncAttendance(int page, Date sTime, Date eTime) {
         log.info("考勤同步第{}批: {} ~ {}", page, sTime, eTime);
-//        Page<XdDdApproveRecordPo> poPage = approveRecordDao2.findAllByStartTimeBeforeAndEndTimeAfter(sTime, eTime, PageRequest.of(page, 50));
-        Page<XdDdApproveRecordPo> poPage = approveRecordDao2.findAll(PageRequest.of(page, 50));
+        Page<XdDdApproveRecordPo> poPage = approveRecordDao2.findAllByEndTimeAfter(sTime, PageRequest.of(page, 40));
+        // 全量同步
+//        Page<XdDdApproveRecordPo> poPage = approveRecordDao2.findAll(PageRequest.of(page, 40));
+//        Page<XdDdApproveRecordPo> poPage = approveRecordDao2.findAllByOpenUserId("FSUID_11F092EC8EEAB75C282DB45DBC325BB6", PageRequest.of(page, 40))
         if (poPage.isEmpty()) {
             return;
         }
-        List<XdDdApproveRecordPo> poList = poPage.getContent();
+        // id去重 [查询单个用户可考虑去重]
+//        List<XdDdApproveRecordPo> poList = poPage.getContent();
+        List<XdDdApproveRecordPo> poList = poPage.getContent().stream().filter(UtilMc.distinctByKey(XdDdApproveRecordPo::getOpenUserId)).collect(Collectors.toList());
         List<String> openUserIds = poList.stream().map(item -> item.getOpenUserId()).collect(Collectors.toList());
-        List<Map> attendanceList = fxkClient.getAttendanceForOutside(fxkClient.getAccessToken(), fxkConf.getCorpId(), sTime.getTime(), eTime.getTime(), openUserIds, null);
-        log.info("同步人员数量 = {}, 考勤数量 = {}", openUserIds.size(), attendanceList.size());
+        List<Map> attendanceList = fxkClient.getAttendance_All(fxkClient.getAccessToken(), fxkConf.getCorpId(), sTime.getTime(), eTime.getTime(), openUserIds);
+        log.info("同步人员数量 = {}, 考勤数量 = {}", openUserIds.size());
         attendanceList.forEach(item -> {
             XdFxkDdAttendancePo attendancePo = JSON.parseObject(JSON.toJSONString(item), XdFxkDdAttendancePo.class);
             attendancePo.setIdDd(poList.stream().filter(row -> row.getOpenUserId().equals(attendancePo.getOpenUserId())).findAny().get().getUserId());
@@ -198,7 +210,7 @@ public class XDImplService implements XDService {
         if (sTime.getMonth() != eTime.getMonth()) {
             sTime = new Date(sTime.getYear(), eTime.getMonth(), 1);
         }
-        List<Map> attendanceList = fxkClient.getAttendanceForOutside(fxkClient.getAccessToken(), fxkConf.getCorpId(), sTime.getTime(), eTime.getTime(), Arrays.asList(openUserId), null);
+        List<Map> attendanceList = fxkClient.getAttendance_All(fxkClient.getAccessToken(), fxkConf.getCorpId(), sTime.getTime(), eTime.getTime(), Arrays.asList(openUserId));
         log.info("后补人员 = {}, 考勤数量 = {}", openUserId, attendanceList.size());
         attendanceList.forEach(item -> {
             XdFxkDdAttendancePo attendancePo = JSON.parseObject(JSON.toJSONString(item), XdFxkDdAttendancePo.class);
@@ -209,28 +221,44 @@ public class XDImplService implements XDService {
 
     // 考勤写入规则
     private void _attendanceRule(XdFxkDdAttendancePo attendancePo) {
-        long check = 0;
+        // 11 - 16 之间之间同步打卡记录
+        long check = attendancePo.getCheckTime().getTime();
         int hour = attendancePo.getCheckTime().getHours();
-        if (hour <= 11) {
-            check = UtilDateTime.parseDateTime(UtilDateTime.formatDate(attendancePo.getCheckTime()) + " 09:00:00").getTime();
+        if (hour < 11) {
+            // 凌晨5点前打卡记为第前天下班卡
+            if (hour < 5) {
+                check = UtilDateTime.parseDateTime(UtilDateTime.formatDate(new Date(attendancePo.getCheckTime().getTime() - (hour + 1) * 60 * 60 * 1000)) + " 18:00:00").getTime();
+            } else {
+                check = UtilDateTime.parseDateTime(UtilDateTime.formatDate(attendancePo.getCheckTime()) + " 09:00:00").getTime();
+            }
         }
         if (hour >= 16) {
             check = UtilDateTime.parseDateTime(UtilDateTime.formatDate(attendancePo.getCheckTime()) + " 18:00:00").getTime();
         }
-        if (check > 0L) {
-            String ss = "纷享销客外勤: " + UtilDateTime.formatDateTime(new Date(attendancePo.getCheckTime().getTime()));
-            String remark;
-            try {
-                // 燕江 0953580166764920
-                ddClient_attendance.uploadAttendanceRecord(ddClient.getAccessToken(), attendancePo.getOpenUserId(), ss, "纷享销客同步", null, check);
-                remark = "同步成功";
-            } catch (McException e) {
-                remark = e.getMessage();
-                log.error(e.getMessage(), e);  // 记录错误日志
+        try {
+            boolean hasRecord = attendanceDao.existsByIdDdAndCheckTimeEquals(attendancePo.getIdDd(), attendancePo.getCheckTime());
+            if (hasRecord) {
+                log.info("存在考勤, {}, {}", attendancePo.getUserName(), attendancePo.getCheckTime());
+                return;
+            }
+            // 中间时段, 匹配是否最晚打卡, 影响钉钉考勤结果
+            if (check == attendancePo.getCheckTime().getTime()) {
+                String sTime = UtilDateTime.formatDateTime(attendancePo.getCheckTime());
+                String eTime = UtilDateTime.formatLocalDate(UtilDateTime.convertToLocalDateTimeFromDate(attendancePo.getCheckTime()).plusDays(1).toLocalDate()) + " 05:00:00";
+                List records = ddClient_attendance.listAttendanceRecord(ddClient.getAccessToken(), Arrays.asList(attendancePo.getIdDd()), sTime, eTime);
+                if (records.size() > 0) {
+                    log.info("避免覆盖, {}, {}, {}, {}", attendancePo.getUserName(), sTime, eTime, records.size());
+                    return;
+                }
             }
-            attendancePo.setRemark(remark);
+            String ss = "纷享销客同步: " + UtilDateTime.formatDateTime(new Date(attendancePo.getCheckTime().getTime()));
+            // 燕江 0953580166764920
+            ddClient_attendance.uploadAttendanceRecord(ddClient.getAccessToken(), attendancePo.getIdDd(), ss, "纷享销客同步", null, check);
+            attendancePo.setRemark("同步成功");
             attendanceDao.save(attendancePo);
             log.info("写入考勤, {}, {}", attendancePo.getUserName(), attendancePo.getCheckTime());
+        } catch (McException e) {
+            log.error(e.getMessage(), e);  // 记录错误日志
         }
     }
 }

+ 7 - 7
mjava-xiding/src/main/resources/application-dev.yml

@@ -14,8 +14,8 @@ spring:
   datasource:
     driver-class-name: com.mysql.cj.jdbc.Driver
     username: root
-    password: mu123
-    url: jdbc:mysql://127.0.0.1:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+    password: cp-root@2022++
+    url: jdbc:mysql://47.97.181.40:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
   jpa:
     hibernate:
       ddl-auto: none      # JPA对表没有任何操作
@@ -26,14 +26,14 @@ spring:
 # filepath
 file:
   path:
-    file: /Users/malk/service/_Tool/var/mjava/tmp//file/
-    image: /Users/malk/service/_Tool/var/mjava/tmp//image/
-    tmp: /Users/malk/service/_Tool/var/mjava/tmp/
+    file: /Users/malk/server/_Tool/var/mjava/tmp//file/
+    image: /Users/malk/server/_Tool/var/mjava/tmp//image/
+    tmp: /Users/malk/server/_Tool/var/mjava/tmp/
   source:
-    fonts: /Users/malk/service/_Tool/fonts/simsun.ttc
+    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
 logging:
   file:
-    path: /Users/malk/service/_Tool/var/mjava/log
+    path: /Users/malk/server/_Tool/var/mjava/log
 
 # dingtalk
 dingtalk:

+ 1 - 1
mjava-minjiaoyuan/src/test/resources/server.sh

@@ -1,5 +1,5 @@
 #!/bin/bash
-appname='mjava-minjiaoyuan'
+appname='mjava-xiding'
 if [ "$1" == "dev" ]; then
   java -Xms256m -Xmx256m -jar $appname.jar --spring.profiles.active=dev
 else

+ 55 - 0
mjava-xiding/src/test/resources/winsw.xml

@@ -0,0 +1,55 @@
+<!--
+  MIT License
+
+  Copyright (c) 2008-2020 Kohsuke Kawaguchi, Sun Microsystems, Inc., CloudBees,
+  Inc., Oleg Nenashev and other contributors
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction, including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all
+  copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+  SOFTWARE.
+-->
+
+<!--
+ This is an example of a minimal Windows Service Wrapper configuration, which includes only mandatory options.
+ 
+ This configuration file should be placed near the WinSW executable, the name should be the same.
+ E.g. for myapp.exe the configuration file name should be myapp.xml
+ 
+ You can find more information about the configuration options here: https://github.com/kohsuke/winsw/blob/master/doc/xmlConfigFile.md
+ Full example: https://github.com/kohsuke/winsw/blob/master/examples/sample-allOptions.xml
+-->
+
+<service>
+    <!-- 注册服务ID -->
+    <id>mjava</id>
+    <!-- 启动服务名称 -->
+    <name>mjava</name>
+    <!-- 对服务的描述 -->
+    <description>标准化后端接口, 自用脚手架封装</description>
+    <!-- 「jdk需要安装」启动的可执行文件:若未配置环境变量executable需要执行绝对路径 -->
+    <!-- <executable>java</executable> -->
+    <executable>C:\Program Files\DingTalkServer\jdk1.8.0_221\bin\java</executable>
+    <!-- Xmx256m 代表堆内存最大值为256MB -jar后面的是项目名 -->
+    <arguments>-Xms256m -Xmx256m -jar mjava-xiding.jar</arguments>
+    <!-- 服务的启动模式:默认Automatic -->
+    <startmode>Automatic</startmode>
+    <!-- 日志地址 -->
+    <logpath>%BASE%\ws</logpath>
+    <!-- 日志模式 -->
+    <logmode>rotate</logmode>
+</service>
+

+ 7 - 7
mjava-xiding/target/classes/application-dev.yml

@@ -14,8 +14,8 @@ spring:
   datasource:
     driver-class-name: com.mysql.cj.jdbc.Driver
     username: root
-    password: mu123
-    url: jdbc:mysql://127.0.0.1:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+    password: cp-root@2022++
+    url: jdbc:mysql://47.97.181.40:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
   jpa:
     hibernate:
       ddl-auto: none      # JPA对表没有任何操作
@@ -26,14 +26,14 @@ spring:
 # filepath
 file:
   path:
-    file: /Users/malk/service/_Tool/var/mjava/tmp//file/
-    image: /Users/malk/service/_Tool/var/mjava/tmp//image/
-    tmp: /Users/malk/service/_Tool/var/mjava/tmp/
+    file: /Users/malk/server/_Tool/var/mjava/tmp//file/
+    image: /Users/malk/server/_Tool/var/mjava/tmp//image/
+    tmp: /Users/malk/server/_Tool/var/mjava/tmp/
   source:
-    fonts: /Users/malk/service/_Tool/fonts/simsun.ttc
+    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
 logging:
   file:
-    path: /Users/malk/service/_Tool/var/mjava/log
+    path: /Users/malk/server/_Tool/var/mjava/log
 
 # dingtalk
 dingtalk:

+ 1 - 1
mjava-minjiaoyuan/target/test-classes/server.sh

@@ -1,5 +1,5 @@
 #!/bin/bash
-appname='mjava-minjiaoyuan'
+appname='mjava-xiding'
 if [ "$1" == "dev" ]; then
   java -Xms256m -Xmx256m -jar $appname.jar --spring.profiles.active=dev
 else

+ 55 - 0
mjava-xiding/target/test-classes/winsw.xml

@@ -0,0 +1,55 @@
+<!--
+  MIT License
+
+  Copyright (c) 2008-2020 Kohsuke Kawaguchi, Sun Microsystems, Inc., CloudBees,
+  Inc., Oleg Nenashev and other contributors
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction, including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all
+  copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+  SOFTWARE.
+-->
+
+<!--
+ This is an example of a minimal Windows Service Wrapper configuration, which includes only mandatory options.
+ 
+ This configuration file should be placed near the WinSW executable, the name should be the same.
+ E.g. for myapp.exe the configuration file name should be myapp.xml
+ 
+ You can find more information about the configuration options here: https://github.com/kohsuke/winsw/blob/master/doc/xmlConfigFile.md
+ Full example: https://github.com/kohsuke/winsw/blob/master/examples/sample-allOptions.xml
+-->
+
+<service>
+    <!-- 注册服务ID -->
+    <id>mjava</id>
+    <!-- 启动服务名称 -->
+    <name>mjava</name>
+    <!-- 对服务的描述 -->
+    <description>标准化后端接口, 自用脚手架封装</description>
+    <!-- 「jdk需要安装」启动的可执行文件:若未配置环境变量executable需要执行绝对路径 -->
+    <!-- <executable>java</executable> -->
+    <executable>C:\Program Files\DingTalkServer\jdk1.8.0_221\bin\java</executable>
+    <!-- Xmx256m 代表堆内存最大值为256MB -jar后面的是项目名 -->
+    <arguments>-Xms256m -Xmx256m -jar mjava-xiding.jar</arguments>
+    <!-- 服务的启动模式:默认Automatic -->
+    <startmode>Automatic</startmode>
+    <!-- 日志地址 -->
+    <logpath>%BASE%\ws</logpath>
+    <!-- 日志模式 -->
+    <logmode>rotate</logmode>
+</service>
+

+ 18 - 0
mjava-xintianlong/src/main/java/com/malk/xintianlong/controller/DDController.java

@@ -0,0 +1,18 @@
+package com.malk.xintianlong.controller;
+
+import com.malk.controller.DDCallbackController;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 钉钉事件回调
+ * -
+ * 子项目直接继承即可有调用, 无需实现, 获取项目回调请求地址 [https://mc.cloudpure.cn/api/xintianlong/dd/callback]
+ */
+@Slf4j
+@RestController
+@RequestMapping("/dd")
+public class DDController extends DDCallbackController {
+
+}

+ 175 - 17
mjava-xintianlong/src/main/java/com/malk/xintianlong/controller/HSController.java

@@ -3,8 +3,10 @@ package com.malk.xintianlong.controller;
 import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSON;
 import com.malk.Util.UtilMap;
+import com.malk.base.BaseDto;
 import com.malk.server.aliwork.YDConf;
 import com.malk.server.aliwork.YDParam;
+import com.malk.server.aliwork.YDR;
 import com.malk.server.common.McException;
 import com.malk.server.common.McR;
 import com.malk.server.dingtalk.DDConf;
@@ -14,29 +16,30 @@ import com.malk.service.aliwork.YDClient;
 import com.malk.service.dingtalk.DDClient;
 import com.malk.service.dingtalk.DDClient_Workflow;
 import com.malk.xintianlong.repository.dao.HSApproveRecordDao;
+import com.malk.xintianlong.repository.dao.HSViewDao;
 import com.malk.xintianlong.repository.entity.HSApproveRecordPo;
 import com.malk.xintianlong.server.HSConf;
 import com.malk.xintianlong.service.HSService;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.repository.query.Param;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
 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 javax.servlet.http.HttpServletRequest;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 /**
  * 错误抛出与拦截详见CatchException
  */
 @Slf4j
 @RestController
-@RequestMapping("/xintianlong")
+@RequestMapping
 public class HSController {
 
     @Autowired
@@ -55,10 +58,10 @@ public class HSController {
      * 推送申购单审批
      */
     @PostMapping("dd/sgd")
-    McR purchaseApprove(@RequestBody Map data, HttpServletRequest request, @Param("name") String name) {
+    McR purchaseApprove(@RequestBody Map data, HttpServletRequest request) {
 
         log.info("推送申购单审批, {}", data);
-        hsService.validateAuthorization(request, String.valueOf(data.get("orderCode")));
+        hsService.validateAuthorization(request, String.valueOf(data.get("orderCode")), String.valueOf(data.get("corpType")));
 
         // 组件数据格式化
         data.put("corpTypeName", HSConf.SUB_CORP_DD.get(data.get("corpType")));
@@ -81,6 +84,59 @@ public class HSController {
         return McR.success(po);
     }
 
+    /**
+     * 推送结算单审批
+     */
+    @PostMapping("dd/jsd")
+    McR settleApprove(@RequestBody Map data, HttpServletRequest request) {
+
+        log.info("推送结算单审批, {}", data);
+        hsService.validateAuthorization(request, String.valueOf(data.get("orderCode")), String.valueOf(data.get("corpType")));
+
+        // 组件数据格式化
+        data.put("corpTypeName", HSConf.SUB_CORP_DD.get(data.get("corpType")));
+        data.put("salesmanCodeDing", JSON.toJSONString(Arrays.asList(data.get("salesmanCode"))));
+        if (StringUtils.isNotBlank(String.valueOf(data.get("transportationCode2")))) {
+            data.put("transportationCode", data.get("transportationCode") + "/" + data.get("transportationCode2"));
+        }
+        if (StringUtils.isNotBlank(String.valueOf(data.get("proposerDate2")))) {
+            data.put("proposerDate", data.get("proposerDate") + "/" + data.get("proposerDate2"));
+        }
+        Map ruleForm = UtilMap.map("corpTypeName, orderCode, proposerDate, salesmanCodeDing", "所属公司, 结算单号, 出货日期, 业务员");
+        ruleForm.put("taskCode", "指定书号");
+        ruleForm.put("purchaseCorp", "要货单位");
+        ruleForm.put("invoiceNumber", "发票号");
+        ruleForm.put("productiionName", "产品名称");
+        ruleForm.put("transportationCode", "调运单号");
+        ruleForm.put("processingCharges", "加工费详情");
+        ruleForm.put("totalPrice", "实收加工费(元)");
+
+        Map ruleDetail = UtilMap.map("casting", UtilMap.map("taskCode, groupCode, size, count, price, total, supplier, remark", "指定书号, 组号, 品名/规格, 数量(米), 单价, 金额(元), 供坯商, 备注"));
+        ruleForm.put("casting", "投坯详情");
+
+        ruleDetail.put("shipment", UtilMap.map("taskCode, groupCode, constructCode, size, num, count, price, total, priceSpread, remark", "指定书号, 组号, 合同号, 品名/规格, 件数, 数量(米), 单价, 金额(元), 辅料差价(元), 备注"));
+        ruleForm.put("shipment", "成品出货详情");
+
+        ruleDetail.put("residue", UtilMap.map("taskCode, groupCode, size, num, count, price, total, otherPrice, remark", "指定书号, 组号, 品名/规格, 件数, 数量(米), 单价, 金额(元), 其他金额(元), 备注"));
+        ruleForm.put("residue", "余坯款");
+
+        // 推送钉钉审批
+        List<Map> formValues = DDFormComponentDto.formatComponentValues(data, ruleForm, ruleDetail);
+
+        String userId = String.valueOf(data.get("proposerCode"));
+        Map extInfo = UtilMap.map("dept_id", DDConf.TOP_DEPARTMENT);
+        String processInstanceId = ddClient_workflow.doProcessInstances(ddClient.getAccessToken(), userId, HSConf.SETTLE_CODE_DD, formValues, extInfo);
+
+        // 保存推送记录
+        HSApproveRecordPo po = JSON.parseObject(JSON.toJSONString(data), HSApproveRecordPo.class);
+        po.setProcessInstanceId(processInstanceId);
+        po.setRemark("结算申请单");
+        po.setFormType("TS001");
+        approveRecordDao.save(po);
+
+        return McR.success(po);
+    }
+
     /**
      * 推送指定书审批
      */
@@ -89,7 +145,7 @@ public class HSController {
 
         data.put("test", "是");
         log.info("推送指定书审批, {}", data);
-        hsService.validateAuthorization(request, String.valueOf(data.get("orderCode")));
+        hsService.validateAuthorization(request, String.valueOf(data.get("orderCode")), String.valueOf(data.get("corpType")));
 
         // 组件数据格式化
         String userId = String.valueOf(data.get("proposerCode"));
@@ -115,16 +171,37 @@ public class HSController {
         return McR.success(po);
     }
 
+    @Autowired
+    HSApproveRecordDao hsApproveRecordDao;
+
     /**
-     * 钉钉审批回调 [连接器-同意]
+     * 钉钉审批回调 [连接器-同意] - 废弃
      */
-    @PostMapping("dd/approve")
+//    @PostMapping("dd/approve")
     McR purchaseApproveCallback(@RequestBody Map<String, String> data) {
 
-        log.info("申购单审批回调, {}", data);
-        McException.assertParamException_Null(data, "processInstanceId", "approveResult");
-        String processInstanceId = data.get("processInstanceId");
-        return McR.success(hsService.syncApproveResult2Hs(processInstanceId, data.get("approveResult")));
+        log.info("###### [HS]开始同步审批中记录 ######");
+        List<HSApproveRecordPo> list = hsApproveRecordDao.findAllByApproveResult("process");
+        log.info("同步数量, {}", list.size());
+        for (HSApproveRecordPo po : list) {
+            log.info("xxx, {}", po);
+            Map rsp = ddClient_workflow.getProcessInstanceId(ddClient.getAccessToken(), po.getProcessInstanceId());
+            if (Arrays.asList("RUNNING", "NEW").contains(rsp.get("status"))) {
+                continue;
+            }
+            if (Arrays.asList("TERMINATED", "CANCELED").contains(rsp.get("status"))) {
+                hsService.syncApproveResult2Hs(po.getProcessInstanceId(), "terminated");
+            }
+            if (StringUtils.isNotBlank(String.valueOf(rsp.get("result")))) {
+                hsService.syncApproveResult2Hs(po.getProcessInstanceId(), "agree".equals(String.valueOf(rsp.get("result"))) ? "agree" : "refuse");
+            }
+        }
+
+//        log.info("申购单审批回调, {}", data);
+//        McException.assertParamException_Null(data, "processInstanceId", "approveResult");
+//        String processInstanceId = data.get("processInstanceId");
+//        return McR.success(hsService.syncApproveResult2Hs(processInstanceId, data.get("approveResult")));
+        return McR.success();
     }
 
     /**
@@ -143,8 +220,8 @@ public class HSController {
     @PostMapping("dd/terminate")
     McR terminateApproveResult(@RequestBody Map<String, String> data) {
 
-        McException.assertParamException_Null(data, "orderCode");
-        HSApproveRecordPo po = approveRecordDao.findByOrderCodeAndApproveResult(data.get("orderCode"), "process");
+        McException.assertParamException_Null(data, "orderCode", "corpType");
+        HSApproveRecordPo po = approveRecordDao.findByOrderCodeAndApproveResultAndCorpType(data.get("orderCode"), "process", data.get("corpType"));
         McException.assertAccessException(ObjectUtil.isNull(po), "该单号下, 没有审批中的单据!");
         ddClient_workflow.terminateRunningApprove(ddClient.getAccessToken(), po.getProcessInstanceId(), true, "环思取消送审", null);
         approveRecordDao.updateApproveResult(po.getProcessInstanceId(), "terminated", "环思取消送审");
@@ -194,4 +271,85 @@ public class HSController {
         DDR_New ddr_new = ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_search_process);
         return McR.success(ddr_new);
     }
+
+
+    @Autowired
+    private HSViewDao hsOrderPlanDao;
+
+    /**
+     * 查询生产计划
+     */
+    @PostMapping("view/queryOrderPlan")
+    McR queryOrderPlan(@RequestBody Map data) {
+
+        log.info("查询生产计划, {}", data);
+
+        String sOrderNo = UtilMap.getString(data, "sOrderNo");
+        Pageable pageable = PageRequest.of(UtilMap.getInt(data, "page") - 1, UtilMap.getInt(data, "size"));
+
+        Page page;
+        if (UtilMap.isNotBlankString(data, "startTime") && UtilMap.isNotBlankString(data, "endTime")) {
+            Date sTime = new Date(UtilMap.getLong(data, "startTime"));
+            Date eTime = new Date(UtilMap.getLong(data, "endTime"));
+            page = hsOrderPlanDao.queryOrderPlan(sTime, eTime, sOrderNo, pageable);
+        } else if (UtilMap.isNotBlankString(data, "startTime")) {
+            Date sTime = new Date(UtilMap.getLong(data, "startTime"));
+            page = hsOrderPlanDao.queryOrderPlan_start(sTime, sOrderNo, pageable);
+        } else if (UtilMap.isNotBlankString(data, "endTime")) {
+            Date eTime = new Date(UtilMap.getLong(data, "endTime"));
+            page = hsOrderPlanDao.queryOrderPlan_end(eTime, sOrderNo, pageable);
+        } else {
+            page = hsOrderPlanDao.queryOrderPlan(sOrderNo, pageable);
+        }
+        Map result = YDR.formatPage(page);
+
+        return McR.success(BaseDto.jsonFormatDateTime(result));
+
+    }
+
+    /**
+     * 查询成品库存
+     */
+    @PostMapping("view/queryStoreWarehouse")
+    McR queryStoreWarehouse(@RequestBody Map data) {
+
+        log.info("查询成品库存, {}", data);
+        String sStoreInNo = UtilMap.getString(data, "sStoreInNo");
+        Pageable pageable = PageRequest.of(UtilMap.getInt(data, "page") - 1, UtilMap.getInt(data, "size"));
+
+        Page page;
+        if (UtilMap.isNotBlankString(data, "startTime") && UtilMap.isNotBlankString(data, "endTime")) {
+            Date sTime = new Date(UtilMap.getLong(data, "startTime"));
+            Date eTime = new Date(UtilMap.getLong(data, "endTime"));
+            page = hsOrderPlanDao.queryStoreWarehouse(sTime, eTime, sStoreInNo, pageable);
+        } else if (UtilMap.isNotBlankString(data, "startTime")) {
+            Date sTime = new Date(UtilMap.getLong(data, "startTime"));
+            page = hsOrderPlanDao.queryStoreWarehouse_start(sTime, sStoreInNo, pageable);
+        } else if (UtilMap.isNotBlankString(data, "endTime")) {
+            Date eTime = new Date(UtilMap.getLong(data, "endTime"));
+            page = hsOrderPlanDao.queryStoreWarehouse_end(eTime, sStoreInNo, pageable);
+        } else {
+            page = hsOrderPlanDao.queryStoreWarehouse(sStoreInNo, pageable);
+        }
+        Map result = YDR.formatPage(page);
+
+        return McR.success(BaseDto.jsonFormatDateTime(result));
+    }
+
+
+    @PostMapping("test")
+    McR test() {
+
+//        approveRecordDao.save(HSApproveRecordPo.builder()
+//                .corpType("01")
+//                .processInstanceId("test1")
+//                .formType("ts")
+//                .orderCode("xx")
+//                .approveResult("xx")
+//                .proposerCode("x")
+//                .build());
+
+
+        return McR.success(approveRecordDao.findAllByOrderCodeIn(Arrays.asList("2023-03-014")));
+    }
 }

+ 64 - 0
mjava-xintianlong/src/main/java/com/malk/xintianlong/delegate/DDDelegate.java

@@ -0,0 +1,64 @@
+package com.malk.xintianlong.delegate;
+
+import com.malk.delegate.DDEvent_Delegate;
+import com.malk.xintianlong.server.HSConf;
+import com.malk.xintianlong.service.HSService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Primary;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+import java.util.Arrays;
+
+/**
+ * OA审批事件 [主项目也有实现, 添加 @Primary 优先注入主项目实现]
+ * -
+ * 取消方案: 撤销和拒绝流程不继续执行连接器, 因此不使用连接器与轮询审批记录方案 [低效而且占用较高钉钉api调次数];
+ * 优化方案: 通过事件订阅实现实时同步所有审批状态, 定时查询钉钉回调失败记录 [配置钉钉事件Delegate, 添加定时任务]
+ */
+@Slf4j
+@Service
+@Primary
+public class DDDelegate implements DDEvent_Delegate {
+
+    // 审批任务回调执行业务逻辑
+    @Async
+    @Override
+    public void executeEvent_Task_Finish(String processInstanceId, String processCode, boolean isAgree, String remark) {
+        log.info("executeEvent_Task_Finish");
+    }
+
+    @Async
+    @Override
+    public void executeEvent_Task_Start(String processInstanceId, String processCode) {
+        log.info("executeEvent_Task_Start");
+    }
+
+    @Async
+    @Override
+    public void executeEvent_Task_Redirect(String processInstanceId, String processCode) {
+        log.info("executeEvent_Task_Redirect");
+    }
+
+    @Async
+    @Override
+    public void executeEvent_Instance_Start(String processInstanceId, String processCode) {
+        log.info("executeEvent_Instance_Start");
+    }
+
+    @Autowired
+    private HSService hsService;
+
+    // 审批实例回调执行业务逻辑
+    @Async
+    @Override
+    public void executeEvent_Instance_Finish(String processInstanceId, String processCode, boolean isAgree, boolean isTerminate) {
+        log.info("executeEvent_Instance_Finish");
+        String approveResult = isAgree ? "agree" : "refuse";
+        if (isTerminate) approveResult = "terminated";
+        if (Arrays.asList(HSConf.PRODUCT_CODE_DD, HSConf.PURCHASE_CODE_DD, HSConf.SETTLE_CODE_DD).contains(processCode)) {
+            hsService.syncApproveResult2Hs(processInstanceId, approveResult);
+        }
+    }
+}

+ 1 - 1
mjava-xintianlong/src/main/java/com/malk/xintianlong/repository/dao/HSApproveRecordDao.java

@@ -21,5 +21,5 @@ public interface HSApproveRecordDao extends JpaRepository<HSApproveRecordPo, Lon
 
     List<HSApproveRecordPo> findAllByOrderCodeIn(List<String> orderCodeList);
 
-    HSApproveRecordPo findByOrderCodeAndApproveResult(String orderCode, String approveResult);
+    HSApproveRecordPo findByOrderCodeAndApproveResultAndCorpType(String orderCode, String approveResult, String corpType);
 }

+ 47 - 0
mjava-xintianlong/src/main/java/com/malk/xintianlong/repository/dao/HSViewDao.java

@@ -0,0 +1,47 @@
+package com.malk.xintianlong.repository.dao;
+
+import com.malk.base.JpaMap;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.CrudRepository;
+
+import javax.transaction.Transactional;
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * 视图表查询 [通过Map实现, 无需定义实体, 主键设置Long即可]
+ */
+@Transactional
+public interface HSViewDao extends CrudRepository<JpaMap, Long> {
+    /**
+     * 查询生产计划
+     */
+    @Query(value = "select * from vwpbCommonDataOrderPlan where dPlanDate >= ?1 and dPlanDate <= ?2 and sOrderNo like LTRIM('%' + ?3 + '%') order by dPlanDate desc", nativeQuery = true)
+    Page<Map> queryOrderPlan(Date start, Date end, String sOrderNo, Pageable pageable);
+
+    @Query(value = "select * from vwpbCommonDataOrderPlan where dPlanDate >= ?1 and sOrderNo like LTRIM('%' + ?2 + '%') order by dPlanDate desc", nativeQuery = true)
+    Page<Map> queryOrderPlan_start(Date end, String sOrderNo, Pageable pageable);
+
+    @Query(value = "select * from vwpbCommonDataOrderPlan where dPlanDate <= ?1 and sOrderNo like LTRIM('%' + ?2 + '%') order by dPlanDate desc", nativeQuery = true)
+    Page<Map> queryOrderPlan_end(Date start, String sOrderNo, Pageable pageable);
+
+    @Query(value = "select * from vwpbCommonDataOrderPlan where sOrderNo like LTRIM('%' + ?1 + '%') order by dPlanDate desc", nativeQuery = true)
+    Page<Map> queryOrderPlan(String sOrderNo, Pageable pageable);
+
+    /**
+     * 查询成品库存
+     */
+    @Query(value = "select * from vwmmSTInStoreQuery where tStoreInTime >= ?1 and tStoreInTime <= ?2 and sStoreInNo like LTRIM('%' + ?3 + '%') order by tStoreInTime desc", nativeQuery = true)
+    Page<Map> queryStoreWarehouse(Date start, Date end, String sOrderNo, Pageable pageable);
+
+    @Query(value = "select * from vwmmSTInStoreQuery where tStoreInTime >= ?1 and sStoreInNo like LTRIM('%' + ?2 + '%') order by tStoreInTime desc", nativeQuery = true)
+    Page<Map> queryStoreWarehouse_start(Date end, String sOrderNo, Pageable pageable);
+
+    @Query(value = "select * from vwmmSTInStoreQuery where tStoreInTime <= ?1 and sStoreInNo like LTRIM('%' + ?2 + '%') order by tStoreInTime desc", nativeQuery = true)
+    Page<Map> queryStoreWarehouse_end(Date start, String sOrderNo, Pageable pageable);
+
+    @Query(value = "select * from vwmmSTInStoreQuery where sStoreInNo like LTRIM('%' + ?1 + '%') order by tStoreInTime desc", nativeQuery = true)
+    Page<Map> queryStoreWarehouse(String sStoreInNo, Pageable pageable);
+}

+ 1 - 2
mjava-xintianlong/src/main/java/com/malk/xintianlong/repository/entity/HSApproveRecordPo.java

@@ -49,7 +49,7 @@ public class HSApproveRecordPo extends BasePo {
     private String remark;
 
     /**
-     * 回调环思单据类型。SD001: 指定书, PU001 申购单
+     * 回调环思单据类型。SD001: 指定书, PU001 申购单, 结算单 TS001
      */
     private String formType;
 
@@ -57,5 +57,4 @@ public class HSApproveRecordPo extends BasePo {
      * 环思回调结果
      */
     private String hsResponse;
-
 }

+ 19 - 2
mjava-xintianlong/src/main/java/com/malk/xintianlong/schedule/HSScheduleTask.java

@@ -1,6 +1,7 @@
 package com.malk.xintianlong.schedule;
 
 import com.malk.service.dingtalk.DDClient;
+import com.malk.service.dingtalk.DDClient_Event;
 import com.malk.service.dingtalk.DDClient_Workflow;
 import com.malk.xintianlong.repository.dao.HSApproveRecordDao;
 import com.malk.xintianlong.repository.entity.HSApproveRecordPo;
@@ -18,7 +19,7 @@ import java.util.List;
 import java.util.Map;
 
 /**
- * @EnableScheduling 开启桑诺定时任务 [配置参考McScheduleTask]
+ * @EnableScheduling 开启定时任务 [配置参考McScheduleTask]
  */
 @Slf4j
 @Configuration
@@ -39,7 +40,7 @@ public class HSScheduleTask {
     private HSService hsService;
 
     /**
-     * 同步审批中数据, [0...5分钟/次]
+     * 同步审批中数据, [0...5分钟/次]  - 未废弃[环思接口请求可能会存在超时情况]
      */
     @Scheduled(cron = "0 0/5 * * * ?")
     public void syncYSB2COrderToDingTalkApprove() {
@@ -65,4 +66,20 @@ public class HSScheduleTask {
         }
         log.info("###### [HS]同步审批中记录结束 ######");
     }
+
+    @Autowired
+    private DDClient_Event ddClient_event;
+
+    /**
+     * 同步钉钉推送失败记录: 推送失败列表, 获取后记录会被清空
+     */
+    @Scheduled(cron = "0 0/30 7-23 * * ?")
+    public void syncDingTalkFailedList() {
+        try {
+            ddClient_event.syncFailedList(ddClient.getAccessToken());
+        } catch (Exception e) {
+            // 记录错误信息
+            e.printStackTrace();
+        }
+    }
 }

+ 5 - 1
mjava-xintianlong/src/main/java/com/malk/xintianlong/server/HSConf.java

@@ -15,11 +15,15 @@ public class HSConf {
      * 指定书编码
      */
     public final static String PRODUCT_CODE_DD = "PROC-73D17253-4553-4F41-9DB4-E923C85842A0";
+    /**
+     * 结算编码
+     */
+    public final static String SETTLE_CODE_DD = "PROC-6C8769AB-5EC2-4A8F-858B-D2C3FA7A0210";
 
     /**
      * 审批主体
      */
-    public final static Map SUB_CORP_DD = UtilMap.map("01, 02", "金塔克斯, 灝宇");
+    public final static Map SUB_CORP_DD = UtilMap.map("01, 02", "浙江金塔克斯科技有限公司, 浙江灏宇科技有限公司");
 
     /**
      * 钉钉秘钥

+ 1 - 1
mjava-xintianlong/src/main/java/com/malk/xintianlong/service/HSService.java

@@ -8,7 +8,7 @@ public interface HSService {
     /**
      * 校验调用授权
      */
-    void validateAuthorization(HttpServletRequest request, String orderCode);
+    void validateAuthorization(HttpServletRequest request, String orderCode, String corpType);
 
     /**
      * 同步环思审批结果

+ 2 - 2
mjava-xintianlong/src/main/java/com/malk/xintianlong/service/impl/HSServiceImpl.java

@@ -29,11 +29,11 @@ public class HSServiceImpl implements HSService {
      * 校验调用授权
      */
     @Override
-    public void validateAuthorization(HttpServletRequest request, String orderCode) {
+    public void validateAuthorization(HttpServletRequest request, String orderCode, String corpType) {
         Map headers = UtilServlet.getHeaders(request);
         log.info("校验调用授权, {}", headers);
         McException.assertAccessException(!headers.containsKey("authorization") || !headers.get("authorization").equals(HSConf.ACCESS_TOKEN_DD), "未获得接口授权");
-        HSApproveRecordPo po = xtlApproveRecordDao.findByOrderCodeAndApproveResult(orderCode, "process");
+        HSApproveRecordPo po = xtlApproveRecordDao.findByOrderCodeAndApproveResultAndCorpType(orderCode, "process", corpType);
         McException.assertAccessException(ObjectUtil.isNotNull(po), "单据已在审批中, 请勿重复提交!");
     }
 

+ 35 - 16
mjava-xintianlong/src/main/resources/application-dev.yml

@@ -2,7 +2,7 @@
 server:
   port: 9001
   servlet:
-    context-path: /api
+    context-path: /api/xintianlong
 
 # condition
 spel:
@@ -11,29 +11,48 @@ spel:
 
 spring:
   # database
+  #  datasource:
+  #    driver-class-name: com.mysql.cj.jdbc.Driver
+  #    username: root
+  #    password: cp-root@2022++
+  #    url: jdbc:mysql://47.97.181.40:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+  #  jpa:
+  #    hibernate:
+  #      ddl-auto: none      # JPA对表没有任何操作
+  #    show-sql: true
+  #    database: MYSQL
+  #    database-platform: org.hibernate.dialect.MySQLDialect
   datasource:
-    driver-class-name: com.mysql.cj.jdbc.Driver
-    username: root
-    password: mu123
-    url: jdbc:mysql://127.0.0.1:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+    driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
+    url: jdbc:sqlserver://122.224.41.74:4335;SelectMethod=cursor;DatabaseName=HSDyeingERP
+    username: dingding
+    password: dd12345678
+    hikari:
+      connection-init-sql:  # SqlServer若设置类型不一致, 需关闭才可连接
+  # JPA
   jpa:
+    database: sql_server
+    properties:
+      hibernate:
+        default_schema: dbo
     hibernate:
-      ddl-auto: none      # JPA对表没有任何操作
-    show-sql: true
-    database: MYSQL
-    database-platform: org.hibernate.dialect.MySQLDialect
+      ddl-auto: none
+      naming:
+        # 取消小驼峰到下划线映射
+        implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
+        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
 
 # filepath
 file:
   path:
-    file: /Users/malk/service/_Tool/var/mjava/tmp//file/
-    image: /Users/malk/service/_Tool/var/mjava/tmp//image/
-    tmp: /Users/malk/service/_Tool/var/mjava/tmp/
+    file: /Users/malk/server/_Tool/var/mjava/tmp//file/
+    image: /Users/malk/server/_Tool/var/mjava/tmp//image/
+    tmp: /Users/malk/server/_Tool/var/mjava/tmp/
   source:
-    fonts: /Users/malk/service/_Tool/fonts/simsun.ttc
+    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
 logging:
   file:
-    path: /Users/malk/service/_Tool/var/mjava/log
+    path: /Users/malk/server/_Tool/var/mjava/log
 
 # dingtalk
 dingtalk:
@@ -41,8 +60,8 @@ dingtalk:
   appKey: dingromjxexd1esgvwwg
   appSecret: AcStrL5bdw69gqeUfTQiFoBsgqisL2g-egzaKyID9Q7d85f_z9EkuTSS9Vse6zDb
   corpId: ding5e83ad92d917b47535c2f4657eb6378f
-  aesKey:
-  token:
+  aesKey: NgBOhTTp38RmPYs3gz7xBRHGNhwLHAv3tZntZ6He54F
+  token: yLQuiiYIBvrzN3tmOduDn
 
 # aliwork
 aliwork:

+ 33 - 11
mjava-xintianlong/src/main/resources/application-prod.yml

@@ -1,22 +1,44 @@
 # 环境配置
 server:
-  port: 9005
+  port: 9001
+  servlet:
+    context-path: /proxy/xintianlong
 
 # condition
 spel:
-  scheduling: true        # 定时任务是否执行
+  scheduling: false       # 定时任务是否执行
   multiSource: false      # 是否多数据源配置
 
 spring:
   # database
+  #  datasource:
+  #    driver-class-name: com.mysql.cj.jdbc.Driver
+  #    username: root
+  #    password: cp-root@2022++
+  #    url: jdbc:mysql://47.97.181.40:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+  #  jpa:
+  #    database: MYSQL
+  #    database-platform: org.hibernate.dialect.MySQL57Dialect
+  # sql_server
   datasource:
-    driver-class-name: com.mysql.cj.jdbc.Driver
-    username: root
-    password: cp-root@2022++
-    url: jdbc:mysql://47.97.181.40:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
-  jpa:
-    database: MYSQL
-    database-platform: org.hibernate.dialect.MySQL57Dialect
+    driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
+    url: jdbc:sqlserver://122.224.41.74:4335;SelectMethod=cursor;DatabaseName=HSDyeingERP
+    username: dingding
+    password: dd12345678
+    hikari:
+      connection-init-sql:  # SqlServer若设置类型不一致, 需关闭才可连接
+    # JPA
+    jpa:
+      database: sql_server
+      properties:
+        hibernate:
+          default_schema: dbo
+      hibernate:
+        ddl-auto: none
+        naming:
+          # 取消小驼峰到下划线映射
+          implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
+          physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
 
 # dingtalk
 dingtalk:
@@ -24,8 +46,8 @@ dingtalk:
   appKey: dingromjxexd1esgvwwg
   appSecret: AcStrL5bdw69gqeUfTQiFoBsgqisL2g-egzaKyID9Q7d85f_z9EkuTSS9Vse6zDb
   corpId: ding5e83ad92d917b47535c2f4657eb6378f
-  aesKey:
-  token:
+  aesKey: NgBOhTTp38RmPYs3gz7xBRHGNhwLHAv3tZntZ6He54F
+  token: yLQuiiYIBvrzN3tmOduDn
 
 # aliwork
 aliwork:

+ 55 - 0
mjava-xintianlong/src/test/resources/winsw.xml

@@ -0,0 +1,55 @@
+<!--
+  MIT License
+
+  Copyright (c) 2008-2020 Kohsuke Kawaguchi, Sun Microsystems, Inc., CloudBees,
+  Inc., Oleg Nenashev and other contributors
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction, including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all
+  copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+  SOFTWARE.
+-->
+
+<!--
+ This is an example of a minimal Windows Service Wrapper configuration, which includes only mandatory options.
+ 
+ This configuration file should be placed near the WinSW executable, the name should be the same.
+ E.g. for myapp.exe the configuration file name should be myapp.xml
+ 
+ You can find more information about the configuration options here: https://github.com/kohsuke/winsw/blob/master/doc/xmlConfigFile.md
+ Full example: https://github.com/kohsuke/winsw/blob/master/examples/sample-allOptions.xml
+-->
+
+<service>
+    <!-- 注册服务ID -->
+    <id>mjava</id>
+    <!-- 启动服务名称 -->
+    <name>mjava</name>
+    <!-- 对服务的描述 -->
+    <description>标准化后端接口, 自用脚手架封装</description>
+    <!-- 「jdk需要安装」启动的可执行文件:若未配置环境变量executable需要执行绝对路径 -->
+    <!-- <executable>java</executable> -->
+    <executable>C:\Program Files\DingTalkServer\jdk1.8.0_221\bin\java</executable>
+    <!-- Xmx256m 代表堆内存最大值为256MB -jar后面的是项目名 [-Dfile.encoding=UTF-8 Windows会乱码, 但Mac上VSCode正常] -->
+    <arguments>-Xms256m -Xmx256m -Dfile.encoding=UTF-8 -jar mjava-xintianlong.jar</arguments>
+    <!-- 服务的启动模式:默认Automatic -->
+    <startmode>Automatic</startmode>
+    <!-- 日志地址 -->
+    <logpath>%BASE%\ws</logpath>
+    <!-- 日志模式 -->
+    <logmode>rotate</logmode>
+</service>
+

+ 35 - 16
mjava-xintianlong/target/classes/application-dev.yml

@@ -2,7 +2,7 @@
 server:
   port: 9001
   servlet:
-    context-path: /api
+    context-path: /api/xintianlong
 
 # condition
 spel:
@@ -11,29 +11,48 @@ spel:
 
 spring:
   # database
+  #  datasource:
+  #    driver-class-name: com.mysql.cj.jdbc.Driver
+  #    username: root
+  #    password: cp-root@2022++
+  #    url: jdbc:mysql://47.97.181.40:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+  #  jpa:
+  #    hibernate:
+  #      ddl-auto: none      # JPA对表没有任何操作
+  #    show-sql: true
+  #    database: MYSQL
+  #    database-platform: org.hibernate.dialect.MySQLDialect
   datasource:
-    driver-class-name: com.mysql.cj.jdbc.Driver
-    username: root
-    password: mu123
-    url: jdbc:mysql://127.0.0.1:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+    driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
+    url: jdbc:sqlserver://122.224.41.74:4335;SelectMethod=cursor;DatabaseName=HSDyeingERP
+    username: dingding
+    password: dd12345678
+    hikari:
+      connection-init-sql:  # SqlServer若设置类型不一致, 需关闭才可连接
+  # JPA
   jpa:
+    database: sql_server
+    properties:
+      hibernate:
+        default_schema: dbo
     hibernate:
-      ddl-auto: none      # JPA对表没有任何操作
-    show-sql: true
-    database: MYSQL
-    database-platform: org.hibernate.dialect.MySQLDialect
+      ddl-auto: none
+      naming:
+        # 取消小驼峰到下划线映射
+        implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
+        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
 
 # filepath
 file:
   path:
-    file: /Users/malk/service/_Tool/var/mjava/tmp//file/
-    image: /Users/malk/service/_Tool/var/mjava/tmp//image/
-    tmp: /Users/malk/service/_Tool/var/mjava/tmp/
+    file: /Users/malk/server/_Tool/var/mjava/tmp//file/
+    image: /Users/malk/server/_Tool/var/mjava/tmp//image/
+    tmp: /Users/malk/server/_Tool/var/mjava/tmp/
   source:
-    fonts: /Users/malk/service/_Tool/fonts/simsun.ttc
+    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
 logging:
   file:
-    path: /Users/malk/service/_Tool/var/mjava/log
+    path: /Users/malk/server/_Tool/var/mjava/log
 
 # dingtalk
 dingtalk:
@@ -41,8 +60,8 @@ dingtalk:
   appKey: dingromjxexd1esgvwwg
   appSecret: AcStrL5bdw69gqeUfTQiFoBsgqisL2g-egzaKyID9Q7d85f_z9EkuTSS9Vse6zDb
   corpId: ding5e83ad92d917b47535c2f4657eb6378f
-  aesKey:
-  token:
+  aesKey: NgBOhTTp38RmPYs3gz7xBRHGNhwLHAv3tZntZ6He54F
+  token: yLQuiiYIBvrzN3tmOduDn
 
 # aliwork
 aliwork:

+ 33 - 11
mjava-xintianlong/target/classes/application-prod.yml

@@ -1,22 +1,44 @@
 # 环境配置
 server:
-  port: 9005
+  port: 9001
+  servlet:
+    context-path: /proxy/xintianlong
 
 # condition
 spel:
-  scheduling: true        # 定时任务是否执行
+  scheduling: false       # 定时任务是否执行
   multiSource: false      # 是否多数据源配置
 
 spring:
   # database
+  #  datasource:
+  #    driver-class-name: com.mysql.cj.jdbc.Driver
+  #    username: root
+  #    password: cp-root@2022++
+  #    url: jdbc:mysql://47.97.181.40:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+  #  jpa:
+  #    database: MYSQL
+  #    database-platform: org.hibernate.dialect.MySQL57Dialect
+  # sql_server
   datasource:
-    driver-class-name: com.mysql.cj.jdbc.Driver
-    username: root
-    password: cp-root@2022++
-    url: jdbc:mysql://47.97.181.40:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
-  jpa:
-    database: MYSQL
-    database-platform: org.hibernate.dialect.MySQL57Dialect
+    driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
+    url: jdbc:sqlserver://122.224.41.74:4335;SelectMethod=cursor;DatabaseName=HSDyeingERP
+    username: dingding
+    password: dd12345678
+    hikari:
+      connection-init-sql:  # SqlServer若设置类型不一致, 需关闭才可连接
+    # JPA
+    jpa:
+      database: sql_server
+      properties:
+        hibernate:
+          default_schema: dbo
+      hibernate:
+        ddl-auto: none
+        naming:
+          # 取消小驼峰到下划线映射
+          implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
+          physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
 
 # dingtalk
 dingtalk:
@@ -24,8 +46,8 @@ dingtalk:
   appKey: dingromjxexd1esgvwwg
   appSecret: AcStrL5bdw69gqeUfTQiFoBsgqisL2g-egzaKyID9Q7d85f_z9EkuTSS9Vse6zDb
   corpId: ding5e83ad92d917b47535c2f4657eb6378f
-  aesKey:
-  token:
+  aesKey: NgBOhTTp38RmPYs3gz7xBRHGNhwLHAv3tZntZ6He54F
+  token: yLQuiiYIBvrzN3tmOduDn
 
 # aliwork
 aliwork:

+ 62 - 0
mjava-xintianlong/target/generated-sources/java/com/malk/xintianlong/repository/entity/QHSApproveRecordPo.java

@@ -0,0 +1,62 @@
+package com.malk.xintianlong.repository.entity;
+
+import static com.querydsl.core.types.PathMetadataFactory.*;
+
+import com.querydsl.core.types.dsl.*;
+
+import com.querydsl.core.types.PathMetadata;
+import javax.annotation.Generated;
+import com.querydsl.core.types.Path;
+
+
+/**
+ * QHSApproveRecordPo is a Querydsl query type for HSApproveRecordPo
+ */
+@Generated("com.querydsl.codegen.EntitySerializer")
+public class QHSApproveRecordPo extends EntityPathBase<HSApproveRecordPo> {
+
+    private static final long serialVersionUID = 1830122090L;
+
+    public static final QHSApproveRecordPo hSApproveRecordPo = new QHSApproveRecordPo("hSApproveRecordPo");
+
+    public final com.malk.base.QBasePo _super = new com.malk.base.QBasePo(this);
+
+    public final StringPath approveResult = createString("approveResult");
+
+    public final StringPath corpType = createString("corpType");
+
+    //inherited
+    public final DateTimePath<java.util.Date> createTime = _super.createTime;
+
+    public final StringPath formType = createString("formType");
+
+    public final StringPath hsResponse = createString("hsResponse");
+
+    //inherited
+    public final NumberPath<Long> id = _super.id;
+
+    public final StringPath orderCode = createString("orderCode");
+
+    public final StringPath processInstanceId = createString("processInstanceId");
+
+    public final StringPath proposerCode = createString("proposerCode");
+
+    public final StringPath remark = createString("remark");
+
+    //inherited
+    public final DateTimePath<java.util.Date> updateTime = _super.updateTime;
+
+    public QHSApproveRecordPo(String variable) {
+        super(HSApproveRecordPo.class, forVariable(variable));
+    }
+
+    public QHSApproveRecordPo(Path<? extends HSApproveRecordPo> path) {
+        super(path.getType(), path.getMetadata());
+    }
+
+    public QHSApproveRecordPo(PathMetadata metadata) {
+        super(HSApproveRecordPo.class, metadata);
+    }
+
+}
+

+ 5 - 0
mjava-xintianlong/target/maven-archiver/pom.properties

@@ -0,0 +1,5 @@
+#Generated by Maven
+#Sat Jun 10 14:31:39 CST 2023
+version=1.0-SNAPSHOT
+groupId=com.malk
+artifactId=mjava-xintianlong

+ 0 - 0
mjava-xintianlong/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst


+ 12 - 0
mjava-xintianlong/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst

@@ -0,0 +1,12 @@
+/Users/malk/server/java-mcli-2/mjava-xintianlong/src/main/java/com/malk/xintianlong/repository/entity/HSApproveRecordPo.java
+/Users/malk/server/java-mcli-2/mjava-xintianlong/src/main/java/com/malk/xintianlong/schedule/HSScheduleTask.java
+/Users/malk/server/java-mcli-2/mjava-xintianlong/src/main/java/com/malk/xintianlong/server/HSConf.java
+/Users/malk/server/java-mcli-2/mjava-xintianlong/target/generated-sources/java/com/malk/xintianlong/repository/entity/QHSApproveRecordPo.java
+/Users/malk/server/java-mcli-2/mjava-xintianlong/src/main/java/com/malk/xintianlong/Boot.java
+/Users/malk/server/java-mcli-2/mjava-xintianlong/src/main/java/com/malk/xintianlong/repository/dao/HSViewDao.java
+/Users/malk/server/java-mcli-2/mjava-xintianlong/src/main/java/com/malk/xintianlong/repository/dao/HSApproveRecordDao.java
+/Users/malk/server/java-mcli-2/mjava-xintianlong/src/main/java/com/malk/xintianlong/controller/HSController.java
+/Users/malk/server/java-mcli-2/mjava-xintianlong/src/main/java/com/malk/xintianlong/delegate/DDDelegate.java
+/Users/malk/server/java-mcli-2/mjava-xintianlong/src/main/java/com/malk/xintianlong/controller/DDController.java
+/Users/malk/server/java-mcli-2/mjava-xintianlong/src/main/java/com/malk/xintianlong/service/impl/HSServiceImpl.java
+/Users/malk/server/java-mcli-2/mjava-xintianlong/src/main/java/com/malk/xintianlong/service/HSService.java

BIN
mjava-xintianlong/target/mjava-xintianlong.jar.original


+ 55 - 0
mjava-xintianlong/target/test-classes/winsw.xml

@@ -0,0 +1,55 @@
+<!--
+  MIT License
+
+  Copyright (c) 2008-2020 Kohsuke Kawaguchi, Sun Microsystems, Inc., CloudBees,
+  Inc., Oleg Nenashev and other contributors
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction, including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in all
+  copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+  SOFTWARE.
+-->
+
+<!--
+ This is an example of a minimal Windows Service Wrapper configuration, which includes only mandatory options.
+ 
+ This configuration file should be placed near the WinSW executable, the name should be the same.
+ E.g. for myapp.exe the configuration file name should be myapp.xml
+ 
+ You can find more information about the configuration options here: https://github.com/kohsuke/winsw/blob/master/doc/xmlConfigFile.md
+ Full example: https://github.com/kohsuke/winsw/blob/master/examples/sample-allOptions.xml
+-->
+
+<service>
+    <!-- 注册服务ID -->
+    <id>mjava</id>
+    <!-- 启动服务名称 -->
+    <name>mjava</name>
+    <!-- 对服务的描述 -->
+    <description>标准化后端接口, 自用脚手架封装</description>
+    <!-- 「jdk需要安装」启动的可执行文件:若未配置环境变量executable需要执行绝对路径 -->
+    <!-- <executable>java</executable> -->
+    <executable>C:\Program Files\DingTalkServer\jdk1.8.0_221\bin\java</executable>
+    <!-- Xmx256m 代表堆内存最大值为256MB -jar后面的是项目名 [-Dfile.encoding=UTF-8 Windows会乱码, 但Mac上VSCode正常] -->
+    <arguments>-Xms256m -Xmx256m -Dfile.encoding=UTF-8 -jar mjava-xintianlong.jar</arguments>
+    <!-- 服务的启动模式:默认Automatic -->
+    <startmode>Automatic</startmode>
+    <!-- 日志地址 -->
+    <logpath>%BASE%\ws</logpath>
+    <!-- 日志模式 -->
+    <logmode>rotate</logmode>
+</service>
+

+ 9 - 0
mjava/src/main/java/com/malk/Filter/CatchException.java

@@ -172,6 +172,15 @@ public class CatchException<T> {
         return McR.errorParam("返回JSON解析异常: " + e.getMessage());
     }
 
+    /**
+     * 反射未匹配到路径
+     */
+    @ExceptionHandler(ClassNotFoundException.class)
+    public McR ClassNotFoundException(ClassNotFoundException e) {
+        log.error(e.getMessage(), e);  // 记录错误日志
+        return McR.errorParam("反射未匹配到路径: " + e.getMessage());
+    }
+
     /**
      * 系统错误抛出
      * -

+ 8 - 3
mjava/src/main/java/com/malk/Util/UtilDateTime.java

@@ -4,7 +4,6 @@ import cn.hutool.core.util.ObjectUtil;
 import lombok.SneakyThrows;
 import org.apache.commons.lang3.StringUtils;
 
-import javax.annotation.Nullable;
 import java.text.SimpleDateFormat;
 import java.time.*;
 import java.time.format.DateTimeFormatter;
@@ -17,6 +16,7 @@ import java.util.Date;
  */
 public abstract class UtilDateTime {
 
+    // todo: 获取次日开启时间, 获取次日结束时间
     public final static String DATE_PATTERN = "yyyy-MM-dd";
     public final static String TIME_PATTERN = "HH:mm:ss";
     public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
@@ -55,11 +55,16 @@ public abstract class UtilDateTime {
         return dateTime.with(TemporalAdjusters.firstDayOfNextMonth());
     }
 
-    // 获取当天0点时间
-    public static LocalDateTime minLocalDateTime(@Nullable LocalDateTime dateTime) {
+    // 获取当天开始时间
+    public static LocalDateTime minLocalDateTime(LocalDateTime dateTime) {
         return LocalDateTime.of(dateTime.toLocalDate(), LocalTime.MIN);
     }
 
+    // 获取当天结束时间
+    public static LocalDateTime maxLocalDateTime(LocalDateTime dateTime) {
+        return LocalDateTime.of(dateTime.toLocalDate(), LocalTime.MAX);
+    }
+
     // 当前时间时间戳
     public static long getLocalDateTimeTimeStamp() {
         return LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();

+ 24 - 0
mjava/src/main/java/com/malk/Util/UtilFile.java

@@ -1,7 +1,9 @@
 package com.malk.Util;
 
 import javax.annotation.Nullable;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.io.FileInputStream;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 
@@ -22,4 +24,26 @@ public abstract class UtilFile {
         }
         return file;
     }
+
+    /**
+     * 文件转化为byte字节数组
+     */
+    public static byte[] fileConvertToByteArray(File file) {
+        byte[] data = null;
+        try {
+            FileInputStream fis = new FileInputStream(file);
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            int len;
+            byte[] buffer = new byte[1024];
+            while ((len = fis.read(buffer)) != -1) {
+                baos.write(buffer, 0, len);
+            }
+            data = baos.toByteArray();
+            fis.close();
+            baos.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return data;
+    }
 }

+ 99 - 36
mjava/src/main/java/com/malk/Util/UtilMap.java

@@ -1,45 +1,35 @@
 package com.malk.Util;
 
+import cn.hutool.core.util.ObjectUtil;
 import com.malk.server.common.McException;
+import org.apache.commons.lang3.StringUtils;
 
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Objects;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.function.BiConsumer;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.function.Predicate;
-
-public class UtilMap {
-
-    // 工具方法
-    public static Consumer<Object> consumerWithIndex(BiConsumer<Object, Integer> consumer) {
-        class Obj {
-            int i;
-        }
-        Obj obj = new Obj();
-        return t -> {
-            int index = obj.i++;
-            consumer.accept(t, index);
-        };
-    }
 
-    // 快速创建map
+public abstract class UtilMap {
+
+    /************* 快速创建map ************/
+
+    /**
+     * 快速创建map [key, Objects]
+     */
     public static Map<String, Object> map(String keys, Object... values) {
         String[] props = keys.split(", ");
         if (props.length != values.length) {
             McException.assertParamException_Null(keys);
         }
         Map<String, Object> map = new HashMap<>();
-        Arrays.stream(values).forEach(consumerWithIndex((item, index) -> {
+        Arrays.stream(values).forEach(UtilMc.consumerWithIndex((item, index) -> {
             map.put(props[index], item);
         }));
         return map;
     }
 
-    // 快速创建map
+    /**
+     * 快速创建map [key, Strings]
+     */
     public static Map<String, String> map(String keys, String values) {
         String[] props = keys.split(", ");
         String[] contents = values.split(", ");
@@ -47,13 +37,15 @@ public class UtilMap {
             McException.assertParamException_Null(keys);
         }
         Map<String, String> map = new HashMap<>();
-        Arrays.stream(contents).forEach(consumerWithIndex((item, index) -> {
+        Arrays.stream(contents).forEach(UtilMc.consumerWithIndex((item, index) -> {
             map.put(props[index], String.valueOf(item));
         }));
         return map;
     }
 
-    // 快速创建map
+    /**
+     * 快速创建map [保留skeys, 取值ckeys]
+     */
     public static Map<String, Object> map(String skeys, String ckeys, Map map) {
         String[] sprops = skeys.split(", ");
         String[] cprops = ckeys.split(", ");
@@ -61,25 +53,96 @@ public class UtilMap {
             McException.assertParamException_Null(skeys);
         }
         Map data = new HashMap();
-        Arrays.stream(cprops).forEach(consumerWithIndex((item, index) -> {
+        Arrays.stream(cprops).forEach(UtilMc.consumerWithIndex((item, index) -> {
             data.put(sprops[index], map.get(item));
         }));
         return data;
     }
 
-    // 快速创建map
-    public static Map<String, Object> map(String skeys, String ckeys, Map map, boolean isReserve) {
-        if (isReserve) {
-            map.putAll(map(skeys, ckeys, map));
-            return map;
+    /**
+     * 快速创建map [合并skeys, 取值ckeys]
+     */
+    public static void map(String skeys, String ckeys, Map sMap, Map cMap) {
+        sMap.putAll(map(skeys, ckeys, cMap));
+    }
+
+    /************* 赋值 ************/
+
+    /**
+     * 赋值 [为空对象, 字符串空null, 忽略]
+     */
+    public static Map put(Map data, String key, Object value) {
+        if (ObjectUtil.isNull(data)) {
+            data = new HashMap();
+        }
+        if (ObjectUtil.isNotNull(value)) {
+            data.put(key, value);
+        }
+        return data;
+    }
+
+    /************* 赋值 ************/
+
+    /**
+     * 取值 [String.valueOf 避免空指针]
+     */
+    public static String getString(Map data, String key) {
+        if (data.containsKey(key)) {
+            return String.valueOf(data.get(key));
         }
-        return map(skeys, ckeys, map);
+        return "";
     }
 
-    // distinctByKey: 从人员列表中过滤出一个子集(每个部门选一个人) employees.stream().filter(distinctByKey(Employee::getDeptCode)).collect(toList());
-    public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
-        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
-        return t -> Objects.isNull(seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE));
+    /**
+     * 取值 [转为 long]
+     */
+    public static long getLong(Map data, String key) {
+        McException.assertParamException_Null(data, key);
+        return Long.valueOf(getString(data, key));
     }
 
+    /**
+     * 取值 [转为 int]
+     */
+    public static int getInt(Map data, String key) {
+        return Integer.valueOf(getString(data, key));
+    }
+
+    /**
+     * 取值 [为空返回默认值]
+     */
+    public static Object get(Map data, String key, Object defaultValue) {
+        Object value = data.get(key);
+        if (ObjectUtil.isNull(value)) {
+            return defaultValue;
+        }
+        return value;
+    }
+
+    /**
+     * 取值 [为空返回默认字符串]
+     */
+    public static String getString(Map data, String key, String defaultValue) {
+        String value = getString(data, key);
+        if (StringUtils.isBlank(value)) {
+            return defaultValue;
+        }
+        return value;
+    }
+
+    /************* 判定 ************/
+
+    /**
+     * 是否空字符串
+     */
+    public static boolean isBlankString(Map data, String key) {
+        return StringUtils.isBlank(getString(data, key));
+    }
+
+    /**
+     * 是否不为空字符串
+     */
+    public static boolean isNotBlankString(Map data, String key) {
+        return StringUtils.isNotBlank(getString(data, key));
+    }
 }

+ 41 - 0
mjava/src/main/java/com/malk/Util/UtilMc.java

@@ -0,0 +1,41 @@
+package com.malk.Util;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+public class UtilMc {
+
+    /**
+     * distinctByKey [SQL去重只能返回列, 不支持返回实体对象]
+     * -
+     * 成员列表去除重复userId
+     * 简写: poList.stream().filter(UtilMc.distinctByKey(XdDdApproveRecordPo::getOpenUserId)).collect(Collectors.toList())
+     * 展开: List<XdDdApproveRecordPo> poList = new ArrayList<>();
+     * poPage.getContent().stream().filter(UtilMc.distinctByKey(p -> p.getOpenUserId()))
+     * .forEach(poList::add);
+     * 打印: poList.forEach(System.out::println);
+     */
+    public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
+        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
+        return t -> Objects.isNull(seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE));
+    }
+
+    /**
+     * 工具方法 [forEach 索引]
+     */
+    public static Consumer<Object> consumerWithIndex(BiConsumer<Object, Integer> consumer) {
+        class Obj {
+            int i;
+        }
+        Obj obj = new Obj();
+        return t -> {
+            int index = obj.i++;
+            consumer.accept(t, index);
+        };
+    }
+}

+ 2 - 2
mjava/src/main/java/com/malk/base/BaseDao.java

@@ -7,14 +7,14 @@ import org.springframework.data.jpa.repository.JpaRepository;
  * @EntityListeners 且需要在启动类添加 @EnableJpaAuditing 注解, 即可在字段上添加 @CreatedDate & @LastModifiedDate 实现 [Date 类型数据 - 自动插入创建 & 更新时间]
  * -
  * 项目绑定数据库后,进行分配。即可消除@Table、 在 idea 下不能匹配到信息的报错提示
- * @Table指定表【下划线和小驼峰都可】, 若使用驼峰则依然会报错提示. 若类名从驼峰转为下划线和表名相同则可不需要注解
+ * @Table指定表【下划线和小驼峰都可】, 若使用驼峰则依然会报错提示. 若类名从驼峰转为下划线和表名相同则可不需要注解
  * -
  * 自定义查询
  * @Query 当设置nativeQuery=true即可以使用原生SQL进行查询, 默认为false, 使用JPQL语法 [JPQL不支持insert语法]
  * - 索引参数: 索引值从1开始,查询中"?X"个数需要与方法定义的参数个数相一致,并且顺序也要一致
  * - 命名参数: 可以定义好参数名,赋值时使用@Param("参数名"), 而不用管顺序. 对入参使用 @Param("email") 修饰, @Query内使用 :email 进行取值
  * - 关于返回值: update 语法, 返回值为 void. select 语法, 返回单个可用集合接收; 若返回多个用对象接收就会异常
- * @Modifying注解 编写JPQL实现DELETE和UPDATE操作的时候必须加上@modifying注解,以通知Spring Data 这是一个DELETE或UPDATE操作**
+ * @Modifying注解 编写JPQL实现DELETE和UPDATE操作的时候必须加上@modifying注解,以通知Spring Data 这是一个DELETE或UPDATE操作
  * -
  * 事务管理 @Transactional注解,可以修饰类或方法
  * - 配置 jpa.database-platform: org.hibernate.dialect.MySQL57Dialect, JPA建表的默认引擎修改为:InNoDB

+ 17 - 2
mjava/src/main/java/com/malk/base/BaseDto.java

@@ -31,7 +31,8 @@ import java.util.Set;
  * @Getter : 注在属性上,提供 get 方法
  * @EqualsAndHashCode : 注在类上,提供对应的 equals 和 hashCode 方法
  * @Log4j/@Slf4j : 注在类上,提供对应的 Logger 对象,变量名为 log
- * @Builder:为类生成相对略微复杂的构建器API。来初始化实例对象::类名.属性(值).属性(值).build() 9. @Singular:在使用@Singular注释注释一个集合字段(使用@Builder注释类),lombok会将该构建器节点视为一个集合,并生成两个adder方法而不是setter方法::点一次集合增加一个元素
+ * @Builder:为类生成相对略微复杂的构建器API。来初始化实例对象::类名.属性(值).属性(值).build()
+ * @Singular:在使用@Singular注释注释一个集合字段(使用@Builder注释类),lombok会将该构建器节点视为一个集合,并生成两个adder方法而不是setter方法::点一次集合增加一个元素
  * @Builder.Default:在类中id和insertTime上都添加注解@Builder.Default,当在使用这个实体对象时,就不需要在为这两个字段进行初始化值
  */
 @Data
@@ -51,7 +52,7 @@ public abstract class BaseDto {
     }
 
     /**
-     * * todo: 4.11 继承Serializable后执行深拷贝, 不能类型转换, 不继承Serializable则返回
+     * * todo: 4.11 继承Serializable后执行深拷贝, 不能类型转换, 不继承Serializable则返回
      * 对象拷贝: 复制一个新的对象, 避免条件被修改, 尤其并发下分页混乱情况
      */
     public BaseDto cloneParam() {
@@ -94,4 +95,18 @@ public abstract class BaseDto {
         }
         return formData;
     }
+
+
+    /**
+     * Map时间格式化, 直接从数据库取值后Map会有市区差, 方法1见BasePo, @Temporal & @JsonFormat 注解
+     * -
+     * [单独时间格式化 [废弃]]
+     * * JSON.parseArray(JSON.toJSONString(data), Map.class).stream().map(item -> {
+     * *     item.put("tStoreInTime", UtilDateTime.formatDateTime(new Date(UtilMap.getLong(item, "tStoreInTime"))));
+     * *     return item;
+     * * });
+     */
+    public static final Object jsonFormatDateTime(Object data) {
+        return JSON.parse(JSON.toJSONString(data, SerializerFeature.WriteNullStringAsEmpty, SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteDateUseDateFormat));
+    }
 }

+ 0 - 0
mjava/src/main/java/com/malk/base/BasePo.java


Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio