Explorar el Código

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

rainco hace 7 años
padre
commit
22311f915b
Se han modificado 80 ficheros con 2569 adiciones y 1119 borrados
  1. 3 0
      applications/commons/commons-dto/src/main/java/com/usoftchina/saas/commons/exception/BizExceptionCode.java
  2. 2 0
      applications/money/money-server/src/main/java/com/usoftchina/saas/money/mapper/OthreceiptsdetailMapper.java
  3. 1 0
      applications/money/money-server/src/main/java/com/usoftchina/saas/money/mapper/OthspendingsdetailMapper.java
  4. 4 0
      applications/money/money-server/src/main/java/com/usoftchina/saas/money/mapper/PaybalanceMapper.java
  5. 1 0
      applications/money/money-server/src/main/java/com/usoftchina/saas/money/mapper/PaybalancedetMapper.java
  6. 1 0
      applications/money/money-server/src/main/java/com/usoftchina/saas/money/mapper/RecbalancedetMapper.java
  7. 14 0
      applications/money/money-server/src/main/java/com/usoftchina/saas/money/mapper/StatsinfoMapper.java
  8. 71 0
      applications/money/money-server/src/main/java/com/usoftchina/saas/money/po/Statsinfo.java
  9. 27 4
      applications/money/money-server/src/main/java/com/usoftchina/saas/money/service/impl/FundtransferServiceImpl.java
  10. 33 4
      applications/money/money-server/src/main/java/com/usoftchina/saas/money/service/impl/OthreceiptsServiceImpl.java
  11. 34 4
      applications/money/money-server/src/main/java/com/usoftchina/saas/money/service/impl/OthspendingsServiceImpl.java
  12. 30 1
      applications/money/money-server/src/main/java/com/usoftchina/saas/money/service/impl/PaybalanceServiceImpl.java
  13. 32 0
      applications/money/money-server/src/main/java/com/usoftchina/saas/money/service/impl/RecbalanceServiceImpl.java
  14. 2 2
      applications/money/money-server/src/main/resources/mapper/OthreceiptsMapper.xml
  15. 4 0
      applications/money/money-server/src/main/resources/mapper/OthreceiptsdetailMapper.xml
  16. 4 0
      applications/money/money-server/src/main/resources/mapper/OthspendingsdetailMapper.xml
  17. 11 2
      applications/money/money-server/src/main/resources/mapper/PaybalanceMapper.xml
  18. 4 0
      applications/money/money-server/src/main/resources/mapper/PaybalancedetMapper.xml
  19. 3 0
      applications/money/money-server/src/main/resources/mapper/RecbalancedetMapper.xml
  20. 103 0
      applications/money/money-server/src/main/resources/mapper/StatsinfoMapper.xml
  21. 1 0
      base-servers/gateway-server/src/main/resources/application.yml
  22. 23 0
      base-servers/mail/mail-api/pom.xml
  23. 191 0
      base-servers/mail/mail-api/src/main/java/com/usoftchina/saas/mail/MailBuilder.java
  24. 33 0
      base-servers/mail/mail-api/src/main/java/com/usoftchina/saas/mail/api/MailApi.java
  25. 0 1
      base-servers/mail/mail-dto/pom.xml
  26. 0 11
      base-servers/mail/mail-dto/src/main/java/com/usoftchina/saas/mail/dto/MailDto.java
  27. 57 0
      base-servers/mail/mail-dto/src/main/java/com/usoftchina/saas/mail/dto/MailLogDTO.java
  28. 89 0
      base-servers/mail/mail-dto/src/main/java/com/usoftchina/saas/mail/dto/TemplateMailMessage.java
  29. 11 25
      base-servers/mail/mail-server/pom.xml
  30. 6 0
      base-servers/mail/mail-server/src/main/java/com/usoftchina/saas/mail/MailApplication.java
  31. 88 0
      base-servers/mail/mail-server/src/main/java/com/usoftchina/saas/mail/controller/MailController.java
  32. 26 0
      base-servers/mail/mail-server/src/main/java/com/usoftchina/saas/mail/mapper/MailLogMapper.java
  33. 40 0
      base-servers/mail/mail-server/src/main/java/com/usoftchina/saas/mail/mapper/MailTemplateMapper.java
  34. 110 0
      base-servers/mail/mail-server/src/main/java/com/usoftchina/saas/mail/po/MailLog.java
  35. 38 0
      base-servers/mail/mail-server/src/main/java/com/usoftchina/saas/mail/po/MailTemplate.java
  36. 29 0
      base-servers/mail/mail-server/src/main/java/com/usoftchina/saas/mail/service/MailLogService.java
  37. 42 0
      base-servers/mail/mail-server/src/main/java/com/usoftchina/saas/mail/service/MailTemplateService.java
  38. 39 0
      base-servers/mail/mail-server/src/main/java/com/usoftchina/saas/mail/service/impl/MailLogServiceImpl.java
  39. 38 0
      base-servers/mail/mail-server/src/main/java/com/usoftchina/saas/mail/service/impl/MailTemplateServiceImpl.java
  40. 85 0
      base-servers/mail/mail-server/src/main/resources/application.yml
  41. 12 0
      base-servers/mail/mail-server/src/main/resources/config/application-docker-dev.yml
  42. 10 0
      base-servers/mail/mail-server/src/main/resources/config/application-docker.yml
  43. 0 0
      base-servers/mail/mail-server/src/main/resources/i18n/messages_en_US.properties
  44. 0 0
      base-servers/mail/mail-server/src/main/resources/i18n/messages_zh_CN.properties
  45. 113 0
      base-servers/mail/mail-server/src/main/resources/logback-spring.xml
  46. 31 0
      base-servers/mail/mail-server/src/main/resources/mapper/MailLogMapper.xml
  47. 29 0
      base-servers/mail/mail-server/src/main/resources/mapper/MailTemplateMapper.xml
  48. 0 1
      base-servers/mail/pom.xml
  49. 1 1
      frontend/saas-portal-web/Dockerfile
  50. 5 2
      frontend/saas-portal-web/README.md
  51. 0 5
      frontend/saas-portal-web/config/dev.env.js
  52. 15 0
      frontend/saas-portal-web/config/env.js
  53. 0 5
      frontend/saas-portal-web/config/prod.env.js
  54. 4 1
      frontend/saas-portal-web/package.json
  55. 23 8
      frontend/saas-portal-web/webpack.conf.js
  56. 47 0
      frontend/saas-portal-web/webpack.dev.conf.js
  57. 337 3
      frontend/saas-portal-web/yarn.lock
  58. 4 0
      frontend/saas-web/app/Application.scss
  59. 0 89
      frontend/saas-web/app/view/core/chart/Area.js
  60. 0 67
      frontend/saas-web/app/view/core/chart/Bar.js
  61. 0 2
      frontend/saas-web/app/view/core/chart/ChartBase.js
  62. 0 38
      frontend/saas-web/app/view/core/chart/Gauge.js
  63. 0 75
      frontend/saas-web/app/view/core/chart/Line.js
  64. 0 65
      frontend/saas-web/app/view/core/chart/Pie.js
  65. 0 42
      frontend/saas-web/app/view/core/chart/Pie3D.js
  66. 0 55
      frontend/saas-web/app/view/core/chart/Polar.js
  67. 0 71
      frontend/saas-web/app/view/core/chart/Stacked.js
  68. 1 1
      frontend/saas-web/app/view/core/dbfind/MultiDbfindGridPanel.js
  69. 18 2
      frontend/saas-web/app/view/core/report/ReportPanel.js
  70. 20 10
      frontend/saas-web/app/view/core/report/ReportPanelController.js
  71. 25 60
      frontend/saas-web/app/view/home/Home.js
  72. 161 363
      frontend/saas-web/app/view/home/HomeModel.js
  73. 2 2
      frontend/saas-web/app/view/home/InfoCard.js
  74. 78 0
      frontend/saas-web/app/view/home/charts/MonthIO.js
  75. 54 62
      frontend/saas-web/app/view/home/charts/MonthPurchase.js
  76. 36 35
      frontend/saas-web/app/view/home/charts/MonthSale.js
  77. 58 0
      frontend/saas-web/app/view/home/charts/PurchaseTrend.js
  78. 77 0
      frontend/saas-web/app/view/home/charts/SaleTrend.js
  79. 58 0
      frontend/saas-web/app/view/home/charts/StockAmount.js
  80. 20 0
      script/mysql/init/mail.sql

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

@@ -37,6 +37,7 @@ public enum BizExceptionCode implements BaseExceptionCode {
     ILLEGAL_ID(79999, "id不正确"),
     PRODUCT_HAS_WAREHOUSE(79502, "存在物料默认仓库资料为该仓库资料,无法删除"),
     PRODUCTWH_HAS_WAREHOUSE(79503, "该仓库资料存在库存,无法删除"),
+    ACCOUNT_EXISTS(79503, "账号已存在"),
 
 
 
@@ -61,6 +62,8 @@ public enum BizExceptionCode implements BaseExceptionCode {
 
     RECALANCE_OUTNOWBALANCE(74003,"本次核销金额不能大于未核销金额"),
 
+    BANK_AMOUNT_NOTENOUGH(74004, "资金账号不足"),
+
 
 
     //库存

+ 2 - 0
applications/money/money-server/src/main/java/com/usoftchina/saas/money/mapper/OthreceiptsdetailMapper.java

@@ -17,4 +17,6 @@ public interface OthreceiptsdetailMapper {
     int updateByPrimaryKeySelective(Othreceiptsdetail record);
 
     int updateByPrimaryKey(Othreceiptsdetail record);
+
+    List<Integer> selectYm(Integer id);
 }

+ 1 - 0
applications/money/money-server/src/main/java/com/usoftchina/saas/money/mapper/OthspendingsdetailMapper.java

@@ -17,4 +17,5 @@ public interface OthspendingsdetailMapper {
     int updateByPrimaryKeySelective(Othspendingsdetail record);
 
     int updateByPrimaryKey(Othspendingsdetail record);
+    List<Integer> selectYm(Integer id);
 }

+ 4 - 0
applications/money/money-server/src/main/java/com/usoftchina/saas/money/mapper/PaybalanceMapper.java

@@ -38,4 +38,8 @@ public interface PaybalanceMapper extends CommonBaseMapper<Paybalance> {
     Vendor selectVendorByPrimaryKey(Integer bkId);
 
     int updateVendorByPrimaryKeySelective(Vendor record);
+
+    Double selectThisamount(Integer id);
+
+    void updateBankAmount(@Param("bk_thisamount") Double bk_thisamount, @Param("id") Integer id);
 }

+ 1 - 0
applications/money/money-server/src/main/java/com/usoftchina/saas/money/mapper/PaybalancedetMapper.java

@@ -19,5 +19,6 @@ public interface PaybalancedetMapper {
     int updateByPrimaryKeySelective(Paybalancedet record);
 
     int updateByPrimaryKey(Paybalancedet record);
+    List<Integer> selectYm(Integer id);
 
 }

+ 1 - 0
applications/money/money-server/src/main/java/com/usoftchina/saas/money/mapper/RecbalancedetMapper.java

@@ -23,4 +23,5 @@ public interface RecbalancedetMapper extends CommonBaseMapper<Recbalancedet> {
     int updateByPrimaryKeySelective(Recbalancedet record);
 
     int updateByPrimaryKey(Recbalancedet record);
+    List<Integer> selectYm(Integer id);
 }

+ 14 - 0
applications/money/money-server/src/main/java/com/usoftchina/saas/money/mapper/StatsinfoMapper.java

@@ -0,0 +1,14 @@
+package com.usoftchina.saas.money.mapper;
+
+import com.usoftchina.saas.money.po.Statsinfo;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * @author heqw
+ * @date 2018/11/14 16:13
+ **/
+public interface StatsinfoMapper {
+    Integer select(@Param("si_yearmonth") Integer si_yearmonth, @Param("companyid") Long companyid);
+    void update(Statsinfo statsinfo);
+    void insert(Statsinfo statsinfo);
+}

+ 71 - 0
applications/money/money-server/src/main/java/com/usoftchina/saas/money/po/Statsinfo.java

@@ -0,0 +1,71 @@
+package com.usoftchina.saas.money.po;
+
+/**
+ * @author heqw
+ * @date 2018/11/14 16:02
+ **/
+public class Statsinfo {
+    private Double si_yearmonth;
+    private Double si_amount_pay;
+    private Double si_amount_otherpay;
+    private Double si_amount_rec;
+    private Double si_amount_otherrec;
+    private Long companyid;
+    private String si_type;
+
+    public Double getSi_yearmonth() {
+        return si_yearmonth;
+    }
+
+    public void setSi_yearmonth(Double si_yearmonth) {
+        this.si_yearmonth = si_yearmonth;
+    }
+
+    public Double getSi_amount_pay() {
+        return si_amount_pay;
+    }
+
+    public void setSi_amount_pay(Double si_amount_pay) {
+        this.si_amount_pay = si_amount_pay;
+    }
+
+    public Double getSi_amount_otherpay() {
+        return si_amount_otherpay;
+    }
+
+    public void setSi_amount_otherpay(Double si_amount_otherpay) {
+        this.si_amount_otherpay = si_amount_otherpay;
+    }
+
+    public Double getSi_amount_rec() {
+        return si_amount_rec;
+    }
+
+    public void setSi_amount_rec(Double si_amount_rec) {
+        this.si_amount_rec = si_amount_rec;
+    }
+
+    public Double getSi_amount_otherrec() {
+        return si_amount_otherrec;
+    }
+
+    public void setSi_amount_otherrec(Double si_amount_otherrec) {
+        this.si_amount_otherrec = si_amount_otherrec;
+    }
+
+    public Long getCompanyid() {
+        return companyid;
+    }
+
+    public void setCompanyid(Long companyid) {
+        this.companyid = companyid;
+    }
+
+    public String getSi_type() {
+        return si_type;
+    }
+
+    public void setSi_type(String si_type) {
+        this.si_type = si_type;
+    }
+}

+ 27 - 4
applications/money/money-server/src/main/java/com/usoftchina/saas/money/service/impl/FundtransferServiceImpl.java

@@ -11,9 +11,7 @@ import com.usoftchina.saas.commons.po.BillCodeSeq;
 import com.usoftchina.saas.commons.po.Status;
 import com.usoftchina.saas.context.BaseContextHolder;
 import com.usoftchina.saas.exception.BizException;
-import com.usoftchina.saas.money.mapper.BanksubledgerMapper;
-import com.usoftchina.saas.money.mapper.FundtransferMapper;
-import com.usoftchina.saas.money.mapper.FundtransferdetailMapper;
+import com.usoftchina.saas.money.mapper.*;
 import com.usoftchina.saas.money.po.*;
 import com.usoftchina.saas.money.service.FundtransferService;
 import com.usoftchina.saas.page.PageRequest;
@@ -38,6 +36,8 @@ public class FundtransferServiceImpl implements FundtransferService {
     private MaxnumberService maxnumberService;
     @Autowired
     private BanksubledgerMapper banksubledgerMapper;
+    @Autowired
+    private PaybalanceMapper paybalanceMapper;
 
     @Override
     public DocBaseDTO insert(Fundtran fundtran) {
@@ -101,17 +101,32 @@ public class FundtransferServiceImpl implements FundtransferService {
             }
         }
 
-        //取从表金额
+        //取从表金额更新中间表、资金账号表
         List<Fundtransferdetail> fundtransferdetailList = fundtran.getItems();
         Iterator isList = fundtransferdetailList.iterator();
         while (isList.hasNext()){
             Fundtransferdetail fundtransferdetail = (Fundtransferdetail) isList.next();
             Double amount = banksubledgerMapper.selectThisamount(fundtransferdetail.getFtd_bankcode());
             Double inamount = banksubledgerMapper.selectThisamount(fundtransferdetail.getFtd_inbankcode());
+
+            //中间表
             banksubledgerMapper.updateBankcode(amount, fundtransferdetail.getFtd_nowbalance(),
                     fundtransferdetail.getFtd_bankcode(), "-");
             banksubledgerMapper.updateBankcode(inamount, fundtransferdetail.getFtd_nowbalance(),
                     fundtransferdetail.getFtd_bankcode(), "+");
+
+            //资金账号表
+            int bk_id = fundtransferdetail.getFtd_bankid();
+            int bk_inid = fundtransferdetail.getFtd_inbankid();
+            Double bk_amount = paybalanceMapper.selectThisamount(bk_id) == null ? new Double(0) : paybalanceMapper.selectThisamount(bk_id);
+            Double bk_inamount = paybalanceMapper.selectThisamount(bk_inid) == null ? new Double(0) : paybalanceMapper.selectThisamount(bk_inid);
+
+            Double thisamount = bk_amount - fundtransferdetail.getFtd_nowbalance();
+            if (thisamount < 0){
+                throw new BizException(500, BizExceptionCode.BANK_AMOUNT_NOTENOUGH.getMessage());
+            }
+            paybalanceMapper.updateBankAmount(thisamount, bk_id);
+            paybalanceMapper.updateBankAmount(bk_inamount + fundtransferdetail.getFtd_nowbalance(), bk_inid);
         }
     }
 
@@ -139,6 +154,14 @@ public class FundtransferServiceImpl implements FundtransferService {
                     fundtransferdetail.getFtd_bankcode(), "+");
             banksubledgerMapper.updateBankcode(inamount, fundtransferdetail.getFtd_nowbalance(),
                     fundtransferdetail.getFtd_bankcode(), "-");
+
+            //资金账号表
+            int bk_id = fundtransferdetail.getFtd_bankid();
+            int bk_inid = fundtransferdetail.getFtd_inbankid();
+            Double bk_amount = paybalanceMapper.selectThisamount(bk_id) == null ? new Double(0) : paybalanceMapper.selectThisamount(bk_id);
+            Double bk_inamount = paybalanceMapper.selectThisamount(bk_inid) == null ? new Double(0) : paybalanceMapper.selectThisamount(bk_inid);
+            paybalanceMapper.updateBankAmount(bk_amount + fundtransferdetail.getFtd_nowbalance(), bk_id);
+            paybalanceMapper.updateBankAmount(bk_inamount - fundtransferdetail.getFtd_nowbalance(), bk_inid);
         }
     }
 

+ 33 - 4
applications/money/money-server/src/main/java/com/usoftchina/saas/money/service/impl/OthreceiptsServiceImpl.java

@@ -14,10 +14,8 @@ import com.usoftchina.saas.exception.BizException;
 import com.usoftchina.saas.money.mapper.BanksubledgerMapper;
 import com.usoftchina.saas.money.mapper.OthreceiptsMapper;
 import com.usoftchina.saas.money.mapper.OthreceiptsdetailMapper;
-import com.usoftchina.saas.money.po.Banksubledger;
-import com.usoftchina.saas.money.po.Othreceipts;
-import com.usoftchina.saas.money.po.Othreceiptsdetail;
-import com.usoftchina.saas.money.po.Othte;
+import com.usoftchina.saas.money.mapper.StatsinfoMapper;
+import com.usoftchina.saas.money.po.*;
 import com.usoftchina.saas.money.service.OthreceiptsService;
 import com.usoftchina.saas.page.PageRequest;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -42,6 +40,8 @@ public class OthreceiptsServiceImpl implements OthreceiptsService {
     private MaxnumberService maxnumberService;
     @Autowired
     private BanksubledgerMapper banksubledgerMapper;
+    @Autowired
+    private StatsinfoMapper statsinfoMapper;
 
     @Override
     public DocBaseDTO insert(Othte othte) {
@@ -114,6 +114,21 @@ public class OthreceiptsServiceImpl implements OthreceiptsService {
             banksubledgerMapper.updateBankcode(amount, othreceiptsdetail.getOrd_nowbalance(),
                     othreceipts.getOr_bankcode(), "+");
         }
+
+        //计算期间金额
+        Statsinfo statsinfo = new Statsinfo();
+        List<Integer> ymList = othreceiptsdetailMapper.selectYm(id);
+        Integer ym = ymList.indexOf(0);
+        System.out.println("ym:"+ym);
+        statsinfo.setCompanyid(BaseContextHolder.getCompanyId());
+        Integer yms = statsinfoMapper.select(ym, BaseContextHolder.getCompanyId());
+        statsinfo.setSi_yearmonth(Double.valueOf(ym));
+        statsinfo.setSi_amount_otherrec(othreceipts.getOr_amount());
+        if (yms == null){
+            statsinfoMapper.insert(statsinfo);
+        }else {
+            statsinfoMapper.update(statsinfo);
+        }
     }
 
     @Override
@@ -138,6 +153,20 @@ public class OthreceiptsServiceImpl implements OthreceiptsService {
                     othreceipts.getOr_bankcode(), "-");
         }
 
+        //计算期间金额
+        Statsinfo statsinfo = new Statsinfo();
+        List<Integer> ymList = othreceiptsdetailMapper.selectYm(id);
+        Integer ym = ymList.indexOf(0);
+        statsinfo.setCompanyid(BaseContextHolder.getCompanyId());
+        Integer yms = statsinfoMapper.select(ym, BaseContextHolder.getCompanyId());
+        statsinfo.setSi_yearmonth(Double.valueOf(ym));
+        statsinfo.setSi_amount_otherrec(othreceipts.getOr_amount());
+        if (yms == null){
+            statsinfoMapper.insert(statsinfo);
+        }else {
+            statsinfoMapper.update(statsinfo);
+        }
+
     }
 
 

+ 34 - 4
applications/money/money-server/src/main/java/com/usoftchina/saas/money/service/impl/OthspendingsServiceImpl.java

@@ -14,10 +14,8 @@ import com.usoftchina.saas.exception.BizException;
 import com.usoftchina.saas.money.mapper.BanksubledgerMapper;
 import com.usoftchina.saas.money.mapper.OthspendingsMapper;
 import com.usoftchina.saas.money.mapper.OthspendingsdetailMapper;
-import com.usoftchina.saas.money.po.Banksubledger;
-import com.usoftchina.saas.money.po.Othsp;
-import com.usoftchina.saas.money.po.Othspendings;
-import com.usoftchina.saas.money.po.Othspendingsdetail;
+import com.usoftchina.saas.money.mapper.StatsinfoMapper;
+import com.usoftchina.saas.money.po.*;
 import com.usoftchina.saas.money.service.OthspendingsService;
 import com.usoftchina.saas.page.PageRequest;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -41,6 +39,8 @@ public class OthspendingsServiceImpl implements OthspendingsService {
     private MaxnumberService maxnumberService;
     @Autowired
     private BanksubledgerMapper banksubledgerMapper;
+    @Autowired
+    private StatsinfoMapper statsinfoMapper;
 
     @Override
     public DocBaseDTO insert(Othsp othsp) {
@@ -146,6 +146,21 @@ public class OthspendingsServiceImpl implements OthspendingsService {
             banksubledgerMapper.updateBankcode(amount, othspendingsdetail.getOsd_nowbalance(),
                     othspendings.getOs_bankcode(), "+");
         }
+
+        //计算期间金额
+        Statsinfo statsinfo = new Statsinfo();
+        List<Integer> ymList = othspendingsdetailMapper.selectYm(id);
+        Integer ym = ymList.indexOf(0);
+        System.out.println("ym:"+ym);
+        statsinfo.setCompanyid(BaseContextHolder.getCompanyId());
+        Integer yms = statsinfoMapper.select(ym, BaseContextHolder.getCompanyId());
+        statsinfo.setSi_yearmonth(Double.valueOf(ym));
+        statsinfo.setSi_amount_otherpay(othspendings.getOs_amount());
+        if (yms == null){
+            statsinfoMapper.insert(statsinfo);
+        }else {
+            statsinfoMapper.update(statsinfo);
+        }
     }
 
     @Override
@@ -170,6 +185,21 @@ public class OthspendingsServiceImpl implements OthspendingsService {
             banksubledgerMapper.updateBankcode(amount, othspendingsdetail.getOsd_nowbalance(),
                     othspendings.getOs_bankcode(), "-");
         }
+
+        //计算期间金额
+        Statsinfo statsinfo = new Statsinfo();
+        List<Integer> ymList = othspendingsdetailMapper.selectYm(id);
+        Integer ym = ymList.indexOf(0);
+        System.out.println("ym:"+ym);
+        statsinfo.setCompanyid(BaseContextHolder.getCompanyId());
+        Integer yms = statsinfoMapper.select(ym, BaseContextHolder.getCompanyId());
+        statsinfo.setSi_yearmonth(Double.valueOf(ym));
+        statsinfo.setSi_amount_otherpay(othspendings.getOs_amount());
+        if (yms == null){
+            statsinfoMapper.insert(statsinfo);
+        }else {
+            statsinfoMapper.update(statsinfo);
+        }
     }
 
     @Override

+ 30 - 1
applications/money/money-server/src/main/java/com/usoftchina/saas/money/service/impl/PaybalanceServiceImpl.java

@@ -40,6 +40,8 @@ public class PaybalanceServiceImpl implements PaybalanceService {
     private SubledgerMapper subledgerMapper;
     @Autowired
     private BanksubledgerMapper banksubledgerMapper;
+    @Autowired
+    private StatsinfoMapper statsinfoMapper;
 
     public DocBaseDTO insert(Pay pay) {
         Paybalance paybalance = pay.getMain();
@@ -243,6 +245,20 @@ public class PaybalanceServiceImpl implements PaybalanceService {
             subledgerMapper.updateByPrimaryKeySelective(subledger1);
         }
 
+        //计算期间金额
+        Statsinfo statsinfo = new Statsinfo();
+        List<Integer> ymList = paybalancedetMapper.selectYm(id);
+        Integer ym = ymList.indexOf(0);
+        System.out.println("ym:"+ym);
+        statsinfo.setCompanyid(BaseContextHolder.getCompanyId());
+        Integer yms = statsinfoMapper.select(ym, BaseContextHolder.getCompanyId());
+        statsinfo.setSi_yearmonth(Double.valueOf(ym));
+        statsinfo.setSi_amount_pay(100.0);
+        if (yms == null){
+            statsinfoMapper.insert(statsinfo);
+        }else {
+            statsinfoMapper.update(statsinfo);
+        }
     }
 
     @Override
@@ -308,7 +324,20 @@ public class PaybalanceServiceImpl implements PaybalanceService {
         subledgerMapper.deleteByPrimaryKey(paybalance.getPb_code(), paybalance.getPb_kind());
         banksubledgerMapper.deleteByPrimaryKey(paybalance.getPb_code(), paybalance.getPb_kind());
 
-
+        //计算期间金额
+        Statsinfo statsinfo = new Statsinfo();
+        List<Integer> ymList = paybalancedetMapper.selectYm(id);
+        Integer ym = ymList.indexOf(0);
+        System.out.println("ym:"+ym);
+        statsinfo.setCompanyid(BaseContextHolder.getCompanyId());
+        Integer yms = statsinfoMapper.select(ym, BaseContextHolder.getCompanyId());
+        statsinfo.setSi_yearmonth(Double.valueOf(ym));
+        statsinfo.setSi_amount_pay(100.0);
+        if (yms == null){
+            statsinfoMapper.insert(statsinfo);
+        }else {
+            statsinfoMapper.update(statsinfo);
+        }
     }
 
 

+ 32 - 0
applications/money/money-server/src/main/java/com/usoftchina/saas/money/service/impl/RecbalanceServiceImpl.java

@@ -40,6 +40,8 @@ public class RecbalanceServiceImpl implements RecbalanceService {
     private BanksubledgerMapper banksubledgerMapper;
     @Autowired
     private SubledgerMapper subledgerMapper;
+    @Autowired
+    private StatsinfoMapper statsinfoMapper;
 
     @Override
     public DocBaseDTO insert(Rec rec) {
@@ -269,6 +271,21 @@ public class RecbalanceServiceImpl implements RecbalanceService {
             subledger1.setSl_namount(namount-nowBalance);//未核销
             subledgerMapper.updateByPrimaryKeySelective(subledger1);
         }
+
+        //计算期间金额
+        Statsinfo statsinfo = new Statsinfo();
+        List<Integer> ymList = recbalancedetMapper.selectYm(id);
+        Integer ym = ymList.indexOf(0);
+        System.out.println("ym:"+ym);
+        statsinfo.setCompanyid(BaseContextHolder.getCompanyId());
+        Integer yms = statsinfoMapper.select(ym, BaseContextHolder.getCompanyId());
+        statsinfo.setSi_yearmonth(Double.valueOf(ym));
+        statsinfo.setSi_amount_rec(100.0);
+        if (yms == null){
+            statsinfoMapper.insert(statsinfo);
+        }else {
+            statsinfoMapper.update(statsinfo);
+        }
     }
 
     @Override
@@ -334,6 +351,21 @@ public class RecbalanceServiceImpl implements RecbalanceService {
             subledger1.setSl_namount(namount+nowBalance);//未核销
             subledgerMapper.updateByPrimaryKeySelective(subledger1);
         }
+
+        //计算期间金额
+        Statsinfo statsinfo = new Statsinfo();
+        List<Integer> ymList = recbalancedetMapper.selectYm(Math.toIntExact(id));
+        Integer ym = ymList.indexOf(0);
+        System.out.println("ym:"+ym);
+        statsinfo.setCompanyid(BaseContextHolder.getCompanyId());
+        Integer yms = statsinfoMapper.select(ym, BaseContextHolder.getCompanyId());
+        statsinfo.setSi_yearmonth(Double.valueOf(ym));
+        statsinfo.setSi_amount_rec(100.0);
+        if (yms == null){
+            statsinfoMapper.insert(statsinfo);
+        }else {
+            statsinfoMapper.update(statsinfo);
+        }
     }
 
     public PageInfo<Recbalance> selectList(PageRequest page, ListReqDTO reqDTO) {

+ 2 - 2
applications/money/money-server/src/main/resources/mapper/OthreceiptsMapper.xml

@@ -324,7 +324,7 @@
         ${con}
       </if>
       <if test="companyId != null">
-        and   othreceipts.companyId = #{companyId}
+        and   othreceipts.companyId = #{companyId, jdbcType=INTEGER}
       </if>
     </where>  order by or_date desc
   </select>
@@ -339,7 +339,7 @@
         ${con}
       </if>
       <if test="companyId != null">
-        and   othreceipts.companyId = #{companyId}
+        and   othreceipts.companyId = #{companyId, jdbcType=INTEGER}
       </if>
     </where>  order by or_date desc
   </select>

+ 4 - 0
applications/money/money-server/src/main/resources/mapper/OthreceiptsdetailMapper.xml

@@ -207,4 +207,8 @@
       ord_text5 = #{ordText5,jdbcType=VARCHAR}
     where ord_id = #{ordId,jdbcType=INTEGER}
   </update>
+
+  <select id="selectYm" parameterType="java.lang.Integer" resultType="java.lang.Integer">
+    select ord_ym from othreceiptsdetail where ord_orid = #{id,jdbcType=INTEGER}
+  </select>
 </mapper>

+ 4 - 0
applications/money/money-server/src/main/resources/mapper/OthspendingsdetailMapper.xml

@@ -213,4 +213,8 @@
       osd_text5 = #{osdText5,jdbcType=VARCHAR}
     where osd_id = #{osdId,jdbcType=INTEGER}
   </update>
+
+  <select id="selectYm" parameterType="java.lang.Integer" resultType="java.lang.Integer">
+    select osd_ym from othspendingsdetail where osd_orid = #{id,jdbcType=INTEGER}
+  </select>
 </mapper>

+ 11 - 2
applications/money/money-server/src/main/resources/mapper/PaybalanceMapper.xml

@@ -428,7 +428,7 @@
       <if test="companyId != null">
         and   paybalance.companyId = #{companyId}
       </if>
-    </where>  order by pb_id
+    </where>  order by pb_date desc, order by pb_code
   </select>
 
   <select id="selectPaybalanceListByCondition" resultMap="BaseResultMap">
@@ -443,7 +443,7 @@
       <if test="companyId != null">
         and   paybalance.companyId = #{companyId}
       </if>
-    </where>  order by pb_id
+    </where>  order by pb_date desc, order by pb_code
   </select>
 
   <select id="validateCodeWhenInsert" resultType="int">
@@ -576,6 +576,15 @@
     where bk_id = #{id,jdbcType=INTEGER}
   </update>
 
+  <update id="updateBankAmount" >
+    update bankinformation set bk_thisamount = #{bk_thisamount,jdbcType=DOUBLE}
+     where bk_id = #{id,jdbcType=INTEGER}
+  </update>
+
+<select id="selectThisamount" parameterType="java.lang.Integer" resultType="java.lang.Double">
+  select bk_thisamount from bankinformation where bk_id = #{id,jdbcType=INTEGER}
+</select>
+
 <!-- 供应商-->
   <resultMap id="VendorResultMapper" type="com.usoftchina.saas.money.po.Vendor">
     <id column="ve_id" property="id" jdbcType="INTEGER" />

+ 4 - 0
applications/money/money-server/src/main/resources/mapper/PaybalancedetMapper.xml

@@ -287,4 +287,8 @@
       </if>
     </where>  order by pb_id
   </select>
+
+  <select id="selectYm" parameterType="java.lang.Integer" resultType="java.lang.Integer">
+    select pd_ym from paybalancedet where pd_pbid = #{id,jdbcType=INTEGER}
+  </select>
 </mapper>

+ 3 - 0
applications/money/money-server/src/main/resources/mapper/RecbalancedetMapper.xml

@@ -294,4 +294,7 @@
     where rd_id = #{id,jdbcType=INTEGER}
   </update>
 
+  <select id="selectYm" parameterType="java.lang.Integer" resultType="java.lang.Integer">
+    select rd_ym from recbalancedet where rd_rbid = #{id,jdbcType=INTEGER}
+  </select>
 </mapper>

+ 103 - 0
applications/money/money-server/src/main/resources/mapper/StatsinfoMapper.xml

@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.usoftchina.saas.money.mapper.StatsinfoMapper" >
+    <resultMap id="BaseResultMap" type="com.usoftchina.saas.money.po.Statsinfo">
+        <result column="si_yearmonth" jdbcType="DOUBLE" property="si_yearmonth" />
+        <result column="si_amount_pay" jdbcType="DOUBLE" property="si_amount_pay" />
+        <result column="si_amount_otherpay" jdbcType="DOUBLE" property="si_amount_otherpay" />
+        <result column="si_amount_rec" jdbcType="DOUBLE" property="si_amount_rec" />
+        <result column="si_amount_otherrec" jdbcType="DOUBLE" property="si_amount_otherrec" />
+        <result column="companyid" jdbcType="INTEGER" property="companyid" />
+        <result column="si_type" jdbcType="VARCHAR" property="si_type" />
+    </resultMap>
+
+    <insert id="insert" parameterType="com.usoftchina.saas.money.po.Statsinfo">
+        insert into statsinfo
+        <trim prefix="(" suffix=")" suffixOverrides="," >
+        <if test="si_yearmonth != null" >
+            si_yearmonth,
+        </if>
+        <if test="si_amount_pay != null" >
+            si_amount_pay,
+        </if>
+        <if test="si_amount_otherpay != null" >
+            si_amount_otherpay,
+        </if>
+        <if test="si_amount_rec != null" >
+            si_amount_rec,
+        </if>
+        <if test="si_amount_otherrec != null" >
+            si_amount_otherrec,
+        </if>
+        <if test="companyid != null" >
+            companyid,
+        </if>
+            si_type,
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides="," >
+            <if test="si_yearmonth != null" >
+                #{si_yearmonth,jdbcType=INTEGER},
+            </if>
+            <if test="si_amount_pay != null" >
+                select sum(pd_amount) from paybalancedet left join paybalance on pd_pbid=pb_id
+                where paybalance.companyId= #{companyid,jdbcType=INTEGER}
+                and pd_ym=#{si_yearmonth,jdbcType=INTEGER} and pb_statuscode='AUDITED',
+            </if>
+            <if test="si_amount_otherpay != null" >
+                (select sum(os_amount) from othspendings RIGHT JOIN othspendingsdetail on os_id = osd_orid
+                where othspendingsdetail.companyId=#{companyid,jdbcType=INTEGER}
+                and osd_ym=#{si_yearmonth,jdbcType=INTEGER} and os_statuscode='AUDITED'),
+            </if>
+            <if test="si_amount_rec != null" >
+                (select sum(rd_amount) from recbalancedet left join recbalance on rd_rbid=rb_id
+                where recbalancedet.companyId=#{companyid,jdbcType=INTEGER}
+                and rd_ym=#{si_yearmonth,jdbcType=INTEGER} and rb_statuscode='AUDITED'),
+            </if>
+            <if test="si_amount_otherrec != null" >
+                (select  sum(or_amount) from othreceipts RIGHT JOIN othreceiptsdetail on or_id = ord_orid
+                where othreceiptsdetail.companyId=#{companyid,jdbcType=INTEGER}
+                and ord_ym=#{si_yearmonth,jdbcType=INTEGER} and or_statuscode='AUDITED'),
+            </if>
+            <if test="companyid != null" >
+                #{companyid,jdbcType=INTEGER},
+            </if>
+                'FUND',
+        </trim>
+    </insert>
+
+    <update id="update" parameterType="com.usoftchina.saas.money.po.Statsinfo" >
+        update statsinfo
+        <set >
+            <if test="si_amount_pay != null" >
+                si_amount_pay =
+                (select sum(pd_amount) from paybalancedet left join paybalance on pd_pbid=pb_id
+                where paybalance.companyId= #{companyid,jdbcType=INTEGER}
+                and pd_ym=#{si_yearmonth,jdbcType=INTEGER} and pb_statuscode='AUDITED'),
+            </if>
+            <if test="si_amount_otherpay != null" >
+                si_amount_otherpay =
+                (select sum(os_amount) from othspendings RIGHT JOIN othspendingsdetail on os_id = osd_orid
+                where othspendingsdetail.companyId=#{companyid,jdbcType=INTEGER}
+                and osd_ym=#{si_yearmonth,jdbcType=INTEGER} and os_statuscode='AUDITED'),
+            </if>
+            <if test="si_amount_rec != null" >
+                si_amount_rec =
+                (select sum(rd_amount) from recbalancedet left join recbalance on rd_rbid=rb_id
+                where recbalancedet.companyId=#{companyid,jdbcType=INTEGER}
+                and rd_ym=#{si_yearmonth,jdbcType=INTEGER} and rb_statuscode='AUDITED'),
+            </if>
+            <if test="si_amount_otherrec != null" >
+                si_amount_otherrec =
+                (select  sum(or_amount) from othreceipts RIGHT JOIN othreceiptsdetail on or_id = ord_orid
+                where othreceiptsdetail.companyId=#{companyid,jdbcType=INTEGER}
+                and ord_ym=#{si_yearmonth,jdbcType=INTEGER} and or_statuscode='AUDITED'),
+            </if>
+        </set>
+        where si_yearmonth = #{si_yearmonth,jdbcType=INTEGER} and companyid = #{companyid,jdbcType=INTEGER}
+        and si_type = 'FUND'
+    </update>
+
+    <select id="select" resultType="java.lang.Integer">
+        select DISTINCT si_yearmonth from statsinfo where si_yearmonth =#{si_yearmonth,jdbcType=INTEGER} and companyid = #{companyid,jdbcType=INTEGER}
+    </select>
+</mapper>

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

@@ -177,3 +177,4 @@ auth:
     - /api/auth/authorize
     - /api/account/account/register
     - /api/account/company/register
+    - /api/auth/info

+ 23 - 0
base-servers/mail/mail-api/pom.xml

@@ -11,4 +11,27 @@
 
     <artifactId>mail-api</artifactId>
     <description>mail api</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.usoftchina.saas</groupId>
+            <artifactId>core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.usoftchina.saas</groupId>
+            <artifactId>mail-dto</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context-support</artifactId>
+        </dependency>
+    </dependencies>
 </project>

+ 191 - 0
base-servers/mail/mail-api/src/main/java/com/usoftchina/saas/mail/MailBuilder.java

@@ -0,0 +1,191 @@
+package com.usoftchina.saas.mail;
+
+import com.usoftchina.saas.base.Result;
+import com.usoftchina.saas.context.SpringContextHolder;
+import com.usoftchina.saas.exception.BizException;
+import com.usoftchina.saas.mail.api.MailApi;
+import com.usoftchina.saas.mail.dto.TemplateMailMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.mail.SimpleMailMessage;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author yingp
+ * @date 2018/11/13
+ */
+public abstract class MailBuilder {
+
+    private Logger logger = LoggerFactory.getLogger(MailBuilder.class);
+
+    protected String from;
+    protected String[] to;
+    protected String[] cc;
+    protected String[] bcc;
+
+    /**
+     * 发送人
+     *
+     * @param from
+     * @return
+     */
+    public MailBuilder from(String from) {
+        this.from = from;
+        return this;
+    }
+
+    /**
+     * 接收人
+     *
+     * @param to
+     * @return
+     */
+    public MailBuilder to(String... to) {
+        this.to = to;
+        return this;
+    }
+
+    /**
+     * 接收人
+     *
+     * @param to
+     * @return
+     */
+    public MailBuilder to(List<String> to) {
+        this.to = to.toArray(new String[]{});
+        return this;
+    }
+
+    /**
+     * @param cc
+     * @return
+     */
+    public MailBuilder cc(String... cc) {
+        this.cc = cc;
+        return this;
+    }
+
+    /**
+     * @param cc
+     * @return
+     */
+    public MailBuilder cc(List<String> cc) {
+        this.cc = cc.toArray(new String[]{});
+        return this;
+    }
+
+    /**
+     * @param bcc
+     * @return
+     */
+    public MailBuilder bcc(String... bcc) {
+        this.bcc = bcc;
+        return this;
+    }
+
+    /**
+     * @param bcc
+     * @return
+     */
+    public MailBuilder bcc(List<String> bcc) {
+        this.bcc = bcc.toArray(new String[]{});
+        return this;
+    }
+
+    /**
+     * 发送邮件
+     *
+     * @param api
+     * @return
+     */
+    protected abstract Result send(MailApi api);
+
+    /**
+     * 发送邮件
+     */
+    public void send() {
+        MailApi api = SpringContextHolder.getBean(MailApi.class);
+        Result result = send(api);
+        if (!result.isSuccess()) {
+            logger.error("failed to send mail, " + result.getMessage());
+            throw new BizException(result.getCode(), result.getMessage());
+        }
+    }
+
+    public static SimpleMailBuilder simple() {
+        return new SimpleMailBuilder();
+    }
+
+    public static TemplateMailBuilder template(String templateId) {
+        return new TemplateMailBuilder(templateId);
+    }
+
+    private static class SimpleMailBuilder extends MailBuilder{
+        private String subject;
+        private String text;
+
+        /**
+         * 邮件主题
+         *
+         * @param subject
+         * @return
+         */
+        public MailBuilder subject(String subject) {
+            this.subject = subject;
+            return this;
+        }
+
+        /**
+         * 邮件内容
+         *
+         * @param text
+         * @return
+         */
+        public MailBuilder text(String text) {
+            this.text = text;
+            return this;
+        }
+
+        @Override
+        protected Result send(MailApi api) {
+            SimpleMailMessage message = new SimpleMailMessage();
+            message.setFrom(from);
+            message.setTo(to);
+            message.setCc(cc);
+            message.setBcc(bcc);
+            message.setSubject(subject);
+            message.setText(text);
+            return api.send(message);
+        }
+    }
+
+    private static class TemplateMailBuilder extends MailBuilder{
+        private String templateId;
+        private Map<String, Object> metadata;
+
+        public TemplateMailBuilder(String templateId) {
+            this.templateId = templateId;
+        }
+
+        public TemplateMailBuilder metadata(Map<String, Object> metadata) {
+            this.metadata = metadata;
+            return this;
+        }
+
+        public TemplateMailBuilder set(String key, String value) {
+            if (null == metadata) {
+                metadata = new HashMap<>(1);
+            }
+            metadata.put(key, value);
+            return this;
+        }
+
+        @Override
+        protected Result send(MailApi api) {
+            return api.sendTemplate(new TemplateMailMessage(templateId, to, cc, bcc, metadata));
+        }
+    }
+}

+ 33 - 0
base-servers/mail/mail-api/src/main/java/com/usoftchina/saas/mail/api/MailApi.java

@@ -0,0 +1,33 @@
+package com.usoftchina.saas.mail.api;
+
+import com.usoftchina.saas.base.Result;
+import com.usoftchina.saas.mail.dto.TemplateMailMessage;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.mail.SimpleMailMessage;
+import org.springframework.web.bind.annotation.PostMapping;
+
+/**
+ * 邮件接口
+ *
+ * @author yingp
+ * @date 2018/11/13
+ */
+@FeignClient(name = "mail-server")
+public interface MailApi {
+    /**
+     * 发送邮件
+     *
+     * @param message
+     * @return
+     */
+    @PostMapping(value = "/send")
+    Result send(SimpleMailMessage message);
+    /**
+     * 指定模板发送邮件
+     *
+     * @param message
+     * @return
+     */
+    @PostMapping(value = "/template/send")
+    Result sendTemplate(TemplateMailMessage message);
+}

+ 0 - 1
base-servers/mail/mail-dto/pom.xml

@@ -12,5 +12,4 @@
     <artifactId>mail-dto</artifactId>
     <description>mail data transfer object</description>
 
-
 </project>

+ 0 - 11
base-servers/mail/mail-dto/src/main/java/com/usoftchina/saas/mail/dto/MailDto.java

@@ -1,11 +0,0 @@
-package com.usoftchina.saas.mail.dto;
-
-import java.io.Serializable;
-
-/**
- * @author yingp
- * @date 2018/10/3
- */
-public class MailDto implements Serializable {
-
-}

+ 57 - 0
base-servers/mail/mail-dto/src/main/java/com/usoftchina/saas/mail/dto/MailLogDTO.java

@@ -0,0 +1,57 @@
+package com.usoftchina.saas.mail.dto;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @author yingp
+ * @date 2018/11/13
+ */
+public class MailLogDTO implements Serializable{
+    private String subject;
+    private String message;
+    private String recipients;
+    private Date createTime;
+
+    public String getSubject() {
+        return subject;
+    }
+
+    public void setSubject(String subject) {
+        this.subject = subject;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public String getRecipients() {
+        return recipients;
+    }
+
+    public void setRecipients(String recipients) {
+        this.recipients = recipients;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    @Override
+    public String toString() {
+        return "MailLogDTO{" +
+                "subject='" + subject + '\'' +
+                ", message='" + message + '\'' +
+                ", recipients='" + recipients + '\'' +
+                ", createTime=" + createTime +
+                '}';
+    }
+}

+ 89 - 0
base-servers/mail/mail-dto/src/main/java/com/usoftchina/saas/mail/dto/TemplateMailMessage.java

@@ -0,0 +1,89 @@
+package com.usoftchina.saas.mail.dto;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * @author yingp
+ * @date 2018/11/13
+ */
+public class TemplateMailMessage implements Serializable{
+    private String templateId;
+    private String from;
+    private String[] to;
+    private String[] cc;
+    private String[] bcc;
+    private Map<String, Object> metadata;
+
+    public TemplateMailMessage() {
+    }
+
+    public TemplateMailMessage(String templateId, String from, String[] to, String[] cc, String[] bcc, Map<String, Object> metadata) {
+        this.templateId = templateId;
+        this.from = from;
+        this.to = to;
+        this.cc = cc;
+        this.bcc = bcc;
+        this.metadata = metadata;
+    }
+
+    public String getFrom() {
+        return from;
+    }
+
+    public void setFrom(String from) {
+        this.from = from;
+    }
+
+    public String[] getTo() {
+        return to;
+    }
+
+    public void setTo(String[] to) {
+        this.to = to;
+    }
+
+    public String[] getCc() {
+        return cc;
+    }
+
+    public void setCc(String[] cc) {
+        this.cc = cc;
+    }
+
+    public String[] getBcc() {
+        return bcc;
+    }
+
+    public void setBcc(String[] bcc) {
+        this.bcc = bcc;
+    }
+
+    public String getTemplateId() {
+        return templateId;
+    }
+
+    public void setTemplateId(String templateId) {
+        this.templateId = templateId;
+    }
+
+    public Map<String, Object> getMetadata() {
+        return metadata;
+    }
+
+    public void setMetadata(Map<String, Object> metadata) {
+        this.metadata = metadata;
+    }
+
+    @Override
+    public String toString() {
+        return "TemplateMailMessage{" +
+                "templateId='" + templateId + '\'' +
+                ", from='" + from + '\'' +
+                ", to=" + Arrays.toString(to) +
+                ", cc=" + Arrays.toString(cc) +
+                ", bcc=" + Arrays.toString(bcc) +
+                ", metadata=" + metadata +
+                '}';
+    }
+}

+ 11 - 25
base-servers/mail/mail-server/pom.xml

@@ -19,7 +19,7 @@
         </dependency>
         <dependency>
             <groupId>com.usoftchina.saas</groupId>
-            <artifactId>core</artifactId>
+            <artifactId>server-starter</artifactId>
         </dependency>
         <dependency>
             <groupId>com.usoftchina.saas</groupId>
@@ -27,30 +27,7 @@
         </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-web</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.hibernate</groupId>
-                    <artifactId>hibernate-validator</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.apache.tomcat.embed</groupId>
-                    <artifactId>tomcat-embed-websocket</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <!-- management -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-actuator</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-security</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.cloud</groupId>
-            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
+            <artifactId>spring-boot-starter-mail</artifactId>
         </dependency>
         <!-- db -->
         <dependency>
@@ -61,6 +38,10 @@
             <groupId>org.mybatis.spring.boot</groupId>
             <artifactId>mybatis-spring-boot-starter</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.github.pagehelper</groupId>
+            <artifactId>pagehelper-spring-boot-starter</artifactId>
+        </dependency>
         <!-- api doc -->
         <dependency>
             <groupId>io.springfox</groupId>
@@ -70,6 +51,11 @@
             <groupId>io.springfox</groupId>
             <artifactId>springfox-swagger2</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>org.freemarker</groupId>
+            <artifactId>freemarker</artifactId>
+        </dependency>
     </dependencies>
 
     <build>

+ 6 - 0
base-servers/mail/mail-server/src/main/java/com/usoftchina/saas/mail/MailApplication.java

@@ -1,8 +1,11 @@
 package com.usoftchina.saas.mail;
 
+import com.usoftchina.saas.auth.client.EnableAuthClient;
+import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
 
 /**
  * @author yingp
@@ -10,6 +13,9 @@ import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
  */
 @SpringBootApplication
 @EnableEurekaClient
+@EnableAuthClient
+@MapperScan
+@EnableTransactionManagement
 public class MailApplication {
     public static void main(String[] args) {
         SpringApplication.run(MailApplication.class, args);

+ 88 - 0
base-servers/mail/mail-server/src/main/java/com/usoftchina/saas/mail/controller/MailController.java

@@ -0,0 +1,88 @@
+package com.usoftchina.saas.mail.controller;
+
+import com.usoftchina.saas.base.Result;
+import com.usoftchina.saas.mail.dto.TemplateMailMessage;
+import com.usoftchina.saas.mail.po.MailLog;
+import com.usoftchina.saas.mail.po.MailTemplate;
+import com.usoftchina.saas.mail.service.MailLogService;
+import com.usoftchina.saas.mail.service.MailTemplateService;
+import freemarker.template.Template;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mail.SimpleMailMessage;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+
+/**
+ * @author yingp
+ * @date 2018/11/13
+ */
+@RestController
+@RequestMapping
+public class MailController {
+
+    @Autowired
+    private MailTemplateService mailTemplateService;
+
+    @Autowired
+    private MailLogService mailLogService;
+
+    @Autowired
+    private JavaMailSender javaMailSender;
+
+    /**
+     * 发送邮件
+     *
+     * @param message
+     * @return
+     */
+    @PostMapping(value = "/send")
+    public Result send(SimpleMailMessage message) {
+        javaMailSender.send(message);
+        mailLogService.save(new MailLog(message));
+        return Result.success();
+    }
+
+    /**
+     * 指定模板发送邮件
+     *
+     * @param message
+     * @return
+     */
+    @PostMapping(value = "/template/send")
+    public Result sendTemplate(TemplateMailMessage message) throws Exception{
+        SimpleMailMessage mailMessage = getMessageByTemplate(message);
+        javaMailSender.send(mailMessage);
+        MailLog log = new MailLog(mailMessage);
+        log.setTemplateId(message.getTemplateId());
+        mailLogService.save(log);
+        return Result.success();
+    }
+
+    /**
+     * freemarker模板处理
+     *
+     * @param message
+     * @return
+     * @throws Exception
+     */
+    private SimpleMailMessage getMessageByTemplate(TemplateMailMessage message) throws Exception{
+        MailTemplate mailTemplate = mailTemplateService.findByPrimaryKey(message.getTemplateId());
+        Template template = new Template(mailTemplate.getId(),
+                new StringReader(mailTemplate.getText()), null);
+        StringWriter text = new StringWriter();
+        template.process(message.getMetadata(), text);
+        SimpleMailMessage mailMessage = new SimpleMailMessage();
+        mailMessage.setBcc(message.getBcc());
+        mailMessage.setCc(message.getCc());
+        mailMessage.setTo(message.getTo());
+        mailMessage.setFrom(message.getFrom());
+        mailMessage.setSubject(mailTemplate.getSubject());
+        mailMessage.setText(text.toString());
+        return mailMessage;
+    }
+}

+ 26 - 0
base-servers/mail/mail-server/src/main/java/com/usoftchina/saas/mail/mapper/MailLogMapper.java

@@ -0,0 +1,26 @@
+package com.usoftchina.saas.mail.mapper;
+
+import com.usoftchina.saas.mail.po.MailLog;
+
+import java.util.List;
+
+/**
+ * @author yingp
+ * @date 2018/11/13
+ */
+public interface MailLogMapper {
+    /**
+     * 新增
+     *
+      * @param log
+     * @return
+     */
+    int insert(MailLog log);
+
+    /**
+     * 查找
+     *
+     * @return
+     */
+    List<MailLog> selectAll();
+}

+ 40 - 0
base-servers/mail/mail-server/src/main/java/com/usoftchina/saas/mail/mapper/MailTemplateMapper.java

@@ -0,0 +1,40 @@
+package com.usoftchina.saas.mail.mapper;
+
+import com.usoftchina.saas.mail.po.MailTemplate;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * @author yingp
+ * @date 2018/11/13
+ */
+public interface MailTemplateMapper {
+    /**
+     * 新增
+     *
+     * @param template
+     * @return
+     */
+    int insert(MailTemplate template);
+
+    /**
+     * 更新
+     * @param template
+     * @return
+     */
+    int updateByPrimaryKey(MailTemplate template);
+
+    /**
+     * 删除
+     *
+     * @param id
+     * @return
+     */
+    int deleteByPrimaryKey(@Param("id") String id);
+    /**
+     * 查询
+     *
+     * @param id
+     * @return
+     */
+    MailTemplate selectByPrimaryKey(@Param("id") String id);
+}

+ 110 - 0
base-servers/mail/mail-server/src/main/java/com/usoftchina/saas/mail/po/MailLog.java

@@ -0,0 +1,110 @@
+package com.usoftchina.saas.mail.po;
+
+import com.usoftchina.saas.context.BaseContextHolder;
+import com.usoftchina.saas.utils.StringUtils;
+import org.springframework.mail.SimpleMailMessage;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @author yingp
+ * @date 2018/11/13
+ */
+public class MailLog implements Serializable{
+    private Long id;
+    private String templateId;
+    private String subject;
+    private String text;
+    private String from;
+    private String to;
+    private Long companyId;
+    private Long creatorId;
+    private Date createTime;
+
+    public MailLog() {
+        this.companyId = BaseContextHolder.getCompanyId();
+        this.creatorId = BaseContextHolder.getUserId();
+        this.createTime = new Date();
+    }
+
+    public MailLog(SimpleMailMessage message) {
+        this();
+        this.from = message.getFrom();
+        this.to = StringUtils.arrayToCommaDelimitedString(message.getTo());
+        this.subject = message.getSubject();
+        this.text = message.getText();
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getTemplateId() {
+        return templateId;
+    }
+
+    public void setTemplateId(String templateId) {
+        this.templateId = templateId;
+    }
+
+    public Long getCompanyId() {
+        return companyId;
+    }
+
+    public void setCompanyId(Long companyId) {
+        this.companyId = companyId;
+    }
+
+    public String getSubject() {
+        return subject;
+    }
+
+    public void setSubject(String subject) {
+        this.subject = subject;
+    }
+
+    public String getText() {
+        return text;
+    }
+
+    public void setText(String text) {
+        this.text = text;
+    }
+
+    public String getFrom() {
+        return from;
+    }
+
+    public void setFrom(String from) {
+        this.from = from;
+    }
+
+    public String getTo() {
+        return to;
+    }
+
+    public void setTo(String to) {
+        this.to = to;
+    }
+
+    public Long getCreatorId() {
+        return creatorId;
+    }
+
+    public void setCreatorId(Long creatorId) {
+        this.creatorId = creatorId;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+}

+ 38 - 0
base-servers/mail/mail-server/src/main/java/com/usoftchina/saas/mail/po/MailTemplate.java

@@ -0,0 +1,38 @@
+package com.usoftchina.saas.mail.po;
+
+import java.io.Serializable;
+
+/**
+ * @author yingp
+ * @date 2018/11/13
+ */
+public class MailTemplate implements Serializable{
+
+    private String id;
+    private String subject;
+    private String text;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getSubject() {
+        return subject;
+    }
+
+    public void setSubject(String subject) {
+        this.subject = subject;
+    }
+
+    public String getText() {
+        return text;
+    }
+
+    public void setText(String text) {
+        this.text = text;
+    }
+}

+ 29 - 0
base-servers/mail/mail-server/src/main/java/com/usoftchina/saas/mail/service/MailLogService.java

@@ -0,0 +1,29 @@
+package com.usoftchina.saas.mail.service;
+
+import com.github.pagehelper.PageInfo;
+import com.usoftchina.saas.mail.dto.MailLogDTO;
+import com.usoftchina.saas.mail.po.MailLog;
+import com.usoftchina.saas.page.PageRequest;
+
+/**
+ * @author yingp
+ * @date 2018/11/13
+ */
+public interface MailLogService {
+
+    /**
+     * 保存日志
+     *
+     * @param log
+     * @return
+     */
+    boolean save(MailLog log);
+
+    /**
+     * 分页查找日志
+     *
+     * @param page
+     * @return
+     */
+    PageInfo<MailLogDTO> findPage(PageRequest page);
+}

+ 42 - 0
base-servers/mail/mail-server/src/main/java/com/usoftchina/saas/mail/service/MailTemplateService.java

@@ -0,0 +1,42 @@
+package com.usoftchina.saas.mail.service;
+
+import com.usoftchina.saas.mail.po.MailTemplate;
+
+/**
+ * @author yingp
+ * @date 2018/11/13
+ */
+public interface MailTemplateService {
+
+    /**
+     * 新增
+     *
+     * @param template
+     * @return
+     */
+    boolean save(MailTemplate template);
+
+    /**
+     * 更新
+     *
+     * @param template
+     * @return
+     */
+    boolean updateByPrimaryKey(MailTemplate template);
+
+    /**
+     * 删除
+     *
+     * @param id
+     * @return
+     */
+    boolean removeByPrimaryKey(String id);
+
+    /**
+     * 查找
+     *
+     * @param id
+     * @return
+     */
+    MailTemplate findByPrimaryKey(String id);
+}

+ 39 - 0
base-servers/mail/mail-server/src/main/java/com/usoftchina/saas/mail/service/impl/MailLogServiceImpl.java

@@ -0,0 +1,39 @@
+package com.usoftchina.saas.mail.service.impl;
+
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import com.usoftchina.saas.mail.dto.MailLogDTO;
+import com.usoftchina.saas.mail.mapper.MailLogMapper;
+import com.usoftchina.saas.mail.po.MailLog;
+import com.usoftchina.saas.mail.service.MailLogService;
+import com.usoftchina.saas.page.PageRequest;
+import com.usoftchina.saas.utils.BeanMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * @author yingp
+ * @date 2018/11/13
+ */
+@Service
+public class MailLogServiceImpl implements MailLogService{
+
+    @Autowired
+    private MailLogMapper mailLogMapper;
+
+    @Override
+    @Async
+    public boolean save(MailLog log) {
+        return mailLogMapper.insert(log) > 0;
+    }
+
+    @Override
+    public PageInfo<MailLogDTO> findPage(PageRequest page) {
+        PageHelper.startPage(page.getNumber(), page.getSize());
+        List<MailLog> logs = mailLogMapper.selectAll();
+        return new PageInfo<>(BeanMapper.mapList(logs, MailLogDTO.class));
+    }
+}

+ 38 - 0
base-servers/mail/mail-server/src/main/java/com/usoftchina/saas/mail/service/impl/MailTemplateServiceImpl.java

@@ -0,0 +1,38 @@
+package com.usoftchina.saas.mail.service.impl;
+
+import com.usoftchina.saas.mail.mapper.MailTemplateMapper;
+import com.usoftchina.saas.mail.po.MailTemplate;
+import com.usoftchina.saas.mail.service.MailTemplateService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author yingp
+ * @date 2018/11/13
+ */
+@Service
+public class MailTemplateServiceImpl implements MailTemplateService{
+
+    @Autowired
+    private MailTemplateMapper mailTemplateMapper;
+
+    @Override
+    public boolean save(MailTemplate template) {
+        return mailTemplateMapper.insert(template) > 0;
+    }
+
+    @Override
+    public boolean updateByPrimaryKey(MailTemplate template) {
+        return mailTemplateMapper.updateByPrimaryKey(template) > 0;
+    }
+
+    @Override
+    public boolean removeByPrimaryKey(String id) {
+        return mailTemplateMapper.deleteByPrimaryKey(id) > 0;
+    }
+
+    @Override
+    public MailTemplate findByPrimaryKey(String id) {
+        return mailTemplateMapper.selectByPrimaryKey(id);
+    }
+}

+ 85 - 0
base-servers/mail/mail-server/src/main/resources/application.yml

@@ -0,0 +1,85 @@
+spring:
+  application:
+    name: mail-server
+  security:
+    user:
+      name: admin
+      password: select111***
+  rabbitmq:
+    host: 192.168.0.176
+    port: 5672
+    virtual-host: dev
+    username: saas
+    password: select123***
+  zipkin:
+    sender:
+      type: rabbit
+    locator:
+      discovery:
+        enabled: true
+  sleuth:
+    sampler:
+      probability: 1.0
+  datasource:
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    url: jdbc:mysql://192.168.253.12:3306/saas_mail?characterEncoding=utf-8&useSSL=false
+    username: root
+    password: select111***
+    hikari:
+      minimum-idle: 5
+      maximum-pool-size: 50
+      idle-timeout: 30000
+      max-lifetime: 1800000
+      connection-timeout: 30000
+  messages:
+    basename: i18n/messages
+  redis:
+    host: 192.168.253.12
+    port: 6379
+  jackson:
+    date-format: yyyy-MM-dd HH:mm:ss
+    time-zone: GMT+8
+  mail:
+    host: smtp.mxhichina.com
+    username: service@ubtob.com
+    password: Aaabbb111
+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}@192.168.0.181:8510/eureka/
+server:
+  port: 8660
+  tomcat:
+    uri-encoding: UTF-8
+management:
+  endpoints:
+    web:
+      exposure:
+        include: "*"
+  endpoint:
+    health:
+      show-details: always
+    shutdown:
+      enabled: true
+    restart:
+      enabled: true
+info:
+  name: '@project.artifactId@'
+  description: '@project.description@'
+  version: '@project.version@'
+  spring-boot-version: '@spring.boot.version@'
+  spring-cloud-version: '@spring.cloud.version@'
+mybatis:
+  type-aliases-package: com.usoftchina.saas.mail.po
+  mapper-locations: classpath:mapper/*.xml
+auth:
+  public-key: auth/pub.key

+ 12 - 0
base-servers/mail/mail-server/src/main/resources/config/application-docker-dev.yml

@@ -0,0 +1,12 @@
+eureka:
+  instance:
+    hostname: saas-mail-server-dev
+    prefer-ip-address: false
+  client:
+    serviceUrl:
+      defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@saas-eureka-server-dev:8510/eureka/
+spring:
+  rabbitmq:
+    virtual-host: dev
+server:
+  port: 8670

+ 10 - 0
base-servers/mail/mail-server/src/main/resources/config/application-docker.yml

@@ -0,0 +1,10 @@
+eureka:
+  instance:
+    hostname: saas-mail-server
+    prefer-ip-address: false
+  client:
+    serviceUrl:
+      defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@saas-eureka-server:8500/eureka/
+spring:
+  rabbitmq:
+    virtual-host: docker

+ 0 - 0
base-servers/mail/mail-server/src/main/resources/i18n/messages_en_US.properties


+ 0 - 0
base-servers/mail/mail-server/src/main/resources/i18n/messages_zh_CN.properties


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

@@ -0,0 +1,113 @@
+<?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/mail-server"/>
+    <springProperty scope="context" name="spring.application.name" source="spring.application.name" defaultValue="mail-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.253.3: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>
+
+</configuration>

+ 31 - 0
base-servers/mail/mail-server/src/main/resources/mapper/MailLogMapper.xml

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.usoftchina.saas.mail.mapper.MailLogMapper">
+
+    <insert id="insert" parameterType="com.usoftchina.saas.mail.po.MailLog"
+            useGeneratedKeys="true" keyProperty="id">
+        insert into m_log(template_id,subject,text,to,company_id,creator_id,create_time)
+        values (#{templateId,jdbcType=VARCHAR},#{subject,jdbcType=VARCHAR},#{text,jdbcType=VARCHAR},
+        #{from,jdbcType=VARCHAR},#{to,jdbcType=VARCHAR},#{companyId,jdbcType=BIGINT},
+        #{creatorId,jdbcType=BIGINT},#{createTime,jdbcType=TIMESTAMP})
+    </insert>
+
+    <resultMap id="BaseResultMap" type="com.usoftchina.saas.mail.po.MailLog">
+        <id column="id" jdbcType="BIGINT" property="id"/>
+        <result column="template_id" jdbcType="BIGINT" property="templateId"/>
+        <result column="subject" jdbcType="VARCHAR" property="subject"/>
+        <result column="text" jdbcType="VARCHAR" property="text"/>
+        <result column="from" jdbcType="VARCHAR" property="from"/>
+        <result column="to" jdbcType="VARCHAR" property="to"/>
+        <result column="company_id" jdbcType="INTEGER" property="companyId"/>
+        <result column="creator_id" jdbcType="BIGINT" property="creatorId"/>
+        <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
+    </resultMap>
+    <sql id="baseColumns">
+        id,template_id,subject,text,from,to,company_id,create_time
+    </sql>
+
+    <select id="selectAll" resultMap="BaseResultMap">
+        select <include refid="baseColumns"/> from m_log order by create_time desc
+    </select>
+</mapper>

+ 29 - 0
base-servers/mail/mail-server/src/main/resources/mapper/MailTemplateMapper.xml

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.usoftchina.saas.mail.mapper.MailTemplateMapper">
+
+    <insert id="insert" parameterType="com.usoftchina.saas.mail.po.MailTemplate">
+        insert into `m_template`(`id`,`subject`,`text`)
+        values (#{id,jdbcType=VARCHAR},#{subject,jdbcType=VARCHAR},#{text,jdbcType=VARCHAR})
+    </insert>
+    <update id="updateByPrimaryKey" parameterType="com.usoftchina.saas.mail.po.MailTemplate">
+        update `m_template` set `subject`=#{subject,jdbcType=VARCHAR},`text`=#{text,jdbcType=VARCHAR}
+        where `id`=#{id,jdbcType=VARCHAR}
+    </update>
+    <delete id="deleteByPrimaryKey" parameterType="java.lang.String">
+        delete from `m_template` where `id`=#{id}
+    </delete>
+
+    <resultMap id="BaseResultMap" type="com.usoftchina.saas.mail.po.MailTemplate">
+        <id column="id" jdbcType="VARCHAR" property="id"/>
+        <result column="subject" jdbcType="VARCHAR" property="subject"/>
+        <result column="text" jdbcType="VARCHAR" property="text"/>
+    </resultMap>
+    <sql id="baseColumns">
+        `id`,`subject`,`text`
+    </sql>
+
+    <select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap">
+        select <include refid="baseColumns"/> from `m_template` where `id`=#{id}
+    </select>
+</mapper>

+ 0 - 1
base-servers/mail/pom.xml

@@ -18,5 +18,4 @@
         <module>mail-dto</module>
     </modules>
 
-
 </project>

+ 1 - 1
frontend/saas-portal-web/Dockerfile

@@ -2,4 +2,4 @@ FROM hub.c.163.com/library/nginx
 MAINTAINER USOFTCHINA <yingp@usoftchina.com>
 RUN rm /etc/nginx/conf.d/default.conf
 ADD runtime/nginx/default.conf /etc/nginx/conf.d/
-COPY src/ /usr/share/nginx/html/
+COPY dist/ /usr/share/nginx/html/

+ 5 - 2
frontend/saas-portal-web/README.md

@@ -7,9 +7,12 @@ yarn
 # 或者
 npm install --registry=https://registry.npm.taobao.org
 
-# Serve at 127.0.0.1
+# Serve at http://127.0.0.1
 npm run dev
 
-# Build for production with minification
+# Build for production
 npm run build
+
+# Build for docker image
+docker build -t saas-portal-web:1.0.0 .
 ```

+ 0 - 5
frontend/saas-portal-web/config/dev.env.js

@@ -1,5 +0,0 @@
-'use strict'
-module.exports = {
-  NODE_ENV: '"development"',
-  BASE_API: '"http://192.168.0.181:8560"',
-}

+ 15 - 0
frontend/saas-portal-web/config/env.js

@@ -0,0 +1,15 @@
+if (process.env.NODE_ENV == 'production') {
+    window.env = {
+        profile: 'production',
+        server: {
+            baseUrl: 'http://192.168.0.181:8560'
+        }
+    }
+} else {
+    window.env = {
+        profile: 'development',
+        server: {
+            baseUrl: 'http://192.168.0.181:8560'
+        }
+    }
+}

+ 0 - 5
frontend/saas-portal-web/config/prod.env.js

@@ -1,5 +0,0 @@
-'use strict'
-module.exports = {
-  NODE_ENV: '"production"',
-  BASE_API: '"http://192.168.0.181:8560"',
-}

+ 4 - 1
frontend/saas-portal-web/package.json

@@ -4,7 +4,7 @@
   "description": "saas portal",
   "main": "index.js",
   "scripts": {
-    "dev": "webpack-dev-server --inline --progress --config ./webpack.conf.js",
+    "dev": "webpack-dev-server --mode development --inline --progress --config ./webpack.dev.conf.js",
     "start": "npm run dev",
     "build": "webpack --mode production --config ./webpack.conf.js"
   },
@@ -14,6 +14,9 @@
   "author": "yingp@usoftchina.com",
   "license": "ISC",
   "devDependencies": {
+    "clean-webpack-plugin": "^1.0.0",
+    "copy-webpack-plugin": "^4.6.0",
+    "html-webpack-plugin": "^3.2.0",
     "webpack": "^4.25.1",
     "webpack-cli": "^3.1.2",
     "webpack-dev-server": "^3.1.10"

+ 23 - 8
frontend/saas-portal-web/webpack.conf.js

@@ -1,12 +1,27 @@
 const path = require('path')
+const cleanWebpackPlugin = require('clean-webpack-plugin')
+const copyWebpackPlugin = require('copy-webpack-plugin')
+const htmlWebpackPlugin = require('html-webpack-plugin')
 
 module.exports = {
-    devServer: {
-        clientLogLevel: 'warning',
-        quiet: true,
-        open: true,
-        contentBase: path.join(__dirname, "src"),
-        port: 80,
-        host: '127.0.0.1'
-    }
+    entry: {
+        env: './config/env.js'
+    },
+    output: {
+		path: path.resolve(__dirname, 'dist'),
+		filename: 'js/[name].js'
+    },
+    plugins: [
+        new cleanWebpackPlugin(["dist"]),
+		new htmlWebpackPlugin({
+			filename: 'index.html',
+			template: './src/index.html',
+			inject: 'head'
+        }),
+        new copyWebpackPlugin([{
+            from: path.resolve(__dirname, 'src'),
+            to: path.resolve(__dirname, 'dist'),
+            ignore: ["index.html", "js/env.js"]
+        }])
+    ]
 }

+ 47 - 0
frontend/saas-portal-web/webpack.dev.conf.js

@@ -0,0 +1,47 @@
+const path = require('path')
+const webpack = require('webpack')
+const copyWebpackPlugin = require('copy-webpack-plugin')
+const htmlWebpackPlugin = require('html-webpack-plugin')
+
+module.exports = {
+    entry: {
+        env: './config/env.js'
+    },
+    output: {
+		path: path.resolve(__dirname, 'dist'),
+		filename: 'js/[name].js'
+    },
+    module: {
+        rules: [{
+            test: /\.css$/,
+            use: [
+                { loader: 'style-loader' },
+                {
+                    loader: 'css-loader',
+                    options: { modules: true}
+                }
+            ]
+        }]
+    },
+    plugins: [
+		new htmlWebpackPlugin({
+			filename: 'index.html',
+			template: './src/index.html',
+			inject: 'head'
+        }),
+        new copyWebpackPlugin([{
+            from: path.resolve(__dirname, 'src'),
+            to: path.resolve(__dirname, 'dist'),
+            ignore: ["index.html", "js/env.js"]
+        }]),
+        new webpack.HotModuleReplacementPlugin()
+    ],
+    devServer: {
+        clientLogLevel: 'warning',
+        quiet: true,
+        open: true,
+        contentBase: path.join(__dirname, "dist"),
+        port: 80,
+        host: '127.0.0.1'
+    }
+}

+ 337 - 3
frontend/saas-portal-web/yarn.lock

@@ -247,6 +247,10 @@ array-unique@^0.3.2:
   version "0.3.2"
   resolved "http://registry.npm.taobao.org/array-unique/download/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
 
+arrify@^1.0.1:
+  version "1.0.1"
+  resolved "http://registry.npm.taobao.org/arrify/download/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
+
 asn1.js@^4.0.0:
   version "4.10.1"
   resolved "http://registry.npm.taobao.org/asn1.js/download/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0"
@@ -343,6 +347,10 @@ bonjour@^3.5.0:
     multicast-dns "^6.0.1"
     multicast-dns-service-types "^1.1.0"
 
+boolbase@~1.0.0:
+  version "1.0.0"
+  resolved "http://registry.npm.taobao.org/boolbase/download/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
+
 brace-expansion@^1.1.7:
   version "1.1.11"
   resolved "http://registry.npm.taobao.org/brace-expansion/download/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@@ -482,6 +490,13 @@ cache-base@^1.0.1:
     union-value "^1.0.0"
     unset-value "^1.0.0"
 
+camel-case@3.0.x:
+  version "3.0.0"
+  resolved "http://registry.npm.taobao.org/camel-case/download/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73"
+  dependencies:
+    no-case "^2.2.0"
+    upper-case "^1.1.1"
+
 camelcase@^4.1.0:
   version "4.1.0"
   resolved "http://registry.npm.taobao.org/camelcase/download/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
@@ -539,6 +554,18 @@ class-utils@^0.3.5:
     isobject "^3.0.0"
     static-extend "^0.1.1"
 
+clean-css@4.2.x:
+  version "4.2.1"
+  resolved "http://registry.npm.taobao.org/clean-css/download/clean-css-4.2.1.tgz#2d411ef76b8569b6d0c84068dabe85b0aa5e5c17"
+  dependencies:
+    source-map "~0.6.0"
+
+clean-webpack-plugin@^1.0.0:
+  version "1.0.0"
+  resolved "http://registry.npm.taobao.org/clean-webpack-plugin/download/clean-webpack-plugin-1.0.0.tgz#f184b9c26d12983d639828e0548ae2080e84b6a7"
+  dependencies:
+    rimraf "^2.6.1"
+
 cliui@^4.0.0:
   version "4.1.0"
   resolved "http://registry.npm.taobao.org/cliui/download/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49"
@@ -568,6 +595,10 @@ color-name@1.1.3:
   version "1.1.3"
   resolved "http://registry.npm.taobao.org/color-name/download/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
 
+commander@2.17.x, commander@~2.17.1:
+  version "2.17.1"
+  resolved "http://registry.npm.taobao.org/commander/download/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
+
 commander@~2.13.0:
   version "2.13.0"
   resolved "http://registry.npm.taobao.org/commander/download/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c"
@@ -660,6 +691,19 @@ copy-descriptor@^0.1.0:
   version "0.1.1"
   resolved "http://registry.npm.taobao.org/copy-descriptor/download/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
 
+copy-webpack-plugin@^4.6.0:
+  version "4.6.0"
+  resolved "http://registry.npm.taobao.org/copy-webpack-plugin/download/copy-webpack-plugin-4.6.0.tgz#e7f40dd8a68477d405dd1b7a854aae324b158bae"
+  dependencies:
+    cacache "^10.0.4"
+    find-cache-dir "^1.0.0"
+    globby "^7.1.1"
+    is-glob "^4.0.0"
+    loader-utils "^1.1.0"
+    minimatch "^3.0.4"
+    p-limit "^1.0.0"
+    serialize-javascript "^1.4.0"
+
 core-util-is@~1.0.0:
   version "1.0.2"
   resolved "http://registry.npm.taobao.org/core-util-is/download/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
@@ -718,6 +762,19 @@ crypto-browserify@^3.11.0:
     randombytes "^2.0.0"
     randomfill "^1.0.3"
 
+css-select@^1.1.0:
+  version "1.2.0"
+  resolved "http://registry.npm.taobao.org/css-select/download/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858"
+  dependencies:
+    boolbase "~1.0.0"
+    css-what "2.1"
+    domutils "1.5.1"
+    nth-check "~1.0.1"
+
+css-what@2.1:
+  version "2.1.2"
+  resolved "http://registry.npm.taobao.org/css-what/download/css-what-2.1.2.tgz#c0876d9d0480927d7d4920dcd72af3595649554d"
+
 cyclist@~0.2.2:
   version "0.2.2"
   resolved "http://registry.npm.taobao.org/cyclist/download/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640"
@@ -769,6 +826,12 @@ default-gateway@^2.6.0:
     execa "^0.10.0"
     ip-regex "^2.1.0"
 
+define-properties@^1.1.2:
+  version "1.1.3"
+  resolved "http://registry.npm.taobao.org/define-properties/download/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
+  dependencies:
+    object-keys "^1.0.12"
+
 define-property@^0.2.5:
   version "0.2.5"
   resolved "http://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116"
@@ -834,6 +897,13 @@ diffie-hellman@^5.0.0:
     miller-rabin "^4.0.0"
     randombytes "^2.0.0"
 
+dir-glob@^2.0.0:
+  version "2.0.0"
+  resolved "http://registry.npm.taobao.org/dir-glob/download/dir-glob-2.0.0.tgz#0b205d2b6aef98238ca286598a8204d29d0a0034"
+  dependencies:
+    arrify "^1.0.1"
+    path-type "^3.0.0"
+
 dns-equal@^1.0.0:
   version "1.0.0"
   resolved "http://registry.npm.taobao.org/dns-equal/download/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d"
@@ -851,10 +921,50 @@ dns-txt@^2.0.2:
   dependencies:
     buffer-indexof "^1.0.0"
 
+dom-converter@~0.2:
+  version "0.2.0"
+  resolved "http://registry.npm.taobao.org/dom-converter/download/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768"
+  dependencies:
+    utila "~0.4"
+
+dom-serializer@0:
+  version "0.1.0"
+  resolved "http://registry.npm.taobao.org/dom-serializer/download/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82"
+  dependencies:
+    domelementtype "~1.1.1"
+    entities "~1.1.1"
+
 domain-browser@^1.1.1:
   version "1.2.0"
   resolved "http://registry.npm.taobao.org/domain-browser/download/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda"
 
+domelementtype@1:
+  version "1.2.1"
+  resolved "http://registry.npm.taobao.org/domelementtype/download/domelementtype-1.2.1.tgz#578558ef23befac043a1abb0db07635509393479"
+
+domelementtype@~1.1.1:
+  version "1.1.3"
+  resolved "http://registry.npm.taobao.org/domelementtype/download/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b"
+
+domhandler@2.1:
+  version "2.1.0"
+  resolved "http://registry.npm.taobao.org/domhandler/download/domhandler-2.1.0.tgz#d2646f5e57f6c3bab11cf6cb05d3c0acf7412594"
+  dependencies:
+    domelementtype "1"
+
+domutils@1.1:
+  version "1.1.6"
+  resolved "http://registry.npm.taobao.org/domutils/download/domutils-1.1.6.tgz#bddc3de099b9a2efacc51c623f28f416ecc57485"
+  dependencies:
+    domelementtype "1"
+
+domutils@1.5.1:
+  version "1.5.1"
+  resolved "http://registry.npm.taobao.org/domutils/download/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf"
+  dependencies:
+    dom-serializer "0"
+    domelementtype "1"
+
 duplexify@^3.4.2, duplexify@^3.6.0:
   version "3.6.1"
   resolved "http://registry.npm.taobao.org/duplexify/download/duplexify-3.6.1.tgz#b1a7a29c4abfd639585efaecce80d666b1e34125"
@@ -902,12 +1012,34 @@ enhanced-resolve@^4.1.0:
     memory-fs "^0.4.0"
     tapable "^1.0.0"
 
+entities@~1.1.1:
+  version "1.1.2"
+  resolved "http://registry.npm.taobao.org/entities/download/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
+
 errno@^0.1.3, errno@~0.1.7:
   version "0.1.7"
   resolved "http://registry.npm.taobao.org/errno/download/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618"
   dependencies:
     prr "~1.0.1"
 
+es-abstract@^1.5.1:
+  version "1.12.0"
+  resolved "http://registry.npm.taobao.org/es-abstract/download/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165"
+  dependencies:
+    es-to-primitive "^1.1.1"
+    function-bind "^1.1.1"
+    has "^1.0.1"
+    is-callable "^1.1.3"
+    is-regex "^1.0.4"
+
+es-to-primitive@^1.1.1:
+  version "1.2.0"
+  resolved "http://registry.npm.taobao.org/es-to-primitive/download/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377"
+  dependencies:
+    is-callable "^1.1.4"
+    is-date-object "^1.0.1"
+    is-symbol "^1.0.2"
+
 escape-html@~1.0.3:
   version "1.0.3"
   resolved "http://registry.npm.taobao.org/escape-html/download/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
@@ -1168,6 +1300,10 @@ fsevents@^1.2.2:
     nan "^2.9.2"
     node-pre-gyp "^0.10.0"
 
+function-bind@^1.1.1:
+  version "1.1.1"
+  resolved "http://registry.npm.taobao.org/function-bind/download/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
+
 gauge@~2.7.3:
   version "2.7.4"
   resolved "http://registry.npm.taobao.org/gauge/download/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
@@ -1225,6 +1361,17 @@ globby@^6.1.0:
     pify "^2.0.0"
     pinkie-promise "^2.0.0"
 
+globby@^7.1.1:
+  version "7.1.1"
+  resolved "http://registry.npm.taobao.org/globby/download/globby-7.1.1.tgz#fb2ccff9401f8600945dfada97440cca972b8680"
+  dependencies:
+    array-union "^1.0.1"
+    dir-glob "^2.0.0"
+    glob "^7.1.2"
+    ignore "^3.3.5"
+    pify "^3.0.0"
+    slash "^1.0.0"
+
 graceful-fs@^4.1.11, graceful-fs@^4.1.2:
   version "4.1.15"
   resolved "http://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
@@ -1237,6 +1384,10 @@ has-flag@^3.0.0:
   version "3.0.0"
   resolved "http://registry.npm.taobao.org/has-flag/download/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
 
+has-symbols@^1.0.0:
+  version "1.0.0"
+  resolved "http://registry.npm.taobao.org/has-symbols/download/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44"
+
 has-unicode@^2.0.0:
   version "2.0.1"
   resolved "http://registry.npm.taobao.org/has-unicode/download/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
@@ -1268,6 +1419,12 @@ has-values@^1.0.0:
     is-number "^3.0.0"
     kind-of "^4.0.0"
 
+has@^1.0.1:
+  version "1.0.3"
+  resolved "http://registry.npm.taobao.org/has/download/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
+  dependencies:
+    function-bind "^1.1.1"
+
 hash-base@^3.0.0:
   version "3.0.4"
   resolved "http://registry.npm.taobao.org/hash-base/download/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918"
@@ -1282,6 +1439,10 @@ hash.js@^1.0.0, hash.js@^1.0.3:
     inherits "^2.0.3"
     minimalistic-assert "^1.0.1"
 
+he@1.2.x:
+  version "1.2.0"
+  resolved "http://registry.npm.taobao.org/he/download/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
+
 hmac-drbg@^1.0.0:
   version "1.0.1"
   resolved "http://registry.npm.taobao.org/hmac-drbg/download/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
@@ -1303,6 +1464,39 @@ html-entities@^1.2.0:
   version "1.2.1"
   resolved "http://registry.npm.taobao.org/html-entities/download/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f"
 
+html-minifier@^3.2.3:
+  version "3.5.21"
+  resolved "http://registry.npm.taobao.org/html-minifier/download/html-minifier-3.5.21.tgz#d0040e054730e354db008463593194015212d20c"
+  dependencies:
+    camel-case "3.0.x"
+    clean-css "4.2.x"
+    commander "2.17.x"
+    he "1.2.x"
+    param-case "2.1.x"
+    relateurl "0.2.x"
+    uglify-js "3.4.x"
+
+html-webpack-plugin@^3.2.0:
+  version "3.2.0"
+  resolved "http://registry.npm.taobao.org/html-webpack-plugin/download/html-webpack-plugin-3.2.0.tgz#b01abbd723acaaa7b37b6af4492ebda03d9dd37b"
+  dependencies:
+    html-minifier "^3.2.3"
+    loader-utils "^0.2.16"
+    lodash "^4.17.3"
+    pretty-error "^2.0.2"
+    tapable "^1.0.0"
+    toposort "^1.0.0"
+    util.promisify "1.0.0"
+
+htmlparser2@~3.3.0:
+  version "3.3.0"
+  resolved "http://registry.npm.taobao.org/htmlparser2/download/htmlparser2-3.3.0.tgz#cc70d05a59f6542e43f0e685c982e14c924a9efe"
+  dependencies:
+    domelementtype "1"
+    domhandler "2.1"
+    domutils "1.1"
+    readable-stream "1.0"
+
 http-deceiver@^1.2.7:
   version "1.2.7"
   resolved "http://registry.npm.taobao.org/http-deceiver/download/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
@@ -1367,6 +1561,10 @@ ignore-walk@^3.0.1:
   dependencies:
     minimatch "^3.0.4"
 
+ignore@^3.3.5:
+  version "3.3.10"
+  resolved "http://registry.npm.taobao.org/ignore/download/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043"
+
 import-local@^2.0.0:
   version "2.0.0"
   resolved "http://registry.npm.taobao.org/import-local/download/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d"
@@ -1454,6 +1652,10 @@ is-buffer@^1.1.5:
   version "1.1.6"
   resolved "http://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
 
+is-callable@^1.1.3, is-callable@^1.1.4:
+  version "1.1.4"
+  resolved "http://registry.npm.taobao.org/is-callable/download/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75"
+
 is-data-descriptor@^0.1.4:
   version "0.1.4"
   resolved "http://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
@@ -1466,6 +1668,10 @@ is-data-descriptor@^1.0.0:
   dependencies:
     kind-of "^6.0.0"
 
+is-date-object@^1.0.1:
+  version "1.0.1"
+  resolved "http://registry.npm.taobao.org/is-date-object/download/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16"
+
 is-descriptor@^0.1.0:
   version "0.1.6"
   resolved "http://registry.npm.taobao.org/is-descriptor/download/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca"
@@ -1546,10 +1752,22 @@ is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4:
   dependencies:
     isobject "^3.0.1"
 
+is-regex@^1.0.4:
+  version "1.0.4"
+  resolved "http://registry.npm.taobao.org/is-regex/download/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491"
+  dependencies:
+    has "^1.0.1"
+
 is-stream@^1.1.0:
   version "1.1.0"
   resolved "http://registry.npm.taobao.org/is-stream/download/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
 
+is-symbol@^1.0.2:
+  version "1.0.2"
+  resolved "http://registry.npm.taobao.org/is-symbol/download/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38"
+  dependencies:
+    has-symbols "^1.0.0"
+
 is-windows@^1.0.2:
   version "1.0.2"
   resolved "http://registry.npm.taobao.org/is-windows/download/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
@@ -1558,6 +1776,10 @@ is-wsl@^1.1.0:
   version "1.1.0"
   resolved "http://registry.npm.taobao.org/is-wsl/download/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
 
+isarray@0.0.1:
+  version "0.0.1"
+  resolved "http://registry.npm.taobao.org/isarray/download/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
+
 isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
   version "1.0.0"
   resolved "http://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
@@ -1626,6 +1848,15 @@ loader-runner@^2.3.0:
   version "2.3.1"
   resolved "http://registry.npm.taobao.org/loader-runner/download/loader-runner-2.3.1.tgz#026f12fe7c3115992896ac02ba022ba92971b979"
 
+loader-utils@^0.2.16:
+  version "0.2.17"
+  resolved "http://registry.npm.taobao.org/loader-utils/download/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348"
+  dependencies:
+    big.js "^3.1.3"
+    emojis-list "^2.0.0"
+    json5 "^0.5.0"
+    object-assign "^4.0.1"
+
 loader-utils@^1.1.0:
   version "1.1.0"
   resolved "http://registry.npm.taobao.org/loader-utils/download/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd"
@@ -1652,7 +1883,7 @@ lodash.debounce@^4.0.8:
   version "4.0.8"
   resolved "http://registry.npm.taobao.org/lodash.debounce/download/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
 
-lodash@^4.17.5:
+lodash@^4.17.3, lodash@^4.17.5:
   version "4.17.11"
   resolved "http://registry.npm.taobao.org/lodash/download/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
 
@@ -1660,6 +1891,10 @@ loglevel@^1.4.1:
   version "1.6.1"
   resolved "http://registry.npm.taobao.org/loglevel/download/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa"
 
+lower-case@^1.1.1:
+  version "1.1.4"
+  resolved "http://registry.npm.taobao.org/lower-case/download/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
+
 lru-cache@^4.1.1:
   version "4.1.3"
   resolved "http://registry.npm.taobao.org/lru-cache/download/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c"
@@ -1904,6 +2139,12 @@ nice-try@^1.0.4:
   version "1.0.5"
   resolved "http://registry.npm.taobao.org/nice-try/download/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
 
+no-case@^2.2.0:
+  version "2.3.2"
+  resolved "http://registry.npm.taobao.org/no-case/download/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac"
+  dependencies:
+    lower-case "^1.1.1"
+
 node-forge@0.7.5:
   version "0.7.5"
   resolved "http://registry.npm.taobao.org/node-forge/download/node-forge-0.7.5.tgz#6c152c345ce11c52f465c2abd957e8639cd674df"
@@ -1990,6 +2231,12 @@ npmlog@^4.0.2:
     gauge "~2.7.3"
     set-blocking "~2.0.0"
 
+nth-check@~1.0.1:
+  version "1.0.2"
+  resolved "http://registry.npm.taobao.org/nth-check/download/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c"
+  dependencies:
+    boolbase "~1.0.0"
+
 number-is-nan@^1.0.0:
   version "1.0.1"
   resolved "http://registry.npm.taobao.org/number-is-nan/download/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
@@ -2006,12 +2253,23 @@ object-copy@^0.1.0:
     define-property "^0.2.5"
     kind-of "^3.0.3"
 
+object-keys@^1.0.12:
+  version "1.0.12"
+  resolved "http://registry.npm.taobao.org/object-keys/download/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2"
+
 object-visit@^1.0.0:
   version "1.0.1"
   resolved "http://registry.npm.taobao.org/object-visit/download/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb"
   dependencies:
     isobject "^3.0.0"
 
+object.getownpropertydescriptors@^2.0.3:
+  version "2.0.3"
+  resolved "http://registry.npm.taobao.org/object.getownpropertydescriptors/download/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16"
+  dependencies:
+    define-properties "^1.1.2"
+    es-abstract "^1.5.1"
+
 object.pick@^1.3.0:
   version "1.3.0"
   resolved "http://registry.npm.taobao.org/object.pick/download/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747"
@@ -2089,7 +2347,7 @@ p-is-promise@^1.1.0:
   version "1.1.0"
   resolved "http://registry.npm.taobao.org/p-is-promise/download/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e"
 
-p-limit@^1.1.0:
+p-limit@^1.0.0, p-limit@^1.1.0:
   version "1.3.0"
   resolved "http://registry.npm.taobao.org/p-limit/download/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8"
   dependencies:
@@ -2137,6 +2395,12 @@ parallel-transform@^1.1.0:
     inherits "^2.0.3"
     readable-stream "^2.1.5"
 
+param-case@2.1.x:
+  version "2.1.1"
+  resolved "http://registry.npm.taobao.org/param-case/download/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247"
+  dependencies:
+    no-case "^2.2.0"
+
 parse-asn1@^5.0.0:
   version "5.1.1"
   resolved "http://registry.npm.taobao.org/parse-asn1/download/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8"
@@ -2183,6 +2447,12 @@ path-to-regexp@0.1.7:
   version "0.1.7"
   resolved "http://registry.npm.taobao.org/path-to-regexp/download/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
 
+path-type@^3.0.0:
+  version "3.0.0"
+  resolved "http://registry.npm.taobao.org/path-type/download/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
+  dependencies:
+    pify "^3.0.0"
+
 pbkdf2@^3.0.3:
   version "3.0.17"
   resolved "http://registry.npm.taobao.org/pbkdf2/download/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6"
@@ -2235,6 +2505,13 @@ posix-character-classes@^0.1.0:
   version "0.1.1"
   resolved "http://registry.npm.taobao.org/posix-character-classes/download/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
 
+pretty-error@^2.0.2:
+  version "2.1.1"
+  resolved "http://registry.npm.taobao.org/pretty-error/download/pretty-error-2.1.1.tgz#5f4f87c8f91e5ae3f3ba87ab4cf5e03b1a17f1a3"
+  dependencies:
+    renderkid "^2.0.1"
+    utila "~0.4"
+
 process-nextick-args@~2.0.0:
   version "2.0.0"
   resolved "http://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"
@@ -2363,6 +2640,15 @@ rc@^1.2.7:
     string_decoder "~1.1.1"
     util-deprecate "~1.0.1"
 
+readable-stream@1.0:
+  version "1.0.34"
+  resolved "http://registry.npm.taobao.org/readable-stream/download/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
+  dependencies:
+    core-util-is "~1.0.0"
+    inherits "~2.0.1"
+    isarray "0.0.1"
+    string_decoder "~0.10.x"
+
 readdirp@^2.0.0:
   version "2.2.1"
   resolved "http://registry.npm.taobao.org/readdirp/download/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525"
@@ -2378,10 +2664,24 @@ regex-not@^1.0.0, regex-not@^1.0.2:
     extend-shallow "^3.0.2"
     safe-regex "^1.1.0"
 
+relateurl@0.2.x:
+  version "0.2.7"
+  resolved "http://registry.npm.taobao.org/relateurl/download/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9"
+
 remove-trailing-separator@^1.0.1:
   version "1.1.0"
   resolved "http://registry.npm.taobao.org/remove-trailing-separator/download/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
 
+renderkid@^2.0.1:
+  version "2.0.2"
+  resolved "http://registry.npm.taobao.org/renderkid/download/renderkid-2.0.2.tgz#12d310f255360c07ad8fde253f6c9e9de372d2aa"
+  dependencies:
+    css-select "^1.1.0"
+    dom-converter "~0.2"
+    htmlparser2 "~3.3.0"
+    strip-ansi "^3.0.0"
+    utila "^0.4.0"
+
 repeat-element@^1.1.2:
   version "1.1.3"
   resolved "http://registry.npm.taobao.org/repeat-element/download/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce"
@@ -2580,6 +2880,10 @@ signal-exit@^3.0.0:
   version "3.0.2"
   resolved "http://registry.npm.taobao.org/signal-exit/download/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
 
+slash@^1.0.0:
+  version "1.0.0"
+  resolved "http://registry.npm.taobao.org/slash/download/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
+
 snapdragon-node@^2.0.1:
   version "2.1.1"
   resolved "http://registry.npm.taobao.org/snapdragon-node/download/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"
@@ -2647,7 +2951,7 @@ source-map@^0.5.6:
   version "0.5.7"
   resolved "http://registry.npm.taobao.org/source-map/download/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
 
-source-map@^0.6.1, source-map@~0.6.1:
+source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
   version "0.6.1"
   resolved "http://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
 
@@ -2750,6 +3054,10 @@ string_decoder@^1.0.0, string_decoder@~1.1.1:
   dependencies:
     safe-buffer "~5.1.0"
 
+string_decoder@~0.10.x:
+  version "0.10.31"
+  resolved "http://registry.npm.taobao.org/string_decoder/download/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
+
 strip-ansi@^3.0.0, strip-ansi@^3.0.1:
   version "3.0.1"
   resolved "http://registry.npm.taobao.org/strip-ansi/download/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
@@ -2835,6 +3143,10 @@ to-regex@^3.0.1, to-regex@^3.0.2:
     regex-not "^1.0.2"
     safe-regex "^1.1.0"
 
+toposort@^1.0.0:
+  version "1.0.7"
+  resolved "http://registry.npm.taobao.org/toposort/download/toposort-1.0.7.tgz#2e68442d9f64ec720b8cc89e6443ac6caa950029"
+
 tslib@^1.9.0:
   version "1.9.3"
   resolved "http://registry.npm.taobao.org/tslib/download/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
@@ -2861,6 +3173,13 @@ uglify-es@^3.3.4:
     commander "~2.13.0"
     source-map "~0.6.1"
 
+uglify-js@3.4.x:
+  version "3.4.9"
+  resolved "http://registry.npm.taobao.org/uglify-js/download/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3"
+  dependencies:
+    commander "~2.17.1"
+    source-map "~0.6.1"
+
 uglifyjs-webpack-plugin@^1.2.4:
   version "1.3.0"
   resolved "http://registry.npm.taobao.org/uglifyjs-webpack-plugin/download/uglifyjs-webpack-plugin-1.3.0.tgz#75f548160858163a08643e086d5fefe18a5d67de"
@@ -2910,6 +3229,10 @@ upath@^1.0.5:
   version "1.1.0"
   resolved "http://registry.npm.taobao.org/upath/download/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd"
 
+upper-case@^1.1.1:
+  version "1.1.3"
+  resolved "http://registry.npm.taobao.org/upper-case/download/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598"
+
 uri-js@^4.2.2:
   version "4.2.2"
   resolved "http://registry.npm.taobao.org/uri-js/download/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
@@ -2942,6 +3265,13 @@ util-deprecate@~1.0.1:
   version "1.0.2"
   resolved "http://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
 
+util.promisify@1.0.0:
+  version "1.0.0"
+  resolved "http://registry.npm.taobao.org/util.promisify/download/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030"
+  dependencies:
+    define-properties "^1.1.2"
+    object.getownpropertydescriptors "^2.0.3"
+
 util@0.10.3:
   version "0.10.3"
   resolved "http://registry.npm.taobao.org/util/download/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
@@ -2954,6 +3284,10 @@ util@^0.10.3:
   dependencies:
     inherits "2.0.3"
 
+utila@^0.4.0, utila@~0.4:
+  version "0.4.0"
+  resolved "http://registry.npm.taobao.org/utila/download/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c"
+
 utils-merge@1.0.1:
   version "1.0.1"
   resolved "http://registry.npm.taobao.org/utils-merge/download/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"

+ 4 - 0
frontend/saas-web/app/Application.scss

@@ -268,6 +268,10 @@ body.launching {
   border-color: #ABDAFF;
 }
 
+.x-grid-item-selected {
+  background-color: #ffefbb;
+}
+
 
 
 /*滚动条样式*/

+ 0 - 89
frontend/saas-web/app/view/core/chart/Area.js

@@ -1,89 +0,0 @@
-Ext.define('saas.view.core.chart.Area', {
-    extend: 'saas.view.core.chart.ChartBase',
-    xtype: 'core-chart-area',
-
-    requires: [
-        'Ext.chart.CartesianChart',
-        'Ext.chart.axis.Category',
-        'Ext.chart.axis.Numeric',
-        'Ext.chart.series.Line',
-        'Ext.chart.interactions.PanZoom'
-    ],
-
-    title: 'Area Chart',
-    iconCls: 'x-fa fa-area-chart',
-
-    items: [{
-        xtype: 'cartesian',
-        colors: [
-            '#115fa6',
-            '#94ae0a'
-        ],
-        bind: '{areaData}',
-        series: [
-            {
-                type: 'line',
-                colors: [
-                    'rgba(103, 144, 199, 0.6)'
-                ],
-                xField: 'xvalue',
-                yField: [
-                    'y1value'
-                ],
-                fill: true,
-                smooth: true
-            },
-            {
-                type: 'line',
-                colors: [
-                    'rgba(238, 146, 156, 0.6)'
-                ],
-                xField: 'xvalue',
-                yField: [
-                    'y2value'
-                ],
-                fill: true,
-                smooth: true
-            }
-        ],
-        platformConfig: {
-            phone: {
-                // On a phone the whole view becomes a vertical strip of charts,
-                // which makes it impossible to scroll the view if touch action
-                // started on a chart. So we use a custom touchAction config.
-                touchAction: {
-                    panX: true,
-                    panY: true
-                }
-            },
-            '!phone': {
-                interactions: {
-                    type: 'panzoom',
-                    zoomOnPanGesture: true
-                }
-            }
-        },
-        axes: [{
-            type: 'category',
-            fields: [
-                'xvalue'
-            ],
-            hidden: true,
-            position: 'bottom'
-        },{
-            type: 'numeric',
-            fields: [
-                'y1value',
-                'y2value',
-                'y3value'
-            ],
-            grid: {
-                odd: {
-                    fill: '#e8e8e8'
-                }
-            },
-            hidden: true,
-            position: 'left'
-        }]
-    }]
-});

+ 0 - 67
frontend/saas-web/app/view/core/chart/Bar.js

@@ -1,67 +0,0 @@
-Ext.define('saas.view.core.chart.Bar', {
-    extend: 'saas.view.core.chart.ChartBase',
-    xtype: 'core-chart-bar',
-
-    requires: [
-        'Ext.chart.CartesianChart',
-        'Ext.chart.axis.Category',
-        'Ext.chart.axis.Numeric',
-        'Ext.chart.interactions.PanZoom',
-        'Ext.chart.series.Bar'
-    ],
-
-    title: 'Bar Chart',
-    iconCls: 'x-fa fa-bar-chart',
-
-    items: [{
-        xtype: 'cartesian',
-        colors: [
-            '#6aa5db'
-        ],
-        bind: '{barData}',
-        axes: [{
-            type: 'category',
-            fields: [
-                'xvalue'
-            ],
-            hidden: true,
-            position: 'bottom'
-        },{
-            type: 'numeric',
-            fields: [
-                'yvalue'
-            ],
-            grid: {
-                odd: {
-                    fill: '#e8e8e8'
-                }
-            },
-            hidden: true,
-            position: 'left'
-        }],
-        series: [{
-            type: 'bar',
-            xField: 'xvalue',
-            yField: [
-                'yvalue'
-            ]
-        }],
-        platformConfig: {
-            phone: {
-                // On a phone the whole view becomes a vertical strip of charts,
-                // which makes it impossible to scroll the view if touch action
-                // started on a chart. So we use a custom touchAction config.
-                touchAction: {
-                    panX: true,
-                    panY: true
-                }
-            },
-            '!phone': {
-                interactions: {
-                    type: 'panzoom',
-                    zoomOnPanGesture: true
-                }
-            }
-        }
-    }]
-});

+ 0 - 2
frontend/saas-web/app/view/core/chart/ChartBase.js

@@ -18,8 +18,6 @@ Ext.define('saas.view.core.chart.ChartBase', {
 
     initComponent: function() {
         var me = this;
-        
-
 
         me.callParent(arguments);
     }

+ 0 - 38
frontend/saas-web/app/view/core/chart/Gauge.js

@@ -1,38 +0,0 @@
-Ext.define('saas.view.core.chart.Gauge', {
-    extend: 'saas.view.core.chart.ChartBase',
-    xtype: 'core-chart-gauge',
-
-    requires: [
-        'Ext.chart.PolarChart',
-        'Ext.chart.series.Gauge'
-    ],
-
-    title: 'Gauge Chart',
-    iconCls: 'x-fa fa-wifi',
-
-    items: [{
-        xtype: 'polar',
-        colors: [
-            '#6aa5db',
-            '#aed581'
-        ],
-        bind: '{gaugeData}',
-        series: [{
-            type: 'gauge',
-            angleField: 'position',
-            needleLength: 100
-        }],
-        platformConfig: {
-            phone: {
-                // On a phone the whole view becomes a vertical strip of charts,
-                // which makes it impossible to scroll the view if touch action
-                // started on a chart. So we use a custom touchAction config.
-                touchAction: {
-                    panX: true,
-                    panY: true
-                }
-            }
-        }
-    }]
-
-});

+ 0 - 75
frontend/saas-web/app/view/core/chart/Line.js

@@ -1,75 +0,0 @@
-Ext.define('saas.view.core.chart.Line', {
-    extend: 'saas.view.core.chart.ChartBase',
-    xtype: 'core-chart-line',
-
-    requires: [
-        'Ext.chart.CartesianChart',
-        'Ext.chart.axis.Category',
-        'Ext.chart.axis.Numeric',
-        'Ext.chart.interactions.PanZoom',
-        'Ext.chart.series.Line'
-
-    ],
-
-    title: 'Line Chart',
-    iconCls: 'x-fa fa-line-chart',
-
-    items: [{
-        xtype: 'cartesian',
-        colors: [
-            '#6aa5db',
-            '#94ae0a'
-        ],
-        bind: '{lineData}',
-        axes: [{
-            type: 'category',
-            fields: [
-                'xvalue'
-            ],
-            hidden: true,
-            position: 'bottom'
-        },{
-            type: 'numeric',
-            fields: [
-                'yvalue',
-                'y1value',
-                'y2value',
-                'y3value',
-                'y4value',
-                'y5value'
-            ],
-            hidden: true,
-            position: 'left'
-        }],
-        series: [{
-            type: 'line',
-            xField: 'xvalue',
-            yField: [
-                'yvalue'
-            ]
-        },{
-            type: 'line',
-            xField: 'xvalue',
-            yField: [
-                'y1value'
-            ]
-        }],
-        platformConfig: {
-            phone: {
-                // On a phone the whole view becomes a vertical strip of charts,
-                // which makes it impossible to scroll the view if touch action
-                // started on a chart. So we use a custom touchAction config.
-                touchAction: {
-                    panX: true,
-                    panY: true
-                }
-            },
-            '!phone': {
-                interactions: {
-                    type: 'panzoom',
-                    zoomOnPanGesture: true
-                }
-            }
-        }
-    }]
-});

+ 0 - 65
frontend/saas-web/app/view/core/chart/Pie.js

@@ -1,65 +0,0 @@
-Ext.define('saas.view.core.chart.Pie', {
-    extend: 'saas.view.core.chart.ChartBase',
-    xtype: 'month_sale',
-
-    requires: [
-        'Ext.chart.PolarChart',
-        'Ext.chart.interactions.Rotate',
-        'Ext.chart.series.Pie',
-        'Ext.chart.series.sprite.PieSlice'
-    ],
-
-    iconCls: 'x-fa fa-pie-chart',
-
-    initComponent: function() {
-        var me = this;
-
-        Ext.apply(me, {
-            items: [{
-                xtype: 'polar',
-                width: '100%',
-                height: 500,
-                innerPadding: me.innerPadding || 20,
-                interactions: ['rotate', 'itemhighlight'],
-                donut: 30,
-                colors: [
-                    '#2C82BE',
-                    '#27A7FF',
-                    '#82CCFF',
-                    '#53A8E2',
-                    '#76DDFB',
-                    '#DBECF8',
-                ],
-                bind: {
-                    store: '{month_sale}',
-                },
-                style: {
-                    border: 'none'
-                },
-                series: [{
-                    type: 'pie',
-                    angleField: me.yfield || 'yvalue',
-                    label: {
-                        field: me.xfield || 'xvalue',
-                        display: 'rotate'
-                    },
-                    donut: 55,
-                    highlight: true,
-                    tooltip: {
-                        trackMouse: true,
-                        renderer: me.onSeriesTooltipRender
-                    }
-                }],
-                // legend: {
-                //     docked: 'bottom'
-                // },
-            }]
-        });
-
-        me.callParent(arguments);
-    },
-
-    onSeriesTooltipRender: function (tooltip, record, item) {
-        tooltip.setHtml(record.get('xvalue') + ': ' + record.get('data1') + '%');
-    }
-});

+ 0 - 42
frontend/saas-web/app/view/core/chart/Pie3D.js

@@ -1,42 +0,0 @@
-Ext.define('saas.view.core.chart.Pie3D', {
-    extend: 'saas.view.core.chart.ChartBase',
-    xtype: 'core-chart-pie3d',
-
-    requires: [
-        'Ext.chart.PolarChart',
-        'Ext.chart.interactions.Rotate',
-        'Ext.chart.series.Pie3D'
-    ],
-
-    title: '3D Pie Chart',
-    iconCls: 'x-fa fa-pie-chart',
-
-    items: [{
-        xtype: 'polar',
-        colors: [
-            '#aed581',
-            '#6aa5db',
-            '#ee929c'
-        ],
-        platformConfig: {
-            phone: {
-                // On a phone the whole view becomes a vertical strip of charts,
-                // which makes it impossible to scroll the view if touch action
-                // started on a chart. So we use a custom touchAction config.
-                touchAction: {
-                    panX: true,
-                    panY: true
-                }
-            },
-            '!phone': {
-                interactions: 'rotate'
-            }
-        },
-        bind: '{pieData}',
-        series: [{
-            type: 'pie3d',
-            angleField: 'yvalue',
-            donut: 30
-        }]
-    }]
-});

+ 0 - 55
frontend/saas-web/app/view/core/chart/Polar.js

@@ -1,55 +0,0 @@
-Ext.define('saas.view.core.chart.Polar', {
-    extend: 'saas.view.core.chart.ChartBase',
-    xtype: 'core-chart-polar',
-
-    requires: [
-        'Ext.chart.PolarChart',
-        'Ext.chart.axis.Category',
-        'Ext.chart.axis.Numeric',
-        'Ext.chart.interactions.Rotate',
-        'Ext.chart.series.Radar'
-    ],
-
-    title: 'Radial Chart',
-    iconCls: 'x-fa fa-dot-circle-o',
-
-    items: [{
-        xtype: 'polar',
-        colors: ['#6aa5db'],
-        bind: '{radialData}',
-        axes: [{
-            type: 'numeric',
-            fields: [
-                'yvalue'
-            ],
-            grid: true,
-            position: 'radial'
-        },{
-            type: 'category',
-            fields: [
-                'xvalue'
-            ],
-            grid: true,
-            position: 'angular'
-        }],
-        series: [{
-            type: 'radar',
-            xField: 'xvalue',
-            yField: 'yvalue'
-        }],
-        platformConfig: {
-            phone: {
-                // On a phone the whole view becomes a vertical strip of charts,
-                // which makes it impossible to scroll the view if touch action
-                // started on a chart. So we use a custom touchAction config.
-                touchAction: {
-                    panX: true,
-                    panY: true
-                }
-            },
-            '!phone': {
-                interactions: 'rotate'
-            }
-        }
-    }]
-});

+ 0 - 71
frontend/saas-web/app/view/core/chart/Stacked.js

@@ -1,71 +0,0 @@
-Ext.define('saas.view.core.chart.Stacked', {
-    extend: 'saas.view.core.chart.ChartBase',
-    xtype: 'core-chart-stacked',
-
-    requires: [
-        'Ext.chart.CartesianChart',
-        'Ext.chart.axis.Category',
-        'Ext.chart.axis.Numeric',
-        'Ext.chart.series.Bar',
-        'Ext.chart.interactions.PanZoom'
-    ],
-
-    title: 'Stacked Bar Chart',
-    iconCls: 'x-fa fa-bar-chart',
-
-    items: [{
-        xtype: 'cartesian',
-        colors: [
-            '#6aa5db',
-            '#ee929c'
-        ],
-        bind: '{stackedData}',
-        axes: [{
-            type: 'category',
-            fields: [
-                'xvalue'
-            ],
-            hidden: true,
-            position: 'bottom'
-        },{
-            type: 'numeric',
-            fields: [
-                'y1value',
-                'y2value',
-                'y3value'
-            ],
-            grid: {
-                odd: {
-                    fill: '#e8e8e8'
-                }
-            },
-            hidden: true,
-            position: 'left'
-        }],
-        series: [{
-            type: 'bar',
-            xField: 'xvalue',
-            yField: [
-                'y2value',
-                'y3value'
-            ]
-        }],
-        platformConfig: {
-            phone: {
-                // On a phone the whole view becomes a vertical strip of charts,
-                // which makes it impossible to scroll the view if touch action
-                // started on a chart. So we use a custom touchAction config.
-                touchAction: {
-                    panX: true,
-                    panY: true
-                }
-            },
-            '!phone': {
-                interactions: {
-                    type: 'panzoom',
-                    zoomOnPanGesture: true
-                }
-            }
-        }
-    }]
-});

+ 1 - 1
frontend/saas-web/app/view/core/dbfind/MultiDbfindGridPanel.js

@@ -144,7 +144,7 @@ Ext.define('saas.view.core.dbfind.MultiDbfindGridPanel', {
                     items:[{
                         xtype:'checkbox',
                         id:'showSelectRecord',
-                        boxLabel:'显示选中数据',
+                        boxLabel:'选中数据',
                         handler:function(b){
                             var grid = me;
                             if(b.checked){

+ 18 - 2
frontend/saas-web/app/view/core/report/ReportPanel.js

@@ -44,7 +44,20 @@ Ext.define('saas.view.core.report.ReportPanel', {
                         xtype: 'button',
                         text: '查询',
                         handler: 'onQuery'
-                    }, {
+                    },{
+                        xtype:'button',
+                        text:'打印',
+                        style: {
+                            float: 'right'
+                        },
+                        handler: 'exportTo',
+                        cfg: {
+                            type: 'html',
+                            includeGroups: true,
+                            includeSummary: true,
+                            isPrint:true
+                        }
+                    },{
                         xtype: 'button',
                         style: {
                             float: 'right'
@@ -245,7 +258,10 @@ Ext.define('saas.view.core.report.ReportPanel', {
 
             if(c.xtype == 'datecolumn') {
                 Ext.applyIf(c, {
-                    format: 'Y-m-d'
+                    format: 'Y-m-d',
+                    exportStyle: {
+                        format: 'Short Date'
+                    }
                 })
             }else if(c.xtype == 'numbercolumn') {
                 Ext.applyIf(c, {

+ 20 - 10
frontend/saas-web/app/view/core/report/ReportPanelController.js

@@ -14,30 +14,40 @@ Ext.define('saas.view.core.report.ReportPanelController', {
         var me = this,
         reportPanel = me.getView(),
         grid = reportPanel.getListGrid();
-
         grid.store.loadPage(1);
     },
-
-    exportTo: function(btn){
+    exportTo:function(btn){
         var me = this,
-        reportPanel = me.getView(),
-        grid = reportPanel.getListGrid(),
-        title = reportPanel.reportTitle;
+            reportPanel = me.getView(),
+            grid = reportPanel.getListGrid(),
+            title = reportPanel.reportTitle;
 
         var cfg = Ext.merge({
             title: title,
+            titleStyle:{
+                alignment:{
+                    horizontal:'Center', vertical:'Center'
+                }
+                //font:
+            },
             fileName: title + '.' + (btn.cfg.ext || btn.cfg.type)
         }, btn.cfg);
-
-
         grid.store.exportPageSize = 5000;
         grid.store.exportNumber = 1;
         grid.store.load(function(records, operation, success) {
-            grid.saveDocumentAs(cfg);
+            if(btn.cfg.isPrint){
+                me.printHtml(grid.getDocumentData(cfg));
+            }else  grid.saveDocumentAs(cfg);
             grid.store.exportPageSize = null;
             grid.store.exportNumber = null;
             grid.store.load(function(records, operation, success) {
             });
         });
-    }
+    },
+    printHtml: function(html){
+        var d = window.open("", "print");
+        d.document.write(html);
+        d.document.close();
+        d.print();
+    },
 });

+ 25 - 60
frontend/saas-web/app/view/home/Home.js

@@ -1,6 +1,7 @@
 Ext.define('saas.view.home.Home', {
     extend: 'Ext.container.Container',
     xtype: 'home',
+    id: 'home',
 
     requires: [
         'Ext.slider.Single',
@@ -27,84 +28,48 @@ Ext.define('saas.view.home.Home', {
     },
 
     items: [{
+        style: {
+            marginRight: '0',
+        },
         xtype: 'infocard'
     }, {
         xtype: 'panel',
+        style: {
+            marginRight: '0',
+        },
         title: '2018年11月经营分析',
         latyout: 'responsivecolumn',
         defaults: {
             cls: 'x-home-chart',
-            margin: '0 0 0 14'
+            margin: '0 0 0 14',
+            userCls: 'big-33 small-50',
         },
         items: [{
             xtype: 'month-sale',
-            userCls: 'big-33 small-50',
         }, {
             xtype: 'month-purchase',
-            userCls: 'big-33 small-50',
         }, {
-            xtype: 'core-chart-gauge',
-            userCls: 'big-33 small-100',
+            xtype: 'month-io',
         }]
     }, {
+        xtype: 'panel',
         title: '2018年11月经营分析',
-        latyout: 'column',
-        // items: [{
-        //     xtype: 'core-chart-line',
-        //     columnWidth: 0.33
-        // }, {
-        //     xtype: 'core-chart-pie',
-        //     columnWidth: 0.33
-        // }, {
-        //     xtype: 'core-chart-pie3d',
-        //     columnWidth: 0.33
-        // }]
-    }],
-
-    items1: [{
-        title: '2018年11月经营分析',
-        userCls: 'big-50 small-100',
-        items: [{
-            xtype: 'core-chart-pie',
-            columnWidth: 0.33,
-            chartConfig: {
-                captions: {
-                    credits: {
-                        text: 'Data: IDC Predictions - 2017\n' +
-                            'Source: Internet',
-                        align: 'left'
-                    }
-                },
-            }
-        }, {
-            xtype: 'core-chart-bar',
-            columnWidth: 0.33
-        }, {
-            xtype: 'core-chart-gauge',
-            columnWidth: 0.33
-        }]
-    }, {
-        title: '经营趋势分析',
-        userCls: 'big-50 small-100',
+        latyout: 'responsivecolumn',
+        style: {
+            marginRight: '0',
+            marginBottom: '0'
+        },
+        defaults: {
+            cls: 'x-home-chart',
+            margin: '0 0 0 14',
+            userCls: 'big-33 small-50',
+        },
         items: [{
-            xtype: 'core-chart-line',
-            columnWidth: 0.33
-        }, {
-            xtype: 'core-chart-pie',
-            columnWidth: 0.33
+            xtype: 'sale-trend',
         }, {
-            xtype: 'core-chart-pie3d',
-            columnWidth: 0.33
-        }]
-    }, {
-        title: '待办事宜',
-        userCls: 'big-100 small-100',
-        items: [{
-            xtype: 'core-chart-polar',
-            columnWidth: 0.5
+            xtype: 'purchase-trend'
         }, {
-            xtype: 'core-chart-stacked',
-            columnWidth: 0.5
+            xtype: 'stock-amount'
         }]
-    }],
+    }]
 });

+ 161 - 363
frontend/saas-web/app/view/home/HomeModel.js

@@ -3,8 +3,10 @@ Ext.define('saas.view.home.HomeModel', {
     alias: 'viewmodel.home',
 
     data: {
-        month_sale_amount: '0',
-        month_purchase_amount: '0'
+        month_sale_amount: '0', // 本月销售合计
+        month_purchase_amount: '0', // 本月采购合计
+        month_in: '0', // 本月收入合计
+        month_out: '0', // 本月支出合计
     },
 
     stores: {
@@ -15,6 +17,10 @@ Ext.define('saas.view.home.HomeModel', {
                 type: 'ajax',
                 // url: 'http://192.168.253.58:8920/homePage/liveData',
                 url: '/api/commons/homePage/liveData',
+                timeout: 8000,
+                actionMethods: {
+                    read: 'GET'
+                },
                 reader: {
                     type: 'json'
                 },
@@ -40,13 +46,33 @@ Ext.define('saas.view.home.HomeModel', {
 
         month_sale: {
             model: 'saas.model.chart.DataXY',
-            // url: 'http://192.168.253.58:8920/homePage/liveData',
-            data: [{
-                "xvalue": "无",
-                "yvalue": 1
-            }],
+            autoLoad: true,
+            proxy: {
+                type: 'ajax',
+                // url: 'http://192.168.253.58:8920/homePage/saleData',
+                url: '/api/commons/homePage/saleData',
+                timeout: 8000,
+                actionMethods: {
+                    read: 'GET'
+                },
+                reader: {
+                    type: 'json',
+                    rootProperty: 'data',
+                },
+                listeners: {
+                    exception: function(proxy, response, operation, eOpts) {
+                        Ext.getCmp('month_sale').setLoading(false);
+                    }
+                }
+            },
             listeners: {
-                load: function() {
+                beforeload: function() {
+                    Ext.getCmp('month_sale').setLoading(true);
+                },
+                load: function(s, d) {
+                    Ext.getCmp('month_sale').setLoading(false);
+                    var sum = Ext.util.Format.number(s.sum('y'), '0.00') || 0;
+                    Ext.getCmp('home').getViewModel().set('month_sale_amount', sum)
                 }
             }
         },
@@ -56,10 +82,15 @@ Ext.define('saas.view.home.HomeModel', {
             autoLoad: true,
             proxy: {
                 type: 'ajax',
-                url: 'http://192.168.253.58:8920/homePage/purchaseData?sixMonths=false',
-                // url: '/api/commons/homePage/liveData',
+                // url: 'http://192.168.253.58:8920/homePage/purchaseData?sixMonths=false',
+                url: '/api/commons/homePage/purchaseData?sixMonths=false',
+                timeout: 8000,
+                actionMethods: {
+                    read: 'GET'
+                },
                 reader: {
-                    type: 'json'
+                    type: 'json',
+                    rootProperty: 'data',
                 },
                 listeners: {
                     exception: function(proxy, response, operation, eOpts) {
@@ -73,384 +104,151 @@ Ext.define('saas.view.home.HomeModel', {
                 },
                 load: function(s, d) {
                     Ext.getCmp('month-purchase').setLoading(false);
+                    var sum = Ext.util.Format.number(s.sum('y'), '0.00') || 0;
+                    Ext.getCmp('home').getViewModel().set('month_purchase_amount', sum+'')
                 }
             }
         },
 
-        barData: {
-            model: 'saas.model.chart.DataXY',
-            data: [
-                {
-                    "xvalue": 2004,
-                    "yvalue": 239
-                },
-                {
-                    "xvalue": 2005,
-                    "yvalue": 402
-                },
-                {
-                    "xvalue": 2006,
-                    "yvalue": 706
-                },
-                {
-                    "xvalue": 2007,
-                    "yvalue": 432
-                },
-                {
-                    "xvalue": 2008,
-                    "yvalue": 200
-                },
-                {
-                    "xvalue": 2009,
-                    "yvalue": 763
-                },
-                {
-                    "xvalue": 2010,
-                    "yvalue": 550
-                },
-                {
-                    "xvalue": 2011,
-                    "yvalue": 630
-                },
-                {
-                    "xvalue": 2012,
-                    "yvalue": 278
+        month_io: {
+            fields: ['x', 'main', 'other'],
+            autoLoad: true,
+            proxy: {
+                type: 'ajax',
+                // url: 'http://192.168.253.58:8920/homePage/payAndRecData',
+                url: '/api/commons/homePage/payAndRecData',
+                timeout: 8000,
+                actionMethods: {
+                    read: 'GET'
                 },
-                {
-                    "xvalue": 2013,
-                    "yvalue": 312
+                reader: {
+                    type: 'json',
+                    rootProperty: 'data',
                 },
-                {
-                    "xvalue": 2014,
-                    "yvalue": 600
+                listeners: {
+                    exception: function(proxy, response, operation, eOpts) {
+                        Ext.getCmp('month_io').setLoading(false);
+                    }
+                }
+            },
+            listeners: {
+                beforeload: function() {
+                    Ext.getCmp('month_io').setLoading(true);
                 },
-                {
-                    "xvalue": 2015,
-                    "yvalue": 283
+                load: function(s, d) {
+                    Ext.getCmp('month_io').setLoading(false);
+                    s.each(function(r) {
+                        var sum = Ext.util.Format.number(r.get('main') + r.get('other'), '0.00') || 0;
+                        if(r.get('x') == '收入') {
+                            Ext.getCmp('home').getViewModel().set('month_in', sum);
+                        }else if(r.get('x') == '支出') {
+                            Ext.getCmp('home').getViewModel().set('month_in', sum);
+                        }
+                    });
                 }
-            ]
+            }
         },
 
-        stackedData: {
-            model: 'saas.model.chart.MultiDataXY',
-            data: [
-                {
-                    "xvalue": 1997,
-                    "y1value": 281,
-                    "y2value": 72,
-                    "y3value": 269,
-                    "y4value": 762
-                },
-                {
-                    "xvalue": 1981,
-                    "y1value": 518,
-                    "y2value": 999,
-                    "y3value": 43,
-                    "y4value": 310
-                },
-                {
-                    "xvalue": 1985,
-                    "y1value": 38,
-                    "y2value": 311,
-                    "y3value": 942,
-                    "y4value": 77
-                },
-                {
-                    "xvalue": 1984,
-                    "y1value": 936,
-                    "y2value": 415,
-                    "y3value": 562,
-                    "y4value": 412
-                },
-                {
-                    "xvalue": 1979,
-                    "y1value": 978,
-                    "y2value": 331,
-                    "y3value": 927,
-                    "y4value": 114
-                },
-                {
-                    "xvalue": 1982,
-                    "y1value": 196,
-                    "y2value": 240,
-                    "y3value": 72,
-                    "y4value": 888
-                },
-                {
-                    "xvalue": 1992,
-                    "y1value": 481,
-                    "y2value": 375,
-                    "y3value": 139,
-                    "y4value": 762
-                },
-                {
-                    "xvalue": 19895,
-                    "y1value": 623,
-                    "y2value": 999,
-                    "y3value": 260,
-                    "y4value": 310
-                },
-                {
-                    "xvalue": 1988,
-                    "y1value": 328,
-                    "y2value": 451,
-                    "y3value": 542,
-                    "y4value": 77
+        sale_trend: {
+            fields: ['x', 'sale', 'saleback'],
+            autoLoad: true,
+            proxy: {
+                type: 'ajax',
+                // url: 'http://192.168.253.58:8920/homePage/saleFutureData',
+                url: '/api/commons/homePage/saleFutureData',
+                timeout: 8000,
+                actionMethods: {
+                    read: 'GET'
                 },
-                {
-                    "xvalue": 1980,
-                    "y1value": 456,
-                    "y2value": 615,
-                    "y3value": 342,
-                    "y4value": 412
+                reader: {
+                    type: 'json',
+                    rootProperty: 'data',
                 },
-                {
-                    "xvalue": 1990,
-                    "y1value": 788,
-                    "y2value": 531,
-                    "y3value": 489,
-                    "y4value": 114
-                }
-            ]
-        },
-
-        gaugeData: {
-            data: [
-                {
-                    position: 40
+                listeners: {
+                    exception: function(proxy, response, operation, eOpts) {
+                        Ext.getCmp('sale_trend').setLoading(false);
+                    }
                 }
+            },
+            sorters: [
+                { property: 'x', direction: 'ASC' }
             ],
-
-            fields: [
-                {
-                    name: 'position'
-                }
-            ]
-        },
-
-        radialData: {
-            model: 'saas.model.chart.DataXY',
-            data: [
-                {
-                    "xvalue": "A",
-                    "yvalue": 417
-                },
-                {
-                    "xvalue": "B",
-                    "yvalue": 676
-                },
-                {
-                    "xvalue": "C",
-                    "yvalue": 606
-                },
-                {
-                    "xvalue": "D",
-                    "yvalue": 124
-                },
-                {
-                    "xvalue": "E",
-                    "yvalue": 473
-                },
-                {
-                    "xvalue": "F",
-                    "yvalue": 108
-                },
-                {
-                    "xvalue": "G",
-                    "yvalue": 847
-                },
-                {
-                    "xvalue": "H",
-                    "yvalue": 947
-                },
-                {
-                    "xvalue": "I",
-                    "yvalue": 694
+            listeners: {
+                beforeload: function() {
+                    Ext.getCmp('sale_trend').setLoading(true);
                 },
-                {
-                    "xvalue": "J",
-                    "yvalue": 603
+                load: function(s, d) {
+                    Ext.getCmp('sale_trend').setLoading(false);
                 }
-            ]
+            } 
         },
 
-        lineData: {
-            model: 'saas.model.chart.DataXY',
-            data: [
-                {
-                    "xvalue": 2011,
-                    "yvalue": 0.1,
-                    "y1value": 0.2,
-                    "y2value": 0.3,
-                    "y3value": 0.1,
-                    "y4value": 0,
-                    "y5value": 1
+        purchase_trend: {
+            fields: ['x', 'y'],
+            autoLoad: true,
+            proxy: {
+                type: 'ajax',
+                // url: 'http://192.168.253.58:8920/homePage/purchaseData?sixMonths=true',
+                url: '/api/commons/homePage/purchaseData?sixMonths=true',
+                timeout: 8000,
+                actionMethods: {
+                    read: 'GET'
                 },
-                {
-                    "xvalue": 2012,
-                    "yvalue": 0.2,
-                    "y1value": 0.4,
-                    "y2value": 0.2,
-                    "y3value": 0.2,
-                    "y4value": 0,
-                    "y5value": 1
+                reader: {
+                    type: 'json',
+                    rootProperty: 'data',
                 },
-                {
-                    "xvalue": 2013,
-                    "yvalue": 0.3,
-                    "y1value": 0.2,
-                    "y2value": 0.4,
-                    "y3value": 0.3,
-                    "y4value": 0,
-                    "y5value": 1
-        
+                listeners: {
+                    exception: function(proxy, response, operation, eOpts) {
+                        Ext.getCmp('purchase_trend').setLoading(false);
+                    }
+                }
+            },
+            sorters: [
+                { property: 'x', direction: 'ASC' }
+            ],
+            listeners: {
+                beforeload: function() {
+                    Ext.getCmp('purchase_trend').setLoading(true);
                 },
-                {
-                    "xvalue": 2014,
-                    "yvalue": 0.2,
-                    "y1value": 0.4,
-                    "y2value": 0.1,
-                    "y3value": 0.2,
-                    "y4value": 0,
-                    "y5value": 1
-                },{
-                    "xvalue": 2015,
-                    "yvalue": 0.4,
-                    "y1value": 0.3,
-                    "y2value": 0.4,
-                    "y3value": 0.4,
-                    "y4value": 0,
-                    "y5value": 1
+                load: function(s, d) {
+                    Ext.getCmp('purchase_trend').setLoading(false);
                 }
-            ]
+            } 
         },
 
-        
-
-        areaData: {
-            model: 'saas.model.chart.MultiDataXY',
-            data: [
-                {
-                    "xvalue": 250,
-                    "y1value": 94,
-                    "y2value": 40
-                },
-                {
-                    "xvalue": 500,
-                    "y1value": 78,
-                    "y2value": 46
-                },
-                {
-                    "xvalue": 750,
-                    "y1value": 60,
-                    "y2value": 53
-                },
-                {
-                    "xvalue": 1250,
-                    "y1value": 51,
-                    "y2value": 48
-                },
-                {
-                    "xvalue": 1500,
-                    "y1value": 60,
-                    "y2value": 36
-                },
-                {
-                    "xvalue": 1750,
-                    "y1value": 68,
-                    "y2value": 26
-                },
-                {
-                    "xvalue": 2250,
-                    "y1value": 59,
-                    "y2value": 37
-                },
-                {
-                    "xvalue": 2500,
-                    "y1value": 40,
-                    "y2value": 58
-                },
-                {
-                    "xvalue": 2750,
-                    "y1value": 24,
-                    "y2value": 78
-                },
-                {
-                    "xvalue": 3250,
-                    "y1value": 36,
-                    "y2value": 85
-                },
-                {
-                    "xvalue": 3500,
-                    "y1value": 65,
-                    "y2value": 70
-                },
-                {
-                    "xvalue": 3750,
-                    "y1value": 94,
-                    "y2value": 55
-                },
-                {
-                    "xvalue": 4250,
-                    "y1value": 103,
-                    "y2value": 61
-                },
-                {
-                    "xvalue": 4500,
-                    "y1value": 83,
-                    "y2value": 82
-                },
-                {
-                    "xvalue": 4750,
-                    "y1value": 61,
-                    "y2value": 102
-                },
-                {
-                    "xvalue": 5250,
-                    "y1value": 55,
-                    "y2value": 95
-                },
-                {
-                    "xvalue": 5500,
-                    "y1value": 70,
-                    "y2value": 67
-                },
-                {
-                    "xvalue": 5750,
-                    "y1value": 84,
-                    "y2value": 39
-                },
-                {
-                    "xvalue": 6250,
-                    "y1value": 78,
-                    "y2value": 31
-                },
-                {
-                    "xvalue": 6500,
-                    "y1value": 58,
-                    "y2value": 49
-                },
-                {
-                    "xvalue": 6750,
-                    "y1value": 38,
-                    "y2value": 69
+        stock_amount: {
+            fields: ['x', 'y'],
+            autoLoad: true,
+            proxy: {
+                type: 'ajax',
+                // url: 'http://192.168.253.58:8920/homePage/storageData',
+                url: '/api/commons/homePage/storageData',
+                timeout: 8000,
+                actionMethods: {
+                    read: 'GET'
                 },
-                {
-                    "xvalue": 7250,
-                    "y1value": 41,
-                    "y2value": 74
+                reader: {
+                    type: 'json',
+                    rootProperty: 'data',
                 },
-                {
-                    "xvalue": 7500,
-                    "y1value": 65,
-                    "y2value": 60
+                listeners: {
+                    exception: function(proxy, response, operation, eOpts) {
+                        Ext.getCmp('stock_amount').setLoading(false);
+                    }
+                }
+            },
+            sorters: [
+                { property: 'x', direction: 'ASC' }
+            ],
+            listeners: {
+                beforeload: function() {
+                    Ext.getCmp('stock_amount').setLoading(true);
                 },
-                {
-                    "xvalue": 7750,
-                    "y1value": 89,
-                    "y2value": 46
+                load: function(s, d) {
+                    Ext.getCmp('stock_amount').setLoading(false);
                 }
-            ]
-        }
-    }
+            } 
+        },
+    },
 });

+ 2 - 2
frontend/saas-web/app/view/home/InfoCard.js

@@ -39,11 +39,11 @@ Ext.define('saas.view.home.InfoCard', {
             color: 'purple'
         },
         unpay: {
-            title: '七天内付款',
+            title: '七天内付款',
             color: 'red'
         },
         unreceive: {
-            title: '七天内收款',
+            title: '七天内收款',
             color: 'pink'
         },
         unauditcheck: {

+ 78 - 0
frontend/saas-web/app/view/home/charts/MonthIO.js

@@ -0,0 +1,78 @@
+Ext.define('saas.view.home.charts.MonthIO', {
+    extend: 'saas.view.core.chart.ChartBase',
+    xtype: 'month-io',
+    id: 'month_io',
+
+    initComponent: function () {
+        var me = this;
+
+        Ext.apply(me, {
+            items: [{
+                xtype: 'cartesian',
+                reference: 'chart',
+                colors: [
+                    '#2C82BE',
+                    '#82CCFF'
+                ],
+                bind: {
+                    captions: {
+                        title: {
+                            text: '本月收入(万元):{month_in}\n本月支出(万元):{month_out}',
+                            style: {
+                                'font-size': '14px',
+                                'color': '#485465',
+                                'letter-spacing': '-0.07px'
+                            },
+                            align: 'left'
+                        },
+                    },
+                    store: '{month_io}'
+                },
+                // legend: {
+                //     type: 'sprite',
+                //     docked: 'bottom'
+                // },
+                axes: [{
+                    type: 'numeric',
+                    position: 'left',
+                    adjustByMajorUnit: true,
+                    fields: ['main'],
+                    minimum: 0
+                }, {
+                    type: 'category',
+                    position: 'bottom',
+                    grid: true,
+                    fields: ['x'],
+                    label: {
+                        rotate: {
+                            degrees: -45
+                        }
+                    }
+                }],
+                series: [{
+                    type: 'bar',
+                    title: ['主营业务', '其他业务'],
+                    xField: 'x',
+                    yField: ['main', 'other'],
+                    stacked: true,
+                    style: {
+                        opacity: 0.80
+                    },
+                    tooltip: {
+                        trackMouse: true,
+                        renderer: me.onBarTipRender
+                    }
+                }]
+            }]
+        });
+
+        me.callParent(arguments);
+    },
+
+    onBarTipRender: function (tooltip, record, item) {
+        var fieldIndex = Ext.Array.indexOf(item.series.getYField(), item.field),
+        type = item.series.getTitle()[fieldIndex];
+
+        tooltip.setHtml(type + record.get('x') + record.get(item.field));
+    },
+});

+ 54 - 62
frontend/saas-web/app/view/home/charts/MonthPurchase.js

@@ -2,71 +2,63 @@ Ext.define('saas.view.home.charts.MonthPurchase', {
     extend: 'saas.view.core.chart.ChartBase',
     xtype: 'month-purchase',
 
-    requires: [
-        'Ext.chart.CartesianChart',
-        'Ext.chart.axis.Category',
-        'Ext.chart.axis.Numeric',
-        'Ext.chart.interactions.PanZoom',
-        'Ext.chart.series.Bar'
-    ],
-
     id: 'month-purchase',
 
-    iconCls: 'x-fa fa-bar-chart',
+    initComponent: function() {
+        var me = this;
+
+        Ext.apply(me, {
+            items: [{
+                xtype: 'cartesian',
+                colors: [
+                    '#34BAF6'
+                ],
+                bind: {
+                    store: '{month_purchase}',
+                    captions: {
+                        title: {
+                            text: '本月采购额(万元):{month_purchase_amount}',
+                            style: {
+                                'font-size': '14px',
+                                'color': '#485465',
+                                'letter-spacing': '-0.07px'
+                            },
+                            align: 'left'
+                        }
+                    },
+                },
+                axes: [{
+                    type: 'category',
+                    fields: [
+                        'x'
+                    ],
+                    position: 'bottom'
+                },{
+                    type: 'numeric',
+                    fields: [
+                        'y'
+                    ],
+                    position: 'left'
+                }],
+                series: [{
+                    type: 'bar',
+                    xField: 'x',
+                    yField: [
+                        'y'
+                    ],
+                    tooltip: {
+                        trackMouse: true,
+                        renderer: me.onBarTipRender
+                    }
+                }]
+            }]
+        });
+
+        me.callParent(arguments);
+    },
 
-    bind: {
-        title: '本月采购额(万元):{month_purchase_amount}',
+    onBarTipRender: function (tooltip, record, item) {
+        tooltip.setHtml(record.get('x') + ': ' + record.get('y') + '万元');
     },
 
-    items: [{
-        xtype: 'cartesian',
-        colors: [
-            '#34BAF6'
-        ],
-        bind: '{month_purchase}',
-        axes: [{
-            type: 'category',
-            fields: [
-                'x'
-            ],
-            hidden: true,
-            position: 'bottom'
-        },{
-            type: 'numeric',
-            fields: [
-                'y'
-            ],
-            grid: {
-                odd: {
-                    fill: '#e8e8e8'
-                }
-            },
-            hidden: true,
-            position: 'left'
-        }],
-        series: [{
-            type: 'bar',
-            xField: 'x',
-            yField: [
-                'y'
-            ]
-        }],
-        platformConfig: {
-            phone: {
-                // On a phone the whole view becomes a vertical strip of charts,
-                // which makes it impossible to scroll the view if touch action
-                // started on a chart. So we use a custom touchAction config.
-                touchAction: {
-                    panX: true,
-                    panY: true
-                }
-            },
-            '!phone': {
-                interactions: {
-                    type: 'panzoom',
-                    zoomOnPanGesture: true
-                }
-            }
-        }
-    }]
 });

+ 36 - 35
frontend/saas-web/app/view/home/charts/MonthSale.js

@@ -2,32 +2,29 @@ Ext.define('saas.view.home.charts.MonthSale', {
     extend: 'saas.view.core.chart.ChartBase',
     xtype: 'month-sale',
 
-    requires: [
-        'Ext.chart.PolarChart',
-        'Ext.chart.interactions.Rotate',
-        'Ext.chart.series.Pie',
-        'Ext.chart.series.sprite.PieSlice'
-    ],
-
     id: 'month_sale',
 
-    iconCls: 'x-fa fa-pie-chart',
-
-    bind: {
-        title: '本月销售额(万元):{month_sale_amount}',
-    },
-
     initComponent: function() {
         var me = this;
 
         Ext.apply(me, {
             items: [{
                 xtype: 'polar',
-                width: '100%',
-                height: 500,
-                innerPadding: me.innerPadding || 20,
-                interactions: ['rotate', 'itemhighlight'],
-                donut: 30,
+                reference: 'chart',
+                bind: {
+                    captions: {
+                        title: {
+                            text: '本月销售额(万元):{month_sale_amount}',
+                            style: {
+                                'font-size': '14px',
+                                'color': '#485465',
+                                'letter-spacing': '-0.07px'
+                            },
+                            align: 'left'
+                        }
+                    },
+                    store: '{month_sale}',
+                },
                 colors: [
                     '#2C82BE',
                     '#27A7FF',
@@ -36,36 +33,40 @@ Ext.define('saas.view.home.charts.MonthSale', {
                     '#76DDFB',
                     '#DBECF8',
                 ],
-                bind: {
-                    store: '{month_sale}',
-                },
-                style: {
-                    border: 'none'
-                },
+                width: '100%',
+                innerPadding: 20,
+                // legend: {
+                //     docked: 'bottom'
+                // },
+                interactions: ['rotate', 'itemhighlight'],
                 series: [{
                     type: 'pie',
-                    angleField: me.yfield || 'yvalue',
+                    angleField: 'y',
+                    donut: 55,
                     label: {
-                        field: me.xfield || 'xvalue',
-                        display: 'rotate'
+                        field: 'x',
+                        renderer: me.onLabelRender
                     },
-                    donut: 55,
                     highlight: true,
                     tooltip: {
                         trackMouse: true,
                         renderer: me.onSeriesTooltipRender
-                    }
-                }],
-                // legend: {
-                //     docked: 'bottom'
-                // },
-            }]
+                    },
+                }]
+            }],
         });
 
         me.callParent(arguments);
     },
 
+    onLabelRender: function(text, sprite, config, rendererData, index) {
+        var homeModel = Ext.getCmp('home').getViewModel();
+        var monthSaleAmount = homeModel.get('month_sale_amount');
+        console.log(text, sprite, config, rendererData, index)
+        return text;
+    },
+
     onSeriesTooltipRender: function (tooltip, record, item) {
-        tooltip.setHtml(record.get('xvalue') + ': ' + record.get('data1') + '%');
+        tooltip.setHtml(record.get('x') + ': ' + record.get('y'));
     }
 });

+ 58 - 0
frontend/saas-web/app/view/home/charts/PurchaseTrend.js

@@ -0,0 +1,58 @@
+Ext.define('saas.view.home.charts.PurchaseTrend', {
+    extend: 'saas.view.core.chart.ChartBase',
+    xtype: 'purchase-trend',
+
+    id: 'purchase_trend',
+
+    initComponent: function() {
+        var me = this;
+
+        Ext.apply(me, {
+            items: [{
+                xtype: 'cartesian',
+                colors: [
+                    '#34BAF6'
+                ],
+                captions: {
+                    title: {
+                        text: '采购金额(万元)',
+                        style: {
+                            'font-size': '14px',
+                            'color': '#485465',
+                            'letter-spacing': '-0.07px'
+                        },
+                        align: 'left'
+                    }
+                },
+                bind: {
+                    store: '{purchase_trend}',
+                },
+                axes: [{
+                    type: 'category',
+                    fields: ['x'],
+                    position: 'bottom'
+                },{
+                    type: 'numeric',
+                    fields: ['y'],
+                    position: 'left'
+                }],
+                series: [{
+                    type: 'bar',
+                    xField: 'x',
+                    yField: ['y'],
+                    tooltip: {
+                        trackMouse: true,
+                        renderer: me.onBarTipRender
+                    }
+                }]
+            }]
+        });
+
+        me.callParent(arguments);
+    },
+
+    onBarTipRender: function (tooltip, record, item) {
+        tooltip.setHtml(record.get('x') + ': ' + record.get('y') + '万元');
+    },
+
+});

+ 77 - 0
frontend/saas-web/app/view/home/charts/SaleTrend.js

@@ -0,0 +1,77 @@
+Ext.define('saas.view.home.charts.SaleTrend', {
+    extend: 'saas.view.core.chart.ChartBase',
+    xtype: 'sale-trend',
+
+    id: 'sale_trend',
+
+    initComponent: function() {
+        var me = this;
+
+        Ext.apply(me, {
+            items: [{
+                xtype: 'cartesian',
+                colors: [
+                    '#64B0E4',
+                    '#FF1038'
+                ],
+                captions: {
+                    title: {
+                        text: '销售趋势图',
+                        style: {
+                            'font-size': '14px',
+                            'color': '#485465',
+                            'letter-spacing': '-0.07px'
+                        },
+                        align: 'left'
+                    }
+                },
+                bind: {
+                    store: '{sale_trend}',
+                },
+                axes: [{
+                    type: 'category',
+                    fields: ['x'],
+                    position: 'bottom',
+                    label: {
+                        rotate: {
+                            degrees: -25
+                        }
+                    }
+                },{
+                    type: 'numeric',
+                    fields: ['sale', 'saleback'],
+                    position: 'left',
+                }],
+                series: [{
+                    type: 'line',
+                    smooth: true,
+                    title: '销售额',
+                    xField: 'x',
+                    yField: ['sale'],
+                    tooltip: {
+                        trackMouse: true,
+                        renderer: me.onSeriesTooltipRender
+                    }
+                }, {
+                    type: 'line',
+                    smooth: true,
+                    title: '销售回款',
+                    xField: 'x',
+                    yField: ['saleback'],
+                    tooltip: {
+                        trackMouse: true,
+                        renderer: me.onSeriesTooltipRender
+                    }
+                }]
+            }]
+        });
+
+        me.callParent(arguments);
+    },
+
+    onSeriesTooltipRender: function (tooltip, record, item) {
+        var title = item.series.getTitle();
+        tooltip.setHtml(record.get('x') + title + record.get(item.series.getYField()) + '万元');
+    },
+
+});

+ 58 - 0
frontend/saas-web/app/view/home/charts/StockAmount.js

@@ -0,0 +1,58 @@
+Ext.define('saas.view.home.charts.StockAmount', {
+    extend: 'saas.view.core.chart.ChartBase',
+    xtype: 'stock-amount',
+
+    id: 'stock_amount',
+
+    initComponent: function() {
+        var me = this;
+
+        Ext.apply(me, {
+            items: [{
+                xtype: 'cartesian',
+                colors: [
+                    '#34BAF6'
+                ],
+                captions: {
+                    title: {
+                        text: '库存金额(万元)',
+                        style: {
+                            'font-size': '14px',
+                            'color': '#485465',
+                            'letter-spacing': '-0.07px'
+                        },
+                        align: 'left'
+                    }
+                },
+                bind: {
+                    store: '{stock_amount}',
+                },
+                axes: [{
+                    type: 'category',
+                    fields: ['x'],
+                    position: 'bottom'
+                },{
+                    type: 'numeric',
+                    fields: ['y'],
+                    position: 'left'
+                }],
+                series: [{
+                    type: 'bar',
+                    xField: 'x',
+                    yField: ['y'],
+                    tooltip: {
+                        trackMouse: true,
+                        renderer: me.onBarTipRender
+                    }
+                }]
+            }]
+        });
+
+        me.callParent(arguments);
+    },
+
+    onBarTipRender: function (tooltip, record, item) {
+        tooltip.setHtml(record.get('x') + ': ' + record.get('y') + '万元');
+    },
+
+});

+ 20 - 0
script/mysql/init/mail.sql

@@ -0,0 +1,20 @@
+CREATE DATABASE `saas_mail` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
+use `saas_mail`;
+
+create table `m_log` (
+  `id` int unsigned primary key not null auto_increment,
+  `template_id` int comment '模板',
+  `subject` varchar(300) not null comment '主题',
+  `text` text comment '内容',
+  `from` varchar(100) comment '发送人',
+  `to` varchar(1000) comment '接收人',
+  `company_id` int,
+  `creator_id` int,
+  `create_time` datetime
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='邮件日志';
+
+create table `m_template` (
+  `id` varchar(300) primary key not null,
+  `subject` varchar(300) not null comment '主题',
+  `text` text comment '内容'
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='邮件模板';