Browse Source

Merge branch 'dev' of ssh://10.10.100.21/source/saas-platform into dev

hy 7 years ago
parent
commit
56c6cd49e4
100 changed files with 2166 additions and 399 deletions
  1. 3 3
      README.md
  2. 1 0
      applications/commons/commons-dto/src/main/java/com/usoftchina/saas/commons/exception/BizExceptionCode.java
  3. 2 0
      applications/commons/commons-server/src/main/resources/application.yml
  4. 12 0
      applications/commons/commons-server/src/main/resources/config/application-dev.yml
  5. 1 1
      applications/commons/commons-server/src/main/resources/logback-spring.xml
  6. 1 1
      applications/commons/commons-server/src/main/resources/mapper/SystemRemindMapper.xml
  7. 5 1
      applications/document/document-server/src/main/java/com/usoftchina/saas/document/service/impl/EmployeeServiceImpl.java
  8. 10 3
      applications/document/document-server/src/main/java/com/usoftchina/saas/document/service/impl/ProductServiceImpl.java
  9. 0 1
      applications/document/document-server/src/main/java/com/usoftchina/saas/document/service/impl/VendorServiceImpl.java
  10. 1 1
      applications/document/document-server/src/main/resources/logback-spring.xml
  11. 3 3
      applications/document/document-server/src/main/resources/mapper/ProductMapper.xml
  12. 1 1
      applications/money/money-server/src/main/resources/logback-spring.xml
  13. 1 1
      applications/money/money-server/src/main/resources/mapper/PayablesdetailMapper.xml
  14. 1 1
      applications/money/money-server/src/main/resources/mapper/ReceivablesdetailMapper.xml
  15. 1 0
      applications/pom.xml
  16. 1 1
      applications/purchase/purchase-server/src/main/resources/logback-spring.xml
  17. 2 0
      applications/sale/sale-server/src/main/resources/application.yml
  18. 12 0
      applications/sale/sale-server/src/main/resources/config/application-dev.yml
  19. 1 1
      applications/sale/sale-server/src/main/resources/logback-spring.xml
  20. 1 1
      applications/storage/storage-server/src/main/resources/logback-spring.xml
  21. 1 1
      applications/storage/storage-server/src/main/resources/mapper/ProdInOutReportMapper.xml
  22. 20 0
      applications/transfers/pom.xml
  23. 17 0
      applications/transfers/transfers-api/pom.xml
  24. 64 0
      applications/transfers/transfers-server/pom.xml
  25. 17 0
      applications/transfers/transfers-server/src/main/java/com/usoftchina/saas/transfers/TransfersApplication.java
  26. 65 0
      applications/transfers/transfers-server/src/main/java/com/usoftchina/saas/transfers/config/RabbitConfig.java
  27. 106 0
      applications/transfers/transfers-server/src/main/java/com/usoftchina/saas/transfers/po/MessageInfo.java
  28. 261 0
      applications/transfers/transfers-server/src/main/java/com/usoftchina/saas/transfers/service/BaseRabbitReceiveService.java
  29. 68 0
      applications/transfers/transfers-server/src/main/java/com/usoftchina/saas/transfers/service/RabbitReceiveService.java
  30. 97 0
      applications/transfers/transfers-server/src/main/java/com/usoftchina/saas/transfers/service/RabbitSendService.java
  31. 63 0
      applications/transfers/transfers-server/src/main/resources/application.yml
  32. 131 0
      applications/transfers/transfers-server/src/main/resources/logback-spring.xml
  33. 36 0
      applications/transfers/transfers-server/src/test/java/com/usoftchina/saas/transfers/service/RabbitSendServiceTest.java
  34. 8 0
      base-servers/account/account-server/src/main/java/com/usoftchina/saas/account/mapper/AccountCompanyMapper.java
  35. 12 7
      base-servers/account/account-server/src/main/java/com/usoftchina/saas/account/service/impl/AccountServiceImpl.java
  36. 1 1
      base-servers/account/account-server/src/main/resources/logback-spring.xml
  37. 3 0
      base-servers/account/account-server/src/main/resources/mapper/AccountCompanyMapper.xml
  38. 1 1
      base-servers/admin-server/src/main/resources/logback-spring.xml
  39. 12 0
      base-servers/auth/auth-api/src/main/java/com/usoftchina/saas/auth/api/AuthApi.java
  40. 7 1
      base-servers/auth/auth-client/src/main/java/com/usoftchina/saas/auth/client/interceptor/AuthRestInterceptor.java
  41. 3 0
      base-servers/auth/auth-common/src/main/java/com/usoftchina/saas/auth/common/jwt/JwtInfo.java
  42. 38 3
      base-servers/auth/auth-server/src/main/java/com/usoftchina/saas/auth/controller/AuthController.java
  43. 1 1
      base-servers/auth/auth-server/src/main/resources/logback-spring.xml
  44. 1 1
      base-servers/datacenter/datacenter-server/src/main/resources/logback-spring.xml
  45. 1 1
      base-servers/eureka-server/src/main/resources/logback-spring.xml
  46. 2 2
      base-servers/file/file-server/src/main/resources/application.yml
  47. 1 1
      base-servers/file/file-server/src/main/resources/logback-spring.xml
  48. 9 0
      base-servers/gateway-server/src/main/java/com/usoftchina/saas/gateway/config/AuthConfig.java
  49. 27 1
      base-servers/gateway-server/src/main/java/com/usoftchina/saas/gateway/config/AuthFilter.java
  50. 1 0
      base-servers/gateway-server/src/main/resources/application.yml
  51. 1 1
      base-servers/gateway-server/src/main/resources/logback-spring.xml
  52. 1 1
      base-servers/mail/mail-server/src/main/resources/logback-spring.xml
  53. 1 1
      base-servers/sms/sms-server/src/main/resources/logback-spring.xml
  54. 1 1
      base-servers/socket/socket-server/src/main/resources/logback-spring.xml
  55. 36 0
      base-servers/ui-server/src/main/java/com/usoftchina/saas/ui/controller/CustomizeController.java
  56. 77 0
      base-servers/ui-server/src/main/java/com/usoftchina/saas/ui/po/Config.java
  57. 38 0
      base-servers/ui-server/src/main/java/com/usoftchina/saas/ui/repository/CustomizeRepository.java
  58. 51 0
      base-servers/ui-server/src/main/java/com/usoftchina/saas/ui/service/CustomizeService.java
  59. 13 0
      base-servers/ui-server/src/main/resources/config/application-dev.yml
  60. 1 1
      base-servers/ui-server/src/main/resources/logback-spring.xml
  61. 1 1
      base-servers/zipkin-server/src/main/resources/application.yml
  62. 1 1
      base-servers/zipkin-server/src/main/resources/logback-spring.xml
  63. 42 0
      framework/core/src/main/java/com/usoftchina/saas/cache/RedisConfig.java
  64. 7 7
      framework/core/src/main/java/com/usoftchina/saas/exception/ExceptionCode.java
  65. 154 0
      framework/core/src/main/java/com/usoftchina/saas/utils/RedisUtil.java
  66. 65 45
      frontend/saas-portal-web/src/components/conenter/addenterprise.vue
  67. 6 1
      frontend/saas-portal-web/src/components/conenter/company.vue
  68. 22 9
      frontend/saas-portal-web/src/components/conenter/details.vue
  69. 31 23
      frontend/saas-portal-web/src/components/conenter/enterprise.vue
  70. 5 3
      frontend/saas-portal-web/src/components/conenter/failure.vue
  71. 27 16
      frontend/saas-portal-web/src/components/conenter/home.vue
  72. 170 38
      frontend/saas-portal-web/src/components/conenter/invitation.vue
  73. 11 2
      frontend/saas-portal-web/static/css/gongsi.css
  74. 5 5
      frontend/saas-portal-web/static/css/main.css
  75. 0 0
      frontend/saas-portal-web/static/img/TriangleCopy.png
  76. BIN
      frontend/saas-portal-web/static/img/tijiao.png
  77. 69 42
      frontend/saas-web/app/view/core/base/BasePanelController.js
  78. 2 1
      frontend/saas-web/app/view/core/dbfind/DbfindGridPanel.scss
  79. 1 0
      frontend/saas-web/app/view/core/form/DataMultiCombo.js
  80. 1 0
      frontend/saas-web/app/view/core/form/MultiCombo.js
  81. 1 0
      frontend/saas-web/app/view/core/form/RemoteCombo.js
  82. 33 33
      frontend/saas-web/app/view/document/bom/FormPanel.js
  83. 32 31
      frontend/saas-web/app/view/document/customer/FormPanel.js
  84. 33 32
      frontend/saas-web/app/view/document/product/FormPanel.js
  85. 33 33
      frontend/saas-web/app/view/document/vendor/FormPanel.js
  86. 2 0
      frontend/saas-web/app/view/home/charts/KeyData.scss
  87. 1 1
      frontend/saas-web/app/view/main/Main.scss
  88. 4 1
      frontend/saas-web/app/view/money/recBalance/FormPanel.js
  89. 1 1
      frontend/saas-web/app/view/money/report/AccountBalance.js
  90. 5 4
      frontend/saas-web/app/view/money/report/AccountDetails.js
  91. 4 2
      frontend/saas-web/app/view/money/report/OtherIODetail.js
  92. 1 1
      frontend/saas-web/app/view/money/report/PayDetail.js
  93. 1 1
      frontend/saas-web/app/view/money/report/ProfitDetail.js
  94. 2 2
      frontend/saas-web/app/view/money/report/RecDetail.js
  95. 5 7
      frontend/saas-web/app/view/money/report/TotalPayDetail.js
  96. 17 0
      frontend/saas-web/app/view/money/report/TotalPayDetailController.js
  97. 4 7
      frontend/saas-web/app/view/money/report/TotalRecDetail.js
  98. 4 2
      frontend/saas-web/app/view/money/report/TotalRecDetailController.js
  99. 1 1
      frontend/saas-web/app/view/purchase/purchase/FormPanel.js
  100. 8 0
      frontend/saas-web/app/view/purchase/purchase/QueryPanel.js

+ 3 - 3
README.md

@@ -118,9 +118,9 @@
 
 > 日志
 
-* [kibana](http://192.168.0.63:5601)
-* [logstash](tcp://192.168.0.63:5000)
-* [elasticsearch](http://192.168.0.63:9200/_search?pretty)
+* [kibana](http://10.1.81.1:5601)
+* [logstash](tcp://10.1.81.1:5000)
+* [elasticsearch](http://10.1.81.1:9200/_search?pretty)
 
 > 服务
 

+ 1 - 0
applications/commons/commons-dto/src/main/java/com/usoftchina/saas/commons/exception/BizExceptionCode.java

@@ -21,6 +21,7 @@ public enum BizExceptionCode implements BaseExceptionCode {
     NULL_CODERULE(79100, "单据规则不存在,请先确定单据生成规则"),
     CODE_EXISTS(79200, "单据编号已存在"),
     BIZ_CLOSE(79301, "只能关闭已审核的单据"),
+    ORDER_NOT_EXITTS(79300, "单据不存在"),
     BIZ_OPEN(79302, "只能打开已关闭的单据"),
     BIZ_AUDITED(79303,"只能审核未审核的单据"),
     BIZ_UNAUDITED(79304,"只能反审核已审核的单据"),

+ 2 - 0
applications/commons/commons-server/src/main/resources/application.yml

@@ -37,6 +37,8 @@ spring:
   redis:
     host: 10.1.81.62
     port: 6379
+  profiles:
+    active: dev
 management:
   endpoints:
     web:

+ 12 - 0
applications/commons/commons-server/src/main/resources/config/application-dev.yml

@@ -0,0 +1,12 @@
+eureka:
+  instance:
+    leaseRenewalIntervalInSeconds: 10
+    health-check-url-path: /actuator/health
+    status-page-url-path: /actuator/info
+    metadata-map:
+      user.name: ${spring.security.user.name}
+      user.password: ${spring.security.user.password}
+  client:
+    registryFetchIntervalSeconds: 5
+    serviceUrl:
+      defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@127.0.0.1:8500/eureka/

+ 1 - 1
applications/commons/commons-server/src/main/resources/logback-spring.xml

@@ -28,7 +28,7 @@
     <springProperty scope="context" name="spring.profiles.active" source="spring.profiles.active" defaultValue="dev"/>
     <springProperty scope="context" name="common-pattern" source="logging.common-pattern" defaultValue="%d{yyyy-MM-dd HH:mm:ss.SSS}:[%5p] [%t:%r] [%C{1}:%M:%L] --> %m%n"/>
     <springProperty scope="context" name="log.level.console" source="logging.level.console" defaultValue="INFO"/>
-    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="192.168.0.63:5000"/>
+    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="10.1.81.1:5000"/>
 
     <contextName>${spring.application.name}-${spring.profiles.active}-logback</contextName>
 

+ 1 - 1
applications/commons/commons-server/src/main/resources/mapper/SystemRemindMapper.xml

@@ -27,7 +27,7 @@
         where re_id = #{id}
     </update>
     <select id="getApplyCountById" resultType="int">
-        SELECT COUNT(*) FROM REMIND WHERE COMPANYID = #{companyId} AND CREATORID = #{accountId}
+        SELECT COUNT(*) FROM REMIND WHERE COMPANYID = #{companyId} AND CREATORID = #{accountId} AND RE_STATUS = 2
     </select>
     <insert id="insertSelective" parameterType="com.usoftchina.saas.commons.po.AddApply">
         <selectKey resultType="java.lang.Long" keyProperty="id">

+ 5 - 1
applications/document/document-server/src/main/java/com/usoftchina/saas/document/service/impl/EmployeeServiceImpl.java

@@ -112,7 +112,11 @@ public class EmployeeServiceImpl extends CommonBaseServiceImpl<EmployeeMapper, E
 
     @Override
     public void delete(Long id) {
+        String code = getMapper().selectByPrimaryKey(id).getEm_code();
+        DocBaseDTO docBaseDTO = generateMsgObj(id, code);
         getMapper().deleteByPrimaryKey(id);
+        //记录LOG
+        messageLogService.delete(docBaseDTO);
     }
 
     @Override
@@ -153,7 +157,7 @@ public class EmployeeServiceImpl extends CommonBaseServiceImpl<EmployeeMapper, E
                 employee.setUpdateTime(new Date());
                 getMapper().updateByPrimaryKeySelective(employee);
                 DocBaseDTO docBaseDTO = generateMsgObj(id,code);
-                messageLogService.open(docBaseDTO);
+                messageLogService.close(docBaseDTO);
                 return docBaseDTO;
             }else {
                 throw new BizException(BizExceptionCode.BIZ_CLOSE);

+ 10 - 3
applications/document/document-server/src/main/java/com/usoftchina/saas/document/service/impl/ProductServiceImpl.java

@@ -30,7 +30,7 @@ import com.usoftchina.saas.document.service.*;
 import com.usoftchina.saas.exception.BizException;
 import com.usoftchina.saas.page.PageRequest;
 import com.usoftchina.saas.utils.CollectionUtils;
-import com.usoftchina.saas.utils.DateUtils;
+import com.usoftchina.saas.utils.ObjectUtils;
 import com.usoftchina.saas.utils.RegexpUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -142,6 +142,9 @@ public class ProductServiceImpl extends CommonBaseServiceImpl<ProductMapper, Pro
             messageLogService.save(docBaseDTO);
         }else{
             String oldCode = getMapper().getCodeById(product.getId());
+            if (StringUtils.isEmpty(oldCode)){
+                throw new BizException(BizExceptionCode.ORDER_NOT_EXITTS);
+            }
             if (!product.getPr_code().equals(oldCode)){
                 validEnableUpdateCode(product.getId());
             }
@@ -425,7 +428,7 @@ public class ProductServiceImpl extends CommonBaseServiceImpl<ProductMapper, Pro
                 close(docBaseDTO.getId());
             }catch (Exception e){
                 String msg = BizExceptionCode.DEAL_FAILED.getMessage();
-                errorMsg.append(String.format(msg, docBaseDTO.getCode(), e.getMessage()));
+                errorMsg.append(String.format(msg, docBaseDTO.getCode(), e.getMessage()) + "<br />");
             }
         }
         return errorMsg.toString();
@@ -439,7 +442,7 @@ public class ProductServiceImpl extends CommonBaseServiceImpl<ProductMapper, Pro
                 open(docBaseDTO.getId());
             }catch (Exception e){
                 String msg = BizExceptionCode.DEAL_FAILED.getMessage();
-                errorMsg.append(String.format(msg, docBaseDTO.getCode(), e.getMessage()));
+                errorMsg.append(String.format(msg, docBaseDTO.getCode(), e.getMessage()) + "<br />");
             }
         }
         return errorMsg.toString();
@@ -580,6 +583,10 @@ public class ProductServiceImpl extends CommonBaseServiceImpl<ProductMapper, Pro
 
     @Override
     public boolean deleteDetailById(Long id) {
+        Product productTemp = getMapper().selectByPrimaryKey(id);
+        if (ObjectUtils.isEmpty(productTemp)){
+            throw new BizException(BizExceptionCode.ORDER_NOT_EXITTS);
+        }
         Long prodId = productDetailMapper.selectProdidByPrimaryKey(id);
         validProductOperation(prodId, BizExceptionCode.BIZ_RELDELETE_DELETEPROD);
         String prCode = getMapper().selectByPrimaryKey(prodId).getPr_code();

+ 0 - 1
applications/document/document-server/src/main/java/com/usoftchina/saas/document/service/impl/VendorServiceImpl.java

@@ -322,7 +322,6 @@ public class VendorServiceImpl extends CommonBaseServiceImpl<VendorMapper, Vendo
             map.put("v_res","");
             vendorMapper.check(map);
             Object result =  map.get("v_res");
-            System.out.println("result:" + result);
             if(!StringUtils.isEmpty(result)){
                 throw new BizException(BizExceptionCode.USING_EXISTS.getCode(),result.toString());
             }else{

+ 1 - 1
applications/document/document-server/src/main/resources/logback-spring.xml

@@ -28,7 +28,7 @@
     <springProperty scope="context" name="spring.profiles.active" source="spring.profiles.active" defaultValue="dev"/>
     <springProperty scope="context" name="common-pattern" source="logging.common-pattern" defaultValue="%d{yyyy-MM-dd HH:mm:ss.SSS}:[%5p] [%t:%r] [%C{1}:%M:%L] --> %m%n"/>
     <springProperty scope="context" name="log.level.console" source="logging.level.console" defaultValue="INFO"/>
-    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="192.168.0.63:5000"/>
+    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="10.1.81.1:5000"/>
 
     <contextName>${spring.application.name}-${spring.profiles.active}-logback</contextName>
 

+ 3 - 3
applications/document/document-server/src/main/resources/mapper/ProductMapper.xml

@@ -941,13 +941,13 @@
         SELECT COUNT(*) FROM PRODUCTONHAND WHERE PO_PRODID = #{id}
     </select>
     <select id="selectProdIOCount" resultType="int">
-        SELECT COUNT(*) FROM PRODIODETAIL WHERE PD_STATUS != 99 AND PD_PRODID = #{id}
+        SELECT COUNT(*) FROM PRODIODETAIL WHERE IFNULL(PD_STATUS,-1) != 99 AND PD_PRODID = #{id}
     </select>
     <select id="selectSale" resultType="int">
-        SELECT COUNT(*) FROM SALE LEFT JOIN SALEDETAIL ON SA_ID = SD_SAID WHERE SA_SENDSTATUS != '已出库' AND SA_SENDSTATUS != '已关闭' AND IFNULL(SD_PRODID,0) = #{id}
+        SELECT COUNT(*) FROM SALE LEFT JOIN SALEDETAIL ON SA_ID = SD_SAID WHERE IFNULL(SA_SENDSTATUS,' ') != '已出库' AND IFNULL(SA_SENDSTATUS,' ') != '已关闭' AND IFNULL(SD_PRODID,0) = #{id}
     </select>
     <select id="selectPurchase" resultType="int">
-        SELECT COUNT(*) FROM PURCHASE LEFT JOIN PURCHASEDETAIL ON PU_ID = PD_PUID WHERE PU_ACCEPTSTATUS != '已出库' AND PU_ACCEPTSTATUSCODE != '已关闭' AND IFNULL(PD_PRODID,0) = #{id}
+        SELECT COUNT(*) FROM PURCHASE LEFT JOIN PURCHASEDETAIL ON PU_ID = PD_PUID WHERE IFNULL(PU_ACCEPTSTATUS,' ') != '已出库' AND IFNULL(PU_ACCEPTSTATUSCODE,' ') != '已关闭' AND IFNULL(PD_PRODID,0) = #{id}
     </select>
 </mapper>
 

+ 1 - 1
applications/money/money-server/src/main/resources/logback-spring.xml

@@ -28,7 +28,7 @@
     <springProperty scope="context" name="spring.profiles.active" source="spring.profiles.active" defaultValue="dev"/>
     <springProperty scope="context" name="common-pattern" source="logging.common-pattern" defaultValue="%d{yyyy-MM-dd HH:mm:ss.SSS}:[%5p] [%t:%r] [%C{1}:%M:%L] --> %m%n"/>
     <springProperty scope="context" name="log.level.console" source="logging.level.console" defaultValue="INFO"/>
-    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="192.168.0.63:5000"/>
+    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="10.1.81.1:5000"/>
 
     <contextName>${spring.application.name}-${spring.profiles.active}-logback</contextName>
 

+ 1 - 1
applications/money/money-server/src/main/resources/mapper/PayablesdetailMapper.xml

@@ -36,7 +36,7 @@
         and  companyId = #{companyId} and pd_query =1 and (pd_addpay + pd_addpre + pd_remain) != 0
       </if>
     </where>
-    order by pd_vendid desc, pd_detno asc, pd_date desc
+    order by pd_vendid DESC, pd_detno asc, pd_date desc
   </select>
 
   <select id="selectCalculateFields" resultType="string">

+ 1 - 1
applications/money/money-server/src/main/resources/mapper/ReceivablesdetailMapper.xml

@@ -36,7 +36,7 @@
         and  companyId = #{companyId} and rd_query = 1 and (rd_addrec + rd_addpre + rd_remain) != 0
       </if>
     </where>
-    order by rd_custid desc, rd_detno asc, rd_date desc
+    order by rd_custid DESC, rd_detno asc, rd_date desc
   </select>
 
   <select id="selectCalculateFields" resultType="string">

+ 1 - 0
applications/pom.xml

@@ -19,6 +19,7 @@
         <module>money</module>
         <module>document</module>
         <module>commons</module>
+        <module>transfers</module>
     </modules>
 
 

+ 1 - 1
applications/purchase/purchase-server/src/main/resources/logback-spring.xml

@@ -28,7 +28,7 @@
     <springProperty scope="context" name="spring.profiles.active" source="spring.profiles.active" defaultValue="dev"/>
     <springProperty scope="context" name="common-pattern" source="logging.common-pattern" defaultValue="%d{yyyy-MM-dd HH:mm:ss.SSS}:[%5p] [%t:%r] [%C{1}:%M:%L] --> %m%n"/>
     <springProperty scope="context" name="log.level.console" source="logging.level.console" defaultValue="INFO"/>
-    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="192.168.0.63:5000"/>
+    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="10.1.81.1:5000"/>
 
     <contextName>${spring.application.name}-${spring.profiles.active}-logback</contextName>
 

+ 2 - 0
applications/sale/sale-server/src/main/resources/application.yml

@@ -37,6 +37,8 @@ spring:
   redis:
     host: 10.1.81.62
     port: 6379
+  profiles:
+    active: dev
 eureka:
   instance:
     leaseRenewalIntervalInSeconds: 10

+ 12 - 0
applications/sale/sale-server/src/main/resources/config/application-dev.yml

@@ -0,0 +1,12 @@
+eureka:
+  instance:
+    leaseRenewalIntervalInSeconds: 10
+    health-check-url-path: /actuator/health
+    status-page-url-path: /actuator/info
+    metadata-map:
+      user.name: ${spring.security.user.name}
+      user.password: ${spring.security.user.password}
+  client:
+    registryFetchIntervalSeconds: 5
+    serviceUrl:
+      defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@127.0.0.1:8500/eureka/

+ 1 - 1
applications/sale/sale-server/src/main/resources/logback-spring.xml

@@ -28,7 +28,7 @@
     <springProperty scope="context" name="spring.profiles.active" source="spring.profiles.active" defaultValue="dev"/>
     <springProperty scope="context" name="common-pattern" source="logging.common-pattern" defaultValue="%d{yyyy-MM-dd HH:mm:ss.SSS}:[%5p] [%t:%r] [%C{1}:%M:%L] --> %m%n"/>
     <springProperty scope="context" name="log.level.console" source="logging.level.console" defaultValue="INFO"/>
-    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="192.168.0.63:5000"/>
+    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="10.1.81.1:5000"/>
 
     <contextName>${spring.application.name}-${spring.profiles.active}-logback</contextName>
 

+ 1 - 1
applications/storage/storage-server/src/main/resources/logback-spring.xml

@@ -28,7 +28,7 @@
     <springProperty scope="context" name="spring.profiles.active" source="spring.profiles.active" defaultValue="dev"/>
     <springProperty scope="context" name="common-pattern" source="logging.common-pattern" defaultValue="%d{yyyy-MM-dd HH:mm:ss.SSS}:[%5p] [%t:%r] [%C{1}:%M:%L] --> %m%n"/>
     <springProperty scope="context" name="log.level.console" source="logging.level.console" defaultValue="INFO"/>
-    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="192.168.0.63:5000"/>
+    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="10.1.81.1:5000"/>
 
     <contextName>${spring.application.name}-${spring.profiles.active}-logback</contextName>
 

+ 1 - 1
applications/storage/storage-server/src/main/resources/mapper/ProdInOutReportMapper.xml

@@ -60,7 +60,7 @@
         and  companyid = #{companyId}
       </if>
     </where>
-    order by pd_prodcode,pi_date desc
+    order by pd_prodcode desc,pi_date desc
   </select>
 
 

+ 20 - 0
applications/transfers/pom.xml

@@ -0,0 +1,20 @@
+<?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>applications</artifactId>
+        <groupId>com.usoftchina.saas</groupId>
+        <version>1.0.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>transfers</artifactId>
+
+    <packaging>pom</packaging>
+    <modules>
+        <module>transfers-api</module>
+        <module>transfers-server</module>
+    </modules>
+
+</project>

+ 17 - 0
applications/transfers/transfers-api/pom.xml

@@ -0,0 +1,17 @@
+<?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>transfers</artifactId>
+        <groupId>com.usoftchina.saas</groupId>
+        <version>1.0.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.usoftchina.saas</groupId>
+    <artifactId>transfers-api</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+
+
+</project>

+ 64 - 0
applications/transfers/transfers-server/pom.xml

@@ -0,0 +1,64 @@
+<?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>transfers</artifactId>
+        <groupId>com.usoftchina.saas</groupId>
+        <version>1.0.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.usoftchina.saas</groupId>
+    <artifactId>transfers-server</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.usoftchina.saas</groupId>
+            <artifactId>server-starter</artifactId>
+        </dependency>
+        <!-- sleuth -->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-zipkin</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.amqp</groupId>
+            <artifactId>spring-rabbit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>net.logstash.logback</groupId>
+            <artifactId>logstash-logback-encoder</artifactId>
+        </dependency>
+        <!-- feign -->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+        </dependency>
+        <!-- test -->
+        <dependency>
+            <groupId>com.usoftchina.saas</groupId>
+            <artifactId>test-starter</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>com.spotify</groupId>
+                <artifactId>docker-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 17 - 0
applications/transfers/transfers-server/src/main/java/com/usoftchina/saas/transfers/TransfersApplication.java

@@ -0,0 +1,17 @@
+package com.usoftchina.saas.transfers;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+
+@SpringBootApplication
+@EnableEurekaClient
+@EnableFeignClients("com.usoftchina.saas")
+public class TransfersApplication {
+    public static void main(String[] args) {
+        SpringApplication.run(TransfersApplication.class, args);
+    }
+
+
+}

+ 65 - 0
applications/transfers/transfers-server/src/main/java/com/usoftchina/saas/transfers/config/RabbitConfig.java

@@ -0,0 +1,65 @@
+package com.usoftchina.saas.transfers.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+import java.io.Serializable;
+
+/**
+ * @Description Rabbit配置类
+ * @Author chenwei
+ * @Date 2018/12/28
+ */
+@ConfigurationProperties("spring.rabbitmq")
+public class RabbitConfig implements Serializable {
+
+//    @Value("${spring.rabbitmq.host}")
+    private String host;
+//    @Value("${spring.rabbitmq.port}")
+    private int port;
+//    @Value("${spring.rabbitmq.username}")
+    private String username;
+//    @Value("${spring.rabbitmq.password}")
+    private String password;
+//    @Value("${spring.rabbitmq.virtual-host}")
+    private String virtualHost;
+
+    public String getHost() {
+        return host;
+    }
+
+    public void setHost(String host) {
+        this.host = host;
+    }
+
+    public int getPort() {
+        return port;
+    }
+
+    public void setPort(int port) {
+        this.port = port;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getVirtualHost() {
+        return virtualHost;
+    }
+
+    public void setVirtualHost(String virtualHost) {
+        this.virtualHost = virtualHost;
+    }
+}

+ 106 - 0
applications/transfers/transfers-server/src/main/java/com/usoftchina/saas/transfers/po/MessageInfo.java

@@ -0,0 +1,106 @@
+package com.usoftchina.saas.transfers.po;
+
+import java.io.Serializable;
+
+/**
+ * @Description 消息内容
+ * @Author chenwei
+ * @Date 2018/12/27
+ */
+public class MessageInfo implements Serializable {
+    /**
+     * 消息ID
+     */
+    private String msgId;
+    /**
+     * 用户ID
+     */
+    private String userId;
+    /**
+     * 应用ID
+     */
+    private String appId;
+    /**
+     * 业务类型
+     */
+    private String bizType;
+    /**
+     * 业务单据ID
+     */
+    private String bizId;
+    /**
+     * 时间戳
+     */
+    private long timestamp;
+    /**
+     * 重试次数
+     */
+    private int retryCount;
+
+    public String getMsgId() {
+        return msgId;
+    }
+
+    public void setMsgId(String msgId) {
+        this.msgId = msgId;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    public String getAppId() {
+        return appId;
+    }
+
+    public void setAppId(String appId) {
+        this.appId = appId;
+    }
+
+    public String getBizType() {
+        return bizType;
+    }
+
+    public void setBizType(String bizType) {
+        this.bizType = bizType;
+    }
+
+    public String getBizId() {
+        return bizId;
+    }
+
+    public void setBizId(String bizId) {
+        this.bizId = bizId;
+    }
+
+    public long getTimestamp() {
+        return timestamp;
+    }
+
+    public void setTimestamp(long timestamp) {
+        this.timestamp = timestamp;
+    }
+
+    public int getRetryCount() {
+        return retryCount;
+    }
+
+    public void setRetryCount(int retryCount) {
+        this.retryCount = retryCount;
+    }
+
+    public MessageInfo(String userId, String appId, String bizType, String bizId) {
+        this.userId = userId;
+        this.appId = appId;
+        this.bizType = bizType;
+        this.bizId = bizId;
+    }
+
+    public MessageInfo() {
+
+    }
+}

+ 261 - 0
applications/transfers/transfers-server/src/main/java/com/usoftchina/saas/transfers/service/BaseRabbitReceiveService.java

@@ -0,0 +1,261 @@
+package com.usoftchina.saas.transfers.service;
+
+import com.rabbitmq.client.AMQP;
+import com.rabbitmq.client.Channel;
+import com.usoftchina.saas.transfers.po.MessageInfo;
+import com.usoftchina.saas.utils.JsonUtils;
+import com.usoftchina.saas.utils.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.amqp.core.AcknowledgeMode;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.rabbit.annotation.RabbitHandler;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
+import org.springframework.amqp.rabbit.connection.ConnectionFactory;
+import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener;
+import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
+import org.springframework.amqp.support.AmqpHeaders;
+import org.springframework.context.annotation.Bean;
+import org.springframework.core.annotation.AnnotationConfigurationException;
+import org.springframework.messaging.handler.annotation.Headers;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Description RabbitMq 消息接收处理基类
+ * @Author chenwei
+ * @Date 2018/12/27
+ */
+public abstract class BaseRabbitReceiveService implements ChannelAwareMessageListener {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(BaseRabbitReceiveService.class);
+    private static final String DELAY_QUEUE_NAME_SUFFIX = "_delay";
+
+    protected boolean isDynamicCreate = false;
+    protected String host;
+    protected int port;
+    protected String virtualHost;
+    protected String username;
+    protected String password;
+    protected String queueName;
+    //延时时间,单位:毫秒
+    protected String delayTime = "60000";
+    //心跳时间,单位秒
+    protected int requestedHeartBeat = 30;
+    protected String delayQueueName;
+
+    /**
+     * 初始化连接
+     * @return
+     */
+    private ConnectionFactory initConnectionFactory(){
+        if (StringUtils.isEmpty(host)) {
+            throw new IllegalArgumentException("host为空");
+        }
+        if (port <= 0) {
+            throw new IllegalArgumentException("port小于等于0");
+        }
+        if (StringUtils.isEmpty(virtualHost)) {
+            throw new IllegalArgumentException("virtualHost为空");
+        }
+        if (StringUtils.isEmpty(username)) {
+            throw new IllegalArgumentException("username为空");
+        }
+        if (StringUtils.isEmpty(password)) {
+            throw new IllegalArgumentException("password为空");
+        }
+        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
+        connectionFactory.setHost(host);
+        connectionFactory.setPort(port);
+        connectionFactory.setVirtualHost(virtualHost);
+        connectionFactory.setUsername(username);
+        connectionFactory.setPassword(password);
+        connectionFactory.setRequestedHeartBeat(requestedHeartBeat);
+        return connectionFactory;
+    }
+
+    /**
+     * 动态创建消息监听
+     * @return
+     */
+    @Bean
+    protected SimpleMessageListenerContainer simpleMessageListenerContainer(){
+        if (!isDynamicCreate){
+            return null;
+        }
+        if (this.getClass().isAnnotationPresent(RabbitListener.class)){
+            throw new AnnotationConfigurationException("动态创建时,不能配置@RabbitListener注解");
+        }
+        if (StringUtils.isEmpty(queueName)){
+            throw new IllegalArgumentException("queueName为空");
+        }
+        ConnectionFactory connectionFactory = initConnectionFactory();
+        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
+        container.setQueueNames(queueName);
+        //设置手动应答
+        container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
+        //使用ChannelAwareMessageListener接口,必须实现OnMessage方法
+        container.setMessageListener(this);
+        return container;
+    }
+
+    @Override
+    public void onMessage(Message message, Channel channel) {
+        String messageJson = new String(message.getBody());
+        long tag = message.getMessageProperties().getDeliveryTag();
+        String queueName = message.getMessageProperties().getConsumerQueue();
+        processMessage(messageJson, channel, tag, queueName);
+    }
+
+    /**
+     * 接收消息处理
+     * @param messageBytes
+     * @param channel
+     * @param headers
+     */
+    @RabbitHandler
+    public void receiveMessage(byte[] messageBytes, Channel channel, @Headers Map<String, Object> headers) {
+        receiveMessage(new String(messageBytes), channel, headers);
+    }
+
+    /**
+     * 接收消息处理
+     *
+     * @param messageJson
+     * @param channel
+     * @param headers
+     */
+    @RabbitHandler
+    public void receiveMessage(String messageJson, Channel channel, @Headers Map<String, Object> headers) {
+        long tag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
+        String queueName = (String) headers.get(AmqpHeaders.CONSUMER_QUEUE);
+        processMessage(messageJson, channel, tag, queueName);
+    }
+
+    /**
+     * 处理消息
+     * @param messageJson
+     * @param channel
+     * @param tag
+     * @param queueName
+     */
+    private void processMessage(String messageJson, Channel channel, long tag, String queueName) {
+        MessageInfo messageInfo = getMessageInfo(messageJson);
+        //当消息不符合格式MessageInfo格式时,丢弃消息
+        if (messageInfo == null) {
+            LOGGER.warn("接收消息处理.消息格式.异常,messageJson:{},tag:{}", messageJson, tag);
+            basicNack(channel, tag);
+            return;
+        }
+
+        try {
+            LOGGER.info("接收消息处理[BaseRabbitReceiveService.receiveMessage].处理开始,messageJson:{},tag:{}", messageJson, tag);
+            processMessage(messageInfo);
+            LOGGER.info("接收消息处理[BaseRabbitReceiveService.receiveMessage].处理结束,messageJson:{},tag:{}", messageJson, tag);
+        } catch (Exception e) {
+            LOGGER.error("接收消息处理[BaseRabbitReceiveService.receiveMessage].异常,messageJson:{},tag:{}", messageJson, tag, e);
+            //出现异常时,消息转发为延时消息
+            sendDelayMessage(messageInfo, channel, queueName);
+        } finally {
+            basicAck(channel, tag);
+        }
+    }
+
+    /**
+     * 获取消息内容
+     * @param messageJson
+     * @return
+     */
+    private MessageInfo getMessageInfo(String messageJson) {
+        MessageInfo messageInfo = null;
+        try {
+            messageInfo = JsonUtils.fromJsonString(messageJson, MessageInfo.class);
+        } catch (Exception e) {
+            LOGGER.error("获取消息内容实体[BaseRabbitReceiveService.getMessageInfo].异常,messageJson:{}", messageJson, e);
+
+        }
+        return messageInfo;
+    }
+
+    /**
+     * 发送延时消息
+     * @param messageInfo
+     * @param channel
+     * @param queueName
+     */
+    private void sendDelayMessage(MessageInfo messageInfo, Channel channel, String queueName) {
+        //重试次数+1
+        messageInfo.setRetryCount(messageInfo.getRetryCount() + 1);
+        String messageJson = JsonUtils.toJsonString(messageInfo);
+        try {
+            String dQueueName = getDelayQueueName(channel, queueName);
+            AMQP.BasicProperties.Builder builder = new AMQP.BasicProperties.Builder();
+            //设置延时时间
+            builder.expiration(delayTime);
+            channel.basicPublish("", dQueueName, builder.build(), messageJson.getBytes());
+            LOGGER.info("发送延时消息[BaseRabbitReceiveService.sendDelayMessage].正常,messageJson:{},queueName:{}", messageJson, queueName);
+        } catch (IOException e) {
+            LOGGER.error("发送延时消息[BaseRabbitReceiveService.sendDelayMessage].异常,messageJson:{},queueName:{}", messageJson, queueName, e);
+        }
+    }
+
+    /**
+     * 获取延时队列
+     * @param channel
+     * @param queueName
+     * @return
+     * @throws IOException
+     */
+    private String getDelayQueueName(Channel channel, String queueName) throws IOException {
+        if (!StringUtils.isEmpty(delayQueueName)) {
+            return delayQueueName;
+        }
+        //初始化延时队列
+        String dQueueName = queueName + DELAY_QUEUE_NAME_SUFFIX;
+        Map<String, Object> arguments = new HashMap<String, Object>(2);
+        arguments.put("x-dead-letter-exchange", "");
+        arguments.put("x-dead-letter-routing-key", queueName);
+        channel.queueDeclare(dQueueName, true, false, false, arguments);
+        delayQueueName = dQueueName;
+        return dQueueName;
+    }
+
+    /**
+     * 消息应答No
+     * @param channel
+     * @param tag
+     */
+    private void basicNack(Channel channel, long tag) {
+        try {
+            channel.basicNack(tag, false, false);
+            LOGGER.info("接收消息处理.消息应答No[BaseRabbitReceiveService.receiveMessage.basicNack].正常,tag:{}", tag);
+        } catch (IOException e) {
+            LOGGER.error("接收消息处理.消息应答No[BaseRabbitReceiveService.receiveMessage.basicNack].异常,tag:{}", tag, e);
+        }
+    }
+
+    /**
+     * 消息应答Yes
+     * @param channel
+     * @param tag
+     */
+    private void basicAck(Channel channel, long tag) {
+        try {
+            channel.basicAck(tag, false);
+            LOGGER.info("接收消息处理.消息应答Yes[BaseRabbitReceiveService.receiveMessage.basicAck].正常,tag:{}", tag);
+        } catch (IOException e) {
+            LOGGER.error("接收消息处理.消息应答Yes[BaseRabbitReceiveService.receiveMessage.basicAck].异常,tag:{}", tag, e);
+        }
+    }
+
+    /**
+     * 处理消息
+     * @param messageInfo
+     * @throws Exception
+     */
+    public abstract void processMessage(MessageInfo messageInfo) throws Exception;
+
+}

+ 68 - 0
applications/transfers/transfers-server/src/main/java/com/usoftchina/saas/transfers/service/RabbitReceiveService.java

@@ -0,0 +1,68 @@
+package com.usoftchina.saas.transfers.service;
+
+import com.usoftchina.saas.transfers.config.RabbitConfig;
+import com.usoftchina.saas.transfers.po.MessageInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+
+/**
+ * @Description 消息消费
+ * @Author chenwei
+ * @Date 2018/12/28
+ */
+@Service
+@EnableConfigurationProperties(RabbitConfig.class)
+public class RabbitReceiveService extends BaseRabbitReceiveService {
+
+    @Autowired
+    private RabbitConfig rabbitConfig;
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(RabbitReceiveService.class);
+    private static final String QUEUENAME = "saas_trade";
+
+    @PostConstruct
+    public void init(){
+        isDynamicCreate = true;
+        host = rabbitConfig.getHost();
+        port = rabbitConfig.getPort();
+        username = rabbitConfig.getUsername();
+        password = rabbitConfig.getPassword();
+        virtualHost = rabbitConfig.getVirtualHost();
+        queueName = QUEUENAME;
+    }
+
+    @Override
+    public void processMessage(MessageInfo messageInfo) throws Exception {
+        switch (messageInfo.getAppId()){
+            case "trade":
+                processMessageForReceivable(messageInfo.getBizId(), messageInfo.getBizType());
+            default:
+                throw new Exception("无法处理的消息");
+        }
+    }
+
+    private void processMessageForReceivable(String bizId, String bizType) throws Exception {
+        /*  根据不同的bizType,方案:1.调用不同的方法.    2.处理自己需要变量操作,调用同一个方法  */
+       switch (bizType){
+           case "PURCHASE":
+               /* 执行必要的操作 */
+               execute();
+               break;
+           case "PURCHASECHANGE":
+               /* 执行必要的操作 */
+               break;
+           default:
+               throw new Exception();
+       }
+    }
+
+    private void execute() throws Exception {
+        throw new Exception();
+    }
+
+}

+ 97 - 0
applications/transfers/transfers-server/src/main/java/com/usoftchina/saas/transfers/service/RabbitSendService.java

@@ -0,0 +1,97 @@
+package com.usoftchina.saas.transfers.service;
+
+import com.usoftchina.saas.transfers.po.MessageInfo;
+import com.usoftchina.saas.utils.JsonUtils;
+import com.usoftchina.saas.utils.ObjectUtils;
+import com.usoftchina.saas.utils.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.amqp.rabbit.support.CorrelationData;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import java.util.UUID;
+
+/**
+ * @Description RabbitMQ发送消息
+ * @Author chenwei
+ * @Date 2018/12/27
+ */
+@Service
+public class RabbitSendService implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnCallback {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(RabbitSendService.class);
+
+    @Autowired
+    private RabbitTemplate rabbitTemplate;
+
+    @PostConstruct
+    public void init(){
+        //如果消息没有到exchange,则confirm回调,ack=false
+        //如果消息到达exchange,则confirm回调,ack=true
+        //exchange到queue成功,则不回调return
+        //exchange到queue失败,则回调return(否则不回回调,消息就丢了)
+        rabbitTemplate.setConfirmCallback(this);
+        rabbitTemplate.setReturnCallback(this);
+    }
+
+    /**
+     *
+     * @param queueName 队列名
+     * @param userId    用户ID
+     * @param appId     应用
+     * @param bizType   业务类型
+     * @param bizId     业务ID
+     * @return  消息ID
+     */
+    public String sendMessage(String queueName, String userId, String appId, String bizType, String bizId){
+        MessageInfo messageInfo = new MessageInfo(userId, appId, bizType, bizId);
+        return sendMessage(queueName, messageInfo);
+    }
+
+    /**
+     * 发送消息
+     * @param queueName     队列名
+     * @param messageInfo   消息体
+     * @return
+     */
+    public String sendMessage(String queueName, MessageInfo messageInfo){
+        if (StringUtils.isEmpty(queueName)){
+            throw new IllegalArgumentException("QueueName(队列名)不能为空!");
+        }
+        if (ObjectUtils.isEmpty(messageInfo)){
+            throw new IllegalArgumentException("messageInfo(消息体)不能为空!");
+        }
+        //消息ID
+        messageInfo.setMsgId(UUID.randomUUID().toString());
+        //时间戳
+        messageInfo.setTimestamp(System.currentTimeMillis());
+        CorrelationData correlationData = new CorrelationData(messageInfo.getMsgId());
+        String messageJson = JsonUtils.toJsonString(messageInfo);
+        rabbitTemplate.convertAndSend(queueName, (Object) messageJson, correlationData);
+        LOGGER.info("发送消息[RabbitSendService.sendMessage].正常,queueName:{},messageInfo:{},correlationData:{}",
+                queueName, messageJson, correlationData.getId());
+        return messageInfo.getMsgId();
+    }
+
+    @Override
+    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
+        if (ack){
+            LOGGER.info("发送消息确认[RabbitSendService.confirm].正常,correlationData:{}",
+                    correlationData.getId());
+        }else {
+            LOGGER.info("发送消息确认[RabbitSendService.confirm].正常,correlationData:{}",
+                    correlationData.getId(), cause);
+        }
+    }
+
+    @Override
+    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
+        LOGGER.error("发送消息确认到达队列[RabbitSendService.returnedMessage].异常," +
+                "message:{},replyCode:{},replyText:{},exchange:{},routingKey:{}",
+                message, replyCode, replyText, exchange, routingKey);
+    }
+}

+ 63 - 0
applications/transfers/transfers-server/src/main/resources/application.yml

@@ -0,0 +1,63 @@
+spring:
+  application:
+    name: transfers-server
+  security:
+    user:
+      name: admin
+      password: select111***
+  messages:
+    basename: i18n/messages
+    encoding: UTF-8
+  rabbitmq:
+    host: 10.1.81.75
+    port: 5672
+    virtual-host: dev
+    username: saas
+    password: select123***
+  zipkin:
+    sender:
+      type: rabbit
+    locator:
+      discovery:
+        enabled: true
+  sleuth:
+    sampler:
+      probability: 1.0
+  redis:
+    host: 10.1.81.62
+    port: 6379
+management:
+  endpoints:
+    web:
+      exposure:
+        include: "*"
+  endpoint:
+    health:
+      show-details: always
+eureka:
+  instance:
+    leaseRenewalIntervalInSeconds: 10
+    health-check-url-path: /actuator/health
+    status-page-url-path: /actuator/info
+    metadata-map:
+      user.name: ${spring.security.user.name}
+      user.password: ${spring.security.user.password}
+  client:
+    registryFetchIntervalSeconds: 5
+    serviceUrl:
+      defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@10.1.81.61:8510/eureka/
+server:
+  port: 8960
+  tomcat:
+    uri-encoding: UTF-8
+info:
+  name: '@project.artifactId@'
+  description: '@project.description@'
+  version: '@project.version@'
+  spring-boot-version: '@spring.boot.version@'
+  spring-cloud-version: '@spring.cloud.version@'
+auth:
+  public-key: auth/pub.key
+ribbon:
+  ReadTimeout: 10000
+  ConnectTimeout: 10000

+ 131 - 0
applications/transfers/transfers-server/src/main/resources/logback-spring.xml

@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <include resource="org/springframework/boot/logging/logback/base.xml" />
+    <jmxConfigurator/>
+
+    <!--
+    %m
+    输出代码中指定的消息
+    %p
+    输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
+    %r
+    输出自应用启动到输出该log信息耗费的毫秒数
+    %c
+    输出所属的类目,通常就是所在类的全名
+    %t
+    输出产生该日志事件的线程名
+    %n
+    输出一个回车换行符,Windows平台为“\r\n”,Unix平台为“\n”
+    %d
+    输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},
+    输出类似:2002年10月18日 22:10:28,921
+    %l
+    输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10)
+    -->
+
+    <springProperty scope="context" name="log.path" source="logging.path" defaultValue="/var/log/saas/transfers-server"/>
+    <springProperty scope="context" name="spring.application.name" source="spring.application.name" defaultValue="transfers-server"/>
+    <springProperty scope="context" name="spring.profiles.active" source="spring.profiles.active" defaultValue="dev"/>
+    <springProperty scope="context" name="common-pattern" source="logging.common-pattern" defaultValue="%d{yyyy-MM-dd HH:mm:ss.SSS}:[%5p] [%t:%r] [%C{1}:%M:%L] --> %m%n"/>
+    <springProperty scope="context" name="log.level.console" source="logging.level.console" defaultValue="INFO"/>
+    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="192.168.0.63:5000"/>
+
+    <contextName>${spring.application.name}-${spring.profiles.active}-logback</contextName>
+
+    <appender name="CONSOLE_APPENDER" class="ch.qos.logback.core.ConsoleAppender">
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>${log.level.console}</level>
+        </filter>
+        <encoder>
+            <pattern>${common-pattern}</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="ROOT_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${log.path}/root.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${log.path}/%d{yyyy-MM}/root-%d{yyyy-MM-dd}-%i.log.gz</fileNamePattern>
+            <maxFileSize>128MB</maxFileSize>
+            <maxHistory>7</maxHistory>
+            <totalSizeCap>20GB</totalSizeCap>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${common-pattern}</pattern>
+        </encoder>
+    </appender>
+
+    <!-- Appender to log in a JSON format -->
+    <appender name="JSON_APPENDER" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
+        <destination>${log.destination}</destination>
+        <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
+            <providers>
+                <pattern>
+                    <pattern>
+                        {
+                        "severity": "%level",
+                        "service": "${spring.application.name:-}",
+                        "trace": "%X{X-B3-TraceId:-}",
+                        "span": "%X{X-B3-SpanId:-}",
+                        "parent": "%X{X-B3-ParentSpanId:-}",
+                        "exportable": "%X{X-Span-Export:-}",
+                        "pid": "${PID:-}",
+                        "thread": "%thread",
+                        "class": "%logger{40}",
+                        "rest": "%message"
+                        }
+                    </pattern>
+                </pattern>
+            </providers>
+        </encoder>
+    </appender>
+
+    <logger name="org.springframework" level="INFO"/>
+    <logger name="com.usoftchina.saas" level="INFO"/>
+
+    <springProfile name="dev">
+        <root level="INFO">
+            <appender-ref ref="CONSOLE_APPENDER"/>
+        </root>
+    </springProfile>
+
+    <springProfile name="test">
+        <root level="INFO">
+            <appender-ref ref="CONSOLE_APPENDER"/>
+            <appender-ref ref="ROOT_APPENDER"/>
+        </root>
+    </springProfile>
+
+    <springProfile name="docker">
+        <logger name="org.springframework" level="WARN"/>
+        <logger name="com.usoftchina.saas" level="WARN"/>
+        <root level="WARN">
+            <appender-ref ref="CONSOLE_APPENDER"/>
+            <appender-ref ref="JSON_APPENDER"/>
+        </root>
+    </springProfile>
+
+    <springProfile name="docker-dev">
+        <root level="INFO">
+            <appender-ref ref="CONSOLE_APPENDER"/>
+        </root>
+    </springProfile>
+
+    <springProfile name="docker-test">
+        <logger name="org.springframework" level="WARN"/>
+        <logger name="com.usoftchina.saas" level="WARN"/>
+        <root level="WARN">
+            <appender-ref ref="CONSOLE_APPENDER"/>
+            <appender-ref ref="JSON_APPENDER"/>
+        </root>
+    </springProfile>
+
+    <springProfile name="docker-prod">
+        <logger name="org.springframework" level="WARN"/>
+        <logger name="com.usoftchina.saas" level="WARN"/>
+        <root level="WARN">
+            <appender-ref ref="CONSOLE_APPENDER"/>
+            <appender-ref ref="JSON_APPENDER"/>
+        </root>
+    </springProfile>
+
+</configuration>

+ 36 - 0
applications/transfers/transfers-server/src/test/java/com/usoftchina/saas/transfers/service/RabbitSendServiceTest.java

@@ -0,0 +1,36 @@
+package com.usoftchina.saas.transfers.service;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+/**
+ * @Description 消息生成测试
+ * @Author chenwei
+ * @Date 2018/12/28
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@SpringBootTest
+@EnableAutoConfiguration
+public class RabbitSendServiceTest {
+
+    @Autowired
+    private RabbitSendService rabbitSendService;
+
+    private final String QUEUENAME = "saas_trade";
+    private final String USERID = "1";
+    private final String APPID = "trade";
+    private final String BIZTYPE = "PURCHASE";
+    private final String BIZID = "1";
+
+
+    @Test
+    public void sendMessage() throws Exception {
+        String messageId = rabbitSendService.sendMessage(QUEUENAME, USERID, APPID, BIZTYPE, BIZID);
+        System.out.println(messageId);
+    }
+
+}

+ 8 - 0
base-servers/account/account-server/src/main/java/com/usoftchina/saas/account/mapper/AccountCompanyMapper.java

@@ -81,4 +81,12 @@ public interface AccountCompanyMapper {
      * @return
      */
     int hasBind(@Param("accountId") Long accountId, @Param("companyId") Long companyId);
+
+    /**
+     * 账户公司以前绑定过,现在已解绑
+     * @param accountId
+     * @param companyId
+     * @return
+     */
+    int hasUnBindData(@Param("accountId") Long accountId, @Param("companyId") Long companyId);
 }

+ 12 - 7
base-servers/account/account-server/src/main/java/com/usoftchina/saas/account/service/impl/AccountServiceImpl.java

@@ -134,7 +134,12 @@ public class AccountServiceImpl implements AccountService {
 
     @Override
     public void bindCompany(Long accountId, Long companyId) {
-        accountCompanyMapper.insert(accountId, companyId);
+        int count = accountCompanyMapper.hasUnBindData(accountId, companyId);
+        if (count > 0) {
+            updateBindCompanyStatus(accountId, companyId, "1");
+        }else {
+            accountCompanyMapper.insert(accountId, companyId);
+        }
     }
 
     @Override
@@ -247,7 +252,7 @@ public class AccountServiceImpl implements AccountService {
         // 根据手机号、邮箱、用户名片段判断是否已注册
         boolean checked = findByUsernameOrMobileOrEmail(accountAddDTO.getUsername(), accountAddDTO.getMobile(), accountAddDTO.getEmail());
         //不存在 ——> 保存 , 存在 ——> 更新
-        addOrUpdate(checked, accountAddDTO);
+        addOrUpdate(checked, accountAddDTO, BaseContextHolder.getCompanyId());
 
         account = findByMobile(accountAddDTO.getMobile());
         //绑定企业
@@ -263,7 +268,7 @@ public class AccountServiceImpl implements AccountService {
      * @param checked
      * @param accountAddDTO
      */
-    private void addOrUpdate(boolean checked, AccountAddDTO accountAddDTO){
+    private void addOrUpdate(boolean checked, AccountAddDTO accountAddDTO, Long companyId){
         Account account = new Account();
         if (!checked) {
             account = BeanMapper.map(accountAddDTO, Account.class);
@@ -271,7 +276,7 @@ public class AccountServiceImpl implements AccountService {
             save(account);
             if (!accountAddDTO.isHasRegister()) {
                 //用户未注册优软云
-                registerAccount(accountAddDTO.getMobile(), accountAddDTO.getRealname());
+                registerAccount(accountAddDTO.getMobile(), accountAddDTO.getRealname(), companyId);
             }
         }else{
             Account accountTemp = findByMobile(accountAddDTO.getMobile());
@@ -290,10 +295,10 @@ public class AccountServiceImpl implements AccountService {
      * @param mobile
      * @param realname
      */
-    private void registerAccount(String mobile, String realname){
+    private void registerAccount(String mobile, String realname, Long companyId){
         //1.添加至优软云
         String password = StringUtils.createInitPassword(mobile.substring(mobile.length() - 3, mobile.length()));
-        Company company = companyService.findByPrimaryKey(BaseContextHolder.getCompanyId());
+        Company company = companyService.findByPrimaryKey(companyId);
         String companyName = company.getName();
 
         //可能存在开通企业时UU号同步到优软云出错的情况,再重新同步一次
@@ -364,7 +369,7 @@ public class AccountServiceImpl implements AccountService {
         }
 
         //不存在 ——> 保存 , 存在 ——> 更新
-        addOrUpdate(checked, accountAddDTO);
+        addOrUpdate(checked, accountAddDTO, companyId);
 
         Account account = findByMobile(accountAddDTO.getMobile());
         //绑定企业

+ 1 - 1
base-servers/account/account-server/src/main/resources/logback-spring.xml

@@ -28,7 +28,7 @@
     <springProperty scope="context" name="spring.profiles.active" source="spring.profiles.active" defaultValue="dev"/>
     <springProperty scope="context" name="common-pattern" source="logging.common-pattern" defaultValue="%d{yyyy-MM-dd HH:mm:ss.SSS}:[%5p] [%t:%r] [%C{1}:%M:%L] --> %m%n"/>
     <springProperty scope="context" name="log.level.console" source="logging.level.console" defaultValue="INFO"/>
-    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="192.168.0.63:5000"/>
+    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="10.1.81.1:5000"/>
 
     <contextName>${spring.application.name}-${spring.profiles.active}-logback</contextName>
 

+ 3 - 0
base-servers/account/account-server/src/main/resources/mapper/AccountCompanyMapper.xml

@@ -42,4 +42,7 @@
     <select id="hasBind" resultType="int">
         SELECT COUNT(*) FROM AC_ACCOUNT_COMPANY WHERE ACCOUNT_ID = #{accountId} AND COMPANY_ID = #{companyId} AND STATUS = 1
     </select>
+    <select id="hasUnBindData" resultType="int">
+        SELECT COUNT(*) FROM AC_ACCOUNT_COMPANY WHERE ACCOUNT_ID = #{accountId} AND COMPANY_ID = #{companyId} AND STATUS = 0
+    </select>
 </mapper>

+ 1 - 1
base-servers/admin-server/src/main/resources/logback-spring.xml

@@ -28,7 +28,7 @@
     <springProperty scope="context" name="spring.profiles.active" source="spring.profiles.active" defaultValue="dev"/>
     <springProperty scope="context" name="common-pattern" source="logging.common-pattern" defaultValue="%d{yyyy-MM-dd HH:mm:ss.SSS}:[%5p] [%t:%r] [%C{1}:%M:%L] --> %m%n"/>
     <springProperty scope="context" name="log.level.console" source="logging.level.console" defaultValue="INFO"/>
-    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="192.168.0.63:5000"/>
+    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="10.1.81.1:5000"/>
 
     <contextName>${spring.application.name}-${spring.profiles.active}-logback</contextName>
 

+ 12 - 0
base-servers/auth/auth-api/src/main/java/com/usoftchina/saas/auth/api/AuthApi.java

@@ -1,12 +1,14 @@
 package com.usoftchina.saas.auth.api;
 
 import com.usoftchina.saas.auth.common.cookie.CookieInfo;
+import com.usoftchina.saas.auth.common.jwt.JwtInfo;
 import com.usoftchina.saas.auth.dto.AuthDTO;
 import com.usoftchina.saas.auth.dto.TokenDTO;
 import com.usoftchina.saas.base.Result;
 import org.springframework.cloud.openfeign.FeignClient;
 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.RequestParam;
 
 /**
@@ -50,4 +52,14 @@ public interface AuthApi {
      */
     @PostMapping(value = "/sso/authorize")
     Result<AuthDTO> ssoAuthorize(CookieInfo info);
+
+    /**
+    * @Description 获取新token
+    * @Param: [info]
+    * @return: com.usoftchina.saas.base.Result<com.usoftchina.saas.auth.dto.TokenDTO>
+    * @Author: guq
+    * @Date: 2018/12/28
+    */
+    @PostMapping("/generateToken")
+    public Result<TokenDTO> generateToken(@RequestBody JwtInfo info);
 }

+ 7 - 1
base-servers/auth/auth-client/src/main/java/com/usoftchina/saas/auth/client/interceptor/AuthRestInterceptor.java

@@ -13,6 +13,7 @@ import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.util.Enumeration;
 
 /**
  * @author yingp
@@ -37,7 +38,12 @@ public class AuthRestInterceptor extends HandlerInterceptorAdapter {
             if (annotation != null) {
                 return super.preHandle(request, response, handler);
             }
-            String token = request.getHeader(authConfig.getAuthHeader());
+            String token = null;
+            Enumeration<String> headers = request.getHeaders(authConfig.getAuthHeader());
+            while(headers.hasMoreElements()){
+                //取最后一个元素
+                token = headers.nextElement();
+            }
             if (null != token) {
                 JwtInfo infoFromToken = JwtHelper.getInfoFromToken(token, authConfig.getPublicKey());
                 BaseContextHolder.setAppId(infoFromToken.getAppId());

+ 3 - 0
base-servers/auth/auth-common/src/main/java/com/usoftchina/saas/auth/common/jwt/JwtInfo.java

@@ -21,6 +21,9 @@ public class JwtInfo implements Serializable{
         this.realName = realName;
     }
 
+    public JwtInfo() {
+    }
+
     public JwtInfo(String appId, Long companyId, Long userId, String userName, String realName) {
         this.appId = appId;
         this.companyId = companyId;

+ 38 - 3
base-servers/auth/auth-server/src/main/java/com/usoftchina/saas/auth/controller/AuthController.java

@@ -19,6 +19,7 @@ import com.usoftchina.saas.auth.po.VirtualAuthorizeLog;
 import com.usoftchina.saas.auth.service.AuthorizeCountService;
 import com.usoftchina.saas.auth.service.AuthorizeLogService;
 import com.usoftchina.saas.base.Result;
+import com.usoftchina.saas.cache.CacheKeyHelper;
 import com.usoftchina.saas.exception.BizException;
 import com.usoftchina.saas.exception.ExceptionCode;
 import com.usoftchina.saas.page.PageDefault;
@@ -98,7 +99,6 @@ public class AuthController {
         if (authorizeCountService.isFrozen(username)) {
             return Result.error(ExceptionCode.AUTH_FROZEN);
         }
-
         Result<AccountDTO> result = accountApi.validByUsernameAndPwd(username, password);
         if (result.isSuccess()) {
             authorizeCountService.clear(username);
@@ -114,6 +114,9 @@ public class AuthController {
             JwtInfo info = new JwtInfo(appId, companyId, accountDTO.getId(), accountDTO.getUsername(), accountDTO.getRealname());
             JwtToken jwtToken = JwtHelper.generateToken(info, privateKeyPath, expire);
             TokenDTO tokenDTO = BeanMapper.map(jwtToken, TokenDTO.class);
+            //登陆成功记入redis
+            String key = CacheKeyHelper.generatePublicKey(tokenDTO.getToken());
+            RedisUtil.set(key, tokenDTO, expire);
             // 登录日志
             authorizeLogService.save(AuthorizeLog.from(request)
                     .setAccountId(accountDTO.getId())
@@ -153,6 +156,9 @@ public class AuthController {
         JwtInfo info = new JwtInfo(appId, companyId, accountDTO.getId(), accountDTO.getUsername(), accountDTO.getRealname());
         JwtToken jwtToken = JwtHelper.generateToken(info, privateKeyPath, expire);
         TokenDTO tokenDTO = BeanMapper.map(jwtToken, TokenDTO.class);
+        //登陆成功记入redis
+        String key = CacheKeyHelper.generatePublicKey(tokenDTO.getToken());
+        RedisUtil.set(key, tokenDTO, expire);
         // 登录日志
         authorizeLogService.saveVirtual(VirtualAuthorizeLog.from(request)
                 .setMobile(Long.parseLong(accountDTO.getMobile()))
@@ -207,6 +213,9 @@ public class AuthController {
             if (null != companyDTO){
                 authDTO.setCompanyId(companyDTO.getId());
             }
+            //登陆成功记入redis
+            String key = CacheKeyHelper.generatePublicKey(tokenDTO.getToken());
+            RedisUtil.set(key, authDTO, expire);
             return Result.success(authDTO);
         }
         return Result.error(ExceptionCode.COOKIE_ILLEGAL_ARGUMENT);
@@ -262,8 +271,12 @@ public class AuthController {
                 JwtInfo jwtInfo = new JwtInfo(appId, companyId, accountDTO.getId(), accountDTO.getUsername(), accountDTO.getRealname());
                 JwtToken jwtToken = JwtHelper.generateToken(jwtInfo, privateKeyPath, expire);
                 TokenDTO tokenDTO = BeanMapper.map(jwtToken, TokenDTO.class);
+                AuthDTO authDTO = new AuthDTO(tokenDTO, accountDTO);
+                //登陆成功记入redis
+                String key = CacheKeyHelper.generatePublicKey(tokenDTO.getToken());
+                RedisUtil.set(key, authDTO, expire);
                 socketMessageApi.sendToClient(new ClientMessage(clientId, "/sso/callback",
-                        JsonUtils.toJsonString(new AuthDTO(tokenDTO, accountDTO))));
+                        JsonUtils.toJsonString(authDTO)));
             }
             ServletUtils.writeJsonPMessage(response, callback, true);
         }
@@ -282,7 +295,7 @@ public class AuthController {
         copyDTO.setEmail(StringUtils.isEmpty(info.getEmail()) ? null : info.getEmail());
         copyDTO.setMobile(info.getMobile());
         copyDTO.setRealname(info.getVipName());
-        copyDTO.setType(AccountType.ADMIN.getType());
+        copyDTO.setType(AccountType.NORMAL.getType());
         copyDTO.setUu(info.getUserUU());
         Result result = accountApi.copyRegistration(copyDTO);
         if (!result.isSuccess()) {
@@ -310,6 +323,9 @@ public class AuthController {
             JwtInfo info = new JwtInfo(infoFromToken.getAppId(), companyId, infoFromToken.getUserId(),
                     infoFromToken.getUserName(), infoFromToken.getRealName());
             JwtToken jwtToken = JwtHelper.generateToken(info, privateKeyPath, expire);
+            //登陆成功记入redis
+            String key = CacheKeyHelper.generatePublicKey(jwtToken.getToken());
+            RedisUtil.set(key, info, expire);
             return Result.success(BeanMapper.map(jwtToken, TokenDTO.class));
         }
         return Result.error(ExceptionCode.COMPANY_NOT_BIND);
@@ -370,4 +386,23 @@ public class AuthController {
     public Result<PageInfo<AuthorizeLogDTO>> getLogs(@PageDefault PageRequest page) {
         return Result.success(authorizeLogService.findByPage(page));
     }
+    /**
+    * @Description 重新生成Token
+    * @Param: [info]
+    * @return: TokenDTO
+    * @Author: guq
+    * @Date: 2018/12/27
+    */
+    @PostMapping("/generateToken")
+    public Result<TokenDTO> generateToken(@RequestBody JwtInfo info) {
+        TokenDTO tokenDTO = null;
+        if (!StringUtils.isEmpty(info)) {
+            JwtToken jwtToken = JwtHelper.generateToken(info, privateKeyPath, expire);
+            tokenDTO = BeanMapper.map(jwtToken, TokenDTO.class);
+            //登陆成功记入redis
+            String key = CacheKeyHelper.generatePublicKey(jwtToken.getToken());
+            RedisUtil.set(key, info, expire);
+        }
+        return Result.success(tokenDTO);
+    }
 }

+ 1 - 1
base-servers/auth/auth-server/src/main/resources/logback-spring.xml

@@ -28,7 +28,7 @@
     <springProperty scope="context" name="spring.profiles.active" source="spring.profiles.active" defaultValue="dev"/>
     <springProperty scope="context" name="common-pattern" source="logging.common-pattern" defaultValue="%d{yyyy-MM-dd HH:mm:ss.SSS}:[%5p] [%t:%r] [%C{1}:%M:%L] --> %m%n"/>
     <springProperty scope="context" name="log.level.console" source="logging.level.console" defaultValue="INFO"/>
-    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="192.168.0.63:5000"/>
+    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="10.1.81.1:5000"/>
 
     <contextName>${spring.application.name}-${spring.profiles.active}-logback</contextName>
 

+ 1 - 1
base-servers/datacenter/datacenter-server/src/main/resources/logback-spring.xml

@@ -28,7 +28,7 @@
     <springProperty scope="context" name="spring.profiles.active" source="spring.profiles.active" defaultValue="dev"/>
     <springProperty scope="context" name="common-pattern" source="logging.common-pattern" defaultValue="%d{yyyy-MM-dd HH:mm:ss.SSS}:[%5p] [%t:%r] [%C{1}:%M:%L] --> %m%n"/>
     <springProperty scope="context" name="log.level.console" source="logging.level.console" defaultValue="INFO"/>
-    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="192.168.0.63:5000"/>
+    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="10.1.81.1:5000"/>
 
     <contextName>${spring.application.name}-${spring.profiles.active}-logback</contextName>
 

+ 1 - 1
base-servers/eureka-server/src/main/resources/logback-spring.xml

@@ -28,7 +28,7 @@
     <springProperty scope="context" name="spring.profiles.active" source="spring.profiles.active" defaultValue="dev"/>
     <springProperty scope="context" name="common-pattern" source="logging.common-pattern" defaultValue="%d{yyyy-MM-dd HH:mm:ss.SSS}:[%5p] [%t:%r] [%C{1}:%M:%L] --> %m%n"/>
     <springProperty scope="context" name="log.level.console" source="logging.level.console" defaultValue="INFO"/>
-    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="192.168.0.63:5000"/>
+    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="10.1.81.1:5000"/>
 
     <contextName>${spring.application.name}-${spring.profiles.active}-logback</contextName>
 

+ 2 - 2
base-servers/file/file-server/src/main/resources/application.yml

@@ -86,6 +86,6 @@ fdfs:
     width: 150
     height: 150
   tracker-list:
-    - 192.168.0.63:22122
+    - 10.1.81.1:22122
 file:
-  base-url: http://192.168.0.63:8888/
+  base-url: http://10.1.81.1:8888/

+ 1 - 1
base-servers/file/file-server/src/main/resources/logback-spring.xml

@@ -28,7 +28,7 @@
     <springProperty scope="context" name="spring.profiles.active" source="spring.profiles.active" defaultValue="dev"/>
     <springProperty scope="context" name="common-pattern" source="logging.common-pattern" defaultValue="%d{yyyy-MM-dd HH:mm:ss.SSS}:[%5p] [%t:%r] [%C{1}:%M:%L] --> %m%n"/>
     <springProperty scope="context" name="log.level.console" source="logging.level.console" defaultValue="INFO"/>
-    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="192.168.0.63:5000"/>
+    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="10.1.81.1:5000"/>
 
     <contextName>${spring.application.name}-${spring.profiles.active}-logback</contextName>
 

+ 9 - 0
base-servers/gateway-server/src/main/java/com/usoftchina/saas/gateway/config/AuthConfig.java

@@ -13,6 +13,15 @@ public class AuthConfig {
     private String publicKey;
     private String authHeader = "Authorization";
     private List<String> ignores;
+    private int expire;
+
+    public int getExpire() {
+        return expire;
+    }
+
+    public void setExpire(int expire) {
+        this.expire = expire;
+    }
 
     public String getPublicKey() {
         return publicKey;

+ 27 - 1
base-servers/gateway-server/src/main/java/com/usoftchina/saas/gateway/config/AuthFilter.java

@@ -12,12 +12,15 @@ import com.usoftchina.saas.auth.common.jwt.JwtInfo;
 import com.usoftchina.saas.auth.dto.AuthDTO;
 import com.usoftchina.saas.auth.dto.TokenDTO;
 import com.usoftchina.saas.base.Result;
+import com.usoftchina.saas.cache.CacheKeyHelper;
 import com.usoftchina.saas.context.BaseContextHolder;
 import com.usoftchina.saas.exception.BizException;
 import com.usoftchina.saas.exception.ExceptionCode;
 import com.usoftchina.saas.gateway.error.PermissionException;
 import com.usoftchina.saas.gateway.util.AntPathRequestMatcher;
 import com.usoftchina.saas.utils.CollectionUtils;
+import com.usoftchina.saas.utils.RedisUtil;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.cloud.gateway.filter.GatewayFilterChain;
@@ -60,7 +63,30 @@ public class AuthFilter implements GlobalFilter, Ordered {
             if (!isIgnore(exchange.getRequest())) {
                 // 鉴别身份信息
                 String token = getAuthToken(exchange.getRequest());
-                JwtInfo jwt = JwtHelper.getInfoFromToken(token, authConfig.getPublicKey());
+                String key = CacheKeyHelper.generatePublicKey(token);
+                //刷新时间
+                RedisUtil.expire(key, authConfig.getExpire());
+                JwtInfo jwt = null;
+                try {
+                    jwt = JwtHelper.getInfoFromToken(token, authConfig.getPublicKey());
+                } catch (BizException e) {
+                    if (ExceptionCode.JWT_TOKEN_EXPIRED.getCode() == e.getCode()) {
+                        jwt = (JwtInfo)RedisUtil.get(key);
+                        if (jwt == null) {
+                            throw new BizException(ExceptionCode.JWT_TOKEN_EXPIRED.getCode(), ExceptionCode.JWT_TOKEN_EXPIRED.getMessage());
+                        }
+                        Result<TokenDTO> result = authApi.generateToken(jwt);
+                        if (result.isSuccess() && null != result.getData()) {
+                            token = result.getData().getToken();
+                            //返回前端处理
+                            exchange.getResponse().getHeaders().add(authConfig.getAuthHeader(), token);
+                            //向headers中放token,记得build
+                            ServerHttpRequest request = exchange.getRequest().mutate().header(authConfig.getAuthHeader(), token).build();
+                            //将现在的request 变成 change对象
+                            exchange = exchange.mutate().request(request).build();
+                        }
+                    }
+                }
                 BaseContextHolder.setAppId(jwt.getAppId());
                 BaseContextHolder.setUserId(jwt.getUserId());
                 BaseContextHolder.setCompanyId(jwt.getCompanyId());

+ 1 - 0
base-servers/gateway-server/src/main/resources/application.yml

@@ -177,6 +177,7 @@ info:
 auth:
   auth-header: Authorization
   public-key: auth/pub.key
+  expire: 18000
   ignores:
     - /api/auth/authorize
     - /api/auth/virtual/authorize/**

+ 1 - 1
base-servers/gateway-server/src/main/resources/logback-spring.xml

@@ -28,7 +28,7 @@
     <springProperty scope="context" name="spring.profiles.active" source="spring.profiles.active" defaultValue="dev"/>
     <springProperty scope="context" name="common-pattern" source="logging.common-pattern" defaultValue="%d{yyyy-MM-dd HH:mm:ss.SSS}:[%5p] [%t:%r] [%C{1}:%M:%L] --> %m%n"/>
     <springProperty scope="context" name="log.level.console" source="logging.level.console" defaultValue="INFO"/>
-    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="192.168.0.63:5000"/>
+    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="10.1.81.1:5000"/>
 
     <contextName>${spring.application.name}-${spring.profiles.active}-logback</contextName>
 

+ 1 - 1
base-servers/mail/mail-server/src/main/resources/logback-spring.xml

@@ -28,7 +28,7 @@
     <springProperty scope="context" name="spring.profiles.active" source="spring.profiles.active" defaultValue="dev"/>
     <springProperty scope="context" name="common-pattern" source="logging.common-pattern" defaultValue="%d{yyyy-MM-dd HH:mm:ss.SSS}:[%5p] [%t:%r] [%C{1}:%M:%L] --> %m%n"/>
     <springProperty scope="context" name="log.level.console" source="logging.level.console" defaultValue="INFO"/>
-    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="192.168.0.63:5000"/>
+    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="10.1.81.1:5000"/>
 
     <contextName>${spring.application.name}-${spring.profiles.active}-logback</contextName>
 

+ 1 - 1
base-servers/sms/sms-server/src/main/resources/logback-spring.xml

@@ -28,7 +28,7 @@
     <springProperty scope="context" name="spring.profiles.active" source="spring.profiles.active" defaultValue="dev"/>
     <springProperty scope="context" name="common-pattern" source="logging.common-pattern" defaultValue="%d{yyyy-MM-dd HH:mm:ss.SSS}:[%5p] [%t:%r] [%C{1}:%M:%L] --> %m%n"/>
     <springProperty scope="context" name="log.level.console" source="logging.level.console" defaultValue="INFO"/>
-    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="192.168.0.63:5000"/>
+    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="10.1.81.1:5000"/>
 
     <contextName>${spring.application.name}-${spring.profiles.active}-logback</contextName>
 

+ 1 - 1
base-servers/socket/socket-server/src/main/resources/logback-spring.xml

@@ -28,7 +28,7 @@
     <springProperty scope="context" name="spring.profiles.active" source="spring.profiles.active" defaultValue="dev"/>
     <springProperty scope="context" name="common-pattern" source="logging.common-pattern" defaultValue="%d{yyyy-MM-dd HH:mm:ss.SSS}:[%5p] [%t:%r] [%C{1}:%M:%L] --> %m%n"/>
     <springProperty scope="context" name="log.level.console" source="logging.level.console" defaultValue="INFO"/>
-    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="192.168.0.63:5000"/>
+    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="10.1.81.1:5000"/>
 
     <contextName>${spring.application.name}-${spring.profiles.active}-logback</contextName>
 

+ 36 - 0
base-servers/ui-server/src/main/java/com/usoftchina/saas/ui/controller/CustomizeController.java

@@ -0,0 +1,36 @@
+package com.usoftchina.saas.ui.controller;
+
+import com.usoftchina.saas.base.Result;
+import com.usoftchina.saas.ui.po.Config;
+import com.usoftchina.saas.ui.service.CustomizeService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+/**自定义字段的处理
+ * @author: guq
+ * @create: 2018-12-26 14:46
+ **/
+@RestController
+@RequestMapping("/customize")
+public class CustomizeController {
+
+    @Autowired
+    private CustomizeService customizeService;
+
+    @GetMapping("/getConfig")
+    public Result getConfig(String name) {
+        return Result.success(customizeService.getConfig(name));
+    }
+
+    @PostMapping("/saveConfig")
+    public Result saveConfig(@RequestBody Config config) {
+        customizeService.save(config);
+        return Result.success();
+    }
+
+    @PostMapping("/deleteConfig")
+    public Result deleteConfig(@RequestParam("name") String name) {
+        customizeService.delete(name);
+        return Result.success();
+    }
+}

+ 77 - 0
base-servers/ui-server/src/main/java/com/usoftchina/saas/ui/po/Config.java

@@ -0,0 +1,77 @@
+package com.usoftchina.saas.ui.po;
+
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.index.Indexed;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @author: guq
+ * @create: 2018-12-26 15:13
+ **/
+@Document(collection = "customize_config")
+public class Config implements Serializable{
+    @Id
+    private String _id;
+    @Indexed(name = "customize_config_index")
+    private String name;
+    private String content;
+    private String position;
+    private Date createTime;
+    @Indexed(name = "customize_config_conpany_index")
+    private Long companyId;
+
+    public String get_id() {
+        return _id;
+    }
+
+
+    public void set_id(String _id) {
+
+        this._id = _id;
+    }
+
+    public Long getCompanyId() {
+        return companyId;
+    }
+
+    public void setCompanyId(Long companyId) {
+        this.companyId = companyId;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    public String getPosition() {
+        return position;
+    }
+
+    public void setPosition(String position) {
+        this.position = position;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+
+}

+ 38 - 0
base-servers/ui-server/src/main/java/com/usoftchina/saas/ui/repository/CustomizeRepository.java

@@ -0,0 +1,38 @@
+package com.usoftchina.saas.ui.repository;
+
+import com.usoftchina.saas.ui.po.Config;
+import org.springframework.data.mongodb.repository.MongoRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface CustomizeRepository extends MongoRepository<Config, String> {
+
+    /**
+    * @Description 添加配置
+    * @Param: [name, companyId]
+    * @return: java.util.List<com.usoftchina.saas.ui.po.Config>
+    * @Author: guq
+    * @Date: 2018/12/26
+    */
+    List<Config> findByNameAndCompanyId(String name, Long companyId);
+
+    /**
+    * @Description 删除配置
+    * @Param: [name, companyId]
+    * @return: void
+    * @Author: guq
+    * @Date: 2018/12/26
+    */
+    void deleteConfigByNameAndCompanyId(String name, Long companyId);
+
+    /**
+    * @Description 删除重复配置
+    * @Param: [name, position, companyId]
+    * @return: void
+    * @Author: guq
+    * @Date: 2018/12/27
+    */
+    void deleteConfigByNameAndPositionAndCompanyId(String name, String position, Long companyId);
+}

+ 51 - 0
base-servers/ui-server/src/main/java/com/usoftchina/saas/ui/service/CustomizeService.java

@@ -0,0 +1,51 @@
+package com.usoftchina.saas.ui.service;
+
+import com.usoftchina.saas.context.BaseContextHolder;
+import com.usoftchina.saas.ui.po.Config;
+import com.usoftchina.saas.ui.repository.CustomizeRepository;
+import com.usoftchina.saas.utils.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author: guq
+ * @create: 2018-12-26 16:07
+ **/
+@Service
+public class CustomizeService {
+
+    @Autowired
+    private CustomizeRepository customizeRepository;
+
+    @Cacheable(value = "customizeConfig", key = "#name")
+    public List<Config> getConfig(String name) {
+        if (StringUtils.isEmpty(name)) {
+            return null;
+        }
+        Long companyId = BaseContextHolder.getCompanyId();
+        return customizeRepository.findByNameAndCompanyId(name, companyId);
+    }
+
+    @CacheEvict(value = "customizeConfig", key = "#config.name")
+    public void save(Config config) {
+        if (!StringUtils.isEmpty(config)) {
+            customizeRepository.deleteConfigByNameAndPositionAndCompanyId(config.getName(), config.getPosition(),
+                    BaseContextHolder.getCompanyId());
+            config.setCompanyId(BaseContextHolder.getCompanyId());
+            config.setCreateTime(new Date());
+            customizeRepository.save(config);
+        }
+    }
+
+    @CacheEvict(value = "customizeConfig", key = "#name")
+    public void delete(String name) {
+        if (!StringUtils.isEmpty(name)) {
+            customizeRepository.deleteConfigByNameAndCompanyId(name, BaseContextHolder.getCompanyId());
+        }
+    }
+}

+ 13 - 0
base-servers/ui-server/src/main/resources/config/application-dev.yml

@@ -0,0 +1,13 @@
+eureka:
+  instance:
+    leaseRenewalIntervalInSeconds: 10
+    health-check-url-path: /actuator/health
+    status-page-url-path: /actuator/info
+    prefer-ip-address: true
+    metadata-map:
+      user.name: ${spring.security.user.name}
+      user.password: ${spring.security.user.password}
+  client:
+    registryFetchIntervalSeconds: 5
+    serviceUrl:
+      defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@127.0.0.1:8500/eureka/

+ 1 - 1
base-servers/ui-server/src/main/resources/logback-spring.xml

@@ -28,7 +28,7 @@
     <springProperty scope="context" name="spring.profiles.active" source="spring.profiles.active" defaultValue="dev"/>
     <springProperty scope="context" name="common-pattern" source="logging.common-pattern" defaultValue="%d{yyyy-MM-dd HH:mm:ss.SSS}:[%5p] [%t:%r] [%C{1}:%M:%L] --> %m%n"/>
     <springProperty scope="context" name="log.level.console" source="logging.level.console" defaultValue="INFO"/>
-    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="192.168.0.63:5000"/>
+    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="10.1.81.1:5000"/>
 
     <contextName>${spring.application.name}-${spring.profiles.active}-logback</contextName>
 

+ 1 - 1
base-servers/zipkin-server/src/main/resources/application.yml

@@ -41,7 +41,7 @@ zipkin:
   storage:
     type: elasticsearch
     elasticsearch:
-      hosts: 192.168.0.63:9200
+      hosts: 10.1.81.1:9200
       index: zipkin
       index-shards: 5
       index-replicas: 1

+ 1 - 1
base-servers/zipkin-server/src/main/resources/logback-spring.xml

@@ -28,7 +28,7 @@
     <springProperty scope="context" name="spring.profiles.active" source="spring.profiles.active" defaultValue="dev"/>
     <springProperty scope="context" name="common-pattern" source="logging.common-pattern" defaultValue="%d{yyyy-MM-dd HH:mm:ss.SSS}:[%5p] [%t:%r] [%C{1}:%M:%L] --> %m%n"/>
     <springProperty scope="context" name="log.level.console" source="logging.level.console" defaultValue="INFO"/>
-    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="192.168.0.63:5000"/>
+    <springProperty scope="context" name="log.destination" source="logging.destination" defaultValue="10.1.81.1:5000"/>
 
     <contextName>${spring.application.name}-${spring.profiles.active}-logback</contextName>
 

+ 42 - 0
framework/core/src/main/java/com/usoftchina/saas/cache/RedisConfig.java

@@ -0,0 +1,42 @@
+package com.usoftchina.saas.cache;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+/**
+ * @author: guq
+ * @create: 2018-12-27 10:32
+ **/
+@Configuration
+public class RedisConfig {
+
+    @Bean
+    @SuppressWarnings("all")
+    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
+        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
+        template.setConnectionFactory(factory);
+        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
+        ObjectMapper om = new ObjectMapper();
+        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+        jackson2JsonRedisSerializer.setObjectMapper(om);
+        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
+        // key采用String的序列化方式
+        template.setKeySerializer(stringRedisSerializer);
+        // hash的key也采用String的序列化方式
+        template.setHashKeySerializer(stringRedisSerializer);
+        // value序列化方式采用jackson
+        template.setValueSerializer(jackson2JsonRedisSerializer);
+        // hash的value序列化方式采用jackson
+        template.setHashValueSerializer(jackson2JsonRedisSerializer);
+        template.afterPropertiesSet();
+        return template;
+    }
+}

+ 7 - 7
framework/core/src/main/java/com/usoftchina/saas/exception/ExceptionCode.java

@@ -31,10 +31,10 @@ public enum ExceptionCode implements BaseExceptionCode {
 
     // 账户管理相关
     COMPANY_NAME_EXIST(52000, "公司名称已注册"),
-    COMPANY_NAME_HASREGISTER(52000, "企业已开通saas,请联系管理员 %s 将您添加至企业"),
+    COMPANY_NAME_HASREGISTER(52000, "企业已开通saas服务,请联系管理员 %s 将您添加至企业"),
     COMPANY_CODE_EXIST(52001, "公司商业登记证号已注册"),
     COMPANY_DOMAIN_EXIST(52002, "域名已存在"),
-    COMPANY_NOT_EXIST(52003, "公司不存在"),
+    COMPANY_NOT_EXIST(52003, "企业不存在"),
     COMPANY_NOT_BIND(52004, "未绑定该公司"),
     USER_NAME_EXIST(53000, "用户名已注册"),
     USER_MOBILE_EXIST(53001, "手机号已注册"),
@@ -45,11 +45,11 @@ public enum ExceptionCode implements BaseExceptionCode {
     USER_NOT_ENABLE(53006, "用户禁止使用"),
     ROLE_NOT_EXIST(53020, "角色不存在"),
     MISSING_PERMISSIONS(53030, "权限缺失"),
-    USER_COMPANY_EXIST(53007, "企业已存在账户"),
-    ROLE_HAS_USE(54030, "存在已使用该角色的账户,不允许删除"),
-    APPLY_DOING_EXIST(54031, "已存在待处理的加入申请"),
-    HAS_BIND_COMPANY(54032, "已加入企业"),
-    SMS_VALIDCODE_EXPIRE(54033, "短信验证码已过期"),
+    USER_COMPANY_EXIST(53007, "该账户已在企业服务中"),
+    ROLE_HAS_USE(54030, "该角色已有账户使用,不允许删除"),
+    APPLY_DOING_EXIST(54031, "您已申请加入此企业,管理员处理中,请勿重复申请"),
+    HAS_BIND_COMPANY(54032, "您的账户存在该企业服务中,请勿重复加入"),
+    SMS_VALIDCODE_EXPIRE(54033, "短信验证码已过期,请重新获取"),
     SMS_VALIDCODE_ERROR(54034, "短信验证码错误"),
 
     // 文件相关

+ 154 - 0
framework/core/src/main/java/com/usoftchina/saas/utils/RedisUtil.java

@@ -0,0 +1,154 @@
+package com.usoftchina.saas.utils;
+
+import com.usoftchina.saas.context.SpringContextHolder;
+import org.springframework.data.redis.core.RedisTemplate;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author: guq
+ * @create: 2018-12-27 10:39
+ **/
+public class RedisUtil {
+
+
+    private static RedisTemplate<String, Object> redisTemplate = SpringContextHolder.getBean("redisTemplate", RedisTemplate.class);
+
+    /**
+     * 指定缓存失效时间
+     * @param key 键
+     * @param time 时间(秒)
+     * @return
+     */
+    public static boolean expire(String key, long time) {
+        try {
+            if (time > 0) {
+                redisTemplate.expire(key, time, TimeUnit.SECONDS);
+            }
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 根据key 获取过期时间
+     * @param key 键 不能为null
+     * @return 时间(秒) 返回0代表为永久有效
+     */
+    public static long getExpire(String key) {
+        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
+    }
+
+    /**
+    * @Description 判断key是否存在
+    * @Param: [key]
+    * @return: boolean
+    * @Author: guq
+    * @Date: 2018/12/27
+    */
+    public static boolean hasKey(String key) {
+        try {
+            return redisTemplate.hasKey(key);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+    * @Description 删除缓存
+    * @Param: [keys]
+    * @return: void
+    * @Author: guq
+    * @Date: 2018/12/27
+    */
+    @SuppressWarnings("unchecked")
+    public static void del(String... keys) {
+        if (null != keys && keys.length > 0) {
+            if (keys.length == 1) {
+                redisTemplate.delete(keys[0]);
+            } else {
+                redisTemplate.delete(CollectionUtils.arrayToList(keys));
+            }
+        }
+    }
+
+    /**
+    * @Description 获取key
+    * @Param: [key]
+    * @return: java.lang.Object
+    * @Author: guq
+    * @Date: 2018/12/27
+    */
+    public static Object get(String key) {
+        return key == null ? null : redisTemplate.opsForValue().get(key);
+    }
+
+    /**
+    * @Description 放入缓存
+    * @Param: [key, obj]
+    * @return: boolean
+    * @Author: guq
+    * @Date: 2018/12/27
+    */
+    public static boolean set(String key, Object obj) {
+        try {
+            redisTemplate.opsForValue().set(key, obj);
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    /**
+    * @Description 添加时间
+    * @Param: [key, value, time]
+    * @return: boolean
+    * @Author: guq
+    * @Date: 2018/12/27
+    */
+    public static boolean set(String key, Object value, long time) {
+        try {
+            if (time > 0) {
+                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
+            } else {
+                set(key, value);
+            }
+            return true;
+        }catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+    * @Description 要增加delta
+    * @Param: [key, delta]
+    * @return: long
+    * @Author: guq
+    * @Date: 2018/12/27
+    */
+    public long incr(String key, long delta) {
+        if (delta < 0) {
+            throw new RuntimeException("递增因子必须大于0");
+        }
+        return redisTemplate.opsForValue().increment(key, delta);
+    }
+
+
+    /**
+     * @Description 要减少delta
+     * @Param: [key, delta]
+     * @return: long
+     * @Author: guq
+     * @Date: 2018/12/27
+     */
+    public long decr(String key, long delta) {
+        if (delta < 0) {
+            throw new RuntimeException("递减因子必须大于0");
+        }
+        return redisTemplate.opsForValue().increment(key, -delta);
+    }
+}

+ 65 - 45
frontend/saas-portal-web/src/components/conenter/addenterprise.vue

@@ -20,7 +20,7 @@
                         </li>
                         <li>
                             <span class="qy-biaoti">所属行业</span>
-                            <select @change="industry" ref="qyindustry" class="industry border" style="padding-left:5px" name="selectAge" id="selectAge">   
+                            <select @change="industry" @click="colors" ref="qyindustry" class="industry border" style="padding-left:5px;color: #BCC8D8;" name="selectAge" id="selectAge">    
                                 <option value="" disabled selected hidden>请选择所属行业</option>
                                 <option value="贸易零售">贸易零售</option>
                                 <option value="制造加工">制造加工</option>
@@ -75,7 +75,7 @@
                     <ul style="padding:0;position: relative;">
                         <li>
                             <span class="qy-biaoti"><span class="xingxing marght">*</span>查找企业</span>
-                            <input @input="Testingqyname" @focus="Testingqyname" @blur="showwarning" ref="lookupqyname" class="inpind" :class= "{showborder:isgsname}" type="text"  placeholder="输入企业名称或管理员">
+                            <input @click.stop @input="Testingqyname" @focus="Testingqyname" @blur="showwarning" ref="lookupqyname" class="inpind" :class= "{showborder:isgsname}" type="text"  placeholder="输入企业名称或管理员">
                             <span v-show="iswarning" class="warning" ref="warningqyname"></span>
                         </li>
                         <!-- 匹配企业后显示的内容 -->
@@ -154,6 +154,7 @@ import { setTimeout, clearTimeout } from 'timers';
                 isqyaddress:false,//地址
                 isyzusername:false,
                 isheidemail:false,
+                iscompanyname:false,
             }
         },
         components:{
@@ -176,6 +177,9 @@ import { setTimeout, clearTimeout } from 'timers';
             tabwatch(i){
                 this.nowindex = i;
             },
+            colors(){
+                this.$refs.qyindustry.style.color = 'black'
+            },
             // 行业
             industry(){
                 this.$refs.qyindustry.style.border = '1px solid #1E88F5'
@@ -224,11 +228,11 @@ import { setTimeout, clearTimeout } from 'timers';
                 this.isqyname1 = false;
             },
             showqyname1(){
-                this.isqyname1 = true;
                 let qyname = this.$refs.qyname.value.replace(/\s+/g, "");//公司名字过滤空格
                 if(qyname == ''){
                     this.$refs.qyno.innerHTML = ' <img style="width:14px" src="/static/img/warning.png" alt=""> 企业名称不能为空';
-                }
+                };
+                this.isqyname1 = true;
             },
             //检测企业名称2
             Testingqyname(){
@@ -260,7 +264,7 @@ import { setTimeout, clearTimeout } from 'timers';
                                 this.companyId = null;
                                 this.isgsname = true;//公司是否存在
                             } else if (res.data.success == false && res.data.message == '公司不存在') {
-                                this.$refs.warningqyname.innerHTML = '<img style="width:14px" src="/static/img/warning.png" alt=""> 企业不存在';
+                                this.$refs.warningqyname.innerHTML = '<img style="width:14px" src="/static/img/warning.png" alt=""> 企业或管理员不存在';
                                 this.islookup = false;
                                 this.isgsname = false;//公司是否存在 
                             } else {
@@ -274,7 +278,15 @@ import { setTimeout, clearTimeout } from 'timers';
             },
             //企业名称2提示语显示
             showwarning(){
-                this.iswarning = true;
+                let qyname = this.$refs.lookupqyname.value.replace(/\s+/g, "");//企业名字
+                if (!this.companyId && qyname!='') {
+                    this.$refs.warningqyname.innerHTML = '<img style="width:14px" src="/static/img/warning.png" alt=""> 请选择要加入的企业';
+                } else {
+                    this.$refs.warningqyname.innerHTML = '<img style="width:14px" src="/static/img/ok.png" alt="">'
+                }
+                setTimeout(()=>{
+                    this.iswarning = true;
+                },100)
             },
             //验证个人姓名1
             yzusername(){
@@ -315,19 +327,28 @@ import { setTimeout, clearTimeout } from 'timers';
                     }
                 }
             },
-            //个人姓名2提示语显示
+            //个人姓名2提示语隐藏
             showTestname(){
                 this.isTestname = false;
             },
             // 选择要加入的企业
             qylist(i){
-                this.companyId = this.arr[i].id,
-                this.admin = this.arr[i].admin,
-                this.newindex = i,
-                this.$refs.lookupqyname.value = this.arr[i].name,
+                let companyName = JSON.parse(window.sessionStorage.getItem("companyname"));
+                this.companyId = this.arr[i].id;
+                this.admin = this.arr[i].admin;
+                this.newindex = i;
+                this.$refs.lookupqyname.value = this.arr[i].name;
                 this.islookup = false;
-                if (this.admin == this.mytoken.account.realname) {
-                    this.$refs.warningqyname.innerHTML = '<img style="width:14px" src="/static/img/warning.png" alt=""> 账号已在企业服务中,不能重复加入';
+                for (let j = 0; j < companyName.length; j++) {
+                    if (this.arr[i].name == companyName[j]) {
+                        this.iscompanyname = true
+                        break
+                    } else {
+                        this.iscompanyname = false
+                    }
+                }
+                if (this.iscompanyname || this.admin == this.mytoken.account.realname) {
+                    this.$refs.warningqyname.innerHTML = '<img style="width:14px" src="/static/img/warning.png" alt=""> 您的账户已在企业服务中,请勿重复加入';
                 } else {
                     this.$refs.warningqyname.innerHTML = '<img style="width:14px" src="/static/img/ok.png" alt="">';
                     // this.$refs.lookupqyname.style.border = '1px solid #1E88F5';
@@ -345,42 +366,42 @@ import { setTimeout, clearTimeout } from 'timers';
                 if (qyname == '') {
                     this.$message.error('企业或管理员不能为空');
                 } else if(!this.isgsname) {
-                    this.$message.error('该企业不存在');
+                    this.$message.error('企业或管理员不存在');
+                } else if (!this.companyId) {
+                    this.$message.error('请选择要加入的企业');
+                } else if (this.admin == this.mytoken.account.realname || this.iscompanyname) {
+                    this.$message.error('您的账户已在企业服务中,请勿重复加入');
                 } else if (!this.isTestingname) {
                     this.$message.error('姓名不能为空');
                 } else if (!this.isregname) {
                     this.$message.error('姓名不能包含符号、数字等非法字符');
-                } else if (this.companyId){
-                    if (this.admin == this.mytoken.account.realname) {
-                        this.$message.error('账号已在企业服务中,不能重复加入');
-                    } else {
-                        this.$ajax({
-                            url: this.$url.api+'/api/account/accountCenter/company/join',
-                            method:'POST',
-                            data:{
-                                username:username,
-                                accountId:this.mytoken.account.id,
-                                companyId:this.companyId,
-                            },
-                            headers:{
-                                "Authorization":token,
-                            }
-                        })
-                        .then(res=>{
-                            if (res.data.success) {
-                                this.$message.success('提交成功,待管理员批准加入');
-                                // this.$store.state.ishongdian = true;//显示红点
-                                setTimeout(()=>{
-                                    this.$router.push({name:'company'});
-                                    document.documentElement.scrollTop = 0;
-                                },3000)
-                            } else {
-                                this.$message.error(res.data.message);
-                            }
-                        })
-                    }
                 } else {
-                    this.$message.error('请选择要加入的企业');
+                    this.$store.state.isloading = true;
+                    this.$ajax({
+                        url: this.$url.api+'/api/account/accountCenter/company/join',
+                        method:'POST',
+                        data:{
+                            username:username,
+                            accountId:this.mytoken.account.id,
+                            companyId:this.companyId,
+                        },
+                        headers:{
+                            "Authorization":token,
+                        }
+                    })
+                    .then(res=>{
+                        this.$store.state.isloading = false;
+                        if (res.data.success) {
+                            this.$message.success('提交成功,待管理员批准加入');
+                            // this.$store.state.ishongdian = true;//显示红点
+                            setTimeout(()=>{
+                                this.$router.push({name:'company'});
+                                document.documentElement.scrollTop = 0;
+                            },3000)
+                        } else {
+                            this.$message.error(res.data.message);
+                        }
+                    })
                 }
             },
             //验证公司详细地址
@@ -476,7 +497,6 @@ import { setTimeout, clearTimeout } from 'timers';
                                     this.$router.push({path: '/enterprise'});
                                 },3000)
                             })
-                            this.$message.success('保存成功,待管理员批准');
                         } else {
                             this.$message.error('企业名称不能包含符号等非法字符');
                         }

+ 6 - 1
frontend/saas-portal-web/src/components/conenter/company.vue

@@ -86,7 +86,7 @@
                 <!-- 中 -->
                 <div class="gs-xqleft">
                     <!-- 点击查看企业详情 -->
-                    <p class="gs-qynema xs" @click= "getEnterpriseInfo(d)">{{d.name}}</p>
+                    <p class="gs-qynema"><span @click= "getEnterpriseInfo(d)" class="xs">{{d.name}}</span></p>
                 </div>
                 <!-- 下 -->
                 <div class="gs-xqright over">
@@ -173,7 +173,10 @@
                         this.list = res.data.data.spaces;
                         this.pagingtion(1,this.size);
                         let enterprise = [];
+                        let qyname = [];
                         for (let i = 0; i < this.list.length; i++) {
+                            qyname.push(this.list[i].name);
+                            window.sessionStorage.setItem('companyname',JSON.stringify(qyname))
                             if (this.list[i].saas_) {
                                 let addenterprise = {'id':'', 'logoUrl': '', 'name': '','dcName':''};
                                 addenterprise.id = this.list[i].id;
@@ -258,6 +261,7 @@
             },
             // 取消默认企业
             hideDefaultWin(i){
+                this.$store.state.isloading = true;
                 let token = this.mytoken.token;
                 this.$ajax({
                     url: this.$url.api+'/api/account/accountCenter/unBind/defaultCompany',
@@ -271,6 +275,7 @@
                     }
                 })
                 .then(res=>{
+                    // this.$store.state.isloading = false;
                     if (res.data.success) {
                         this.$router.go(0);
                     }

+ 22 - 9
frontend/saas-portal-web/src/components/conenter/details.vue

@@ -19,7 +19,7 @@
             </div>
             <div class="gs-worp qy-worp" style="width:100%">
                 <div class="qy-title">
-                    <span>saas服务管理员信息</span>
+                    <span>管理员信息</span>
                 </div>
                 <div class="qy-conent">
                     <ul>
@@ -48,8 +48,8 @@
                         </li>
                         <li>
                             <span class="qy-biaoti">所属行业</span>
-                            <select ref="qyindustry" class="industry border" name="selectAge" id="selectAge">   
-                                <option value="">请选择所属行业</option>
+                            <select @change="industry" ref="qyindustry" class="industry border" name="selectAge" id="selectAge">   
+                                <option value="" disabled selected hidden>请选择所属行业</option>
                                 <option value="贸易零售">贸易零售</option>
                                 <option value="制造加工">制造加工</option>
                                 <option value="服务业">服务业</option>
@@ -78,7 +78,7 @@
             </div>
             <div class="gs-worp qy-worp" style="width: 100%">
                 <div class="qy-title">
-                    <span>saas服务管理员信息</span>
+                    <span>管理员信息</span>
                 </div>
                 <div class="qy-conent">
                     <ul>
@@ -86,8 +86,8 @@
                         <li><span class="qy-biaoti">手机号</span><span>{{content.adminMobile}}</span></li>
                         <li>
                             <span class="qy-biaoti">邮<span style="width:2em;display: inline-block;"></span>箱</span>
-                            <input @change="email" ref="email" type="text" value="">
-                            <div class="qy-Tips"><span style="color:red" v-html="Email"></span></div>
+                            <input @blur="email" @focus="heidemail" ref="email" type="text" value="" :class= "{showborder:isemail}">
+                            <div v-show="isheidemail" class="qy-Tips"><span style="color:red" v-html="Email"></span></div>
                         </li>
                     </ul>
                 </div>
@@ -107,7 +107,8 @@ import Session from '@/utils/session'
                 mytoken: Session.get(),//本地储存的用户信息
                 isId: false,
                 isemail: true,//正则邮箱
-                ismodifyId: false
+                ismodifyId: false,
+                isheidemail:false,
             }
         },
         mounted(){
@@ -124,11 +125,18 @@ import Session from '@/utils/session'
                 let options = selects.options;
                 for (let i = 0; i < options.length; i++) {
                     if (options[i].innerHTML == this.content.type) {
-                        options[i].selected = true
+                        options[i].selected = true;
+                        this.$refs.qyindustry.style.border = '1px solid #1E88F5'
                     }
                 };
                 let email = this.$refs.email;
-                email.value = this.content.adminEmail;
+                if (this.content.adminEmail) {
+                    email.value = this.content.adminEmail;
+                }
+            },
+            // 行业
+            industry(){
+                this.$refs.qyindustry.style.border = '1px solid #1E88F5'
             },
             //修改企业信息
             xiugaiqiye(){
@@ -139,6 +147,7 @@ import Session from '@/utils/session'
                 },10)
             },
             email(){ //验证邮箱
+                this.isheidemail = true;
                 let reg = new RegExp("^[a-z0-9A-Z]+[- | a-z0-9A-Z . _]+@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-z]{2,}$"); 
                 let email = this.$refs.email.value;//邮箱
                 if (email == '') {
@@ -154,6 +163,10 @@ import Session from '@/utils/session'
                     }
                 }
             },
+            //邮箱提示显示
+            heidemail(){
+                this.isheidemail = false;
+            },
             // 取消修改
             quxiaoxiugai(){
                 document.documentElement.scrollTop = 0;

+ 31 - 23
frontend/saas-portal-web/src/components/conenter/enterprise.vue

@@ -82,10 +82,10 @@
                             <img src="/static/img/qiye/yonghu@2x.png" alt="">
                         </div>
                         <div class="left gr-right" style="margin-bottom: 50px;">
-                            <ul>
+                            <ul style="padding:0">
                                 <li>
                                     <span>姓名</span>
-                                    <span>{{mytoken.realname}}</span>
+                                    <span style="display: inline-block;width:200px">{{mytoken.realname}}</span>
                                     <button class="modifyname dianji" @click="modify">修改</button>
                                 </li>
                                 <li>
@@ -109,8 +109,8 @@
                             <ul>
                                 <li>
                                     <span><span class="xinghao" style="width:5px">*</span>姓名</span>
-                                    <input @change="regname" class="realname" type="text" ref="realname" :value="mytoken.realname">
-                                    <p class="usname" ref="usname"></p>
+                                    <input @blur="regname" @focus="hideregname" class="realname" type="text" ref="realname" value="">
+                                    <span v-show="isusname" class="usname" ref="usname"></span>
                                 </li>
                                 <li>
                                     <span>UU号</span><span>{{mytoken.uu}}</span>
@@ -220,6 +220,7 @@ import { setTimeout } from 'timers';
                 mobile: null,
                 ismodifyname:true,
                 isname:true,//姓名验证
+                isusname:false,
                 reg: new RegExp(/[\@\#\$\%\&\*!!\¥]/),//非法字符
                 isheigh:false,//默认高度
                 isnews: false,
@@ -372,33 +373,42 @@ import { setTimeout } from 'timers';
             },
             //修改姓名
             modify(){
-                this.ismodifyname = false
+                this.ismodifyname = false;
+                setTimeout(()=>{
+                    this.$refs.realname.value = this.mytoken.realname;
+                },10)
             },
             //取消修改姓名
             cancel(){
                 this.ismodifyname = true
             },
             regname(){
+                this.isusname = true;
                 let name = this.$refs.realname.value.replace(/\s+/g, "");
                 if (name == '') {
-                    this.$refs.usname.innerHTML = '个人姓名不能为空'
-                    this.isname = false
+                    this.$refs.usname.innerHTML = '<img style="width:14px" src="/static/img/warning.png" alt=""> 个人姓名不能为空'
+                    // this.isname = false
                 } else {
-                    this.isname = true
+                    // this.isname = true
                     if (this.reg.test(name)) {
-                        this.$refs.usname.innerHTML = '不能包含非法字符'
+                        this.$refs.usname.innerHTML = '<img style="width:14px" src="/static/img/warning.png" alt=""> 不能包含非法字符'
                         this.isname = false
                     } else {
-                        this.$refs.usname.innerHTML = ''
+                        this.$refs.usname.innerHTML = '<img style="width:14px" src="/static/img/ok.png" alt="">'
                         this.isname = true
                     }
                 }
             },
+            hideregname(){
+                this.isusname = false;
+            },
             // 保存修改姓名
             Preservation(){
-                if (this.isname) {
-                    let name = this.$refs.realname.value.replace(/\s+/g, "");
-                    let id = this.mytoken.id;
+                let name = this.$refs.realname.value.replace(/\s+/g, "");
+                let id = this.mytoken.id;
+                if (name == '') {
+                    this.$message.error('个人姓名不能为空');
+                } else if (this.isname) {
                     this.$ajax({
                         url: this.$url.api+"/api/account/account/update",
                         method :'post',
@@ -418,10 +428,9 @@ import { setTimeout } from 'timers';
                             this.$router.go(0);
                         }
                     })
-                    .catch(err=>{
-                        // console.log("请求错误",err);
-                    })
-                }
+                } else {
+                    this.$message.error('姓名不能包含非法字符');
+                } 
             },
             //ele常见问题
             handleSelect(){
@@ -503,13 +512,13 @@ import { setTimeout } from 'timers';
     background: #1E88F5 !important;
 }
 .modifyname {
-    margin-left: 80px;
+    margin-left: 20px;
     font-family: PingFangSC-Regular;
     font-size: 14px;
     color: #FFFFFF;
     letter-spacing: 0.25px;
     text-align: center;
-    padding: 5px 20px;
+    padding: 5px 30px;
     background: #1E88F5;
     border-radius: 2px;
     border: 0
@@ -534,8 +543,7 @@ import { setTimeout } from 'timers';
     padding-left: 5px;
 }
 .usname {
-    height: 0px;
-    margin-left: 85px;
+    margin-left: 10px;
     color: red;
     font-size: 12px;
 }
@@ -574,10 +582,10 @@ import { setTimeout } from 'timers';
     white-space: nowrap;
 }
 .gs-news > ul > li > span:nth-child(1) {
-    width: 58%;
+    width: 63%;
 }
 .gs-news > ul > li > span:nth-child(2) {
-    width: 20%;
+    width: 15%;
 }
 .gs-news > ul > li > span:nth-child(3) {
     width: 20%;

+ 5 - 3
frontend/saas-portal-web/src/components/conenter/failure.vue

@@ -30,6 +30,7 @@
 <style scoped>
 .failure {
     overflow: hidden;
+    margin-top: -80px;
 }
 p {
     text-align: center;
@@ -38,14 +39,15 @@ p {
 }
 .text1 {
     font-family: PingFangSC-Regular;
-    font-size: 3rem;
+    font-size: 2.5rem;
     color: #344A69;
     letter-spacing: 0;
-    top: 70%;
+    top: 60%;
+    line-height: 40px;
 }
 .text2 {
     font-family: PingFangSC-Regular;
-    font-size: 1.5rem;
+    font-size: 1.4rem;
     color: #7C93AD;
     letter-spacing: 0;
     bottom: 5%;

+ 27 - 16
frontend/saas-portal-web/src/components/conenter/home.vue

@@ -45,10 +45,8 @@
         <div class="collapse navbar-collapse navbar-right" role="navigation" style="position: absolute;left: 35%;">
           <ul @click="gohome" id="nav" class="nav navbar-nav menu">
             <li><a href="#" @click="setTurnHome"><span>首页</span></a></li>
-            <li>
-              <a href="#feature"><span>特色</span></a>
-            </li>
-            <li><a href="#service"><span>功能</span></a></li>
+            <li class="xs"><a @click="feature2"><span>特色</span></a></li>
+            <li class="xs"><a @click="service2"><span>功能</span></a></li>
             <li>
               <el-menu  
               class="el-menu-demo" 
@@ -81,7 +79,7 @@
       </div>
 
       <!-- 体验弹窗 -->
-      <div class="tiyan" v-if="isexperience">
+      <div class="tiyan" v-show="isexperience">
         <img @click="Closeexperience" class="tc-on ty-out" src="/static/img/qiye/x.png" alt="" />
         <div><img class="ty-logo" src="/static/img/assets/dalogo@2x.png" alt=""></div>
         <div class="ty-phone over">
@@ -89,7 +87,7 @@
             <span><img style="margin: 6px 8px 10px 15px;" src="/static/img/assets/phone.png" alt=""></span>
             <input ref="typhone" type="text" placeholder="请输入您的11位手机号">
           </div>
-          <div class="left" style="margin-left: 8px;"><button @click="openexperience">立即申请试用</button></div>
+          <div class="left" style="margin-left: 8px;"><button @click="openexperience">立即体验</button></div>
         </div>
         <div style="text-align: left;">
           <span class="Caution" ref="Caution"></span>
@@ -410,22 +408,21 @@
       },
       //体验
       experience(){
-        this.isexperience = true;
-        setTimeout(()=>{
-          if (this.account) {
-            this.$refs.typhone.value = this.account.mobile;
-            this.openexperience();
-          }
-        },10)
+        if (this.account) {
+          let mobile = this.account.mobile;
+          this.openexperience(mobile);
+        } else {
+          this.isexperience = true;
+        }
       },
       //关闭体验
       Closeexperience(){
         this.isexperience = false;
       },
       //进入体验
-      openexperience(){
-        let me = this
-        let phone = this.$refs.typhone.value;
+      openexperience(mobile){
+        let me = this;
+        let phone = this.$refs.typhone.value || mobile;
         let reg = new RegExp('^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\\d{8}$')
         if (phone == '') {
           this.$refs.Caution.innerHTML = '号码不能为空'
@@ -470,6 +467,20 @@
         this.$store.commit('problemfalse');
         document.documentElement.scrollTop = 0;
       },
+      //特色
+      feature2(){
+        setTimeout(()=>{
+          document.documentElement.scrollTop = 700;
+        },5);
+        this.setTurnHome();
+      },
+      //功能
+      service2(){
+        setTimeout(()=>{
+          document.documentElement.scrollTop = 3550;
+        },5);
+        this.setTurnHome();
+      },
       gohome(e){
         this.$store.commit('problemtrue')
         // this.isproblem = true

+ 170 - 38
frontend/saas-portal-web/src/components/conenter/invitation.vue

@@ -1,33 +1,52 @@
 <template>
     <div class="invitation">
+        <div class="zhezhao" v-if="istanchaung"></div>
+        <div class="Popup" v-if="istanchaung">
+        <!-- <div class="Popup"> -->
+            <div class="shang">
+                <!-- <img src="/static/img/caidian2x.png" alt=""> -->
+                <img src="/static/img/tijiao.png" alt="">
+                <img class="xs" @click="hidden" src="/static/img/assets/chahao.png" alt="">
+            </div>
+            <div class="zhong">
+                <p>欢迎你加入U企云服,立即畅享轻松工作!</p>
+                <p>新用户登录密码随后将发送短信通知请注意查收</p>
+            </div>
+            <div class="xia">
+                <button @click="gohome">立即访问</button>
+            </div>
+        </div>
+
         <img src="/static/img/beijing.png" alt="">
         <div class="centent">
-            <img src="/static/img/assets/logo@2x.png" alt="">
-            <p class="inv-logo">U企云服</p>
+            <div>
+                <img style="width:80px" src="/static/img/assets/logo@2x.png" alt="">
+                <span class="inv-logo">U企云服</span>
+            </div>
             <div class="inv-title">
                 <p>{{enterprise.username}}</p>
                 <p>
                     <span class="inv-text">邀请您加入</span>
-                    <span>{{enterprise.companyName}}</span>
-                    <span class="inv-text">SAAS服务</span>
+                    <span class="inv-text">{{enterprise.companyName}}</span>
+                    <!-- <span class="inv-text">SAAS服务</span> -->
                 </p>
             </div>
-            <input type="text" ref="phone" @blur="phone" placeholder="请输入手机号">
+            <input class="padding-left" type="text" ref="phone" @blur="phone" placeholder="请输入手机号">
             <div class="Verification">
-                <input type="text" ref="Verification" @change="validCode" placeholder="请输入验证码">
+                <input class="padding-left" type="text" ref="Verification" @change="validCode" placeholder="请输入验证码">
                 <span v-if="isobtaincode" class="xs" @click="Obtaincode">获取验证码</span>
                 <span v-if="!isobtaincode" ref="obtaincode">{{time}}</span>
             </div>
-            <input type="text" ref="name" @blur="name" placeholder="请输入姓名">
-            <select class="role" ref="role" @blur="roles">
-                <option value="">岗位角色</option>
+            <input class="padding-left" type="text" ref="name" @blur="name" placeholder="请输入姓名">
+            <select style="background-color: white;" class="role padding-left" ref="role" @blur="roles">
+                <option value="" disabled selected hidden>岗位角色</option>
                 <option v-for="(d,i) in arr" :key="i" :value=d.id>{{d.name}}</option>
             </select>
             <button class="login" @click="login">提交</button>
         </div>
         <div class="bottom">
             <p>U企云服|电子行业企业管理云端解决方案</p>
-            <p>版权所有:深圳市优软科技有限公司 Copyright @ 2017 All Rights Reserved</p>
+            <p>深圳市优软科技有限公司</p>
         </div>
     </div>
 </template>
@@ -44,26 +63,49 @@ import { setTimeout } from 'timers';
                 isregphone:false,
                 isname:false,
                 isregname:false,
-                regname:new RegExp(/[\@\#\$\%\&\*!!\¥0-9a-zA-Z]/),//非法字符加数字加英文
+                regname:new RegExp(/[\@\#\$\%\&\*!!\¥0-9]/),//非法字符加数字
                 isvalidCode:false,
                 isrole:false,
                 enterprise:[],
                 arr:[],
                 roleId:'',
                 times:'',
+                istanchaung:false,
             }
+        },
+        computed: {
+            
         },
         created(){
             this.$store.state.isinvitation = false;
-            this.param();//获取页面参数
+            this.browserRedirect();
         },
         mounted(){
-            
+            this.$store.state.isinvitation = false;
         },
         destroyed(){
             this.$store.state.isinvitation = true
         },
         methods:{
+            browserRedirect() {
+                let url1 = window.location.href;
+                let param = url1.substring(url1.lastIndexOf('=')+1, url1.length);
+                var sUserAgent = navigator.userAgent.toLowerCase();
+                var bIsIpad = sUserAgent.match(/ipad/i) == "ipad";
+                var bIsIphoneOs = sUserAgent.match(/iphone os/i) == "iphone os";
+                var bIsMidp = sUserAgent.match(/midp/i) == "midp";
+                var bIsUc7 = sUserAgent.match(/rv:1.2.3.4/i) == "rv:1.2.3.4";
+                var bIsUc = sUserAgent.match(/ucweb/i) == "ucweb";
+                var bIsAndroid = sUserAgent.match(/android/i) == "android";
+                var bIsCE = sUserAgent.match(/windows ce/i) == "windows ce";
+                var bIsWM = sUserAgent.match(/windows mobile/i) == "windows mobile";
+                if (bIsIpad || bIsIphoneOs || bIsMidp || bIsUc7 || bIsUc || bIsAndroid || bIsCE || bIsWM) {
+                    // 移动端访问跳转到移动端页面
+                    window.location.href = 'invitation_mobile_join.html?param='+param
+                } else {
+                    this.param();//获取pc端页面参数
+                }
+            },
             //验证手机
             phone(){
                 let phone = this.$refs.phone.value;//手机 
@@ -90,7 +132,7 @@ import { setTimeout } from 'timers';
                 } else {
                     this.isname = true;
                     if (this.regname.test(name)) {
-                        this.$message.error('姓名不能包含符号、数字、英文等非法字符');
+                        this.$message.error('姓名不能包含符号、数字等非法字符');
                         this.isregname = false
                     } else {
                         this.isregname = true
@@ -150,13 +192,15 @@ import { setTimeout } from 'timers';
                 let name = this.$refs.name.value;//姓名
                 let roleid = this.$refs.role.value;//角色
                 if (!this.isphone) {
-                    this.$message.error('手机号码不能为空');
+                    this.$message.error({
+                        message: '手机号码不能为空'
+                        });
                 } else if (!this.isregphone){
                     this.$message.error('请输入正确的手机号码');
                 } else if (!this.isname) {
                     this.$message.error('姓名不能为空');
                 } else if (!this.isregname) {
-                    this.$message.error("姓名不能包含符号、数字、英文等非法字符");
+                    this.$message.error("姓名不能包含符号、数字等非法字符");
                 } else if(!this.isvalidCode){
                     this.$message.error("请输入验证码");
                 } else if(!this.isrole){
@@ -178,16 +222,17 @@ import { setTimeout } from 'timers';
                     })
                     .then(res=>{
                         if (res.data.success) {
-                            this.$message.success('提交成功,3秒后自动跳转...');
-                            setTimeout(()=>{
-                                this.$router.push({path: '/home'});
-                            },3000)
+                            this.istanchaung = true;
                         } else {
                             this.$message.error(res.data.message);
                         }
                     })
                 }
             },
+            // 跳转首页
+            gohome(){
+                this.$router.push({path: '/home'});
+            },
             //倒计时
             settime(){
                 this.times = setTimeout(()=>{
@@ -205,7 +250,7 @@ import { setTimeout } from 'timers';
             role(){
                 let companyId = this.enterprise.companyId;
                 this.$ajax({
-                    url: this.$url.api+'/api/account/role/list'+`?id=${companyId}`,
+                    url: this.$url.api+'/api/account/role/list/'+companyId,
                     headers:{
                         "Authorization":Session.getToken(),
                     }
@@ -236,11 +281,18 @@ import { setTimeout } from 'timers';
                             this.role()
                         },800)
                     } else {
-                        this.$message.error(res.data.message);
+                        this.$message.error({
+                            message:res.data.message,
+                            center : true
+                            });
                         this.$router.push({path:'/failure'})
                     }
                 })
             },
+            //关闭弹窗
+            hidden(){
+                this.istanchaung = false;
+            },
         }
     }
 </script>
@@ -250,7 +302,7 @@ import { setTimeout } from 'timers';
     width: 100%;
 }
 .centent {
-    width: 352px;
+    width: 27rem;
     position: absolute;
     top: 50%;
     left: 50%;
@@ -262,22 +314,28 @@ import { setTimeout } from 'timers';
     font-size: 26px;
     color: #FFFFFF;
     letter-spacing: 3.25px;
+    display: inline-block;
+    position: relative;
+    bottom: -20px;
+}
+.padding-left {
+    padding-left: 15px; 
 }
-
 .centent > input {
     width: 100%;
-    margin-bottom: 16px;
-    opacity: 0.95;
+    margin-bottom: 11px;
+    opacity: 0.87;
     background: #FFFFFF;
     box-shadow: 0 2px 4px 0 #3C8EFF;
-    font-size: 15px;
-    padding: 3px 0px 3px 5px;
+    font-size: 14px;
     border: 0;
+    height: 40px;
+    border-radius: 4px;
 }
 .inv-title {
     text-align: left;
     margin-top: 37px;
-    margin-bottom: 40px;
+    margin-bottom: 20px;
 }
 .inv-title > p{
     font-family: PingFangSC-Medium;
@@ -285,9 +343,10 @@ import { setTimeout } from 'timers';
     color: #FFFFFF;
     letter-spacing: 2.25px;
     text-shadow: 0 2px 4px #1B5099;
+    line-height: 30px;
 }
 .inv-title >p:nth-child(1) {
-    margin-bottom: 16px;
+    /* margin-bottom: 16px; */
 }
 .inv-text {
     font-family: PingFangSC-Regular;
@@ -296,30 +355,47 @@ import { setTimeout } from 'timers';
     background: #004CE0;
     width: 100%;
     border: 0;
-    height: 36px;
+    height: 40px;
+    border-radius: 4px;
+    color: #FFFFFF;
+    letter-spacing: 1.75px;
 }
 .role {
     width: 100%;
-    margin-bottom: 32px;
-    padding: 3px 0px;
+    margin-bottom: 39px;
+    opacity: 0.87;
+    box-shadow: 0 2px 4px 0 #3C8EFF;
+    font-size: 14px;
+    border: 0;
+    height: 40px;
+    border-radius: 4px;
+    appearance:none;
+   -moz-appearance:none;
+   -webkit-appearance:none;
+   /*设置箭头*/
+   background: url(/static/img/TriangleCopy.png) no-repeat scroll right center transparent;
+   padding-right: 14px;
+   background-position-x: 95%;
 }
 .Verification {
     border: 0;
-    opacity: 0.95;
+    opacity: 0.87;
     background: #FFFFFF;
     box-shadow: 0 2px 4px 0 #3C8EFF;
-    margin-bottom: 16px;
+    margin-bottom: 11px;
+    height: 40px;
+    line-height: 38px;
+    border-radius: 4px;
 }
 .Verification > input {
     width: 68%;
     border: 0;
-    font-size: 15px;
-    padding: 3px 0px 3px 5px;
+    font-size: 14px;
+    outline:none;
 }
 .Verification > span {
     width: 30%;
     display: inline-block;
-    border-left: 1px solid #2F86FE;
     font-family: PingFangSC-Regular;
     font-size: 12px;
     color: #2F86FE;
@@ -337,4 +413,60 @@ import { setTimeout } from 'timers';
     color: #666666;
     letter-spacing: 2px;
 }
+/* 弹窗 */
+.Popup {
+    width: 428px;
+    height: 235px;
+    background: #FFFFFF;
+    border-radius: 2px;
+    position: fixed;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    z-index: 10001;
+    text-align: center;
+    padding: 24px;
+}
+.shang {
+    height: 30%;
+    position: relative;
+}
+.shang > img:nth-child(1){
+    width: 124px;
+    margin-top: 15px;
+}
+.shang > img:nth-child(2){
+    position: absolute;
+    top: 0px;
+    right: 0px;
+}
+.zhong {
+    height: 50%;
+    line-height: 36px;
+}
+.zhong > p:nth-child(1) {
+    font-family: PingFangSC-Regular;
+    font-size: 14px;
+    color: #333333;
+    letter-spacing: 1.75px;
+}
+.zhong > p:nth-child(2) {
+    font-family: PingFangSC-Regular;
+    font-size: 12px;
+    color: #666666;
+    letter-spacing: 1.5px;
+}
+.xia {
+    height: 20%;
+}
+.xia > button {
+    background: #207CFF;
+    border-radius: 2px;
+    font-family: PingFangSC-Regular;
+    font-size: 14px;
+    color: #FFFFFF;
+    letter-spacing: 1.75px;
+    padding: 6px 16px;
+    border: 0;
+}
 </style>

+ 11 - 2
frontend/saas-portal-web/static/css/gongsi.css

@@ -25,6 +25,11 @@ input::-webkit-input-placeholder {
     min-width: 96px !important;
     padding: 0 !important;
     text-align: center !important;
+    margin-top: 0px !important;
+}
+.el-message {
+    min-width: 240px !important;
+    height: 32px !important;
 }
 /* 弹窗 -----------------------------------------------*/
 .tanchuang {
@@ -299,8 +304,11 @@ input::-webkit-input-placeholder {
     box-shadow: 0 20px 60px 8px #F4F8FC;
     border-radius: 2px;
 }
-.gr-worp div {
-    width: 50%;
+.gr-worp > div:nth-child(1) {
+    width: 40%;
+}
+.gr-worp > div:nth-child(2) {
+    width: 60%;
 }
 .gr-left {
     text-align: center;
@@ -460,6 +468,7 @@ input::-webkit-input-placeholder {
 }
 .lookup > ul > li span:nth-child(2) {
     width: 74%;
+    padding-right: 10px;
 } 
 /* .lookup > ul > li span:nth-child(3) {
     width: 40%;

+ 5 - 5
frontend/saas-portal-web/static/css/main.css

@@ -101,7 +101,7 @@ main > section {
     height: 100%;
     width: 100%;
     background: #000;
-    opacity: 0.3;
+    opacity: 0.35;
     z-index: 10000;
 }
 /* 登录弹窗 */
@@ -353,8 +353,8 @@ main > section {
     background-size: 100%;
 }
 .db-text {
-    background: white;
-    color: #000;
+    background:  #1E88F5;
+    color:  #FFFFFF;
 }
 .footer .container{
     margin: 0 auto;
@@ -453,10 +453,10 @@ main > section {
 
 
 .friend-link{
-    height: 48px;
+    height: 56px;
     background: #14152D;
     width: 100%;
-    line-height: 48px;
+    line-height: 56px;
     text-align: center;
 }
 .friend-link span {

+ 0 - 0
frontend/saas-portal-web/static/img/Triangle Copy 4.png → frontend/saas-portal-web/static/img/TriangleCopy.png


BIN
frontend/saas-portal-web/static/img/tijiao.png


+ 69 - 42
frontend/saas-web/app/view/core/base/BasePanelController.js

@@ -8,14 +8,8 @@ Ext.define('saas.view.core.base.BasePanelController', {
     query: function() {
         var form = this.view;
         var grid = form.down('core-base-gridpanel');
-        grid.condition = '';
-        var fields = form.searchField.map(f => f.name);
-        var items = [];
-        Ext.each(fields, function(f, index){
-            var field = form.dockedItems.items[0].down('[name='+f+']');
-            items.push(field);
-        });
-        grid.condition = this.getCondition(items);
+        
+        grid.condition = this.getConditions();
         grid.store.loadPage(1);
     },
 
@@ -25,11 +19,16 @@ Ext.define('saas.view.core.base.BasePanelController', {
         saas.util.BaseUtil.openTab(form.xtype,'新增' + form._title,id);
     },
 
-    getCondition: function(items) {
-        var me = this,
-        conditions = [];
+    /**
+     * 获得过滤条件
+     */
+    getConditions: function() {
+        var me = this;
+        var form = this.view;
+        var items = form.dockedItems.items[0].items.items;
+        var conditions = [];
 
-        for(var i = 0; i < items.length; i++) {
+        for(let i = 0; i < items.length; i++) {
             var item = items[i];
             var field = item.name,
             func = item.getCondition,
@@ -43,10 +42,9 @@ Ext.define('saas.view.core.base.BasePanelController', {
                         value: func(value)
                     }
                 }else {
-                    var xtype = item.xtype || 'textfield',
-                    type = item.fieldType || me.getDefaultFieldType(xtype),
-                    operation = item.operation || me.getDefaultFieldOperation(xtype),
-                    conditionValue = me.getConditionValue(xtype, value);
+                    var type = item.fieldType || me.getDefaultFieldType(item),
+                    operation = item.operation || me.getDefaultFieldOperation(item),
+                    conditionValue = me.getConditionValue(item, value);
         
                     if(!conditionValue) {
                         continue;
@@ -60,38 +58,58 @@ Ext.define('saas.view.core.base.BasePanelController', {
                 }
                 conditions.push(condition);
             }
-        };
+        }
+
         return conditions;
     },
 
-    getDefaultFieldType: function(xtype) {
-        var type;
+    /**
+     * 只要arr1和arr2中存在相同项即返回真
+     */
+    isContainsAny: function (arr1, arr2) {
+        for (var i = 0; i < arr2.length; i++) {
+            var a2 = arr2[i];
+            if (!!arr1.find(function (a1) {
+                    return a1 == a2
+                })) {
+                return true;
+            }
+        }
+        return false;
+    },
+
+    getDefaultFieldType: function (field) {
+        var me = this,
+            xtypes = field.getXTypes().split('/'),
+            type;
 
-        if(Ext.Array.contains(['numberfield'], xtype)) {
+        if (me.isContainsAny(xtypes, ['numberfield'])) {
             type = 'number';
-        }else if(Ext.Array.contains(['datefield', 'condatefield'], xtype)) {
+        } else if (me.isContainsAny(xtypes, ['datefield', 'condatefield', 'conmonthfield'])) {
             type = 'date';
-        }else if(Ext.Array.contains(['combobox', 'multicombo', 'combo', 'radiofield', 'radio'], xtype)) {
+        } else if (me.isContainsAny(xtypes, ['dbfindtrigger'])) {
             type = 'enum';
-        }else {
+        } else if (me.isContainsAny(xtypes, ['combobox', 'multicombo', 'combo', 'radiofield', 'radio'])) {
+            type = 'enum';
+        } else {
             type = 'string';
         }
 
         return type;
     },
 
-    getDefaultFieldOperation: function(xtype) {
-        var operation;
+    getDefaultFieldOperation: function (field) {
+        var me = this,
+            xtypes = field.getXTypes().split('/'),
+            operation;
 
-        if(Ext.Array.contains(['numberfield'], xtype)) {
-            operation = '=';
-        }else if(Ext.Array.contains(['datefield'], xtype)) {
+        if (me.isContainsAny(xtypes, ['numberfield', 'datefield', 'dbfindtrigger'])) {
             operation = '=';
-        }else if(Ext.Array.contains(['condatefield'], xtype)) {
+        } else if (me.isContainsAny(xtypes, ['condatefield', 'conmonthfield'])) {
             operation = 'between';
-        }else if(Ext.Array.contains(['combobox', 'multicombo', 'combo'], xtype)) {
+        } else if (me.isContainsAny(xtypes, ['multidbfindtrigger', 'combobox', 'multicombo', 'combo'])) {
             operation = 'in';
-        }else {
+        } else {
             operation = 'like';
         }
 
@@ -101,25 +119,34 @@ Ext.define('saas.view.core.base.BasePanelController', {
     /**
      * 处理部分字段值
      */
-    getConditionValue: function(xtype, value) {
-        var conditionValue;
-        if(xtype == 'datefield') {
+    getConditionValue: function (field, value) {
+        var me = this,
+            xtypes = field.getXTypes().split('/'),
+            conditionValue;
+        if (me.isContainsAny(xtypes, ['datefield'])) {
             conditionValue = Ext.Date.format(new Date(from), 'Y-m-d H:i:s');
-        }else if(xtype == 'condatefield') {
+        } else if (me.isContainsAny(xtypes, ['conmonthfield'])) {
+            var from = value.from,
+                to = value.to;
+
+            conditionValue = from + ',' + to;
+        } else if (me.isContainsAny(xtypes, ['condatefield'])) {
             var from = value.from,
-            to = value.to;
+                to = value.to;
 
             conditionValue = Ext.Date.format(new Date(from), 'Y-m-d 00:00:00') + ',' + Ext.Date.format(new Date(to), 'Y-m-d 23:59:59');
-        }else if(xtype == 'combobox' || xtype == 'combo') {
+        } else if (me.isContainsAny(xtypes, ['dbfindtrigger'])) {
+            conditionValue = value;
+        } else if (me.isContainsAny(xtypes, ['combobox', 'combo'])) {
             conditionValue = '\'' + value + '\'';
-        }else if(xtype == 'multicombo') {
-            conditionValue = value.map(function(v) {
+        } else if (me.isContainsAny(xtypes, ['multicombo'])) {
+            conditionValue = value.map ? value.map(function (v) {
                 return '\'' + v.value + '\'';
-            }).join(',');
-        }else {
+            }).join(',') : '';
+        } else {
             conditionValue = value;
         }
 
         return conditionValue;
-    }
+    },
 });

+ 2 - 1
frontend/saas-web/app/view/core/dbfind/DbfindGridPanel.scss

@@ -34,7 +34,7 @@
     .x-window-body{
         padding-top: 0px !important;
     }
-    .x-toolbar-default {
+    .x-toolbar-docked-top {
         padding: 6px 0 12px 0px;
     }
     .x-grid-header-ct {
@@ -46,6 +46,7 @@
         border-right-width: 1px !important;
         border-left-width: 1px !important;
         border-top-width: 0px !important;
+        border-bottom-width: 1px !important;
     }
     .x-grid-paging-toolbar{
         border: 1px solid #abdaff !important;

+ 1 - 0
frontend/saas-web/app/view/core/form/DataMultiCombo.js

@@ -13,6 +13,7 @@ Ext.define('saas.view.core.form.DataMultiCombo', {
     publishes: 'value',
     matchFieldWidth: true,
     autoScroll:true,
+    triggerCls:'x-form-trigger',
     value: [],
     cachedConfig: {
         menuAlign: 'tl-bl?',

+ 1 - 0
frontend/saas-web/app/view/core/form/MultiCombo.js

@@ -6,6 +6,7 @@ Ext.define('saas.view.core.form.MultiCombo', {
     alias: 'widget.multicombo',
     editable : false,
     matchFieldWidth: true,
+    triggerCls:'x-form-trigger',
     value: [],
     cachedConfig: {
         menuAlign: 'tl-bl?',

+ 1 - 0
frontend/saas-web/app/view/core/form/RemoteCombo.js

@@ -7,6 +7,7 @@ Ext.define('saas.view.core.form.RemoteCombo', {
     displayField: 'display',
     valueField: 'value',
     queryMode: 'local',//只在组件加载的时候请求一次
+    triggerCls:'x-form-trigger',
     listConfig: {
         maxHeight: (Ext.isIE?screen.height:window.innerHeight)*0.5-50,
     },

+ 33 - 33
frontend/saas-web/app/view/document/bom/FormPanel.js

@@ -22,32 +22,41 @@ Ext.define('saas.view.document.bom.FormPanel', {
     _deleteMsg: '删除的BOM资料将不能恢复,请确认是否删除?',
     codeInHeader: false,
 
+    defaultButtons:[{
+        cls: 'x-formpanel-btn-blue',
+        xtype: 'button',
+        text: '新增',
+        bind: {
+            hidden: '{!id}'
+        },
+        handler: 'add'
+    }, {
+        xtype: 'button',
+        text: '保存',
+        handler: 'onSave'
+    }, {
+        xtype: 'button',
+        text: '删除',
+        handler: 'delete'
+    }, {
+        xtype: 'button',
+        bind: {
+            text: '{auditBtnText}'
+        },
+        handler: "auditBtnClick",
+    }],
+
+    auditTexts: {
+        auditCode: 'BANNED',
+        auditText: '已禁用',
+        unAuditCode: 'ENABLE',
+        unAuditText: '已启用',
+        auditBtnText: '禁用',
+        unAuditBtnText: '启用',
+    },
+
     initComponent: function () {
         Ext.applyIf(this, {
-            defaultButtons:[{
-                cls: 'x-formpanel-btn-blue',
-                xtype: 'button',
-                text: '新增',
-                bind: {
-                    hidden: '{!id}'
-                },
-                handler: 'add'
-            }, {
-                xtype: 'button',
-                text: '保存',
-                handler: 'onSave'
-            }, {
-                xtype: 'button',
-                text: '删除',
-                handler: 'delete'
-            }, {
-                xtype: 'button',
-                bind: {
-                    text: '{auditBtnText}'
-                },
-                handler: "auditBtnClick",
-            }],
-        
             defaultItems: [{
                 xtype: 'hidden',
                 name: 'id',
@@ -245,15 +254,6 @@ Ext.define('saas.view.document.bom.FormPanel', {
                 name : "createTime", 
                 fieldLabel : "录入时间"
             }],
-        
-            auditTexts: {
-                auditCode: 'BANNED',
-                auditText: '已禁用',
-                unAuditCode: 'ENABLE',
-                unAuditText: '已启用',
-                auditBtnText: '禁用',
-                unAuditBtnText: '启用',
-            }
         });
         this.callParent(arguments);
     },

+ 32 - 31
frontend/saas-web/app/view/document/customer/FormPanel.js

@@ -22,6 +22,38 @@ Ext.define('saas.view.document.customer.FormPanel', {
 
     codeInHeader: false,
 
+    defaultButtons:[{
+        cls: 'x-formpanel-btn-blue',
+        xtype: 'button',
+        text: '新增',
+        bind: {
+            hidden: '{!id}'
+        },
+        handler: 'add'
+    }, {
+        xtype: 'button',
+        text: '保存',
+        handler: 'onSave',
+    }, {
+        xtype: 'button',
+        text: '删除',
+        handler: 'delete'
+    }, {
+        xtype: 'button',
+        bind: {
+            text: '{auditBtnText}'
+        },
+        handler: "auditBtnClick",
+    }],
+    auditTexts: {
+        auditCode: 'BANNED',
+        auditText: '已禁用',
+        unAuditCode: 'ENABLE',
+        unAuditText: '已启用',
+        auditBtnText: '禁用',
+        unAuditBtnText: '启用',
+    },
+
     initComponent: function () {
         Ext.applyIf(this, {
             defaultItems: [{
@@ -359,37 +391,6 @@ Ext.define('saas.view.document.customer.FormPanel', {
                         xtype:'yncolumn'
                     }]
             }],
-            defaultButtons:[{
-                cls: 'x-formpanel-btn-blue',
-                xtype: 'button',
-                text: '新增',
-                bind: {
-                    hidden: '{!id}'
-                },
-                handler: 'add'
-            }, {
-                xtype: 'button',
-                text: '保存',
-                handler: 'onSave',
-            }, {
-                xtype: 'button',
-                text: '删除',
-                handler: 'delete'
-            }, {
-                xtype: 'button',
-                bind: {
-                    text: '{auditBtnText}'
-                },
-                handler: "auditBtnClick",
-            }],
-            auditTexts: {
-                auditCode: 'BANNED',
-                auditText: '已禁用',
-                unAuditCode: 'ENABLE',
-                unAuditText: '已启用',
-                auditBtnText: '禁用',
-                unAuditBtnText: '启用',
-            }
         });
         this.callParent(arguments);
     },

+ 33 - 32
frontend/saas-web/app/view/document/product/FormPanel.js

@@ -22,6 +22,38 @@ Ext.define('saas.view.document.product.FormPanel', {
 
     codeInHeader: false,
 
+    defaultButtons:[{
+        cls: 'x-formpanel-btn-blue',
+        xtype: 'button',
+        text: '新增',
+        bind: {
+            hidden: '{!id}'
+        },
+        handler: 'add'
+    }, {
+        xtype: 'button',
+        text: '保存',
+        handler: 'onSave',
+    }, {
+        xtype: 'button',
+        text: '删除',
+        handler: 'delete'
+    }, {
+        xtype: 'button',
+        bind: {
+            text: '{auditBtnText}'
+        },
+        handler: "auditBtnClick",
+    }],
+    auditTexts: {
+        auditCode: 'BANNED',
+        auditText: '已禁用',
+        unAuditCode: 'ENABLE',
+        unAuditText: '已启用',
+        auditBtnText: '禁用',
+        unAuditBtnText: '启用',
+    },
+
     initComponent: function () {
         Ext.applyIf(this, {
             defaultItems: [{
@@ -244,7 +276,7 @@ Ext.define('saas.view.document.product.FormPanel', {
                 xtype : "detailGridField", 
                 storeModel:'saas.model.document.ProductDetail',
                 detnoColumn: 'pd_detno',
-                emptyRows: 1,
+                emptyRows: 3,
                 showCount: true,
                 allowEmpty:true,
                 // hidden: true,
@@ -348,37 +380,6 @@ Ext.define('saas.view.document.product.FormPanel', {
                 }]
             }],
         
-            defaultButtons:[{
-                cls: 'x-formpanel-btn-blue',
-                xtype: 'button',
-                text: '新增',
-                bind: {
-                    hidden: '{!id}'
-                },
-                handler: 'add'
-            }, {
-                xtype: 'button',
-                text: '保存',
-                handler: 'onSave',
-            }, {
-                xtype: 'button',
-                text: '删除',
-                handler: 'delete'
-            }, {
-                xtype: 'button',
-                bind: {
-                    text: '{auditBtnText}'
-                },
-                handler: "auditBtnClick",
-            }],
-            auditTexts: {
-                auditCode: 'BANNED',
-                auditText: '已禁用',
-                unAuditCode: 'ENABLE',
-                unAuditText: '已启用',
-                auditBtnText: '禁用',
-                unAuditBtnText: '启用',
-            },
             listeners: {
                 load: function(form, data) {
                     var viewModel = form.getViewModel();

+ 33 - 33
frontend/saas-web/app/view/document/vendor/FormPanel.js

@@ -22,6 +22,38 @@ Ext.define('saas.view.document.vendor.FormPanel', {
 
     codeInHeader: false,
 
+    defaultButtons:[{
+        cls: 'x-formpanel-btn-blue',
+        xtype: 'button',
+        text: '新增',
+        bind: {
+            hidden: '{!id}'
+        },
+        handler: 'add'
+    }, {
+        xtype: 'button',
+        text: '保存',
+        handler: 'onSave',
+    }, {
+        xtype: 'button',
+        text: '删除',
+        handler: 'delete'
+    }, {
+        xtype: 'button',
+        bind: {
+            text: '{auditBtnText}'
+        },
+        handler: "auditBtnClick",
+    }],
+    auditTexts: {
+        auditCode: 'BANNED',
+        auditText: '已禁用',
+        unAuditCode: 'ENABLE',
+        unAuditText: '已启用',
+        auditBtnText: '禁用',
+        unAuditBtnText: '启用',
+    },
+
     initComponent: function() {
         Ext.apply(this, {
             defaultItems: [{
@@ -220,7 +252,7 @@ Ext.define('saas.view.document.vendor.FormPanel', {
             },{
                 xtype : "textfield", 
                 name : "ve_address", 
-                fieldLabel : "地址", 
+                fieldLabel : "公司地址", 
                 allowBlank : true, 
                 columnWidth : 0.75
             },{
@@ -292,38 +324,6 @@ Ext.define('saas.view.document.vendor.FormPanel', {
                     }]
                 }
             ],
-        
-            defaultButtons:[{
-                cls: 'x-formpanel-btn-blue',
-                xtype: 'button',
-                text: '新增',
-                bind: {
-                    hidden: '{!id}'
-                },
-                handler: 'add'
-            }, {
-                xtype: 'button',
-                text: '保存',
-                handler: 'onSave',
-            }, {
-                xtype: 'button',
-                text: '删除',
-                handler: 'delete'
-            }, {
-                xtype: 'button',
-                bind: {
-                    text: '{auditBtnText}'
-                },
-                handler: "auditBtnClick",
-            }],
-            auditTexts: {
-                auditCode: 'BANNED',
-                auditText: '已禁用',
-                unAuditCode: 'ENABLE',
-                unAuditText: '已启用',
-                auditBtnText: '禁用',
-                unAuditBtnText: '启用',
-            }
         });
         this.callParent(arguments);
     },

+ 2 - 0
frontend/saas-web/app/view/home/charts/KeyData.scss

@@ -14,6 +14,7 @@
             cursor: pointer;
             transition: all 0.3s ease;
             outline: none !important;
+            background: transparent;
 
             // &:hover {
             //     box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
@@ -71,6 +72,7 @@
                     border-radius: 4px 4px 0 0;
                 }
                 .x-contain {
+                    background: #fff;
                     border-style: solid;
                     border-width: 0 1px 1px 1px;
                     border-radius: 0 0 4px 4px;

+ 1 - 1
frontend/saas-web/app/view/main/Main.scss

@@ -210,7 +210,7 @@ $treelist-nav-ui: (
 }
 body > .x-mask {
     background-image: none;
-    background-color: rgba(142, 141, 141, 0.75);
+    background-color: rgba(0, 0, 0, 0.3);
 }
 .icon-usoftchina{
     margin-top: 0px;

+ 4 - 1
frontend/saas-web/app/view/money/recBalance/FormPanel.js

@@ -56,16 +56,19 @@ Ext.define('saas.view.money.recBalance.FormPanel', {
                 xtype: "numberfield",
                 name: "cu_leftamount",
                 fieldLabel: "总欠款",
+                thousandSeparator: ',',
                 ignore: true,
                 readOnly: true
             }, {
                 xtype: 'hidden',
                 name: 'rb_rbdamount',
-                fieldLabel: '本次核销金额(元)'
+                fieldLabel: '本次核销金额(元)',
+                thousandSeparator: ','
             }, {
                 xtype: 'hidden',
                 name: 'rb_rdamount',
                 fieldLabel: '本次付款金额(元)',
+                thousandSeparator: ','
             }, {
                 xtype: "datefield",
                 name: "rb_date",

+ 1 - 1
frontend/saas-web/app/view/money/report/AccountBalance.js

@@ -34,7 +34,7 @@ Ext.define('saas.view.money.report.AccountBalance', {
     }, {
         text: '账户编号',
         dataIndex: 'bankcode',
-        width: 80
+        width: 150
     }, {
         text: '账户名称',
         dataIndex: 'bankname',

+ 5 - 4
frontend/saas-web/app/view/money/report/AccountDetails.js

@@ -16,13 +16,14 @@ Ext.define('saas.view.money.report.AccountDetails', {
     searchItems: [{
         name: 'sl_code',
         xtype: 'textfield',
-        emptyText: '单号',
+        emptyText: '请输入单号',
         columnWidth: 0.1
     }, {
         xtype: 'multicombo',
         name: 'sl_kind',
-        emptyText: '单据类型',
+        emptyText: '请选择业务类型',
         columnWidth: 0.1,
+        triggerCls:'x-form-trigger',
         datas: [
             ["采购验收单", "采购验收单"],
             ["采购验退单", "采购验退单"],
@@ -42,12 +43,12 @@ Ext.define('saas.view.money.report.AccountDetails', {
     // }, {
         xtype: "customerDbfindTrigger",
         name: "cu_name",
-        emptyText: '客户编号/名称',
+        emptyText: '请输入客户名称',
         columnWidth: 0.15
     }, {
         xtype: 'vendorDbfindTrigger',
         name: 've_name',
-        emptyText: '供应商编号/名称',
+        emptyText: '请输入供应商名称',
         columnWidth: 0.15
     }],
 

+ 4 - 2
frontend/saas-web/app/view/money/report/OtherIODetail.js

@@ -19,7 +19,7 @@ Ext.define('saas.view.money.report.OtherIODetail', {
     searchItems: [{
         xtype: 'bandinfoDbfindTrigger',
         name: 'bl_bankname',
-        emptyText: '资金账户',
+        emptyText: '请输入资金账户',
         columnWidth: 0.15,
         dbfinds:[
             {
@@ -37,7 +37,7 @@ Ext.define('saas.view.money.report.OtherIODetail', {
         queryMode: 'local',
         displayField: 'display',
         valueField: 'value',
-        emptyText : '收支类别',
+        emptyText : '请选择收支类别',
         editable:false,
         columnWidth: 0.15,
         store: Ext.create('Ext.data.ArrayStore', {
@@ -88,6 +88,7 @@ Ext.define('saas.view.money.report.OtherIODetail', {
             return saas.util.BaseUtil.numberFormat(v, 2, true);
         },
         summaryType: 'sum',
+        summaryLabel: '收入',
         summaryRenderer: function(v) {
             return saas.util.BaseUtil.numberFormat(v, 2, true);
         }
@@ -100,6 +101,7 @@ Ext.define('saas.view.money.report.OtherIODetail', {
             return saas.util.BaseUtil.numberFormat(v, 2, true);
         },
         summaryType: 'sum',
+        summaryLabel: '支出',
         summaryRenderer: function(v) {
             return saas.util.BaseUtil.numberFormat(v, 2, true);
         }

+ 1 - 1
frontend/saas-web/app/view/money/report/PayDetail.js

@@ -6,7 +6,7 @@ Ext.define('saas.view.money.report.PayDetail', {
     viewModel: 'money-report-paydetail',
     viewName: 'money-report-paydetail',
 
-    groupField:'pd_vendname',
+    groupField:'pd_vendid',
     groupHeaderTpl: '供应商名称: {[values.rows[0].data.pd_vendname]}',
     listUrl: '/api/money/report/payDetail',
     defaultCondition: null,

+ 1 - 1
frontend/saas-web/app/view/money/report/ProfitDetail.js

@@ -29,7 +29,7 @@ Ext.define('saas.view.money.report.ProfitDetail', {
         xtype : "remotecombo", 
         storeUrl:'/api/document/customerkind/getCombo',
         name : "cu_type", 
-        emptyText : "客户类型", 
+        emptyText : "请选择客户类型", 
         columnWidth: 0.15,
         hiddenBtn:true
     }, {

+ 2 - 2
frontend/saas-web/app/view/money/report/RecDetail.js

@@ -7,7 +7,7 @@ Ext.define('saas.view.money.report.RecDetail', {
 
     viewName: 'money-report-recdetail',
 
-    groupField: 'rd_custname',
+    groupField: 'rd_custid',
     groupHeaderTpl: '客户名称: {[values.rows[0].data.rd_custname]}',
     listUrl: '/api/money/report/recDetail',
     defaultCondition: null,
@@ -19,7 +19,7 @@ Ext.define('saas.view.money.report.RecDetail', {
     searchItems: [{
         xtype: 'customerDbfindTrigger',
         name: 'rd_custname',
-        fieldLabel: '客户名称',
+        emptyText: '请输入客户名称',
         columnWidth: 0.25
     }, {
         xtype: 'conmonthfield',

+ 5 - 7
frontend/saas-web/app/view/money/report/TotalPayDetail.js

@@ -18,13 +18,10 @@ Ext.define('saas.view.money.report.TotalPayDetail', {
     allowPaging: false,
 
     searchItems: [{
-        xtype: 'textfield',
-        name: 'vm_vendcode',
-        emptyText: '供应商编号/名称',
-        columnWidth: 0.25,
-        getCondition: function (v) {
-            return "(upper(vm_vendcode) like '%" + v.toUpperCase() + "%' or upper(vm_vendname) like '%" + v.toUpperCase() + "%')";
-        },
+        xtype: 'vendorDbfindTrigger',
+        name: 'vm_vendname',
+        emptyText: '请输入供应商名称',
+        columnWidth: 0.25
     }, {
         xtype: 'conmonthfield',
         fieldLabel: '期间',
@@ -132,6 +129,7 @@ Ext.define('saas.view.money.report.TotalPayDetail', {
             return saas.util.BaseUtil.numberFormat(v, 2, true);
         },
         summaryType: 'sum',
+        summaryLabel: '应付余额',
         summaryRenderer: function (v) {
             return saas.util.BaseUtil.numberFormat(v, 2, true);
         }

+ 17 - 0
frontend/saas-web/app/view/money/report/TotalPayDetailController.js

@@ -1,4 +1,21 @@
 Ext.define('saas.view.money.report.TotalPayDetailController', {
     extend: 'saas.view.core.report.ReportPanelController',
     alias: 'controller.money-report-totalpaydetail',
+    init: function (form) {
+        this.control({
+            // 供应商编号
+            'dbfindtrigger[name=vm_vendname]':{
+                beforerender:function(f){
+                    Ext.apply(f,{
+                        dbfinds:[{
+                            from:'ve_code',to:'vm_vendcode'
+                        },{
+                            from:'ve_name',to:'vm_vendname'
+                        }],
+                    }) ;
+
+                }
+            }
+        });
+    },
 });

+ 4 - 7
frontend/saas-web/app/view/money/report/TotalRecDetail.js

@@ -12,20 +12,16 @@ Ext.define('saas.view.money.report.TotalRecDetail', {
 
     groupField: null,
     listUrl: '/api/money/report/custormonthdetails',
-    // listUrl: 'http://192.168.253.139:8560/api/money/report/custormonthdetails',
     defaultCondition: null,
     reportTitle: '应收总账',
     QueryWidth: 0.35,
     allowPaging: false,
 
     searchItems: [{
-        xtype: 'textfield',
+        xtype: 'customerDbfindTrigger',
         name: 'cm_custcode',
-        emptyText: '客户编号/名称',
-        columnWidth: 0.25,
-        getCondition: function (v) {
-            return "(upper(cm_custcode) like '%" + v.toUpperCase() + "%' or upper(cm_custname) like '%" + v.toUpperCase() + "%')";
-        },
+        emptyText: '请输入客户名称',
+        columnWidth: 0.25
     }, {
         xtype: 'conmonthfield',
         fieldLabel: '期间',
@@ -133,6 +129,7 @@ Ext.define('saas.view.money.report.TotalRecDetail', {
             return saas.util.BaseUtil.numberFormat(v, 2, true);
         },
         summaryType: 'sum',
+        summaryLabel: '应收余额',
         summaryRenderer: function (v) {
             return saas.util.BaseUtil.numberFormat(v, 2, true);
         }

+ 4 - 2
frontend/saas-web/app/view/money/report/TotalRecDetailController.js

@@ -4,11 +4,13 @@ Ext.define('saas.view.money.report.TotalRecDetailController', {
     init: function (form) {
         this.control({
             // 供应商编号
-            'dbfindtrigger[name=pi_vendname]':{
+            'dbfindtrigger[name=cm_custname]':{
                 beforerender:function(f){
                     Ext.apply(f,{
                         dbfinds:[{
-                            from:'ve_name',to:'pi_vendname'
+                            from:'cu_code',to:'cm_custcode'
+                        },{
+                            from:'cu_name',to:'cm_custname'
                         }],
                     }) ;
 

+ 1 - 1
frontend/saas-web/app/view/purchase/purchase/FormPanel.js

@@ -296,7 +296,7 @@ Ext.define('saas.view.purchase.purchase.FormPanel', {
                     },
                 }]
             }, {
-                xtype: "numberfield",
+                xtype: "textfield",
                 name: "pu_remark",
                 fieldLabel: "备注",
                 columnWidth: 1

+ 8 - 0
frontend/saas-web/app/view/purchase/purchase/QueryPanel.js

@@ -219,6 +219,14 @@ Ext.define('saas.view.purchase.purchase.QueryPanel', {
             renderer : function(v) {
                 return saas.util.BaseUtil.numberFormat(v, 4, true);
             }
+        }, {
+            text: '含税单价(元)',
+            dataIndex: 'pd_price',
+            xtype: 'numbercolumn',
+            width: 110,
+            renderer : function(v) {
+                return saas.util.BaseUtil.numberFormat(v, 4, true);
+            }
         },{
             text: '金额(元)',
             dataIndex: 'pd_taxtotal',

Some files were not shown because too many files changed in this diff