gongdecai il y a 3 ans
commit
505444147d
100 fichiers modifiés avec 8725 ajouts et 0 suppressions
  1. 170 0
      .gitignore
  2. 2 0
      README.md
  3. 227 0
      pom.xml
  4. 187 0
      winsea-haixin-platform-backend/pom.xml
  5. 79 0
      winsea-haixin-platform-backend/src/main/java/com/alipay/sofa/runtime/api/annotation/SofaMethod.java
  6. 37 0
      winsea-haixin-platform-backend/src/main/java/com/alipay/sofa/runtime/api/annotation/SofaParameter.java
  7. 85 0
      winsea-haixin-platform-backend/src/main/java/com/alipay/sofa/runtime/api/annotation/SofaReference.java
  8. 160 0
      winsea-haixin-platform-backend/src/main/java/com/alipay/sofa/runtime/api/annotation/SofaReferenceBinding.java
  9. 85 0
      winsea-haixin-platform-backend/src/main/java/com/alipay/sofa/runtime/api/annotation/SofaService.java
  10. 111 0
      winsea-haixin-platform-backend/src/main/java/com/alipay/sofa/runtime/api/annotation/SofaServiceBinding.java
  11. 32 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/PlatformApplication.java
  12. 19 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/config/AccessInterceptor.java
  13. 25 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/config/PlatformConfig.java
  14. 48 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/config/PluginFeatureAspect.java
  15. 30 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/config/SMSConfigYlyy.java
  16. 13 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/constants/Constants.java
  17. 39 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/AccountResultController.java
  18. 352 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/AppendixController.java
  19. 41 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/BIController.java
  20. 39 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/BillOperateHisController.java
  21. 36 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/CommonParameterCompanyController.java
  22. 65 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/CompanyCustomDropDownController.java
  23. 77 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/EmailConfigController.java
  24. 157 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/ExcelController.java
  25. 47 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/FlowTaskCandidateController.java
  26. 52 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/FuncClickInfoController.java
  27. 270 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/OfficeController.java
  28. 54 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/PluginServiceController.java
  29. 97 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/RoleController.java
  30. 249 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/StaffController.java
  31. 115 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/SystemController.java
  32. 44 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/ThermalRoutingController.java
  33. 86 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/VesselController.java
  34. 85 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/entity/FuncClickInfo.java
  35. 43 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/entity/NotificationBusinessCode.java
  36. 64 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/entity/ThermalRouting.java
  37. 63 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/entity/view/CommonRoleMenuView.java
  38. 69 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/entity/view/FlowTaskCandidateStaffView.java
  39. 42 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/exception/EnterpriseErrorCodeEnums.java
  40. 32 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/exception/EnterpriseException.java
  41. 16 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/mapper/FuncClickInfoMapper.java
  42. 8 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/mapper/NotificationBusinessCodeMapper.java
  43. 7 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/mapper/ThermalRoutingMapper.java
  44. 54 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/properties/BIProperties.java
  45. 25 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/properties/CompanyProperties.java
  46. 20 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/CommonParameterCompanyService.java
  47. 22 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/IBIService.java
  48. 16 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/IBillOperateHisService.java
  49. 28 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/IFlowTaskCandidateService.java
  50. 34 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/IFuncClickInfoService.java
  51. 30 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/INotificationBusinessCodeService.java
  52. 13 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/IThermalRoutingService.java
  53. 68 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/impl/BIServiceImpl.java
  54. 57 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/impl/BillOprateHisImpl.java
  55. 100 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/impl/CommonParameterCompanyServiceImpl.java
  56. 278 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/impl/FlowTaskCandidateServiceImpl.java
  57. 71 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/impl/FuncClickInfoServiceImpl.java
  58. 35 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/impl/NotificationBusinessCodeServiceImpl.java
  59. 52 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/impl/ThermalRoutingServiceImpl.java
  60. 124 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/util/GtAppendixUtil.java
  61. 16 0
      winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/vo/NotificationStaffTodoTaskVO.java
  62. 1 0
      winsea-haixin-platform-backend/src/main/resources/META-INF/services/sofa-rpc/com.alipay.sofa.rpc.client.Router
  63. 2 0
      winsea-haixin-platform-backend/src/main/resources/META-INF/spring.factories
  64. 104 0
      winsea-haixin-platform-backend/src/main/resources/application-dev.yml
  65. 87 0
      winsea-haixin-platform-backend/src/main/resources/application-local.yml
  66. 87 0
      winsea-haixin-platform-backend/src/main/resources/application-prod.yml
  67. 96 0
      winsea-haixin-platform-backend/src/main/resources/application-test.yml
  68. 356 0
      winsea-haixin-platform-backend/src/main/resources/application.yml
  69. 24 0
      winsea-haixin-platform-backend/src/main/resources/banner.txt
  70. 79 0
      winsea-haixin-platform-backend/src/main/resources/db/migration/V6.0.1__init.sql
  71. 76 0
      winsea-haixin-platform-backend/src/main/resources/logback-spring.xml
  72. 5 0
      winsea-haixin-platform-backend/src/main/resources/mapper/CommonFuncClickInfoMapper.xml
  73. 5 0
      winsea-haixin-platform-backend/src/main/resources/mapper/CommonParameterConstMapper.xml
  74. 5 0
      winsea-haixin-platform-backend/src/main/resources/mapper/CommonParameterTenantMapper.xml
  75. 53 0
      winsea-haixin-platform-backend/src/main/resources/templates/office/browser.html
  76. 53 0
      winsea-haixin-platform-backend/src/main/resources/templates/office/office.html
  77. 55 0
      winsea-haixin-plugin-base/pom.xml
  78. 73 0
      winsea-haixin-plugin-base/src/main/java/com/alibaba/fastjson/support/spring/PropertyPreFilters.java
  79. 24 0
      winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/annotation/EnableService.java
  80. 116 0
      winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/config/CommonConfig.java
  81. 172 0
      winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/config/MybatisPlusConfig.java
  82. 64 0
      winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/config/WebConfig.java
  83. 24 0
      winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/international/International.java
  84. 25 0
      winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/international/InternationalConfig.java
  85. 116 0
      winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/international/InternationalProperties.java
  86. 38 0
      winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/international/InternationalResourceProvider.java
  87. 282 0
      winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/international/InternationalResourceProviderAdapter.java
  88. 52 0
      winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/international/InternationalSerializer.java
  89. 14 0
      winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/mq/MessageListener.java
  90. 84 0
      winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/mq/MessageQueueClient.java
  91. 29 0
      winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/mq/MessageQueueConfig.java
  92. 93 0
      winsea-haixin-plugin-base/src/main/java/com/winsea/svc/crew/constant/CrewSeafarerStatusEnum.java
  93. 767 0
      winsea-haixin-plugin-base/src/main/java/com/winsea/svc/crew/entity/CrewSeafarerInfo.java
  94. 99 0
      winsea-haixin-plugin-base/src/main/java/com/winsea/svc/crew/entity/view/CrewSeafarerInfoView.java
  95. 27 0
      winsea-haixin-plugin-base/src/main/java/com/winsea/svc/crew/service/ICrewSeafarerInfoService.java
  96. 11 0
      winsea-haixin-plugin-base/src/main/java/com/yh/saas/plugin/base/config/PluginBaseConfig.java
  97. 122 0
      winsea-haixin-plugin-base/src/main/java/com/yh/saas/plugin/base/entity/CommonBillOperateHis.java
  98. 216 0
      winsea-haixin-plugin-base/src/main/java/com/yh/saas/plugin/base/entity/EOBase.java
  99. 305 0
      winsea-haixin-plugin-base/src/main/java/com/yh/saas/plugin/base/entity/EOVDBillBasicDataInfo.java
  100. 282 0
      winsea-haixin-plugin-base/src/main/java/com/yh/saas/plugin/base/entity/EOXTAppendixInfo.java

+ 170 - 0
.gitignore

@@ -0,0 +1,170 @@
+######################
+# Project Specific
+######################
+/target/classes/static/**
+/src/test/javascript/coverage/
+
+### target ###
+/target/
+/winsea-haixin-platform-backend/target/
+/winsea-haixin-plugin-base/target/
+/winsea-haixin-plugin-clouddisk/target/
+/winsea-haixin-plugin-configuration/target/
+/winsea-haixin-plugin-news/target/
+/winsea-haixin-plugin-operation/target/
+/winsea-haixin-plugin-servicer/target/
+/winsea-haixin-plugin-yiliangyiyun/unpackage/dist/
+
+
+######################
+# Node
+######################
+/node/
+node_tmp/
+node_modules/
+npm-debug.log.*
+/.awcache/*
+/.cache-loader/*
+
+######################
+# SASS
+######################
+.sass-cache/
+
+######################
+# Eclipse
+######################
+*.pydevproject
+.project
+.metadata
+tmp/
+tmp/**/*
+*.tmp
+*.bak
+*.swp
+*~.nib
+local.properties
+.classpath
+.settings/
+.loadpath
+.factorypath
+/src/main/resources/rebel.xml
+
+# External tool builders
+.externalToolBuilders/**
+
+# Locally stored "Eclipse launch configurations"
+*.launch
+
+# CDT-specific
+.cproject
+
+# PDT-specific
+.buildpath
+
+# STS-specific
+/.sts4-cache/*
+######################
+# Intellij
+######################
+.idea/
+*.iml
+*.iws
+*.ipr
+*.ids
+*.orig
+classes/
+out/
+
+######################
+# Visual Studio Code
+######################
+.vscode/
+
+######################
+# Maven
+######################
+/log/
+/target/
+
+######################
+# Gradle
+######################
+.gradle/
+/build/
+
+######################
+# Package Files
+######################
+*.jar
+*.war
+*.ear
+*.db
+
+######################
+# Windows
+######################
+# Windows image file caches
+Thumbs.db
+
+# Folder config file
+Desktop.ini
+
+######################
+# Mac OSX
+######################
+.DS_Store
+.svn
+
+# Thumbnails
+._*
+
+# Files that might appear on external disk
+.Spotlight-V100
+.Trashes
+
+######################
+# Directories
+######################
+/bin/
+/deploy/
+
+######################
+# Logs
+######################
+*.log*
+
+######################
+# Others
+######################
+*.class
+*.*~
+*~
+.merge_file*
+
+######################
+# Gradle Wrapper
+######################
+!gradle/wrapper/gradle-wrapper.jar
+
+######################
+# Maven Wrapper
+######################
+!.mvn/wrapper/maven-wrapper.jar
+
+######################
+# ESLint
+######################
+.eslintcache
+
+######################
+# Rancher
+######################
+.rancher-pipeline.yml
+deployment.yaml
+
+######################
+# Docker
+######################
+Dockerfile
+/.recommenders/

+ 2 - 0
README.md

@@ -0,0 +1,2 @@
+# com.yh.saas.plugin.yiliangyiyun
+

+ 227 - 0
pom.xml

@@ -0,0 +1,227 @@
+<?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>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.1.1.RELEASE</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.yh.haixin</groupId>
+    <artifactId>winsea-haixin</artifactId>
+    <version>0.7.0</version>
+    <packaging>pom</packaging>
+
+    <properties>
+        <winsea.saas.version>6.0.0</winsea.saas.version>
+    </properties>
+
+    <modules>
+        <module>winsea-haixin-plugin-configuration</module>
+<!--        <module>winsea-haixin-plugin-crew</module>-->
+<!--        <module>winsea-haixin-plugin-monitor</module>-->
+        <module>winsea-haixin-platform-backend</module>
+        <module>winsea-haixin-plugin-base</module>
+<!--        <module>winsea-haixin-plugin-oil</module>-->
+        <module>winsea-haixin-plugin-clouddisk</module>
+<!--        <module>winsea-haixin-plugin-certificate</module>-->
+<!--        <module>winsea-haixin-plugin-maintain</module>-->
+        <module>winsea-haixin-plugin-servicer</module>
+        <module>winsea-haixin-plugin-news</module>
+<!--        <module>winsea-haixin-plugin-ism</module>-->
+<!--        <module>winsea-haixin-plugin-purchase</module>-->
+<!--        <module>winsea-haixin-plugin-finance</module>-->
+        <module>winsea-haixin-plugin-operation</module>
+<!--        <module>winsea-haixin-plugin-repair</module>-->
+        <module>winsea-haixin-plugin-yiliangyiyun</module>
+    </modules>
+
+    <repositories>
+        <!--        <repository>-->
+        <!--            <id>aliyun</id>-->
+        <!--            <name>aliyun-maven</name>-->
+        <!--            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>-->
+        <!--        </repository>-->
+        <repository>
+            <id>maven-public</id>
+            <url>http://maven.zthymaoyi.com/nexus/repository/maven-public/</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+    </repositories>
+    <pluginRepositories>
+        <pluginRepository>
+            <id>aliyun</id>
+            <name>aliyun-maven</name>
+            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
+        </pluginRepository>
+    </pluginRepositories>
+    <distributionManagement>
+        <repository>
+            <id>maven-releases</id>
+            <name>Nexus Release Repository</name>
+            <url>http://maven.zthymaoyi.com/nexus/repository/maven-releases/</url>
+        </repository>
+        <snapshotRepository>
+            <id>maven-snapshots</id>
+            <name>Nexus Snapshot Repository</name>
+            <url>http://maven.zthymaoyi.com/nexus/repository/maven-snapshots/</url>
+        </snapshotRepository>
+    </distributionManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>javax.validation</groupId>
+            <artifactId>validation-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alipay.sofa</groupId>
+            <artifactId>sofa-rpc-api</artifactId>
+            <version>5.6.5</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.github.ulisesbocchio</groupId>
+            <artifactId>jasypt-spring-boot-starter</artifactId>
+            <version>2.1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>2.3.3</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.velocity</groupId>
+            <artifactId>velocity-engine-core</artifactId>
+            <version>2.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.yh.saas</groupId>
+            <artifactId>winsea-saas-common-support</artifactId>
+            <version>${winsea.saas.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.yh.saas</groupId>
+            <artifactId>winsea-saas-toolkit-ie</artifactId>
+            <version>${winsea.saas.version}</version>
+            <classifier>standard</classifier>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.freemarker</groupId>
+            <artifactId>freemarker</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.github.yedaxia</groupId>
+            <artifactId>japidocs</artifactId>
+            <version>1.4.3</version>
+        </dependency>
+        <!-- 消息 -->
+        <dependency>
+            <groupId>com.winsea.svc</groupId>
+            <artifactId>winsea-notice-service-gateway</artifactId>
+            <version>1.0.0</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.winsea.svc</groupId>
+                    <artifactId>winsea-notice-service-spi</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.winsea.svc</groupId>
+                    <artifactId>winsea-base-service-spi</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.alipay.sofa</groupId>
+                    <artifactId>rpc-sofa-boot-starter</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.winsea.svc</groupId>
+                    <artifactId>winsea-standard-service-support</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+
+        <!-- 共通base -->
+        <dependency>
+            <groupId>com.winsea.svc</groupId>
+            <artifactId>winsea-base-service-gateway</artifactId>
+            <version>0.7.0</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.winsea.svc</groupId>
+                    <artifactId>winsea-base-service-spi</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.winsea.svc</groupId>
+                    <artifactId>winsea-standard-service-support</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.alipay.sofa</groupId>
+                    <artifactId>rpc-sofa-boot-starter</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+    </dependencies>
+
+    <profiles>
+        <profile>
+            <id>local</id>
+            <properties>
+                <env>local</env>
+            </properties>
+            <activation>
+                <activeByDefault>true</activeByDefault>
+            </activation>
+        </profile>
+        <profile>
+            <id>dev</id>
+            <properties>
+                <env>dev</env>
+            </properties>
+        </profile>
+        <profile>
+            <id>test</id>
+            <properties>
+                <env>test</env>
+            </properties>
+        </profile>
+        <profile>
+            <id>prod</id>
+            <properties>
+                <env>prod</env>
+            </properties>
+
+
+        </profile>
+    </profiles>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                    <encoding>UTF-8</encoding>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+
+</project>

+ 187 - 0
winsea-haixin-platform-backend/pom.xml

@@ -0,0 +1,187 @@
+<?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>winsea-haixin</artifactId>
+        <groupId>com.yh.haixin</groupId>
+        <version>0.7.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>winsea-haixin-platform-backend</artifactId>
+    <packaging>jar</packaging>
+
+    <repositories>
+        <repository>
+            <id>aliyun</id>
+            <name>aliyun-maven</name>
+            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
+        </repository>
+        <repository>
+            <id>maven-public</id>
+            <url>http://maven.zthymaoyi.com/nexus/repository/maven-public/</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+    </repositories>
+    <pluginRepositories>
+        <pluginRepository>
+            <id>aliyun</id>
+            <name>aliyun-maven</name>
+            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
+        </pluginRepository>
+    </pluginRepositories>
+    <distributionManagement>
+        <repository>
+            <id>maven-releases</id>
+            <name>Nexus Release Repository</name>
+            <url>http://maven.zthymaoyi.com/nexus/repository/maven-releases/</url>
+        </repository>
+        <snapshotRepository>
+            <id>maven-snapshots</id>
+            <name>Nexus Snapshot Repository</name>
+            <url>http://maven.zthymaoyi.com/nexus/repository/maven-snapshots/</url>
+        </snapshotRepository>
+    </distributionManagement>
+    <dependencies>
+
+        <!--海务模块-->
+<!--        <dependency>-->
+<!--            <groupId>com.yh.haixin</groupId>-->
+<!--            <artifactId>winsea-haixin-plugin-monitor</artifactId>-->
+<!--            <version>0.7.0</version>-->
+<!--        </dependency>-->
+        <!--公告模块-->
+        <dependency>
+            <groupId>com.yh.haixin</groupId>
+            <artifactId>winsea-haixin-plugin-configuration</artifactId>
+            <version>0.7.0</version>
+        </dependency>
+        <!--船员模块-->
+<!--        <dependency>-->
+<!--            <groupId>com.yh.haixin</groupId>-->
+<!--            <artifactId>winsea-haixin-plugin-crew</artifactId>-->
+<!--            <version>0.7.0</version>-->
+<!--        </dependency>-->
+        <!--云盘模块-->
+        <dependency>
+            <groupId>com.yh.haixin</groupId>
+            <artifactId>winsea-haixin-plugin-clouddisk</artifactId>
+            <version>0.7.0</version>
+        </dependency>
+        <!--易粮易云-->
+        <dependency>
+            <groupId>com.yh.haixin</groupId>
+            <artifactId>winsea-haixin-plugin-yiliangyiyun</artifactId>
+            <version>0.7.0</version>
+        </dependency>
+        <!--油品模块-->
+<!--        <dependency>-->
+<!--            <groupId>com.yh.haixin</groupId>-->
+<!--            <artifactId>winsea-haixin-plugin-oil</artifactId>-->
+<!--            <version>0.7.0</version>-->
+<!--        </dependency>-->
+        <!--船舶证书模块-->
+<!--        <dependency>-->
+<!--            <groupId>com.yh.haixin</groupId>-->
+<!--            <artifactId>winsea-haixin-plugin-certificate</artifactId>-->
+<!--            <version>0.7.0</version>-->
+<!--        </dependency>-->
+        <!--维修保养模块-->
+<!--        <dependency>-->
+<!--            <groupId>com.yh.haixin</groupId>-->
+<!--            <artifactId>winsea-haixin-plugin-maintain</artifactId>-->
+<!--            <version>0.7.0</version>-->
+<!--        </dependency>-->
+        <!--采购模块、备件模块、物料模块-->
+<!--        <dependency>-->
+<!--            <groupId>com.yh.haixin</groupId>-->
+<!--            <artifactId>winsea-haixin-plugin-purchase</artifactId>-->
+<!--            <version>0.7.0</version>-->
+<!--        </dependency>-->
+        <!--新闻模块-->
+        <dependency>
+            <groupId>com.yh.haixin</groupId>
+            <artifactId>winsea-haixin-plugin-news</artifactId>
+            <version>0.7.0</version>
+        </dependency>
+        <!--财务模块-->
+<!--        <dependency>-->
+<!--            <groupId>com.yh.haixin</groupId>-->
+<!--            <artifactId>winsea-haixin-plugin-finance</artifactId>-->
+<!--            <version>0.7.0</version>-->
+<!--        </dependency>-->
+        <!--服务商模块-->
+        <dependency>
+            <groupId>com.yh.haixin</groupId>
+            <artifactId>winsea-haixin-plugin-servicer</artifactId>
+            <version>0.7.0</version>
+        </dependency>
+        <!--运营后台、企业后台-->
+        <dependency>
+            <groupId>com.yh.haixin</groupId>
+            <artifactId>winsea-haixin-plugin-operation</artifactId>
+            <version>0.7.0</version>
+        </dependency>
+        <!--修船-->
+<!--        <dependency>-->
+<!--            <groupId>com.yh.haixin</groupId>-->
+<!--            <artifactId>winsea-haixin-plugin-repair</artifactId>-->
+<!--            <version>0.7.0</version>-->
+<!--        </dependency>-->
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-websocket</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>5.1.38</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-websocket</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-messaging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot</artifactId>
+            <version>2.1.1.RELEASE</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-autoconfigure</artifactId>
+            <version>2.1.1.RELEASE</version>
+        </dependency>
+        <dependency>
+            <groupId>io.github.yedaxia</groupId>
+            <artifactId>japidocs</artifactId>
+            <version>1.4.3</version>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+
+</project>

+ 79 - 0
winsea-haixin-platform-backend/src/main/java/com/alipay/sofa/runtime/api/annotation/SofaMethod.java

@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alipay.sofa.runtime.api.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author bystander
+ * @since 2.6.4
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface SofaMethod {
+
+    /**
+     * method name
+     *
+     * @return method name
+     * @since 2.6.4
+     */
+    String name() default "";
+
+    /**
+     * timeout
+     *
+     * @return timeout
+     * @since 2.6.4
+     */
+    int timeout() default 6000;
+
+    /**
+     * retry times
+     *
+     * @return retry times
+     * @since 2.6.4
+     */
+    int retries() default 0;
+
+    /**
+     * invoke type
+     *
+     * @return invoke type
+     * @since 2.6.4
+     */
+    String invokeType() default "sync";
+
+    /**
+     * callback implementation class name
+     *
+     * @return callback implementation class name
+     * @since 2.6.4
+     */
+    String callbackClass() default "";
+
+    /**
+     * callback spring beanName ref
+     *
+     * @return callback spring beanName ref
+     * @since 2.6.4
+     */
+    String callbackRef() default "";
+}

+ 37 - 0
winsea-haixin-platform-backend/src/main/java/com/alipay/sofa/runtime/api/annotation/SofaParameter.java

@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alipay.sofa.runtime.api.annotation;
+
+/**
+ * Configure parameters by annotation
+ *
+ * @author <a href="mailto:scienjus@gmail.com">ScienJus</a>
+ */
+public @interface SofaParameter {
+
+    /**
+     * Parameter key
+     * @return
+     */
+    String key();
+
+    /**
+     * Parameter value
+     * @return
+     */
+    String value();
+}

+ 85 - 0
winsea-haixin-platform-backend/src/main/java/com/alipay/sofa/runtime/api/annotation/SofaReference.java

@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alipay.sofa.runtime.api.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.annotation.AliasFor;
+
+
+/**
+ * Annotation used to create a SOFA reference and set it to the annotated field
+ * of a Spring bean. Sample usage:
+ *
+ * <pre>
+ *
+ * public class ReferenceAnnotationSample {
+ *
+ * 	&#064;SofaReference
+ * 	private SampleService sampleService;
+ * }
+ * </pre>
+ *
+ * @author xuanbei 18/3/2
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
+@Autowired
+public @interface SofaReference {
+
+    /**
+     * Declares whether the annotated dependency is required.
+     * <p>
+     * Defaults to {@code true}.
+     */
+    @AliasFor(annotation = Autowired.class, attribute = "required")
+    boolean required() default false;
+
+    /**
+     * The type of the SOFA reference to be created. Default to the type of field
+     * annotated when not specified.
+     *
+     * @return return interface type
+     */
+    Class<?> interfaceType() default void.class;
+
+    /**
+     * The unique id of the SOFA reference to be created. Default to an empty string
+     * when not specified.
+     *
+     * @return return reference unique-id
+     */
+    String uniqueId() default "";
+
+    /**
+     * invoke jvm service first
+     *
+     * @return is jvm first or not
+     */
+    boolean jvmFirst() default true;
+
+    /**
+     * binding of reference
+     *
+     * @return binding of reference
+     */
+    SofaReferenceBinding binding() default @SofaReferenceBinding(bindingType = "bolt");
+}

+ 160 - 0
winsea-haixin-platform-backend/src/main/java/com/alipay/sofa/runtime/api/annotation/SofaReferenceBinding.java

@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alipay.sofa.runtime.api.annotation;
+
+/**
+ * @author xuanbei 18/5/11
+ */
+public @interface SofaReferenceBinding {
+    /**
+     * binding type, maybe jvm/bolt/rest
+     *
+     * @return binding type
+     */
+    String bindingType() default "jvm";
+
+    /**
+     * timeout
+     *
+     * @return timeout
+     */
+    int timeout() default 6000;
+
+    /**
+     * retry times
+     *
+     * @return retry times
+     */
+    int retries() default 0;
+
+    /**
+     * address time out
+     *
+     * @return address time out
+     */
+    int addressWaitTime() default 0;
+
+    /**
+     * invoke type
+     *
+     * @return invoke type
+     */
+    String invokeType() default "sync";
+
+    /**
+     * filter beans
+     *
+     * @return filter beans
+     */
+    String[] filters() default {};
+
+    /**
+     * direct url
+     *
+     * @return direct url
+     */
+    String directUrl() default "";
+
+    /**
+     * @return callback handler
+     * @deprecated this attribute is not intended for use and will be removed the next major version.
+     * callback handler
+     */
+    @Deprecated
+    String callbackHandler() default "";
+
+    /**
+     * callback implementation class name
+     *
+     * @return callback implementation class name
+     * @since 2.5.0
+     */
+    String callbackClass() default "";
+
+    /**
+     * callback spring beanName ref
+     *
+     * @return callback spring beanName ref
+     * @since 2.5.0
+     */
+    String callbackRef() default "";
+
+    /**
+     * registry for this consumer
+     *
+     * @return registry for this consumer
+     */
+    String registry() default "";
+
+    /**
+     * delay init connection
+     *
+     * @return
+     */
+    boolean lazy() default false;
+
+    /**
+     * specify serialize type
+     *
+     * @return
+     */
+    String serializeType() default "";
+
+    /**
+     * specify load balance type
+     *
+     * @return
+     */
+    String loadBalancer() default "";
+
+    /**
+     * parameters of consumer
+     *
+     * @return parameters of consumer
+     */
+    SofaParameter[] parameters() default {};
+
+    /**
+     * serialization between biz, default is false.
+     * only serialize of reference and service is false
+     * then invocation between biz would skip serialization
+     * Note that the serialize of {@link SofaServiceBinding} is true
+     *
+     * @return
+     */
+    boolean serialize() default false;
+
+    /**
+     * for each method config
+     *
+     * @return method configs
+     * @since 2.6.4
+     */
+    SofaMethod[] methodInfos() default {};
+
+    /**
+     * mock mode of reference
+     * @return "local", "remote" or empty
+     */
+    String mockMode() default "";
+
+    /**
+     * get mock from spring beans
+     * @return bean name
+     */
+    String mockBean() default "";
+}

+ 85 - 0
winsea-haixin-platform-backend/src/main/java/com/alipay/sofa/runtime/api/annotation/SofaService.java

@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alipay.sofa.runtime.api.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.springframework.core.annotation.AliasFor;
+import org.springframework.stereotype.Service;
+
+
+/**
+ * Annotation used to create a SOFA service of a spring bean. Sample usage:
+ *
+ * <pre>
+ *
+ * &#064;SofaService(uniqueId = &quot;aop&quot;)
+ * public class SampleServiceImpl implements SampleService {
+ *
+ * 	&#064;Override
+ * 	public String say() {
+ * 		return &quot;sampleService&quot;;
+ *    }
+ * }
+ * </pre>
+ *
+ * @author xuanbei 18/3/1
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+@Service
+public @interface SofaService {
+
+    /**
+     * The value may indicate a suggestion for a logical component name, to be
+     * turned into a Spring bean in case of an autodetected component.
+     *
+     * @return the suggested component name, if any (or empty String otherwise)
+     */
+    @AliasFor(annotation = Service.class, attribute = "value")
+    String value() default "";
+
+    /**
+     * The interface type of the SOFA service to be create. Default to the only
+     * interface of the annotated Spring bean when not specified. When the annotated
+     * Spring bean has more than one interface, this field must be specified. When
+     * you want to create a SOFA service which's interface type is not a java
+     * interface but and concrete java class, this field must be specified.
+     *
+     * @return return interface type
+     */
+    Class<?> interfaceType() default void.class;
+
+    /**
+     * The unique id of the SOFA service to be created. Default to an empty string
+     * when not specified.
+     *
+     * @return return service unique-id
+     */
+    String uniqueId() default "";
+
+    /**
+     * bindings of service
+     *
+     * @return bindings of service
+     */
+    SofaServiceBinding[] bindings() default {
+            @SofaServiceBinding(bindingType = "bolt")};
+}

+ 111 - 0
winsea-haixin-platform-backend/src/main/java/com/alipay/sofa/runtime/api/annotation/SofaServiceBinding.java

@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alipay.sofa.runtime.api.annotation;
+
+/**
+ * @author xuanbei 18/5/11
+ */
+public @interface SofaServiceBinding {
+    /**
+     * binding type, maybe jvm/bolt/rest
+     *
+     * @return binding type
+     */
+    String bindingType() default "jvm";
+
+    /**
+     * normal weight, default is 100
+     *
+     * @return normal weight
+     */
+    int weight() default 0;
+
+    /**
+     * when warmup, the weight.
+     *
+     * @return warmup weight
+     */
+    int warmUpWeight() default 0;
+
+    /**
+     * warmup time, default is 0
+     *
+     * @return warmup time
+     */
+    int warmUpTime() default 0;
+
+    /**
+     * filter beans
+     *
+     * @return filter beans
+     */
+    String[] filters() default {};
+
+    /**
+     * custom thread pool for current service
+     *
+     * @return custom thread pool
+     */
+    String userThreadPool() default "";
+
+    /**
+     * registry for this service
+     *
+     * @return registry for this service
+     */
+    String registry() default "";
+
+    /**
+     * timeout
+     *
+     * @return timeout
+     */
+    int timeout() default 6000;
+
+    /**
+     * specify serialize type
+     *
+     * @return
+     */
+    String serializeType() default "";
+
+    /**
+     * parameters of service
+     *
+     * @return parameters of service
+     */
+    SofaParameter[] parameters() default {};
+
+    /**
+     * serialization between biz, default is true.
+     * only serialize of reference and service is false
+     * then invocation between biz would skip serialization
+     *
+     * Note that the serialize of {@link SofaReferenceBinding} is false
+     *
+     * @return
+     */
+    boolean serialize() default true;
+
+    /**
+     * for each method config
+     *
+     * @return method configs
+     * @since 2.6.4
+     */
+    SofaMethod[] methodInfos() default {};
+}

+ 32 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/PlatformApplication.java

@@ -0,0 +1,32 @@
+package com.yh.saas;
+
+import com.winsea.svc.common.annotation.EnableService;
+import org.activiti.spring.boot.SecurityAutoConfiguration;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+@SpringBootApplication(exclude = SecurityAutoConfiguration.class)
+@EnableTransactionManagement
+@EnableScheduling // 开始定时任务
+@EnableService
+@ComponentScan(value = {
+        "com.yh.saas",
+        "com.winsea.svc"})
+public class PlatformApplication extends SpringBootServletInitializer {
+
+    public static void main(String[] args) {
+        //发送邮件传输附件用
+        System.setProperty("mail.mime.splitlongparameters", "false");
+        SpringApplication.run(PlatformApplication.class, args);
+    }
+
+    @Override
+    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+        System.setProperty("mail.mime.splitlongparameters", "false");
+        return application.sources(PlatformApplication.class);
+    }
+}

+ 19 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/config/AccessInterceptor.java

@@ -0,0 +1,19 @@
+package com.yh.saas.platform.config;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.web.servlet.HandlerInterceptor;
+
+public class AccessInterceptor implements HandlerInterceptor {
+
+	@Override
+	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
+		response.setHeader("Access-Control-Allow-Credentials", "true");
+		response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
+		response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept,Token");
+		response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH");
+		response.setHeader("Access-Control-Expose-Headers", "Token");
+		return true;
+	}
+}

+ 25 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/config/PlatformConfig.java

@@ -0,0 +1,25 @@
+package com.yh.saas.platform.config;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
+
+import com.yh.saas.common.support.gateway.EnableAccessLog;
+import com.yh.saas.common.support.gateway.EnableResponseWrapper;
+
+/**
+ * 平台配置
+ * 
+ * @author gdc
+ *
+ */
+@MapperScan({ "com.yh.saas.platform.mapper" })
+@EnableTransactionManagement
+@EnableAccessLog // 开启访问日志
+@EnableResponseWrapper(ignores = { "/swagger-resources.*", "/v2/api-docs", "/webjars.*" }) // 开启response封装
+@Configuration
+public class PlatformConfig implements WebMvcConfigurer {
+	
+}

+ 48 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/config/PluginFeatureAspect.java

@@ -0,0 +1,48 @@
+package com.yh.saas.platform.config;
+
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.stereotype.Component;
+
+import com.alipay.sofa.runtime.api.annotation.SofaReference;
+import com.winsea.svc.base.base.service.IAccountOperationHistoryService;
+import com.winsea.svc.base.security.service.IAccountService;
+import com.winsea.svc.base.security.util.AuthSecurityUtils;
+import com.yh.saas.common.support.plugin.PluginFeature;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * <p>
+ * 操作历史截面
+ * </p>
+ *
+ * @author ZhangMingYu
+ * @since 2020年3月6日13:06:39
+ */
+@Aspect
+@Component
+@Slf4j
+public class PluginFeatureAspect {
+
+	@SofaReference
+	private IAccountOperationHistoryService accountOperationHistoryService;
+
+	@SofaReference
+	private IAccountService accountService;
+
+	@Pointcut("@annotation(com.yh.saas.common.support.plugin.PluginFeature)")
+	public void aspect() {
+	}
+
+	@Before("aspect()&&@annotation(pluginFeature)")
+	public void deBefore(PluginFeature pluginFeature) {
+		if (null == AuthSecurityUtils.getCurrentUserInfo()) {
+			accountService.logout();
+		}
+		String accountId = AuthSecurityUtils.getCurrentUserInfo().getUserId();
+		accountOperationHistoryService.create(accountId, pluginFeature.id(), pluginFeature.name(),
+				pluginFeature.desc());
+	}
+}

+ 30 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/config/SMSConfigYlyy.java

@@ -0,0 +1,30 @@
+package com.yh.saas.platform.config;
+
+
+import com.yh.saas.plugin.yiliangyiyun.util.AliyunSMSClient;
+import com.yh.saas.plugin.yiliangyiyun.util.MockSMSClient;
+import com.yh.saas.plugin.yiliangyiyun.util.SMSClientYlyy;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * Created by rize on 2019/7/2.
+ */
+@Configuration
+public class SMSConfigYlyy {
+
+    @Value("${sms.enable}")
+    private String enable;
+
+    @Bean
+    public SMSClientYlyy smsClientYlyy() {
+        if ("aliyun".equals(enable)) {
+            return new AliyunSMSClient();
+        } else if ("mock".equals(enable)) {
+            return new MockSMSClient();
+        } else {
+            return new MockSMSClient();
+        }
+    }
+}

+ 13 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/constants/Constants.java

@@ -0,0 +1,13 @@
+package com.yh.saas.platform.constants;
+
+/**
+ * 常量定义
+ * 
+ * @author gdc
+ *
+ */
+public class Constants {
+
+	private Constants() {
+	}
+}

+ 39 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/AccountResultController.java

@@ -0,0 +1,39 @@
+package com.yh.saas.platform.controller;
+
+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 com.alipay.sofa.runtime.api.annotation.SofaReference;
+import com.winsea.svc.base.base.entity.AccountResult;
+import com.winsea.svc.base.base.service.IAccountResultService;
+import com.winsea.svc.base.security.util.AuthSecurityUtils;
+import com.yh.saas.common.support.util.StringUtils;
+
+/**
+ * <p>
+ * APP使用 - 登录写入推送ID
+ * </p>
+ *
+ * @author ZhangMingyu
+ * @since 2020年2月26日11:15:43
+ */
+
+@RestController
+@RequestMapping("/accountResultId")
+public class AccountResultController {
+
+	@SofaReference
+	private IAccountResultService accountResultService;
+
+	@PostMapping("/api/setReg")
+	public void setReg(@RequestBody AccountResult accountResult) {
+		String accountId = AuthSecurityUtils.getCurrentUserInfo().getAccountId();
+		if (StringUtils.isEmpty(accountId)) {
+			// TODO 需要添加空登录人错误
+			return;
+		}
+		accountResultService.create(accountId, accountResult.getRegId());
+	}
+}

+ 352 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/AppendixController.java

@@ -0,0 +1,352 @@
+package com.yh.saas.platform.controller;
+
+import ch.qos.logback.classic.Logger;
+import com.alibaba.fastjson.JSONObject;
+import com.alipay.sofa.runtime.api.annotation.SofaReference;
+import com.aliyun.oss.OSSClient;
+import com.aliyun.oss.model.ObjectMetadata;
+import com.aliyun.oss.model.PutObjectRequest;
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.baomidou.mybatisplus.mapper.Wrapper;
+import com.baomidou.mybatisplus.toolkit.CollectionUtils;
+import com.winsea.svc.base.base.entity.CommonAppendix;
+import com.winsea.svc.base.base.service.IAppendixService;
+import com.winsea.svc.base.base.util.AppendixWrapper;
+import com.winsea.svc.base.base.util.ClientTypeChecker;
+import com.winsea.svc.base.base.util.DateUtils;
+import com.winsea.svc.base.base.view.CommonAppendixView;
+import com.winsea.svc.base.security.util.AuthSecurityUtils;
+import com.yh.saas.platform.util.GtAppendixUtil;
+import com.yh.saas.plugin.yiliangyiyun.util.GeneratorUtil;
+import lombok.Getter;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.tomcat.util.http.fileupload.util.Streams;
+import org.apache.velocity.shaded.commons.io.FilenameUtils;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.multipart.MultipartHttpServletRequest;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.text.MessageFormat;
+import java.util.*;
+import java.util.zip.ZipOutputStream;
+
+/**
+ * <p>
+ * 附件表 前端控制器
+ * </p>
+ *
+ * @author zhaojz
+ * @since 2019-03-25
+ */
+@RestController
+@RequestMapping("/appendix")
+public class AppendixController implements InitializingBean {
+
+    private Logger log = (Logger) LoggerFactory.getLogger(this.getClass());
+
+    private static final String FILE_SEPERATOR = "/";
+
+    @SofaReference
+    private IAppendixService appendixService;
+
+    @Autowired
+    private AppendixWrapper appendixWrapper;
+
+    @Value("${file-root-path}")
+    private String fileRootPath;
+
+    @Value("${front-origin}")
+    private String frontOrigin;
+
+    @Getter
+    @Value("${oss.bucket.name:}")
+    private String bucketName;
+
+    @Getter
+    @Value("${oss.endpoint.default:}")
+    private String endpoint;
+
+    @Value("${server.port:}")
+    private String port;
+
+    @Value("${oss.isUsed:true}") // 默认使用OSS存储 即使不在.properties配置 默认是true
+    private boolean isOssUsed;
+
+    static final String LOCAL_PERFIX_URL = "http://127.0.0.1:{0}/";
+
+    static final String OSS_PERFIX_URL = "https://{0}.{1}/";
+
+    private String host;
+
+    @Getter
+    @Value("${oss.endpoint.internal:}")
+    private String baseUrl;
+    @Autowired
+    private OSSClient ossClient;
+    @Override
+    public void afterPropertiesSet() throws Exception {
+        host = "http://" + bucketName + "." + endpoint;
+    }
+    /**
+     * 查询附件
+     * @return
+     */
+    @GetMapping("/query/getFileList")
+    public List<CommonAppendix> getFileList(@RequestParam String appendixIds) {
+        List<CommonAppendix> list = appendixService.selectBatchIds(Arrays.asList(appendixIds.split(",")));
+        return list;
+    }
+
+    /**
+     * 批量下载附件
+     */
+    @GetMapping("/download/batchAttachment")
+    public void batchDownload(@RequestParam String appendixIds, @RequestParam String zipName) {
+        List<String> appendixIdList = new ArrayList<>();
+        if (appendixIds.contains(",")) {
+            appendixIdList = Arrays.asList(appendixIds.split(","));
+        } else {
+            appendixIdList.add(appendixIds);
+        }
+        List<CommonAppendix> appendices = this.appendixService.getAppendixs(appendixIdList);
+        appendixWrapper.packAndDownloadByIdList(appendices, zipName);
+    }
+
+    /**
+     * 保存附件
+     *
+     * @return
+     */
+    @PostMapping("/api/saveFiles")
+    public List<String> saveFiles(@RequestBody CommonAppendixView appendixView) {
+        if (CollectionUtils.isNotEmpty(appendixView.getNewAppendixs())) {
+            String compId = AuthSecurityUtils.getCurrentUserInfo().getCompId();
+            appendixView.getNewAppendixs().stream().forEach(appendix -> appendix.setCompId(compId));
+        }
+        return appendixService.saveFiles(appendixView.getNewAppendixs(), appendixView.getOldAppendixIds());
+    }
+
+    /**
+     * 删除附件
+     *
+     * @return
+     */
+    @PostMapping("/api/deleteFiles")
+    public void deleteFiles(String appendixIds) {
+        if (StringUtils.isNotBlank(appendixIds)) {
+            appendixService.deleteBatchIds(Arrays.asList(appendixIds.split(",")));
+        }
+    }
+
+    /**
+     * 关联附件
+     *
+     * @param appendixIds
+     * @param modelId
+     * @return
+     */
+    @PostMapping("/api/relateFiles")
+    public void relateFiles(String appendixIds, String modelId) {
+        appendixService.relateAppendixs(appendixIds, modelId);
+    }
+
+    /**
+     * 单个附件下载
+     *
+     * @param request
+     * @param response
+     */
+    @GetMapping("/api/singleDownLoadFile")
+    public HttpServletResponse singleDownLoadFile(HttpServletRequest request, HttpServletResponse response) {
+        String appendixId = request.getParameter("appendixId");
+        return getCommonAppendixOutputStream(request, response, appendixId);
+    }
+
+    public HttpServletResponse getCommonAppendixOutputStream(HttpServletRequest request, HttpServletResponse response, String appendixId) {
+        try {
+            List<File> fileList = new ArrayList<>();
+            CommonAppendix appendixs = appendixService.selectById(appendixId);
+            // path是指欲下载的文件的路径。
+            File file = new File(fileRootPath + URLDecoder.decode(appendixs.getAppendixPath(), String.valueOf(StandardCharsets.UTF_8)));
+            // 取得文件名。
+            String filename = appendixs.getAppendixName();
+
+            // 以流的形式下载文件。
+            InputStream fis = new BufferedInputStream(new FileInputStream(fileRootPath + URLDecoder.decode(appendixs.getAppendixPath(), String.valueOf(StandardCharsets.UTF_8))));
+            byte[] buffer = new byte[fis.available()];
+            fis.read(buffer);
+            fis.close();
+            // 清空response
+            response.reset();
+            // 设置response的Header
+            response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes(StandardCharsets.UTF_8), "ISO8859-1"));
+            response.addHeader("Content-Length", "" + file.length());
+            OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
+            response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
+            response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
+            response.setHeader("Access-Control-Allow-Credentials", "true");
+            toClient.write(buffer);
+            toClient.flush();
+            toClient.close();
+        } catch (IOException ex) {
+            log.error("下载失败", ex);
+        }
+        return response;
+    }
+
+
+    /**
+     * 上传附件
+     *
+     * @param request
+     * @return
+     */
+    @PostMapping("/api/uploadFiles")
+    public Object uploadFiles(HttpServletRequest request) {
+        List<MultipartFile> files = ((MultipartHttpServletRequest) request).getFiles("fileName");
+        if (files.isEmpty()) {
+            return null;
+        }
+        String companyId = request.getParameter("companyId");
+        for (MultipartFile file : files) {
+            String fileName = file.getOriginalFilename();
+            fileName = fileName.substring(0, fileName.lastIndexOf("."));
+            try {
+                CommonAppendix appendix = new CommonAppendix();
+                appendix.setAppendixName(
+                        fileName + file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")));
+                String path = upload(file,file.getOriginalFilename(),companyId);
+                appendix.setAppendixPath(path);
+                int size = (int) file.getSize();
+                appendix.setAppendixSize(GtAppendixUtil.getFileSize(size));
+                log.info("文件上传成功 地址:", path);
+                return appendix;
+            } catch (Exception e) {
+                log.error("文件上传失败", e.toString());
+            }
+            finally {
+//                dest.delete();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 打包下载附件
+     *
+     * @param request
+     * @param response
+     */
+    @PostMapping("/api/downLoadFiles")
+    public void downLoadFiles(HttpServletRequest request, HttpServletResponse response) {
+        String billId = request.getParameter("billId");
+        try {
+            if (StringUtils.isBlank(frontOrigin)) {
+                response.getWriter().print(JSONObject.toJSON(this.getPrintJson("noPermission")));
+                return;
+            }
+            String[] allowDomain = frontOrigin.split(",");
+            String requestOrigin = request.getHeader("Origin");
+            Set<String> allowedOrigins = new HashSet<>(Arrays.asList(allowDomain));
+            if (!allowedOrigins.contains(requestOrigin)) {
+                response.getWriter().print(JSONObject.toJSON(this.getPrintJson("noPermission")));
+                return;
+            }
+            List<File> fileList = new ArrayList<>();
+            List<CommonAppendix> appendixs = this.selectAppendixList(billId);
+            // 添加前缀
+            addPrefix(appendixs);
+            if (CollectionUtils.isEmpty(appendixs) || StringUtils.isBlank(frontOrigin)) {
+                response.getWriter().print(JSONObject.toJSON(this.getPrintJson("noFileData")));
+                return;
+            }
+            for (CommonAppendix appendix : appendixs) {
+                File file = new File(fileRootPath + File.separator + appendix.getAppendixPath());
+                if (!file.exists()) {
+                    continue;
+                }
+                fileList.add(file);
+            }
+            File rootFile = new File(fileRootPath + File.separator + "tempFile.zip");
+            if (!rootFile.exists()) {
+                boolean result = rootFile.createNewFile();
+                if (!result) {
+                    log.warn(rootFile.getAbsolutePath() + "创建失败!");
+                }
+            }
+            // 创建文件输出流
+            try (FileOutputStream fous = new FileOutputStream(rootFile);
+                 ZipOutputStream zipOut = new ZipOutputStream(fous)) {
+                GtAppendixUtil.zipFiles(fileList, zipOut);
+                GtAppendixUtil.downloadZip(rootFile, requestOrigin, response);
+            }
+        } catch (Exception e) {
+            log.error("文删除失败", e);
+        }
+    }
+
+    /**
+     * 查询要打包的附件
+     *
+     * @param billIds
+     * @return
+     */
+    private List<CommonAppendix> selectAppendixList(String billIds) {
+        String[] billIdArr = billIds.split(",");
+        List<CommonAppendix> appendixs = new ArrayList<>();
+        for (String billId : billIdArr) {
+            Wrapper<CommonAppendix> wrapper = new EntityWrapper<CommonAppendix>().eq("delete_flag", "0").eq("bill_id",
+                    billId);
+            List<CommonAppendix> dataList = appendixService.selectList(wrapper);
+            if (!CollectionUtils.isEmpty(dataList)) {
+                appendixs.addAll(dataList);
+            }
+        }
+        return appendixs;
+    }
+
+    private Map<String, String> getPrintJson(String dataMsg) {
+        Map<String, String> resultMap = new HashMap<>();
+        resultMap.put("code", String.valueOf(HttpServletResponse.SC_OK));
+        resultMap.put("data", dataMsg);
+        resultMap.put("message", "Success");
+        return resultMap;
+    }
+
+    /**
+     * 添加前缀
+     *
+     * @param list
+     */
+    private void addPrefix(List<CommonAppendix> list) {
+        if (ClientTypeChecker.isLandBased()) {
+            String prefixUrl = MessageFormat.format(OSS_PERFIX_URL, bucketName, endpoint);
+            list.stream().filter(appendix -> !StringUtils.startsWith(appendix.getAppendixPath(), "http"))
+                    .forEach(appendix -> appendix.setAppendixPath(prefixUrl + appendix.getAppendixPath()));
+        }
+    }
+    /**
+     * 后台通过服务器间接传文件
+     * @param file
+     * @return
+     * @throws IOException
+     */
+    public  String upload(MultipartFile file,String name,String companyId) throws IOException {
+        ObjectMetadata objectMetadata = new ObjectMetadata();
+        objectMetadata.setContentLength(file.getSize());
+        objectMetadata.setContentType(file.getContentType());
+        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, "eliangeyun/"+companyId+"/" +name, file.getInputStream(), objectMetadata);
+        ossClient.putObject(putObjectRequest);
+        return baseUrl + "eliangeyun/" +companyId+"/" +name;
+    }
+}

+ 41 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/BIController.java

@@ -0,0 +1,41 @@
+package com.yh.saas.platform.controller;
+
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.yh.saas.platform.service.IBIService;
+
+/**
+ * BI接口
+ * 
+ * @author gdc
+ */
+@RequestMapping("/bi")
+@RestController
+public class BIController {
+
+	@Autowired
+	private IBIService biService;
+
+	/**
+	 * 获取BI报表路径
+	 * 
+	 * @param params 请求参数
+	 * @return BI报表路径
+	 */
+	@GetMapping("/query/reportUrl")
+	public String getReportUrl(@RequestParam Map<String, String> params) {
+		String operation = params.remove("operation");
+		String reportName = params.remove("reportName");
+		String exportFormat = params.remove("exportFormat");
+		if (null == operation || null == reportName) {
+			return null;
+		}
+		return biService.getReportUrl(operation, reportName, exportFormat, params);
+	}
+}

+ 39 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/BillOperateHisController.java

@@ -0,0 +1,39 @@
+package com.yh.saas.platform.controller;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.yh.saas.platform.service.IBillOperateHisService;
+import com.yh.saas.plugin.base.entity.CommonBillOperateHis;
+
+/**
+ * <p>
+ * 记录单据操作历史 前端控制器
+ * </p>
+ *
+ * @author SongJin
+ * @since 2020-01-03
+ */
+@RestController
+@RequestMapping("/billOperateHis")
+public class BillOperateHisController {
+
+    @Autowired
+    private IBillOperateHisService billOperateHisService;
+
+    /**
+     * 操作历史查询
+     *
+     * @param
+     * @return
+     */
+    @GetMapping("/query/commonBillOperateHis")
+    public List<CommonBillOperateHis> getBillOperateHis(@RequestParam String id,String billType) {
+        return this.billOperateHisService.getBillOperateHis(id,billType);
+    }
+}

+ 36 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/CommonParameterCompanyController.java

@@ -0,0 +1,36 @@
+package com.yh.saas.platform.controller;
+
+import com.winsea.svc.base.base.entity.CommonParameterCompany;
+import com.yh.saas.platform.service.CommonParameterCompanyService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 公司变量 前端控制器
+ * </p>
+ *
+ * @author Wangxiangshun
+ * @since 2021-02-19
+ */
+@RestController
+@RequestMapping("/compParameter")
+public class CommonParameterCompanyController {
+
+    @Autowired
+    private CommonParameterCompanyService commonParameterCompanyService;
+
+    /**
+     * 查询公司常量
+     * @return
+     */
+    @GetMapping("/query/selectList")
+    public List<CommonParameterCompany> getListCommon(String constCode,String businessCode) {
+        return commonParameterCompanyService.selectListParam(constCode,businessCode);
+    }
+
+}

+ 65 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/CompanyCustomDropDownController.java

@@ -0,0 +1,65 @@
+package com.yh.saas.platform.controller;
+
+import java.util.List;
+
+import org.springframework.web.bind.annotation.GetMapping;
+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 com.alipay.sofa.runtime.api.annotation.SofaReference;
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.winsea.svc.base.base.entity.CommonCustomDropDown;
+import com.winsea.svc.base.base.service.ICommonCustomDropDownService;
+
+/**
+ * <p>
+ * 'winsea_platform.certificate_view' is not BASE TABLE 前端控制器
+ * </p>
+ *
+ * @author jiangailong
+ * @since 2019-09-4
+ */
+@RestController
+@RequestMapping("/customDropDown")
+public class CompanyCustomDropDownController {
+
+	@SofaReference
+    private ICommonCustomDropDownService customDropDownService;
+
+    @GetMapping("/query/customDropDown")
+    public List<CommonCustomDropDown> queryCommonParameterTenant(CommonCustomDropDown parameterCompany) {
+        return customDropDownService.selectList(new EntityWrapper<CommonCustomDropDown>()
+                .eq(CommonCustomDropDown.QueryFields.COMP_ID, parameterCompany.getCompId())
+                .eq(CommonCustomDropDown.QueryFields.CONST_CODE, parameterCompany.getConstCode())
+                .setSqlSelect("const_code as constCode,const_key as constKey,const_value as constValue,id as id"));
+    }
+
+    /**
+     * 新增
+     *
+     * @param
+     */
+    @PostMapping("/api/saveAdd")
+    public String saveAdd(@RequestBody CommonCustomDropDown example) {
+    	return this.customDropDownService.create(example);
+    }
+
+    /**
+     * 编辑
+     */
+    @PostMapping("/api/saveEdit")
+    public void saveEdit(@RequestBody CommonCustomDropDown example) {
+        customDropDownService.updateAllColumnById(example);
+    }
+
+    /**
+     * 删除 da
+     */
+    @PostMapping("/api/saveDelete")
+    public void saveDelete(@RequestBody CommonCustomDropDown example) {
+        customDropDownService.deleteById(example.getId());
+    }
+}
+

+ 77 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/EmailConfigController.java

@@ -0,0 +1,77 @@
+package com.yh.saas.platform.controller;
+
+import java.util.List;
+
+import org.activiti.engine.impl.util.CollectionUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.web.bind.annotation.GetMapping;
+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.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.alipay.sofa.runtime.api.annotation.SofaReference;
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.winsea.svc.base.base.entity.CommonEmailConfig;
+import com.winsea.svc.base.base.service.ICommonEmailConfigService;
+import com.winsea.svc.base.security.util.AuthSecurityUtils;
+
+/**
+ * <p>
+ * 'winsea_platform.certificate_view' is not BASE TABLE 前端控制器
+ * </p>
+ *
+ * @author ZhangMingYu
+ * @since 2019-06-13
+ */
+@RestController
+@RequestMapping("/emailConfig")
+public class EmailConfigController {
+
+	@SofaReference
+	private ICommonEmailConfigService emailConfigService;
+
+	/**
+	 *
+	 * @param emailConfig 邮件配置信息
+	 * @return emailConfigID 邮件配置信息id
+	 */
+	@PostMapping("/api/create")
+	public String create(@RequestBody CommonEmailConfig emailConfig) {
+		emailConfig.setCompId(getCompId(emailConfig.getCompId()));
+		return emailConfigService.create(emailConfig);
+	}
+
+	/**
+	 *
+	 * @param compId 公司id
+	 * @param code   code
+	 * @return 邮件配置信息
+	 */
+	@GetMapping("/query/emailConfig")
+	public CommonEmailConfig emailConfig(@RequestParam String compId, @RequestParam String code) {
+		List<CommonEmailConfig> emailConfigs = emailConfigService.selectList(new EntityWrapper<CommonEmailConfig>()
+				.eq(CommonEmailConfig.QueryFields.COMP_ID, compId).eq(CommonEmailConfig.QueryFields.CODE, code));
+		return CollectionUtil.isEmpty(emailConfigs) ? null : emailConfigs.get(0);
+	}
+
+	/**
+	 *
+	 * @param emailConfig 邮件配置信息
+	 */
+	@PostMapping("/api/update")
+	public void update(@RequestBody CommonEmailConfig emailConfig) {
+		emailConfigService.updateById(emailConfig);
+	}
+
+	/**
+	 * 获取公司ID
+	 *
+	 * @param compId 公司ID
+	 * @return 公司ID
+	 */
+	private String getCompId(String compId) {
+		return !StringUtils.isEmpty(compId) ? compId : AuthSecurityUtils.getCurrentUserInfo().getCompId();
+	}
+}

+ 157 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/ExcelController.java

@@ -0,0 +1,157 @@
+package com.yh.saas.platform.controller;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.tomcat.util.http.fileupload.util.Streams;
+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;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.multipart.MultipartHttpServletRequest;
+
+import com.alipay.sofa.runtime.api.annotation.SofaReference;
+import com.winsea.svc.base.base.entity.CommonAppendix;
+import com.winsea.svc.base.base.service.IAppendixService;
+import com.winsea.svc.base.security.util.AuthSecurityUtils;
+import com.yh.saas.common.support.util.IdGenerator;
+import com.yh.saas.common.support.util.StringUtils;
+import com.yh.saas.platform.exception.EnterpriseErrorCodeEnums;
+import com.yh.saas.platform.exception.EnterpriseException;
+import com.yh.saas.toolkit.ie.util.ExcelTemplateUtils;
+
+/**
+ * <p>
+ * Excel存储 - Controller层
+ * </p>
+ *
+ * @author ZhangMingYu
+ * @since 2019年12月30日10:45:30
+ */
+
+@RestController
+@RequestMapping("/excel")
+public class ExcelController {
+
+	@Autowired
+	private ExcelTemplateUtils excelTemplateUtils;
+
+	@SofaReference
+	private IAppendixService appendixService;
+
+	private static final String EXCEL_TEMPLATE = "excelTemplate";
+
+	private static final String PRIVATE_PATH = "private";
+
+	private static final String PUBLIC_PATH = "public";
+
+	@PostMapping("/api/savePrivateTemplate")
+	public void savePrivateTemplate(HttpServletRequest request) throws IOException {
+		MultipartFile file = ((MultipartHttpServletRequest) request).getFile("template");
+		if (null == file) {
+			throw new EnterpriseException(EnterpriseErrorCodeEnums.EXCEL_TEMPLATE_FILE_NOT);
+		}
+		String compId = AuthSecurityUtils.getCurrentUserInfo().getCompId();
+		String serviceCode = request.getParameter("serviceCode");
+
+		if (StringUtils.isEmpty(compId) || StringUtils.isEmpty(serviceCode)) {
+			throw new EnterpriseException(EnterpriseErrorCodeEnums.EXCEL_TEMPLATE_NOT);
+		}
+
+		String fileRootPath = excelTemplateUtils.getFileRootPath();
+		String privatePath = fileRootPath + File.separator + EXCEL_TEMPLATE;
+		checkPath(privatePath);
+
+		privatePath += File.separator + PRIVATE_PATH;
+		checkPath(privatePath);
+
+		privatePath += File.separator + compId;
+		checkPath(privatePath);
+
+		String originalFileName = file.getOriginalFilename();
+		String suffixName = originalFileName.substring(originalFileName.lastIndexOf("."));
+
+		// 创建文件
+		privatePath += File.separator + serviceCode + suffixName;
+		Streams.copy(file.getInputStream(), new FileOutputStream(new File(privatePath)), true);
+
+		createAppendixData(compId, originalFileName, privatePath);
+	}
+
+	@PostMapping("/api/savePublicTemplate")
+	public void savePublicTemplate(HttpServletRequest request) throws IOException {
+		MultipartFile file = ((MultipartHttpServletRequest) request).getFile("template");
+		if (null == file) {
+			throw new EnterpriseException(EnterpriseErrorCodeEnums.EXCEL_TEMPLATE_FILE_NOT);
+		}
+		String serviceCode = request.getParameter("serviceCode");
+		if (StringUtils.isEmpty(serviceCode)) {
+			throw new EnterpriseException(EnterpriseErrorCodeEnums.EXCEL_TEMPLATE_NOT);
+		}
+
+		String fileRootPath = excelTemplateUtils.getFileRootPath();
+		String publicPath = fileRootPath + File.separator + EXCEL_TEMPLATE;
+		checkPath(publicPath);
+
+		publicPath += File.separator + PUBLIC_PATH;
+		checkPath(publicPath);
+
+		String originalFileName = file.getOriginalFilename();
+		String filePath = publicPath + File.separator + serviceCode
+				+ originalFileName.substring(originalFileName.lastIndexOf("."));
+		Streams.copy(file.getInputStream(), new FileOutputStream(new File(filePath)), true);
+
+		createAppendixData(null, originalFileName, filePath);
+	}
+
+	/**
+	 * 检测路径是否拥有(如果没有进行创建)
+	 *
+	 * @param path 路径
+	 */
+	private void checkPath(String path) {
+		if (!new File(path).exists()) {
+			new File(path).mkdir();
+		}
+	}
+
+	/**
+	 * 创建附件数据
+	 *
+	 * @param compId       公司id
+	 * @param appendixName 附件名称
+	 * @param appendixPath 附件路径
+	 */
+	private void createAppendixData(String compId, String appendixName, String appendixPath) {
+		// 如果是共通模板那就所有船都进行同步
+		if (StringUtils.isEmpty(compId)) {
+			CommonAppendix appendix = new CommonAppendix();
+			appendix.setAppendixId(IdGenerator.generateUUID());
+			appendix.setAppendixName(appendixName);
+			appendix.setAppendixPath(appendixPath);
+			appendix.setFromTableName(EXCEL_TEMPLATE);
+			appendixService.insert(appendix);
+			return;
+		}
+
+		// 如果是私有模板那就生成多条数据进行同步
+		List<CommonAppendix> appendices = new ArrayList<>();
+		CommonAppendix appendix = new CommonAppendix();
+		appendix.setVesselId(null);
+		appendix.setAppendixId(IdGenerator.generateUUID());
+		appendix.setCompId(compId);
+		appendix.setAppendixName(appendixName);
+		appendix.setAppendixPath(appendixPath);
+		appendix.setFromTableName(EXCEL_TEMPLATE);
+
+		appendices.add(appendix);
+
+		appendixService.insertBatch(appendices);
+	}
+}

+ 47 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/FlowTaskCandidateController.java

@@ -0,0 +1,47 @@
+package com.yh.saas.platform.controller;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.yh.saas.platform.entity.view.FlowTaskCandidateStaffView;
+import com.yh.saas.platform.service.IFlowTaskCandidateService;
+
+/**
+ * 工作流候选API
+ * 
+ * @author gdc
+ */
+@RequestMapping("/flowTaskCandidate")
+@RestController
+public class FlowTaskCandidateController {
+
+	@Autowired
+	private IFlowTaskCandidateService flowTaskCandidateService;
+
+	/**
+	 * 获取候选人信息
+	 * 
+	 * @param workflowId  工作流ID
+	 * @param businessKey 业务ID
+	 * @return 候选人信息
+	 */
+	@GetMapping("/query/candidateStaffInfo")
+	public FlowTaskCandidateStaffView getCandidateStaffInfo(@RequestParam String workflowId,
+			@RequestParam String businessKey) {
+		return flowTaskCandidateService.getCandidateStaffInfo(workflowId, businessKey);
+	}
+
+	/**
+	 *  获取预选人信息
+	 * @param businessCode 业务code
+	 * @return 返回候选人信息
+	 */
+	@GetMapping("/query/findPreReveiewerStaffInfo")
+	public FlowTaskCandidateStaffView findPreReveiewerStaffInfo(@RequestParam String businessCode) {
+		return flowTaskCandidateService.findPreReveiewerStaffInfo(businessCode);
+	}
+
+}

+ 52 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/FuncClickInfoController.java

@@ -0,0 +1,52 @@
+package com.yh.saas.platform.controller;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.yh.saas.platform.entity.FuncClickInfo;
+import com.yh.saas.platform.service.IFuncClickInfoService;
+
+/**
+ * <p>
+ * APP功能点击次数记录表 前端控制器
+ * </p>
+ *
+ * @author wxg
+ * @since 2019-11-12
+ */
+@RestController
+@RequestMapping("/funcClickInfo")
+public class FuncClickInfoController {
+	@Autowired
+	private IFuncClickInfoService funcClickInfoService;
+
+	/**
+	 * 查询功能点击次数记录信息
+	 * 
+	 * @param userId
+	 * @return List<FuncClickInfo>
+	 */
+	@GetMapping("/query/queryFuncClickInfoList")
+	public List<FuncClickInfo> queryFuncClickInfoList(@RequestParam String userId) {
+		return funcClickInfoService.queryFuncClickInfoList(userId);
+	}
+
+	/**
+	 * 保存功能点击次数记录信息
+	 * 
+	 * @param FuncClickInfo
+	 * @return Id
+	 */
+	@PostMapping("/api/saveFuncClickInfo")
+	public String saveFuncClickInfo(@RequestBody FuncClickInfo funcClickInfo) {
+		return funcClickInfoService.saveFuncClickInfo(funcClickInfo);
+	}
+
+}

+ 270 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/OfficeController.java

@@ -0,0 +1,270 @@
+package com.yh.saas.platform.controller;
+
+import ch.qos.logback.classic.Logger;
+import com.alipay.sofa.runtime.api.annotation.SofaReference;
+import com.winsea.svc.base.base.entity.CommonAppendix;
+import com.winsea.svc.base.base.exception.FileErrorCodeEnums;
+import com.winsea.svc.base.base.exception.FileException;
+import com.winsea.svc.base.base.exception.OfficeException;
+import com.winsea.svc.base.base.service.IAppendixService;
+import com.yh.saas.common.support.util.IdGenerator;
+import com.yh.saas.common.support.util.StringUtils;
+import com.yh.saas.common.support.util.po.POHelper;
+//import com.zhuozhengsoft.pageoffice.OpenModeType;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.servlet.ModelAndView;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.File;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+
+@RestController
+@RequestMapping("/office")
+public class OfficeController {
+
+    @Value("${file-root-path}")
+    private String fileRootPath;
+
+    private Logger log = (Logger) LoggerFactory.getLogger(this.getClass());
+
+    @Autowired
+    private POHelper pOHelper;
+
+    @SofaReference
+    private IAppendixService appendixService;
+
+    /**
+     * 测试用请求
+     *
+     * @return
+     */
+    @GetMapping("/file")
+    public ModelAndView showIndex(HttpServletRequest request) {
+        ModelAndView mv = new ModelAndView("office/office");
+        // 页面点击连接拼接的文件ID
+        String fileId = request.getParameter("fileId");
+        // 标识:是否另存  0 保存源文件   1 另存新文件     如果打开的是模板 保存的时候即为另存  1
+        // 保存关闭按按钮 showSave 1:显示 0 不显示
+        String sameFlag = StringUtils.isEmpty(request.getParameter("sameFlag")) ? "0" : request.getParameter("sameFlag");
+        String newFilePath = StringUtils.isEmpty(request.getParameter("newFilePath")) ? "" : request.getParameter("newFilePath");
+        String showSaveFlag = StringUtils.isEmpty(request.getParameter("showSaveFlag")) ? "0" : request.getParameter("showSaveFlag");
+
+        // 将打开的文件ID保存到session中  之后在打开该文件的方法中需要
+        request.getSession().setAttribute("fileId", fileId);
+        request.getSession().setAttribute("sameFlag", sameFlag);
+        request.getSession().setAttribute("newFilePath", newFilePath);
+        request.getSession().setAttribute("showSaveFlag", showSaveFlag);
+        return mv;
+    }
+
+    /**
+     * 获取打开文件的URL连接
+     *
+     * @param request
+     * @param response
+     * @param map
+     */
+    @GetMapping("/getUrl")
+    public String getUrl(HttpServletRequest request, HttpServletResponse response, Map<String, Object> map) {
+        String fileId = (String) request.getSession().getAttribute("fileId");
+        String sameFlag = (String) request.getSession().getAttribute("sameFlag");
+        String newFilePath = (String) request.getSession().getAttribute("newFilePath");
+        String showSaveFlag = (String) request.getSession().getAttribute("showSaveFlag");
+        String urlSTR = request.getParameter("urlSTR");
+        return "javascript:POBrowser.openWindowModeless('" + urlSTR + "/office/open?fileId=" + fileId + "&userName=abc&sameFlag=" + sameFlag + "&newFilePath=" + newFilePath + "&showSaveFlag=" + showSaveFlag + "&urlSTR=" + urlSTR + "','fullscreen=yes;');";
+    }
+
+    /**
+     * 删除无效文件
+     *
+     * @param fileId
+     */
+    @GetMapping("/delTemp")
+    public void delTempNewFile(HttpServletRequest request, @RequestParam String fileId) {
+        // 编辑文件后不进行保存操作 删除临时保存的附件信息
+        CommonAppendix file = appendixService.getAppendixById(fileId);
+        if (file != null) {
+            try {
+                File tempFile = new File(fileRootPath + File.separator
+                        + URLDecoder.decode(file.getAppendixPath(), String.valueOf(StandardCharsets.UTF_8)));
+                if (tempFile.exists() && tempFile.delete()) {
+                    log.info(tempFile.getAbsolutePath() + "刪除成功!");
+                }
+            } catch (UnsupportedEncodingException e) {
+                throw new FileException(FileErrorCodeEnums.READ_EXCEPTION);
+            }
+        }
+
+        appendixService.deleteById(fileId);
+        request.getSession().removeAttribute("TempFileId");
+    }
+
+    /**
+     * 根据文件id取的文件路径,初始化并显示Office浏览器
+     *
+     * @param request
+     * @param map
+     * @param fileId   文件id
+     * @param userName 文档编辑者名称
+     * @return 返回到Office页面
+     * @throws UnsupportedEncodingException
+     */
+    @GetMapping("/open")
+    public ModelAndView open(HttpServletRequest request, Map<String, Object> map, @RequestParam String fileId, @RequestParam String userName, String sameFlag) throws UnsupportedEncodingException {
+//        Map<String, Object> result = checkFileId(fileId);
+        return null;
+//        return show(request, map, (CommonAppendix) result.get("appendix"), userName, (OpenModeType) result.get("openModeType"));
+    }
+
+    /**
+     * 初始化并显示Office浏览器
+     *
+     * @param request
+     * @param map
+     * @param userName 文档编辑者名称
+     * @return 返回到Office页面
+     * @throws UnsupportedEncodingException
+     */
+//    private ModelAndView show(HttpServletRequest request, Map<String, Object> map, @RequestParam CommonAppendix appendix, @RequestParam String userName, OpenModeType openModeType) throws UnsupportedEncodingException {
+//        String htmlCode = "文件格式不支持";
+//
+//        if (userName == null || "".equals(userName.trim())) {
+//            userName = "administrator";
+//        }
+//
+//        if (openModeType != null) {
+//            if ("1".equals(request.getParameter("sameFlag"))) {
+//                // 以模板为准  另存新路径文件   需要插入条新common_appendix记录
+//                String oldFilePath = appendix.getAppendixPath();
+//                String newFilePath = request.getParameter("newFilePath");
+//                String newFileId = IdGenerator.generateLongIncrId();
+//                appendix.setAppendixId(newFileId);
+//                String temp = appendix.getAppendixName();
+//                String fileType = temp.substring(temp.lastIndexOf(".") + 1, temp.length());
+//                // 创建时间戳文件名
+//                temp = String.valueOf(new Date().getTime());
+//                newFilePath = newFilePath + temp + "." + fileType;
+//                appendix.setAppendixPath(newFilePath);
+//
+//                appendixService.insert(appendix);
+//                //
+//                if (oldFilePath.startsWith("/")) {
+//                    oldFilePath = oldFilePath.substring(1);
+//                }
+//
+//                //
+//                if (newFilePath.startsWith("/")) {
+//                    newFilePath = newFilePath.substring(1);
+//                }
+//
+//                htmlCode = pOHelper.openOffice(request, newFileId, oldFilePath, newFilePath, openModeType, userName, "PageOfficeCtrl1");
+//            } else {
+//                String strApixString = appendix.getAppendixPath();
+//                // 原路径保存文件
+//                htmlCode = pOHelper.openOffice(request, strApixString, null, userName, "PageOfficeCtrl1");
+//            }
+//
+//        }
+//        /*
+//         * else { // PDF格式 htmlCode =
+//         * pOHelper.openPdf(request,appendix.getAppendixPath(), "PageOfficeCtrl1"); }
+//         */
+//
+//        map.put("pageOffice", htmlCode);
+//
+//        ModelAndView mv = new ModelAndView("office/browser");
+//        return mv;
+//    }
+
+    /**
+     * 保存文档操作
+     *
+     * @param request
+     * @param response
+     * @param map
+     * @throws UnsupportedEncodingException
+     */
+    @PostMapping("/save")
+    public void save(HttpServletRequest request, HttpServletResponse response, Map<String, Object> map) throws IOException {
+        pOHelper.saveOffice(request, response);
+    }
+
+    /**
+     * 根据fileId 检查文件正确性
+     *
+     * @return
+     */
+//    private Map<String, Object> checkFileId(String fileId) {
+//
+//        Map<String, Object> result = new HashMap<>();
+//        String fileType = "";
+//        OpenModeType openModeType = null;
+//
+//        if (fileId == null || "".equals(fileId.trim())) {
+//            //文件路径不能为空
+//            throw new OfficeException(FileErrorCodeEnums.FILE_PATH_BLANK);
+//        }
+//
+//        CommonAppendix appendix = appendixService.getAppendixById(fileId);
+//        if (appendix == null || "".equals(appendix.getAppendixPath())) {
+//            //文件路径不能为空
+//            throw new OfficeException(FileErrorCodeEnums.FILE_PATH_BLANK);
+//        }
+//
+//        String filePath = appendix.getAppendixPath();
+//        if (filePath == null || "".equals(filePath.trim())) {
+//            //文件路径不能为空
+//            throw new OfficeException(FileErrorCodeEnums.FILE_PATH_BLANK);
+//        }
+//
+//        filePath = filePath.replaceAll("%2E", ".");
+//        if (filePath.contains(".")) {
+//            fileType = filePath.substring(filePath.lastIndexOf("."), filePath.length());
+//        } else {
+//            //文件类型异常
+//            throw new OfficeException(FileErrorCodeEnums.FILE_TYPE_EXCEPTION);
+//        }
+//
+//        if (".doc#.docx#.wps".contains(fileType)) {
+//            openModeType = OpenModeType.docNormalEdit;
+//        } else if (".xls#.xlsx".contains(fileType)) {
+//            openModeType = OpenModeType.xlsNormalEdit;
+//        } else if (".ppt#.pptx".contains(fileType)) {
+//            openModeType = OpenModeType.pptNormalEdit;
+//        } else {
+//            //Todo:pdf文件处理   现有pageoffice 标准版 不支持PDF功能
+//            //文件类型异常
+//            throw new OfficeException(FileErrorCodeEnums.FILE_TYPE_EXCEPTION);
+//        }
+//        result.put("openModeType", openModeType);
+//        result.put("appendix", appendix);
+//        return result;
+//
+//    }
+
+    @GetMapping("/setTempFileId")
+    public void setFileId(HttpServletRequest request) {
+        // request.getSession().setAttribute("TempFileId",request.getParameter("FileId"));
+    }
+
+    @GetMapping("/getTempFileId")
+    public List<String> getTempFileId(HttpServletRequest request) {
+        List<String> list = new ArrayList<String>();
+        String tempFileId = "";
+        tempFileId = request.getSession().getAttribute("TempFileId") == null ? ""
+                : (String) request.getSession().getAttribute("TempFileId");
+
+        list.add(tempFileId);
+        request.getSession().removeAttribute("TempFileId");
+        return list;
+    }
+
+}

+ 54 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/PluginServiceController.java

@@ -0,0 +1,54 @@
+package com.yh.saas.platform.controller;
+
+import com.alipay.sofa.runtime.api.annotation.SofaReference;
+import com.winsea.svc.base.plugin.service.ITenantPluginAttributeService;
+import com.winsea.svc.base.plugin.service.ITenantPluginService;
+import com.winsea.svc.base.security.util.AuthSecurityUtils;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 插件服务共通 - Controller
+ * </p>
+ *
+ * @author ZhangMingYu
+ * @since 2019年9月23日10:59:34
+ */
+
+@RestController
+@RequestMapping("/pluginService")
+public class PluginServiceController {
+
+	@SofaReference
+	private ITenantPluginAttributeService tenantPluginAttributeService;
+
+	@SofaReference
+	private ITenantPluginService tenantPluginService;
+
+	/**
+	 * 根据租户id 和 属性服务code 查询是否购买
+	 *
+	 * @param tenantId      租户id
+	 * @param attributeCode 属性服务code
+	 * @return 是否购买
+	 */
+	@GetMapping("/query/attributeService")
+	public Boolean attributeService(@RequestParam String tenantId, @RequestParam String attributeCode) {
+		return null != tenantPluginAttributeService.findTenantPlugin(tenantId, attributeCode);
+	}
+
+	/**
+	 * 查询当前租户是否购买当前服务(一级服务||二级服务||三级服务)
+	 *
+	 * @param serviceCode 服务code
+	 * @return 是否购买
+	 */
+	@GetMapping("/query/findTenantDredgeService")
+	public Boolean findTenantDredgeService(@RequestParam String serviceCode) {
+		return tenantPluginService.findTenantDredgeService(serviceCode,
+				AuthSecurityUtils.getCurrentUserInfo().getTenantId());
+	}
+}

+ 97 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/RoleController.java

@@ -0,0 +1,97 @@
+package com.yh.saas.platform.controller;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+import com.baomidou.mybatisplus.mapper.Wrapper;
+import com.yh.saas.common.support.entity.BaseModel;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.alipay.sofa.runtime.api.annotation.SofaReference;
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.baomidou.mybatisplus.plugins.Page;
+import com.winsea.svc.base.base.entity.CommonRole;
+import com.winsea.svc.base.base.service.ICommonRoleService;
+
+/**
+ * <p>
+ * 岸端职务 - Controller
+ * </p>
+ *
+ * @author ZhangMingYu
+ * @since 2019年9月19日13:53:32
+ */
+
+@RestController
+@RequestMapping("/role")
+public class RoleController {
+
+	@SofaReference
+	private ICommonRoleService roleService;
+
+	/**
+	 * 通过部门获取职务列表
+	 *
+	 * @param commonRole deptId 部门id
+	 * @return 分页职务
+	 */
+	@GetMapping("/query/role")
+	public Page<CommonRole> role(CommonRole commonRole) {
+		return roleService.selectPage(commonRole.getQueryPage(),
+				new EntityWrapper<CommonRole>().eq(CommonRole.QueryFields.DEPT_ID, commonRole.getDeptId()));
+	}
+
+	/**
+	 * 通过公司查询职务列表
+	 *
+	 * @param commonRole compId 公司id
+	 * @return 返回集合
+	 */
+	@GetMapping("/query/roleList")
+	public List<HashMap> roleList(CommonRole commonRole) {
+		return roleService.roleList(commonRole);
+	}
+
+	/**
+	 * 通过部门id 查询角色
+	 */
+	@GetMapping("/query/deptRoleList")
+	public List<CommonRole> findDeptRoleList(@RequestParam String deptIds) {
+		List<String> deptIdlist = new ArrayList<>();
+		if (deptIds.contains(",")) {
+			deptIdlist = Arrays.asList(deptIds.split(","));
+		} else {
+			deptIdlist.add(deptIds);
+		}
+		return roleService.findDeptRoleList(deptIdlist);
+	}
+
+	/**
+	 * 根据船舶id 获取所有职务
+	 * 
+	 * @param vesselId 船舶id
+	 * @return 返回所有职务
+	 */
+	@GetMapping("/query/findVesselRole")
+	public List<CommonRole> findVesselRole(@RequestParam String vesselId) {
+		return roleService.findVesselRole(vesselId);
+	}
+
+
+	@GetMapping("/query/getRoleByCompId")
+	public List<CommonRole> getRoleByCompId(String compId,String flag) {
+		Wrapper<CommonRole> wrapper = new EntityWrapper<>();
+		wrapper.eq(CommonRole.QueryFields.COMP_ID, compId);
+		wrapper.eq(CommonRole.QueryFields.VESSEL_BANK_FLAG, flag);
+		wrapper.orderBy("duty_id IS NULL", true);// 把没有船端职务id的放后面
+		wrapper.orderBy("duty_id = ''", true);
+		wrapper.orderBy("CONVERT ( duty_id, signed )", true);
+		wrapper.orderBy(BaseModel.CommonQueryFields.CREATE_DATE, false);
+		return roleService.selectList(wrapper);// 按船长,大副,二副,三副,轮机长,大管轮,二管轮,三管轮,电机员排序
+	}
+}

+ 249 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/StaffController.java

@@ -0,0 +1,249 @@
+package com.yh.saas.platform.controller;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import com.winsea.svc.base.security.service.IAccountService;
+import com.yh.saas.plugin.yiliangyiyun.entity.WarehouseBaseInfo;
+import com.yh.saas.plugin.yiliangyiyun.service.IWarehouseBaseInfoService;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.alipay.sofa.runtime.api.annotation.SofaReference;
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.baomidou.mybatisplus.mapper.Wrapper;
+import com.winsea.svc.base.base.entity.CommonDepartment;
+import com.winsea.svc.base.base.entity.CommonRole;
+import com.winsea.svc.base.base.entity.CommonStaff;
+import com.winsea.svc.base.base.entity.CommonStaffRole;
+import com.winsea.svc.base.base.entity.CommonVessel;
+import com.winsea.svc.base.base.service.ICommonDepartmentService;
+import com.winsea.svc.base.base.service.ICommonRoleService;
+import com.winsea.svc.base.base.service.ICommonStaffRoleService;
+import com.winsea.svc.base.base.service.ICommonStaffService;
+import com.winsea.svc.base.base.service.ICommonVesselService;
+import com.winsea.svc.base.security.util.AuthSecurityUtils;
+
+/**
+ * <p>
+ * 职员信息 前端控制器
+ * </p>
+ *
+ * @author zhaojiuzhou
+ * @since 2019-05-28
+ */
+@RestController
+@RequestMapping("/staff")
+public class StaffController {
+
+	@SofaReference
+	private ICommonStaffService staffService;
+
+	@SofaReference
+	private ICommonDepartmentService deptService;
+
+	@SofaReference
+	private ICommonVesselService vesselInfoService;
+
+	@SofaReference
+	private ICommonDepartmentService deptInfoService;
+
+	@SofaReference
+	private ICommonStaffRoleService staffRoleService;
+
+	@SofaReference
+	private ICommonRoleService roleService;
+
+	@Autowired
+	private IWarehouseBaseInfoService warehouseBaseInfoService;
+	/**
+	 * 获取当前登录用户信息
+	 *
+	 * @return
+	 */
+	@GetMapping("/query/getCurrentUserInfo")
+	public CommonStaff getCurrentUserInfo() {
+		String staffId = AuthSecurityUtils.getCurrentUserInfo().getUserId();
+		CommonStaff staff = staffService.selectById(staffId);
+		CommonDepartment dept = deptService.selectById(staff.getDeptId());
+		if (dept != null) {
+			staff.setDeptName(dept.getDeptName());
+		}
+		staff.setRoles(staffService.getStaffRoles(staffId));
+		staff.setVessels(vesselInfoService.getStaffVessels(staffId, CommonVessel.VesselStatus.UNDER_CONTROL));
+		CommonStaffRole staffRole = staffRoleService.getMajorRole(staffId);
+		if (staffRole != null) {
+			staff.setMajorRole(roleService.selectById(staffRole.getRoleId()));
+		}
+		return staff;
+	}
+
+	/**
+	 * 根据ID获得staff信息
+	 *
+	 * @return
+	 */
+	@GetMapping("/query/getUserInfoByIds")
+	public List<CommonStaff> getUserInfoByIds(@RequestParam String staffIds) {
+		List<CommonStaff> staffList = staffService.selectBatchIds(Arrays.asList(staffIds.split(",")));
+		Map<String, CommonRole> roleMap = new HashMap<>();
+		staffList.forEach(staff -> {
+			if (roleMap.get(staff.getMajorRoleId()) == null) {
+				roleMap.put(staff.getMajorRoleId(), roleService.selectById(staff.getMajorRoleId()));
+			}
+			staff.setMajorRole(roleMap.get(staff.getMajorRoleId()));
+		});
+		return staffList;
+	}
+
+	/**
+	 * 根据公司ID获得职员信息集合
+	 *
+	 * @param deptId
+	 * @return
+	 */
+	@GetMapping("/query/getStaffListByDeptId")
+	public List<CommonStaff> getStaffListByDeptId(String deptId) {
+		return staffService.selectList(new EntityWrapper<CommonStaff>().eq("dept_id", deptId));
+	}
+
+	/**
+	 * 根据公司ID获得职员信息集合
+	 *
+	 * @param compId
+	 * @return
+	 */
+	@GetMapping("/query/getStaffListByCompId")
+	public List<CommonStaff> getStaffListByCompId(String compId) {
+		return staffService.selectList(new EntityWrapper<CommonStaff>().eq("comp_id", compId));
+	}
+
+	/**
+	 * 根据公司ID和库点id获得有权限的人员集合
+	 *
+	 * @param compId
+	 * @return
+	 */
+//	@GetMapping("/query/getStaffListByCompIdAndWarehouseId")
+//	public List<CommonStaff> getStaffListByCompId(String compId,String warehouseId) {
+//		if(compId == null || compId.isEmpty()){
+//			compId=AuthSecurityUtils.getStaffById(AuthSecurityUtils.getCurrentUserId()).getCompId();
+//		}
+//		if(warehouseId != null && !warehouseId.isEmpty()){
+//			WarehouseBaseInfo warehouseBaseInfo = warehouseBaseInfoService.selectById(warehouseId);
+//			String phones = warehouseBaseInfo.getOtherPersonPhone()!=null?warehouseBaseInfo.getPersonPhone()+","+warehouseBaseInfo.getOtherPersonPhone():warehouseBaseInfo.getPersonPhone();
+//
+//			return staffService.selectList(new EntityWrapper<CommonStaff>().eq("comp_id", compId).in("staff_mobile_phone",phones));
+//		}
+//		else{
+//			return staffService.selectList(new EntityWrapper<CommonStaff>().eq("comp_id", compId));
+//		}
+//	}
+
+
+	/**
+	 * 通过公司ID获取部门列表
+	 *
+	 * @return 部门列表
+	 */
+	@GetMapping("/query/deptListByCompId")
+	public List<CommonDepartment> getDeptListByCompId(@RequestParam(name = "compId", required = false) String compId,
+			@RequestParam(required = false) String vesselBankFlag) {
+		Wrapper<CommonDepartment> wrapper = new EntityWrapper<CommonDepartment>().eq("comp_id", getCompId(compId))
+				.orderBy("parent_dept_id", true);
+		if (!StringUtils.isEmpty(vesselBankFlag)) {
+			wrapper.eq(CommonDepartment.QueryFields.VESSEL_BANK_FLAG, vesselBankFlag);
+		}
+		return deptInfoService.selectList(wrapper);
+	}
+
+	/**
+	 * 通过公司ID获取船舶列表
+	 *
+	 * @return 船舶列表
+	 */
+	@GetMapping("/query/vesselListByCompId")
+	public List<CommonVessel> getVesselListByCompId(@RequestParam(name = "compId", required = false) String compId) {
+		return vesselInfoService.selectList(new EntityWrapper<CommonVessel>().eq("comp_id", getCompId(compId))
+				.orderBy(CommonVessel.QueryFields.VESSEL_NAME));
+	}
+
+	/**
+	 * 职员手机号重复性检查接口
+	 *
+	 * @return
+	 * @Param 手机号
+	 * @Auther ZhangMingYu
+	 */
+	@GetMapping("/api/checkPhone")
+	public Integer checkPhone(@RequestParam String staffId, @RequestParam String phone) {
+		return staffService.checkPhone(staffId, phone);
+	}
+
+	/**
+	 * 职员账号重复性检查接口
+	 *
+	 * @Param 账号
+	 * @Auther ZhangMingYu
+	 */
+	@GetMapping("/api/checkAccount")
+	public Integer checkAccount(@RequestParam String staffId, @RequestParam String account) {
+		return staffService.checkAccount(staffId, account);
+	}
+
+	/**
+	 * 通过公司ID获取部门下职员
+	 *
+	 * @return 部门列表
+	 */
+	@GetMapping("/query/getDeptStaffListByCompId")
+	public List<CommonStaff> deptStaffListByCompId(@RequestParam String type) {
+		return staffService.deptStaffListByCompId(type, AuthSecurityUtils.getCurrentUserInfo().getCompId());
+	}
+
+	/**
+	 * 根据职务查询人员
+	 *
+	 * @param roles 职务结合
+	 * @return 返回人员关联
+	 */
+	@GetMapping("/query/findRole")
+	public List<CommonStaff> findRoleStaff(@RequestParam String roles) {
+		List<String> roleIds = new ArrayList<>();
+		if (roles.contains(",")) {
+			roleIds = Arrays.asList(roles.split(","));
+		} else {
+			roleIds.add(roles);
+		}
+		List<CommonStaffRole> staffRoles = staffRoleService.findStaff(roleIds);
+		if (CollectionUtils.isNotEmpty(staffRoles)) {
+			List<String> staffIds = staffRoles.stream().map(CommonStaffRole::getStaffId).collect(Collectors.toList());
+			return staffService.findStaffs(staffIds);
+		}
+		return null;
+	}
+
+	/**
+	 * 查询船舶的船长、大副、轮机长、大管轮
+	 * 
+	 * @param vesselId
+	 * @return
+	 */
+	@GetMapping("/query/getVesselLeaders")
+	public Object getVesselLeaders(@RequestParam String vesselId) {
+		return staffService.getVesselLeaders(vesselId);
+	}
+
+	private String getCompId(String compId) {
+		return StringUtils.isNotBlank(compId) ? compId : AuthSecurityUtils.getCurrentUserInfo().getCompId();
+	}
+}

+ 115 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/SystemController.java

@@ -0,0 +1,115 @@
+package com.yh.saas.platform.controller;
+
+import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.codec.binary.StringUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.winsea.svc.base.base.util.ClientTypeChecker;
+
+/**
+ * <p>
+ * 服务器 前端控制器
+ * </p>
+ *
+ * @author zhaojz
+ * @since 2019-04-03
+ */
+@RestController
+@RequestMapping("/system")
+public class SystemController {
+
+	@Value("${comany-mgr-url}")
+	private String comanyMgrUrl;
+
+	@Value("${file-show-path}")
+	private String fileShowPath;
+
+	@Value("${pc-url}")
+	private String pcUrl;
+
+	/**
+	 * 获得服务器地址
+	 * 
+	 * @param request
+	 * @return
+	 * @throws UnknownHostException
+	 * @throws Exception
+	 */
+	@GetMapping("/query/getRootUrl")
+	public Object getRootUrl(HttpServletRequest request) {
+		String ip = getIpAddr(request);
+		int port = request.getLocalPort();
+		return "http://" + ip + ":" + port + "/";
+	}
+
+	/**
+	 * 获得服务器地址
+	 *
+	 * @param request
+	 * @return
+	 * @throws UnknownHostException
+	 * @throws Exception
+	 */
+	@GetMapping("/query/getComanyMgrUrl")
+	public Object getFileUploadUrl() {
+		Map<String, String> map = new HashMap<String, String>();
+		map.put("fileUrl", fileShowPath);
+		map.put("comanyMgrUrl", comanyMgrUrl);
+		map.put("pcUrl", pcUrl);
+		return map;
+	}
+
+	/**
+	 * 判断当前客户端是否是船端
+	 */
+	@GetMapping("/query/isVesselTerminal")
+	public boolean isVesselTerminal() {
+		return ClientTypeChecker.isVesselTerminal();
+	}
+
+	/**
+	 * 判断当前客户端是否是岸基
+	 */
+	@GetMapping("/query/isLandBased")
+	public boolean isLandBased() {
+		return ClientTypeChecker.isLandBased();
+	}
+
+	private String getIpAddr(HttpServletRequest request) {
+		String ip = request.getHeader("x-forwarded-for");
+		if (!isNullIp(ip) && ip.indexOf(',') != -1) {
+			ip = ip.split(",")[0];
+		}
+		if (isNullIp(ip)) {
+			ip = request.getHeader("Proxy-Client-IP");
+		}
+		if (isNullIp(ip)) {
+			ip = request.getHeader("WL-Proxy-Client-IP");
+		}
+		if (isNullIp(ip)) {
+			ip = request.getHeader("HTTP_CLIENT_IP");
+		}
+		if (isNullIp(ip)) {
+			ip = request.getHeader("HTTP_X_FORWARDED_FOR");
+		}
+		if (isNullIp(ip)) {
+			ip = request.getHeader("X-Real-IP");
+		}
+		if (isNullIp(ip)) {
+			ip = request.getLocalAddr();
+		}
+		return ip;
+	}
+
+	private boolean isNullIp(String ip) {
+		return ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip) || StringUtils.equals("127.0.0.1", ip);
+	}
+}

+ 44 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/ThermalRoutingController.java

@@ -0,0 +1,44 @@
+package com.yh.saas.platform.controller;
+
+
+import com.yh.saas.platform.entity.ThermalRouting;
+import com.yh.saas.platform.service.IThermalRoutingService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.List;
+
+/**
+ * <p>
+ * 热度路由
+ * 解释:
+ * 用来存储哪个路由对用户使用率最高
+ * </p>
+ *
+ * @author ZhangMingYu
+ * @since 2020年2月21日15:19:04
+ */
+@RestController
+@RequestMapping("/thermalRouting")
+public class ThermalRoutingController {
+
+    @Autowired
+    private IThermalRoutingService thermalRoutingService;
+
+    /**
+     * 更新热度
+     */
+    @PostMapping("/api/renewalHead")
+    public void renewalHead(@Valid @RequestBody ThermalRouting thermalRouting) {
+        thermalRoutingService.renewalHead(thermalRouting);
+    }
+
+    /**
+     * 查询 - 最热路由
+     */
+    @GetMapping("/query/findHottestRouting")
+    public List<ThermalRouting> findHottestRouting(ThermalRouting thermalRouting){
+       return thermalRoutingService.findHottestRouting(thermalRouting);
+    }
+}

+ 86 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/controller/VesselController.java

@@ -0,0 +1,86 @@
+package com.yh.saas.platform.controller;
+
+import java.util.List;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.alipay.sofa.runtime.api.annotation.SofaReference;
+import com.winsea.svc.base.base.entity.CommonVessel;
+import com.winsea.svc.base.base.service.ICommonVesselService;
+import com.winsea.svc.base.security.util.AuthSecurityUtils;
+
+/**
+ * <p>
+ * 记录船舶信息 前端控制器
+ * </p>
+ *
+ * @author gdc
+ * @since 2019-04-18
+ */
+@RestController
+@RequestMapping("/vessel")
+public class VesselController {
+
+	@SofaReference
+	private ICommonVesselService vesselInfoService;
+
+	/**
+	 * 获取用户拥有的船舶列表
+	 * 
+	 * @param vesselStatus 船舶状态
+	 * @return 船舶列表
+	 */
+	@GetMapping("/query/getUserVesselListByStatus")
+	public List<CommonVessel> getUserVesselListByStatus(
+			@RequestParam(name = "vesselStatus", required = false) CommonVessel.VesselStatus vesselStatus) {
+		return vesselInfoService.getStaffVessels(AuthSecurityUtils.getCurrentUserInfo().getUserId(), vesselStatus);
+	}
+
+	/**
+	 * 查询船舶是否购买客户端
+	 * 
+	 * @param vesselId 船舶id
+	 * @return 是否购买
+	 * @author ZhangMingYu
+	 */
+	@GetMapping("/query/findVesselClientFlag")
+	public Boolean findVesselClientFlag(String vesselId) {
+		return vesselInfoService.findVesselClientFlag(vesselId);
+	}
+
+	/**
+	 * 查询船舶信息
+	 * 
+	 * @param vesselId 船舶id
+	 * @return 船舶信息
+	 * @author Dongah
+	 */
+	@GetMapping("/query/getVesselInfo")
+	public CommonVessel getVesselInfo(String vesselId) {
+		return vesselInfoService.getVesselInfo(vesselId);
+	}
+
+	/**
+	 * 获取租户下所有的船舶
+	 * 
+	 * @param tenantId
+	 * @return
+	 */
+	@GetMapping("/query/getVesselListByTenantId")
+	public List<CommonVessel> getVesselListByTenantId(CommonVessel vessel) {
+		return this.vesselInfoService.getVesselListByTenantId(vessel);
+	}
+
+//	/**
+//	 * 根据所属公司获取船舶信息
+//	 * @param underCompId
+//	 * @return
+//	 */
+//	@GetMapping("/query/getVesselListByUnderCompId")
+//	public List<CommonVessel> getVesselListByUnderCompId(CommonVessel vessel){
+//		return this.vesselInfoService.getVesselListByUnderCompId(vessel);
+//	}
+}

+ 85 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/entity/FuncClickInfo.java

@@ -0,0 +1,85 @@
+package com.yh.saas.platform.entity;
+
+import java.io.Serializable;
+
+import com.baomidou.mybatisplus.annotations.TableId;
+import com.baomidou.mybatisplus.annotations.TableName;
+import com.baomidou.mybatisplus.enums.IdType;
+import com.yh.saas.common.support.entity.BaseModel;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * APP功能点击次数记录表
+ * </p>
+ *
+ * @author wxg
+ * @since 2019-11-12
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Accessors(chain = true)
+@TableName("common_func_click_info")
+public class FuncClickInfo extends BaseModel<FuncClickInfo> {
+
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * ID
+	 */
+	@TableId(type = IdType.INPUT)
+	private String id;
+	/**
+	 * 公司ID
+	 */
+	private String compId;
+	/**
+	 * 用户ID
+	 */
+	private String userId;
+	/**
+	 * 用户名称
+	 */
+	private String userName;
+	/**
+	 * 功能类型:1 新增证书 2 证书换证 3 证书检验
+	 */
+	private Integer funcType;
+	/**
+	 * 功能名称
+	 */
+	private String funcName;
+	/**
+	 * 点击次数
+	 */
+	private Long clickCount;
+	
+
+	@Override
+	protected Serializable pkVal() {
+		return this.id;
+	}
+
+	/**
+	 * 查询字段
+	 */
+	public static class QueryFields {
+		public static final String ID = "id";
+
+		public static final String COMP_ID = "comp_id";
+
+		public static final String USER_ID = "user_id";
+
+		public static final String CLICK_COUNT = "click_count";
+
+		public static final String FUNC_TYPE = "func_type";
+
+		private QueryFields() {
+
+		}
+	}
+
+}

+ 43 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/entity/NotificationBusinessCode.java

@@ -0,0 +1,43 @@
+package com.yh.saas.platform.entity;
+
+import com.baomidou.mybatisplus.annotations.TableName;
+import com.yh.saas.common.support.entity.BaseModel;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+
+@Data
+@TableName("notification_business_code_info")
+@EqualsAndHashCode(callSuper = true)
+public class NotificationBusinessCode extends BaseModel<NotificationBusinessCode> {
+
+    /**
+     * 主键id
+     */
+    private String id;
+
+    /**
+     * 业务编码
+     */
+    private String businessCode;
+
+    /**
+     * 单据名称
+     */
+    private String nameBill;
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+    /**
+     * 查询字段
+     */
+    public static class QueryFiled {
+
+        public static final String BUSINESS_CODE = "business_code";
+
+    }
+}

+ 64 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/entity/ThermalRouting.java

@@ -0,0 +1,64 @@
+package com.yh.saas.platform.entity;
+
+import com.baomidou.mybatisplus.annotations.TableId;
+import com.baomidou.mybatisplus.annotations.TableName;
+import com.baomidou.mybatisplus.enums.IdType;
+import com.yh.saas.common.support.entity.BaseModel;
+import com.yh.saas.common.support.util.query.SearchField;
+import com.yh.saas.common.support.util.query.SearchMode;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import javax.validation.constraints.NotBlank;
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 热度路由 (仅存在用户前台)
+ * </p>
+ *
+ * @author ZhangMingYu
+ * @since 2020年2月21日15:04:17
+ */
+
+@Data
+@TableName(value = "thermal_routing_info")
+@EqualsAndHashCode(callSuper = true)
+public class ThermalRouting extends BaseModel<ThermalRouting> {
+
+    /**
+     * 主键id
+     */
+    @TableId(type = IdType.INPUT)
+    private String id;
+
+    /**
+     * 使用人Id(账户表中的accountId)
+     */
+    @SearchField(mode = SearchMode.EQ)
+    private String accountId;
+
+    /**
+     * 路由中文名称
+     */
+    @NotBlank(message = "路由中文名不能为空")
+    @SearchField(mode = SearchMode.EQ)
+    private String title;
+
+    /**
+     * 路由URI
+     */
+    @NotBlank(message = "路由URI不能为空")
+    private String routingUri;
+
+    /**
+     * 当前热度
+     */
+    private int currentHead;
+
+    @Override
+    protected Serializable pkVal() {
+        return null;
+    }
+
+}

+ 63 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/entity/view/CommonRoleMenuView.java

@@ -0,0 +1,63 @@
+package com.yh.saas.platform.entity.view;
+
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.winsea.svc.base.base.util.tree.ITreeItem;
+
+import lombok.Data;
+
+@Data
+public class CommonRoleMenuView implements ITreeItem<CommonRoleMenuView> {
+
+	private String name;
+
+	@JsonIgnore
+	private String parentName;
+
+	private List<CommonRoleMenuView> children;
+
+	@JsonIgnore
+	@Override
+	public Object getId() {
+		return name;
+	}
+
+	@Override
+	public void setId(Object id) {
+		this.name = (String) id;
+	}
+
+	@JsonIgnore
+	@Override
+	public String getLabel() {
+		return null;
+	}
+
+	@Override
+	public void setLabel(String label) {
+		// do nothing
+	}
+
+	@JsonIgnore
+	@Override
+	public Object getParentId() {
+		return parentName;
+	}
+
+	@Override
+	public void setParentId(Object parentId) {
+		this.parentName = (String) parentId;
+	}
+
+	@JsonIgnore
+	@Override
+	public Integer getIndex() {
+		return 1;
+	}
+
+	@Override
+	public void setIndex(Integer index) {
+		// do nothing
+	}
+}

+ 69 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/entity/view/FlowTaskCandidateStaffView.java

@@ -0,0 +1,69 @@
+package com.yh.saas.platform.entity.view;
+
+import java.util.List;
+
+import com.winsea.svc.base.base.entity.CommonRole;
+import com.winsea.svc.base.base.entity.CommonStaff;
+
+import lombok.Data;
+
+/**
+ * 流程任务候选人
+ * 
+ * @author gdc
+ */
+@Data
+public class FlowTaskCandidateStaffView {
+
+	/**
+	 * 当前活动任务ID
+	 */
+	private String currentActiveTaskId;
+
+	/**
+	 * 职员列表
+	 */
+	private List<CommonStaff> staffs;
+
+	/**
+	 * 角色职员
+	 */
+	private List<RoleStaffView> roleStaffs;
+
+	/**
+	 * 候选类型
+	 */
+	private CandidateType candidateType;
+
+	/**
+	 * 角色职员
+	 */
+	@Data
+	public static class RoleStaffView {
+
+		private CommonRole role;
+
+		private List<CommonStaff> staffs;
+	}
+
+	/**
+	 * 候选类型
+	 */
+	public enum CandidateType {
+
+		/**
+		 * 没有候选人
+		 */
+		NONE,
+
+		/**
+		 * 职员
+		 */
+		STAFF,
+
+		/**
+		 * 角色下职员
+		 */
+		ROLE_STAFF
+	}
+}

+ 42 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/exception/EnterpriseErrorCodeEnums.java

@@ -0,0 +1,42 @@
+package com.yh.saas.platform.exception;
+
+import lombok.Getter;
+
+/**
+ * 管理后台错误码
+ *
+ * @author SunTianjun
+ */
+public enum EnterpriseErrorCodeEnums {
+
+    //公告模块-不是创建人不允许删除
+    ANNOUNCEMENT_NOT_ISSUE_USER_ID("NOT_ANNOUNCEMENT_MAN", "你不是这条公告的创建人!"),
+
+
+    //Excel模板
+    EXCEL_TEMPLATE_NOT("EXCEL_TEMPLATE_NOT", "缺少公司主键或服务名称!"),
+
+    //Excel 模板文件为空
+    EXCEL_TEMPLATE_FILE_NOT("EXCEL_TEMPLATE_FILE_NOT", "缺少模板文件!"),
+
+    //当前节点没有过滤部门的人儿
+    WORKFLOW_DEPT_CANDIDATE_NULL("WORKFLOW_DEPT_CANDIDATE_NULL", "当前无部门内部人员审核可选!")
+
+    ;
+
+    @Getter
+    private String value;
+
+    @Getter
+    private String desc;
+
+    private EnterpriseErrorCodeEnums(String value, String desc) {
+        this.value = value;
+        this.desc = desc;
+    }
+
+    @Override
+    public String toString() {
+        return "[" + this.value + "]" + this.desc;
+    }
+}

+ 32 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/exception/EnterpriseException.java

@@ -0,0 +1,32 @@
+package com.yh.saas.platform.exception;
+
+import lombok.Getter;
+
+/**
+ * 管理后台自定义错误
+ * 
+ * @author SunTianjun
+ */
+@Getter
+public class EnterpriseException extends RuntimeException {
+
+	private static final long serialVersionUID = 1L;
+
+	private final String code;
+
+	private final String message;
+
+	public EnterpriseException(EnterpriseErrorCodeEnums errorDefined) {
+		super(errorDefined.getDesc());
+
+		this.code = errorDefined.getValue();
+		this.message = errorDefined.getDesc();
+	}
+
+	public EnterpriseException(String code, String message) {
+		super(message);
+
+		this.code = code;
+		this.message = message;
+	}
+}

+ 16 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/mapper/FuncClickInfoMapper.java

@@ -0,0 +1,16 @@
+package com.yh.saas.platform.mapper;
+
+import com.baomidou.mybatisplus.mapper.BaseMapper;
+import com.yh.saas.platform.entity.FuncClickInfo;
+
+/**
+ * <p>
+ * APP功能点击次数记录表 Mapper 接口
+ * </p>
+ *
+ * @author wxg
+ * @since 2019-11-12
+ */
+public interface FuncClickInfoMapper extends BaseMapper<FuncClickInfo> {
+
+}

+ 8 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/mapper/NotificationBusinessCodeMapper.java

@@ -0,0 +1,8 @@
+package com.yh.saas.platform.mapper;
+
+import com.baomidou.mybatisplus.mapper.BaseMapper;
+import com.yh.saas.platform.entity.NotificationBusinessCode;
+
+public interface NotificationBusinessCodeMapper extends BaseMapper<NotificationBusinessCode> {
+
+}

+ 7 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/mapper/ThermalRoutingMapper.java

@@ -0,0 +1,7 @@
+package com.yh.saas.platform.mapper;
+
+import com.baomidou.mybatisplus.mapper.BaseMapper;
+import com.yh.saas.platform.entity.ThermalRouting;
+
+public interface ThermalRoutingMapper extends BaseMapper<ThermalRouting> {
+}

+ 54 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/properties/BIProperties.java

@@ -0,0 +1,54 @@
+package com.yh.saas.platform.properties;
+
+import java.util.Map;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * BI配置信息
+ * 
+ * @author SunTianjun
+ */
+public class BIProperties {
+
+	private BIProperties() {
+	}
+
+	/**
+	 * BI服务器配置
+	 */
+	@Getter
+	@Setter
+	@Configuration
+	@ConfigurationProperties(prefix = "bi.server")
+	public static class BIServerProperties {
+
+		private String protocol;
+
+		private String ip;
+
+		private String port;
+
+		private String contextPath;
+
+		private String reportBasePath;
+	}
+
+	/**
+	 * BI报表配置
+	 */
+	@Getter
+	@Setter
+	@Configuration
+	@ConfigurationProperties(prefix = "bi.report")
+	public static class BIReportProperties {
+
+		private Map<String, String> view;
+
+		private Map<String, String> export;
+	}
+}

+ 25 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/properties/CompanyProperties.java

@@ -0,0 +1,25 @@
+package com.yh.saas.platform.properties;
+
+import java.util.Map;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 公司配置信息
+ * 
+ * @author SunTianjun
+ */
+@Getter
+@Setter
+@Configuration
+@ConfigurationProperties(prefix = "company")
+public class CompanyProperties {
+
+	private Map<String, String> domain;
+
+	private String simplePhonetic;
+}

+ 20 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/CommonParameterCompanyService.java

@@ -0,0 +1,20 @@
+package com.yh.saas.platform.service;
+
+import com.winsea.svc.base.base.entity.CommonParameterCompany;
+
+import java.util.List;
+
+/**
+ * 公司常量服务
+ *
+ * @author Wangxiangshun
+ */
+public interface CommonParameterCompanyService {
+
+    /**
+     *
+     * @return
+     */
+    List<CommonParameterCompany> selectListParam(String constCode,String businessCode);
+
+}

+ 22 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/IBIService.java

@@ -0,0 +1,22 @@
+package com.yh.saas.platform.service;
+
+import java.util.Map;
+
+/**
+ * BI服务
+ * 
+ * @author SunTianjun
+ */
+public interface IBIService {
+
+	/**
+	 * 获取BI报表路径
+	 * 
+	 * @param operation    操作
+	 * @param reportName   报表名称
+	 * @param exportFormat 导出格式
+	 * @param params       参数
+	 * @return BI报表路径
+	 */
+	String getReportUrl(String operation, String reportName, String exportFormat, Map<String, String> params);
+}

+ 16 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/IBillOperateHisService.java

@@ -0,0 +1,16 @@
+package com.yh.saas.platform.service;
+
+import com.yh.saas.plugin.base.entity.CommonBillOperateHis;
+
+import java.util.List;
+
+public interface IBillOperateHisService {
+
+    /**
+     * 操作历史查询
+     *
+     * @param
+     * @return
+     */
+    List<CommonBillOperateHis> getBillOperateHis(String id,String billType);
+}

+ 28 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/IFlowTaskCandidateService.java

@@ -0,0 +1,28 @@
+package com.yh.saas.platform.service;
+
+import com.yh.saas.platform.entity.view.FlowTaskCandidateStaffView;
+
+/**
+ * 流程候选人服务
+ * 
+ * @author SunTianjun
+ */
+public interface IFlowTaskCandidateService {
+
+	/**
+	 * 获取候选人信息
+	 * 
+	 * @param flowId      流程ID
+	 * @param businessKey 业务ID
+	 * @return 候选人信息
+	 */
+	FlowTaskCandidateStaffView getCandidateStaffInfo(String flowId, String businessKey);
+
+	/**
+	 *  获取预选人信息
+	 * @param businessCode 业务code
+	 * @return 返回候选人信息
+	 */
+	FlowTaskCandidateStaffView findPreReveiewerStaffInfo(String businessCode);
+
+}

+ 34 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/IFuncClickInfoService.java

@@ -0,0 +1,34 @@
+package com.yh.saas.platform.service;
+
+import java.util.List;
+
+import com.baomidou.mybatisplus.service.IService;
+import com.yh.saas.platform.entity.FuncClickInfo;
+
+/**
+ * <p>
+ * APP功能点击次数记录表 服务类
+ * </p>
+ *
+ * @author wxg
+ * @since 2019-11-12
+ */
+public interface IFuncClickInfoService extends IService<FuncClickInfo> {
+
+	/**
+	 * 查询功能点击次数记录信息
+	 * 
+	 * @param userId
+	 * @return List<FuncClickInfo>
+	 */
+	List<FuncClickInfo> queryFuncClickInfoList(String userId);
+
+	/**
+	 * 保存功能点击次数记录信息
+	 * 
+	 * @param FuncClickInfo
+	 * @return Id
+	 */
+	String saveFuncClickInfo(FuncClickInfo funcClickInfo);
+
+}

+ 30 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/INotificationBusinessCodeService.java

@@ -0,0 +1,30 @@
+package com.yh.saas.platform.service;
+
+import com.yh.saas.platform.entity.NotificationBusinessCode;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 工作通知业务编码详情 - Service
+ * </p>
+ *
+ * @author ZhangMingYu
+ * @since 2020年2月21日09:05:44
+ */
+
+public interface INotificationBusinessCodeService {
+
+    /**
+     * 查询 - 根据业务编码查询工作通知业务编码详情
+     * @param businessCode 业务编码
+     * @return 单个详情
+     */
+    NotificationBusinessCode findBusinessCodeInfo(String businessCode);
+
+    /**
+     * 查询 - 所有工作流中的code
+     * @return 返回所有集合Code
+     */
+    List<String> findBusinessCodes();
+}

+ 13 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/IThermalRoutingService.java

@@ -0,0 +1,13 @@
+package com.yh.saas.platform.service;
+
+import com.baomidou.mybatisplus.service.IService;
+import com.yh.saas.platform.entity.ThermalRouting;
+
+import java.util.List;
+
+public interface IThermalRoutingService extends IService<ThermalRouting> {
+
+    void renewalHead(ThermalRouting thermalRouting);
+
+    List<ThermalRouting> findHottestRouting(ThermalRouting thermalRouting);
+}

+ 68 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/impl/BIServiceImpl.java

@@ -0,0 +1,68 @@
+package com.yh.saas.platform.service.impl;
+
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.web.util.UriUtils;
+
+import com.winsea.svc.base.security.util.AuthSecurityUtils;
+import com.yh.saas.common.support.util.StringUtils;
+import com.yh.saas.platform.properties.BIProperties;
+import com.yh.saas.platform.service.IBIService;
+
+/**
+ * BI服务实现
+ * 
+ * @author SunTianjun
+ */
+@Service
+public class BIServiceImpl implements IBIService {
+
+	@Autowired
+	private BIProperties.BIServerProperties serverProperties;
+
+	@Autowired
+	private BIProperties.BIReportProperties reportProperties;
+
+	@Override
+	public String getReportUrl(String operation, String reportName, String exportFormat, Map<String, String> params) {
+		if (null == params) {
+			params = new HashMap<>();
+		}
+
+		String reportSubPath = null;
+		switch (operation) {
+		case "view":
+			reportSubPath = reportProperties.getView().get(reportName);
+			params.put("op", "view");
+			break;
+		case "export":
+			reportSubPath = reportProperties.getExport().get(reportName);
+			params.put("format", !StringUtils.isEmpty(exportFormat) ? exportFormat : "excel");
+			break;
+		default:
+			// do nothing
+		}
+
+		if (null == reportSubPath) {
+			return null;
+		}
+
+		String compId = AuthSecurityUtils.getCurrentUserInfo().getCompId();
+		String protocol = serverProperties.getProtocol();
+		String ip = serverProperties.getIp();
+		String port = serverProperties.getPort();
+		String contextPath = serverProperties.getContextPath();
+		String reportBasePath = serverProperties.getReportBasePath().replace("{compId}", compId);
+		String reportPath = UriUtils.encode(reportBasePath + reportSubPath, "UTF-8");
+		String paramsStr = params.entrySet().stream().map(entrySet -> entrySet.getKey() + "=" + entrySet.getValue())
+				.collect(Collectors.joining("&"));
+
+		return MessageFormat.format("{0}://{1}:{2}{3}?reportlet={4}&{5}", protocol, ip, port, contextPath, reportPath,
+				paramsStr);
+	}
+}

+ 57 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/impl/BillOprateHisImpl.java

@@ -0,0 +1,57 @@
+package com.yh.saas.platform.service.impl;
+
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.baomidou.mybatisplus.mapper.Wrapper;
+import com.winsea.svc.base.workflow.entity.WorkflowHistoricTask;
+import com.yh.saas.platform.service.IBillOperateHisService;
+import com.yh.saas.plugin.base.entity.CommonBillOperateHis;
+import com.yh.saas.plugin.base.service.ICommonBillOperateHisService;
+import com.yh.saas.toolkit.workflow.service.IWorkflowHistoryService;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Service
+public class BillOprateHisImpl implements IBillOperateHisService {
+
+    @Autowired
+    private ICommonBillOperateHisService billOperateHisService;
+
+    @Autowired
+    private IWorkflowHistoryService workflowHistoryService;
+
+    @Override
+    public List<CommonBillOperateHis> getBillOperateHis(String id, String billType) {
+        Wrapper<CommonBillOperateHis> wrapper = new EntityWrapper<>();
+        wrapper.eq(CommonBillOperateHis.QueryFields.BILL_ID, id);
+        if (StringUtils.isNotBlank(billType)) {
+            wrapper.eq(CommonBillOperateHis.QueryFields.BILL_TYPE, billType);
+        }
+        wrapper.orderBy(CommonBillOperateHis.QueryFields.OPERATE_DATE, false);
+        List<CommonBillOperateHis> list = billOperateHisService.selectList(wrapper);
+
+        // 采购询价单特殊处理
+        if ("PURCHASE-MAT-TYPE-ENQUIRY".equals(billType) || "PURCHASE-MAP-TYPE-ENQUIRY".equals(billType)
+                || "PURCHASE-SP-TYPE-ENQUIRY".equals(billType)) {
+            return list;
+        }
+        List<WorkflowHistoricTask> historicTasks = this.workflowHistoryService.getInstanceHistories(id);
+        if (CollectionUtils.isNotEmpty(historicTasks)) {
+            historicTasks
+                    .forEach(
+                            histortyTask -> list.add(CommonBillOperateHis.getInstance(histortyTask.getOperatorName(),
+                                    histortyTask.getClaimTime(),
+                                    histortyTask.getApproved() ? "1" : "0", histortyTask.getTaskName(),
+                                    histortyTask.getTaskNameEn(), histortyTask.getOperatorMajorRoleName(),
+                                    histortyTask.getAuditMind())));
+        }
+        return list.stream().sorted(Comparator.comparing(CommonBillOperateHis::getOperateDate).reversed())
+                .collect(Collectors.toList());
+    }
+
+}

+ 100 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/impl/CommonParameterCompanyServiceImpl.java

@@ -0,0 +1,100 @@
+package com.yh.saas.platform.service.impl;
+
+import com.alipay.sofa.runtime.api.annotation.SofaReference;
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.baomidou.mybatisplus.mapper.Wrapper;
+import com.baomidou.mybatisplus.toolkit.CollectionUtils;
+import com.winsea.svc.base.base.entity.CommonParameterCompany;
+import com.winsea.svc.base.base.service.ICommonParameterCompanyService;
+import com.winsea.svc.base.security.util.AuthSecurityUtils;
+import com.winsea.svc.base.workflow.entity.Workflow;
+import com.winsea.svc.base.workflow.entity.WorkflowStep;
+import com.winsea.svc.base.workflow.entity.WorkflowStepCondition;
+import com.yh.saas.platform.service.CommonParameterCompanyService;
+import com.yh.saas.toolkit.workflow.service.IWorkflowService;
+import com.yh.saas.toolkit.workflow.service.IWorkflowStepConditionService;
+import com.yh.saas.toolkit.workflow.service.IWorkflowStepService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 公司常量 服务实现类
+ * </p>
+ *
+ * @author Wangxiangshun
+ * @since 2021-02-19
+ */
+@Service
+public class CommonParameterCompanyServiceImpl implements CommonParameterCompanyService {
+
+    @SofaReference
+    private ICommonParameterCompanyService commonParameterCompanyService;
+    @Autowired
+    private IWorkflowService workflowService;
+    @Autowired
+    private IWorkflowStepService stepService;
+    @Autowired
+    private IWorkflowStepConditionService stepConditionService;
+
+    /**
+     * 查询基础数据,是否能删除标识
+     * @param constCode 变量code
+     * @param businessCode 工作流code
+     * @return
+     */
+    @Override
+    public List<CommonParameterCompany> selectListParam(String constCode,String businessCode) {
+        Wrapper<CommonParameterCompany> wr = new EntityWrapper<>();
+        // 根据公司,code,顺序号查询
+        List<CommonParameterCompany> parameterCompanyList = commonParameterCompanyService.selectList(wr);
+
+        if (CollectionUtils.isNotEmpty(parameterCompanyList)) {
+            // 查询物料申请单审核流条件中用到的key
+            List<String> conditionKey = getMatApplWorkflowStepConditionVal(businessCode);
+            // 设置当前类型能否删除
+            for (CommonParameterCompany commonParameterCompany : parameterCompanyList) {
+                // 在审核流中用到的也不能删
+                if (CollectionUtils.isNotEmpty(conditionKey) && conditionKey.contains(commonParameterCompany.getParameterKey())) {
+                    commonParameterCompany.setConstCodes("1");
+                }
+            }
+        }
+        return parameterCompanyList;
+    }
+
+    /**
+     * 查询审核流条件中用到的key
+     *
+     * @return
+     */
+    private List<String> getMatApplWorkflowStepConditionVal(String businessCode) {
+        List<String> conditionKey = new ArrayList<>();
+        // 查询审核流信息
+        List<Workflow> workflowDefinitions1 = workflowService.getWorkflowDefinitions(businessCode,
+                AuthSecurityUtils.getCurrentUserInfo().getCompId());
+
+        if (CollectionUtils.isEmpty(workflowDefinitions1)) {
+            return conditionKey;
+        }
+        // 查审核流步骤
+        List<WorkflowStep> detailByWorkflowId = stepService.getDetailByWorkflowId(workflowDefinitions1.get(0).getId());
+        if (CollectionUtils.isNotEmpty(detailByWorkflowId)) {
+            // 查出所有步骤对应的条件
+            List<WorkflowStepCondition> byStepIdList = stepConditionService.findByStepIdList(detailByWorkflowId.stream()
+                    .map(WorkflowStep::getId).collect(Collectors.toList()));
+            // 取出条件值
+            if (CollectionUtils.isNotEmpty(byStepIdList)) {
+                conditionKey = byStepIdList.stream().map(WorkflowStepCondition::getVarValue).collect(Collectors.toList());
+            }
+        }
+        return conditionKey;
+    }
+
+
+
+}

+ 278 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/impl/FlowTaskCandidateServiceImpl.java

@@ -0,0 +1,278 @@
+package com.yh.saas.platform.service.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import com.winsea.svc.base.workflow.entity.Workflow;
+import com.winsea.svc.base.workflow.entity.WorkflowStep;
+import com.yh.saas.toolkit.workflow.exception.WorkflowErrorCodeEnums;
+import com.yh.saas.toolkit.workflow.exception.WorkflowException;
+import com.yh.saas.toolkit.workflow.service.IWorkflowService;
+import com.yh.saas.toolkit.workflow.service.IWorkflowStepService;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.alipay.sofa.runtime.api.annotation.SofaReference;
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.google.common.collect.Lists;
+import com.winsea.svc.base.base.entity.CommonRole;
+import com.winsea.svc.base.base.entity.CommonStaff;
+import com.winsea.svc.base.base.entity.CommonStaffRole;
+import com.winsea.svc.base.base.service.ICommonRoleService;
+import com.winsea.svc.base.base.service.ICommonStaffRoleService;
+import com.winsea.svc.base.base.service.ICommonStaffService;
+import com.yh.saas.platform.entity.view.FlowTaskCandidateStaffView;
+import com.yh.saas.platform.entity.view.FlowTaskCandidateStaffView.CandidateType;
+import com.yh.saas.platform.service.IFlowTaskCandidateService;
+import com.yh.saas.toolkit.workflow.activiti.util.ActivitiProcessUtils;
+import com.yh.saas.toolkit.workflow.activiti.util.ActivitiTaskUtils;
+
+/**
+ * 流程候选人服务实现
+ *
+ * @author SunTianjun
+ */
+@Service
+public class FlowTaskCandidateServiceImpl implements IFlowTaskCandidateService {
+
+	@SofaReference
+	private ICommonStaffService staffService;
+
+	@SofaReference
+	private ICommonRoleService roleService;
+
+	@SofaReference
+	private ICommonStaffRoleService staffRoleService;
+
+	@Autowired
+	private IWorkflowService workflowService;
+
+	@Autowired
+	private IWorkflowStepService workflowStepService;
+
+
+	@Override
+	public FlowTaskCandidateStaffView getCandidateStaffInfo(String flowId, String businessKey) {
+		FlowTaskCandidateStaffView flowTaskCandidateStaffView = buildStaffView(flowId, businessKey);
+		if (null == flowTaskCandidateStaffView) {
+			flowTaskCandidateStaffView = buildRoleStaffView(flowId, businessKey);
+		}
+
+		if (null == flowTaskCandidateStaffView) {
+			flowTaskCandidateStaffView = new FlowTaskCandidateStaffView();
+			flowTaskCandidateStaffView.setCandidateType(CandidateType.NONE);
+		}
+
+		return flowTaskCandidateStaffView;
+	}
+
+
+	@Override
+	public FlowTaskCandidateStaffView findPreReveiewerStaffInfo(String businessCode) {
+		//查询当前步骤最新审核流
+		Workflow workflow = this.workflowService.findLatestWorkflowByBusinessCode(businessCode);
+		if (null == workflow) {
+			throw new WorkflowException(WorkflowErrorCodeEnums.WORKFLOW_NULL);
+		}
+
+		//查询步骤
+		List<WorkflowStep> workflowSteps = workflowStepService.getDetailByWorkflowId(workflow.getId());
+		WorkflowStep preWorkflowStep = null;
+		for (int i = 0; i < workflowSteps.size(); i++) {
+			WorkflowStep workflowStep = workflowSteps.get(i);
+			if (!"_PLACEHOLDER_".equals(workflowStep.getDesc())) {
+				if (!WorkflowStep.StepType.NORMAL.equals(workflowStep.getStepType())) {
+					throw new WorkflowException(WorkflowErrorCodeEnums.WORKFLOW_STEP_NOT_NORMAL);
+				}
+				preWorkflowStep = workflowStep;
+				break;
+			}
+		}
+
+		if (null == preWorkflowStep) {
+			throw new WorkflowException(WorkflowErrorCodeEnums.WORKFLOW_STEP_NULL);
+		}
+
+		//带选择角色
+		List<CommonStaffRole> staffRoles = null;
+		List<FlowTaskCandidateStaffView.RoleStaffView> roleStaffViews = new ArrayList<>();
+
+		FlowTaskCandidateStaffView flowTaskCandidateStaffView = new FlowTaskCandidateStaffView();
+
+		//查出审核人
+		String auditType = StringUtils.isEmpty(preWorkflowStep.getAuditRoles()) ? "staff" : "role";
+		if ("staff".equals(auditType)) {
+			List<String> staffIds = Lists.newArrayList(preWorkflowStep.getAuditUsers().split(","));
+			flowTaskCandidateStaffView.setCandidateType(CandidateType.STAFF);
+			flowTaskCandidateStaffView.setStaffs(staffService.findStaffs(staffIds));
+			return flowTaskCandidateStaffView;
+		} else {
+			List<String> roleIds = Lists.newArrayList(preWorkflowStep.getAuditRoles().split(","));
+			staffRoles = staffRoleService.findStaff(roleIds);
+			Map<String, List<CommonStaffRole>> staffRoleMap = staffRoles.stream().collect(Collectors.groupingBy(CommonStaffRole::getRoleId));
+
+			for (String roleId : staffRoleMap.keySet()) {
+				List<String> staffIds = staffRoleMap.get(roleId).stream().map(CommonStaffRole::getStaffId).collect(Collectors.toList());
+				FlowTaskCandidateStaffView.RoleStaffView roleStaffView = new FlowTaskCandidateStaffView.RoleStaffView();
+				roleStaffView.setRole(roleService.selectById(roleId));
+				roleStaffView.setStaffs(staffService.findStaffs(staffIds));
+				roleStaffViews.add(roleStaffView);
+			}
+
+			flowTaskCandidateStaffView.setCandidateType(CandidateType.ROLE_STAFF);
+			flowTaskCandidateStaffView.setRoleStaffs(roleStaffViews);
+			return flowTaskCandidateStaffView;
+		}
+	}
+
+
+	/**
+	 * 构建候选人信息<br/>
+	 * 候选人类型为职员
+	 *
+	 * @param flowId      流程ID
+	 * @param businessKey 业务ID
+	 * @return 候选人信息
+	 */
+	private FlowTaskCandidateStaffView buildStaffView(String flowId, String businessKey, String deptId) {
+		FlowTaskCandidateStaffView flowTaskCandidateStaffView = null;
+		List<String> staffIds = ActivitiTaskUtils.getCurrentSingleActiveTaskUsers(flowId, businessKey);
+		if (!staffIds.isEmpty()) {
+			flowTaskCandidateStaffView = new FlowTaskCandidateStaffView();
+			flowTaskCandidateStaffView.setCandidateType(CandidateType.STAFF);
+			List<CommonStaff> staffList = staffIds.stream().map(staffId -> staffService.selectById(staffId))
+					.collect(Collectors.toList());
+			if (StringUtils.isNotBlank(deptId)) {
+				flowTaskCandidateStaffView.setStaffs(staffList.stream()
+						.filter(staff -> StringUtils.equals(deptId, staff.getDeptId())).collect(Collectors.toList()));
+			} else {
+				flowTaskCandidateStaffView.setStaffs(staffList);
+			}
+			flowTaskCandidateStaffView.setCurrentActiveTaskId(setCurrentActiveTaskId(flowId, businessKey));
+
+			// 2020年3月4日17:03:22 整理数据 跟职务人员一样,使前端不用改变原有的数据结构
+			integratedData(flowTaskCandidateStaffView);
+		}
+		return flowTaskCandidateStaffView;
+	}
+
+	/**
+	 * 构建候选人信息<br/>
+	 * 候选人类型为职员
+	 *
+	 * @param flowId      流程ID
+	 * @param businessKey 业务ID
+	 * @return 候选人信息
+	 */
+	private FlowTaskCandidateStaffView buildStaffView(String flowId, String businessKey) {
+		FlowTaskCandidateStaffView flowTaskCandidateStaffView = null;
+		List<String> staffIds = ActivitiTaskUtils.getCurrentSingleActiveTaskUsers(flowId, businessKey);
+		if (!staffIds.isEmpty()) {
+			flowTaskCandidateStaffView = new FlowTaskCandidateStaffView();
+			flowTaskCandidateStaffView.setCandidateType(CandidateType.STAFF);
+			flowTaskCandidateStaffView.setStaffs(
+					staffIds.stream().map(staffId -> staffService.selectById(staffId)).collect(Collectors.toList()));
+
+			flowTaskCandidateStaffView.setCurrentActiveTaskId(setCurrentActiveTaskId(flowId, businessKey));
+
+			//2020年3月4日17:03:22 整理数据 跟职务人员一样,使前端不用改变原有的数据结构
+			integratedData(flowTaskCandidateStaffView);
+		}
+		return flowTaskCandidateStaffView;
+	}
+
+
+	/**
+	 * 通过角色下所有职员
+	 *
+	 * @param roleId 角色ID
+	 * @return 职员列表
+	 */
+	private List<CommonStaff> getStaffsByRoleId(String roleId) {
+		List<CommonStaffRole> staffRoles = staffRoleService
+				.selectList(new EntityWrapper<CommonStaffRole>().eq(CommonStaffRole.QueryFields.ROLE_ID, roleId));
+
+		return staffRoles.stream().map(staffRole -> staffService.selectById(staffRole.getStaffId()))
+				.collect(Collectors.toList());
+	}
+
+	/**
+	 * 获取当前活动的任务ID
+	 *
+	 * @param flowId      流程ID
+	 * @param businessKey 业务ID
+	 * @return 当前活动的任务ID
+	 */
+	private String setCurrentActiveTaskId(String flowId, String businessKey) {
+		return ActivitiTaskUtils.getActiveTask(
+				ActivitiProcessUtils.findInstanceByWorkflowIdAndBusinessKey(flowId, businessKey).getProcessInstanceId())
+				.getId();
+	}
+
+	/**
+	 * 整合数据清理下
+	 */
+	private void integratedData(FlowTaskCandidateStaffView flowTaskCandidateStaffView) {
+		Map<String, CommonStaff> staffMap = flowTaskCandidateStaffView.getStaffs().stream()
+				.collect(Collectors.toMap(CommonStaff::getStaffId, staff -> staff));
+		List<String> staffIds = Lists.newArrayList(staffMap.keySet());
+		// 只获取主要职务
+		List<CommonStaffRole> staffRoles = staffRoleService.findStaffRoles(staffIds).stream()
+				.filter(staffRole -> staffRole.getRoleMajor().equals("1")).collect(Collectors.toList());
+		Set<String> roleIds = staffRoles.stream().map(CommonStaffRole::getRoleId).collect(Collectors.toSet());
+
+		flowTaskCandidateStaffView.getStaffs().clear();
+		List<FlowTaskCandidateStaffView.RoleStaffView> roleStaffViews = new ArrayList<>();
+		roleIds.forEach(roleId -> {
+			CommonRole role = this.roleService.selectById(roleId);
+			List<String> newStaffIds = staffRoleService.findStaff(Lists.newArrayList(roleId)).stream()
+					.map(CommonStaffRole::getStaffId).collect(Collectors.toList());
+			newStaffIds.retainAll(staffIds);
+			List<CommonStaff> staffs = new ArrayList<>();
+			for (String staffId : newStaffIds) {
+				staffs.add(staffMap.get(staffId));
+			}
+
+			FlowTaskCandidateStaffView.RoleStaffView roleStaffView = new FlowTaskCandidateStaffView.RoleStaffView();
+			roleStaffView.setRole(role);
+			roleStaffView.setStaffs(staffs);
+			roleStaffViews.add(roleStaffView);
+		});
+
+		flowTaskCandidateStaffView.setRoleStaffs(roleStaffViews);
+	}
+
+	/**
+	 * 构建候选人信息<br/>
+	 * 候选人类型为角色职员
+	 *
+	 * @param flowId      流程ID
+	 * @param businessKey 业务ID
+	 * @return 候选人信息
+	 */
+	private FlowTaskCandidateStaffView buildRoleStaffView(String flowId, String businessKey) {
+		FlowTaskCandidateStaffView flowTaskCandidateStaffView = null;
+		List<String> roleIds = ActivitiTaskUtils.getCurrentSingleActiveTaskRoles(flowId, businessKey);
+		if (!roleIds.isEmpty()) {
+			flowTaskCandidateStaffView = new FlowTaskCandidateStaffView();
+			flowTaskCandidateStaffView.setCurrentActiveTaskId(setCurrentActiveTaskId(flowId, businessKey));
+			flowTaskCandidateStaffView.setCandidateType(CandidateType.ROLE_STAFF);
+			flowTaskCandidateStaffView.setRoleStaffs(new ArrayList<>());
+
+			for (String roleId : roleIds) {
+				FlowTaskCandidateStaffView.RoleStaffView roleStaffView = new FlowTaskCandidateStaffView.RoleStaffView();
+				roleStaffView.setRole(roleService.selectById(roleId));
+				roleStaffView.setStaffs(getStaffsByRoleId(roleId));
+
+				flowTaskCandidateStaffView.getRoleStaffs().add(roleStaffView);
+			}
+		}
+		return flowTaskCandidateStaffView;
+	}
+
+
+}

+ 71 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/impl/FuncClickInfoServiceImpl.java

@@ -0,0 +1,71 @@
+package com.yh.saas.platform.service.impl;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.baomidou.mybatisplus.mapper.Wrapper;
+import com.baomidou.mybatisplus.service.impl.ServiceImpl;
+import com.winsea.svc.base.security.util.AuthSecurityUtils;
+import com.yh.saas.common.support.util.IdGenerator;
+import com.yh.saas.platform.entity.FuncClickInfo;
+import com.yh.saas.platform.mapper.FuncClickInfoMapper;
+import com.yh.saas.platform.service.IFuncClickInfoService;
+
+/**
+ * <p>
+ * APP功能点击次数记录表 服务实现类
+ * </p>
+ *
+ * @author wxg
+ * @since 2019-11-12
+ */
+@Service
+public class FuncClickInfoServiceImpl extends ServiceImpl<FuncClickInfoMapper, FuncClickInfo>
+		implements IFuncClickInfoService {
+
+	@Override
+	public List<FuncClickInfo> queryFuncClickInfoList(String userId) {
+		// 查询功能点击次数记录列表
+		Wrapper<FuncClickInfo> itemWrapper = new EntityWrapper<>();
+		itemWrapper.eq(FuncClickInfo.QueryFields.USER_ID, userId);
+		// itemWrapper.orderBy(FuncClickInfo.QueryFields.CLICK_COUNT, false);
+		List<FuncClickInfo> itemList = selectList(itemWrapper);
+
+		// 按点击次数倒序排序
+		return itemList.stream().sorted(Comparator.comparing(FuncClickInfo::getClickCount).reversed())
+				.collect(Collectors.toList());
+	}
+
+	@Override
+	public String saveFuncClickInfo(FuncClickInfo funcClickInfo) {
+		if (StringUtils.isBlank(funcClickInfo.getCompId())) {
+			funcClickInfo.setCompId(AuthSecurityUtils.getCurrentUserInfo().getCompId());
+		}
+
+		// 查询用户功能点击次数记录
+		Wrapper<FuncClickInfo> itemWrapper = new EntityWrapper<>();
+		itemWrapper.eq(FuncClickInfo.QueryFields.USER_ID, funcClickInfo.getUserId());
+		itemWrapper.eq(FuncClickInfo.QueryFields.FUNC_TYPE, funcClickInfo.getFuncType());
+		FuncClickInfo funcClick = this.selectOne(itemWrapper);
+
+		if (funcClick == null) {
+			// 如果不存在新增
+			funcClickInfo.setId(IdGenerator.generateLongIncrId());
+			funcClickInfo.setClickCount(1L);
+			this.insert(funcClickInfo);
+		} else {
+			// 如果存在更新
+			funcClickInfo.setId(funcClick.getId());
+			funcClickInfo.setClickCount(funcClick.getClickCount() + 1);
+			this.updateById(funcClickInfo);
+		}
+
+		return funcClickInfo.getId();
+	}
+
+}

+ 35 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/impl/NotificationBusinessCodeServiceImpl.java

@@ -0,0 +1,35 @@
+package com.yh.saas.platform.service.impl;
+
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.baomidou.mybatisplus.service.impl.ServiceImpl;
+import com.yh.saas.platform.entity.NotificationBusinessCode;
+import com.yh.saas.platform.mapper.NotificationBusinessCodeMapper;
+import com.yh.saas.platform.service.INotificationBusinessCodeService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 工作流 - businessCode集合 - 实现类
+ * </p>
+ *
+ * @author ZhangMingYu
+ * @since 2020年4月16日09:05:23
+ */
+@Service
+public class NotificationBusinessCodeServiceImpl extends ServiceImpl<NotificationBusinessCodeMapper, NotificationBusinessCode>
+        implements INotificationBusinessCodeService {
+
+    @Override
+    public NotificationBusinessCode findBusinessCodeInfo(String businessCode) {
+        return this.selectOne(new EntityWrapper<NotificationBusinessCode>().eq(NotificationBusinessCode.QueryFiled.BUSINESS_CODE, businessCode));
+    }
+
+    @Override
+    public List<String> findBusinessCodes() {
+        List<NotificationBusinessCode> notificationBusinessCodes = this.selectList(new EntityWrapper<>());
+        return notificationBusinessCodes.stream().map(NotificationBusinessCode::getBusinessCode).collect(Collectors.toList());
+    }
+}

+ 52 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/service/impl/ThermalRoutingServiceImpl.java

@@ -0,0 +1,52 @@
+package com.yh.saas.platform.service.impl;
+
+import java.util.List;
+
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.baomidou.mybatisplus.plugins.Page;
+import com.baomidou.mybatisplus.service.impl.ServiceImpl;
+import com.winsea.svc.base.security.util.AuthSecurityUtils;
+import com.yh.saas.common.support.util.IdGenerator;
+import com.yh.saas.common.support.util.StringUtils;
+import com.yh.saas.common.support.util.query.QueryUtils;
+import com.yh.saas.platform.entity.ThermalRouting;
+import com.yh.saas.platform.mapper.ThermalRoutingMapper;
+import com.yh.saas.platform.service.IThermalRoutingService;
+
+@Service
+public class ThermalRoutingServiceImpl extends ServiceImpl<ThermalRoutingMapper, ThermalRouting>
+		implements IThermalRoutingService {
+
+	@Override
+	@Transactional
+	public void renewalHead(ThermalRouting thermalRouting) {
+		if (StringUtils.isEmpty(thermalRouting.getAccountId())) {
+			thermalRouting.setAccountId(AuthSecurityUtils.getCurrentUserInfo().getAccountId());
+		}
+		thermalRouting.setCurrentHead(thermalRouting.getCurrentHead() + 1);
+		boolean isSuccess = this.update(thermalRouting, QueryUtils.convertExampleToWrapper(thermalRouting));
+		if (isSuccess) {
+			return;
+		}
+
+		thermalRouting.setCurrentHead(thermalRouting.getCurrentHead() - 1);
+		thermalRouting.setId(IdGenerator.generateUUID());
+		this.insert(thermalRouting);
+	}
+
+	@Override
+	public List<ThermalRouting> findHottestRouting(ThermalRouting thermalRouting) {
+		if (StringUtils.isEmpty(thermalRouting.getAccountId())) {
+			thermalRouting.setAccountId(AuthSecurityUtils.getCurrentUserInfo().getAccountId());
+		}
+		thermalRouting.setCurrentPage(1);
+		thermalRouting.setOrderColunm("updateCount");
+		thermalRouting.setOrder("descing");
+		Page<ThermalRouting> thermalRoutingPage = this.selectPage(thermalRouting.getQueryPage(),
+				QueryUtils.convertExampleToWrapper(thermalRouting));
+		return thermalRoutingPage.getRecords();
+
+	}
+}

+ 124 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/util/GtAppendixUtil.java

@@ -0,0 +1,124 @@
+package com.yh.saas.platform.util;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.Logger;
+
+public class GtAppendixUtil {
+
+	private static Logger log = (Logger) LoggerFactory.getLogger(GtAppendixUtil.class);
+
+	private GtAppendixUtil() {
+
+	}
+
+	/**
+	 * 把接受的全部文件打成压缩包
+	 * 
+	 * @param List<File>;
+	 * @param org.apache.tools.zip.ZipOutputStream
+	 */
+	public static void zipFiles(List<File> files, ZipOutputStream outputStream) {
+		int size = files.size();
+		for (int i = 0; i < size; i++) {
+			File file = files.get(i);
+			zipFile(file, outputStream);
+		}
+	}
+
+	/**
+	 * 根据输入的文件与输出流对文件进行打包
+	 * 
+	 * @param File
+	 * @param org.apache.tools.zip.ZipOutputStream
+	 */
+	public static void zipFile(File inputFile, ZipOutputStream ouputStream) {
+		try {
+			if (inputFile.isFile()) {
+				try (FileInputStream in = new FileInputStream(inputFile);
+						BufferedInputStream bins = new BufferedInputStream(in, 512)) {
+					ZipEntry entry = new ZipEntry(inputFile.getName());
+					ouputStream.putNextEntry(entry);
+					// 向压缩文件中输出数据
+					int nNumber;
+					byte[] buffer = new byte[512];
+					while ((nNumber = bins.read(buffer)) != -1) {
+						ouputStream.write(buffer, 0, nNumber);
+					}
+				}
+			} else {
+				File[] files = inputFile.listFiles();
+				for (int i = 0; i < files.length; i++) {
+					zipFile(files[i], ouputStream);
+				}
+			}
+		} catch (Exception e) {
+			log.error("文件打包出错", e);
+		}
+	}
+
+	public static void downloadZip(File rootFile, String frontOrigin, HttpServletResponse response) {
+		try {
+			response.reset();
+
+			response.setContentType("application/octet-stream");
+			// 如果输出的是中文名的文件,在此处就要用URLEncoder.encode方法进行处理
+			response.setHeader("Content-Disposition",
+					"attachment;filename=" + new String(rootFile.getName().getBytes("UTF-8"), "ISO8859-1"));
+			response.setHeader("Access-Control-Allow-Origin", frontOrigin);
+			response.setHeader("Access-Control-Allow-Credentials", "true");
+			// 以流的形式下载文件。
+			try (InputStream fis = new BufferedInputStream(new FileInputStream(rootFile.getPath()));
+					OutputStream toClient = new BufferedOutputStream(response.getOutputStream())) {
+				byte[] buffer = new byte[fis.available()];
+				int nNumber;
+				while ((nNumber = fis.read(buffer)) > 0) {
+					toClient.write(buffer, 0, nNumber);
+				}
+			}
+		} catch (Exception ex) {
+			log.error("文件下载出错", ex);
+		} finally {
+			try {
+				File file = new File(rootFile.getPath());
+				boolean result = file.delete();
+				if (!result) {
+					log.warn(file.getAbsolutePath() + "删除失败!");
+				}
+			} catch (Exception e) {
+				log.error(e.getMessage());
+			}
+		}
+	}
+
+	/**
+	 * 计算文件大小
+	 * 
+	 * @param size
+	 * @return
+	 */
+	public static String getFileSize(int size) {
+		String result = "";
+		if (size / 1024 / 1024 >= 1) {
+			result = String.valueOf(size / 1024 / 1024) + "MB";
+		} else if (size / 1024 >= 1) {
+			result = String.valueOf(size / 1024) + "KB";
+		} else {
+			result = String.valueOf(size) + "B";
+		}
+		return result;
+	}
+
+}

+ 16 - 0
winsea-haixin-platform-backend/src/main/java/com/yh/saas/platform/vo/NotificationStaffTodoTaskVO.java

@@ -0,0 +1,16 @@
+package com.yh.saas.platform.vo;
+
+import lombok.Data;
+
+@Data
+public class NotificationStaffTodoTaskVO {
+
+    //主键id
+    private String id;
+
+    //当前系统时间
+    private String time;
+
+    //略过天数
+    private String delay;
+}

+ 1 - 0
winsea-haixin-platform-backend/src/main/resources/META-INF/services/sofa-rpc/com.alipay.sofa.rpc.client.Router

@@ -0,0 +1 @@
+customerRouter=com.winsea.svc.common.sofa.CustomerRouter

+ 2 - 0
winsea-haixin-platform-backend/src/main/resources/META-INF/spring.factories

@@ -0,0 +1,2 @@
+org.springframework.boot.env.EnvironmentPostProcessor=\
+com.winsea.svc.common.config.CommonConfig

+ 104 - 0
winsea-haixin-platform-backend/src/main/resources/application-dev.yml

@@ -0,0 +1,104 @@
+server:
+  port: 8090
+
+spring:
+  application:
+    name: winsea-haixin-project
+  datasource:
+    driver-class-name: com.mysql.jdbc.Driver
+#    password:
+#    url: jdbc:mysql://127.0.0.1:3306/winsea_haixin?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&serverTimezone=Asia/Shanghai
+#    username: root
+# password: yinghai.2019
+#    url: jdbc:mysql://192.168.26.6:3306/winsea_haixin?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&serverTimezone=Asia/Shanghai
+#    username: root
+  password: Ccj841968545
+    url: jdbc:mysql://47.100.3.209:3306/yilaingyiyun?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&serverTimezone=Asia/Shanghai
+    username: root
+  redis:
+    database: 0
+    host: 192.168.26.10
+    password: ''
+    pool:
+      max-active: 8
+      max-idle: 8
+      max-wait: -1
+      min-idle: 0
+    port: 6379
+    timeout: 5000
+  servlet:
+    multipart:
+      max-file-size: 15MB
+      max-request-size: 120MB
+
+auth:
+  default-user-kind: STAFF
+client:
+  ftp:
+    ip: 114.115.215.70
+    port: 21
+  sync:
+    address: http://114.115.215.70:85/webservice/ClientUpdateService?wsdl
+file:
+  path: E://haixin-data//winsea//file//
+file-root-path: /winsea/static/
+front-origin: 192.168.1.162:9527
+jasypt:
+  encryptor:
+    password: yinghaikeji
+logging:
+  level:
+    root: INFO
+  path: E:/environmentae-science/haixin-files/uat/logs
+oss:
+  access:
+    key:
+      id: Y8IZ2bDqwsFDLqM0
+      secret: GX34icMi6crTpF3IW31hv2CMTnpEO4
+  bucket:
+    name: winsea-saas-test
+  endpoint:
+    default: oss-cn-shanghai.aliyuncs.com
+    internal: http://oss-cn-shanghai.aliyuncs.com
+po:
+  password: CA1XB-MF7Y-12ST-PSBP2
+  syspath: E://officeTest//
+purchase:
+  webservice:
+    address: http://114.115.215.70:8018/webservice/QuoteServerService?wsdl
+
+servicer:
+  register:
+    webservice:
+      address: http://114.115.215.70:8018/webservice/QuoteServerService?wsdl
+
+system:
+  temp-file-path: E://haixin-data//
+  prod-temp-file-path: /environmentae-science/haixin-files/uat/tpl/
+  department-deck: efc79c703d6c4a8dafb88b5e60192e82
+
+#sp:
+#  enquiry:
+#    path:  http://vms-test.winseacity.com/layer/v1/winsea/gateway/enquiry/apply/sp
+#  purchase:
+#    path:  http://vms-test.winseacity.com/layer/v1/winsea/ddPurchaseInfo/purchase/sp
+#  again:
+#    path:  http://vms-test.winseacity.com/layer/v1/winsea/gateway/enquiry/apply/editXjQuotesInfo
+#  enquirydate:
+#    path:  http://vms-test.winseacity.com/layer/v1/winsea/gateway/enquiry/apply/batchEditEnquiryDate
+#ma:
+#  enquiry:
+#    path:  http://vms-test.winseacity.com/layer/v1/winsea/gateway/enquiry/apply/ma
+#  purchase:
+#    path:  http://vms-test.winseacity.com/layer/v1/winsea/ddPurchaseInfo/purchase/ma
+
+
+gexinpush:
+  host: http://yilaingyiyun.com/
+  appId: 1001
+  appkey: 2001
+  appSecret: 3001
+  masterSecret: 4001
+  environment: 5001
+  live:
+    time: 10

+ 87 - 0
winsea-haixin-platform-backend/src/main/resources/application-local.yml

@@ -0,0 +1,87 @@
+server:
+  port: 8090
+
+spring:
+  application:
+    name: winsea-changchang-project
+  datasource:
+    driver-class-name: com.mysql.jdbc.Driver
+    password: Ccj841968545
+    url: jdbc:mysql://47.100.3.209:3306/wlhy?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&serverTimezone=Asia/Shanghai
+#    url: jdbc:mysql://47.100.3.209:3306/ylyy?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&serverTimezone=Asia/Shanghai
+    username: root
+  redis:
+    database: 0
+    host: 127.0.0.1
+    password: ''
+    pool:
+      max-active: 8
+      max-idle: 8
+      max-wait: -1
+      min-idle: 0
+    port: 6379
+    timeout: 200
+  servlet:
+    multipart:
+      max-file-size: 15MB
+      max-request-size: 120MB
+
+auth:
+  default-user-kind: STAFF
+client:
+  ftp:
+    ip: 114.115.215.70
+    port: 21
+  sync:
+    address: http://114.115.215.70:85/webservice/ClientUpdateService?wsdl
+file:
+  path: E://alpha//winsea//file//
+file-root-path: E://file//crew/
+front-origin: 192.168.1.162:9527
+jasypt:
+  encryptor:
+#    password: yinghaikeji
+    password: yilaingyiyun
+logging:
+  level:
+    root: DEBUG
+  path: E:/winsea_platform6.0/logs
+oss:
+  access:
+    key:
+      id: LTAI4G9c14PgKvM23WZ9zrpc
+      secret: FpClTp4OVrRRtHEfi3lBOWUoLxKieW
+  bucket:
+    name: taohaoliang
+  endpoint:
+    default: oss-cn-beijing.aliyuncs.com
+    internal: https://taohaoliang.oss-cn-beijing.aliyuncs.com/
+po:
+  password: CA1XB-MF7Y-12ST-PSBP2
+  syspath: E://officeTest//
+purchase:
+  webservice:
+    address: http://114.115.215.70:8018/webservice/QuoteServerService?wsdl
+
+servicer:
+  register:
+    webservice:
+      address: http://114.115.215.70:8018/webservice/QuoteServerService?wsdl
+
+system:
+  temp-file-path: E://file//
+  prod-temp-file-path: /opt/winsea/temp/platform/
+  department-deck: efc79c703d6c4a8dafb88b5e60192e82
+
+
+
+
+gexinpush:
+  host:
+  appId: 1001
+  appkey: 2001
+  appSecret: 3001
+  masterSecret: 4001
+  environment: 5001
+  live:
+    time: 10

+ 87 - 0
winsea-haixin-platform-backend/src/main/resources/application-prod.yml

@@ -0,0 +1,87 @@
+server:
+  port: 9100
+
+spring:
+  application:
+    name: winsea-changchang-project
+  datasource:
+    driver-class-name: com.mysql.jdbc.Driver
+    password: Ccj841968545
+    url: jdbc:mysql://47.100.3.209:3306/ylyy?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&serverTimezone=Asia/Shanghai
+    username: root
+  redis:
+    database: 0
+    host: 127.0.0.1
+    password: ''
+    pool:
+      max-active: 8
+      max-idle: 8
+      max-wait: -1
+      min-idle: 0
+    port: 6379
+    timeout: 200
+  servlet:
+    multipart:
+      max-file-size: 50MB
+      max-request-size: 120MB
+
+auth:
+  default-user-kind: STAFF
+client:
+  ftp:
+    ip: 114.115.215.70
+    port: 21
+  sync:
+    address: http://114.115.215.70:85/webservice/ClientUpdateService?wsdl
+file:
+  path: E://alpha//winsea//file//
+file-root-path: E://file//crew/
+front-origin: 192.168.1.162:9527
+jasypt:
+  encryptor:
+    #    password: yinghaikeji
+    password: yilaingyiyun
+logging:
+  level:
+    root: INFO
+  path: E:/winsea_platform6.0/logs
+oss:
+  access:
+    key:
+      id: LTAI4G9c14PgKvM23WZ9zrpc
+      secret: FpClTp4OVrRRtHEfi3lBOWUoLxKieW
+  bucket:
+    name: taohaoliang
+  endpoint:
+    default: oss-cn-beijing.aliyuncs.com
+    internal: https://taohaoliang.oss-cn-beijing.aliyuncs.com/
+
+po:
+  password: CA1XB-MF7Y-12ST-PSBP2
+  syspath: E://officeTest//
+purchase:
+  webservice:
+    address: http://114.115.215.70:8018/webservice/QuoteServerService?wsdl
+
+servicer:
+  register:
+    webservice:
+      address: http://114.115.215.70:8018/webservice/QuoteServerService?wsdl
+
+system:
+  temp-file-path: E://file//
+  prod-temp-file-path: /opt/winsea/temp/platform/
+  department-deck: efc79c703d6c4a8dafb88b5e60192e82
+
+
+
+
+gexinpush:
+  host:
+  appId: 1001
+  appkey: 2001
+  appSecret: 3001
+  masterSecret: 4001
+  environment: 5001
+  live:
+    time: 10

+ 96 - 0
winsea-haixin-platform-backend/src/main/resources/application-test.yml

@@ -0,0 +1,96 @@
+server:
+  port: 9000
+
+spring:
+  datasource:
+    driver-class-name: com.mysql.jdbc.Driver
+#    password: yinghai.2020
+#    url: jdbc:mysql://127.0.0.1:3306/winsea_szenergy_uat?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&serverTimezone=Asia/Shanghai
+    username: root
+  redis:
+    database: 0
+    host: 127.0.0.1
+    password: ''
+    pool:
+      max-active: 8
+      max-idle: 8
+      max-wait: -1
+      min-idle: 0
+    port: 6379
+    timeout: 200
+  servlet:
+    multipart:
+      max-file-size: 15MB
+      max-request-size: 120MB
+
+auth:
+  default-user-kind: STAFF
+  test-domain-name: YLYY
+bi:
+  server:
+    context-path: /WebReport/ReportServer
+    ip: 106.15.237.127
+    port: 8075
+    protocol: http
+    report-base-path: /test/winsea6.0/{compId}
+client:
+  ftp:
+    ip: 114.115.215.70
+    port: 21
+  sync:
+    address: http://114.115.215.70:85/webservice/ClientUpdateService?wsdl
+file-root-path: D:\xtdata\
+front-origin: ''
+gateway:
+  access-log:
+    end-log-format: '[LOG#${id}] ${name} END ${result}'
+    error-log-format: '[LOG#${id}] ${name} EXCEPTION (${exClass}) ${message}'
+    start-log-format: '[LOG#${id}] ${name} START ${params}'
+jasypt:
+  encryptor:
+    password: yinghaikeji
+job:
+  admin:
+    addresses: http://172.18.0.99:8080/xxl-job-admin
+  executor:
+    appname: platform-executor
+    ip: ''
+    logpath: /winsea/logs/xxl-job/platform
+    logretentiondays: -1
+    port: 9999
+logging:
+  level:
+    root: INFO
+  path: /environmentae-science/xt-files/uat/logs
+oss:
+  access:
+    key:
+      id: Y8IZ2bDqwsFDLqM0
+      secret: GX34icMi6crTpF3IW31hv2CMTnpEO4
+  bucket:
+    name: winsea-saas-test
+  endpoint:
+    default: oss-cn-shanghai.aliyuncs.com
+    internal: http://oss-cn-shanghai-internal.aliyuncs.com
+  isUsed: false
+po:
+  password: CA1XB-MF7Y-12ST-PSBP2
+#  syspath: /environmentae-science/xt-files/license/pageoffice/
+purchase:
+  webservice:
+    address: http://114.115.215.70:8018/webservice/QuoteServerService?wsdl
+
+servicer:
+  register:
+    webservice:
+      address: http://114.115.215.70:8018/webservice/QuoteServerService?wsdl
+
+system:
+  proxy:
+    flag: false
+    ip: 10.170.190.5
+    password: ''
+    port: 9090
+    user: ''
+  temp-file-path: /environmentae-science/xt-files/uat/tpl/
+  department-deck: ea79c0c9f9cb41fb8a20a7bc1362437b

+ 356 - 0
winsea-haixin-platform-backend/src/main/resources/application.yml

@@ -0,0 +1,356 @@
+spring:
+  activiti:
+    check-process-definitions: false
+    database-schema-update: true
+  application:
+    name: winsea-haixin-project
+  freemarker:
+    template:
+      makename: OPM 5.4C Seafarers Pre-Joining Vessel Training Record.doc
+      name: OPM 5.4C Seafarers Pre-Joining Vessel Training Record.xml
+  jackson:
+    date-format: yyyy-MM-dd HH:mm:ss
+    time-zone: GMT+8
+  profiles:
+    active: @env@
+  resources:
+    static-locations: file:///winsea/static/
+  thymeleaf:
+    cache: false
+    encoding: UTF-8
+    mode: HTML5
+    prefix: classpath:/templates/
+    suffix: .html
+
+auth:
+  anon-methods:
+    - GET
+    - POST
+  anon-urls:
+    - /auth/api/login
+    - /auth/api/loginEnhanced
+    - /auth/api/loginQuickly
+    - /auth/api/checkPassword
+    - /auth/api/retrievePassword
+    - /veriCode/api/send
+    - /veriCode/api/check
+    - /company/query/companyInfoByDomainName
+    - /webservice/**/*
+    - /workflowSync/api/startFlow
+    - /office/*
+    - /warehouseInOutInfo/*
+    - /warehouseInOutInfo/**/*
+    - /warehouseBaseInfo/*
+    - /warehouseBaseInfo/**/*
+    - /identityAuthenticationInfo/*
+    - /identityAuthenticationInfo/**/*
+    - /purchaseOrder/*
+    - /purchaseOrder/**/*
+    - /appVersion/*
+    - /procurementPlanInfo/*
+    - /procurementPlanInfo/**/*
+    - /tranCarInfo/*
+    - /tranCarInfo/**/*
+    - /auth/api/phoneLogin
+    - /system/query/getComanyMgrUrl
+    - /saas/**/*
+    - /ws/**/*
+    - /commonUser/*
+    - /commonUser/**/*
+    - /contractManagementInfo/*
+    - /contractManagementInfo/**/*
+    - /salePlanInfo/*
+    - /salePlanInfo/**/*
+    - /freightReceivingDispatching/*
+    - /freightReceivingDispatching/**/*
+    - /receivingUser/*
+    - /receivingUser/**/*
+    - /settledCompanyInfo/*
+    - /settledCompanyInfo/**/*
+    - /settledCompanyDynamics/*
+    - /settledCompanyDynamics/**/*
+    - /searchRecordsInfo/*
+    - /searchRecordsInfo/**/*
+    - /saleOrder/*
+    - /saleOrder/**/*
+    - /driverViewInfo/*
+    - /driverViewInfo/**/*
+    - /appendix/*
+    - /appendix/**/*
+    - /noticeTask/*
+    - /noticeTask/**/*
+    - /notice/*
+    - /notice/**/*
+    - /paymentManagement/*
+    - /paymentManagement/**/*
+    - /qualityInspectionManagement/*
+    - /qualityInspectionManagement/**/*
+    - /weighingManagement/*
+    - /weighingManagement/**/*
+    - /biInfoController/**/*
+    - /biInfoController/*
+  expire-in: 2592000
+  login-url: /login.html
+  logout-url: /auth/api/logout
+  session-timeout: -1
+  success-url: ''
+  unauthorized-url: ''
+
+bi:
+  report:
+    export:
+      crew_library: /crew_library.cpt
+      crew_resume: /crew_resume.cpt
+      crew_warning_certificate: /crew_warning_certificate.cpt
+      embarkation_crew: /embarkation_crew.cpt
+      finance_dept_budget: /finance_dept_budget.cpt
+      finance_monthly_fund_summary: /finance_monthly_fund_summary.cpt
+      finance_reimbursement_apply: /finance_reimbursement_apply.cpt
+      finance_year_budget: /finance_year_budget.cpt
+      interview_assessment: /interview_assessment.cpt
+      ma_price_parity: /ma_price_parity.cpt
+      ma_quotes: /ma_quotes.cpt
+      ma_sparepart: /ma_sparepart.cpt
+      map_price_parity: /map_price_parity.cpt
+      map_quotes: /map_quotes.cpt
+      map_sparepart: /map_sparepart.cpt
+      on_board_crew: /on_board_crew.cpt
+      payment_approval: /payment_approval.cpt
+      payment_request: /payment_request.cpt
+      ship_certificate: /ship_certificate.cpt
+      sp_price_parity: /sp_price_parity.cpt
+      sp_quotes: /sp_quotes.cpt
+      sp_sparepart: /sp_sparepart.cpt
+      spending_statistics: /spending_statistics.cpt
+      travel_expenses_apply: /travel_expenses_apply.cpt
+      xxx: /xxx/xxx2.cpt
+      zj_1e_handover: /zj_1e_handover.cpt
+      zj_2e_handover: /zj_2e_handover.cpt
+      zj_2o_handover: /zj_2o_handover.cpt
+      zj_3e_handover: /zj_3e_handover.cpt
+      zj_3o_handover: /zj_3o_handover.cpt
+      zj_capt_assessment: /zj_capt_assessment.cpt
+      zj_capt_assessment_training: /zj_capt_assessment_training.cpt
+      zj_capt_handover: /zj_capt_handover.cpt
+      zj_ce_assessment: /zj_ce_assessment.cpt
+      zj_ce_assessment_training: /zj_ce_assessment_training.cpt
+      zj_ce_handover: /zj_ce_handover.cpt
+      zj_co_handover: /zj_co_handover.cpt
+      zj_crew_assessment: /zj_crew_assessment.cpt
+      zj_crew_handover: /zj_crew_handover.cpt
+      zj_crew_interview: /zj_crew_interview.cpt
+      zj_driver_assessment: /zj_driver_assessment.cpt
+      zj_electrical_engineer_handover: /zj_electrical_engineer_handover.cpt
+      zj_engineer_assessment: /zj_engineer_assessment.cpt
+      zj_pre_job_training: /zj_pre_job_training.cpt
+      zj_seafarer_registration: /zj_seafarer_registration.cpt
+      zj_system_training: /zj_system_training.cpt
+    view:
+      annual_comparison: /annual_comparison.cpt
+      annual_summary: /annual_summary.cpt
+      dept_budget: /dept_budget.cpt
+      month_comparison: /month_comparison.cpt
+      month_summary: /month_summary.cpt
+      xxx: /xxx/xxx1.cpt
+
+certificate:
+  import:
+    datafile:
+      data-row-no: 2
+      title-row-no: 1
+
+comany-mgr-url: http://yilaingyiyun.com/mgr
+
+company:
+  simple-phonetic: HF
+cxf:
+  path: /webservice
+file:
+  base: saas
+  path:
+    car_brand: car/brand
+
+file-show-path: http://yilaingyiyun.com/pb/
+
+jpush:
+  appkey: 0f39aadb2d14d6a34c8a0d14
+  environment: true
+  live:
+    time: 10000
+  masterSecret: 2d5c37c625445ee37080ecbb
+
+mybatis-plus:
+  configuration:
+    map-underscore-to-camel-case: true
+  custom-config:
+    injections:
+      - column: now_version_no
+        expression: now_version_no+1
+      - column: update_count
+        expression: update_count+1
+  global-config:
+    logic-delete-value: 1
+    logic-not-delete-value: 0
+  mapper-locations: classpath*:/mapper/*Mapper.xml
+
+oss:
+  sts:
+    access:
+      key:
+        id: LTAIbgqtiEHUrOiX
+        secret: cdVxYXEPewoLcBnr49alcyAsoMjVH5
+    role:
+      arn: acs:ram::1699452713430929:role/winseaoss
+      policy: '{"Statement":[{"Action": "oss:*","Effect": "Allow","Resource":
+                "*"}],"Version": "1"}'
+  upload:
+    comp:
+      crew:
+        crew_library:
+          photo: /crew/crewLibrary/photo/
+        training:
+          word: /crew/training/word/
+      purchase:
+        quotes:
+          appendix: /purchase/quotes/appendix/
+    prefix: saas/
+    timeout: 30000
+pc-url: http://yilaingyiyun.com
+
+### 阿里云短信配置 ###
+sms:
+  aliyun:
+    accessId: LTAI4G9c14PgKvM23WZ9zrpc
+    accessKey: FpClTp4OVrRRtHEfi3lBOWUoLxKieW
+    signature: 易粮易运
+    register-template-id: SMS_202415307
+    bind-phone-template-id: SMS_202415307
+    reset-password-template-id: SMS_202415307
+    admin-login-template-id: SMS_202415307
+  enable: aliyun
+sys:
+  client-flag: B
+
+zuul:
+  routes:
+    accountLoginHistory:
+      id: /accountLoginHistory/**
+      url: ${zuul.baseServiceAddress}/authLoginHistory
+    auth:
+      id: /auth/**
+      url: ${zuul.baseServiceAddress}/auth
+    authCompanyController:
+      id: /authCompanyController/**
+      url: ${zuul.baseServiceAddress}/authCompanyController
+    baseCompany:
+      id: /baseCompany/**
+      url: ${zuul.baseServiceAddress}/baseCompany
+    baseRole:
+      id: /baseRole/**
+      url: ${zuul.baseServiceAddress}/baseRole
+    baseStaff:
+      id: /baseStaff/**
+      url: ${zuul.baseServiceAddress}/baseStaff
+    baseVessel:
+      id: /baseVessel/**
+      url: ${zuul.baseServiceAddress}/baseVessel
+    businessFeature:
+      id: /businessFeature/**
+      url: ${zuul.baseServiceAddress}/businessFeature
+    commonAnnouncementIssueInfo:
+      id: /commonAnnouncementIssueInfo/**
+      url: ${zuul.baseServiceAddress}/commonAnnouncementIssueInfo
+    commonCity:
+      id: /commonCity/**
+      url: ${zuul.baseServiceAddress}/commonCity
+    commonDeptRole:
+      id: /commonDeptRole/**
+      url: ${zuul.baseServiceAddress}/commonDeptRole
+    commonSendMailHostType:
+      id: /commonSendMailHostType/**
+      url: ${zuul.baseServiceAddress}/commonSendMailHostType
+    commonSendMailInfo:
+      id: /commonSendMailInfo/**
+      url: ${zuul.baseServiceAddress}/commonSendMailInfo
+    company:
+      id: /company/**
+      url: ${zuul.baseServiceAddress}/company
+    contactCompany:
+      id: /contactCompany/**
+      url: ${zuul.baseServiceAddress}/contactCompany
+    department:
+      id: /department/**
+      url: ${zuul.baseServiceAddress}/department
+    dictionary:
+      id: /dictionary/**
+      url: ${zuul.baseServiceAddress}/dictionary
+    dynamicForm:
+      id: /dynamicForm/**
+      url: ${zuul.baseServiceAddress}/dynamicForm
+    enums:
+      id: /enums/**
+      url: ${zuul.baseServiceAddress}/enums
+    featureTenant:
+      id: /featureTenant/**
+      url: ${zuul.baseServiceAddress}/featureTenant
+    file:
+      id: /file/**
+      url: ${zuul.baseServiceAddress}/file
+    manager:
+      id: /manager/**
+      url: ${zuul.baseServiceAddress}/manager
+    managerStaff:
+      id: /managerStaff/**
+      url: ${zuul.baseServiceAddress}/managerStaff
+    notificationCompanySystemMesage:
+      id: /notificationCompanySystemMesage/**
+      url: ${zuul.baseServiceAddress}/notificationCompanySystemMesage
+    parameterCompany:
+      id: /parameterCompany/**
+      url: ${zuul.baseServiceAddress}/parameterCompany
+    plugin:
+      id: /plugin/**
+      url: ${zuul.baseServiceAddress}/plugin
+    pluginMetaInfo:
+      id: /pluginMetaInfo/**
+      url: ${zuul.baseServiceAddress}/pluginMetaInfo
+    resourceGroup:
+      id: /resourceGroup/**
+      url: ${zuul.baseServiceAddress}/resourceGroup
+    resourceGroupRelation:
+      id: /resourceGroupRelation/**
+      url: ${zuul.baseServiceAddress}/resourceGroupRelation
+    roleMenu:
+      id: /roleMenu/**
+      url: ${zuul.baseServiceAddress}/roleMenu
+    roleResourceGroup:
+      id: /roleResourceGroup/**
+      url: ${zuul.baseServiceAddress}/roleResourceGroup
+    staffHomeShowInfo:
+      id: /staffHomeShowInfo/**
+      url: ${zuul.baseServiceAddress}/staffHomeShowInfo
+    statistical:
+      id: /statistical/**
+      url: ${zuul.baseServiceAddress}/statistical
+    tenantPlugin:
+      id: /tenantPlugin/**
+      url: ${zuul.baseServiceAddress}/tenantPlugin
+    tenantPluginAttribute:
+      id: /tenantPluginAttribute/**
+      url: ${zuul.baseServiceAddress}/tenantPluginAttribute
+    tenantPluginType:
+      id: /tenantPluginType/**
+      url: ${zuul.baseServiceAddress}/tenantPluginType
+    tenantResource:
+      id: /tenantResource/**
+      url: ${zuul.baseServiceAddress}/tenantResource
+    tenantService:
+      id: /tenantService/**
+      url: ${zuul.baseServiceAddress}/tenantService
+    tplForm:
+      id: /tplForm/**
+      url: ${zuul.baseServiceAddress}/tplForm
+    veriCode:
+      id: /veriCode/**
+      url: ${zuul.baseServiceAddress}/veriCode
+  sensitiveHeaders: ''

+ 24 - 0
winsea-haixin-platform-backend/src/main/resources/banner.txt

@@ -0,0 +1,24 @@
+
+ _______           _______  _        _______ _________ _______ _________
+/ ___   )|\     /|(  ___  )( (    /|(  ____ \\__   __/(  ___  )\__   __/
+\/   )  || )   ( || (   ) ||  \  ( || (    \/   ) (   | (   ) |   ) (
+    /   )| (___) || |   | ||   \ | || |         | |   | (___) |   | |
+   /   / |  ___  || |   | || (\ \) || | ____    | |   |  ___  |   | |
+  /   /  | (   ) || |   | || | \   || | \_  )   | |   | (   ) |   | |
+ /   (_/\| )   ( || (___) || )  \  || (___) |   | |   | )   ( |___) (___
+(_______/|/     \|(_______)|/    )_)(_______)   )_(   |/     \|\_______/
+
+ _                 _______  _______                    _______  _
+( (    /||\     /|(  ___  )(  ___  )|\     /||\     /|(  ___  )( (    /|
+|  \  ( || )   ( || (   ) || (   ) |( \   / )| )   ( || (   ) ||  \  ( |
+|   \ | || (___) || (___) || |   | | \ (_) / | |   | || (___) ||   \ | |
+| (\ \) ||  ___  ||  ___  || |   | |  \   /  | |   | ||  ___  || (\ \) |
+| | \   || (   ) || (   ) || |   | |   ) (   | |   | || (   ) || | \   |
+| )  \  || )   ( || )   ( || (___) |   | |   | (___) || )   ( || )  \  |
+|/    )_)|/     \||/     \|(_______)   \_/   (_______)|/     \||/    )_)
+ _  _  ____  __    ____    __    _  _  ___  _  _  ____  _  _  __  __  _  _
+( \/ )(_  _)(  )  (_  _)  /__\  ( \( )/ __)( \/ )(_  _)( \/ )(  )(  )( \( )
+ \  /  _)(_  )(__  _)(_  /(__)\  )  (( (_-. \  /  _)(_  \  /  )(__)(  )  (
+ (__) (____)(____)(____)(__)(__)(_)\_)\___/ (__) (____) (__) (______)(_)\_)
+
+::: Project (version:${application.version}) :::             \(^O^)/

+ 79 - 0
winsea-haixin-platform-backend/src/main/resources/db/migration/V6.0.1__init.sql

@@ -0,0 +1,79 @@
+/*
+ Navicat Premium Data Transfer
+
+ Source Server         : 192.168.1.89
+ Source Server Type    : MySQL
+ Source Server Version : 80015
+ Source Host           : 192.168.1.89:3306
+ Source Schema         : winsea_platform
+
+ Target Server Type    : MySQL
+ Target Server Version : 80015
+ File Encoding         : 65001
+
+ Date: 15/04/2019 10:46:08
+*/
+
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+-- Table structure for gt_appendix
+-- ----------------------------
+DROP TABLE IF EXISTS `gt_appendix`;
+CREATE TABLE `gt_appendix`  (
+  `appendix_id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '附件ID',
+  `bill_id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '表单ID',
+  `detail_id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '详细ID',
+  `model_id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '模块ID(同步数据用)',
+  `appendix_name` varchar(300) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '附件名称',
+  `appendix_path` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '附件路径',
+  `appendix_size` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '附件大小',
+  `create_date` datetime(0) NOT NULL COMMENT '作成年月日',
+  `create_user_id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '作成用户ID',
+  `update_date` datetime(0) NOT NULL COMMENT '更新年月日',
+  `update_user_id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '更新用户ID',
+  `update_flag` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '更新标识',
+  `delete_flag` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '删除标识',
+  PRIMARY KEY (`appendix_id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '附件表' ROW_FORMAT = Compact;
+
+-- ----------------------------
+-- Table structure for gt_company_menu
+-- ----------------------------
+DROP TABLE IF EXISTS `gt_company_menu`;
+CREATE TABLE `gt_company_menu`  (
+  `company_id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '公司ID',
+  `menu_id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '菜单ID',
+  `menu_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单名称',
+  `menu_name_en` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单英文名称',
+  `menu_order` int(11) NULL DEFAULT NULL COMMENT '菜单图标',
+  `parent_id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '父级菜单ID',
+  `create_user_id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '作成用户ID',
+  `create_date` datetime(0) NOT NULL COMMENT '作成时间',
+  `update_user_id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '更新用户ID',
+  `update_date` datetime(0) NOT NULL COMMENT '更新时间',
+  `update_flag` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '更新标识',
+  `delete_flag` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '删除标识',
+  PRIMARY KEY (`menu_id`, `company_id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '记录公司菜单资源信息' ROW_FORMAT = Compact;
+
+-- ----------------------------
+-- Table structure for gt_menu
+-- ----------------------------
+DROP TABLE IF EXISTS `gt_menu`;
+CREATE TABLE `gt_menu`  (
+  `menu_id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '菜单ID',
+  `menu_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单名称',
+  `menu_name_en` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单英文名称',
+  `menu_function` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单链接地址',
+  `create_user_id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '作成用户ID',
+  `create_date` datetime(0) NOT NULL ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '作成时间',
+  `update_user_id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '更新用户ID',
+  `update_date` datetime(0) NOT NULL ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '更新时间',
+  `update_flag` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '更新标识',
+  `delete_flag` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '删除标识',
+  PRIMARY KEY (`menu_id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '记录基本菜单资源信息' ROW_FORMAT = Compact;
+
+SET FOREIGN_KEY_CHECKS = 1;

+ 76 - 0
winsea-haixin-platform-backend/src/main/resources/logback-spring.xml

@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+	<property name="logFilePerfix" value="winsea-platform" />
+    <springProperty scope="context" name="logPath" source="logging.path"/>
+ 
+	<!--输出到控制台-->
+	<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+		<encoder>
+			<pattern>%d %-5p (%file:%line\) %m%n</pattern>
+			<charset>UTF-8</charset>
+		</encoder>
+	</appender>
+
+	<!--输出到文件-->
+    <!-- 时间滚动输出 level为 DEBUG 日志 -->
+    <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${logPath}/${logFilePerfix}-debug.log</file>
+        <!--日志文件输出格式-->
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+            <charset>UTF-8</charset> <!-- 设置字符集 -->
+        </encoder>
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志归档 -->
+            <fileNamePattern>${logPath}/debug/${logFilePerfix}-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>100MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+            <!--日志文件保留天数-->
+            <maxHistory>10</maxHistory>
+        </rollingPolicy>
+        <!-- 此日志文件只记录DEBUG级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>DEBUG</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+    
+    <!-- 时间滚动输出 level为INFO以及INFO以上级别的日志 -->
+    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${logPath}/${logFilePerfix}-info.log</file>
+        <!--日志文件输出格式-->
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+            <charset>UTF-8</charset>
+        </encoder>
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 每天日志归档路径以及格式 -->
+            <fileNamePattern>${logPath}/info/${logFilePerfix}-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>100MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+            <!--日志文件保留天数-->
+            <maxHistory>10</maxHistory>
+        </rollingPolicy>
+        <!-- 此日志文件只记录level为INFO以及INFO以上级别的日志 -->
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>INFO</level>
+        </filter>
+    </appender>
+
+    <root>
+        <appender-ref ref="CONSOLE" />
+        <appender-ref ref="DEBUG_FILE" />
+        <appender-ref ref="INFO_FILE" />
+    </root>
+
+ 	<logger name="java.sql.Connection" level="DEBUG"/>
+    <logger name="java.sql.Statement" level="DEBUG"/>
+    <logger name="java.sql.PreparedStatement" level="DEBUG"/>
+</configuration> 

+ 5 - 0
winsea-haixin-platform-backend/src/main/resources/mapper/CommonFuncClickInfoMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.yh.saas.platform.mapper.CommonFuncClickInfoMapper">
+
+</mapper>

+ 5 - 0
winsea-haixin-platform-backend/src/main/resources/mapper/CommonParameterConstMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.yh.saas.platform.mapper.CommonParameterConstMapper">
+
+</mapper>

+ 5 - 0
winsea-haixin-platform-backend/src/main/resources/mapper/CommonParameterTenantMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.yh.saas.platform.mapper.CommonParameterTenantMapper">
+
+</mapper>

+ 53 - 0
winsea-haixin-platform-backend/src/main/resources/templates/office/browser.html

@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
+      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
+    <head>
+        <title>winsea</title>
+        <script type="text/javascript">
+          	function Save() {
+              	document.getElementById("PageOfficeCtrl1").WebSave();
+              	// 如果是模板文件另存   返回新存储文件的fileID
+              	var fileId = document.getElementById("PageOfficeCtrl1").CustomSaveResult;
+              	//存储新文件的文件ID
+              	if(fileId != null && fileId != ""){
+              		// 调用父页 保存新文件ID方法
+              		window.external.CallParentFunc('setLocalFileId(\''+ fileId +'\');');
+              	}
+              	//子页面窗口调用父页面的refresh函数   页面回退 -1
+              	window.external.CallParentFunc("refresh();");
+              	//关闭POBrowser窗口
+              	window.external.close();
+        	}
+          	
+          	function SaveAs() {
+          		// window.external.CallParentFunc("refresh();");
+          		var fileId = "abc";
+              	//存储新文件的文件ID(已经不保存ID,因为同时间不可关闭弹窗和空白页 所以 通过异步实现关闭页面 )
+           		window.external.CallParentFunc('setLocalFileId(\''+ fileId +'\');');
+          		window.external.close();
+	        }
+
+            function PrintPreview() {
+                document.getElementById("PageOfficeCtrl1").PrintPreview();
+            }
+            function ShowPrintDlg() {
+                document.getElementById("PageOfficeCtrl1").ShowDialog(4); //打印对话框
+            }
+
+            function SetFullScreen() {
+                document.getElementById("PageOfficeCtrl1").FullScreen = !document.getElementById("PageOfficeCtrl1").FullScreen;
+            }
+	        function AddSeal() {
+				try{
+	        		  document.getElementById("PageOfficeCtrl1").ZoomSeal.AddSeal();
+				}catch (e){ };
+	       	}
+  		</script>
+        
+    </head>
+    <body>
+    	<div style="width:100%;height:800px;">
+	        <div style="width:100%;height:1000px;" th:utext="${pageOffice}"></div>
+    	</div>
+    </body>
+</html>

+ 53 - 0
winsea-haixin-platform-backend/src/main/resources/templates/office/office.html

@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
+      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
+    <head>
+        <title>Index</title>
+        <script type="text/javascript" src="../office/jquery.min.js"></script>
+     	<script type="text/javascript" src="../office/pageoffice.js" id="po_js_main"></script>
+		<script type="text/javascript">
+			// 获取访问文件URL
+			$(function(){
+				 var urlTemp = location.href;
+				 var urlStr = urlTemp.substr(0,urlTemp.indexOf("/office"));
+				 $.ajax({
+		             type: "GET",
+		             url: urlStr + "/office/getUrl",
+		             data: {urlSTR:urlStr},
+		             dataType: "json",
+		             success: function(result){
+		            	 		// localStorage.removeItem("pageOfficeFileId");
+		            	 		var urlT = result.data;
+		            	 		$('#clickBut').attr('href',urlT);
+		        				document.getElementById("clickBut").click();
+		                      }
+		         });
+			});
+			
+			// 保存文件ID 供弹出框调用 (实际为关闭页面操作  )
+			function setLocalFileId(fileIdTemp){
+				 var urlTemp = location.href;
+				 var urlStr = urlTemp.substr(0,urlTemp.indexOf("/office"));
+                 $.ajax({
+                     type: "GET",
+                     url: urlStr + "/office/setTempFileId?FileId="+fileIdTemp,
+                     data: {},
+                     dataType: "json",
+                     success: function(result){
+						window.close();
+                     }
+                 });
+			}
+			
+			// 回退方法     供弹出框调用
+			function refresh(){
+				window.close();
+	       	}
+	       	
+  		</script>
+		
+    </head>
+    <body>
+        <a id="clickBut" href=""></a>
+    </body>
+</html>

+ 55 - 0
winsea-haixin-plugin-base/pom.xml

@@ -0,0 +1,55 @@
+<?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>winsea-haixin</artifactId>
+        <groupId>com.yh.haixin</groupId>
+        <version>0.7.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>winsea-haixin-plugin-base</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.yh.saas</groupId>
+            <artifactId>winsea-saas-workflow-engine</artifactId>
+            <version>${winsea.saas.version}</version>
+            <classifier>standard</classifier>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.yh.saas</groupId>
+                    <artifactId>winsea-saas-common-support</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.yh.saas</groupId>
+                    <artifactId>winsea-saas-common-security</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.winsea.svc</groupId>
+                    <artifactId>winsea-base-service-spi</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.winsea.svc</groupId>
+                    <artifactId>winsea-notice-service-spi</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.60</version>
+        </dependency>
+        <!-- 阿里云 SMS -->
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-core</artifactId>
+            <version>4.1.1</version>
+        </dependency>
+
+    </dependencies>
+
+</project>

+ 73 - 0
winsea-haixin-plugin-base/src/main/java/com/alibaba/fastjson/support/spring/PropertyPreFilters.java

@@ -0,0 +1,73 @@
+package com.alibaba.fastjson.support.spring;
+
+import com.alibaba.fastjson.serializer.SimplePropertyPreFilter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * {@link SimplePropertyPreFilter}的一个简单封装
+ * @author  yanquanyu
+ * @author  liuming
+ */
+public class PropertyPreFilters {
+    private List<MySimplePropertyPreFilter> filters = new ArrayList<MySimplePropertyPreFilter>();
+
+
+    public MySimplePropertyPreFilter addFilter(){
+        MySimplePropertyPreFilter filter = new MySimplePropertyPreFilter();
+        filters.add(filter);
+        return filter;
+    }
+
+    public MySimplePropertyPreFilter addFilter(String... properties){
+        MySimplePropertyPreFilter filter = new MySimplePropertyPreFilter(properties);
+        filters.add(filter);
+        return filter;
+    }
+
+    public MySimplePropertyPreFilter addFilter(Class<?> clazz, String... properties){
+        MySimplePropertyPreFilter filter = new MySimplePropertyPreFilter(clazz,properties);
+        filters.add(filter);
+        return filter;
+    }
+
+    public List<MySimplePropertyPreFilter> getFilters() {
+        return filters;
+    }
+
+    public void setFilters(List<MySimplePropertyPreFilter> filters) {
+        this.filters = filters;
+    }
+
+    public MySimplePropertyPreFilter[] toFilters(){
+        return filters.toArray(new MySimplePropertyPreFilter[]{});
+    }
+
+    public class MySimplePropertyPreFilter extends SimplePropertyPreFilter {
+
+        public MySimplePropertyPreFilter(){}
+
+        public MySimplePropertyPreFilter(String... properties){
+            super(properties);
+        }
+
+        public MySimplePropertyPreFilter(Class<?> clazz, String... properties){
+            super(clazz,properties);
+        }
+
+        public MySimplePropertyPreFilter addExcludes(String... filters){
+            for (int i = 0; i < filters.length; i++) {
+                this.getExcludes().add(filters[i]);
+            }
+            return this;
+        }
+
+        public MySimplePropertyPreFilter addIncludes(String... filters){
+            for (int i = 0; i < filters.length; i++) {
+                this.getIncludes().add(filters[i]);
+            }
+            return this;
+        }
+    }
+}

+ 24 - 0
winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/annotation/EnableService.java

@@ -0,0 +1,24 @@
+package com.winsea.svc.common.annotation;
+
+import com.winsea.svc.common.config.MybatisPlusConfig;
+import com.winsea.svc.common.config.WebConfig;
+import com.winsea.svc.common.international.InternationalConfig;
+import com.winsea.svc.common.mq.MessageQueueConfig;
+import org.springframework.context.annotation.Import;
+
+import java.lang.annotation.*;
+
+/**
+ * 启用服务
+ *
+ * @author SunTianjun
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Import({MybatisPlusConfig.class,
+        WebConfig.class,
+        MessageQueueConfig.class,
+        InternationalConfig.class})
+public @interface EnableService {
+}

+ 116 - 0
winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/config/CommonConfig.java

@@ -0,0 +1,116 @@
+package com.winsea.svc.common.config;
+
+import com.yh.saas.common.support.util.StringUtils;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.env.EnvironmentPostProcessor;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.MapPropertySource;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 所有服务的共通配置
+ *
+ * @author SunTianjun
+ */
+public class CommonConfig implements EnvironmentPostProcessor {
+
+    @Override
+    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
+        String active = environment.getProperty("spring.profiles.active");
+        if (StringUtils.isEmpty(active)) {
+            return;
+        }
+
+        Map<String, Object> defaultConfig = new HashMap<>();
+        defaultConfig.putAll(getJacksonConfig());
+        defaultConfig.putAll(getUnnecessaryConfig());
+        defaultConfig.putAll(getDefaultWhitelistConfig());
+        defaultConfig.putAll(getDefaultPushConfig());
+        defaultConfig.putAll(getDefaultOssConfig(active));
+        defaultConfig.putAll(getDefaultMybatisPlusConfig());
+
+        environment.getPropertySources().addLast(new MapPropertySource("defaultProperties", defaultConfig));
+    }
+
+    /**
+     * 获取Jackson配置
+     */
+    private Map<String, Object> getJacksonConfig() {
+        Map<String, Object> jacksonConfig = new HashMap<>();
+        jacksonConfig.put("spring.jackson.date-format", "yyyy-MM-dd HH:mm:ss");
+        jacksonConfig.put("spring.jackson.time-zone", "GMT+8");
+        return jacksonConfig;
+    }
+
+    /**
+     * 获取不是每个服务都必要的配置
+     */
+    private Map<String, Object> getUnnecessaryConfig() {
+        Map<String, Object> unnecessaryConfig = new HashMap<>();
+        unnecessaryConfig.put("front-origin", "");
+        unnecessaryConfig.put("file-root-path", "");
+        unnecessaryConfig.put("system.temp-file-path", "");
+        unnecessaryConfig.put("po.password", "");
+        unnecessaryConfig.put("po.syspath", "");
+        return unnecessaryConfig;
+    }
+
+    /**
+     * 获取默认白名单配置
+     */
+    private Map<String, Object> getDefaultWhitelistConfig() {
+        Map<String, Object> whitelistConfig = new HashMap<>();
+        whitelistConfig.put("auth.anon-urls[0]", "/auth/api/login");
+        whitelistConfig.put("auth.anon-urls[1]", "/auth/api/loginEnhanced");
+        whitelistConfig.put("auth.anon-urls[2]", "/auth/api/loginQuickly");
+        whitelistConfig.put("auth.anon-urls[3]", "/auth/api/checkPassword");
+        whitelistConfig.put("auth.anon-urls[4]", "/auth/api/retrievePassword");
+        whitelistConfig.put("auth.anon-urls[5]", "/veriCode/api/send");
+        whitelistConfig.put("auth.anon-urls[6]", "/veriCode/api/check");
+        whitelistConfig.put("auth.anon-urls[7]", "/company/query/companyInfoByDomainName");
+        whitelistConfig.put("auth.anon-urls[8]", "/webservice/**/*");
+        whitelistConfig.put("auth.anon-urls[9]", "/workflowSync/api/startFlow");
+        whitelistConfig.put("auth.anon-urls[10]", "/office/*");
+        whitelistConfig.put("auth.anon-urls[11]", "/auth/api/phoneLogin");
+        whitelistConfig.put("auth.anon-urls[12]", "/test/test/test");
+        return whitelistConfig;
+    }
+
+    /**
+     * 获取默认推送配置
+     */
+    private Map<String, Object> getDefaultPushConfig() {
+        Map<String, Object> pushConfig = new HashMap<>();
+        pushConfig.put("jpush.appkey", "0f39aadb2d14d6a34c8a0d14");
+        pushConfig.put("jpush.live.time", "10000");
+        pushConfig.put("jpush.masterSecret", "2d5c37c625445ee37080ecbb");
+        return pushConfig;
+    }
+
+    /**
+     * 获取默认OSS配置
+     */
+    private Map<String, Object> getDefaultOssConfig(String active) {
+        Map<String, Object> ossConfig = new HashMap<>();
+        ossConfig.put("oss.access.key.id", "LTAI4G9c14PgKvM23WZ9zrpc");
+        ossConfig.put("oss.access.key.secret", "FpClTp4OVrRRtHEfi3lBOWUoLxKieW");
+        ossConfig.put("oss.endpoint.default", "oss-cn-beijing.aliyuncs.com");
+        ossConfig.put("oss.endpoint.internal", "https://taohaoliang.oss-cn-beijing.aliyuncs.com/");
+        ossConfig.put("oss.bucket.name", "prod".equals(active) ? "eliangeyun" : "eliangeyun-test");
+        return ossConfig;
+    }
+
+    /**
+     * 获取默认MybatisPlus配置
+     */
+    private Map<String, Object> getDefaultMybatisPlusConfig() {
+        Map<String, Object> mybatisPlusConfig = new HashMap<>();
+        mybatisPlusConfig.put("mybatis-plus.mapper-locations", "classpath*:/mapper/*Mapper.xml");
+        mybatisPlusConfig.put("mybatis-plus.global-config.logic-delete-value", "1");
+        mybatisPlusConfig.put("mybatis-plus.global-config.logic-not-delete-value", "0");
+        mybatisPlusConfig.put("mybatis-plus.configuration.map-underscore-to-camel-case", "true");
+        return mybatisPlusConfig;
+    }
+}

+ 172 - 0
winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/config/MybatisPlusConfig.java

@@ -0,0 +1,172 @@
+package com.winsea.svc.common.config;
+
+import com.alipay.sofa.rpc.context.RpcInvokeContext;
+import com.baomidou.mybatisplus.mapper.ISqlInjector;
+import com.baomidou.mybatisplus.mapper.MetaObjectHandler;
+import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
+import com.winsea.svc.common.international.InternationalResourceProviderAdapter;
+import com.yh.saas.common.support.mpext.CustomSqlInjector;
+import com.yh.saas.common.support.mpext.LogicDeleteFilledAspect;
+import com.yh.saas.common.support.util.ContextWrapper;
+import org.apache.ibatis.reflection.MetaObject;
+import org.apache.shiro.SecurityUtils;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.Date;
+
+/**
+ * Mybatis plus配置
+ *
+ * @author SunTianjun
+ */
+@Configuration
+public class MybatisPlusConfig {
+
+
+    /**
+     * 分页插件
+     */
+    @ConditionalOnMissingBean(PaginationInterceptor.class)
+    @Bean
+    public PaginationInterceptor paginationInterceptor() {
+        return new PaginationInterceptor();
+    }
+
+    /**
+     * 自定义SQL注入器<br/>
+     * 支持逻辑删除与共通字段递增
+     */
+    @ConditionalOnMissingBean(ISqlInjector.class)
+    @Bean
+    public ISqlInjector sqlInjector() {
+        return new CustomSqlInjector();
+    }
+
+    /**
+     * 修改逻辑删除不能填充问题
+     */
+    @ConditionalOnMissingBean(LogicDeleteFilledAspect.class)
+    @Bean
+    public LogicDeleteFilledAspect logicDeleteFilledAspect() {
+        return new LogicDeleteFilledAspect();
+    }
+
+    /**
+     * 字段自动填充
+     */
+    @ConditionalOnMissingBean(MetaObjectHandler.class)
+    @Bean
+    public MetaObjectHandler metaObjectHandler() {
+
+        final String SOFA_USER_ID_VAR_NAME = "userId";
+
+        final String SOFA_USER_INFO_VAR_NAME = "userInfo";
+
+        final String DEFAULT_USER = "sysadmin";
+
+        final String CREATE_USER_ID_FIELD = "createUserId";
+
+        final String UPDATE_USER_ID_FIELD = "updateUserId";
+
+        final String CREATE_DATE_FIELD = "createDate";
+
+        final String UPDATE_DATE_FIELD = "updateDate";
+
+        final String UPDATE_FLAG_FIELD = "updateFlag";
+
+        final String DELETE_FLAG_FIELD = "deleteFlag";
+
+        return new MetaObjectHandler() {
+
+            @Override
+            public void insertFill(MetaObject metaObject) {
+                Date currentDate = new Date();
+                String currentUserId = null;
+                try{
+                    currentUserId = (String) SecurityUtils.getSubject().getPrincipal();
+                } catch (Exception e){
+                    currentUserId = RpcInvokeContext.getContext().getRequestBaggage("userId");
+                }
+                this.setFieldValByName(CREATE_DATE_FIELD, currentDate, metaObject);
+                this.setFieldValByName(UPDATE_DATE_FIELD, currentDate, metaObject);
+                this.setFieldValByName(UPDATE_FLAG_FIELD, "0", metaObject);
+                this.setFieldValByName(DELETE_FLAG_FIELD, "0", metaObject);
+
+                if (null != currentUserId) {
+                    this.setFieldValByName(CREATE_USER_ID_FIELD, currentUserId, metaObject);
+                    this.setFieldValByName(UPDATE_USER_ID_FIELD, currentUserId, metaObject);
+                } else {
+                    if (null == this.getFieldValByName(CREATE_USER_ID_FIELD, metaObject)) {
+                        this.setFieldValByName(CREATE_USER_ID_FIELD, DEFAULT_USER, metaObject);
+                    }
+
+                    if (null == this.getFieldValByName(UPDATE_USER_ID_FIELD, metaObject)) {
+                        this.setFieldValByName(UPDATE_USER_ID_FIELD, DEFAULT_USER, metaObject);
+                    }
+                }
+
+                this.setInternationResourceId(metaObject, false);
+            }
+
+            @Override
+            public void updateFill(MetaObject metaObject) {
+                String currentUserId = null;
+                try{
+                    currentUserId = (String) SecurityUtils.getSubject().getPrincipal();
+                } catch (Exception e){
+                    currentUserId = RpcInvokeContext.getContext().getRequestBaggage("userId");
+                }
+                if (null != currentUserId) {
+                    this.setFieldValByName(UPDATE_USER_ID_FIELD, currentUserId, metaObject);
+                } else if (null == this.getFieldValByName(UPDATE_USER_ID_FIELD, metaObject)) {
+                    this.setFieldValByName(UPDATE_USER_ID_FIELD, DEFAULT_USER, metaObject);
+                }
+                this.setFieldValByName(UPDATE_DATE_FIELD, new Date(), metaObject);
+                this.setFieldValByName(UPDATE_FLAG_FIELD, "1", metaObject);
+
+                this.setInternationResourceId(metaObject, true);
+            }
+
+            /**
+             * 设置国际化资源ID
+             */
+            private void setInternationResourceId(MetaObject metaObject, boolean updated) {
+                InternationalResourceProviderAdapter iResourceProvider = null;
+                try {
+                    iResourceProvider = ContextWrapper.getApplicationContext()
+                            .getBean(InternationalResourceProviderAdapter.class);
+                } catch (Exception ex) {
+                    // ignore
+                }
+
+                if (null != iResourceProvider) {
+                    iResourceProvider.setInternationalText(metaObject, updated);
+                }
+            }
+
+//            /**
+//             * 获取当前用户ID
+//             */
+//            private String getCurrentUserId() {
+//                try {
+//                    if (null != RpcInvokeContext.getContext().getRequestBaggage(SOFA_USER_ID_VAR_NAME)) {
+//                        return RpcInvokeContext.getContext().getRequestBaggage(SOFA_USER_ID_VAR_NAME);
+//                    }
+//                } catch (Exception ex) {
+//                    // ignore
+//                }
+//
+//                try {
+//                    return (String) SecurityUtils.getSubject().getPrincipal();
+//                } catch (Exception e) {
+//                    return null;
+//                }
+//            }
+        };
+    }
+
+
+
+}

+ 64 - 0
winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/config/WebConfig.java

@@ -0,0 +1,64 @@
+package com.winsea.svc.common.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * Web配置
+ * 
+ * @author SunTianjun
+ */
+@Configuration
+public class WebConfig {
+
+	@Value("${allowed-origins:*}")
+	private String allowedOrigins;
+
+	@Value("${allowed-headers:Access-Control-Allow-Headers,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Authorization,Access-Control-Request-Headers}")
+	private String allowedHeaders;
+
+	/**
+	 * 测试用,跨域访问
+	 */
+	@Bean
+	public Filter corsFilter() {
+		return new Filter() {
+
+			@Override
+			public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+					throws IOException, ServletException {
+				HttpServletRequest req = ((HttpServletRequest) request);
+				HttpServletResponse res = (HttpServletResponse) response;
+				if ("*".equals(allowedOrigins) || allowedOrigins.contains(req.getHeader("Origin"))) {
+					res.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin"));
+//					res.setHeader("Access-Control-Allow-Origin", allowedOrigins);
+				}
+
+				res.setHeader("Access-Control-Allow-Credentials", "true");
+				res.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS");
+				res.setHeader("Access-Control-Allow-Headers", allowedHeaders);
+				if (req.getMethod().equals("OPTIONS")) {
+					response.getWriter().println("ok");
+					return;
+				}
+				chain.doFilter(request, response);
+			}
+
+			@Override
+			public void init(FilterConfig filterConfig) throws ServletException {
+				// ignore
+			}
+
+			@Override
+			public void destroy() {
+				// ignore
+			}
+		};
+	}
+}

+ 24 - 0
winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/international/International.java

@@ -0,0 +1,24 @@
+package com.winsea.svc.common.international;
+
+import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 字段国际化
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.FIELD, ElementType.METHOD })
+@JacksonAnnotationsInside
+@JsonSerialize(using = InternationalSerializer.class)
+public @interface International {
+
+	/**
+	 * 所属类型
+	 */
+	String type() default "";
+}

+ 25 - 0
winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/international/InternationalConfig.java

@@ -0,0 +1,25 @@
+package com.winsea.svc.common.international;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Lazy;
+
+/**
+ * 国际化配置
+ * 
+ * @author SunTianjun
+ */
+@Configuration
+public class InternationalConfig {
+
+	@Bean
+	public InternationalProperties internationalProperties() {
+		return new InternationalProperties();
+	}
+
+	@Bean
+	@Lazy
+	public InternationalResourceProviderAdapter internationalResourceProviderAdapter() {
+		return new InternationalResourceProviderAdapter();
+	}
+}

+ 116 - 0
winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/international/InternationalProperties.java

@@ -0,0 +1,116 @@
+package com.winsea.svc.common.international;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * 国际化配置属性
+ *
+ * @author SunTianjun
+ */
+@ConfigurationProperties(prefix = "sys.international")
+public class InternationalProperties {
+
+	/**
+	 * 是否启用持久化,默认为False
+	 */
+	private boolean persistenceEnabled = false;
+
+	/**
+	 * 是否启用序列化,默认为False
+	 */
+	private boolean serializationEnabled = false;
+
+	/**
+	 * 请求语言参数位置(HEADER/PARAM),默认为HEADER
+	 */
+	private RequestLangParamPosition paramPosition = RequestLangParamPosition.HEADER;
+
+	/**
+	 * 请求语言参数名称,默认为lang
+	 */
+	private String paramName = "lang";
+	
+	/**
+	 * 默认语言,默认为zh-cn
+	 */
+	private String defaultLang = "zh-cn";
+
+	public boolean isPersistenceEnabled() {
+		return persistenceEnabled;
+	}
+
+	public void setPersistenceEnabled(boolean persistenceEnabled) {
+		this.persistenceEnabled = persistenceEnabled;
+	}
+
+	public boolean isSerializationEnabled() {
+		return serializationEnabled;
+	}
+
+	public void setSerializationEnabled(boolean serializationEnabled) {
+		this.serializationEnabled = serializationEnabled;
+	}
+
+	public RequestLangParamPosition getParamPosition() {
+		return paramPosition;
+	}
+
+	public void setParamPosition(RequestLangParamPosition paramPosition) {
+		this.paramPosition = paramPosition;
+	}
+
+	public String getParamName() {
+		return paramName;
+	}
+
+	public void setParamName(String paramName) {
+		this.paramName = paramName;
+	}
+
+	public String getDefaultLang() {
+		return defaultLang;
+	}
+
+	public void setDefaultLang(String defaultLang) {
+		this.defaultLang = defaultLang;
+	}
+
+	/**
+	 * 获取请求语言
+	 * 
+	 * @return 请求语言
+	 */
+	public String getLang() {
+		HttpServletRequest request = null;
+		try {
+			request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+		} catch (Exception ex) {
+			// ignore
+		}
+
+		if (null == request) {
+			return null;
+		}
+
+		String lang;
+		if (paramPosition == RequestLangParamPosition.HEADER) {
+			lang = request.getHeader(paramName);
+		} else {
+			lang = request.getParameter(paramName);
+		}
+		return !StringUtils.isBlank(lang) ? lang : defaultLang;
+	}
+
+	/**
+	 * 请求语言参数位置
+	 */
+	public enum RequestLangParamPosition {
+
+		HEADER, PARAM
+	}
+}

+ 38 - 0
winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/international/InternationalResourceProvider.java

@@ -0,0 +1,38 @@
+package com.winsea.svc.common.international;
+
+/**
+ * 国际资源提供者
+ * 
+ * @author SunTianjun
+ */
+public interface InternationalResourceProvider {
+
+	/**
+	 * 获取文本
+	 * 
+	 * @param resourceId 资源ID
+	 * @param lang       语言
+	 * @return 国际化文本
+	 */
+	String getText(String resourceId, String lang);
+
+	/**
+	 * 创建资源
+	 * 
+	 * @param text 文本
+	 * @param type 类型
+	 * @param lang 语言
+	 * @return 资源ID
+	 */
+	default String create(String text, String type, String lang) {
+		return text;
+	}
+
+	/**
+	 * 标识待删除资源
+	 * 
+	 * @param resourceId 资源ID
+	 */
+	default void markDeletion(String resourceId) {
+	}
+}

+ 282 - 0
winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/international/InternationalResourceProviderAdapter.java

@@ -0,0 +1,282 @@
+package com.winsea.svc.common.international;
+
+import com.alipay.sofa.runtime.api.annotation.SofaReference;
+import com.baomidou.mybatisplus.annotations.TableField;
+import com.baomidou.mybatisplus.annotations.TableId;
+import com.baomidou.mybatisplus.enums.FieldFill;
+import com.baomidou.mybatisplus.mapper.BaseMapper;
+import com.baomidou.mybatisplus.mapper.Wrapper;
+import com.baomidou.mybatisplus.toolkit.StringUtils;
+import com.google.common.cache.Cache;
+import com.google.common.collect.Sets;
+import com.yh.saas.common.support.util.ContextWrapper;
+import org.apache.commons.beanutils.BeanUtils;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.ibatis.reflection.MetaObject;
+import org.apache.ibatis.reflection.SystemMetaObject;
+import org.apache.ibatis.session.RowBounds;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.ParameterizedType;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+
+/**
+ * 国际化资源提供者(包装类)
+ * 
+ * @author SunTianjun
+ */
+public class InternationalResourceProviderAdapter {
+
+	private static final String META_OBJ_PREFIX = "et";
+
+	private Map<String, BaseMapper<?>> entityClassBaseMapperMap = new ConcurrentHashMap<>();
+
+	@Autowired
+	@Qualifier("localMinuteCache")
+	private Cache<String, Object> cache;
+
+	@Autowired
+	private InternationalProperties iProperties;
+
+	@SofaReference
+	private InternationalResourceProvider iResourceProvider;
+
+	/**
+	 * 获取文本
+	 * 
+	 * @param resourceId 资源ID
+	 * @param lang       语言
+	 * @return 国际化文本
+	 */
+	public String getText(String resourceId, String lang) {
+		if (!iProperties.isSerializationEnabled() || StringUtils.isEmpty(lang)) {
+			return resourceId;
+		}
+
+		Object text = cache.getIfPresent(resourceId);
+		if (null == text) {
+			text = iResourceProvider.getText(resourceId, lang);
+			if (null != text && text.toString().length() != 0) {
+				cache.put(resourceId, text);
+			}
+		}
+		return null != text ? text.toString() : null;
+	}
+
+	/**
+	 * 设置国际化文本
+	 * 
+	 * @param metaObject MetaObject
+	 * @param updated    是否是更新操作
+	 */
+	public void setInternationalText(MetaObject metaObject, boolean updated) {
+		if (!iProperties.isPersistenceEnabled() || StringUtils.isEmpty(iProperties.getLang())) {
+			return;
+		}
+
+		findFillFields(metaObject).forEach(field -> {
+
+			// 如果是修改则删除上一次的资源
+			Object resourceId = null;
+			if (updated) {
+				resourceId = removeLastResource(metaObject, field);
+			}
+
+			if (null == resourceId) {
+				resourceId = internationalize(field, getFieldValByName(field.getName(), metaObject));
+			}
+
+			setFieldValByName(field.getName(), resourceId, metaObject);
+		});
+	}
+
+	/**
+	 * 删除上一次资源
+	 * 
+	 * @param metaObject         MetaObject
+	 * @param internationalField 国际化字段
+	 * @return 如果未删除则返回保留的资源ID
+	 */
+	@SuppressWarnings({ "unchecked", "rawtypes" })
+	private String removeLastResource(MetaObject metaObject, Field internationalField) {
+		Object itext = getFieldValByName(internationalField.getName(), metaObject);
+		// 待国际化字段内容为空直接返回
+		if (null == itext) {
+			return null;
+		}
+
+		Class<?> tableClass = getOriginalObjectClass(metaObject);
+		BaseMapper baseMapper = getEntityClassBaseMapperMap().get(tableClass.getName());
+
+		Object originalObj = null;
+		Map<?, ?> map = (Map<?, ?>) metaObject.getOriginalObject();
+
+		// 如果是条件更新,则只获取匹配的第一条数据进行删除
+		if (map.containsKey("ew")) {
+			List objs = baseMapper.selectPage(new RowBounds(0, 1), (Wrapper) map.get("ew"));
+
+			// 查询不到则直接返回
+			if (CollectionUtils.isEmpty(objs)) {
+				return null;
+			}
+
+			originalObj = objs.get(0);
+		}
+		// 根据ID进行更新
+		else {
+			Set<Field> fields = getAllFields(tableClass).stream()
+					.filter(field -> null != field.getAnnotation(TableId.class)).collect(Collectors.toSet());
+			if (fields.isEmpty()) {
+				return null;
+			}
+
+			// 根据ID查询原始对象
+			String idValue = getFieldValByName(fields.iterator().next().getName(), metaObject).toString();
+			originalObj = baseMapper.selectById(idValue);
+		}
+
+		String resourceId;
+		try {
+			resourceId = BeanUtils.getProperty(originalObj, internationalField.getName());
+		} catch (Exception e) {
+			return null;
+		}
+
+		if (null == resourceId) {
+			return null;
+		}
+
+		// 如果当前文本与前一次文本不同则删除
+		if (!itext.toString().equals(getText(resourceId, iProperties.getLang()))) {
+			iResourceProvider.markDeletion(resourceId);
+			return null;
+		}
+		// 否则返回保留的资源ID
+		else {
+			return resourceId;
+		}
+	}
+
+	/**
+	 * 查找填充字段
+	 */
+	private Set<Field> findFillFields(MetaObject metaObject) {
+		return getAllFields(getOriginalObjectClass(metaObject)).stream()
+				.filter(field -> null != field.getAnnotation(International.class)
+						&& null != field.getAnnotation(TableField.class)
+						&& field.getAnnotation(TableField.class).fill() != FieldFill.DEFAULT)
+				.collect(Collectors.toSet());
+	}
+
+	/**
+	 * 国际化
+	 * 
+	 * @param fieldName  字段名
+	 * @param fieldValue 字段值
+	 * @return 国际化资源ID
+	 */
+	private Object internationalize(Field field, Object fieldValue) {
+		if (null == fieldValue || fieldValue.toString().equals(StringUtils.EMPTY)) {
+			return fieldValue;
+		}
+
+		// 国际化资源类型
+		String type = field.getAnnotation(International.class).type();
+		return iResourceProvider.create(fieldValue.toString(), type, iProperties.getLang());
+	}
+
+	/**
+	 * 设置填充对象值
+	 * 
+	 * @param fieldName  字段名
+	 * @param fieldVal   字段值
+	 * @param metaObject 待填充对象
+	 */
+	private void setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject) {
+		if (metaObject.hasSetter(fieldName) && metaObject.hasGetter(fieldName)) {
+			metaObject.setValue(fieldName, fieldVal);
+		} else if (metaObject.hasGetter(META_OBJ_PREFIX)) {
+			Object et = metaObject.getValue(META_OBJ_PREFIX);
+			if (et != null) {
+				MetaObject etMeta = SystemMetaObject.forObject(et);
+				if (etMeta.hasSetter(fieldName)) {
+					etMeta.setValue(fieldName, fieldVal);
+				}
+			}
+		}
+	}
+
+	/**
+	 * 从待填充对象获取值
+	 * 
+	 * @param fieldName  字段名
+	 * @param metaObject 待填充对象
+	 */
+	private Object getFieldValByName(String fieldName, MetaObject metaObject) {
+		if (metaObject.hasGetter(fieldName)) {
+			return metaObject.getValue(fieldName);
+		} else if (metaObject.hasGetter(META_OBJ_PREFIX + "." + fieldName)) {
+			return metaObject.getValue(META_OBJ_PREFIX + "." + fieldName);
+		}
+		return StringUtils.EMPTY;
+	}
+
+	/**
+	 * 获取所有父类
+	 */
+	private Set<Class<?>> getAllSuperTypes(final Class<?> type) {
+		Set<Class<?>> result = Sets.newLinkedHashSet();
+		if (type != null && !type.equals(Object.class)) {
+			result.add(type);
+			result.addAll(getAllSuperTypes(type.getSuperclass()));
+			for (Class<?> ifc : type.getInterfaces())
+				result.addAll(getAllSuperTypes(ifc));
+		}
+		return result;
+	}
+
+	/**
+	 * 获取所有声明字段,包含父类声明的
+	 */
+	private Set<Field> getAllFields(final Class<?> type) {
+		Set<Field> result = Sets.newHashSet();
+		for (Class<?> t : getAllSuperTypes(type))
+			result.addAll(Sets.newHashSet(t.getDeclaredFields()));
+		return result;
+	}
+
+	/**
+	 * 获取原始对象类
+	 */
+	private Class<?> getOriginalObjectClass(MetaObject metaObject) {
+		if (metaObject.getOriginalObject() instanceof Map) {
+			return ((Map<?, ?>) metaObject.getOriginalObject()).get(META_OBJ_PREFIX).getClass();
+		} else {
+			return metaObject.getOriginalObject().getClass();
+		}
+	}
+
+	/**
+	 * 获取实体类和对应Mapper映射
+	 */
+	private Map<String, BaseMapper<?>> getEntityClassBaseMapperMap() {
+		if (entityClassBaseMapperMap.isEmpty()) {
+			ContextWrapper.getApplicationContext().getBeansOfType(BaseMapper.class).values().forEach(baseMapper -> {
+				try {
+					Class<?> entityClass = (Class<?>) ((ParameterizedType) (((Class<?>) baseMapper.getClass()
+							.getGenericInterfaces()[0]).getGenericInterfaces()[0])).getActualTypeArguments()[0];
+					entityClassBaseMapperMap.put(entityClass.getName(), baseMapper);
+				} catch (ClassCastException ex) {
+					// ignore
+				}
+			});
+		}
+		return entityClassBaseMapperMap;
+	}
+}

+ 52 - 0
winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/international/InternationalSerializer.java

@@ -0,0 +1,52 @@
+package com.winsea.svc.common.international;
+
+import com.baomidou.mybatisplus.toolkit.StringUtils;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.yh.saas.common.support.util.ContextWrapper;
+
+import java.io.IOException;
+
+/**
+ * 国际化序列化器
+ * 
+ * @author SunTianjun
+ */
+public class InternationalSerializer extends JsonSerializer<String> {
+
+	@Override
+	public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
+		if (null == value) {
+			gen.writeNull();
+			return;
+		}
+
+		InternationalResourceProviderAdapter iResourceProvider = getInternationalResourceProvider();
+		if (null == iResourceProvider) {
+			gen.writeString(value);
+			return;
+		}
+
+		// 获取客户语言环境
+		String lang = ContextWrapper.getApplicationContext().getBean(InternationalProperties.class).getLang();
+		if (!StringUtils.isEmpty(lang)) {
+			String itext = iResourceProvider.getText(value, lang);
+			if (StringUtils.isEmpty(itext)) {
+				gen.writeString(value);
+			} else {
+				gen.writeString(itext);
+			}
+		} else {
+			gen.writeString(value);
+		}
+	}
+
+	private InternationalResourceProviderAdapter getInternationalResourceProvider() {
+		try {
+			return ContextWrapper.getApplicationContext().getBean(InternationalResourceProviderAdapter.class);
+		} catch (Exception ex) {
+			return null;
+		}
+	}
+}

+ 14 - 0
winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/mq/MessageListener.java

@@ -0,0 +1,14 @@
+package com.winsea.svc.common.mq;
+
+/**
+ * 消息监听器
+ * 
+ * @author SunTianjun
+ *
+ * @param <T>
+ */
+@FunctionalInterface
+public interface MessageListener<T> {
+
+	void onMessage(T body, String channel);
+}

+ 84 - 0
winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/mq/MessageQueueClient.java

@@ -0,0 +1,84 @@
+package com.winsea.svc.common.mq;
+
+import com.alibaba.fastjson.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.listener.PatternTopic;
+import org.springframework.data.redis.listener.RedisMessageListenerContainer;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 消息队列客户端
+ * 
+ * @author SunTianjun
+ */
+public class MessageQueueClient {
+
+	@Autowired
+	private RedisTemplate<String, String> redisTemplate;
+
+	@Autowired
+	private RedisMessageListenerContainer messageListenerContainer;
+
+	/**
+	 * 消息推送
+	 */
+	public <T> void push(String channel, T body) {
+		redisTemplate.opsForList().leftPush(channel, serialize(body));
+	}
+
+	/**
+	 * 消息拉取
+	 * 
+	 * @param channel 频道
+	 * @param timeout 拉取超时时间
+	 * @param unit    时间单位
+	 * @param clazz   反序列化类型
+	 * @return 拉取的消息内容
+	 */
+	public <T> T pop(String channel, long timeout, TimeUnit unit, Class<T> clazz) {
+		return deserialize(redisTemplate.opsForList().rightPop(channel, timeout, unit), clazz);
+	}
+
+	/**
+	 * 消息发布
+	 */
+	public <T> void publish(String channel, T body) {
+		redisTemplate.convertAndSend(channel, serialize(body));
+	}
+
+	/**
+	 * 消息订阅
+	 * 
+	 * @param pattern         订阅的频道(正则匹配)
+	 * @param messageListener 消息监听器
+	 * @param bodyClass       消息体类型
+	 */
+	public <T> void subscribe(String pattern, MessageListener<T> messageListener, Class<T> bodyClass) {
+		messageListenerContainer.addMessageListener((message, p) -> messageListener
+				.onMessage(deserialize(message.getBody(), bodyClass), new String(message.getChannel())),
+				new PatternTopic(pattern));
+	}
+
+	/**
+	 * 序列化
+	 */
+	private <T> String serialize(T body) {
+		return JSONObject.toJSONString(body);
+	}
+
+	/**
+	 * 反序列化
+	 */
+	private <T> T deserialize(String body, Class<T> clazz) {
+		return JSONObject.parseObject(body, clazz);
+	}
+
+	/**
+	 * 反序列化
+	 */
+	private <T> T deserialize(byte[] body, Class<T> clazz) {
+		return JSONObject.parseObject(redisTemplate.getValueSerializer().deserialize(body).toString(), clazz);
+	}
+}

+ 29 - 0
winsea-haixin-plugin-base/src/main/java/com/winsea/svc/common/mq/MessageQueueConfig.java

@@ -0,0 +1,29 @@
+package com.winsea.svc.common.mq;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.listener.RedisMessageListenerContainer;
+
+/**
+ * 消息队列配置
+ * 
+ * @author SunTianjun
+ */
+@ConditionalOnProperty(prefix = "sys", name = "client-flag", havingValue = "B")
+@Configuration
+public class MessageQueueConfig {
+
+	@Bean
+	public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory redisConnectionFactory) {
+		RedisMessageListenerContainer container = new RedisMessageListenerContainer();
+		container.setConnectionFactory(redisConnectionFactory);
+		return container;
+	}
+
+	@Bean
+	public MessageQueueClient messageQueueClient() {
+		return new MessageQueueClient();
+	}
+}

+ 93 - 0
winsea-haixin-plugin-base/src/main/java/com/winsea/svc/crew/constant/CrewSeafarerStatusEnum.java

@@ -0,0 +1,93 @@
+package com.winsea.svc.crew.constant;
+
+/**
+ * 船员状态枚举
+ * 
+ * @author XinGuang
+ *
+ */
+public enum CrewSeafarerStatusEnum {
+
+	/**
+	 * 已登记,Registered
+	 */
+	REGISTERED,
+
+//	/**
+//	 * 待面试,To be interview
+//	 */
+//	TOTERVIEW,
+//	/**
+//	 * 面试中,In the interview
+//	 */
+//	INTERVIEW,
+//
+//	/**
+//	 * 已取消面试
+//	 */
+//	CANELINTERVIEW,
+//
+//	/**
+//	 * 面试通过
+//	 */
+//	ADOPTINTERVIEW,
+//
+//	/**
+//	 * 面试不通过
+//	 */
+//	FAILEDINTERVIEW,
+//	/**
+//	 * 面试结束
+//	 */
+//	ENDOFINTERVIEW,
+//
+//	/**
+//	 * 培训中
+//	 */
+//	TRAINING,
+//
+//	/**
+//	 * 已取消培训
+//	 */
+//	CANELTRAIN,
+//
+//	/**
+//	 * 培训合格
+//	 */
+//	QUALIFIEDTRAIN,
+//
+//	/**
+//	 * 培训结束
+//	 */
+//	ENDTRAIN,
+//
+//	/**
+//	 * 培训不合格
+//	 */
+//	FAILEDTRAIN,
+//
+//	/**
+//	 * 待上船,Wait for boarding
+//	 */
+//	STAYONBOARD,
+
+	/**
+	 * 在船,On board
+	 */
+	ONBOARD,
+
+	/**
+	 * 已下船
+	 */
+	DOWNBOARD,
+
+	/**
+	 * 黑名单
+	 */
+	BLACKLIST,
+
+//	/**
+//	 * 离职
+//	 */
+//	QUIT;
+}

+ 767 - 0
winsea-haixin-plugin-base/src/main/java/com/winsea/svc/crew/entity/CrewSeafarerInfo.java

@@ -0,0 +1,767 @@
+package com.winsea.svc.crew.entity;
+
+import com.baomidou.mybatisplus.annotations.TableField;
+import com.baomidou.mybatisplus.annotations.TableId;
+import com.baomidou.mybatisplus.enums.IdType;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.winsea.svc.crew.constant.CrewSeafarerStatusEnum;
+import com.yh.saas.common.support.entity.BaseModel;
+import com.yh.saas.common.support.util.query.SearchField;
+import com.yh.saas.common.support.util.query.SearchMode;
+import com.yh.saas.common.support.util.query.SelectColunm;
+import com.yh.saas.common.support.util.uniqueness.Unique;
+import lombok.*;
+import lombok.experimental.Accessors;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import javax.validation.constraints.NotBlank;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * <p>
+ * 船员表
+ * </p>
+ *
+ * @author XinGuang
+ * @since 2019-06-27
+ */
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Accessors(chain = true)
+public class CrewSeafarerInfo extends BaseModel<CrewSeafarerInfo> {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 船员ID
+     */
+    @SelectColunm
+    @TableId(type = IdType.INPUT)
+    private String seafarerId;
+
+    /**
+     * 公司ID
+     */
+    @NotBlank
+    @SearchField(mode = SearchMode.EQ)
+    @SelectColunm
+    private String compId;
+    /**
+     * 船员姓名
+     */
+    @SearchField(mode = SearchMode.LIKE)
+    @SelectColunm
+    private String seafarerName;
+
+    /**
+     * 外派公司id
+     */
+    @SelectColunm
+    private String ownedOutCompId;
+
+    /**
+     * 外派公司名称
+     */
+    @SelectColunm
+    private String ownedOutCompName;
+
+    /**
+     * 船舶id(在船的时候有,不在船的时候为空)
+     */
+    @SelectColunm(typeValue = "B")
+    private String vesselId;
+
+    /**
+     * 船舶名称(在船的时候有,不在船的时候为空)
+     */
+    @SelectColunm(typeValue = "B")
+    private String vesselName;
+
+    /**
+     * 在船职务ID
+     */
+    @SelectColunm(typeValue = "B")
+    private String onDutyId;
+
+    /**
+     * 在船职务
+     */
+    @SelectColunm(typeValue = "B")
+    private String onDutyName;
+    /**
+     * 出生日期
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @SelectColunm(typeValue = "A")
+    private Date birthday;
+    /**
+     * 入司时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @SelectColunm(typeValue = "A")
+    private Date enterCompanyDate;
+    /**
+     * 证书职务ID
+     */
+    @SelectColunm(typeValue = "A")
+    private String crtDutyId;
+    /**
+     * 证书职务名称
+     */
+    @SelectColunm(typeValue = "A")
+    private String crtDutyName;
+    /**
+     * 家庭住址
+     */
+    @SelectColunm(typeValue = "A")
+    private String homeAddress;
+    /**
+     * 手机号
+     */
+    @Unique(value = "SEAFARER_001", message = "手机号重复")
+    @SelectColunm
+    private String mobilePhone;
+    /**
+     * 备注Id
+     */
+    @SelectColunm(typeValue = "A")
+    private String remarkId;
+    /**
+     * 备注
+     */
+    @SelectColunm(typeValue = "A")
+    private String remark;
+    /**
+     * 船员状态key
+     */
+    @SelectColunm(typeValue = "A")
+    private CrewSeafarerStatusEnum statusKey;
+    /**
+     * 状态
+     */
+    @SelectColunm(typeValue = "A")
+    private String statusValue;
+
+
+    /**
+     * 在船船员状态(在船船员的预警状态)
+     */
+    @SelectColunm(typeValue = "B")
+    private String onStatusValue;
+    /**
+     * 上船日期
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @SelectColunm(typeValue = "B")
+    private Date onBoardDate;
+
+    /**
+     * 在船时间
+     */
+    private String onBoardTime;
+
+    /**
+     * 显示在船船员预警天数
+     */
+    @SelectColunm(typeValue = "B")
+    private String alertDays;
+
+    /**
+     * 船员头像地址
+     */
+    private String seafarerHeadimgAddress;
+    /**
+     * 船员英文名称
+     */
+    @SelectColunm
+    private String seafarerNameEn;
+    /**
+     * 船员号
+     */
+    @SelectColunm
+    private Long seafarerNumber;
+    /**
+     * 申请职务ID
+     */
+    private String applyDutyId;
+    /**
+     * 申请职务姓名
+     */
+    private String applyDutyName;
+
+    /**
+     * 证书等级
+     */
+    @SelectColunm(typeValue = "A")
+    private String crtLevelId;
+
+    /**
+     * 证书等级
+     */
+    @SelectColunm(typeValue = "A")
+    private String crtLevelName;
+    /**
+     * 国籍Key
+     */
+    @SelectColunm(typeValue = "A")
+    private String nationalityKey;
+    /**
+     * 国籍
+     */
+    @SelectColunm(typeValue = "A")
+    private String nationalityValue;
+    /**
+     * 出生省key
+     */
+    private Integer brithplaceProvKey;
+    /**
+     * 出生省
+     */
+    private String brithplaceProvValue;
+    /**
+     * 出生城市key
+     */
+    private Integer brithplaceCityKey;
+    /**
+     * 出生城市
+     */
+    private String brithplaceCityValue;
+    /**
+     * 民族
+     */
+    private String nation;
+    /**
+     * 政治面貌key
+     */
+    private String politicalKey;
+    /**
+     * 政治面貌
+     */
+    private String politicalValue;
+    /**
+     * 籍贯省ID
+     */
+    @SelectColunm(typeValue = "A")
+    private Integer placeOfOriginProvKey;
+    /**
+     * 籍贯省
+     */
+    @SelectColunm(typeValue = "A")
+    private String placeOfOriginProvValue;
+    /**
+     * 籍贯城市
+     */
+    @SelectColunm(typeValue = "A")
+    private Integer placeOfOriginCityKey;
+    /**
+     * 籍贯城市
+     */
+    @SelectColunm(typeValue = "A")
+    private String placeOfOriginCityValue;
+    /**
+     * 身份证号
+     */
+    @Unique(value = "SEAFARER_002", message = "身份证号重复")
+    @SelectColunm(typeValue = "B")
+    private String seafarerIdNo;
+    /**
+     * 婚姻状况key
+     */
+    private String marriageStatusKey;
+    /**
+     * 婚姻状况
+     */
+    private String marriageStatusValue;
+    /**
+     * 健康状况
+     */
+    private String healthy;
+    /**
+     * 性别key
+     */
+    private String seafarerSexKey;
+    /**
+     * 性别
+     */
+    private String seafarerSexValue;
+    /**
+     * 腰围
+     */
+    private String waistline;
+    /**
+     * 身高
+     */
+    private String height;
+    /**
+     * 血型key
+     */
+    private String bloodKey;
+    /**
+     * 血型
+     */
+    private String bloodValue;
+    /**
+     * 体重
+     */
+    private String weight;
+    /**
+     * 工作服号
+     */
+    private String suitSize;
+    /**
+     * 鞋号
+     */
+    private String shoeSize;
+    /**
+     * 船员类型key
+     */
+    @SelectColunm(typeValue = "A")
+    private String seafarerTypeKey;
+    /**
+     * 船员类型
+     */
+    @SelectColunm(typeValue = "A")
+    private String seafarerTypeValue;
+    /**
+     * 用工形式ID
+     */
+    private String employmentId;
+    /**
+     * 用工形式名称
+     */
+    private String employmentName;
+    /**
+     * 航海经验key
+     */
+    @SelectColunm(typeValue = "A")
+    private String maritimeExperienceKey;
+    /**
+     * 航海经验
+     */
+    @SelectColunm(typeValue = "A")
+    private String maritimeExperienceValue;
+    /**
+     * 遣返地
+     */
+    private String repatriateCity;
+    /**
+     * 参加工作日期
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date beginWorkDate;
+    /**
+     * 其他电话
+     */
+    private String otherTel;
+    /**
+     * 邮箱
+     */
+    private String email;
+    /**
+     * qq或微信
+     */
+    private String qqWechat;
+    /**
+     * 邮政编号
+     */
+    private String postCode;
+    /**
+     * 通讯地址
+     */
+    private String currentAddress;
+    /**
+     * 英文地址
+     */
+    @SelectColunm(typeValue = "A")
+    private String homeAddressEn;
+    /**
+     * 户口地址
+     */
+    private String censusRegister;
+    /**
+     * 联络备注
+     */
+    private String liaisonRemark;
+    /**
+     * 毕业学校
+     */
+    private String school;
+    /**
+     * 学校所在地
+     */
+    private String schoolPlace;
+    /**
+     * 学校性质key
+     */
+    private String schoolNatureKey;
+    /**
+     * 学校性质
+     */
+    private String schoolNatureValue;
+    /**
+     * 学历key
+     */
+    private String educationKey;
+    /**
+     * 学历
+     */
+    private String educationValue;
+    /**
+     * 学历证号
+     */
+    private String educationCertNo;
+    /**
+     * 入学日期
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date enrollmentDate;
+    /**
+     * 结业日期
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date graduationDate;
+    /**
+     * 专业
+     */
+    private String major;
+    /**
+     * 职称
+     */
+    private String jobTitle;
+    /**
+     * 第二学历标识
+     */
+    private String secondEducationKey;
+    /**
+     * 第二学历
+     */
+    private String secondEducationValue;
+    /**
+     * 第二学历证号
+     */
+    private String secondEducationCertNo;
+    /**
+     * 英语等级
+     */
+    private String englishLevel;
+    /**
+     * 船型ID
+     */
+    private String vesselKey;
+    /**
+     * 船型
+     */
+    private String vesselValue;
+    /**
+     * 月薪要求
+     */
+    private String salary;
+    /**
+     * 币种key
+     */
+    private String currencyKey;
+    /**
+     * 币种名称
+     */
+    private String currencyValue;
+    /**
+     * 要求载重吨key
+     */
+    private String tonKey;
+    /**
+     * 要求载重吨
+     */
+    private String tonValue;
+    /**
+     * 航区key
+     */
+    private String navigatingAreaKey;
+    /**
+     * 航区
+     */
+    private String navigatingAreaValue;
+    /**
+     * 计划上船时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date planDate;
+    /**
+     * 上船要求_备注
+     */
+    private String otherRemark;
+
+    /**
+     * 社保号
+     */
+    private String socialSecurityNo;
+
+    /**
+     * 是否ISM培训
+     */
+    private String ismTraining;
+
+    /**
+     * 签名地址
+     */
+    private String autographUrl;
+
+    /**
+     * 当前船舶ID
+     */
+    private String currentVesselId;
+
+    /**
+     * 当前船舶名称
+     */
+    private String currentVesselName;
+
+    /**
+     * 最近服务资历id
+     */
+    private String serviceId;
+
+    /**
+     * 船员年龄
+     */
+    @TableField(exist = false)
+    private String seafarerAge;
+
+    /**
+     * 任职时间
+     */
+    @TableField(exist = false)
+    private String servingTime;
+
+    /**
+     * 显示参加工作时间
+     */
+    @TableField(exist = false)
+    private String beginWorkTime;
+    /**
+     * 显示的船员标号
+     */
+    @TableField(exist = false)
+    private String seafarerNo;
+
+    /**
+     * 开始出生时间
+     */
+    @TableField(exist = false)
+    @SearchField(value = "birthday", mode = SearchMode.GE)
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date beginBirthday;
+
+    /**
+     * 结束出生时间
+     */
+    @SearchField(value = "birthday", mode = SearchMode.LE)
+    @TableField(exist = false)
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date endBirthday;
+
+    /**
+     * 计划开始上船时间
+     */
+    @TableField(exist = false)
+    @SearchField(value = "on_board_date", mode = SearchMode.GE)
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date beginOnday;
+
+    /**
+     * 计划结束上船时间
+     */
+
+    @SearchField(value = "on_board_date", mode = SearchMode.LE)
+    @TableField(exist = false)
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date endOnday;
+
+    /**
+     * 开始上船时间
+     */
+    @TableField(exist = false)
+    @SearchField(value = "on_board_date", mode = SearchMode.GE)
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date beginOnBoardDate;
+
+    /**
+     * 结束上船时间
+     */
+
+    @SearchField(value = "on_board_date", mode = SearchMode.LE)
+    @TableField(exist = false)
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date endOnBoardDate;
+
+    /**
+     * 证书种类
+     */
+    @TableField(exist = false)
+    @SearchField(value = "crt_duty_id", mode = SearchMode.IN)
+    private String cdis;
+
+    /**
+     * 船舶ID集合
+     */
+    @TableField(exist = false)
+    @SearchField(value = "vessel_id", mode = SearchMode.IN)
+    private String vesselIds;
+
+    /**
+     * 外派公司种类
+     */
+    @TableField(exist = false)
+    @SearchField(value = "owned_out_comp_id", mode = SearchMode.IN)
+    private String outCompIds;
+
+    /**
+     * 船员状态key
+     */
+    @TableField(exist = false)
+    @SearchField(value = "status_key", mode = SearchMode.IN)
+    private String seafarerStatus;
+
+    /**
+     * 下船原因种类
+     */
+    @TableField(exist = false)
+    private String downBoardReasonKeys;
+
+
+    /**
+     * 合同下船日期
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @SelectColunm(typeValue = "B")
+    private Date downBoardDate;
+
+
+    /**
+     * 在船状态(多条用,分隔)
+     */
+    @TableField(exist = false)
+    @SearchField(value = "on_status_key", mode = SearchMode.IN)
+    private String onStatusKeys;
+
+    /**
+     * 多条证书状态
+     */
+    @TableField(exist = false)
+    private String crtStatuses;
+
+    /**
+     * 动态表单数据
+     */
+    @TableField(exist = false)
+    private String dynamicData;
+
+    /**
+     * 在船职务
+     */
+    @TableField(exist = false)
+    @SearchField(value = "on_duty_id", mode = SearchMode.IN)
+    private String onDutyIds;
+
+    /**
+     * 开始下船时间
+     */
+    @TableField(exist = false)
+    @SearchField(value = "down_board_date", mode = SearchMode.GE)
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date beginDownday;
+
+    /**
+     * 结束下船时间
+     */
+
+    @SearchField(value = "down_board_date", mode = SearchMode.LE)
+    @TableField(exist = false)
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date endDownday;
+
+    /**
+     * 航区keys(查询)
+     */
+    @TableField(exist = false)
+    private String navigatingAreaKeys;
+
+    /**
+     * 电子签名地址
+     */
+    private String eSignatureAddress;
+
+    /**
+     * 船员状态s
+     */
+    @TableField(exist = false)
+    private String statusKeys;
+
+    @Override
+    protected Serializable pkVal() {
+        return this.seafarerId;
+    }
+
+    /**
+     * 查询用字段
+     */
+    public static class QueryFields {
+
+        public static final String SEAFARER_ID = "seafarer_id";
+
+        public static final String SEAFARER_NAME = "seafarer_name";
+
+        public static final String GETPY_SEAFARER_NAME = "getPY(seafarer_name)";
+
+        public static final String SEAFARER_NAME_EN = "seafarer_name_en";
+
+        public static final String STATUS_KEY = "status_key";
+
+        public static final String BIRTHDAY = "birthday";
+
+        public static final String COMP_ID = "comp_id";
+
+        public static final String ENTER_COMPANY_DATE = "enter_company_date";
+
+        public static final String OWNED_OUT_COMP_ID = "owned_out_comp_id";
+
+        public static final String VESSEL_ID = "vessel_id";
+
+        public static final String MOBILE_PHONE = "mobile_phone";
+
+        public static final String ON_DUTY_ID = "on_duty_id";
+
+        public static final String CREATE_DATE = "create_date";
+
+        public static final String DOWN_BOARD_DATE = "down_board_date";
+
+        public static final String ON_BOARD_DATE = "on_board_date";
+
+        public static final String SEAFARER_ID_NO = "seafarer_id_no";
+
+        public static final String SEAFARER_NUMBER = "seafarer_number";
+
+        public static final String SEAFARER_TYPE_KEY = "seafarer_type_key";
+
+        public static final String APPLY_DUTY_ID = "apply_duty_id";
+
+        public static final String CRT_DUTY_ID = "crt_duty_id";
+
+        private QueryFields() {
+        }
+    }
+
+}

+ 99 - 0
winsea-haixin-plugin-base/src/main/java/com/winsea/svc/crew/entity/view/CrewSeafarerInfoView.java

@@ -0,0 +1,99 @@
+package com.winsea.svc.crew.entity.view;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.winsea.svc.crew.constant.CrewSeafarerStatusEnum;
+import com.winsea.svc.crew.entity.CrewSeafarerInfo;
+import com.yh.saas.common.support.entity.BaseModel;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * <p>
+ * 船员表
+ * </p>
+ *
+ * @author XinGuang
+ * @since 2019-06-27
+ */
+
+@Data
+public class CrewSeafarerInfoView extends BaseModel<CrewSeafarerInfo> {
+	
+	/**
+	 * 船员状态key
+	 */
+	private CrewSeafarerStatusEnum statusKey;
+	
+	/**
+	 * 船舶id(在船的时候有,不在船的时候为空)
+	 */
+	private String vesselId;
+	
+	/**
+	 * 船员类型key
+	 */
+	private String seafarerTypeKey;
+
+	/**
+	 * 公司ID
+	 */
+	private String compId;
+
+	/**
+	 * 外派公司id
+	 */
+	private String ownedOutCompId;
+
+	/**
+	 * 在船职务ID
+	 */
+	private String onDutyId;
+
+	/**
+	 * 船员状态s
+	 */
+	private String statusKeys;
+	
+	/**
+	 * 申请职务ID
+	 */
+	private String applyDutyId;
+	
+	/**
+	 * 船员姓名检索
+	 */
+	private String seafarerName;
+	
+	/**
+	 * 证书职务id
+	 */
+	private String crtDutyId;
+
+	/**
+	 * 查询符合免试船员标识
+	 */
+	private String allowFlag;
+
+	private String seafarerId;
+ 	/**
+	* 计划开始上船时间
+	 */
+	@JsonFormat(pattern = "yyyy-MM-dd")
+	@DateTimeFormat(pattern = "yyyy-MM-dd")
+	private Date beginOnday;
+
+	/**
+	 * 计划结束上船时间
+	 */
+
+	@JsonFormat(pattern = "yyyy-MM-dd")
+	@DateTimeFormat(pattern = "yyyy-MM-dd")
+	private Date endOnday;
+	@Override
+	protected Serializable pkVal() {
+		return this.seafarerId;
+	}
+}

+ 27 - 0
winsea-haixin-plugin-base/src/main/java/com/winsea/svc/crew/service/ICrewSeafarerInfoService.java

@@ -0,0 +1,27 @@
+package com.winsea.svc.crew.service;
+
+import com.baomidou.mybatisplus.service.IService;
+import com.winsea.svc.crew.entity.CrewSeafarerInfo;
+import com.winsea.svc.crew.entity.view.CrewSeafarerInfoView;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 船员表 服务类
+ * </p>
+ *
+ * @author XinGuang
+ * @since 2019-06-27
+ */
+public interface ICrewSeafarerInfoService extends IService<CrewSeafarerInfo> {
+
+    /**
+     * 根据各种参数获取船员列表
+     *
+     * @param example
+     * @return
+     */
+    List<CrewSeafarerInfo> getListBySeafarerCrew(CrewSeafarerInfoView example);
+
+}

+ 11 - 0
winsea-haixin-plugin-base/src/main/java/com/yh/saas/plugin/base/config/PluginBaseConfig.java

@@ -0,0 +1,11 @@
+package com.yh.saas.plugin.base.config;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.annotation.Configuration;
+
+
+@MapperScan("com.yh.saas.plugin.base.mapper")
+@Configuration
+public class PluginBaseConfig {
+	
+}

+ 122 - 0
winsea-haixin-plugin-base/src/main/java/com/yh/saas/plugin/base/entity/CommonBillOperateHis.java

@@ -0,0 +1,122 @@
+package com.yh.saas.plugin.base.entity;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import com.baomidou.mybatisplus.annotations.TableField;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.yh.saas.common.support.entity.BaseModel;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 记录单据操作历史
+ * </p>
+ *
+ * @author SongJin
+ * @since 2020-01-03
+ */
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Accessors(chain = true)
+public class CommonBillOperateHis extends BaseModel<CommonBillOperateHis> {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键id
+     */
+    private String id;
+    /**
+     * 单据ID
+     */
+    private String billId;
+
+    /**
+     * 单据枚举类型(两个单据ID相同的时候用类型区分)
+     */
+    private String billType;
+    /**
+     * 单据名称
+     */
+    private String billName;
+    /**
+     * 操作人
+     */
+    private String operateUser;
+    /**
+     * 操作时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date operateDate;
+    /**
+     * 处理信息
+     */
+    private String dealMsg;
+    /**
+     * 处理信息英文
+     */
+    private String dealMsgEn;
+    /**
+     * 审核意见
+     */
+    private String verifyRemark;
+    /**
+     * 审核人职务
+     */
+    private String verifyUserDuty;
+    /**
+     * 签名路径
+     */
+    private String signPath;
+    /**
+     * 审批结果
+     */
+    @TableField(exist = false)
+    private String approveResult;
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+    /**
+     * 查询类
+     */
+    public static class QueryFields {
+
+        private QueryFields() {
+
+        }
+
+        public static final String BILL_ID = "bill_id";
+        public static final String OPERATE_DATE = "operate_date";
+        public static final String BILL_NAME = "bill_name";
+        public static final String CREATE_USER_ID = "create_user_id";
+        public static final String BILL_TYPE = "bill_type";
+
+
+    }
+
+    public static CommonBillOperateHis getInstance(String operateUser, Date operateDate, String approveResult,
+                                                   String dealMsg, String dealMsgEn, String duty, String verifyRemark) {
+        CommonBillOperateHis history = new CommonBillOperateHis();
+        history.setOperateUser(duty + " " + operateUser);
+        history.setOperateDate(operateDate);
+        history.setDealMsg(dealMsg);
+        history.setDealMsgEn(dealMsgEn);
+        history.setApproveResult(approveResult);
+        history.setVerifyRemark(verifyRemark);
+        return history;
+    }
+
+}

+ 216 - 0
winsea-haixin-plugin-base/src/main/java/com/yh/saas/plugin/base/entity/EOBase.java

@@ -0,0 +1,216 @@
+/**
+ * Copyright (C) 2008 TT. All rights reserved.
+ */
+package com.yh.saas.plugin.base.entity;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 类名称:EOBase
+ * 内容摘要:EO抽象类  (create_user_id和update_user_id固定传sysadmin  其他的不用传)
+ *
+ * @author yinghai
+ * @version 1.0 2013/04/02
+ */
+@SuppressWarnings("serial")
+public abstract class EOBase implements Serializable {
+    /**
+     * 删除标识
+     */
+    private String delete_flag;
+    /**
+     * 更新次数
+     */
+    private Long update_count;
+    /**
+     * 作成年月日
+     */
+    private Date create_date;
+    /**
+     * 作成用户ID
+     */
+    private String create_user_id;  //固定传sysadmin  
+    /**
+     * 更新年月日
+     */
+    private Date update_date;
+    /**
+     * 更新用户ID
+     */
+    private String update_user_id; //固定传sysadmin
+    /**
+     * 更新标识
+     */
+    private String update_flag;
+    /**
+     * 当前版本号
+     */
+    private Long now_version_no;
+    /**
+     * 上一次同步后版本号
+     */
+    private Long prev_version_no;
+
+    /**
+     * 取得 删除标识
+     *
+     * @return 删除标识
+     */
+    public String getDelete_flag() {
+        return delete_flag;
+    }
+
+    /**
+     * 设定 删除标识
+     *
+     * @param delete_flag 删除标识
+     */
+    public void setDelete_flag(String delete_flag) {
+        this.delete_flag = delete_flag;
+    }
+
+    /**
+     * 取得 更新次数
+     *
+     * @return 更新次数
+     */
+    public Long getUpdate_count() {
+        return update_count;
+    }
+
+    /**
+     * 设定 更新次数
+     *
+     * @param update_count 更新次数
+     */
+    public void setUpdate_count(Long update_count) {
+        this.update_count = update_count;
+    }
+
+    /**
+     * 取得 作成年月日
+     *
+     * @return 作成年月日
+     */
+    public Date getCreate_date() {
+        return create_date;
+    }
+
+    /**
+     * 设定 作成年月日
+     *
+     * @param create_date 作成年月日
+     */
+    public void setCreate_date(Date create_date) {
+        this.create_date = create_date;
+    }
+
+    /**
+     * 取得 作成用户ID
+     *
+     * @return 作成用户ID
+     */
+    public String getCreate_user_id() {
+        return create_user_id;
+    }
+
+    /**
+     * 设定 作成用户ID
+     *
+     * @param create_user_id 作成用户ID
+     */
+    public void setCreate_user_id(String create_user_id) {
+        this.create_user_id = create_user_id;
+    }
+
+    /**
+     * 取得 更新年月日
+     *
+     * @return 更新年月日
+     */
+    public Date getUpdate_date() {
+        return update_date;
+    }
+
+    /**
+     * 设定 更新年月日
+     *
+     * @param update_date 更新年月日
+     */
+    public void setUpdate_date(Date update_date) {
+        this.update_date = update_date;
+    }
+
+    /**
+     * 取得 更新用户ID
+     *
+     * @return 更新用户ID
+     */
+    public String getUpdate_user_id() {
+        return update_user_id;
+    }
+
+    /**
+     * 设定 更新用户ID
+     *
+     * @param update_user_id 更新用户ID
+     */
+    public void setUpdate_user_id(String update_user_id) {
+        this.update_user_id = update_user_id;
+    }
+
+    /**
+     * 取得 更新标识
+     *
+     * @return 更新标识
+     */
+    public String getUpdate_flag() {
+        return update_flag;
+    }
+
+    /**
+     * 设定 更新标识
+     *
+     * @param update_flag 更新标识
+     */
+    public void setUpdate_flag(String update_flag) {
+        this.update_flag = update_flag;
+    }
+
+    /**
+     * 取得 当前版本号
+     *
+     * @return now_version_no 当前版本号
+     */
+    public Long getNow_version_no() {
+        return now_version_no;
+    }
+
+    /**
+     * 设定 当前版本号
+     *
+     * @param nowVersionNo 当前版本号
+     */
+    public void setNow_version_no(Long nowVersionNo) {
+        now_version_no = nowVersionNo;
+    }
+
+    /**
+     * 取得 上一次同步后版本号
+     *
+     * @return prev_version_no 上一次同步后版本号
+     */
+    public Long getPrev_version_no() {
+        return prev_version_no;
+    }
+
+    /**
+     * 设定 上一次同步后版本号
+     *
+     * @param prevVersionNo 上一次同步后版本号
+     */
+    public void setPrev_version_no(Long prevVersionNo) {
+        prev_version_no = prevVersionNo;
+    }
+}

+ 305 - 0
winsea-haixin-plugin-base/src/main/java/com/yh/saas/plugin/base/entity/EOVDBillBasicDataInfo.java

@@ -0,0 +1,305 @@
+package com.yh.saas.plugin.base.entity;
+
+import com.baomidou.mybatisplus.annotations.TableField;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Accessors(chain = true)
+public class EOVDBillBasicDataInfo extends EOBase {
+
+    /**
+     * 公司ID
+     **/
+    private String comp_id;
+    /**
+     * 客户公司ID
+     **/
+    private String c_comp_id;
+    /**
+     * 单据ID(询价单ID)
+     **/
+    private String bill_id;
+    /**
+     * 单据类型ID
+     **/
+    private String bill_type_id;
+    /**
+     * 单据名称
+     **/
+    private String bill_name;
+    /**
+     * 单据名称英文
+     **/
+    private String bill_name_en;
+    /**
+     * 项目ID
+     **/
+    private String item_id;
+    /**
+     * 项目名称
+     **/
+    private String item_name;
+    /**
+     * 项目名称英文
+     **/
+    private String item_name_en;
+    /**
+     * 是否必填项标识
+     **/
+    private String required_flag;
+    /**
+     * 显示标识
+     **/
+    private String show_flag;
+    /**
+     * 项目类型标识
+     **/
+    private String item_type_flag;
+    /**
+     * 打印标识
+     **/
+    private String print_flag;
+    /**
+     * 所占列数
+     **/
+    private String columns;
+    /**
+     * 所占行数
+     **/
+    private String rows;
+    /**
+     * 顺序号
+     **/
+    private Integer serial_number;
+    /**
+     * 备用字段1
+     **/
+    private String reserve01;
+    /**
+     * 备用字段2
+     **/
+    private String reserve02;
+    /**
+     * 备用字段3
+     **/
+    private String reserve03;
+    /**
+     * 备用字段4
+     **/
+    private String reserve04;
+    /**
+     * 备用字段5
+     **/
+    private String reserve05;
+    /**
+     * 备用字段6
+     **/
+    private String reserve06;
+    /**
+     * 备用字段7
+     **/
+    private String reserve07;
+    /**
+     * 备用字段8
+     **/
+    private String reserve08;
+    /**
+     * 备用字段9
+     **/
+    private String reserve09;
+    /**
+     * 备用字段10
+     **/
+    private String reserve10;
+
+    /**
+     * 编辑标识 值为show时可编辑,否则为label
+     **/
+    @TableField(exist = false)
+    private String edit_flag;
+
+    /**
+     * 公司ID
+     **/
+    public void setComp_id(String customCompId) {
+        this.comp_id = customCompId;
+    }
+
+    /**
+     * 客户公司ID
+     **/
+    public void setC_comp_id(String vendorIdSupply) {
+        this.c_comp_id = vendorIdSupply;
+    }
+
+    /**
+     * 单据ID(询价单ID)
+     **/
+    public void setBill_id(String quotesId) {
+        this.bill_id = quotesId;
+    }
+
+    /**
+     * 单据类型ID
+     **/
+    public void setBill_type_id(String billTypeId) {
+        this.bill_type_id = billTypeId;
+    }
+
+    /**
+     * 单据名称
+     **/
+    public void setBill_name(String billName) {
+        this.bill_name = billName;
+    }
+
+    /**
+     * 单据名称英文
+     **/
+    public void setBill_name_en(String billNameEn) {
+        this.bill_name_en = billNameEn;
+    }
+
+    /**
+     * 项目ID
+     **/
+    public void setItem_id(String itemId) {
+        this.item_id = itemId;
+    }
+
+    /**
+     * 项目名称
+     **/
+    public void setItem_name(String itemName) {
+        this.item_name = itemName;
+    }
+
+    /**
+     * 项目名称英文
+     **/
+    public void setItem_name_en(String itemNameEn) {
+        this.item_name_en = itemNameEn;
+    }
+
+    /**
+     * 是否必填项标识
+     **/
+    public void setRequired_flag(String requiredFlag) {
+        this.required_flag = requiredFlag;
+    }
+
+    /**
+     * 显示标识
+     **/
+    public void setShow_flag(String showFlag) {
+        this.show_flag = showFlag;
+    }
+
+    /**
+     * 项目类型标识
+     **/
+    public void setItem_type_flag(String itemTypeFlag) {
+        this.item_type_flag = itemTypeFlag;
+    }
+
+    /**
+     * 打印标识
+     **/
+    public void setPrint_flag(String printFlag) {
+        this.print_flag = printFlag;
+    }
+
+    /**
+     * 所占列数
+     **/
+    public void setColumns(String columns) {
+        this.columns = columns;
+    }
+
+    /**
+     * 所占行数
+     **/
+    public void setRows(String rows) {
+        this.rows = rows;
+    }
+
+    /**
+     * 顺序号
+     **/
+    public void setSerial_number(Integer serialNumber) {
+        this.serial_number = serialNumber;
+    }
+
+    /**
+     * 备用字段1
+     **/
+    public void setReserve01(String reserve01) {
+        this.reserve01 = reserve01;
+    }
+
+    /**
+     * 备用字段2
+     **/
+    public void setReserve02(String reserve02) {
+        this.reserve02 = reserve02;
+    }
+
+    /**
+     * 备用字段3
+     **/
+    public void setReserve03(String reserve03) {
+        this.reserve03 = reserve03;
+    }
+
+    /**
+     * 备用字段4
+     **/
+    public void setReserve04(String reserve04) {
+        this.reserve04 = reserve04;
+    }
+
+    /**
+     * 备用字段5
+     **/
+    public void setReserve05(String reserve05) {
+        this.reserve05 = reserve05;
+    }
+
+    /**
+     * 备用字段6
+     **/
+    public void setReserve06(String reserve06) {
+        this.reserve06 = reserve06;
+    }
+
+    /**
+     * 备用字段7
+     **/
+    public void setReserve07(String reserve07) {
+        this.reserve07 = reserve07;
+    }
+
+    /**
+     * 备用字段8
+     **/
+    public void setReserve08(String reserve08) {
+        this.reserve08 = reserve08;
+    }
+
+    /**
+     * 备用字段9
+     **/
+    public void setReserve09(String reserve09) {
+        this.reserve09 = reserve09;
+    }
+
+    /**
+     * 备用字段10
+     **/
+    public void setReserve10(String reserve10) {
+        this.reserve10 = reserve10;
+    }
+}

+ 282 - 0
winsea-haixin-plugin-base/src/main/java/com/yh/saas/plugin/base/entity/EOXTAppendixInfo.java

@@ -0,0 +1,282 @@
+package com.yh.saas.plugin.base.entity;
+
+import java.util.Date;
+
+public class EOXTAppendixInfo extends EOBase {
+
+    /**
+     * 公司ID
+     **/
+    private String comp_id;
+    /**
+     * 单据ID
+     **/
+    private String bill_id;
+    /**
+     * 附件ID
+     **/
+    private String appendix_id;
+    /**
+     * 附件类别
+     **/
+    private String appendix_type;
+    /**
+     * 详细ID
+     **/
+    private String detail_id;
+    /**
+     * 附件名称
+     **/
+    private String appendix_name;
+    /**
+     * 附件路径
+     **/
+    private String appendix_path;
+    /**
+     * 上传日期
+     **/
+    private Date upload_date;
+    /**
+     * 上传人ID
+     **/
+    private String upload_user_id;
+    /**
+     * 上传人姓名
+     **/
+    private String upload_user_name;
+    /**
+     * 上传文件大小
+     **/
+    private String upload_file_size;
+    /**
+     * 文件来源标识
+     **/
+    private String file_source_flag;
+
+    public EOXTAppendixInfo() {
+    }
+
+    public EOXTAppendixInfo(String comp_id, String bill_id, String appendix_id) {
+        this.comp_id = comp_id;
+        this.bill_id = bill_id;
+        this.appendix_id = appendix_id;
+    }
+
+    /**
+     * 取得公司ID
+     *
+     * @return 公司ID
+     */
+    public String getComp_id() {
+        return this.comp_id;
+    }
+
+    /**
+     * 设置公司ID
+     *
+     * @return 公司ID
+     */
+    public void setComp_id(String comp_id) {
+        this.comp_id = comp_id;
+    }
+
+    /**
+     * 取得单据ID
+     *
+     * @return 单据ID
+     */
+    public String getBill_id() {
+        return this.bill_id;
+    }
+
+    /**
+     * 设置单据ID
+     *
+     * @return 单据ID
+     */
+    public void setBill_id(String bill_id) {
+        this.bill_id = bill_id;
+    }
+
+    /**
+     * 取得附件ID
+     *
+     * @return 附件ID
+     */
+    public String getAppendix_id() {
+        return this.appendix_id;
+    }
+
+    /**
+     * 设置附件ID
+     *
+     * @return 附件ID
+     */
+    public void setAppendix_id(String appendix_id) {
+        this.appendix_id = appendix_id;
+    }
+
+    /**
+     * 取得附件类别
+     *
+     * @return 附件类别
+     */
+    public String getAppendix_type() {
+        return this.appendix_type;
+    }
+
+    /**
+     * 设置附件类别
+     *
+     * @return 附件类别
+     */
+    public void setAppendix_type(String appendix_type) {
+        this.appendix_type = appendix_type;
+    }
+
+    /**
+     * 取得详细ID
+     *
+     * @return 详细ID
+     */
+    public String getDetail_id() {
+        return this.detail_id;
+    }
+
+    /**
+     * 设置详细ID
+     *
+     * @return 详细ID
+     */
+    public void setDetail_id(String detail_id) {
+        this.detail_id = detail_id;
+    }
+
+    /**
+     * 取得附件名称
+     *
+     * @return 附件名称
+     */
+    public String getAppendix_name() {
+        return this.appendix_name;
+    }
+
+    /**
+     * 设置附件名称
+     *
+     * @return 附件名称
+     */
+    public void setAppendix_name(String appendix_name) {
+        this.appendix_name = appendix_name;
+    }
+
+    /**
+     * 取得附件路径
+     *
+     * @return 附件路径
+     */
+    public String getAppendix_path() {
+        return this.appendix_path;
+    }
+
+    /**
+     * 设置附件路径
+     *
+     * @return 附件路径
+     */
+    public void setAppendix_path(String appendix_path) {
+        this.appendix_path = appendix_path;
+    }
+
+    /**
+     * 取得上传日期
+     *
+     * @return 上传日期
+     */
+    public Date getUpload_date() {
+        return this.upload_date;
+    }
+
+    /**
+     * 设置上传日期
+     *
+     * @return 上传日期
+     */
+    public void setUpload_date(Date upload_date) {
+        this.upload_date = upload_date;
+    }
+
+    /**
+     * 取得上传人ID
+     *
+     * @return 上传人ID
+     */
+    public String getUpload_user_id() {
+        return this.upload_user_id;
+    }
+
+    /**
+     * 设置上传人ID
+     *
+     * @return 上传人ID
+     */
+    public void setUpload_user_id(String upload_user_id) {
+        this.upload_user_id = upload_user_id;
+    }
+
+    /**
+     * 取得上传人姓名
+     *
+     * @return 上传人姓名
+     */
+    public String getUpload_user_name() {
+        return this.upload_user_name;
+    }
+
+    /**
+     * 设置上传人姓名
+     *
+     * @return 上传人姓名
+     */
+    public void setUpload_user_name(String upload_user_name) {
+        this.upload_user_name = upload_user_name;
+    }
+
+    /**
+     * 取得上传文件大小
+     *
+     * @return 上传文件大小
+     */
+    public String getUpload_file_size() {
+        return this.upload_file_size;
+    }
+
+    /**
+     * 设置上传文件大小
+     *
+     * @return 上传文件大小
+     */
+    public void setUpload_file_size(String upload_file_size) {
+        this.upload_file_size = upload_file_size;
+    }
+
+    /**
+     * 取得文件来源标识
+     *
+     * @return 文件来源标识
+     */
+    public String getFile_source_flag() {
+        return this.file_source_flag;
+    }
+
+    /**
+     * 设置文件来源标识
+     *
+     * @return 文件来源标识
+     */
+    public void setFile_source_flag(String file_source_flag) {
+        this.file_source_flag = file_source_flag;
+    }
+
+
+}

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff