pruple_boy 2 år sedan
förälder
incheckning
7d6eb00f41
100 ändrade filer med 28986 tillägg och 15869 borttagningar
  1. 49 0
      mjava-cloudpure/src/main/java/com.malk.cloudpure/controller/DemoController.java
  2. 75 0
      mjava-cloudpure/src/main/java/com.malk.cloudpure/controller/FGGBase64.java
  3. 51 2
      mjava-cloudpure/src/main/java/com.malk.cloudpure/controller/XBBController.java
  4. 17 7
      mjava-cloudpure/src/main/resources/application-dev.yml
  5. 10 1
      mjava-cloudpure/src/main/resources/application-prod.yml
  6. 17 7
      mjava-cloudpure/target/classes/application-dev.yml
  7. 10 1
      mjava-cloudpure/target/classes/application-prod.yml
  8. 0 5
      mjava-cloudpure/target/maven-archiver/pom.properties
  9. 0 0
      mjava-cloudpure/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
  10. 0 2
      mjava-cloudpure/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
  11. BIN
      mjava-cloudpure/target/mjava-cloudpure.jar.original
  12. 5 0
      mjava-guyuan/pom.xml
  13. 153 24
      mjava-guyuan/src/main/java/com/malk/guyuan/controller/IVController.java
  14. 6 1
      mjava-guyuan/src/main/java/com/malk/guyuan/server/model/McInvoiceDto.java
  15. 3 0
      mjava-guyuan/src/main/java/com/malk/guyuan/server/model/McInvoiceKind.java
  16. 55 72
      mjava-guyuan/src/main/java/com/malk/guyuan/server/model/sample.md
  17. 2 0
      mjava-guyuan/src/main/java/com/malk/guyuan/server/tencent/TXYConf.java
  18. 11 4
      mjava-guyuan/src/main/java/com/malk/guyuan/service/tencent/TXYInvoice.java
  19. 37 10
      mjava-guyuan/src/main/java/com/malk/guyuan/service/tencent/impl/TXYImplInvoice.java
  20. 4 10
      mjava-guyuan/src/main/resources/application-dev.yml
  21. 0 2
      mjava-guyuan/src/main/resources/application-prod.yml
  22. 13853 7835
      mjava-guyuan/src/main/resources/static/mjs/mjs.js
  23. 1 1
      mjava-guyuan/src/main/resources/static/mjs/mjs.min.js
  24. 1 1
      mjava-guyuan/target/classes/META-INF/spring-configuration-metadata.json
  25. 4 10
      mjava-guyuan/target/classes/application-dev.yml
  26. 0 2
      mjava-guyuan/target/classes/application-prod.yml
  27. 13853 7835
      mjava-guyuan/target/classes/static/mjs/mjs.js
  28. 1 1
      mjava-guyuan/target/classes/static/mjs/mjs.min.js
  29. 0 3
      mjava-hangshi/src/main/java/com/malk/hangshi/Boot.java
  30. 5 5
      mjava-hangshi/src/main/resources/application-dev.yml
  31. 5 1
      mjava-hangshi/src/test/resources/server.sh
  32. 56 0
      mjava-hangshi/src/test/resources/winsw.xml
  33. 5 5
      mjava-hangshi/target/classes/application-dev.yml
  34. 5 1
      mjava-hangshi/target/test-classes/server.sh
  35. 1 1
      mjava-mcli/src/main/java/com/malk/mcli/test/JSPTestController.java
  36. 5 5
      mjava-mcli/src/main/resources/application-dev.yml
  37. 5 5
      mjava-mcli/target/classes/application-dev.yml
  38. 5 5
      mjava-suodisi/src/main/resources/application-dev.yml
  39. 5 5
      mjava-suodisi/target/classes/application-dev.yml
  40. 54 0
      mjava-zhuogao/pom.xml
  41. 29 0
      mjava-zhuogao/src/main/java/com/malk/zhuogao/Boot.java
  42. 137 0
      mjava-zhuogao/src/main/java/com/malk/zhuogao/controller/ZGController.java
  43. 18 0
      mjava-zhuogao/src/main/java/com/malk/zhuogao/repository/dao/ZSDFileRecordDao.java
  44. 158 0
      mjava-zhuogao/src/main/java/com/malk/zhuogao/repository/entity/ZSDFileRecordPo.java
  45. 39 0
      mjava-zhuogao/src/main/java/com/malk/zhuogao/schedule/ZSDcheduleTask.java
  46. 21 0
      mjava-zhuogao/src/main/java/com/malk/zhuogao/service/ZSDClient_File.java
  47. 104 0
      mjava-zhuogao/src/main/java/com/malk/zhuogao/service/impl/ZSDImplClient_File.java
  48. 48 0
      mjava-zhuogao/src/main/resources/application-dev.yml
  49. 33 0
      mjava-zhuogao/src/main/resources/application-prod.yml
  50. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/app.1e205474.css
  51. BIN
      mjava-zhuogao/src/main/resources/static/web/css/app.1e205474.css.gz
  52. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-020bde4f.8cd353de.css
  53. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-03803d04.d28c0d77.css
  54. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-09d432c5.08e92398.css
  55. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-0dc3c267.a04b5e6e.css
  56. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-13e18d6c.29149725.css
  57. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-16622649.5f788a64.css
  58. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-1ee91c18.2c5e6b95.css
  59. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-241c9cfc.2ad4aee4.css
  60. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-2b3d1d97.3e61a36e.css
  61. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-34786a36.9b156963.css
  62. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-35d77297.5dd7accd.css
  63. BIN
      mjava-zhuogao/src/main/resources/static/web/css/chunk-35d77297.5dd7accd.css.gz
  64. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-3f61e0f1.eef13e95.css
  65. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-4e109df4.b671580b.css
  66. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-5d241c38.e69d3699.css
  67. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-6279ca32.6c624d50.css
  68. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-65abd8c2.182cda6f.css
  69. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-6b83ef66.f91727df.css
  70. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-6d750ba2.b1127071.css
  71. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-723eb2cc.5ca1aba6.css
  72. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-767b9dea.7228e7cc.css
  73. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-87f1c134.0cd21f17.css
  74. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-b189ddd8.7a1576f4.css
  75. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-d773cad0.b7a55ecf.css
  76. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-de510a84.694e0ad8.css
  77. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/chunk-fd2bf652.2e6b27df.css
  78. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/npm.ant-design-vue.05a448c8.css
  79. BIN
      mjava-zhuogao/src/main/resources/static/web/css/npm.ant-design-vue.05a448c8.css.gz
  80. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/npm.element-ui.2fe571ab.css
  81. BIN
      mjava-zhuogao/src/main/resources/static/web/css/npm.element-ui.2fe571ab.css.gz
  82. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/npm.quasar.2415b056.css
  83. 1 0
      mjava-zhuogao/src/main/resources/static/web/css/npm.swiper.23437b54.css
  84. BIN
      mjava-zhuogao/src/main/resources/static/web/css/npm.swiper.23437b54.css.gz
  85. BIN
      mjava-zhuogao/src/main/resources/static/web/fonts/element-icons.535877f5.woff
  86. BIN
      mjava-zhuogao/src/main/resources/static/web/fonts/element-icons.732389de.ttf
  87. BIN
      mjava-zhuogao/src/main/resources/static/web/fonts/flUhRq6tzZclQEJ-Vdg-IuiaDsNa.29b882f0.woff
  88. BIN
      mjava-zhuogao/src/main/resources/static/web/img/+pk-select.472d7dee.png
  89. BIN
      mjava-zhuogao/src/main/resources/static/web/img/404.0a45bba9.jpg
  90. BIN
      mjava-zhuogao/src/main/resources/static/web/img/link.038ba0a1.png
  91. BIN
      mjava-zhuogao/src/main/resources/static/web/img/logo.a24f00e9.png
  92. BIN
      mjava-zhuogao/src/main/resources/static/web/img/look.68727e17.png
  93. BIN
      mjava-zhuogao/src/main/resources/static/web/img/no-data-pk.fc4bd766.png
  94. BIN
      mjava-zhuogao/src/main/resources/static/web/img/no-data-search.26341beb.png
  95. BIN
      mjava-zhuogao/src/main/resources/static/web/img/pk-relation.05ad7b4b.png
  96. BIN
      mjava-zhuogao/src/main/resources/static/web/img/player.a587f6e2.png
  97. BIN
      mjava-zhuogao/src/main/resources/static/web/img/reset.e99a88b6.png
  98. BIN
      mjava-zhuogao/src/main/resources/static/web/img/search-to.c3c08449.png
  99. BIN
      mjava-zhuogao/src/main/resources/static/web/img/selected.52f9c8b3.png
  100. 0 0
      mjava-zhuogao/src/main/resources/static/web/index.html

+ 49 - 0
mjava-cloudpure/src/main/java/com.malk.cloudpure/controller/DemoController.java

@@ -0,0 +1,49 @@
+package com.malk.cloudpure.controller;
+
+import com.malk.server.common.McR;
+import com.malk.service.xbongbong.XBBClient;
+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("demo")
+public class DemoController {
+
+    @Autowired
+    private XBBClient xbbClient;
+
+    @PostMapping("test")
+    McR test() {
+
+        String SecretId = "AKIDcpy2c3np0dp8gv7k4590uneCsU6m9sdwf7N9";
+        String SecretKey = "cSm8vEkLTgd7a9GKUAohC60C9UgFq0i4UwYzg9Lj";
+        String source = "fagougou";
+
+        String auth = "hmac id=\"" + SecretId +
+                "\", algorithm=\"hmac-sha1\", headers=\"x-date source\", signature=\"";
+//        var signStr = "x-date: " + dateTime + "\n" + "source: " + source;
+//        Map headers = UtilMap.map("Source, X-Date, Authorization", "fagougou", new Date().toGMTString(), );
+
+
+//        UtilHttp.doUpload("https://open.fagougou.com/release/api/contract-compare/auth/upload", headers, )
+
+//        return McR.success(xbbClient.getFormDefine(1003094, 0)); // 钉钉 864836 tb 1003094
+        return McR.success(xbbClient.getFormList("", 1, 100));
+//        return McR.success(likeCusterList("钉钉客户", "计算机", "16808499470903077"));
+
+//        return McR.success(xbbClient.getFormList("", 1, 601));
+//        return McR.success(xbbClient.getFormDefine(864840, 0));
+
+    }
+
+
+}
+
+

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 75 - 0
mjava-cloudpure/src/main/java/com.malk.cloudpure/controller/FGGBase64.java


+ 51 - 2
mjava-cloudpure/src/main/java/com.malk.cloudpure/controller/XBBController.java

@@ -1,13 +1,24 @@
 package com.malk.cloudpure.controller;
 
+import com.alibaba.fastjson.JSON;
+import com.malk.server.common.McException;
 import com.malk.server.common.McR;
+import com.malk.server.xbongbong.XBBConf;
 import com.malk.service.xbongbong.XBBClient;
+import com.malk.utils.UtilMap;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
 /**
  * 错误抛出与拦截详见 CatchException
  */
@@ -21,10 +32,48 @@ public class XBBController {
 
     @PostMapping("test")
     McR test() {
+//        return McR.success(xbbClient.getFormDefine(1003094, 0)); // 钉钉 864836 tb 1003094
+        return McR.success(xbbClient.getFormList("", 1, 100));
+//        return McR.success(likeCusterList("钉钉客户", "计算机", "16808499470903077"));
+
+//        return McR.success(xbbClient.getFormList("", 1, 601));
+//        return McR.success(xbbClient.getFormDefine(864840, 0));
+
+    }
+
 
-        xbbClient.getAccessToken(null);
+    /**
+     * 模糊查询归属权限下客户列表
+     */
+    @PostMapping("list/customer")
+    McR customerList(@RequestBody Map<String, String> data) {
+
+        log.info("客户列表, {}", data);
+        McException.assertParamException_Null(data, "name, userId");
+
+        List<Map> customers = new ArrayList<>();
+        customers.addAll(likeCusterList("钉钉客户", data.get("name"), data.get("userId")));
+        customers.addAll(likeCusterList("Teambition客户", data.get("name"), data.get("userId")));
+
+        log.info("客户响应, {}", customers);
+        return McR.success(customers);
+    }
 
-        return McR.success();
+    /**
+     * 模糊查询归属权限下客户列表
+     */
+    private List<Map> likeCusterList(String type, String name, String userId) {
+        List<Map> rsp = xbbClient.getFormList(type, 1, 100); // 客户表单: 钉钉 864836 tb 1003094
+        long formId = UtilMap.getLong(rsp.get(0), "formId");
+        rsp = xbbClient.getFormDefine(formId, 0); // 表单定义
+        String nameField = (rsp.stream().filter(item -> item.get("attrName").equals("客户名称")).findAny().get()).get("attr").toString();
+        rsp = xbbClient.getCustomerList(formId, Arrays.asList(XBBConf.getConditionMap(nameField, "like", name)), null);
+        return rsp.stream().filter(item -> {
+            List<String> ownerId = (List<String>) JSON.parse(String.valueOf(((Map) item.get("data")).get("ownerId")));
+            List<String> coUserId = (List<String>) JSON.parse(String.valueOf(((Map) item.get("data")).get("coUserId")));
+            // 后置查询, 属于客户负责人和协同人
+            return ownerId.contains(userId) || coUserId.contains(userId);
+        }).map(item -> UtilMap.map("name", String.valueOf(((Map) item.get("data")).get(nameField)))).collect(Collectors.toList());  // 客户名称
     }
 }
 

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

@@ -2,7 +2,7 @@
 server:
   port: 9001
   servlet:
-    context-path: /api/suodisi
+    context-path: /api/cloudpure
 
 # condition
 spel:
@@ -18,6 +18,16 @@ spring:
     username: root
     password: mu123
     url: jdbc:mysql://127.0.0.1:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+    # 主库
+    primary:
+      username: root
+      password: mu123
+      jdbc-url: jdbc:mysql://127.0.0.1:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+    # 从库
+    slave:
+      username: root
+      password: mu123
+      jdbc-url: jdbc:mysql://127.0.0.1:3306/mjava_slave?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
   jpa:
     hibernate:
       ddl-auto: none      # JPA对表没有任何操作
@@ -28,14 +38,14 @@ spring:
 # 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/
+    file: /Users/zhuogao/server/_Tool/var/mjava/tmp/file/
+    image: /Users/zhuogao/server/_Tool/var/mjava/tmp/image/
+    tmp: /Users/zhuogao/server/_Tool/var/mjava/tmp/
   source:
-    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
+    fonts: /Users/zhuogao/server/_Tool/fonts/simsun.ttc
 logging:
   file:
-    path: /Users/malk/server/_Tool/var/mjava/log
+    path: /Users/zhuogao/server/_Tool/var/mjava/log
 
 # dingtalk
 dingtalk:
@@ -56,7 +66,7 @@ aliwork:
 xbongbong:
   corpid: dingcc1b1ffad0d5ca1d
   token: f760ea3d154e45c839b2169f09b76f23
-  userId: 102314374732747224
+  userId: 102314374732747224 # 汐瑶
   callbackToken:
 
 

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

@@ -1,6 +1,8 @@
 # 环境配置
 server:
   port: 9011
+  servlet:
+    context-path: /api/cloudpure
 
 # condition
 spel:
@@ -33,4 +35,11 @@ dingtalk:
 # aliwork
 aliwork:
   appType: APP_YH7W0E5637YUBU5UJ837
-  systemToken: IC766WA11EW8BMOPBEZZMBA4MPUQ214JDL7FLC9
+  systemToken: IC766WA11EW8BMOPBEZZMBA4MPUQ214JDL7FLC9
+
+# xbongbong
+xbongbong:
+  corpid: dingcc1b1ffad0d5ca1d
+  token: f760ea3d154e45c839b2169f09b76f23
+  userId: 102314374732747224 # 汐瑶
+  callbackToken:

+ 17 - 7
mjava-cloudpure/target/classes/application-dev.yml

@@ -2,7 +2,7 @@
 server:
   port: 9001
   servlet:
-    context-path: /api/suodisi
+    context-path: /api/cloudpure
 
 # condition
 spel:
@@ -18,6 +18,16 @@ spring:
     username: root
     password: mu123
     url: jdbc:mysql://127.0.0.1:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+    # 主库
+    primary:
+      username: root
+      password: mu123
+      jdbc-url: jdbc:mysql://127.0.0.1:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+    # 从库
+    slave:
+      username: root
+      password: mu123
+      jdbc-url: jdbc:mysql://127.0.0.1:3306/mjava_slave?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
   jpa:
     hibernate:
       ddl-auto: none      # JPA对表没有任何操作
@@ -28,14 +38,14 @@ spring:
 # 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/
+    file: /Users/zhuogao/server/_Tool/var/mjava/tmp/file/
+    image: /Users/zhuogao/server/_Tool/var/mjava/tmp/image/
+    tmp: /Users/zhuogao/server/_Tool/var/mjava/tmp/
   source:
-    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
+    fonts: /Users/zhuogao/server/_Tool/fonts/simsun.ttc
 logging:
   file:
-    path: /Users/malk/server/_Tool/var/mjava/log
+    path: /Users/zhuogao/server/_Tool/var/mjava/log
 
 # dingtalk
 dingtalk:
@@ -56,7 +66,7 @@ aliwork:
 xbongbong:
   corpid: dingcc1b1ffad0d5ca1d
   token: f760ea3d154e45c839b2169f09b76f23
-  userId: 102314374732747224
+  userId: 102314374732747224 # 汐瑶
   callbackToken:
 
 

+ 10 - 1
mjava-cloudpure/target/classes/application-prod.yml

@@ -1,6 +1,8 @@
 # 环境配置
 server:
   port: 9011
+  servlet:
+    context-path: /api/cloudpure
 
 # condition
 spel:
@@ -33,4 +35,11 @@ dingtalk:
 # aliwork
 aliwork:
   appType: APP_YH7W0E5637YUBU5UJ837
-  systemToken: IC766WA11EW8BMOPBEZZMBA4MPUQ214JDL7FLC9
+  systemToken: IC766WA11EW8BMOPBEZZMBA4MPUQ214JDL7FLC9
+
+# xbongbong
+xbongbong:
+  corpid: dingcc1b1ffad0d5ca1d
+  token: f760ea3d154e45c839b2169f09b76f23
+  userId: 102314374732747224 # 汐瑶
+  callbackToken:

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

@@ -1,5 +0,0 @@
-#Generated by Maven
-#Fri Jun 23 15:57:38 CST 2023
-version=1.0-SNAPSHOT
-groupId=com.malk
-artifactId=mjava-cloudpure

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


+ 0 - 2
mjava-cloudpure/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst

@@ -1,2 +0,0 @@
-/Users/malk/server/java-mcli-3/mjava-cloudpure/src/main/java/com.malk.cloudpure/Boot.java
-/Users/malk/server/java-mcli-3/mjava-cloudpure/src/main/java/com.malk.cloudpure/controller/XBBController.java

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


+ 5 - 0
mjava-guyuan/pom.xml

@@ -29,6 +29,11 @@
             <groupId>com.tencentcloudapi</groupId>
             <artifactId>tencentcloud-sdk-java</artifactId>
         </dependency>
+        <dependency>
+            <groupId>net.coobird</groupId>
+            <artifactId>thumbnailator</artifactId>
+            <version>0.4.8</version>
+        </dependency>
     </dependencies>
 
     <build>

+ 153 - 24
mjava-guyuan/src/main/java/com/malk/guyuan/controller/IVController.java

@@ -10,22 +10,25 @@ import com.malk.server.aliwork.YDParam;
 import com.malk.server.common.McException;
 import com.malk.server.common.McR;
 import com.malk.service.aliwork.YDClient;
-import com.malk.utils.UtilMap;
-import com.malk.utils.UtilMc;
-import com.malk.utils.UtilNumber;
+import com.malk.utils.*;
 import com.tencentcloudapi.common.exception.TencentCloudSDKException;
+import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
+import net.coobird.thumbnailator.Thumbnails;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.util.IOUtils;
 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.math.BigDecimal;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
+import javax.servlet.http.HttpServletRequest;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -43,6 +46,7 @@ public class IVController {
     @Autowired
     private YDClient ydClient;
 
+    /// 优先获取字段, 新版本接口已支持字段返回
     private String findValue(List<Map<String, String>> infos, String... names) {
         for (String name : names) {
             Optional optional = infos.stream().filter(info -> info.get("Name").equals(name)).findAny();
@@ -53,30 +57,79 @@ public class IVController {
         return "";
     }
 
+    // 兼容历史配置, 格式 (谷元)
+    private String guyuanNameRepalce(String name) {
+        if (name.contains("谷元")) {
+            return UtilString.replaceBracketIsWhole(name);
+        } else {
+            return UtilString.replaceBracketIsSemiangle(name);
+        }
+    }
+
+    /// url压缩转base64
+    @SneakyThrows
+    private String imageUrlConvertBase64(String imageUrl) {
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        // scale(比例), outputQuality(质量)
+        Thumbnails.fromURLs(Arrays.asList(new URL(imageUrl))).scale(0.5f).outputQuality(0.25f).toOutputStream(out);
+        InputStream inputStream = new ByteArrayInputStream(out.toByteArray());
+        //转换为base64
+        byte[] bytes = IOUtils.toByteArray(inputStream);
+        return Base64.getEncoder().encodeToString(bytes);
+    }
+
+    // prd 校验发票抬头, 购买方范围
+    private void validateBuyer(String BuyerName, String tips) {
+        List<String> corpNames = Arrays.asList(
+                "谷元(上海)文化科技有限责任公司",
+                "上海爱鱼文化传媒有限公司",
+                "上海渔米可禧文化传媒有限公司",
+                "上海巧豆文化传媒有限公司",
+                "钰鸿文化创意(上海)有限公司",
+                "上海攸元文化科技有限公司",
+                "上海盈田演出经纪有限公司",
+                "上海小蝠文化科技有限公司",
+                "沐田居海(厦门)文化传媒有限公司",
+                "北京元环文化科技有限责任公司",
+                "厦门攸元文化科技有限公司",
+                "厦门亨有文化科技有限公司",
+                "厦门银雀思汀文化传媒有限公司",
+                "上海渝泽信息科技有限公司",
+                "厦门神谷飞流影视传媒有限公司",
+                "厦门谷钛数字科技有限公司",
+                "上海观情科技有限公司");
+        McException.assertAccessException(!corpNames.contains(BuyerName), tips + ", 购买方名称不合法!");
+    }
+
     /**
-     * 混票识别
+     * 混票识别 [旧版]
      */
     @PostMapping("invoice-iv")
     McR invoice_iv(@RequestBody Map<String, String> data) throws TencentCloudSDKException {
 
         McException.assertParamException_Null(data, "url");
-        String imageUrl = ydClient.convertTemporaryUrl(data.get("url"));
-        log.info("混票识别, 免登地址, {}", imageUrl);
-
+        String image = ydClient.convertTemporaryUrl(data.get("url"));
+        log.info("混票识别, 免登地址, {}", image);
+        // 非PDF, 且内存大于3M, 压缩后上传
+        if (!UtilMap.getBoolean(data, "isPdf") && UtilMap.getFloat(data, "size") > 3.0f) {
+            image = imageUrlConvertBase64(image);
+        }
         // ppExt: 通用字段定义
-        List<Map> invoices = (List<Map>) txyInvoice.doMixedInvoiceOCR(imageUrl).get("MixedInvoiceItems");
+        List<Map> invoices = (List<Map>) txyInvoice.doMixedInvoiceOCR(image).get("MixedInvoiceItems");
         List<McInvoiceDto> result = invoices.stream().map(item -> {
             String kind = TXYConf.TYPE_INVOICE.get(item.get("Type").toString());
             List<Map<String, String>> infos = (List<Map<String, String>>) item.get("SingleInvoiceInfos");
 
             McInvoiceDto.assertSuccess(item, kind); // 响应断言
-
             String invoiceName = findValue(infos, "发票名称");
             if (kind.equals("全电发票")) {
-                kind = invoiceName.contains("增值税专用发票") ? "增值税电子专用发票" : "增值税电子普通发票";
+                kind = invoiceName.contains("增值税专用发票") ? "全电专用发票" : "全电普通发票";
             }
             if (kind.equals("增值税发票")) {
                 kind = invoiceName.contains("增值税专用发票") ? "增值税专用发票" : "增值税普通发票";
+                if (invoiceName.contains("增值税电子")) {
+                    kind = invoiceName.contains("专用发票") ? "增值税电子专用发票" : "增值税电子普通发票";
+                }
             }
             McInvoiceDto invoiceDto = McInvoiceDto.builder()
                     .name(invoiceName)
@@ -87,11 +140,12 @@ public class IVController {
                     .serial(findValue(infos, "发票号码", "编号", "电子客票号码", "票据号码").replace("No", "")) // 发票, 非税发票
                     .date(findValue(infos, "开票日期").replace("年", "-").replace("月", "-").replace("日", ""))
                     .checkCode(findValue(infos, "校验码"))
-                    .amount(new BigDecimal(UtilNumber.replaceCurrencyCHY(findValue(infos, "小写金额", "价税合计(小写)", "合计金额", "票价", "金额")))) // 发票, 全电票, 行程单, 火车票, 过路过桥费
-                    .excludingTax(new BigDecimal(findValue(infos, "金额", "票价", "小写金额"))) // 行程单, 火车票, 定额发票
-                    .buyerName(findValue(infos, "购买方名称", "交款人")) // 发票, 非税发票
+                    .amount(UtilNumber.replaceCurrencyCHYToDecimal(findValue(infos, "小写金额", "价税合计(小写)", "合计金额", "票价", "金额"))) // 发票, 全电票, 行程单, 火车票, 过路过桥费
+                    .excludingTax(UtilNumber.replaceCurrencyCHYToDecimal(findValue(infos, "合计金额", "金额", "票价", "小写金额"))) // [ppExt: 多明细行时, 优先取值合计] 行程单, 火车票, 定额发票
+                    .tax(UtilNumber.replaceCurrencyCHYToDecimal(findValue(infos, "合计税额"))) // 增值税发票
+                    .buyerName(guyuanNameRepalce(findValue(infos, "购买方名称", "交款人"))) // 发票, 非税发票
                     .buyerTaxId(findValue(infos, "购买方识别号", "购买方统一社会信用代码/纳税人识别号", "交款人统一社会信用代码")) // 发票, 全电票, 非税发票
-                    .sellerName(findValue(infos, "销售方名称", "填开单位")) // 行程单
+                    .sellerName(guyuanNameRepalce(findValue(infos, "销售方名称", "填开单位"))) // 行程单
                     .sellerTaxId(findValue(infos, "销售方识别号", "销售方统一社会信用代码/纳税人识别号", "销售单位代号")) // 发票, 全电票, 行程单
                     .passengerName(findValue(infos, "旅客姓名", "姓名")) // 行程单, 火车票
                     .seatType(findValue(infos, "座位等级", "席别")) // 行程单, 火车票
@@ -136,6 +190,7 @@ public class IVController {
             String invoiceNo = dto.getSerial(); // 唯一标识, 发票号码
 
             String serial = "第【" + (index + 1) + "】张发票";
+            validateBuyer(dto.getBuyerName(), serial + "有疑问");
             McException.assertAccessException(StringUtils.isBlank(invoiceNo), serial + ", 识别结果为空, 请检查!");
             YDParam ydParam = YDParam.builder()
                     .formUuid("FORM-W2A66Z910O9B3LP9C6IYUDPRVWY62DO0YHIILY")
@@ -147,20 +202,94 @@ public class IVController {
             }
             // prd 仅仅识别增值税普通发票
             if (dto.getKindName().contains("普通发票")) {
+                String serialTips = serial + "有疑问";
                 try {
                     // ppExt: 识别与验真后抬头对比
-                    Map rsp = txyInvoice.VatInvoiceVerifyNew(dto.getKindName(), dto.getCode(), invoiceNo, dto.getDate(), String.valueOf(dto.getAmount()), dto.getCheckCode(), String.valueOf(dto.getExcludingTax()));
+                    Map rsp = txyInvoice.VatInvoiceVerifyNew(dto.getKindName(), dto.getCode(), invoiceNo, dto.getDate(), String.valueOf(dto.getAmount()), dto.getCheckCode(), String.valueOf(dto.getExcludingTax()), serialTips);
                     Map invoice = (Map) rsp.get("Invoice");
-                    McException.assertAccessException(!dto.getBuyerName().equals(invoice.get("BuyerName")), "发票有疑问, 购买方名称不匹配!");
-                    McException.assertAccessException(!dto.getBuyerTaxId().equals(invoice.get("BuyerTaxCode")), "发票有疑问, 购买方税号不匹配!");
-                    McException.assertAccessException(!dto.getSellerName().equals(invoice.get("SellerName")), "发票有疑问, 销售方名称不匹配!");
-                    McException.assertAccessException(!dto.getSellerTaxId().equals(invoice.get("SellerTaxCode")), "发票有疑问, 销售方税号不匹配!");
+                    McException.assertAccessException(!dto.getBuyerName().equals(guyuanNameRepalce(invoice.get("BuyerName").toString())), serialTips + ", 购买方名称不匹配!");
+                    McException.assertAccessException(!dto.getBuyerTaxId().equals(invoice.get("BuyerTaxCode")), serialTips + ", 购买方税号不匹配!");
+                    McException.assertAccessException(!dto.getSellerName().equals(guyuanNameRepalce(invoice.get("SellerName").toString())), serialTips + ", 销售方名称不匹配!");
+                    McException.assertAccessException(!dto.getSellerTaxId().equals(invoice.get("SellerTaxCode")), serialTips + ", 销售方税号不匹配!");
                 } catch (TencentCloudSDKException e) {
-                    McException.exceptionAccess(serial + e.getMessage());
+                    log.error(e.getMessage(), e);
+                    // prd: 上传发票为假发票时,提示:该发票有疑问,请联系财务人员
+                    String message = e.getMessage();
+                    if (message.contains("发票不存在")) {
+                        message = "有疑问,请联系财务人员";
+                    }
+                    McException.exceptionAccess(serial + message);
                 }
             }
         }));
 
         return McR.success("发票查重, 验真响应");
     }
+
+    /**
+     * 发票状态更新: 服务注册 // todo 通用服务, { 组件Id: 值, 组件id: 值 }
+     */
+    @PostMapping("invoice-up")
+    McR invoice_va(HttpServletRequest request) {
+        Map data = UtilServlet.getParamMap(request);
+        log.info("发票状态更新: 服务注册, {}", data);
+
+        String compId = UtilMap.getString(data, "compId");
+        String status = UtilMap.getString(data, "status");
+
+        // 读取关联表单
+        List<String> associationForm = (List<String>) JSON.parse(UtilMap.getString(data, "multiAssociation"));
+        List<String> formInstanceIds = new ArrayList<>();
+        for (String record : associationForm) {
+            // 解析关联表单
+            List<Map> associationData = (List<Map>) JSON.parse(record);
+            formInstanceIds.addAll(associationData.stream().map(form -> UtilMap.getString(form, "instanceId")).collect(Collectors.toList()));
+        }
+        // 宜搭批量更新
+        Map update = UtilMap.map(compId, status);
+        if (compId.equals("selectField_liihyrt6")) {
+            update.put("radioField_liw7rb2q", "否"); // 提交后, 更新是否退回标识为否
+        }
+        ydClient.operateData(YDParam.builder()
+                .formUuid("FORM-W2A66Z910O9B3LP9C6IYUDPRVWY62DO0YHIILY")
+                .formInstanceIdList(formInstanceIds)
+                .updateFormDataJson(JSON.toJSONString(update))
+                .build(), YDConf.FORM_OPERATION.multi_update);
+
+        return McR.success();
+    }
+
+    /**
+     * 发票状态更新: 退回提交
+     */
+    @PostMapping("invoice-zy")
+    McR invoice_zy(@RequestBody Map data) {
+        log.info("发票状态更新: 退回提交, {}", data);
+
+        List<String> pre_ids = (List<String>) data.get("pre_ids"); // 释放修改前
+        List<String> cur_ids = (List<String>) data.get("cur_ids"); // 占用修改后
+
+        // [前端调用添加] 退回为监听宜搭dom事件, 先执行接口调用, 才会校验宜搭必填, 过滤无效调用
+        if (cur_ids.size() == 0) {
+            return McR.success();
+        }
+
+        Map pre_update = (Map) data.get("pre_update");
+        Map cur_update = (Map) data.get("cur_update");
+
+        // 宜搭批量更新
+        ydClient.operateData(YDParam.builder()
+                .formUuid("FORM-W2A66Z910O9B3LP9C6IYUDPRVWY62DO0YHIILY")
+                .formInstanceIdList(pre_ids)
+                .updateFormDataJson(JSON.toJSONString(pre_update))
+                .build(), YDConf.FORM_OPERATION.multi_update);
+
+        ydClient.operateData(YDParam.builder()
+                .formUuid("FORM-W2A66Z910O9B3LP9C6IYUDPRVWY62DO0YHIILY")
+                .formInstanceIdList(cur_ids)
+                .updateFormDataJson(JSON.toJSONString(cur_update))
+                .build(), YDConf.FORM_OPERATION.multi_update);
+
+        return McR.success();
+    }
 }

+ 6 - 1
mjava-guyuan/src/main/java/com/malk/guyuan/server/model/McInvoiceDto.java

@@ -75,6 +75,11 @@ public class McInvoiceDto extends BaseDto {
      */
     private BigDecimal excludingTax;
 
+    /**
+     * 不含税金额
+     */
+    private BigDecimal tax;
+
     /**
      * 购买方名称
      */
@@ -156,7 +161,7 @@ public class McInvoiceDto extends BaseDto {
      */
     public static Map formatDtoLabelAndProp() {
 
-        Map data = UtilMap.map("发票名称, 发票类型, 发票代码, 发票号码, 开票日期, 校验码, 价税合计, 不含税金额", "name, kindName, code, serial, date, checkCode, amount, excludingTax");
+        Map data = UtilMap.map("发票名称, 发票类型, 发票代码, 发票号码, 开票日期, 校验码, 价税合计, 不含税金额, 税额", "name, kindName, code, serial, date, checkCode, amount, excludingTax, tax");
         data.putAll(UtilMap.map("购买方名称, 购买方税号, 销售方名称, 销售方税号", "buyerName, buyerTaxId, sellerName, sellerTaxId"));
         data.putAll(UtilMap.map("乘客姓名, 座位类型, 出发地, 到达地, 出发时间, 车次编号/航班号, 保险费, 燃油附加费, 民航发展基金", "passengerName, seatType, departurePort, arrivePort, departureTime, trainNo, insuranceCosts, fuelCosts, constructionCosts"));
         return data;

+ 3 - 0
mjava-guyuan/src/main/java/com/malk/guyuan/server/model/McInvoiceKind.java

@@ -16,6 +16,8 @@ public enum McInvoiceKind {
     ZP("增值税专用发票", 2),
     DP("增值税电子普通发票", 3),
     DZ("增值税电子专用发票", 4),
+    QP("全电普通发票", 5),
+    QZ("全电专用发票", 6),
 
     HC("火车票", 11),
     JP("机票行程单", 12),
@@ -49,6 +51,7 @@ public enum McInvoiceKind {
      */
     public final static int getKindCode(String name) {
         Optional optional = Arrays.stream(McInvoiceKind.values()).filter(item -> item.desc.equals(name)).findAny();
+        //log.info("发票类型, {}", Arrays.stream(McInvoiceKind.values()).map(item -> item.desc).collect(Collectors.toList()));
         if (optional.isPresent()) {
             return ((McInvoiceKind) optional.get()).code;
         }

+ 55 - 72
mjava-guyuan/src/main/java/com/malk/guyuan/server/model/sample.md

@@ -1,80 +1,62 @@
-## 上传发票
+## 退回处理
 
 ```
-/*** mc 系列之 mjs
- * 对接宜搭公共JavaScript库
- * 公共库地址:https://mc.cloudpure.cn/mjs/mjs.min.js
- ***/
-export function _mjsLoad() {
-  // const src = "https://mc.cloudpure.cn/mjs/mjs.min.js"
-  // const src = "http://127.0.0.1:7001/dist/mjs.js"
-  const src = "https://mc.cloudpure.cn/api/guyuan/mjs/mjs.min.js"
-  const script = document.createElement('script');
-  script.type = 'text/javascript';
-  script.src = src;
-  script.addEventListener('load', () => this._mjsInit(), false);
-  document.head.appendChild(script);
-};
-
-//---------------------- private ----------------------//
-
-// 加载即调用方法请在此处进行调用
-export async function _mjsInit() {
-  await mjs.init(this, { vconsole: false })
-  // 页面环境:0提交(其它),1查看,2编辑(审批)
-  if (mjs.env) { }
-}
-
-
-//---------------------- event ----------------------//
-
-// 页面节点加载渲染完毕
-export function didMount() {
-  // 工具库: mjs & 初始化
-  this._mjsLoad();
-}
-
-// 发票上传
-export function onSuccess(file, value) {
-  mjs.corp.guyuan.mixedInvoice(file.url)
-}
-
-// 发票移除
-export function onRemove(file) {
-  this.$('tableField_liv5f4d2').setValue([]);
-}
-
-// 发票查重、验真
-export function beforeSubmit({ formDataMap }) {
-  return mjs.corp.guyuan.batchCheck()
-}
-```
-
-## 发票夹
-
-```
-/*** mc 系列之 mjs
- * 对接宜搭公共JavaScript库
- * 公共库地址:https://mc.cloudpure.cn/mjs/mjs.min.js
- ***/
-export function _mjsLoad() {
-  // const src = "https://mc.cloudpure.cn/mjs/mjs.min.js"
-  // const src = "http://127.0.0.1:7001/dist/mjs.js"
-  const src = "https://mc.cloudpure.cn/api/guyuan/mjs/mjs.min.js"
-  const script = document.createElement('script');
-  script.type = 'text/javascript';
-  script.src = src;
-  script.addEventListener('load', () => this._mjsInit(), false);
-  document.head.appendChild(script);
-};
-
 //---------------------- private ----------------------//
 
 // 加载即调用方法请在此处进行调用
 export async function _mjsInit() {
   await mjs.init(this, { vconsole: false })
   // 页面环境:0提交(其它),1查看,2编辑(审批)
-  if (mjs.env) { }
+  if (mjs.env) {
+    // 记录修改前ids
+    mjs.pre_ids = this.$('tableField_krmybpq6').getValue().reduce((acc, cur) => {
+      acc.push(...cur.associationFormField_liya90jt.map(item => item.instanceId))
+      return acc;
+    }, [])
+    console.log("当前明细实例Ids", mjs.pre_ids);
+
+   }
+  // 价税合计,计算
+  function round(number, precision) {
+    return Math.round(+number + 'e' + precision) / Math.pow(10, precision);
+  }
+  mjs._calcTotal = mjs.optimize.debounce(() => {
+    const details = this.$('tableField_krmybpq6').getValue();
+    const total = details.reduce((acc, cur) => {
+      const count = (cur.associationFormField_liya90jt || []).reduce((sum, ass) => {
+        sum += Number(ass.subTitle)
+        return sum;
+      }, 0)
+      cur.numberField_krn4ig4x = round(count, 2);
+      acc += cur.numberField_krn4ig4x;
+      return acc;
+    }, 0)
+    this.$('numberField_krn54uoe').setValue(total)
+  }, 400)
+
+  // 退回点击事件注册 & 响应
+  mjs.bus.DOM_CALLBACK_APPROVE = async (_this, title) => {
+    console.log(_this, title, title == "提交")
+    if (title == "提交") {
+      const cur_ids = this.$('tableField_krmybpq6').getValue().reduce((acc, cur) => {
+        acc.push(...cur.associationFormField_liya90jt.map(item => item.instanceId))
+        return acc;
+      }, [])
+      // 接口处理: 释放修改删除的全部数据,占用重新提交的全部数据
+      mjs.request.xhr.doPost("https://mc.cloudpure.cn/frp/guyuan/invoice-zy", null, {
+        pre_ids: mjs.pre_ids,
+        pre_update: {
+          selectField_liihyrt6: "未使用",
+        },
+        cur_ids: cur_ids,
+        cur_update: {
+          selectField_liihyrt6: "已使用",
+          radioField_liw7rb2q: "否" // 提交后, 更新是否退回标识为否
+        }
+      })
+    }
+  }
+  mjs.dom.registerFlowEvent(this);
 }
 
 //---------------------- event ----------------------//
@@ -85,8 +67,9 @@ export function didMount() {
   this._mjsLoad();
 }
 
-// 发票查重、验真
-export function beforeSubmit({ formDataMap }) {
-  return mjs.corp.guyuan.validate()
+//子表分类求和
+export function onChange({ value, extra }) { 
+  // 价税合计,计算
+  mjs._calcTotal()
 }
 ```

+ 2 - 0
mjava-guyuan/src/main/java/com/malk/guyuan/server/tencent/TXYConf.java

@@ -25,6 +25,8 @@ public class TXYConf {
 
     /**
      * 票据类型
+     * -
+     * 中央非税未返回税号官方说明: 非税发票理论是没有税号的,图片中那个属于信用代码 [两个版本接口均为返回]
      */
     public static final Map<String, String> TYPE_INVOICE = UtilMap.map("-1, 0, 1, 2, 3, 5, 8, 9, 10, 11, 12, 13, 15, 16",
             "未知类型, 出租车发票, 定额发票, 火车票, 增值税发票, 机票行程单, 通用机打发票, 汽车票, 轮船票, 增值税发票(卷票) , 购车发票, 过路过桥费发票, 非税发票, 全电发票");

+ 11 - 4
mjava-guyuan/src/main/java/com/malk/guyuan/service/tencent/TXYInvoice.java

@@ -7,11 +7,18 @@ import java.util.Map;
 public interface TXYInvoice {
 
     /**
-     * 混贴票据识别
+     * 混贴票据识别 [将弃用, 直接返回识别数据, 官方停止更新]
      *
-     * @param imageUrl 图片不超过6m
+     * @param image 下载图片经Base64编码后不超过 7M。图片下载时间不超过 3 秒
      */
-    Map doMixedInvoiceOCR(String imageUrl) throws TencentCloudSDKException;
+    Map doMixedInvoiceOCR(String image) throws TencentCloudSDKException;
+
+    /**
+     * 通用票据识别(高级版)[返回结构化数据]
+     *
+     * @param imageUrl 下载图片经Base64编码后不超过 8M。图片下载时间不超过 3 秒
+     */
+    Map doRecognizeGeneralInvoice(String imageUrl) throws TencentCloudSDKException;
 
     /**
      * 发票验真[新版]
@@ -20,5 +27,5 @@ public interface TXYInvoice {
      * @param checkCode           校验码后 6 位,增值税普通发票、增值税电子普通发票、增值税普通发票(卷式)、增值税电子普通发票(通行费)时必填;
      * @param excludingTax/amount 不含税金额,增值税专用发票、增值税电子专用发票、机动车销售统一发票、二手车销售统一发票、区块链发票时必填; 全电发票为价税合计(含税金额)
      */
-    Map VatInvoiceVerifyNew(String invoiceKind, String invoiceCode, String invoiceNo, String invoiceDate, String amount, String checkCode, String excludingTax) throws TencentCloudSDKException;
+    Map VatInvoiceVerifyNew(String invoiceKind, String invoiceCode, String invoiceNo, String invoiceDate, String amount, String checkCode, String excludingTax, String tips) throws TencentCloudSDKException;
 }

+ 37 - 10
mjava-guyuan/src/main/java/com/malk/guyuan/service/tencent/impl/TXYImplInvoice.java

@@ -11,10 +11,7 @@ import com.tencentcloudapi.common.exception.TencentCloudSDKException;
 import com.tencentcloudapi.common.profile.ClientProfile;
 import com.tencentcloudapi.common.profile.HttpProfile;
 import com.tencentcloudapi.ocr.v20181119.OcrClient;
-import com.tencentcloudapi.ocr.v20181119.models.MixedInvoiceOCRRequest;
-import com.tencentcloudapi.ocr.v20181119.models.MixedInvoiceOCRResponse;
-import com.tencentcloudapi.ocr.v20181119.models.VatInvoiceVerifyNewRequest;
-import com.tencentcloudapi.ocr.v20181119.models.VatInvoiceVerifyNewResponse;
+import com.tencentcloudapi.ocr.v20181119.models.*;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -45,28 +42,54 @@ public class TXYImplInvoice implements TXYInvoice {
      * @apiNote https://cloud.tencent.com/document/product/866/37835
      */
     @Override
-    public Map doMixedInvoiceOCR(String imageUrl) throws TencentCloudSDKException {
+    public Map doMixedInvoiceOCR(String image) throws TencentCloudSDKException {
 
         Credential cred = new Credential(txyConf.getSecretId(), txyConf.getSecretKey());
         ClientProfile clientProfile = doRequest("ocr.tencentcloudapi.com");
         OcrClient client = new OcrClient(cred, txyConf.getRegion(), clientProfile);
 
         MixedInvoiceOCRRequest req = new MixedInvoiceOCRRequest();
-        req.setImageUrl(imageUrl);
+        if (image.startsWith("http")) {
+            req.setImageUrl(image);
+        } else {
+            req.setImageBase64(image);
+        }
         req.setReturnMultiplePage(true); // PDF多页识别, 仅支持返回文件前30页
+        log.debug("请求参数, {}", JSON.toJSONString(req));
         MixedInvoiceOCRResponse resp = client.MixedInvoiceOCR(req);
         String result = MixedInvoiceOCRResponse.toJsonString(resp);
         log.debug("请求响应, {}", result);
         return (Map) JSON.parse(result);
     }
 
+    /**
+     * 通用票据识别(高级版)
+     *
+     * @apiNote https://cloud.tencent.com/document/api/866/90802
+     */
+    @Override
+    public Map doRecognizeGeneralInvoice(String imageUrl) throws TencentCloudSDKException {
+        Credential cred = new Credential(txyConf.getSecretId(), txyConf.getSecretKey());
+        ClientProfile clientProfile = doRequest("ocr.tencentcloudapi.com");
+        OcrClient client = new OcrClient(cred, txyConf.getRegion(), clientProfile);
+
+        RecognizeGeneralInvoiceRequest req = new RecognizeGeneralInvoiceRequest();
+        req.setImageUrl(imageUrl);
+        req.setEnableMultiplePage(true); // PDF多页识别, 仅支持返回文件前30页
+        req.setEnableCutImage(true); // 返回切割图片base64
+        RecognizeGeneralInvoiceResponse resp = client.RecognizeGeneralInvoice(req);
+        String result = MixedInvoiceOCRResponse.toJsonString(resp);
+        log.debug("请求响应, {}", result);
+        return (Map) JSON.parse(result);
+    }
+
     /**
      * 发票验真[新版]
      *
      * @apiNote https://cloud.tencent.com/document/product/866/73674
      */
     @Override
-    public Map VatInvoiceVerifyNew(String invoiceKind, String invoiceCode, String invoiceNo, String invoiceDate, String amount, String checkCode, String excludingTax) throws TencentCloudSDKException {
+    public Map VatInvoiceVerifyNew(String invoiceKind, String invoiceCode, String invoiceNo, String invoiceDate, String amount, String checkCode, String excludingTax, String tips) throws TencentCloudSDKException {
         Credential cred = new Credential(txyConf.getSecretId(), txyConf.getSecretKey());
         ClientProfile clientProfile = doRequest("ocr.tencentcloudapi.com");
         OcrClient client = new OcrClient(cred, txyConf.getRegion(), clientProfile);
@@ -80,7 +103,7 @@ public class TXYImplInvoice implements TXYInvoice {
         req.setInvoiceDate(invoiceDate);
         req.setInvoiceCode(invoiceCode);
         req.setCheckCode(checkCode);
-        if (invoiceKind.contains("增值税电子") || invoiceKind.contains("电子发票") || invoiceKind.contains("全电发票")) {
+        if (invoiceKind.contains("全电")) {
             // 全电票, 需要价税合计且无发票代码与校验码
             req.setCheckCode(null);
             req.setInvoiceCode(null);
@@ -89,14 +112,18 @@ public class TXYImplInvoice implements TXYInvoice {
             req.setAmount(null);
             req.setAmount(excludingTax);
         }
+        log.info("发票验真, {}", JSON.toJSONString(req));
         VatInvoiceVerifyNewResponse resp = client.VatInvoiceVerifyNew(req);
         String result = VatInvoiceVerifyNewResponse.toJsonString(resp);
         Map rsp = (Map) JSON.parse(result);
 
         // 因全电票取值, 取值价税合计, 单独校验下金额
         Map invoice = (Map) rsp.get("Invoice");
-        McException.assertAccessException(!UtilNumber.equalBigDecimal(UtilMap.getString(invoice, "AmountWithTax"), amount), "发票有疑问, 价税合计金额不匹配!");
-        McException.assertAccessException(!UtilNumber.equalBigDecimal(UtilMap.getString(invoice, "AmountWithoutTax"), excludingTax), "发票有疑问, 不含税金额不匹配!");
+        if (StringUtils.isBlank(tips)) {
+            tips = "发票有疑问";
+        }
+        McException.assertAccessException(!UtilNumber.equalBigDecimal(UtilMap.getString(invoice, "AmountWithTax"), amount), tips + ", 价税合计金额不匹配!");
+        McException.assertAccessException(!UtilNumber.equalBigDecimal(UtilMap.getString(invoice, "AmountWithoutTax"), excludingTax), tips + ", 不含税金额不匹配!");
 
         log.debug("请求响应, {}", result);
         return rsp;

+ 4 - 10
mjava-guyuan/src/main/resources/application-dev.yml

@@ -24,24 +24,18 @@ spring:
     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
+    file: /Users/zhuogao/server/_Tool/var/mjava/tmp/file
+    image: /Users/zhuogao/server/_Tool/var/mjava/tmp/image
     tmp: /Users/mcli/server/_Tool/var/mjava/tmp
   source:
-    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
+    fonts: /Users/zhuogao/server/_Tool/fonts/simsun.ttc
 logging:
   file:
-    path: /Users/malk/server/_Tool/var/mjava/log
+    path: /Users/zhuogao/server/_Tool/var/mjava/log
 
 # dingtalk
 dingtalk:

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

@@ -21,8 +21,6 @@ spring:
   jpa:
     database: MYSQL
     database-platform: org.hibernate.dialect.MySQL57Dialect
-  flyway:
-    enabled: false      #  需要配置 jpa.hibernate.ddl-auto 为 none. 否则 flyway.enabled 配置会无效, 在没有数库连接情况下程序无法启动
 
 # dingtalk
 dingtalk:

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 13853 - 7835
mjava-guyuan/src/main/resources/static/mjs/mjs.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 1
mjava-guyuan/src/main/resources/static/mjs/mjs.min.js


+ 1 - 1
mjava-guyuan/target/classes/META-INF/spring-configuration-metadata.json

@@ -30,7 +30,7 @@
     {
       "name": "tencent.t-y-p-e-i-n-v-o-i-c-e",
       "type": "java.util.Map<java.lang.String,java.lang.String>",
-      "description": "票据类型",
+      "description": "票据类型 - 中央非税未返回税号官方说明: 非税发票理论是没有税号的,图片中那个属于信用代码 [两个版本接口均为返回]",
       "sourceType": "com.malk.guyuan.server.tencent.TXYConf"
     }
   ],

+ 4 - 10
mjava-guyuan/target/classes/application-dev.yml

@@ -24,24 +24,18 @@ spring:
     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
+    file: /Users/zhuogao/server/_Tool/var/mjava/tmp/file
+    image: /Users/zhuogao/server/_Tool/var/mjava/tmp/image
     tmp: /Users/mcli/server/_Tool/var/mjava/tmp
   source:
-    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
+    fonts: /Users/zhuogao/server/_Tool/fonts/simsun.ttc
 logging:
   file:
-    path: /Users/malk/server/_Tool/var/mjava/log
+    path: /Users/zhuogao/server/_Tool/var/mjava/log
 
 # dingtalk
 dingtalk:

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

@@ -21,8 +21,6 @@ spring:
   jpa:
     database: MYSQL
     database-platform: org.hibernate.dialect.MySQL57Dialect
-  flyway:
-    enabled: false      #  需要配置 jpa.hibernate.ddl-auto 为 none. 否则 flyway.enabled 配置会无效, 在没有数库连接情况下程序无法启动
 
 # dingtalk
 dingtalk:

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 13853 - 7835
mjava-guyuan/target/classes/static/mjs/mjs.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 1
mjava-guyuan/target/classes/static/mjs/mjs.min.js


+ 0 - 3
mjava-hangshi/src/main/java/com/malk/hangshi/Boot.java

@@ -10,9 +10,6 @@ import javax.persistence.EntityManager;
 
 /**
  * corp项目: 扫描公共模块
- * -
- * 若是无需数据库模块, 配置无效地址也可启动, 引入mjava不支持直接 @SpringBootApplication(exclude = DataSourceAutoConfiguration.class) 配置
- * 需要配置 jpa.hibernate.ddl-auto 为 none. 标识对表没有任何操作. 若不设置为 non, flyway.enabled 配置会无效, 在没有数库连接情况下程序无法启动
  */
 @EnableJpaAuditing
 @SpringBootApplication(scanBasePackages = {"com.malk"})

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

@@ -28,14 +28,14 @@ spring:
 # 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/
+    file: /Users/zhuogao/server/_Tool/var/mjava/tmp/file/
+    image: /Users/zhuogao/server/_Tool/var/mjava/tmp/image/
+    tmp: /Users/zhuogao/server/_Tool/var/mjava/tmp/
   source:
-    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
+    fonts: /Users/zhuogao/server/_Tool/fonts/simsun.ttc
 logging:
   file:
-    path: /Users/malk/server/_Tool/var/mjava/log
+    path: /Users/zhuogao/server/_Tool/var/mjava/log
 
 # dingtalk
 dingtalk:

+ 5 - 1
mjava-hangshi/src/test/resources/server.sh

@@ -1,15 +1,19 @@
 #!/bin/bash
-appname='mjava-hangshi'
+
+appname='mjava-xxx'
+
 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"
+    tail -f log/info.log
   else
     if [ "$1" == "test" ]; then
       nohup java -Xms256m -Xmx256m -jar $appname.jar --spring.profiles.active=test &
       echo "server test is starting"
+      tail -f log/info.log
     else
       if [ "$1" == "stop" ]; then
         PID=$(ps -ef | grep $appname.jar | grep -v grep | awk '{ print $2 }')

+ 56 - 0
mjava-hangshi/src/test/resources/winsw.xml

@@ -0,0 +1,56 @@
+<!--
+  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 -jar mjava.jar</arguments>
+    <!-- <arguments>-Xms256m -Xmx256m -Dfile.encoding=UTF-8 -jar mjava.jar</arguments> -->
+    <!-- 服务的启动模式:默认Automatic -->
+    <startmode>Automatic</startmode>
+    <!-- 日志地址 -->
+    <logpath>%BASE%\ws</logpath>
+    <!-- 日志模式 -->
+    <logmode>rotate</logmode>
+</service>
+

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

@@ -28,14 +28,14 @@ spring:
 # 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/
+    file: /Users/zhuogao/server/_Tool/var/mjava/tmp/file/
+    image: /Users/zhuogao/server/_Tool/var/mjava/tmp/image/
+    tmp: /Users/zhuogao/server/_Tool/var/mjava/tmp/
   source:
-    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
+    fonts: /Users/zhuogao/server/_Tool/fonts/simsun.ttc
 logging:
   file:
-    path: /Users/malk/server/_Tool/var/mjava/log
+    path: /Users/zhuogao/server/_Tool/var/mjava/log
 
 # dingtalk
 dingtalk:

+ 5 - 1
mjava-hangshi/target/test-classes/server.sh

@@ -1,15 +1,19 @@
 #!/bin/bash
-appname='mjava-hangshi'
+
+appname='mjava-xxx'
+
 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"
+    tail -f log/info.log
   else
     if [ "$1" == "test" ]; then
       nohup java -Xms256m -Xmx256m -jar $appname.jar --spring.profiles.active=test &
       echo "server test is starting"
+      tail -f log/info.log
     else
       if [ "$1" == "stop" ]; then
         PID=$(ps -ef | grep $appname.jar | grep -v grep | awk '{ print $2 }')

+ 1 - 1
mjava-mcli/src/main/java/com/malk/mcli/test/JSPTestController.java

@@ -24,7 +24,7 @@ import java.util.Map;
  * 4. jsp文件有三种语法, JSP表达式 / EL表达式 / JSTL标签库; 正常书写 html, 数据获取通过 ModelAndView 传递进来 [c标签最实用]
  * 5. 在controller内返回 ModelAndView, 渲染为jsp文件名称, 参数传递可用 request.setAttribute / modelAndView.addObject
  * 6. 可选: 在启动配置内, environment - working directory 下填写 $MODULE_WORKING_DIR$
- * 7. 进阶: 实现jsp效果后, 后续可通过 mvc 解耦视图和控制器, view 可使用模板依赖进行统一管理与继承, controller 可通过 servlet 统一接管
+ * 7. 进阶: 实现jsp效果后, 后续可通过 mvc 解耦视图和控制器, view 可使用模板依赖进行统一管理与继承, com.zhuogao.zhuogao.controller 可通过 servlet 统一接管
  **/
 @Slf4j
 @Profile({"dev", "test"})

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

@@ -32,14 +32,14 @@ spring:
 # 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/
+    file: /Users/zhuogao/server/_Tool/var/mjava/tmp/file/
+    image: /Users/zhuogao/server/_Tool/var/mjava/tmp/image/
+    tmp: /Users/zhuogao/server/_Tool/var/mjava/tmp/
   source:
-    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
+    fonts: /Users/zhuogao/server/_Tool/fonts/simsun.ttc
 logging:
   file:
-    path: /Users/malk/server/_Tool/var/mjava/log
+    path: /Users/zhuogao/server/_Tool/var/mjava/log
 
 # dingtalk
 dingtalk:

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

@@ -32,14 +32,14 @@ spring:
 # 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/
+    file: /Users/zhuogao/server/_Tool/var/mjava/tmp/file/
+    image: /Users/zhuogao/server/_Tool/var/mjava/tmp/image/
+    tmp: /Users/zhuogao/server/_Tool/var/mjava/tmp/
   source:
-    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
+    fonts: /Users/zhuogao/server/_Tool/fonts/simsun.ttc
 logging:
   file:
-    path: /Users/malk/server/_Tool/var/mjava/log
+    path: /Users/zhuogao/server/_Tool/var/mjava/log
 
 # dingtalk
 dingtalk:

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

@@ -28,14 +28,14 @@ spring:
 # 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/
+    file: /Users/zhuogao/server/_Tool/var/mjava/tmp/file/
+    image: /Users/zhuogao/server/_Tool/var/mjava/tmp/image/
+    tmp: /Users/zhuogao/server/_Tool/var/mjava/tmp/
   source:
-    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
+    fonts: /Users/zhuogao/server/_Tool/fonts/simsun.ttc
 logging:
   file:
-    path: /Users/malk/server/_Tool/var/mjava/log
+    path: /Users/zhuogao/server/_Tool/var/mjava/log
 
 # dingtalk
 dingtalk:

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

@@ -28,14 +28,14 @@ spring:
 # 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/
+    file: /Users/zhuogao/server/_Tool/var/mjava/tmp/file/
+    image: /Users/zhuogao/server/_Tool/var/mjava/tmp/image/
+    tmp: /Users/zhuogao/server/_Tool/var/mjava/tmp/
   source:
-    fonts: /Users/malk/server/_Tool/fonts/simsun.ttc
+    fonts: /Users/zhuogao/server/_Tool/fonts/simsun.ttc
 logging:
   file:
-    path: /Users/malk/server/_Tool/var/mjava/log
+    path: /Users/zhuogao/server/_Tool/var/mjava/log
 
 # dingtalk
 dingtalk:

+ 54 - 0
mjava-zhuogao/pom.xml

@@ -0,0 +1,54 @@
+<?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-malk</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>${mjava.version}</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>

+ 29 - 0
mjava-zhuogao/src/main/java/com/malk/zhuogao/Boot.java

@@ -0,0 +1,29 @@
+package com.malk.zhuogao;
+
+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项目: 扫描公共模块
+ */
+@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);
+    }
+}

+ 137 - 0
mjava-zhuogao/src/main/java/com/malk/zhuogao/controller/ZGController.java

@@ -0,0 +1,137 @@
+package com.malk.zhuogao.controller;
+
+import com.alibaba.fastjson.JSON;
+import com.malk.server.common.McException;
+import com.malk.server.common.McR;
+import com.malk.service.dingtalk.DDClient;
+import com.malk.service.dingtalk.DDClient_ORGAPP;
+import com.malk.utils.UtilDateTime;
+import com.malk.utils.UtilExcel;
+import com.malk.utils.UtilMap;
+import com.malk.utils.UtilString;
+import com.malk.zhuogao.repository.entity.ZSDFileRecordPo;
+import com.malk.zhuogao.service.ZSDClient_File;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 错误抛出与拦截详见 CatchException
+ */
+@Slf4j
+@RestController
+@RequestMapping
+public class ZGController {
+
+
+    @Autowired
+    private DDClient ddClient;
+
+    @Autowired
+    private DDClient_ORGAPP ddClient_orgapp;
+
+    @Autowired
+    private ZSDClient_File zsdFileClient;
+
+
+    /**
+     * 查询文件操作记录
+     */
+    @SneakyThrows
+    @PostMapping("records/query")
+    McR queryRecords(@RequestBody Map data) {
+
+        McException.assertParamException_Null(data, "pageIndex", "pageSize");
+        return McR.success(zsdFileClient.queryRecords(data, UtilMap.getInt(data, "pageIndex"), UtilMap.getInt(data, "pageSize")));
+    }
+
+    /**
+     * 导出审计操作记录
+     */
+    @PostMapping("records/export")
+    public void exprotRecords(HttpServletResponse response, @RequestBody Map param) {
+
+        log.info("导出审计操作记录 入参, {}", param);
+
+        Page page = zsdFileClient.queryRecords(param, 1, 1);
+        McException.assertAccessException(page.getTotalElements() > 100000L, "单次导出不能超过10万条数据!");
+
+        List<ZSDFileRecordPo> dataList = zsdFileClient.queryRecords(param, 1, Integer.MAX_VALUE).getContent();
+        List<String> columnHeader = Arrays.asList("员工姓名", "操作终端", "操作类型", "操作来源", "知识库名称", "知识库链接", "操作时间", "接收方名称", "接收方类型", "文件名称", "文件类型", "文件大小", "文件所属组织");
+        List<String> columnProp = Arrays.asList("realName", "platformView", "actionView", "operateModuleView", "workSpaceName", "link", "gmtCreateTime", "receiverName", "receiverTypeView", "resource", "resourceExtension", "resourceSizeToM", "orgName");
+
+        log.info("导出审计操作记录 数量, {}", dataList.size());
+        UtilExcel.builder().heardList(columnHeader.toArray(new String[0])).heardKey(columnProp.toArray(new String[0]))
+                .data(JSON.parseArray(JSON.toJSONString(dataList), Map.class)).fileName("审计操作记录").build()
+                .exportExcelByPoi(response);
+    }
+
+    /////// test ///////
+
+    /**
+     * 同步记录
+     */
+    @PostMapping("sync")
+    McR sync(@RequestParam String startDate, String endDate) {
+        long startTime = UtilDateTime.parseDateTime(startDate + " 00:00:00").getTime();
+        long endTime = UtilDateTime.parseDateTime(endDate + " 23:59:59").getTime();
+
+        int pageSize = 500;
+        zsdFileClient.syncFileRecords(startTime, endTime, pageSize, null);
+        return McR.success();
+    }
+
+    /**
+     * 同步记录: 失败续传
+     */
+    @PostMapping("sync-bc")
+    McR sync_bc() {
+
+        long startTime = 1688953500001L;
+        long endTime = 1688954400001L;
+
+        int pageSize = 500;
+        Map last = UtilMap.map("gmtCreate, bizId", 1688954399589L, 109794444265L);
+        zsdFileClient.syncFileRecords(startTime, endTime, pageSize, last);
+        return McR.success();
+    }
+
+    /**
+     * test
+     */
+    @PostMapping("test")
+    McR test(@RequestBody Map data) {
+        McException.assertParamException_Null(data, "startTime", "endTime", "pageSize");
+        log.info("查询文件审计, {}", data);
+//        long startTime = new Date().getTime() - 7 * 24 * 60 * 60 * 1000L;
+//        long endTime = new Date().getTime();
+//        int pageSize = 500;
+        long startTime = UtilMap.getLong(data, "startTime");
+        long endTime = UtilMap.getLong(data, "endTime");
+        int pageSize = UtilMap.getInt(data, "pageSize");
+        Map preLastRecord = (Map) data.get("preLastRecord");
+        List<Map> records = ddClient_orgapp.obtainFileOperationRecords(ddClient.getAccessToken(), startTime, endTime, pageSize, preLastRecord).stream().map(item -> {
+            item.put("resourceName", UtilMap.getString(item, "resource") + "." + UtilMap.getString(item, "resourceExtension"));
+            if (item.containsKey("resourceSize")) {
+                item.put("resourceSizeToM", UtilString.stringFormatFixed((UtilMap.getLong(item, "resourceSize") / 1024F / 1024L)) + "M");
+            }
+            return item;
+        }).collect(Collectors.toList());
+
+        log.info("响应文件审计, {}", records.size());
+
+        return McR.success(records);
+    }
+
+
+}
+
+

+ 18 - 0
mjava-zhuogao/src/main/java/com/malk/zhuogao/repository/dao/ZSDFileRecordDao.java

@@ -0,0 +1,18 @@
+package com.malk.zhuogao.repository.dao;
+
+import com.malk.zhuogao.repository.entity.ZSDFileRecordPo;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+import javax.transaction.Transactional;
+
+/**
+ * 接口多继承
+ * -
+ * - JpaRepository 中有常用的 CRUD 、分页、排序等方法
+ * - JpaSpecificationExecutor 可以实现任意的复杂查询
+ */
+@Transactional
+public interface ZSDFileRecordDao extends JpaRepository<ZSDFileRecordPo, Long>, JpaSpecificationExecutor<ZSDFileRecordPo> {
+
+}

+ 158 - 0
mjava-zhuogao/src/main/java/com/malk/zhuogao/repository/entity/ZSDFileRecordPo.java

@@ -0,0 +1,158 @@
+package com.malk.zhuogao.repository.entity;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.malk.base.BasePo;
+import com.malk.utils.UtilString;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+
+import javax.persistence.*;
+import java.util.Date;
+
+@Entity
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@Table(name = "record_file")
+@Slf4j
+public class ZSDFileRecordPo extends BasePo {
+
+    /**
+     * 员工姓名
+     */
+    private String realName;
+
+    /**
+     * 操作终端
+     */
+    private String platformView;
+
+    /**
+     * 操作类型
+     */
+    private String actionView;
+
+    /**
+     * 操作来源
+     */
+    private String operateModuleView;
+
+    /**
+     * 知识库名称
+     */
+    private String workSpaceName;
+
+    /// 是否知识库
+    @Builder.Default
+    private boolean isWorkSpace = false;
+
+    public void setWorkSpaceName(String workSpaceName) {
+        this.workSpaceName = workSpaceName;
+        isWorkSpace = StringUtils.isNotBlank(workSpaceName);
+    }
+
+    /**
+     * 知识库链接
+     */
+    private String workSpacePcUrl;
+
+    /**
+     * 在线文档链接
+     */
+    private String docPcUrl;
+
+    /**
+     * 成员授权列表: JSON
+     */
+    private String docMemberList;
+
+    /**
+     * 文件接收人列表: JSON
+     */
+    private String docReceiverList;
+
+    /**
+     * 操作时间
+     */
+    @Temporal(TemporalType.TIMESTAMP)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date gmtCreateTime;
+
+    /**
+     * 记录修改时间,UNIX时间戳,单位毫秒
+     */
+    @Temporal(TemporalType.TIMESTAMP)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date gmtModifiedTime;
+
+    /**
+     * 接收方名称
+     */
+    private String receiverName;
+
+    /**
+     * 接收方类型
+     */
+    private String receiverTypeView;
+
+    /**
+     * 记录状态
+     */
+    private Integer status;
+
+    /**
+     * 文件名称
+     */
+    private String resource;
+
+    /**
+     * 文件类型
+     */
+    private String resourceExtension;
+
+    /**
+     * 文件大小
+     */
+    private Long resourceSize;
+
+    /// 文件大小: M
+    @Transient
+    private String resourceSizeToM;
+
+    public String getResourceSizeToM() {
+        if (UtilString.isNotBlankCompatNull(String.valueOf(resourceSize))) {
+            return UtilString.stringFormatFixed(resourceSize / 1024F / 1024L) + "M";
+        }
+        return "";
+    }
+
+    /**
+     * 文件所属组织
+     */
+    private String orgName;
+
+    /**
+     * 本次操作所在的机器IP
+     */
+    private String ipAddress;
+
+    /**
+     * 文件所属的空间ID
+     */
+    private Long targetSpaceId;
+
+    /**
+     * 文件ID
+     */
+    private String bizId;
+
+    /**
+     * 知识库id
+     */
+    private Long workSpaceId;
+}

+ 39 - 0
mjava-zhuogao/src/main/java/com/malk/zhuogao/schedule/ZSDcheduleTask.java

@@ -0,0 +1,39 @@
+package com.malk.zhuogao.schedule;
+
+import com.malk.zhuogao.service.ZSDClient_File;
+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;
+
+import java.util.Date;
+
+/**
+ * @EnableScheduling 开启定时任务 [配置参考McScheduleTask]
+ */
+@Slf4j
+@Configuration
+@EnableScheduling
+@ConditionalOnProperty(name = {"spel.scheduling"})
+public class ZSDcheduleTask {
+
+    @Autowired
+    private ZSDClient_File zsdClient_file;
+
+    /**
+     * 15分钟拉取一次文件记录
+     */
+    @Scheduled(cron = "0 0/15 * * * ?")
+    public void syncDingTalkFailedList() {
+        try {
+            long endTime = new Date().getTime();
+            long startTime = endTime - 15 * 60 * 1000L;
+            zsdClient_file.syncFileRecords(startTime, endTime, 500, null);
+        } catch (Exception e) {
+            // 记录错误信息
+            e.printStackTrace();
+        }
+    }
+}

+ 21 - 0
mjava-zhuogao/src/main/java/com/malk/zhuogao/service/ZSDClient_File.java

@@ -0,0 +1,21 @@
+package com.malk.zhuogao.service;
+
+import com.malk.zhuogao.repository.entity.ZSDFileRecordPo;
+import org.springframework.data.domain.Page;
+
+import java.util.Map;
+
+public interface ZSDClient_File {
+
+    /**
+     * 查询文件审计记录
+     *
+     * @implNote 数据库从0页开始, 可以使用重载的 of(int page, int size, Sort sort) 方法指定排序字段
+     */
+    Page<ZSDFileRecordPo> queryRecords(Map<String, String> data, int page, int size);
+
+    /**
+     * 同步记录, 落库
+     */
+    void syncFileRecords(long startTime, long endTime, int pageSize, Map preLastRecord);
+}

+ 104 - 0
mjava-zhuogao/src/main/java/com/malk/zhuogao/service/impl/ZSDImplClient_File.java

@@ -0,0 +1,104 @@
+package com.malk.zhuogao.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.malk.service.dingtalk.DDClient;
+import com.malk.service.dingtalk.DDClient_ORGAPP;
+import com.malk.utils.UtilMap;
+import com.malk.zhuogao.repository.dao.ZSDFileRecordDao;
+import com.malk.zhuogao.repository.entity.ZSDFileRecordPo;
+import com.malk.zhuogao.service.ZSDClient_File;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import javax.persistence.criteria.Predicate;
+import java.util.*;
+import java.util.stream.Collectors;
+
+
+@Service
+@Slf4j
+public class ZSDImplClient_File implements ZSDClient_File {
+
+    @Resource
+    private ZSDFileRecordDao recordDao;
+
+    /**
+     * 查询文件审计记录
+     */
+    @Override
+    public Page<ZSDFileRecordPo> queryRecords(Map<String, String> data, int page, int size) {
+
+        // 分页 & 排序
+        Sort sort = Sort.by(Sort.Direction.DESC, "gmtCreateTime");
+        Pageable pageable = PageRequest.of(page - 1, size, sort);
+
+        // 卓高查询条件: 匹配员工姓名、操作终端、操作类型、操作来源; 模糊: 知识库名称、接收方名称、文件名称; 日期范围
+        Specification<ZSDFileRecordPo> specification = (root, criteriaQuery, criteriaBuilder) -> {
+
+            List<Predicate> predicateList = new ArrayList<>();
+            List<String> conditionsEqual = Arrays.asList("realName", "platformView", "actionView", "operateModuleView", "isWorkSpace");
+            List<String> conditionsLike = Arrays.asList("workSpaceName", "receiverName", "resource");
+            for (String equal : conditionsEqual) {
+                if (UtilMap.isNotBlankString(data, equal)) {
+                    predicateList.add(criteriaBuilder.equal(root.get(equal), data.get(equal)));
+                }
+            }
+            for (String like : conditionsLike) {
+                if (UtilMap.isNotBlankString(data, like)) {
+                    predicateList.add(criteriaBuilder.like(root.get(like), "%" + data.get(like) + "%"));
+                }
+            }
+            // 查询日期范围,闭区间
+            if (data.containsKey("startTime") && data.containsKey("endTime")) {
+                predicateList.add(criteriaBuilder.between(root.get("gmtCreateTime").as(String.class), data.get("startTime"), data.get("endTime")));
+            }
+            return criteriaBuilder.and(predicateList.toArray(new javax.persistence.criteria.Predicate[predicateList.size()]));
+        };
+        // 无数据时返回空列表
+        return recordDao.findAll(specification, pageable);
+    }
+
+    @Autowired
+    private DDClient ddClient;
+
+    @Autowired
+    private DDClient_ORGAPP ddClient_orgapp;
+
+    @Autowired
+    private ZSDFileRecordDao zsdFileRecordDao;
+
+    /**
+     * 同步记录, 落库
+     */
+    @Override
+    public void syncFileRecords(long startTime, long endTime, int pageSize, Map preLastRecord) {
+
+        // 单表储存: 格式化
+        List<Map> records = ddClient_orgapp.obtainFileOperationRecords(ddClient.getAccessToken(), startTime, endTime, pageSize, preLastRecord).stream().map(item -> {
+            if (item.containsKey("docReceiverList")) {
+                item.put("docReceiverList", JSON.toJSONString(item.get("docReceiverList")));
+            }
+            if (item.containsKey("docMemberList")) {
+                item.put("docMemberList", JSON.toJSONString(item.get("docMemberList")));
+            }
+            item.put("gmtCreateTime", new Date(UtilMap.getLong(item, "gmtCreate")));
+            item.put("gmtModifiedTime", new Date(UtilMap.getLong(item, "gmtModified")));
+            return item;
+        }).collect(Collectors.toList());
+
+        // 递归同步日期范围记录
+        if (records.size() > 0) {
+            List<ZSDFileRecordPo> poList = JSON.parseArray(JSON.toJSONString(records), ZSDFileRecordPo.class);
+            log.info("文件审计同步, {}, preLastRecord = {}", records.size(), records.get(records.size() - 1));
+            zsdFileRecordDao.saveAll(poList);
+            syncFileRecords(startTime, endTime, pageSize, records.get(records.size() - 1));
+        }
+    }
+}

+ 48 - 0
mjava-zhuogao/src/main/resources/application-dev.yml

@@ -0,0 +1,48 @@
+# 环境配置
+server:
+  port: 9001
+  servlet:
+    context-path: /api/zhuogao
+
+# condition
+spel:
+  scheduling: false        # 定时任务是否执行
+  multiSource: false       # 是否多数据源配置
+
+spring:
+  # database
+  datasource:
+    hikari:
+      connection-init-sql: SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci           # SqlServer, Oracle 无需设置类型
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    username: root
+    password: zg-data2023
+    url: jdbc:mysql://106.14.201.187:3306/zsd_file?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/zhuogao/server/_Tool/var/mjava/tmp/file
+    image: /Users/zhuogao/server/_Tool/var/mjava/tmp/image
+    tmp: /Users/mcli/server/_Tool/var/mjava/tmp
+  source:
+    fonts: /Users/zhuogao/server/_Tool/fonts/simsun.ttc
+logging:
+  file:
+    path: /Users/zhuogao/server/_Tool/var/mjava/log
+
+# dingtalk
+dingtalk:
+  agentId: 2637590343
+  appKey: dingpf58d8stvjmlmeum
+  appSecret: aEk90YBnlXl8Kn1rOhtuq8igxVwR6VKUdVZhngks-0SBR6ySy5j9HRqaFCEMlH8n
+  corpId: dingd5d648cdd1e2518635c2f4657eb6378f
+  aesKey:
+  token:
+  operator: ""   # OA管理员账号 [首字符若为0需要转一下字符串]

+ 33 - 0
mjava-zhuogao/src/main/resources/application-prod.yml

@@ -0,0 +1,33 @@
+# 环境配置
+server:
+  port: 9011
+  servlet:
+    context-path: /api/zhuogao
+
+# condition
+spel:
+  scheduling: true        # 定时任务是否执行
+  multiSource: false      # 是否多数据源配置
+
+spring:
+  # database
+  datasource:
+    hikari:
+      connection-init-sql: SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci           # SqlServer, Oracle 无需设置类型
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    username: root
+    password: zg-data2023
+    url: jdbc:mysql://106.14.201.187:3306/zsd_file?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+  jpa:
+    database: MYSQL
+    database-platform: org.hibernate.dialect.MySQL57Dialect
+
+# dingtalk
+dingtalk:
+  agentId: 2637590343
+  appKey: dingpf58d8stvjmlmeum
+  appSecret: aEk90YBnlXl8Kn1rOhtuq8igxVwR6VKUdVZhngks-0SBR6ySy5j9HRqaFCEMlH8n
+  corpId: dingd5d648cdd1e2518635c2f4657eb6378f
+  aesKey:
+  token:
+  operator: ""   # OA管理员账号 [首字符若为0需要转一下字符串]

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/app.1e205474.css


BIN
mjava-zhuogao/src/main/resources/static/web/css/app.1e205474.css.gz


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-020bde4f.8cd353de.css


+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-03803d04.d28c0d77.css

@@ -0,0 +1 @@
+[data-v-100f05f3]:export{colorTheme:#2663f4}.main[data-v-100f05f3]{background-color:#f0f2f5}.swiper[data-v-100f05f3]{--swiper-theme-color:#f60}.swiper-image[data-v-100f05f3]{width:100%}

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-09d432c5.08e92398.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-0dc3c267.a04b5e6e.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-13e18d6c.29149725.css


+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-16622649.5f788a64.css

@@ -0,0 +1 @@
+[data-v-2cbd7a50]:export{colorTheme:#2663f4}.webview[data-v-2cbd7a50]{width:100%}

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-1ee91c18.2c5e6b95.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-241c9cfc.2ad4aee4.css


+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-2b3d1d97.3e61a36e.css

@@ -0,0 +1 @@
+[data-v-55a7af65]:export{colorTheme:#2663f4}.comp .el-input[data-v-55a7af65]{width:20rem}.comp-form-oper[data-v-55a7af65]{margin-top:7rem;text-align:center}.comp-form-oper .el-button[data-v-55a7af65]{margin:0 1.5rem;width:40%}

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-34786a36.9b156963.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-35d77297.5dd7accd.css


BIN
mjava-zhuogao/src/main/resources/static/web/css/chunk-35d77297.5dd7accd.css.gz


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-3f61e0f1.eef13e95.css


+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-4e109df4.b671580b.css

@@ -0,0 +1 @@
+.comp-department{color:#435a99;margin-right:1rem;margin-left:2rem}.comp .el-input{width:20rem}.comp-department{cursor:pointer}.comp-department:hover{text-decoration:underline}.comp-department i{margin-left:.3rem}

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-5d241c38.e69d3699.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-6279ca32.6c624d50.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-65abd8c2.182cda6f.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-6b83ef66.f91727df.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-6d750ba2.b1127071.css


+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-723eb2cc.5ca1aba6.css

@@ -0,0 +1 @@
+[data-v-512e95e0]:export{colorTheme:#2663f4}.comp[data-v-512e95e0]{background-color:#fff}.comp-pagination[data-v-512e95e0]{padding:3rem 0 1rem 0}[data-v-512e95e0] .tableStyle{background-color:#f5f7fa!important;color:#333;font-weight:700}.paginationStyle[data-v-512e95e0]{text-align:center}

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-767b9dea.7228e7cc.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-87f1c134.0cd21f17.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-b189ddd8.7a1576f4.css


+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-d773cad0.b7a55ecf.css

@@ -0,0 +1 @@
+[data-v-76591bca]:export{colorTheme:#2663f4}.main[data-v-76591bca]{text-align:center;background-color:#fff;height:100%}.guide[data-v-76591bca]{width:100%}.guide img[data-v-76591bca]{width:5rem;height:5rem;margin:auto;margin-top:7%}h2[data-v-76591bca]{padding-top:4rem;font-size:2.4rem;text-align:justify-all}

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-de510a84.694e0ad8.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/chunk-fd2bf652.2e6b27df.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/npm.ant-design-vue.05a448c8.css


BIN
mjava-zhuogao/src/main/resources/static/web/css/npm.ant-design-vue.05a448c8.css.gz


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/npm.element-ui.2fe571ab.css


BIN
mjava-zhuogao/src/main/resources/static/web/css/npm.element-ui.2fe571ab.css.gz


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/npm.quasar.2415b056.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
mjava-zhuogao/src/main/resources/static/web/css/npm.swiper.23437b54.css


BIN
mjava-zhuogao/src/main/resources/static/web/css/npm.swiper.23437b54.css.gz


BIN
mjava-zhuogao/src/main/resources/static/web/fonts/element-icons.535877f5.woff


BIN
mjava-zhuogao/src/main/resources/static/web/fonts/element-icons.732389de.ttf


BIN
mjava-zhuogao/src/main/resources/static/web/fonts/flUhRq6tzZclQEJ-Vdg-IuiaDsNa.29b882f0.woff


BIN
mjava-zhuogao/src/main/resources/static/web/img/+pk-select.472d7dee.png


BIN
mjava-zhuogao/src/main/resources/static/web/img/404.0a45bba9.jpg


BIN
mjava-zhuogao/src/main/resources/static/web/img/link.038ba0a1.png


BIN
mjava-zhuogao/src/main/resources/static/web/img/logo.a24f00e9.png


BIN
mjava-zhuogao/src/main/resources/static/web/img/look.68727e17.png


BIN
mjava-zhuogao/src/main/resources/static/web/img/no-data-pk.fc4bd766.png


BIN
mjava-zhuogao/src/main/resources/static/web/img/no-data-search.26341beb.png


BIN
mjava-zhuogao/src/main/resources/static/web/img/pk-relation.05ad7b4b.png


BIN
mjava-zhuogao/src/main/resources/static/web/img/player.a587f6e2.png


BIN
mjava-zhuogao/src/main/resources/static/web/img/reset.e99a88b6.png


BIN
mjava-zhuogao/src/main/resources/static/web/img/search-to.c3c08449.png


BIN
mjava-zhuogao/src/main/resources/static/web/img/selected.52f9c8b3.png


+ 0 - 0
mjava-zhuogao/src/main/resources/static/web/index.html


Vissa filer visades inte eftersom för många filer har ändrats