Browse Source

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

rainco 7 years ago
parent
commit
409bdb1fdb
75 changed files with 2474 additions and 1271 deletions
  1. 15 0
      applications/commons/commons-api/src/main/java/com/usoftchina/saas/commons/api/SystemRemindApi.java
  2. 80 0
      applications/commons/commons-dto/src/main/java/com/usoftchina/saas/commons/dto/AddApplyDTO.java
  3. 1 1
      applications/commons/commons-dto/src/main/java/com/usoftchina/saas/commons/exception/BizExceptionCode.java
  4. 63 0
      applications/commons/commons-dto/src/main/java/com/usoftchina/saas/commons/po/AddApply.java
  5. 52 0
      applications/commons/commons-server/src/main/java/com/usoftchina/saas/commons/controller/SystemRemindController.java
  6. 15 0
      applications/commons/commons-server/src/main/java/com/usoftchina/saas/commons/mapper/SystemRemindMapper.java
  7. 29 0
      applications/commons/commons-server/src/main/java/com/usoftchina/saas/commons/service/SystemRemindService.java
  8. 68 0
      applications/commons/commons-server/src/main/java/com/usoftchina/saas/commons/service/impl/SystemRemindServiceImpl.java
  9. 75 0
      applications/commons/commons-server/src/main/resources/mapper/SystemRemindMapper.xml
  10. 1 1
      applications/document/document-server/src/main/java/com/usoftchina/saas/document/mapper/BanksubledgerMapper.java
  11. 1 0
      applications/document/document-server/src/main/java/com/usoftchina/saas/document/service/impl/BankinformationServiceImpl.java
  12. 2 2
      applications/document/document-server/src/main/java/com/usoftchina/saas/document/service/impl/ProductServiceImpl.java
  13. 4 5
      applications/document/document-server/src/main/java/com/usoftchina/saas/document/service/impl/WarehouseServiceImpl.java
  14. 1 1
      applications/document/document-server/src/main/resources/mapper/BanksubledgerMapper.xml
  15. 1 1
      applications/document/document-server/src/main/resources/mapper/CustomerkindMapper.xml
  16. 1 1
      applications/document/document-server/src/main/resources/mapper/ProductDetailMapper.xml
  17. 3 3
      applications/document/document-server/src/main/resources/mapper/ProductMapper.xml
  18. 1 1
      applications/money/money-server/src/main/java/com/usoftchina/saas/money/mapper/BanksubledgerMapper.java
  19. 1 1
      applications/money/money-server/src/main/java/com/usoftchina/saas/money/service/impl/PaybalanceServiceImpl.java
  20. 1 1
      applications/money/money-server/src/main/java/com/usoftchina/saas/money/service/impl/RecbalanceServiceImpl.java
  21. 1 1
      applications/money/money-server/src/main/resources/mapper/BanksubledgerMapper.xml
  22. 19 0
      applications/sale/sale-server/src/main/java/com/usoftchina/saas/sale/service/impl/ProdInOutServiceImpl.java
  23. 18 0
      base-servers/account/account-api/src/main/java/com/usoftchina/saas/account/api/AccountApi.java
  24. 9 0
      base-servers/account/account-dto/src/main/java/com/usoftchina/saas/account/dto/BindCompanyDTO.java
  25. 8 0
      base-servers/account/account-server/pom.xml
  26. 45 1
      base-servers/account/account-server/src/main/java/com/usoftchina/saas/account/controller/AccountCenterController.java
  27. 1 1
      base-servers/account/account-server/src/main/java/com/usoftchina/saas/account/controller/AccountController.java
  28. 1 1
      base-servers/account/account-server/src/main/resources/application.yml
  29. 1 1
      base-servers/account/account-server/src/main/resources/mapper/AccountCompanyMapper.xml
  30. 165 84
      frontend/saas-portal-web/src/components/conenter/addenterprise.vue
  31. 37 84
      frontend/saas-portal-web/src/components/conenter/company.vue
  32. 138 8
      frontend/saas-portal-web/src/components/conenter/enterprise.vue
  33. 1 1
      frontend/saas-portal-web/src/components/conenter/home.vue
  34. 0 2
      frontend/saas-portal-web/src/store/index.js
  35. 13 8
      frontend/saas-portal-web/static/css/gongsi.css
  36. BIN
      frontend/saas-portal-web/static/img/banner--X.jpg
  37. BIN
      frontend/saas-portal-web/static/img/banner@3x@2x.png
  38. BIN
      frontend/saas-portal-web/static/img/ok.png
  39. BIN
      frontend/saas-portal-web/static/img/warning.png
  40. 3 0
      frontend/saas-web/app.json
  41. 18 0
      frontend/saas-web/app/util/BaseUtil.js
  42. 181 0
      frontend/saas-web/app/view/core/chart/EChartsBase.js
  43. 5 5
      frontend/saas-web/app/view/core/query/QueryGridPanel.js
  44. 17 13
      frontend/saas-web/app/view/core/tab/Controller.js
  45. 2 2
      frontend/saas-web/app/view/document/employee/Window.js
  46. 0 87
      frontend/saas-web/app/view/home/HomeModel.js
  47. 4 4
      frontend/saas-web/app/view/home/charts/KeyData.scss
  48. 107 77
      frontend/saas-web/app/view/home/charts/MonthIO.js
  49. 0 91
      frontend/saas-web/app/view/home/charts/MonthPurchase.js
  50. 76 65
      frontend/saas-web/app/view/home/charts/MonthSale.js
  51. 93 72
      frontend/saas-web/app/view/home/charts/ProfitDetail.js
  52. 0 98
      frontend/saas-web/app/view/home/charts/PurchaseTrend.js
  53. 102 170
      frontend/saas-web/app/view/home/charts/SaleTrend.js
  54. 80 68
      frontend/saas-web/app/view/home/charts/StockAmount.js
  55. 0 1
      frontend/saas-web/app/view/home/infoCardList/InfoList.js
  56. 5 1
      frontend/saas-web/app/view/main/Main.js
  57. 1 13
      frontend/saas-web/app/view/stock/inventory/EditDataList.js
  58. 2 2
      frontend/saas-web/app/view/sys/account/DataList.js
  59. 2 2
      frontend/saas-web/app/view/sys/account/EditWindow.js
  60. 2 2
      frontend/saas-web/app/view/sys/config/FormPanel.js
  61. 2 2
      frontend/saas-web/app/view/sys/feedback/FormPanel.js
  62. 25 6
      frontend/saas-web/app/view/viewport/ViewportController.js
  63. BIN
      frontend/saas-web/electron/build/icon.icns
  64. BIN
      frontend/saas-web/electron/build/icon.ico
  65. BIN
      frontend/saas-web/electron/build/icons/48x48.png
  66. 2 0
      frontend/saas-web/electron/dev-app-update.yml
  67. BIN
      frontend/saas-web/electron/images/icon.ico
  68. 79 2
      frontend/saas-web/electron/login.html
  69. 0 32
      frontend/saas-web/electron/main.dev.js
  70. 111 36
      frontend/saas-web/electron/main.js
  71. 57 10
      frontend/saas-web/electron/package.json
  72. 85 0
      frontend/saas-web/electron/update.html
  73. 515 199
      frontend/saas-web/electron/yarn.lock
  74. 21 0
      frontend/saas-web/lib/echarts.common.min.js
  75. 5 1
      frontend/saas-web/overrides/data/Connection.js

+ 15 - 0
applications/commons/commons-api/src/main/java/com/usoftchina/saas/commons/api/SystemRemindApi.java

@@ -0,0 +1,15 @@
+package com.usoftchina.saas.commons.api;
+
+import com.usoftchina.saas.base.Result;
+import com.usoftchina.saas.commons.dto.AddApplyDTO;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+@FeignClient("commons-server")
+public interface SystemRemindApi {
+
+    @PostMapping("/remind/apply/save")
+    Result save(@RequestBody AddApplyDTO addApplyDTO);
+
+}

+ 80 - 0
applications/commons/commons-dto/src/main/java/com/usoftchina/saas/commons/dto/AddApplyDTO.java

@@ -0,0 +1,80 @@
+package com.usoftchina.saas.commons.dto;
+
+import com.usoftchina.saas.base.dto.CommonBaseDTO;
+
+import java.io.Serializable;
+
+/**
+ * @Description 加入企业申请  传输对象
+ * @Author chenwei
+ * @Date 2018/12/14
+ */
+public class AddApplyDTO extends CommonBaseDTO implements Serializable {
+
+    private String companyName;
+    private String username;
+    private String mobile;
+    private String roles;
+    /**
+     * 审批状态:  2.待处理  0.不同意   1.同意
+     */
+    private String status;
+    private Long creatorId;
+    private Long companyId;
+
+    public Long getCompanyId() {
+        return companyId;
+    }
+
+    public void setCompanyId(Long companyId) {
+        this.companyId = companyId;
+    }
+
+    public String getRoles() {
+        return roles;
+    }
+
+    public String getCompanyName() {
+        return companyName;
+    }
+
+    public void setCompanyName(String companyName) {
+        this.companyName = companyName;
+    }
+
+    public Long getCreatorId() {
+        return creatorId;
+    }
+
+    public void setCreatorId(Long creatorId) {
+        this.creatorId = creatorId;
+    }
+
+    public void setRoles(String roles) {
+        this.roles = roles;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getMobile() {
+        return mobile;
+    }
+
+    public void setMobile(String mobile) {
+        this.mobile = mobile;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+}

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

@@ -111,7 +111,7 @@ public enum BizExceptionCode implements BaseExceptionCode {
     DELETE_NOT_EXIS(74008,"删除失败,当前单据不存在!"),
     DOCUMENTS_AUDITED(74009,"存在已审核单据:%S"),
     DOCUMENTS_UNAUDITED(74010,"存在未审核单据:%S"),
-    BANK_AMOUNT_NOTENOUGHS(74011, "审核失败!资金账户:%S 余额不足"),
+    BANK_AMOUNT_NOTENOUGHS(74011, "资金账户:%S 余额不足"),
 
     //反结账
     EARLY_USERING(74012, "期初余额被使用,无法反结账"),

+ 63 - 0
applications/commons/commons-dto/src/main/java/com/usoftchina/saas/commons/po/AddApply.java

@@ -0,0 +1,63 @@
+package com.usoftchina.saas.commons.po;
+
+import com.usoftchina.saas.base.entity.CommonBaseEntity;
+
+import java.io.Serializable;
+
+/**
+ * @Description 加入申请 实体对象
+ * @Author chenwei
+ * @Date 2018/12/14
+ */
+public class AddApply extends CommonBaseEntity implements Serializable {
+
+    private String username;
+    private String mobile;
+    private String roles;
+    /**
+     * 审批状态:  2.待处理  0.不同意   1.同意
+     */
+    private String status;
+    private Long companyId;
+
+    @Override
+    public Long getCompanyId() {
+        return companyId;
+    }
+
+    public void setCompanyId(Long companyId) {
+        this.companyId = companyId;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getMobile() {
+        return mobile;
+    }
+
+    public void setMobile(String mobile) {
+        this.mobile = mobile;
+    }
+
+    public String getRoles() {
+        return roles;
+    }
+
+    public void setRoles(String roles) {
+        this.roles = roles;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+}

+ 52 - 0
applications/commons/commons-server/src/main/java/com/usoftchina/saas/commons/controller/SystemRemindController.java

@@ -0,0 +1,52 @@
+package com.usoftchina.saas.commons.controller;
+
+import com.usoftchina.saas.base.Result;
+import com.usoftchina.saas.commons.dto.AddApplyDTO;
+import com.usoftchina.saas.commons.dto.ListReqDTO;
+import com.usoftchina.saas.commons.service.SystemRemindService;
+import com.usoftchina.saas.page.PageDefault;
+import com.usoftchina.saas.page.PageRequest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * @Description 系统提醒
+ * @Author chenwei
+ * @Date 2018/12/14
+ */
+@RestController
+@RequestMapping("/remind")
+public class SystemRemindController {
+
+    @Autowired
+    private SystemRemindService systemRemindService;
+
+    /**
+     * @description 申请列表
+     * @param pageRequest
+     * @param listReqDTO
+     * @return
+     */
+    @GetMapping("/apply/list")
+    public Result getApplyList(@PageDefault(number = 1, size = 10) PageRequest pageRequest, ListReqDTO listReqDTO){
+        return Result.success(systemRemindService.getApplyList(pageRequest, listReqDTO));
+    }
+
+    /**
+     * 批准、不批准申请
+     * @param addApplyDTO
+     * @return
+     */
+    @PostMapping("/apply/confirm")
+    public Result confirmApply(@RequestBody AddApplyDTO addApplyDTO){
+        systemRemindService.confirmApply(addApplyDTO);
+        return Result.success();
+    }
+
+    @PostMapping("/apply/save")
+    public Result save(@RequestBody AddApplyDTO addApplyDTO){
+        systemRemindService.save(addApplyDTO);
+        return Result.success();
+    }
+
+}

+ 15 - 0
applications/commons/commons-server/src/main/java/com/usoftchina/saas/commons/mapper/SystemRemindMapper.java

@@ -0,0 +1,15 @@
+package com.usoftchina.saas.commons.mapper;
+
+import com.usoftchina.saas.base.mapper.CommonBaseMapper;
+import com.usoftchina.saas.commons.dto.AddApplyDTO;
+import com.usoftchina.saas.commons.po.AddApply;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface SystemRemindMapper extends CommonBaseMapper<AddApply> {
+
+    List<AddApplyDTO> getApplyList(@Param("condition") String condition, @Param("companyId") Long companyId);
+
+    void confirmApply(@Param("status") String status, @Param("id") Long id, @Param("updaterId") Long updaterId);
+}

+ 29 - 0
applications/commons/commons-server/src/main/java/com/usoftchina/saas/commons/service/SystemRemindService.java

@@ -0,0 +1,29 @@
+package com.usoftchina.saas.commons.service;
+
+import com.github.pagehelper.PageInfo;
+import com.usoftchina.saas.commons.dto.AddApplyDTO;
+import com.usoftchina.saas.commons.dto.ListReqDTO;
+import com.usoftchina.saas.page.PageRequest;
+
+public interface SystemRemindService {
+
+    /**
+     * 保存加入申请
+     * @param addApplyDTO
+     */
+    void save(AddApplyDTO addApplyDTO);
+
+    /**
+     * 查询申请列表
+     * @param pageRequest
+     * @param listReqDTO
+     * @return
+     */
+    PageInfo<AddApplyDTO> getApplyList(PageRequest pageRequest, ListReqDTO listReqDTO);
+
+    /**
+     * 批准、不批准
+     * @param addApplyDTO
+     */
+    void confirmApply(AddApplyDTO addApplyDTO);
+}

+ 68 - 0
applications/commons/commons-server/src/main/java/com/usoftchina/saas/commons/service/impl/SystemRemindServiceImpl.java

@@ -0,0 +1,68 @@
+package com.usoftchina.saas.commons.service.impl;
+
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import com.usoftchina.saas.account.api.AccountApi;
+import com.usoftchina.saas.account.dto.AccountDTO;
+import com.usoftchina.saas.commons.dto.AddApplyDTO;
+import com.usoftchina.saas.commons.dto.ListReqDTO;
+import com.usoftchina.saas.commons.mapper.SystemRemindMapper;
+import com.usoftchina.saas.commons.po.AddApply;
+import com.usoftchina.saas.commons.service.SystemRemindService;
+import com.usoftchina.saas.context.BaseContextHolder;
+import com.usoftchina.saas.page.PageRequest;
+import com.usoftchina.saas.utils.BeanMapper;
+import com.usoftchina.saas.utils.ObjectUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @Description TODO
+ * @Author chenwei
+ * @Date 2018/12/14
+ */
+@Service
+public class SystemRemindServiceImpl implements SystemRemindService {
+
+    @Autowired
+    private SystemRemindMapper systemRemindMapper;
+    @Autowired
+    private AccountApi accountApi;
+
+    @Override
+    public void save(AddApplyDTO addApplyDTO) {
+        addApplyDTO.setCreateTime(new Date());
+        AddApply addApply = BeanMapper.map(addApplyDTO, AddApply.class);
+        addApply.setCreatorId(BaseContextHolder.getUserId());
+        addApply.setCreatorName(BaseContextHolder.getUserName());
+        systemRemindMapper.insertSelective(addApply);
+    }
+
+    @Override
+    public PageInfo<AddApplyDTO> getApplyList(PageRequest pageRequest, ListReqDTO listReqDTO) {
+        PageHelper.startPage(pageRequest.getNumber(), pageRequest.getSize());
+        String condition = listReqDTO.getFinalCondition();
+        List<AddApplyDTO> addApplyDTOList = systemRemindMapper.getApplyList(condition, BaseContextHolder.getCompanyId());
+        PageInfo<AddApplyDTO> pageInfo = new PageInfo<AddApplyDTO>(addApplyDTOList);
+        return pageInfo;
+    }
+
+    @Override
+    public void confirmApply(AddApplyDTO addApplyDTO) {
+        //批准
+        if ("1".equals(addApplyDTO.getStatus())){
+            AccountDTO accountDTO = accountApi.getAccount(addApplyDTO.getMobile()).getData();
+            if (!ObjectUtils.isEmpty(accountDTO)){
+                //绑定公司
+                accountApi.bindCompany(accountDTO.getId(), BaseContextHolder.getCompanyId());
+                //绑定角色
+                accountApi.bindRoles(accountDTO.getId(), addApplyDTO.getRoles());
+            }
+        }
+        //更新申请单状态
+        systemRemindMapper.confirmApply(addApplyDTO.getStatus(), addApplyDTO.getId(), BaseContextHolder.getUserId());
+    }
+}

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

@@ -0,0 +1,75 @@
+<?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.commons.mapper.SystemRemindMapper">
+    <resultMap id="BaseResultMap" type="com.usoftchina.saas.commons.dto.AddApplyDTO">
+        <result column="re_id" jdbcType="INTEGER" property="id" />
+        <result column="re_applyname" jdbcType="VARCHAR" property="username" />
+        <result column="re_applymobile" jdbcType="VARCHAR" property="mobile" />
+        <result column="re_status" jdbcType="VARCHAR" property="status" />
+        <result column="creatorId" jdbcType="INTEGER" property="creatorId" />
+        <result column="creatorName" jdbcType="VARCHAR" property="creatorName" />
+        <result column="updateTime" jdbcType="TIMESTAMP" property="updateTime" />
+    </resultMap>
+    <select id="getApplyList" resultMap="BaseResultMap">
+      SELECT * FROM REMIND
+      <where>
+          <if test="condition != null">
+              ${condition}
+          </if>
+          <if test="companyId != null">
+              AND COMPANYID = #{companyId}
+          </if>
+      </where>
+      ORDER BY RE_STATUS, CREATETIME DESC
+    </select>
+    <update id="confirmApply">
+        UPDATE REMIND SET STATUS = #{status}, updateTime = now(), updaterId = #{updaterId}
+        where re_id = #{id}
+    </update>
+    <insert id="insertSelective" parameterType="com.usoftchina.saas.commons.po.AddApply">
+        <selectKey resultType="java.lang.Long" keyProperty="id">
+            SELECT LAST_INSERT_ID() AS ID
+        </selectKey>
+        insert into remind
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="username != null">
+                re_applyname,
+            </if>
+            <if test="mobile != null">
+                re_applymobile,
+            </if>
+            <if test="creatorId != null">
+                creatorId,
+            </if>
+            <if test="creatorName != null">
+                creatorName,
+            </if>
+            <if test="createTime != null">
+                createTime,
+            </if>
+            <if test="companyId != null">
+                companyId
+            </if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="username != null">
+                #{username, jdbcType=VARCHAR},
+            </if>
+            <if test="mobile != null">
+                #{mobile, jdbcType=VARCHAR},
+            </if>
+            <if test="creatorId != null">
+                #{creatorId, jdbcType=INTEGER},
+            </if>
+            <if test="creatorName != null">
+                #{creatorName, jdbcType=VARCHAR},
+            </if>
+            <if test="createTime != null">
+                #{createTime, jdbcType=TIMESTAMP},
+            </if>
+            <if test="companyId != null">
+                #{companyId, jdbcType=TIMESTAMP}
+            </if>
+        </trim>
+    </insert>
+</mapper>

+ 1 - 1
applications/document/document-server/src/main/java/com/usoftchina/saas/document/mapper/BanksubledgerMapper.java

@@ -19,7 +19,7 @@ public interface BanksubledgerMapper extends CommonBaseMapper<Banksubledger> {
 //    Long insert(Banksubledger record);
 
     int insertSelective(Banksubledger record);
-    List<String> selectCode(@Param("code") String code, @Param("companyid") Long companyid);
+    List<String> selectCode(@Param("bl_code") String code, @Param("companyid") Long companyid);
 
     Banksubledger selectByPrimaryKey(Integer bl_id);
 

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

@@ -81,6 +81,7 @@ public class BankinformationServiceImpl extends CommonBaseServiceImpl<Bankinform
             //判断是否能修改期初金额
             Double beginamount = bankinformationMapper.selectamount(bankinformation.getId());
             Double fbeginamount = bankinformation.getBk_beginamount();
+            bankinformation.setBk_thisamount(bankinformation.getBk_beginamount());
             if (!(fbeginamount.equals(beginamount))){
                 DocBaseDTO docBaseDTO = getBaseDTOById(bid);
                 Map<String, Object> map = new HashMap<String, Object>();

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

@@ -556,7 +556,7 @@ public class ProductServiceImpl extends CommonBaseServiceImpl<ProductMapper, Pro
         PageInfo<ProductReserveCostDTO> pageInfo = new PageInfo<ProductReserveCostDTO>(reserveCostList);
         map.put("list", pageInfo);
         //替换listReqDTO中的数据
-        String calculateFields = listReqDTO.getCalculateFields().replaceAll("rc_amount", "pw_amount").replaceAll("pw_onhand", "rc_number");
+        String calculateFields = listReqDTO.getCalculateFields().replaceAll("rc_amount", "po_amount").replaceAll("po_onhand", "rc_number");
         listReqDTO.setCalculateFields(calculateFields);
         //取对应计算数据
         String calculateFieldsSql = listReqDTO.getCalculateFieldsSql();
@@ -565,7 +565,7 @@ public class ProductServiceImpl extends CommonBaseServiceImpl<ProductMapper, Pro
         JSONArray arr = new JSONArray();
         if (!StringUtils.isEmpty(calculateFieldsSql)) {
             String res = getMapper().selectCalculateFields(calculateFieldsSql, condition, companyId);
-            res = res.replaceAll("pw_amount", "rc_amount").replace("pw_onhand", "rc_number");
+            res = res.replaceAll("po_amount", "rc_amount").replace("po_onhand", "rc_number");
             try {
                 arr = JSONArray.parseArray(res);
             } catch (Exception e) {

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

@@ -110,16 +110,15 @@ public class WarehouseServiceImpl extends CommonBaseServiceImpl<WarehouseMapper,
         if(record.getId() == 0){
             String whcode = record.getWh_code().trim().toUpperCase();
             whcode = RegexpUtils.replaceSpecCharacter(whcode);
+            //验证名称是否重复
+            validName(record.getWh_description(), record.getId());
+            //验证编号是否重复
+            validCode(whcode, record.getId());
             String code = pushMaxnubmer(whcode, record.getId());
             record.setCompanyId(BaseContextHolder.getCompanyId());
             record.setCreatorId(BaseContextHolder.getUserId());
             record.setCreateTime(new Date());
             record.setCreatorName(BaseContextHolder.getUserName());
-            //验证名称是否重复
-            validName(record.getWh_description(), record.getId());
-            //验证编号是否重复
-            validCode(code, record.getId());
-
             count = getMapper().insertSelective(record);
             //记录LOG
             docBaseDTO = generateMsgObj(record.getId(), code);

+ 1 - 1
applications/document/document-server/src/main/resources/mapper/BanksubledgerMapper.xml

@@ -345,7 +345,7 @@
       updatedate = #{updatedate,jdbcType=TIMESTAMP}
     where bl_id = #{bl_id,jdbcType=INTEGER}
   </update>
-    <select id="selectCode" parameterType="java.lang.String" resultType="java.lang.String">
+    <select id="selectCode" resultType="java.lang.String">
         select bl_code
         from banksubledger
         where bl_code = #{bl_code,jdbcType=VARCHAR} and companyId = #{companyid}

+ 1 - 1
applications/document/document-server/src/main/resources/mapper/CustomerkindMapper.xml

@@ -108,7 +108,7 @@
     SELECT * FROM CUSTOMERKIND WHERE COMPANYID=#{companyId} order by ck_id desc
   </select>
   <select id="getCombo" resultType="com.usoftchina.saas.commons.dto.ComboDTO">
-    SELECT ck_name display,ck_name value FROM CUSTOMERKIND WHERE COMPANYID=#{companyId}
+    SELECT ck_name display,ck_name value FROM CUSTOMERKIND WHERE COMPANYID=#{companyId} order by ck_id desc
   </select>
     <select id="selectCountByName" resultType="int">
         SELECT count(*) FROM CUSTOMERKIND

+ 1 - 1
applications/document/document-server/src/main/resources/mapper/ProductDetailMapper.xml

@@ -337,6 +337,6 @@
         DELETE FROM PRODUCTDETAIL WHERE PD_PRODID=#{id}
     </delete>
     <update id="updatePd_price" parameterType="long">
-        update productdetail set pd_amount=round(pd_num*pd_price,2) where pd_piid=#{id};
+        update productdetail set pd_amount=round(pd_num*pd_price,2) where pd_prodid=#{id};
     </update>
 </mapper>

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

@@ -494,14 +494,14 @@
     </select>
     <select id="selectCalculateFields" resultType="string">
         select   ${fields}
-        from productWH tab left join Product on pw_prodid=pr_id left join warehouse on pw_whid=wh_id
+        from productonhand tab left join Product on pr_id = po_prodid and productonhand.companyId = product.companyId
         <where>
             <if test="con != null">
                 ${con}
             </if>
             <if test="companyId!=null">
-                and tab.companyId=#{companyId} and Product.companyId=#{companyId} and warehouse.companyId=#{companyId}
-                and pw_onhand!=0
+                and productonhand.companyId=#{companyId}
+                and po_onhand != 0
             </if>
         </where>
     </select>

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

@@ -22,7 +22,7 @@ public interface BanksubledgerMapper extends CommonBaseMapper<Banksubledger> {
 //    Long insert(Banksubledger record);
 
     int insertSelective(Banksubledger record);
-    List<String> selectCode(@Param("code") String code, @Param("companyid") Long companyid);
+    List<String> selectCode(@Param("bl_code") String code, @Param("companyid") Long companyid);
 
     List<Banksubledger> selectByExample(BanksubledgerExample example);
 

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

@@ -148,7 +148,7 @@ public class PaybalanceServiceImpl extends CommonBaseServiceImpl<PaybalanceMappe
                 namount = subledger.getSl_namount();
             }
             //本次核销金额不能大于未核销金额
-            if(nowbalance>namount){
+            if(Math.abs(nowbalance) > Math.abs(namount)){
                 throw new BizException(BizExceptionCode.PAYBALANCE_OUTNOWBALANCE);
             }
             //单据金额

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

@@ -148,7 +148,7 @@ public class RecbalanceServiceImpl extends CommonBaseServiceImpl<RecbalanceMappe
                 namount = subledger.getSl_namount()==null?new Double(0):subledger.getSl_namount();
             }
             //本次核销金额不能大于未核销金额
-            if(nowbalance>namount){
+            if(Math.abs(nowbalance) > Math.abs(namount)){
                 throw new BizException(500, BizExceptionCode.RECALANCE_OUTNOWBALANCE.getMessage());
             }
             //单据金额

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

@@ -431,7 +431,7 @@
       updatedate = #{updatedate,jdbcType=TIMESTAMP}
     where bl_id = #{bl_id,jdbcType=INTEGER}
   </update>
-    <select id="selectCode" parameterType="java.lang.String" resultType="java.lang.String">
+    <select id="selectCode" resultType="java.lang.String">
         select bl_code
         from banksubledger
         where bl_code = #{bl_code,jdbcType=VARCHAR} and companyId = #{companyid}

+ 19 - 0
applications/sale/sale-server/src/main/java/com/usoftchina/saas/sale/service/impl/ProdInOutServiceImpl.java

@@ -527,6 +527,13 @@ public class ProdInOutServiceImpl extends CommonBaseServiceImpl<ProdInOutMapper,
                 targetPid.setPd_inqty(pdOutqty-pdYqty);
                 targetPid.setPd_total((pdOutqty-pdYqty)*pdSendPrice);
                 targetPid.setPd_nettotal((pdOutqty-pdYqty)*(pdSendPrice/(1+pdTaxrate/100)));
+                //获取物料默认仓库
+                Map<String, Object> warehouse = getWareHouseByCode(sourcePid.getPd_prodcode());
+                if (null != warehouse) {
+                    targetPid.setPd_whid(warehouse.get("pr_whid") == null ? 0 : Long.valueOf(warehouse.get("pr_whid").toString()));
+                    targetPid.setPd_whcode(warehouse.get("pr_whcode") == null ? null : warehouse.get("pr_whcode").toString());
+                    targetPid.setPd_whname(warehouse.get("pr_whname") == null ? null : warehouse.get("pr_whname").toString());
+                }
                 prodIODetailMapper.insertSelective(targetPid);
                 //更新已转数
                 sourcePid.setPd_yqty(pdOutqty);
@@ -548,6 +555,18 @@ public class ProdInOutServiceImpl extends CommonBaseServiceImpl<ProdInOutMapper,
 
     }
 
+    private Map<String, Object> getWareHouseByCode(String code) {
+        if (StringUtils.isEmpty(code)) {
+            return null;
+        }
+        Long companyId = BaseContextHolder.getCompanyId();
+        List<HashMap<String, Object>> list = prodInOutMapper.getWareHouseByCode(code, companyId);
+        if (null != list && list.size() > 0) {
+            return list.get(0);
+        }
+        return null;
+    }
+
     @Override
     @Transactional
     public DocBaseDTO close(Long id) {

+ 18 - 0
base-servers/account/account-api/src/main/java/com/usoftchina/saas/account/api/AccountApi.java

@@ -78,4 +78,22 @@ public interface AccountApi {
      */
     @PostMapping("/account/update")
     Result update(@RequestBody AccountUpdateDTO accountUpdateDTO);
+
+    /**
+     * 个人账户绑定公司
+     * @param accountId
+     * @param companyId
+     * @return
+     */
+    @PostMapping("/bind/company")
+    Result bindCompany(@RequestParam("accountId") long accountId, @RequestParam("companyId") long companyId);
+
+    /**
+     * 个人账户绑定多个角色
+     * @param accountId
+     * @param roleIds
+     * @return
+     */
+    @PostMapping("/bind/roles")
+    Result bindRoles(@RequestParam("accountId") Long accountId, @RequestParam("roleIds") String roleIds);
 }

+ 9 - 0
base-servers/account/account-dto/src/main/java/com/usoftchina/saas/account/dto/BindCompanyDTO.java

@@ -6,6 +6,15 @@ public class BindCompanyDTO implements Serializable {
 
     private Long companyId;
     private Long accountId;
+    private String username;
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
 
     public Long getCompanyId() {
         return companyId;

+ 8 - 0
base-servers/account/account-server/pom.xml

@@ -52,6 +52,14 @@
             <artifactId>sms-api</artifactId>
             <version>1.0.0-SNAPSHOT</version>
         </dependency>
+        <dependency>
+            <groupId>com.usoftchina.saas</groupId>
+            <artifactId>commons-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.usoftchina.saas</groupId>
+            <artifactId>commons-dto</artifactId>
+        </dependency>
         <!-- db -->
         <dependency>
             <groupId>mysql</groupId>

+ 45 - 1
base-servers/account/account-server/src/main/java/com/usoftchina/saas/account/controller/AccountCenterController.java

@@ -1,9 +1,16 @@
 package com.usoftchina.saas.account.controller;
 
+import com.usoftchina.saas.account.api.AccountApi;
+import com.usoftchina.saas.account.api.CompanyApi;
+import com.usoftchina.saas.account.dto.AccountDTO;
 import com.usoftchina.saas.account.dto.BindCompanyDTO;
 import com.usoftchina.saas.account.dto.CompanyAccountDTO;
+import com.usoftchina.saas.account.dto.CompanyDTO;
 import com.usoftchina.saas.account.service.AccountCenterService;
 import com.usoftchina.saas.base.Result;
+import com.usoftchina.saas.commons.api.SystemRemindApi;
+import com.usoftchina.saas.commons.dto.AddApplyDTO;
+import com.usoftchina.saas.utils.ObjectUtils;
 import com.usoftchina.sso.api.SsoUserSpaceApi;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
@@ -16,6 +23,12 @@ public class AccountCenterController {
     private AccountCenterService accountCenterService;
     @Autowired
     private SsoUserSpaceApi ssoUserSpaceApi;
+    @Autowired
+    private CompanyApi companyApi;
+    @Autowired
+    private AccountApi accountApi;
+    @Autowired
+    private SystemRemindApi systemRemindApi;
 
     /**
      * 信息完善界面   保存接口
@@ -71,7 +84,7 @@ public class AccountCenterController {
     }
 
     /**
-     * 校验企业名称时候已在账户中心注册过
+     * 校验企业名称是否已在账户中心注册过
      * @param spaceName
      * @return
      */
@@ -80,4 +93,35 @@ public class AccountCenterController {
         return Result.success(ssoUserSpaceApi.checkSpaceName(spaceName));
     }
 
+    /**
+     * 校验企业是否已开通saas
+     * @param companyName
+     * @return
+     */
+    @GetMapping("/company/isOpen")
+    public Result checkIsOpen(@RequestParam("companyName") String companyName){
+        CompanyDTO companyDTO = companyApi.getCompanyByName(companyName).getData();
+        if (ObjectUtils.isEmpty(companyDTO)){
+            return Result.error();
+        }
+        return Result.success(companyDTO.getId());
+    }
+
+    /**
+     * 加入企业,在系统的提醒中生成一条记录待管理员确认
+     * @param bindCompanyDTO
+     * @return
+     */
+    @PostMapping("/company/join")
+    public Result joinCompany(@RequestBody BindCompanyDTO bindCompanyDTO){
+        AddApplyDTO addApplyDTO = new AddApplyDTO();
+        AccountDTO accountDTO = accountApi.getAccountById(bindCompanyDTO.getAccountId()).getData();
+        addApplyDTO.setMobile(accountDTO.getMobile());
+        addApplyDTO.setCompanyId(bindCompanyDTO.getCompanyId());
+        addApplyDTO.setUsername(bindCompanyDTO.getUsername());
+        addApplyDTO.setStatus("0");
+        systemRemindApi.save(addApplyDTO);
+        return Result.success();
+    }
+
 }

+ 1 - 1
base-servers/account/account-server/src/main/java/com/usoftchina/saas/account/controller/AccountController.java

@@ -427,7 +427,7 @@ public class AccountController {
     }
 
     /**
-     * 个人账户绑定角色
+     * 个人账户绑定多个角色
      * @param accountId
      * @param roleIds
      * @return

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

@@ -86,4 +86,4 @@ sso:
   base-url: https://test-sso.uuzcc.cn
 ribbon:
   ReadTimeout: 6000
-  ConnectTimeout: 2000
+  ConnectTimeout: 6000

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

@@ -14,7 +14,7 @@
         delete from ac_account_company where company_id=#{companyId}
     </delete>
     <select id="getCompanyListByAccountMobile" resultType="com.usoftchina.saas.account.dto.CompanyRspDTO">
-        SELECT cmp.id,cmp.name,cmp.uu,cmp.business_code businessCode,cmp.address,accmp.is_default default_,'1' saas_,aci.realname admin,cmp.creator_id adminId,cmp.type,ac.email adminEmail,ac.mobile adminMobile from ac_company cmp
+        SELECT cmp.id,cmp.name,cmp.uu,cmp.business_code businessCode,cmp.address,accmp.is_default default_,'1' saas_,aci.realname admin,cmp.creator_id adminId,cmp.type,aci.email adminEmail,aci.mobile adminMobile from ac_company cmp
         left join ac_account_company accmp on accmp.company_id=cmp.id
         left join ac_account ac on ac.id = accmp.account_id
         left join ac_account aci on aci.id = cmp.creator_id

+ 165 - 84
frontend/saas-portal-web/src/components/conenter/addenterprise.vue

@@ -4,21 +4,18 @@
             <div class="tc-conent"><img src="/static/img/qiye/dengji@1x.png" alt=""></div>
             <div class="tc-text"><span>添加企业成功</span></div>
         </div>
-        <span class="tjtishi" ref="tjtishi"></span>
         <div>
             <div class="gs-worp qy-worp tj-up">
                 <div class="qy-title" style="position: relative;">
-                    <span>完善企业信息</span>
-                    <div class="qy-anniu" style="position: absolute;top: 0;right: 20px;margin-top: 0;">
-                        <span @click= "Preservation" class="qy-xiugai dianji" style="left: -2px">保存</span>
-                        <span @click= "tjquxiao" class="qy-quxiao xs">取消</span>
-                    </div>
+                    <ul class="over">
+                        <li style="width:100%" class="left xs" v-for="(d, i) in tab" :key="i" :class= "{qyactive:nowindex == i}" @click="tabwith(i)">{{d.name}}</li>
+                    </ul>
                 </div>
-                <div class="qy-conent">
+                <div class="qy-conent" :class= "{showqiye:nowindex == 0}" style="padding-top: 60px;">
                     <ul>
                         <li style="margin: 0">
-                            <span class="qy-biaoti"><span class="xingxing">*</span>公司名称</span>
-                            <input class="inpind" ref="qyname" @change= "spaceName" type="text" placeholder="请填写公司全称">
+                            <span class="qy-biaoti"><span class="xingxing">*</span>企业名称</span>
+                            <input class="inpind" ref="qyname" @change= "spaceName" type="text" placeholder="请填写企业全称">
                             <dir class="qy-Tips"><span ref="qyno" style="color:red"></span></dir>
                         </li>
                         <li>
@@ -44,28 +41,17 @@
                                 <option value="其他">其他</option>   
                             </select>
                         </li>
-                        <li style="height:70px;">
-                            <span class="qy-biaoti left"><span class="xingxing">*</span>公司地址</span>
-                            <div class="addbiaoqian">
-                                <!-- <v-distpicker @province= 'qyprovince' @city= 'qycity' @area= 'qyarea'></v-distpicker> -->
-                                <!-- <v-distpicker @selected= 'selected' province="广东省" city="广州市" area="荔湾区" :placeholders= 'placeholder'></v-distpicker> -->
+                        <li>
+                            <span class="qy-biaoti"><span class="xingxing">*</span>企业地址</span>
+                            <input ref="address" @change="address" class="inpind" type="text" placeholder="输入企业详细地址">
+                            <!-- <div class="addbiaoqian">
                                 <v-distpicker @selected= 'selected' @province= 'qyprovince' :placeholders= 'placeholder'></v-distpicker>
-                                <input ref="address" @change="address" :disabled="disabled" class="qy-xiangxi" type="text" placeholder="输入企业详细地址">
-                                
-                            </div>
+                                <input ref="address" @change="address" class="qy-xiangxi" type="text" placeholder="输入企业详细地址">
+                            </div> -->
                             <div class="qy-Tips left">
                                 <span ref="ress" style="color:red;margin-left:40px;"></span>
                             </div>
                         </li>
-                    </ul>
-                </div>
-            </div>
-            <div class="gs-worp qy-worp tj-down">
-                <div class="qy-title">
-                    <span>完善个人信息</span>
-                </div>
-                <div class="qy-conent">
-                    <ul>
                         <li style="margin:0">
                             <span class="qy-biaoti"><span class="xingxing">*</span>姓名</span>
                             <input class="inpind" @change= "yzusername" ref="name" type="text" value="">
@@ -77,6 +63,43 @@
                             <input class="inpind" @change="email" ref="email" type="email" value="">
                             <div class="qy-Tips Tips-buttom"><span style="color:red">{{Email}}</span></div>
                         </li>
+                        <li>
+                            <div class="qy-anniu">
+                                <span @click= "Preservation" class="qy-xiugai dianji" style="left: -2px">保存</span>
+                                <span @click= "tjquxiao" class="qy-quxiao xs">取消</span>
+                            </div>
+                        </li>
+                    </ul>
+                </div>
+                <div class="qy-conent jr-conent" :class= "{showqiye:nowindex == 1}">
+                    <ul style="padding:0">
+                        <li>
+                            <span class="qy-biaoti"><span class="xingxing marght">*</span>查找企业</span>
+                            <input @blur.prevent="Testingqyname" ref="lookupqyname" class="inpind" type="text" value="" placeholder="输入企业名称或管理员">
+                            <span class="warning" ref="warningqyname"></span>
+                        </li>
+                        <li class="hied" :class= "{showlookup:islookup}">
+                            <div class="lookup">
+                                <ul>
+                                    <li v-for="(d, i) in arr" :key="i">
+                                        <span>企业名称:</span><span>{{d.qyname}}</span>
+                                        <span class="saasguanli">SaaS管理员:</span><span>{{d.saas}}</span>
+                                        <span>联系方式:</span><span>{{d.phone}}</span>
+                                    </li>
+                                </ul>
+                            </div>
+                        </li>
+                        <li>
+                            <span class="qy-biaoti"><span class="xingxing marght">*</span>姓<span style="width:2em;display: inline-block;"></span>名</span>
+                            <input @blur.prevent="Testingname" class="inpind" type="text" ref="lookupname" placeholder="输入真实姓名,待管理员审核">
+                            <span class="warning" ref="warningname"></span>
+                        </li>
+                        <li>
+                            <div class="qy-anniu" style="margin-top: 70px;">
+                                <span @click="Submission" class="qy-xiugai dianji" style="left: -2px">提交</span>
+                                <span @click= "tjquxiao" class="qy-quxiao xs">取消</span>
+                            </div>
+                        </li>
                     </ul>
                 </div>
             </div>
@@ -91,25 +114,35 @@ import { setTimeout } from 'timers';
     export default {
         data(){
             return {
-                province:'',//省
-                city:'',//市
-                area:'',//区
+                // province:'',//省
+                // city:'',//市
+                // area:'',//区
                 qymingzi: false,//企业名是否注册
                 Email: '',
                 mytoken: JSON.parse(localStorage.getItem('app-state-session')),//本地储存的用户信息
                 reg: new RegExp(/[\@\#\$\%\&\*!\¥]/),//非法字符
+                regname:new RegExp(/[\@\#\$\%\&\*!\¥0-9]/),//非法字符加数字
                 isaddress: false,//公司地址验证
                 isaddressname: false,//公司地址是否为空
                 isname: true,//姓名验证
                 isspaceName: false,//公司名验证
                 isemail: true,//验证邮箱
-                disabled: true,
+                // disabled: true,
                 isadd: false,//添加成功弹窗
-                placeholder:{province:"省", city:"市", area:"区"},
-                placeholde:{province:"", city:"", area:""},
+                // placeholder:{province:"省", city:"市", area:"区"},
+                // placeholde:{province:"", city:"", area:""},
                 tab:[
                     {name:'创建新企业'},
-                    {name:'加入企业'},
+                    // {name:'加入企业'},
+                ],
+                nowindex:0,
+                islookup:false,
+                isTestingname:false,
+                isregname:false,
+                arr:[
+                    {qyname:'XX房贷首付范德萨发达企业',saas:'反倒是地方反对法管理员',phone:'13456789023'},
+                    {qyname:'XX企业',saas:'管理员',phone:'13456789023'},
+                    {qyname:'XX企业',saas:'管理员',phone:'13456789023'},
                 ]
             }
         },
@@ -121,19 +154,22 @@ import { setTimeout } from 'timers';
             this.$refs.email.value = this.mytoken.account.email
         },
         methods: {
+            tabwith(i){
+                this.nowindex = i;
+            },
             //取消添加企业
             tjquxiao(){
                 document.documentElement.scrollTop = 0;
                 this.$router.push({name:'company',}); 
             },
-            //检测企业名称
+            //检测企业名称1
             spaceName(){
                 let qyname = this.$refs.qyname.value.replace(/\s+/g, "");//公司名字过滤空格
                 if(qyname == ''){
-                    this.$refs.qyno.innerHTML = '企业名不能为空';
+                    this.$refs.qyno.innerHTML = '企业名不能为空';
                 } else {
                     if (this.reg.test(qyname)) {
-                        this.$refs.qyno.innerHTML = '不能包含非法字符';
+                        this.$refs.qyno.innerHTML = '不能包含符号等非法字符';
                         this.isspaceName = false;
                     } else {
                         this.$refs.qyno.innerHTML = '';
@@ -149,6 +185,7 @@ import { setTimeout } from 'timers';
                         .then(res=>{
                             if (res.data.data.success) {
                                 this.qymingzi = true;
+                                this.$refs.qyno.innerHTML = '<span style="color:green">该企业可创建</span>';
                             } else {
                                 this.$refs.qyno.innerHTML = '该企业已在优软云注册';
                                 this.qymingzi = false
@@ -160,14 +197,25 @@ import { setTimeout } from 'timers';
                     }
                 }
             },
-            //验证个人姓名
+            //检测企业名称2
+            Testingqyname(){
+                let qyname = this.$refs.lookupqyname.value.replace(/\s+/g, "");//企业名字
+                if (qyname == '') {
+                    this.$refs.warningqyname.innerHTML = '<img style="width:14px" src="/static/img/warning.png" alt=""> 企业或管理员不能为空';
+                    this.islookup = false
+                } else {
+                    this.$refs.warningqyname.innerHTML = '<img style="width:14px" src="/static/img/ok.png" alt="">';
+                    this.islookup = true
+                }
+            },
+            //验证个人姓名1
             yzusername(){
                 let name = this.$refs.name.value.replace(/\s+/g, "");//姓名过滤空格
                 if (name == '') {
                     this.$refs.usname.innerHTML = '个人姓名不能为空'
                 } else {
                     if (this.reg.test(name)) {
-                        this.$refs.usname.innerHTML = '不能包含非法字符'
+                        this.$refs.usname.innerHTML = '不能包含符号等非法字符'
                         this.isname = false
                     } else {
                         this.$refs.usname.innerHTML = ''
@@ -175,6 +223,38 @@ import { setTimeout } from 'timers';
                     }
                 }
             },
+            //验证个人姓名2
+            Testingname(){
+                let name = this.$refs.lookupname.value.replace(/\s+/g, "");//姓名过滤空格
+                if (name == '') {
+                    this.$refs.warningname.innerHTML = '<img style="width:14px" src="/static/img/warning.png" alt=""> 姓名不能为空';
+                    this.isTestingname = false;
+                } else {
+                    this.isTestingname = true;
+                    if (this.regname.test(name)) {
+                        this.$refs.warningname.innerHTML = '<img style="width:14px" src="/static/img/warning.png" alt=""> 姓名不能包含符号、数字等非法字符';
+                        this.isregname = false;
+                    } else {
+                        this.$refs.warningname.innerHTML = '<img style="width:14px" src="/static/img/ok.png" alt="">';
+                        this.isregname = true;
+                    }
+                }
+            },
+            //加入企业提交按钮
+            Submission(){
+                if (!this.islookup) {
+                    this.$message.error('企业或管理员不能为空');
+                } else if (!this.isTestingname) {
+                    this.$message.error('姓名不能为空');
+                } else if (!this.isregname) {
+                    this.$message.error('姓名不能包含符号、数字等非法字符');
+                } else {
+                    this.$message({
+                        message: '提交成功,待管理员批准加入',
+                        type: 'success'
+                    });
+                }
+            },
             //验证公司详细地址
             address(){
                 let address = this.$refs.address.value.replace(/\s+/g, "");//过滤空格
@@ -184,7 +264,7 @@ import { setTimeout } from 'timers';
                 } else {
                     this.isaddressname = true
                     if (this.reg.test(address)) {
-                        this.$refs.ress.innerHTML = '不能包含非法字符'
+                        this.$refs.ress.innerHTML = '不能包含符号等非法字符'
                         this.isaddress = false
                     } else {
                         this.$refs.ress.innerHTML = ''
@@ -213,7 +293,7 @@ import { setTimeout } from 'timers';
                 this.listLoading = true
                 let qyname = this.$refs.qyname.value.replace(/\s+/g, "");//公司名字
                 let qyindustry = this.$refs.qyindustry.value;//所属行业
-                let address = this.province+this.city+this.area+this.$refs.address.value.replace(/\s+/g, "");//公司详细地址
+                let address = this.$refs.address.value.replace(/\s+/g, "");//公司详细地址
                 let name = this.$refs.name.value.replace(/\s+/g, "");//个人姓名
                 let email = this.$refs.email.value;//邮箱
                 let mytoken = JSON.parse(localStorage.getItem('app-state-session'));
@@ -230,11 +310,9 @@ import { setTimeout } from 'timers';
                 // console.log('企业名字',this.isspaceName)//企业名字正则
                 // console.log('邮箱',this.isemail)//邮箱正则
                 if (name == '') {
-                    this.$refs.tjtishi.innerHTML = '个人姓名不能为空';
-                    this.remotxt()
+                    this.$message.error('个人姓名不能为空');
                 } else if (qyname == '') {
-                    this.$refs.tjtishi.innerHTML = '企业名字不能为空';
-                    this.remotxt()
+                    this.$message.error('企业名称不能为空');
                 } else {
                     switch (this.qymingzi && this.isaddress && this.isname && this.isspaceName && this.isemail && this.isaddressname) {
                         case this.qymingzi:
@@ -252,62 +330,47 @@ import { setTimeout } from 'timers';
                                 }
                             })
                             .then(res=>{
-                                let id = res.data.data;
-                                let logoUrl = null;
-                                let addenterprise = {'id':id, 'logoUrl': logoUrl, 'name': qyname};
-                                let session = JSON.parse(window.localStorage.getItem('app-state-session'));
-                                session.account.companies.push(addenterprise);
-                                session.account.realname = name;
-                                Session.set(session);
-                                this.isadd = true;
+                                this.isadd = true;//添加成功弹窗
                                 setTimeout(()=>{
                                     document.documentElement.scrollTop = 0;
                                     // this.$router.push({name:'company'})
                                     this.$router.push({path: '/enterprise'})
-                                },1000)
+                                },3000)
                             })
-                            this.$refs.tjtishi.innerHTML = '';
+                            this.$message({
+                                message: '保存成功,待管理员批准',
+                                type: 'success'
+                            });
                         } else {
-                            this.$refs.tjtishi.innerHTML = '该企业已在优软云注册';
-                            this.remotxt()
+                            this.$message.error('该企业已在优软云注册');
                         }
                         break;
                         case this.isaddressname:
-                        this.$refs.tjtishi.innerHTML = '企业地址不能为空';
-                        this.remotxt()
+                        this.$message.error('企业地址不能为空');
                         break;
                         case this.isaddress:
-                        this.$refs.tjtishi.innerHTML = '企业地址不能包含非法字符';
-                        this.remotxt()
+                        this.$message.error('企业地址不能包含符号等非法字符');
                         break;
                         case this.isname:
-                        this.$refs.tjtishi.innerHTML = '个人姓名不能包含非法字符';
-                        this.remotxt()
+                        this.$message.error('个人姓名不能包含符号等非法字符');
                         break;
                         case this.isspaceName:
-                        this.$refs.tjtishi.innerHTML = '企业名字不能包含非法字符';
-                        this.remotxt()
+                        this.$message.error('企业名称不能包含符号等非法字符');
                         break;
                         case this.isemail:
-                        this.$refs.tjtishi.innerHTML = '请填写正确的邮箱';
-                        this.remotxt()
+                        this.$message.error('请填写正确的邮箱');
                         break;
                     }
                 }
                 this.listLoading = false
             },
-            remotxt(){
-                setTimeout(()=>{
-                    this.$refs.tjtishi.innerHTML = ' ';
-                },3000)
-            },
             //获取省市区
-            selected(data){
-                this.province = data.province.value;
-                this.city = data.city.value;
-                this.area = data.area.value;
-                this.disabled= false
-            },
+            // selected(data){
+            //     this.province = data.province.value;
+            //     this.city = data.city.value;
+            //     this.area = data.area.value;
+            //     this.disabled= false
+            // },
             qyprovince(){
                 this.placeholder = this.placeholde
             },
@@ -316,12 +379,6 @@ import { setTimeout } from 'timers';
 </script>
 
 <style scoped>
-.tjtishi {
-    color: red;
-    display: block;
-    text-align: center;
-    height: 20px;
-}
 .addspace {
     height: 200px;
     border: 1px solid #cccccc
@@ -329,7 +386,6 @@ import { setTimeout } from 'timers';
 .tj-up {
     width: 100%;
     margin-bottom: 0px;
-    border-bottom: 0;
     padding-bottom: 1px;
     border-radius: 4px 4px 0 0;
     /* margin-top: -30px; */
@@ -367,4 +423,29 @@ import { setTimeout } from 'timers';
 .inpind {
     padding-left: 10px;
 }
+.qyactive {
+    border-bottom: 3px solid  #1E88F5;
+}
+.qy-conent {
+    display: none;
+}
+.showqiye {
+    display: block !important;
+}
+.warning {
+    color: red;
+    margin-left: 25px;
+    font-size: 12px;
+    position: absolute;
+    display: inline-block;
+    width: 150px;
+    text-align: left;
+    text-indent: -16px;
+}
+.warning img {
+    width: 14px;
+}
+.marght {
+    margin-right: 5px;
+}
 </style>

+ 37 - 84
frontend/saas-portal-web/src/components/conenter/company.vue

@@ -65,38 +65,33 @@
                     </div>
                 </router-link>
             </div>
-            <!-- 点击查看企业详情 -->
             <div v-for="(d , i) in arr " :key="i" class="gs-xiangqing">
                 <!-- 上 -->
                 <div class="gs-shang">
-                    <div class="gs-morentop" :class= "{gsqiye:nowindex == (i+1)}">
-                        <span v-if = "d.default_" @click="hideDefaultWin(i)" class="gs-btn2 xs">取消默认</span>
-                        <span v-else @click="showDefaultWin(i)" class="gs-btn2 xs">设为默认</span>
-                    </div>
-                    <img @click.stop @mouseenter="setismoren" @click="setmoren(i)" class="shezhi xs" src="/static/img/shezhi.png" alt="设置">
+                    <el-dropdown v-if= "d.saas_" trigger="hover" size="mini" placement='bottom-start'>
+                        <img  class="shezhi xs" src="/static/img/shezhi.png" alt="设置">
+                        <el-dropdown-menu slot="dropdown">
+                            <el-dropdown-item v-if = "d.default_">
+                                <span @click="hideDefaultWin(i)">取消默认</span>
+                            </el-dropdown-item>
+                            <el-dropdown-item v-else>
+                                <span @click="showDefaultWin(i)">设为默认</span>
+                            </el-dropdown-item>
+                        </el-dropdown-menu>
+                    </el-dropdown>
                     <img v-if = "d.default_" class="gs-morenimg" src="/static/img/moren2x.png" alt="">
                 </div>
                 <!-- 中 -->
                 <div class="gs-xqleft">
+                    <!-- 点击查看企业详情 -->
                     <p class="gs-qynema xs" @click= "getEnterpriseInfo(d)">{{d.name}}</p>
-                    <!-- <img @mouseenter="setismoren" @click="setmoren(i)" class="shezhi xs" src="/static/img/shezhi.png" alt="设置"> -->
-                    <!-- <div class="gs-morentop" :class= "{gsqiye:nowindex == (i+1)}">
-                        <span v-if = "d.default_" @click="hideDefaultWin(i)" class="gs-btn2 xs">取消默认</span>
-                        <span v-else @click="showDefaultWin(i)" class="gs-btn2 xs">设为默认</span>
-                    </div> -->
                 </div>
                 <!-- 下 -->
                 <div class="gs-xqright over">
-                    <div v-if= "d.saas_" class="gs-xqright-left left" style="margin-top: 5%;" @click.stop >
-                        <!-- <p class="saasfuwu"><span>SaaS服务</span></p> -->
-                        <!-- <p v-if= "d.saas_"  class="saasgengduo xs">
-                            <span @mouseenter="setissaasxiangxi" @click="gengduo(i)">更多 ></span>
-                        </p> -->
-                        <!-- <div class="saasxiangxi" :class= "{gssaasxiangxi:nowindex2 == (i+1)}"> -->
-                            <p><span>saas管理员:</span>{{d.admin}}</p>
-                            <p><span>联系方式:</span>{{d.adminMobile}}</p>
-                            <!-- <p><span>开通日期:</span></p> -->
-                        <!-- </div> -->
+                    <div v-if= "d.saas_" class="gs-xqright-left left" style="margin-top: 5%;">
+                        <p><span>saas管理员:</span>{{d.admin}}</p>
+                        <p><span>联系方式:</span>{{d.adminMobile}}</p>
+                        <!-- <p><span>开通日期:</span></p> -->
                     </div>
                     <div class="gs-border gs-xqright-right right">
                         <span v-if= "d.saas_" class="gs-btn1 xs" @click="selectServe(d.id)">进入服务</span>
@@ -128,20 +123,12 @@
                 isheigh:false,//是否添加默认高度
                 admin: '',
                 adminMobile: '',
-                ismoren:true,
-                issaasxiangxi:true,
             }
         },
         computed :{
             setTokenPage() {
                 return this.$url.web + '/set-token.html'
             },
-            nowindex() {
-                return this.$store.state.ismoren
-            },
-            nowindex2() {
-                return this.$store.state.issaasxiangxi
-            },
         },
         watch:{
             arr:function(){
@@ -168,6 +155,23 @@
                 .then(res=>{
                     const frame = window.frames[window.frames.length - 1];
                     this.arr = res.data.data.spaces;
+                    let enterprise = [];
+                    for (let i = 0; i < this.arr.length; i++) {
+                        if (this.arr[i].saas_) {
+                            let addenterprise = {'id':'', 'logoUrl': '', 'name': '','dcName':''};
+                            addenterprise.id = this.arr[i].id;
+                            addenterprise.logoUrl = this.arr[i].logoUrl || null;
+                            addenterprise.name = this.arr[i].name;
+                            addenterprise.dcName = this.arr[i].dcName || null;
+                            enterprise.push(addenterprise)
+                        }
+                    };
+                    let session = JSON.parse(window.localStorage.getItem('app-state-session'));
+                    if (enterprise.length != session.account.companies.length) {
+                        session.account.companies = enterprise;
+                        session.account.realname = this.arr[0].admin;
+                        Session.set(session);
+                    };
                     let hasCompany = res.data.data.hasDefaultCompany;
                     let companyId = res.data.data.defaultCompanyId;
                     let token = res.data.data.token.token;
@@ -232,8 +236,9 @@
                     }
                 })
                 .then(res=>{
-                    // console.log('请求成功',res);
-                    this.$router.go(0);
+                    if (res.data.success) {
+                        this.$router.go(0);
+                    }
                 })
                 .catch(err=>{
                     // console.log('请求失败',err);
@@ -352,30 +357,6 @@
                 this.isNoopen = false;
                 this.isokopensaas = false
             },
-            // 弹出设置
-            setmoren(i){
-                if (this.ismoren) {
-                    this.$store.state.ismoren = i+1
-                } else {
-                    this.$store.state.ismoren = ''
-                }
-                this.ismoren = !this.ismoren
-            },
-            // 弹出更多
-            gengduo(i){
-                if (this.issaasxiangxi) {
-                    this.$store.state.issaasxiangxi = i+1
-                } else {
-                    this.$store.state.issaasxiangxi = ''
-                }
-                this.issaasxiangxi = !this.issaasxiangxi
-            },
-            setismoren(){
-                this.ismoren = true
-            },
-            setissaasxiangxi(){
-                this.issaasxiangxi = true
-            },
             //没有内容也要有一定的高度
             boxheight(){
                 let H = this.$refs.qiyebox.offsetHeight;
@@ -400,38 +381,10 @@
     -khtml-user-select: none;
     user-select: none;
 }
-.shezhi {
-    /* margin-left: 92%;
-    margin-top: 23%; */
-}
 .gs-morentop {
     position: absolute;
-    margin-top: 20px;
-    /* right: 11px; */
+    margin-top: 0px;
     left: 5px;
     display: none;
 }
-.saasfuwu {
-    font-size: 16px;
-    color: #677897;
-}
-.saasgengduo {
-    font-family: PingFangSC-Regular;
-    font-size: 12px;
-    color: #1E88F5;
-    letter-spacing: 0;
-}
-.saasxiangxi {
-    display: none;
-    position: absolute;
-    background: #F8FBFF;
-    border: 1px solid #1E88F5;
-    border-radius: 4px;
-    padding: 10px;
-    font-size: 14px;
-    color: #1E88F5 !important;
-}
-.gssaasxiangxi {
-    display: block;
-}
 </style>

+ 138 - 8
frontend/saas-portal-web/src/components/conenter/enterprise.vue

@@ -1,5 +1,5 @@
 <template>
-    <div class="div" @click="onshezhi">
+    <div class="div">
         <div id="navigation" class="navbar-inverse navbar-fixed-top animated-header">
         <div class="container">
             <div class="navbar-header">
@@ -37,6 +37,7 @@
             <div class="gs-tab">
                 <ul>
                     <li class="xs" v-for="(btn , index) in tab" :key='index' :class= "{gsactive:nowindex == index}" @click= "tabswitch(index)">{{btn.name}}</li>
+                    <!-- <span class="reddian"></span> -->
                 </ul>
             </div>
             <div class="gs-none">
@@ -120,7 +121,28 @@
                 </div>
     <!-- 消息 ------------------------------------------------------------------>
                 <div :class="{gsqiye:nowindex == 3}">
-                    我是消息页面
+                    <div class="gs-news" ref="qiyebox" :class="isheigh ? 'heigh' : ''">
+                        <ul>
+                            <li>
+                                <span>消息类型</span>
+                                <span>时间</span>
+                                <span class="newscentent">消息内容</span>
+                                <span>状态</span>
+                                <span>操作</span>
+                            </li>
+                            <li class="newslist" v-for="(d, i) in arr" :key="i">
+                                <span>{{d.leixing}}</span>
+                                <span>{{d.time}}</span>
+                                <span class="newscentent">
+                                    <span>{{d.neirong.qyname}}</span>
+                                    <span>{{d.neirong.saas}}</span>
+                                    <span>{{d.neirong.phone}}</span>
+                                </span>
+                                <span>{{d.zhuangtai}}</span>
+                                <span><button v-if="d.caozuo" @click="Rejoin" class="news-btn">重新加入</button></span>
+                            </li>
+                        </ul>
+                    </div>
                 </div>
             </div>
         </div>
@@ -140,17 +162,30 @@ import { setTimeout } from 'timers';
                 ismodifyname:true,
                 isname:true,//姓名验证
                 reg: new RegExp(/[\@\#\$\%\&\*!\¥]/),//非法字符
+                isheigh:false,//默认高度
                 tab: [
                     {name: '企业信息'},
                     {name: '个人信息'},
                     {name: '安全设置'},
                     // {name: '消息'},
-                    ],
+                ],
+                arr: [
+                    {leixing:'加入申请',time:'2018/12/01  12:45:21',neirong:{qyname:'X防守对方的发士大夫XX公司',saas:'管理员名称范德萨发达',phone:'1345678923'},zhuangtai:'待批准',caozuo:false},
+                    {leixing:'加入申请',time:'2018/12/01  12:45:21',neirong:{qyname:'XXX公司',saas:'管理员名称',phone:'1345678923'},zhuangtai:'未通过',caozuo:true},
+                ]
             }
         },
         mounted(){
             let mob = this.mytoken.mobile.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
-            this.mobile = mob
+            this.mobile = mob;
+            this.boxheight();
+        },
+        watch:{
+            arr:function(){
+                this.$nextTick(function(){
+                    this.boxheight();
+                })
+            }
         },
         computed :{
             setTokenPage() {
@@ -221,7 +256,10 @@ import { setTimeout } from 'timers';
                     })
                     .then(res=>{
                         if (res.data.success) {
-                            this.$router.go(0)
+                            let session = JSON.parse(window.localStorage.getItem('app-state-session'));
+                            session.account.realname = name;
+                            Session.set(session);
+                            this.$router.go(0);
                         }
                     })
                     .catch(err=>{
@@ -229,9 +267,22 @@ import { setTimeout } from 'timers';
                     })
                 }
             },
-            onshezhi(){
-                this.$store.state.ismoren = '';
-                this.$store.state.issaasxiangxi = ''
+            //重新加入
+            Rejoin(){
+                //成功后提示
+                this.$message({
+                    message: '提交成功,待管理员批准',
+                    type: 'success'
+                });
+            },
+            //没有内容也要有一定的高度
+            boxheight(){
+                let H = this.$refs.qiyebox.offsetHeight;
+                if (H < 500) {
+                    this.isheigh = true
+                } else {
+                    this.isheigh = false
+                }
             },
         },
     }
@@ -242,6 +293,9 @@ import { setTimeout } from 'timers';
     padding-top: 100px;
     background: #FDFDFD;
 }
+.heigh {
+    height: 500px;
+}
 .gsqiye div:last-child {
     margin-bottom: 100px;
 }
@@ -287,4 +341,80 @@ import { setTimeout } from 'timers';
     margin-left: -10px;
     color: red;
 }
+
+/* 消息 */
+.gs-news {
+    width: 130%;
+    margin-left: -15%;
+}
+.gs-news > ul {
+    padding: 0;
+    font-family: PingFangSC-Regular;
+    font-size: 14px;
+    color: #243A52;
+}
+.gs-news > ul > li:nth-child(1) {
+    font-family: PingFangSC-Regular;
+    font-size: 14px;
+    color: #243A52;
+    font-weight: 600;
+    padding: 0px 10px;
+}
+.gs-news > ul > li > span {
+    display: inline-block;
+    text-align: center;
+}
+.gs-news > ul > li > span:nth-child(1),
+.gs-news > ul > li > span:nth-child(4),
+.gs-news > ul > li > span:nth-child(5) {
+    width: 10%;
+}
+.gs-news > ul > li > span:nth-child(2) {
+    width: 23%;
+}
+.gs-news > ul > li > span:nth-child(3) {
+    width: 43%;
+}
+.newscentent {
+    text-align: left !important;
+}
+.newscentent span{
+    width: 32%;
+    display: inline-block;
+    overflow: hidden;
+    text-overflow:ellipsis;
+    white-space: nowrap;
+}
+.newscentent span:nth-child(2),
+.newscentent span:nth-child(3) {
+    text-align: center;
+}
+.newslist {
+    background: #FFFFFF;
+    border: 1px solid rgba(30,136,245,0.32);
+    box-shadow: 0 20px 60px 8px #F4F8FC;
+    border-radius: 4px;
+    margin: 24px 0px;
+    padding: 30px 10px;
+}
+.news-btn {
+    background: #1E88F5;
+    border-radius: 2px;
+    color: white;
+    border: 0;
+    font-family: PingFangSC-Regular;
+    font-size: 14px;
+    color: #FFFFFF;
+    letter-spacing: 0.25px;
+    text-align: center;
+    padding: 5px 16px;
+}
+.reddian {
+    display: inline-block;
+    width: 4px;
+    height: 4px;
+    border-radius: 2px;
+    background: red;
+    margin-left: -22px;
+}
 </style>

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

@@ -74,7 +74,7 @@
       <!--Home Slider==================================== -->
       <div>
         <div class="slider-1" style="position: relative;">
-          <img src="/static/img/banner@3x@2x.png" alt="">
+          <img src="/static/img/banner--X.jpg" alt="">
           <div class="my-text" style="top:63%">
             <button class='my-tiyan' @click="experience">立即体验</button>
           </div>

+ 0 - 2
frontend/saas-portal-web/src/store/index.js

@@ -7,8 +7,6 @@ export default new Vuex.Store({
         isAutoLogin: false,
         isproblem: '',//常见问题
         isloading:false,
-        ismoren:'',
-        issaasxiangxi:''
     },
     mutations:{
          Logintrue(state) {

+ 13 - 8
frontend/saas-portal-web/static/css/gongsi.css

@@ -396,27 +396,32 @@
     border: 0;
     border-bottom: 1px solid #BDBEBE;
 }
+.hied {
+    display: none;
+}
 .lookup {
-    width: 40%;
+    width: 90%;
+    margin-left: 5%;
     background: #FFFFFF;
     border: 1px solid #1E88F5;
     border-radius: 2px;
-    margin-left: 5%;
-    position: absolute;
-    /* display: none; */
-    margin-top: -20px;
-    z-index: 1;
     text-align: left;
 }
+.showlookup {
+    display: block !important;
+}
 .lookup > ul {
-    padding: 20px;
+    padding: 20px 20px 0px 20px;
 }
 .lookup > ul > li {
     margin-bottom: 10px;
 } 
 .lookup > ul > li span{
-    width: 15%;
+    width: 16%;
     display: inline-block;
+    overflow: hidden;
+    text-overflow:ellipsis;
+    white-space: nowrap;
 } 
 .saasguanli {
     width: 18% !important;

BIN
frontend/saas-portal-web/static/img/banner--X.jpg


BIN
frontend/saas-portal-web/static/img/banner@3x@2x.png


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


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


+ 3 - 0
frontend/saas-web/app.json

@@ -212,6 +212,9 @@
         {
             "path": "${framework.dir}/build/ext-all-rtl-debug.js"
         },
+        {
+            "path": "lib/echarts.common.min.js"
+        },
         {
             "path": "app.js",
             "bundle": true

+ 18 - 0
frontend/saas-web/app/util/BaseUtil.js

@@ -174,5 +174,23 @@ Ext.define('saas.util.BaseUtil', {
                 });
             })
         },
+
+        /**
+         * 格式化数字
+         * @param value: 需要格式化的数字
+         * @param decimalPrecision: 最大小数位数
+         * @param thousandSeparator: 显示千分位分隔符
+         */
+        numberFormat: function(value, decimalPrecision, thousandSeparator) {
+            value = Number(value) || 0;
+            decimalPrecision = Ext.isNumber(decimalPrecision) ? decimalPrecision : 2;
+            thousandSeparator = !!thousandSeparator;
+            
+            var f1 = thousandSeparator ? '0,000' : '0';
+            var arr = (value + '.').split('.');
+            var xr = (new Array(arr[1].length > decimalPrecision ? decimalPrecision : arr[1].length)).fill('0');
+            var format = f1 + '.' + xr.join('');
+            return Ext.util.Format.number(value, format);
+        }
     }
 });

+ 181 - 0
frontend/saas-web/app/view/core/chart/EChartsBase.js

@@ -0,0 +1,181 @@
+Ext.define('saas.view.core.EChartsBase', {
+    extend: 'Ext.Container',
+    xtype: 'echartsbase',
+
+    mixins: [
+        'Ext.util.StoreHolder'
+    ],
+
+    border: false,
+    style: {
+        width: '100%',
+        height: '100%'
+    },
+    config: {
+        option: null
+    },
+
+    initComponent: function () {
+        var me = this;
+        me.on('resize', function(container, width, height, oldWidth, oldHeight, eOpts) {
+            if(me.timer) {
+                window.clearTimeout(me.timer);
+            }
+            me.timer = window.setTimeout(function() {
+                me.echarts.resize();
+            }, 100);
+        });
+        me.on("boxready", function () {
+            me.echarts = echarts.init(me.getEl().dom);
+        });
+        me.callParent();
+    },
+
+    setStore: function (newStore) {
+        var me = this;
+ 
+        if (me.store !== newStore) {
+            if (me.isConfiguring) {
+                me.store = newStore;
+            } else {
+                me.bindStore(newStore, false);
+            }
+        }
+    },
+
+    onBindStore: function(store, oldStore) {
+        var me = this;
+ 
+        if (me.store.isBufferedStore) {
+            me.store.preserveScrollOnReload = me.preserveScrollOnReload;
+        }
+        if (oldStore && oldStore.isBufferedStore) {
+            delete oldStore.preserveScrollOnReload;
+        }
+ 
+        if (!me.dataSource) {
+            me.dataSource = store;
+        }
+    },
+
+    onUnbindStore: function(store) {
+        if (this.dataSource === store) {
+            this.dataSource = null;
+        }
+    },
+
+    bindStore: function (store, initial) {
+        var me = this;
+        
+        me.mixins.storeholder.bindStore.apply(me, arguments);
+ 
+ 
+        if (store && me.componentLayoutCounter && !me.blockRefresh) {
+            me.doFirstRefresh(store, !initial);
+        }
+    },
+
+    doFirstRefresh: function(store, noDefer) {
+        var me = this;
+ 
+        if (me.deferInitialRefresh && !noDefer) {
+            Ext.defer(me.doFirstRefresh, 1, me, [store, true]);
+        }
+ 
+        else {
+            if (store && !me.deferRefreshForLoad(store)) {
+                me.refresh();
+            }
+        }
+    },
+
+    deferRefreshForLoad: function(store) {
+        return store.isLoading();
+    },
+
+    getStoreListeners: function() {
+        var me = this;
+        return {
+            scope: me,
+            refresh: me.onDataRefresh,
+            replace: me.onReplace,
+            add: me.onAdd,
+            remove: me.onRemove,
+            update: me.onUpdate,
+            clear: me.onDataRefresh,
+            beginupdate: me.onBeginUpdate,
+            endupdate: me.onEndUpdate
+        };
+    },
+
+    onDataRefresh: function(store) {
+        // console.log('onDataRefresh');
+        var me = this,
+            preserveScrollOnRefresh = me.preserveScrollOnRefresh;
+ 
+        if (store.loadCount > (me.lastRefreshLoadCount || 0)) {
+            me.preserveScrollOnRefresh = me.preserveScrollOnReload;
+        }
+        me.refreshView();
+        me.preserveScrollOnRefresh = preserveScrollOnRefresh;
+        me.lastRefreshLoadCount = store.loadCount;
+    },
+
+    onReplace: function() {
+        // console.log('onReplace');
+    },
+
+    onAdd: function() {
+        // console.log('onAdd');
+    },
+
+    onRemove: function() {
+        // console.log('onRemove');
+    },
+
+    onUpdate: function() {
+        // console.log('onUpdate');
+    },
+
+    onBeginUpdate: function() {
+        // console.log('onBeginUpdate');
+    },
+
+    onEndUpdate: function() {
+        // console.log('onEndUpdate');
+    },
+
+    refreshView: function(startIndex) {
+        var me = this,
+            // If we have an ancestor in a non-boxready state (collapsed or about to collapse, or hidden), then block the 
+            // refresh because the next layout will trigger the refresh 
+            blocked = me.blockRefresh || !me.rendered || me.up('[collapsed],[isCollapsingOrExpanding=1],[hidden]'),
+            bufferedRenderer = me.bufferedRenderer;
+ 
+        // If we are blocked in any way due to either a setting, or hidden or collapsed, or animating ancestor, then 
+        // the next refresh attempt at the upcoming layout must not defer. 
+        if (blocked) {
+            me.refreshNeeded = true;
+        } else {
+            if (bufferedRenderer) {
+                bufferedRenderer.refreshView(startIndex);
+            } else {
+                me.refresh();
+            }
+        }
+    },
+
+    refresh: function() {
+        var me = this,
+        store = me.store,
+        option = me.createOption(store);
+
+        if(option) {
+            me.echarts.setOption(option);
+        }
+    },
+
+    createOption: function(store) {
+        return null;
+    }
+});

+ 5 - 5
frontend/saas-web/app/view/core/query/QueryGridPanel.js

@@ -303,10 +303,10 @@ Ext.define('saas.view.core.query.QueryGridPanel', {
         });
     },
     onAudit: function(me){
-        me.up('grid').vastOperation("batchAudit");
+        me.up('grid').vastOperation("batchAudit",'审核');
     },
     onUnAudit:function(me){
-        me.up('grid').vastOperation("batchUnAudit");
+        me.up('grid').vastOperation("batchUnAudit",'反审核');
     },
     onPrint: function (me) {
         console.log("打印");
@@ -366,7 +366,7 @@ Ext.define('saas.view.core.query.QueryGridPanel', {
             saas.util.BaseUtil.showErrorToast('请勾选至少一条明细。');
         }
     },
-    vastOperation :function(type){
+    vastOperation :function(type,msg){
         var me = this;
         var data = me.getGridSelected();
         if(data&&data.length>0){
@@ -381,14 +381,14 @@ Ext.define('saas.view.core.query.QueryGridPanel', {
                 if(res.data){
                     saas.util.BaseUtil.showSuccessToast(res.data);
                 }else{
-                    saas.util.BaseUtil.showSuccessToast('操作成功');
+                    saas.util.BaseUtil.showSuccessToast(msg?msg + '成功':'操作成功');
                 }
                 me.store.load();
                 me.selModel.deselectAll();
             })
             .catch(function(res) {
                 console.error(res);
-                saas.util.BaseUtil.showErrorToast('操作失败: ' + res.message);
+                saas.util.BaseUtil.showErrorToast((msg?msg + '失败: ':'操作失败: ') + res.message);
             });
         }else{
             saas.util.BaseUtil.showErrorToast('请勾选至少一条明细。');

+ 17 - 13
frontend/saas-web/app/view/core/tab/Controller.js

@@ -3,19 +3,23 @@ Ext.define('saas.view.core.tab.Controller', {
     alias: 'controller.core-tab-controller',
 
     init: function() {
-        var me = this,
-        tab = me.getView(),
-        viewType = tab.viewType,
-        _config = tab.index,
-        viewConfig = tab.viewConfig;
-
-        var view = {
-            _config : viewConfig,
-            xtype: viewType
-        };
-        Ext.apply(view, viewConfig);
-
-        tab.add(view);
+        try {
+            var me = this,
+            tab = me.getView(),
+            viewType = tab.viewType,
+            _config = tab.index,
+            viewConfig = tab.viewConfig;
+    
+            var view = {
+                _config : viewConfig,
+                xtype: viewType
+            };
+            Ext.apply(view, viewConfig);
+    
+            tab.add(view);
+        }catch(e) {
+            console.error(e);
+        }
     },
 
     onTabActivate: function(component) {

+ 2 - 2
frontend/saas-web/app/view/document/employee/Window.js

@@ -88,8 +88,8 @@ Ext.define('saas.view.document.employee.Window', {
                 xtype:'textfield',
                 fieldLabel: '联系电话',
                 name: 'em_mobile',
-                regex:/^1(3|4|5|7|8|9)\d{9}$/,
-                regexText:'请输入正确的手机号码',
+                // regex:/^1(3|4|5|7|8|9)\d{9}$/,
+                // regexText:'请输入正确的手机号码',
                 allowBlank:false,
                 maxLength: 20
             },{

+ 0 - 87
frontend/saas-web/app/view/home/HomeModel.js

@@ -4,12 +4,6 @@ Ext.define('saas.view.home.HomeModel', {
 
     data: {
         month_sale_amount: '0', // 本月销售合计
-        month_purchase_amount: '0', // 本月采购合计
-        month_in: '0', // 本月收入合计
-        month_out: '0', // 本月支出合计
-
-        insetPadding: '12 0 0 0', // 图表insetPadding
-        maxBarWidth: 25, // 最大柱宽
     },
 
     stores: {
@@ -97,42 +91,6 @@ Ext.define('saas.view.home.HomeModel', {
             }
         },
 
-        // month_purchase: {
-        //     model: 'saas.model.chart.DataXY',
-        //     autoLoad: true,
-        //     proxy: {
-        //         type: 'ajax',
-        //         // 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',
-        //             rootProperty: 'data',
-        //         },
-        //         listeners: {
-        //             exception: function(proxy, response, operation, eOpts) {
-        //                 var p = Ext.getCmp('month_purchase');
-        //                 p && p.setLoading(false);
-        //             }
-        //         }
-        //     },
-        //     listeners: {
-        //         beforeload: function() {
-        //             var p = Ext.getCmp('month_purchase');
-        //                 p && p.setLoading(true);
-        //         },
-        //         load: function(s, d) {
-        //             var p = Ext.getCmp('month_purchase');
-        //                 p && p.setLoading(false);
-        //             var sum = Ext.util.Format.number(s.sum('y'), '0.00') || 0;
-        //             Ext.getCmp('home').getViewModel().set('month_purchase_amount', sum+'')
-        //         }
-        //     }
-        // },
-
         month_io: {
             fields: ['x', 'main', 'other'],
             autoLoad: true,
@@ -163,14 +121,6 @@ Ext.define('saas.view.home.HomeModel', {
                 load: function(s, d) {
                     var p = Ext.getCmp('month_io');
                     p && p.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_out', sum);
-                        }
-                    });
                 }
             }
         },
@@ -212,43 +162,6 @@ Ext.define('saas.view.home.HomeModel', {
             } 
         },
 
-        // 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'
-        //         },
-        //         reader: {
-        //             type: 'json',
-        //             rootProperty: 'data',
-        //         },
-        //         listeners: {
-        //             exception: function(proxy, response, operation, eOpts) {
-        //                 var p = Ext.getCmp('purchase_trend');
-        //                 p && p.setLoading(false);
-        //             }
-        //         }
-        //     },
-        //     sorters: [
-        //         { property: 'x', direction: 'ASC' }
-        //     ],
-        //     listeners: {
-        //         beforeload: function() {
-        //             var p = Ext.getCmp('purchase_trend');
-        //                 p && p.setLoading(true);
-        //         },
-        //         load: function(s, d) {
-        //             var p = Ext.getCmp('purchase_trend');
-        //                 p && p.setLoading(false);
-        //         }
-        //     } 
-        // },
-
         stock_amount: {
             fields: ['x', 'y'],
             autoLoad: true,

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

@@ -55,16 +55,16 @@
                     }
 
                     &-storageTotal {
-                        background-image: url(/resources/images/home/storageTotal.png);
+                        background-image: url(get-resource-path('images/home/storageTotal.png'));
                     }
                     &-receiveTotal {
-                        background-image: url(/resources/images/home/receiveTotal.png);
+                        background-image: url(get-resource-path('images/home/receiveTotal.png'));
                     }
                     &-payTotal {
-                        background-image: url(/resources/images/home/payTotal.png);
+                        background-image: url(get-resource-path('images/home/payTotal.png'));
                     }
                     &-balanceTotal {
-                        background-image: url(/resources/images/home/balanceTotal.png);
+                        background-image: url(get-resource-path('images/home/balanceTotal.png'));
                     }
                 }
 

+ 107 - 77
frontend/saas-web/app/view/home/charts/MonthIO.js

@@ -3,9 +3,6 @@ Ext.define('saas.view.home.charts.MonthIO', {
     xtype: 'month-io',
     id: 'month_io',
 
-    // bind: {
-    //     title: '本月收入支出额(万元)<div style="text-align: right;"><span style="font-weight:bold;">收入:{month_in}</span><span style="font-weight:bold;margin-left: 10px;">支出:{month_out}</span></div>'
-    // },
     title: '本月收入支出额(万元)',
 
     initComponent: function () {
@@ -13,87 +10,120 @@ Ext.define('saas.view.home.charts.MonthIO', {
 
         Ext.apply(me, {
             items: [{
-                xtype: 'cartesian',
-                colors: [
-                    '#2C82BE',
-                    '#82CCFF'
-                ],
+                xtype: 'echartsbase',
                 bind: {
-                    legend: {
-                        type: 'dom',
-                        docked: 'top',
-                        padding: 0,
-                        bodyPadding: 0,
-                        border: 0,
-                        cls: 'x-monthio-legend',
-                        html: '<div class="sumtip"><span>收入:{month_in}</span><span>支出:{month_out}</span></div>'
-                    },
-                    insetPadding: '{insetPadding}',
-                    store: '{month_io}'
+                    store: '{month_io}',
                 },
-                axes: [{
-                    type: 'numeric',
-                    position: 'left',
-                    adjustByMajorUnit: true,
-                    fields: ['main'],
-                    minimum: 0,
-                    label: {
-                        fontSize: '12px',
-                        fillStyle: '#485465'
-                    },
-                    grid: {
-                        even: {
-                            stroke: '#E5EAEF'
-                        },
-                        odd: {
-                            stroke: '#E5EAEF',
-                        }
-                    },
-                    style: {
-                        fill: '#fff',
-                        strokeStyle: 'transparent'
-                    },
-                }, {
-                    type: 'category',
-                    position: 'bottom',
-                    fields: ['x'],
-                    label: {
-                        fontSize: '12px',
-                        fillStyle: '#485465'
-                    },
-                    style: {
-                        fill: '#E5EAEF',
-                        strokeStyle: 'transparent'
-                    },
-                }],
-                series: [{
-                    type: 'bar',
-                    title: ['主营业务', '其他业务'],
-                    xField: 'x',
-                    yField: ['main', 'other'],
-                    stacked: true,
-                    bind: {
-                        style: {
-                            lineWidth: 0,
-                            strokeStyle: 'transparent',
-                            maxBarWidth: '{maxBarWidth}',
-                        },
-                    },
-                    tooltip: {
-                        trackMouse: true,
-                        renderer: me.onBarTipRender
-                    }
-                }]
+                createOption: me.createOption
             }]
         });
 
         me.callParent(arguments);
     },
 
-    onBarTipRender: function (tooltip, record, item) {
-        var fieldIndex = Ext.Array.indexOf(item.series.getYField(), item.field),
-        type = item.series.getTitle()[fieldIndex];
+    createOption: function (store) {
+        var fields = [],
+            main = [],
+            other = [],
+            data = [];
 
-        tooltip.setHtml(type + record.get('x') + ': ' + Ext.util.Format.number(record.get(item.field), '0,000.00') + '万元');
-    },
+        store.each(function (d) {
+            var d = d.data;
+            // fields.push(d.x);
+            main.push(d.main);
+            other.push(d.other);
+        });
+
+        var o = {
+            color: [
+                '#2C82BE',
+                '#82CCFF'
+            ],
+            tooltip: {
+                trigger: 'axis',
+                formatter: function (params, ticket, callback) {
+                    var name = '',
+                    total = 0,
+                    series = [];
+
+                    for(var x = 0; x < params.length; x++) {
+                        var p = params[x],
+                        marker = p.marker,
+                        seriesName = p.seriesName,
+                        name = p.name,
+                        value = p.value;
+
+                        total += value;
+
+                        value = saas.util.BaseUtil.numberFormat(value, 4, true);
+                        
+                        series.push(marker + seriesName + ': ' + value);
+                    }
+
+                    total = saas.util.BaseUtil.numberFormat(total, 4, true);
+                    
+                    return name + ': ' + total + '<br/>' + series.join('<br/>');
+                }
+            },
+            legend: {
+                orient: 'horizontal',
+                left: 0,
+                icon: 'circle',
+                data: ['主营业务', '其他业务'],
+                itemWidth: 9,
+                itemHeight: 9
+            },
+            grid: {
+                left: 0,
+                right: 0,
+                bottom: 0,
+                top: 40,
+                borderColor: '#E5EAEF',
+                containLabel: true
+            },
+            xAxis: [{
+                type: 'category',
+                data: ['收入', '支出'],
+                axisLine: {
+                    lineStyle: {
+                        color: '#E5EAEF',
+                    }
+                },
+                axisLabel: {
+                    color: '#485465'
+                },
+            }],
+            yAxis: [{
+                type: 'value',
+                axisLine: {
+                    lineStyle: {
+                        color: '#E5EAEF',
+                    }
+                },
+                splitLine: {
+                    lineStyle: {
+                        color: ['#E5EAEF']
+                    }
+                },
+                axisLabel: {
+                    color: '#485465'
+                }
+            }],
+            series: [{
+                name: '主营业务',
+                type: 'bar',
+                stack: '合计',
+                barWidth: 25,
+                data: main
+            },
+            {
+                name: '其他业务',
+                type: 'bar',
+                stack: '合计',
+                barWidth: 25,
+                data: other
+            }]
+        };
+        return o;
+    }
 });

+ 0 - 91
frontend/saas-web/app/view/home/charts/MonthPurchase.js

@@ -1,91 +0,0 @@
-Ext.define('saas.view.home.charts.MonthPurchase', {
-    extend: 'saas.view.core.chart.ChartBase',
-    xtype: 'month-purchase',
-
-    id: 'month_purchase',
-
-    bind: {
-        title: '本月采购额(万元):{month_purchase_amount}'
-    },
-
-    initComponent: function() {
-        var me = this;
-
-        Ext.apply(me, {
-            items: [{
-                xtype: 'cartesian',
-                colors: [
-                    '#34BAF6'
-                ],
-                bind: {
-                    insetPadding: '{insetPadding}',
-                    store: '{month_purchase}',
-                },
-                axes: [{
-                    type: 'category',
-                    fields: ['x'],
-                    position: 'bottom',
-                    label: {
-                        fontSize: '12px',
-                        fillStyle: '#485465',
-                    },
-                    style: {
-                        fill: '#E5EAEF',
-                        strokeStyle: 'transparent'
-                    },
-                    renderer: me.onCategoryLabelRender
-                },{
-                    type: 'numeric',
-                    fields: ['y'],
-                    position: 'left',
-                    adjustByMajorUnit: true,
-                    grid: {
-                        even: {
-                            stroke: '#E5EAEF'
-                        },
-                        odd: {
-                            stroke: '#E5EAEF',
-                        }
-                    },
-                    label: {
-                        fontSize: '12px',
-                        fillStyle: '#485465',
-                        textAlign: 'end'
-                    },
-                    style: {
-                        fill: '#fff',
-                        strokeStyle: 'transparent'
-                    },
-                    minimum: 0
-                }],
-                series: [{
-                    type: 'bar',
-                    xField: 'x',
-                    yField: ['y'],
-                    bind: {
-                        style: {
-                            lineWidth: 0,
-                            strokeStyle: 'transparent',
-                            maxBarWidth: '{maxBarWidth}',
-                        },
-                    },
-                    tooltip: {
-                        trackMouse: true,
-                        renderer: me.onBarTipRender
-                    }
-                }]
-            }]
-        });
-
-        me.callParent(arguments);
-    },
-
-    onCategoryLabelRender: function(axis, label, layoutContent, lastLabel) {
-        return label.substr(0,2) + '...';
-    },
-
-    onBarTipRender: function (tooltip, record, item) {
-        tooltip.setHtml(record.get('x') + ': ' + Ext.util.Format.number(record.get('y'), '0,000.00') + '万元');
-    },
-
-});

+ 76 - 65
frontend/saas-web/app/view/home/charts/MonthSale.js

@@ -4,6 +4,7 @@ Ext.define('saas.view.home.charts.MonthSale', {
 
     id: 'month_sale',
 
+    title: '本月销售额(万元):0', // 设置默认标题占好默认高度,使容器内的组件可以正确获得展示高度
     bind: {
         title: '本月销售额(万元):{month_sale_amount}'
     },
@@ -13,79 +14,89 @@ Ext.define('saas.view.home.charts.MonthSale', {
 
         Ext.apply(me, {
             items: [{
-                xtype: 'polar',
-                width: '100%',
-                height: '100%',
+                xtype: 'echartsbase',
                 bind: {
                     store: '{month_sale}',
                 },
-                colors: [
-                    '#1EC09F',
-                    '#27A7FF',
-                    '#4E84F5',
-                    '#FDC200',
-                    '#76DDFB',
-                    '#FE7D6B',
-                ],
-                interactions: ['rotate', 'itemhighlight'],
-                innerPadding: 2,
-                legend: {
-                    type: 'dom',
-                    docked: 'right',
-                    width: 120,
-                    padding: 0,
-                    bodyPadding: 0,
-                    border: 0,
-                    // liveDrag: true,
-                    cls: 'x-pie-legend'
-                },
-                style: {
-                    lineWidth: 0,
-                    stroke: "#789"
-                },
-                series: [{
-                    type: 'pie',
-                    angleField: 'y',
-                    donut: 55,
-                    label: {
-                        field: 'x',
-                        display: 'inside',
-                        renderer: me.onLabelRender,
-                        color: '#fff',
-                        font: '12px Microsoft YaHei'
-                    },
-                    style: {
-                        // lineWidth: 0,
-                        // strokeStyle: 'transparent',
-                        // fillStyle: 'transparent',
-                        // fillOpacity: 0
-                    },
-                    // label: {
-                    //     field: 'x',
-                    //     renderer: me.onLabelRender
-                    // },
-                    highlight: false,
-                    tooltip: {
-                        trackMouse: true,
-                        renderer: me.onSeriesTooltipRender
-                    }
-                }]
-            }],
+                createOption: me.createOption
+            }]
         });
 
         me.callParent(arguments);
     },
 
-    onLabelRender: function(text, sprite, config, rendererData, index) {
-        var homeModel = Ext.getCmp('home').getViewModel();
-        var monthSaleAmount = homeModel.get('month_sale_amount');
-        var store = rendererData.store;
-        var data = store.getAt(index);
-        var v = data.get('y');
-        return Ext.util.Format.number((v/monthSaleAmount)*100, '0.00') + '%';
-    },
+    createOption: function(store) {
+        var fields = [],
+        data = [];
 
-    onSeriesTooltipRender: function (tooltip, record, item) {
-        tooltip.setHtml(record.get('x') + ': ' + Ext.util.Format.number(record.get('y'), '0,000.00'));
+        store.each(function(d) {
+            var d = d.data;
+            fields.push(d.x);
+            data.push({
+                value: d.y,
+                name: d.x
+            });
+        });
+
+        return {
+            color: [
+                '#1EC09F',
+                '#27A7FF',
+                '#4E84F5',
+                '#FDC200',
+                '#76DDFB',
+                '#FE7D6B',
+            ],
+            tooltip: {
+                trigger: 'item',
+                formatter: function (params, ticket, callback) {
+                    var name = params.name,
+                    value = params.value,
+                    marker = params.marker,
+                    percent = params.percent;
+
+                    if(name.length > 7) {
+                        name = Ext.String.insert(name, '<br/>', 7)
+                    }
+                    value = saas.util.BaseUtil.numberFormat(value, 4, true);
+
+                    return name + '<br/>' + marker + value+ '  (' + percent + '%)';
+                }
+            },
+            legend: {
+                orient: 'horizontal',
+                left: '70%',
+                width: '30%',
+                icon: 'circle',
+                data: fields,
+                itemWidth: 9,
+                itemHeight: 9
+            },
+            series: [
+                {
+                    type:'pie',
+                    radius: ['48%', '88%'],
+                    center: ['35%', '50%'],
+                    label: {
+                        normal: {
+                            show: false,
+                        },
+                        emphasis: {
+                            show: false,
+                            textStyle: {
+                                fontSize: '30',
+                                fontWeight: 'bold'
+                            }
+                        }
+                    },
+                    labelLine: {
+                        normal: {
+                            show: false
+                        }
+                    },
+                    data: data
+                }
+            ]
+        }
     }
 });

+ 93 - 72
frontend/saas-web/app/view/home/charts/ProfitDetail.js

@@ -4,91 +4,112 @@ Ext.define('saas.view.home.charts.ProfitDetail', {
 
     id: 'profit_detail',
 
-    bind: {
-        title: '毛利润分析(万元)'
-    },
+    title: '毛利润分析(万元)',
 
-    initComponent: function() {
+    initComponent: function () {
         var me = this;
 
         Ext.apply(me, {
             items: [{
-                xtype: 'cartesian',
-                colors: [
-                    '#34BAF6'
-                ],
+                xtype: 'echartsbase',
                 bind: {
-                    insetPadding: '{insetPadding}',
                     store: '{profit_detail}',
                 },
-                axes: [{
-                    type: 'category',
-                    fields: ['x'],
-                    position: 'bottom',
-                    label: {
-                        fontSize: '12px',
-                        fillStyle: '#485465',
-                    },
-                    style: {
-                        fill: '#E5EAEF',
-                        strokeStyle: 'transparent'
-                    },
-                    renderer: me.onCategoryLabelRender
-                },{
-                    type: 'numeric',
-                    fields: ['y'],
-                    position: 'left',
-                    adjustByMajorUnit: true,
-                    grid: {
-                        even: {
-                            stroke: '#E5EAEF'
-                        },
-                        odd: {
-                            stroke: '#E5EAEF',
-                        }
-                    },
-                    label: {
-                        fontSize: '12px',
-                        fillStyle: '#485465',
-                        textAlign: 'end'
-                    },
-                    style: {
-                        fill: '#fff',
-                        strokeStyle: 'transparent'
-                    },
-                    minimum: 0
-                }],
-                series: [{
-                    type: 'bar',
-                    xField: 'x',
-                    yField: ['y'],
-                    bind: {
-                        style: {
-                            lineWidth: 0,
-                            strokeStyle: 'transparent',
-                            maxBarWidth: '{maxBarWidth}',
-                        },
-                    },
-                    tooltip: {
-                        trackMouse: true,
-                        renderer: me.onBarTipRender
-                    }
-                }]
+                createOption: me.createOption
             }]
         });
 
         me.callParent(arguments);
     },
 
-    onCategoryLabelRender: function(axis, label, layoutContent, lastLabel) {
-        var cWidth = this.gridSurface.el.dom.clientWidth,
-        dataCount = layoutContent.data.length,
-        maxLength = Math.ceil((cWidth/dataCount)/20);
-        return label.length > maxLength ? label.substring(0, maxLength) + '...' : label;
-    },
+    createOption: function (store) {
+        var fields = [],
+            data = [];
 
-    onBarTipRender: function (tooltip, record, item) {
-        tooltip.setHtml(record.get('x') + ': ' + Ext.util.Format.number(record.get('y'), '0,000.00') + '万元');
-    },
+        store.each(function (d) {
+            var d = d.data;
+            fields.push(d.x);
+            data.push(d.y);
+        });
+        return {
+            color: [
+                '#34BAF6'
+            ],
+            grid: {
+                left: 0,
+                right: 0,
+                top: 10,
+                bottom: 0,
+                borderColor: '#E5EAEF',
+                containLabel: true
+            },
+            tooltip: {
+                trigger: 'axis',
+                formatter: function (params, ticket, callback) {
+                    var name = '',
+                    series = [];
+
+                    for(var x = 0; x < params.length; x++) {
+                        var p = params[x],
+                        marker = p.marker,
+                        seriesName = p.seriesName,
+                        name = p.name,
+                        value = p.value;
+
+                        value = saas.util.BaseUtil.numberFormat(value, 4, true);
+
+                        series.push(marker + ': ' + value);
+                    }
+
+                    if(name.length > 9) {
+                        name = Ext.String.insert(name, '<br/>', 7)
+                    }
+        
+
+                    return name + ': ' + '<br/>' + series.join('<br/>');
+                }
+            },
+            xAxis: {
+                type: 'category',
+                axisLine: {
+                    lineStyle: {
+                        color: '#E5EAEF',
+                    }
+                },
+                axisLabel: {
+                    color: '#485465',
+                    interval: 0,
+                    formatter: function (value, index) {
+                        var cWidth = Ext.getCmp('profit_detail').items.items[0].echarts.getWidth() * 0.9,
+                            dataCount = fields.length,
+                            maxLength = Math.ceil((cWidth / dataCount) / 20);
+                        return value.length > maxLength ? value.substring(0, maxLength) + '...' : value;
+                    },
+                },
+                data: fields,
+            },
+            yAxis: {
+                type: 'value',
+                axisLine: {
+                    lineStyle: {
+                        color: '#E5EAEF',
+                    }
+                },
+                splitLine: {
+                    lineStyle: {
+                        color: ['#E5EAEF']
+                    }
+                },
+                axisLabel: {
+                    color: '#485465'
+                }
+            },
+            series: [{
+                type: 'bar',
+                barWidth: 25,
+                data: data,
+            }]
+        };
+    }
 
-});
+});

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

@@ -1,98 +0,0 @@
-Ext.define('saas.view.home.charts.PurchaseTrend', {
-    extend: 'saas.view.core.chart.ChartBase',
-    xtype: 'purchase-trend',
-
-    id: 'purchase_trend',
-
-    bind: {
-        title: '近六月采购趋势图(万元)'
-    },
-
-    initComponent: function() {
-        var me = this;
-
-        Ext.apply(me, {
-            items: [{
-                xtype: 'cartesian',
-                colors: [
-                    '#34BAF6'
-                ],
-                bind: {
-                    insetPadding: '{insetPadding}',
-                    store: '{purchase_trend}',
-                },
-                axes: [{
-                    // title: {
-                    //     text: '月',
-                    //     fontSize: 14,
-                    // },
-                    type: 'category',
-                    fields: ['x'],
-                    position: 'bottom',
-                    label: {
-                        fontSize: '12px',
-                        fillStyle: '#485465'
-                    },
-                    style: {
-                        fill: '#E5EAEF',
-                        strokeStyle: 'transparent'
-                    },
-                    renderer: me.categoryRender
-                },{
-                    type: 'numeric',
-                    fields: ['y'],
-                    position: 'left',
-                    grid: {
-                        even: {
-                            stroke: '#E5EAEF'
-                        },
-                        odd: {
-                            stroke: '#E5EAEF',
-                        }
-                    },
-                    label: {
-                        fontSize: '12px',
-                        fillStyle: '#485465'
-                    },
-                    style: {
-                        fill: '#fff',
-                        strokeStyle: 'transparent'
-                    },
-                }],
-                series: [{
-                    type: 'bar',
-                    xField: 'x',
-                    yField: ['y'],
-                    tooltip: {
-                        trackMouse: true,
-                        renderer: me.onBarTipRender
-                    },
-                    // label: {
-                    //     field: 'y',
-                    //     display: 'insideEnd',
-                    //     fontSize: '12px',
-                    //     strokeStyle: '#fff',
-                    // },
-                    bind: {
-                        style: {
-                            lineWidth: 0,
-                            strokeStyle: 'transparent',
-                            maxBarWidth: '{maxBarWidth}',
-                        },
-                    },
-                }]
-            }]
-        });
-
-        me.callParent(arguments);
-    },
-
-    onBarTipRender: function (tooltip, record, item) {
-        tooltip.setHtml(record.get('x') + '月: ' + Ext.util.Format.number(record.get('y'), '0,000.00') + '万元');
-    },
-
-    categoryRender: function(axis, label, layoutContext, lastLabel) {
-        return label + '月';
-    }
-
-});

+ 102 - 170
frontend/saas-web/app/view/home/charts/SaleTrend.js

@@ -4,194 +4,126 @@ Ext.define('saas.view.home.charts.SaleTrend', {
 
     id: 'sale_trend',
 
-    bind: {
-        title: '近六月销售趋势图(万元)'
-    },
+    title: '近六月销售趋势图(万元)',
+    bodyPadding: '16 0 16 0',
 
-    initComponent: function() {
+    initComponent: function () {
         var me = this;
 
         Ext.apply(me, {
             items: [{
-                xtype: 'cartesian',
-                colors: [
-                    '#64B0E4',
-                    '#FF1038'
-                ],
+                xtype: 'echartsbase',
                 bind: {
-                    insetPadding: '{insetPadding}',
                     store: '{sale_trend}',
                 },
-                // legend: {
-                //     type: 'dom',
-                //     docked: 'top',
-
-                // },
-                axes: [{
-                    // title: {
-                    //     text: '月',
-                    //     fontSize: 14,
-                    // },
-                    type: 'category',
-                    fields: ['x'],
-                    position: 'bottom',
-                    label: {
-                        fontSize: '12px',
-                        fillStyle: '#485465',
-                    },
-                    style: {
-                        fill: '#E5EAEF',
-                        strokeStyle: 'transparent'
-                    },
-                    renderer: me.categoryRender
-                },{
-                    type: 'numeric',
-                    fields: ['sale', 'saleback'],
-                    position: 'left',
-                    grid: {
-                        even: {
-                            stroke: '#E5EAEF',
-                        },
-                        odd: {
-                            stroke: '#E5EAEF',
-                        }
-                    },
-                    label: {
-                        fontSize: '12px',
-                        fillStyle: '#485465',
-                    },
-                    style: {
-                        fill: '#fff',
-                        strokeStyle: 'transparent'
-                    },
-                }],
-                series: [{
-                    type: 'line',
-                    // smooth: true,
-                    title: '销售额',
-                    xField: 'x',
-                    yField: 'sale',
-                    label: {
-                        field: 'sale',
-                        display: 'over',
-                        fontSize: '12px',
-                        strokeStyle: '#A3D0EE',
-                    },
-                    marker: {
-                        radius: 0,
-                        lineWidth: 0
-                    },
-                    highlight: {
-                        fillStyle: '#53A8E2',
-                        fillOpacity: 1,
-                        strokeStyle: '#A3D0EE',
-                        radius: 5,
-                        lineWidth: 2,
-                    },
-                    style: {
-                        lineWidth: 2,
-                        fillStyle: '#53A8E2',
-                        fillOpacity: 0.1,
-                    },
-                    tooltip: {
-                        trackMouse: true,
-                        renderer: me.onSeriesTooltipRender
-                    },
-                    // renderer: me.onSeriesRenderer
-                }, {
-                    type: 'line',
-                    // smooth: true,
-                    title: '销售回款',
-                    xField: 'x',
-                    yField: 'saleback',
-                    label: {
-                        field: 'saleback',
-                        display: 'over',
-                        fontSize: '12px',
-                        strokeStyle: '#D54F65',
-                    },
-                    tooltip: {
-                        trackMouse: true,
-                        renderer: me.onSeriesTooltipRender
-                    },
-                    marker: {
-                        radius: 0,
-                        lineWidth: 0
-                    },
-                    highlight: {
-                        fillStyle: '#D54F65',
-                        fillOpacity: 1,
-                        strokeStyle: '#FF9BAC',
-                        radius: 5,
-                        lineWidth: 2,
-                    },
-                    style: {
-                        lineWidth: 2,
-                        fillStyle: '#D54F65',
-                        fillOpacity: 0.1,
-                    },
-                }],
-                legend: {
-                    type: 'dom',
-                    docked: 'top',
-                    padding: 0,
-                    bodyPadding: 0,
-                    border: 0,
-                    cls: 'x-saletrend-legend'
-                },
-                listeners: {
-                    itemhighlightchange: me.itemhighlightchange
-                }
+                createOption: me.createOption
             }]
         });
 
         me.callParent(arguments);
     },
 
-    onSeriesRender: function (sprite, config, rendererData, index) {
-        var store = rendererData.store,
-            storeItems = store.getData().items,
-            currentRecord = storeItems[index],
-            previousRecord = (index > 0 ? storeItems[index-1] : currentRecord),
-            current = currentRecord && currentRecord.data['g1'],
-            previous = previousRecord && previousRecord.data['g1'],
-            isUp = current >= previous,
-            changes = {};
+    createOption: function (store) {
+        var fields = [],
+        sale = [],
+        saleBack = [],
+        data = [];
 
-        switch (config.type) {
-            case 'marker':
-                changes.strokeStyle = (isUp ? 'cornflowerblue' : 'tomato');
-                changes.fillStyle = (isUp ? 'aliceblue' : 'lightpink');
-                break;
-            case 'line':
-                changes.strokeStyle = (isUp ? 'cornflowerblue' : 'tomato');
-                changes.fillStyle = (isUp ? 'rgba(100, 149, 237, 0.4)' : 'rgba(255, 99, 71, 0.4)');
-                break;
-        }
+        store.each(function (d) {
+            var d = d.data;
+            fields.push(d.x + '月');
+            sale.push(d.sale);
+            saleBack.push(d.saleback);
+        });
 
-        return changes;
-    },
+        data = data.concat([{
+            name: '销售额',
+            type: 'line',
+            data: sale,
+            symbolSize: 1,
+            areaStyle: {
+                color: '#EDF6FC',
+            }
+        }, {
+            name: '销售回款',
+            type: 'line',
+            data: saleBack,
+            symbolSize: 1,
+            areaStyle: {
+                color: '#FBEDEF',
+            }
+        }]);
+        return {
+            color: [
+                '#64B0E4',
+                '#FF1038'
+            ],
+            tooltip: {
+                trigger: 'axis',
+                formatter: function (params, ticket, callback) {
+                    var name = '',
+                    series = [];
 
-    onSeriesTooltipRender: function (tooltip, record, item) {
-        tooltip.setHtml(record.get('x') + '月: ' + Ext.util.Format.number(record.get(item.series.getYField()), '0,000.00') + '万元');
-    },
+                    for(var x = 0; x < params.length; x++) {
+                        var p = params[x],
+                        marker = p.marker,
+                        seriesName = p.seriesName,
+                        name = p.name,
+                        value = p.value;
 
-    categoryRender: function(axis, label, layoutContext, lastLabel) {
-        return label + '月';
-    },
+                        value = saas.util.BaseUtil.numberFormat(value, 4, true);
 
-    itemhighlightchange: function(chart, newHighlightItem, oldHighlightItem) {
-        this.setSeriesLineWidth(newHighlightItem, 4);
-        this.setSeriesLineWidth(oldHighlightItem, 2);
-    },
+                        series.push(marker + seriesName + ': ' + value);
+                    }
 
-    setSeriesLineWidth: function (item, lineWidth) {
-        console.log('xxxx');
-        if (item) {
-            item.series.setStyle({
-                lineWidth: lineWidth
-            });
+                    return name + ': ' + '<br/>' + series.join('<br/>');
+                }
+            },
+            legend: {
+                left: 0,
+                data: ['销售额', '销售回款'],
+                icon: 'rect',
+                itemWidth: 10,
+                itemHeight: 2
+            },
+            grid: {
+                left: 0,
+                right: 16,
+                bottom: 0,
+                top: 40,
+                borderColor: '#E5EAEF',
+                containLabel: true
+            },
+            xAxis: {
+                type: 'category',
+                boundaryGap: false,
+                data: fields,
+                axisLine: {
+                    lineStyle: {
+                        color: '#E5EAEF',
+                    }
+                },
+                axisLabel: {
+                    color: '#485465'
+                },
+            },
+            yAxis: {
+                type: 'value',
+                axisLine: {
+                    lineStyle: {
+                        color: '#E5EAEF',
+                    }
+                },
+                splitLine: {
+                    lineStyle: {
+                        color: ['#E5EAEF']
+                    }
+                },
+                axisLabel: {
+                    color: '#485465'
+                }
+            },
+            series: data
         }
-    },
-
-});
+    }
+});

+ 80 - 68
frontend/saas-web/app/view/home/charts/StockAmount.js

@@ -4,89 +4,101 @@ Ext.define('saas.view.home.charts.StockAmount', {
 
     id: 'stock_amount',
 
-    bind: {
-        title: '近六月库存金额图(万元)'
-    },
+    title: '近六月库存金额图(万元)',
 
-    initComponent: function() {
+    initComponent: function () {
         var me = this;
 
         Ext.apply(me, {
             items: [{
-                xtype: 'cartesian',
-                colors: [
-                    '#34BAF6'
-                ],
+                xtype: 'echartsbase',
                 bind: {
-                    insetPadding: '{insetPadding}',
                     store: '{stock_amount}',
                 },
-                axes: [{
-                    // title: {
-                    //     text: '月',
-                    //     fontSize: 14,
-                    // },
-                    type: 'category',
-                    fields: ['x'],
-                    position: 'bottom',
-                    label: {
-                        fontSize: '12px',
-                        fillStyle: '#485465'
-                    },
-                    style: {
-                        fill: '#E5EAEF',
-                        strokeStyle: 'transparent'
-                    },
-                    renderer: me.categoryRender
-                },{
-                    type: 'numeric',
-                    fields: ['y'],
-                    position: 'left',
-                    grid: {
-                        even: {
-                            stroke: '#E5EAEF',
-                        },
-                        odd: {
-                            stroke: '#E5EAEF',
-                        }
-                    },
-                    label: {
-                        fontSize: '12px',
-                        fillStyle: '#485465'
-                    },
-                    style: {
-                        fill: '#fff',
-                        strokeStyle: 'transparent'
-                    },
-                }],
-                series: [{
-                    type: 'bar',
-                    xField: 'x',
-                    yField: ['y'],
-                    tooltip: {
-                        trackMouse: true,
-                        renderer: me.onBarTipRender
-                    },
-                    bind: {
-                        style: {
-                            lineWidth: 0,
-                            strokeStyle: 'transparent',
-                            maxBarWidth: '{maxBarWidth}',
-                        },
-                    },
-                }]
+                createOption: me.createOption
             }]
         });
 
         me.callParent(arguments);
     },
 
-    onBarTipRender: function (tooltip, record, item) {
-        tooltip.setHtml(record.get('x') + '月: ' + Ext.util.Format.number(record.get('y'), '0,000.00') + '万元');
-    },
+    createOption: function (store) {
+        var fields = [],
+            data = [];
+
+        store.each(function (d) {
+            var d = d.data;
+            fields.push(d.x + '月');
+            data.push(d.y);
+        });
+
+        return {
+            color: [
+                '#34BAF6'
+            ],
+            tooltip: {
+                trigger: 'axis',
+                formatter: function (params, ticket, callback) {
+                    var name = '',
+                    series = [];
+
+                    for(var x = 0; x < params.length; x++) {
+                        var p = params[x],
+                        marker = p.marker,
+                        seriesName = p.seriesName,
+                        name = p.name,
+                        value = p.value;
+
+                        value = saas.util.BaseUtil.numberFormat(value, 4, true);
 
-    categoryRender: function(axis, label, layoutContext, lastLabel) {
-        return label + '月';
+                        series.push(marker + ': ' + value);
+                    }
+
+                    return name + ': ' + '<br/>' + series.join('<br/>');
+                }
+            },
+            grid: {
+                left: 0,
+                right: 0,
+                bottom: 0,
+                top: 10,
+                borderColor: '#E5EAEF',
+                containLabel: true
+            },
+            xAxis: {
+                type: 'category',
+                data: fields,
+                axisLine: {
+                    lineStyle: {
+                        color: '#E5EAEF',
+                    }
+                },
+                axisLabel: {
+                    color: '#485465'
+                },
+            },
+            yAxis: {
+                type: 'value',
+                axisLine: {
+                    lineStyle: {
+                        color: '#E5EAEF',
+                    }
+                },
+                splitLine: {
+                    lineStyle: {
+                        color: ['#E5EAEF']
+                    }
+                },
+                axisLabel: {
+                    color: '#485465'
+                }
+            },
+            series: [{
+                type: 'bar',
+                barWidth: 25,
+                data: data
+            }]
+        }
     }
 
 });

+ 0 - 1
frontend/saas-web/app/view/home/infoCardList/InfoList.js

@@ -36,7 +36,6 @@ Ext.define('saas.view.home.infoCardList.InfoList', {
             },
             viewConfig: {
                 deferEmptyText: false,
-                emptyText: '无数据',
                 listeners: {
                     itemcontextmenu: function(view, rec, node, index, e) {
                         e.stopEvent();

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

@@ -133,7 +133,7 @@ Ext.define('saas.view.main.Main', {
                         html:'<img class="x-img x-box-item x-toolbar-item x-img-header" style="height:35px;width:35px;margin-top: 6px;margin-left: 14px;" src="{avatarUrl}" alt="">'
                     }, 
                     menu: {
-                        height: 98,
+                        height: 132,
                         cls:'x-main-menu2 sa-nav-menu', 
                         items: [ {  
                             text: '账户中心',
@@ -145,6 +145,10 @@ Ext.define('saas.view.main.Main', {
                             text: '意见反馈',
                             iconCls:'x-fa fa-comment-o sa-navicon',
                             handler:'feedbackMsg'
+                        }, {  
+                            text: '加入邀请',
+                            iconCls:'x-fa fa-handshake-o sa-navicon',
+                            handler:'invitation'
                         }, {
                             text: '退出',
                             iconCls:'x-fa fa-power-off sa-navicon',

+ 1 - 13
frontend/saas-web/app/view/stock/inventory/EditDataList.js

@@ -214,18 +214,6 @@ Ext.define('saas.view.stock.inventory.EditDataList', {
         }  
     }],
 
-    listeners:{
-        boxready: function(grid, width, height, eOpts) {
-            var store = grid.getStore(),
-            gridBodyBox = grid.body.dom.getBoundingClientRect(),
-            gridBodyBoxHeight = gridBodyBox.height;
-
-            var pageSize = Math.floor(gridBodyBoxHeight / 33);
-
-            store.setPageSize(pageSize);
-        }
-    },
-
     initComponent: function() {
         var me = this;
         if(me.columns){
@@ -304,7 +292,7 @@ Ext.define('saas.view.stock.inventory.EditDataList', {
                     keydown: {
                         fn: function(th, e, eOpts) {
                             if(e.keyCode == 13) {
-                                grid.store.load();
+                                grid.onbuild();
                             }
                         }
                     }

+ 2 - 2
frontend/saas-web/app/view/sys/account/DataList.js

@@ -23,8 +23,8 @@ Ext.define('saas.view.sys.account.DataList', {
         name: 'mobile',
         xtype: 'textfield',
         emptyText : '手机号码',
-        regex:/^1(3|4|5|7|8|9)\d{9}$/,
-        regexText:'请输入正确的手机号码'
+        // regex:/^1(3|4|5|7|8|9)\d{9}$/,
+        // regexText:'请输入正确的手机号码'
     },{
         xtype:'button',
         text:'查询',

+ 2 - 2
frontend/saas-web/app/view/sys/account/EditWindow.js

@@ -47,8 +47,8 @@ Ext.define('saas.view.sys.account.EditWindow', {
             },{
                 xtype:'textfield',
                 fieldLabel: '手机号码',
-                regex:/^1(3|4|5|7|8|9)\d{9}$/,
-                regexText:'请输入正确的手机号码',
+                // regex:/^1(3|4|5|7|8|9)\d{9}$/,
+                // regexText:'请输入正确的手机号码',
                 name: 'mobile',
                 readOnly:true,
                 editable:false,

+ 2 - 2
frontend/saas-web/app/view/sys/config/FormPanel.js

@@ -67,8 +67,8 @@ Ext.define('saas.view.sys.config.FormPanel', {
         bind:'{tel}',
         xtype: 'textfield',
         name: 'tel',
-        regex:/^1(3|4|5|7|8|9)\d{9}$/,
-        regexText:'请输入正确的手机号码',
+        // regex:/^1(3|4|5|7|8|9)\d{9}$/,
+        // regexText:'请输入正确的手机号码',
         fieldLabel: '电话',
         beforeLabelTextTpl : "<font color=\"red\" style=\"position:relative; top:2px;right:2px; font-weight: bolder;\">*</font>",
         allowBlank: false,

+ 2 - 2
frontend/saas-web/app/view/sys/feedback/FormPanel.js

@@ -37,8 +37,8 @@ Ext.define('saas.view.sys.feedback.FormPanel', {
             xtype : "textfield", 
             name : "fb_mobile", 
             fieldLabel : "手机号",
-            regex:/^1(3|4|5|7|8|9)\d{9}$/,
-            regexText:'请输入正确的手机号码',
+            // regex:/^1(3|4|5|7|8|9)\d{9}$/,
+            // regexText:'请输入正确的手机号码',
             value:saas.util.BaseUtil.getCurrentUser() ? saas.util.BaseUtil.getCurrentUser().mobile:null
         }, {
             xtype : "textfield", 

+ 25 - 6
frontend/saas-web/app/view/viewport/ViewportController.js

@@ -18,8 +18,18 @@ Ext.define('saas.view.viewport.ViewportController', {
     },
 
     init: function() {
-        this.originalRoute = saas.getApplication().getDefaultToken();
-        this.restoreSession();
+        var me = this;
+        me.originalRoute = saas.getApplication().getDefaultToken();
+        // electron app
+        if (typeof require === 'function') {
+            me.ipc = require('electron').ipcRenderer;
+            me.ipc.on('session', function(e, session){
+                saas.util.State.set('session', Ext.decode(session));
+                me.restoreSession();
+            });
+        } else {
+            me.restoreSession();
+        }
     },
 
     mainviewboxready: function() {
@@ -72,7 +82,7 @@ Ext.define('saas.view.viewport.ViewportController', {
     handleUnmatchedRoute: function(route) {
         var me = this;
 
-        if (!me.session || !me.session.isValid()) {
+        if ((!me.session || !me.session.isValid()) && !me.ipc) {
             // There is no authenticated user, let's redirect to the login page but keep track
             // of the original route to restore the requested route after user authentication.
             me.originalRoute = route;
@@ -238,14 +248,23 @@ Ext.define('saas.view.viewport.ViewportController', {
      * @param {} session 
      */
     syncSessionToPortal: function(session) {
-        const frame = window.frames[window.frames.length - 1];
-        frame.postMessage(session ? JSON.stringify(session.data) : '', '*');
+        var sessionStr = session ? JSON.stringify(session) : '';
+        if (this.ipc) {
+            this.ipc.send('session.change', sessionStr);
+        } else {
+            const frame = window.frames[window.frames.length - 1];
+            frame.postMessage(sessionStr, '*');
+        }
     },
     /**
      * 跳转门户
      */
     redirectPortal: function() {
-        window.location.href = Ext.manifest.server.accountCenter;
+        if (this.ipc) {
+            // window.close();
+        } else {
+            window.location.href = Ext.manifest.server.accountCenter;
+        }
     }
 });
 

BIN
frontend/saas-web/electron/build/icon.icns


BIN
frontend/saas-web/electron/build/icon.ico


BIN
frontend/saas-web/electron/build/icons/48x48.png


+ 2 - 0
frontend/saas-web/electron/dev-app-update.yml

@@ -0,0 +1,2 @@
+provider: generic
+url: http://127.0.0.1/saas/

BIN
frontend/saas-web/electron/images/icon.ico


+ 79 - 2
frontend/saas-web/electron/login.html

@@ -2,13 +2,75 @@
 <html lang="zh_CN">
     <head>
         <title>账户登录 - U企云服</title>
+        <link rel="icon" href="./images/icon.ico" type="image/x-icon">
         <style>
             body {
                 margin: 0;
+                overflow: hidden;
             }
             iframe {
                 border: 0;
             }
+            .loading-wrap {
+                position: absolute;
+                background-color: #fff;
+                width: 100%;
+                height: 100%;
+                text-align: center;
+                z-index: 1;
+            }
+            .loading{
+                display: inline-block;
+                width: 150px;
+                height: 15px;
+                margin: 0 auto;
+                margin-top: 150px;
+            }
+            .loading span{
+                display: inline-block;
+                width: 15px;
+                height: 100%;
+                margin-right: 5px;
+                border-radius: 50%;
+                background: #34baf6;
+                -webkit-animation: load 1.04s ease infinite;
+            }
+            .loading span:last-child{
+                margin-right: 0px; 
+            }
+            @-webkit-keyframes load{
+                0%{
+                    opacity: 1;
+                    -webkit-transform: scale(1.3);
+                }
+                100%{
+                    opacity: 0.2;
+                    -webkit-transform: scale(.3);
+                }
+            }
+            .loading span:nth-child(1){
+                -webkit-animation-delay:0.13s;
+            }
+            .loading span:nth-child(2){
+                -webkit-animation-delay:0.26s;
+            }
+            .loading span:nth-child(3){
+                -webkit-animation-delay:0.39s;
+            }
+            .loading span:nth-child(4){
+                -webkit-animation-delay:0.52s;
+            }
+            .loading span:nth-child(5){
+                -webkit-animation-delay:0.65s;
+            }
+            .message {
+                position: absolute;
+                bottom: 150px;
+                left: 0;
+                width: 100%;
+                text-align: center;
+                color: #9c9c9c;
+            }
         </style>
         <script src="./lib/sockjs.min.js"></script>
         <script src="./lib/stomp.min.js"></script>
@@ -40,6 +102,18 @@
         </script>
     </head>
     <body>
+        <div class="loading-wrap">
+            <div class="loading">
+                <span></span>
+                <span></span>
+                <span></span>
+                <span></span>
+                <span></span>
+            </div>
+            <div class="message">
+                正在读取网络文件,请稍等
+            </div>
+        </div>
         <script>
             const ipc = require('electron').ipcRenderer;
             var clientId = Math.random().toString(36).substr(2);
@@ -49,12 +123,15 @@
                 session.account = account;
                 ipc.send('session.change', JSON.stringify(session));
             });
-            var frame = document.createElement("iframe");
+            var loading = document.querySelector('.loading-wrap'), frame = document.createElement("iframe");
             frame.setAttribute("src", "https://sso.ubtob.com/sassLogin?appId=sp&baseUrl=" + 
                 encodeURIComponent('https://saas-api.usoftchina.com/api/auth/sso/callback/' + clientId));
             frame.setAttribute("width", "430");
-            frame.setAttribute("height", "504");
+            frame.setAttribute("height", "539");
             document.body.appendChild(frame);
+            frame.onload = function() {
+                loading.style.display = 'none';
+            };
         </script>       
     </body>
 </html>

+ 0 - 32
frontend/saas-web/electron/main.dev.js

@@ -1,32 +0,0 @@
-const { app, BrowserWindow } = require('electron');
-let mainWindow;
-
-function createWindow () {
-    mainWindow = new BrowserWindow({ width: 1280, height: 720, show: false });
-    mainWindow.once('ready-to-show', function(){
-        mainWindow.maximize();
-        mainWindow.show();
-    });
-    mainWindow.loadURL('http://127.0.0.1:1841/');
-
-    mainWindow.webContents.openDevTools();
-
-    mainWindow.on('closed', function () {
-        mainWindow = null;
-    });
-}
-
-app.on('ready', createWindow);
-
-// Quit when all windows are closed, except for Mac users
-app.on('window-all-closed', function () {
-    if (process.platform !== 'darwin') {
-        app.quit()
-    }
-});
-
-app.on('activate', function () {
-    if (mainWindow === null) {
-        createWindow();
-    }
-});

+ 111 - 36
frontend/saas-web/electron/main.js

@@ -1,8 +1,14 @@
-const { app, BrowserWindow, ipcMain } = require('electron');
+const electron = require('electron');
+const app = electron.app;
+const BrowserWindow = electron.BrowserWindow;
+const ipcMain = electron.ipcMain;
+const globalShortcut = electron.globalShortcut;
+const { autoUpdater } = require('electron-updater');
 const path = require('path');
 const url = require('url');
-const isLocal = process.argv[process.argv.length - 1] === 'local';
-const extDir = isLocal ? '../build/production/saas' : 'dist';
+const profile = process.argv[process.argv.length - 1];
+const extDir = profile == 'local' ? '../build/production/saas' : 'dist';
+let updateWindow;
 let loginWindow;
 let mainWindow;
 
@@ -10,66 +16,135 @@ let mainWindow;
 ipcMain.on('session.change', (event, arg) => {
     if (arg) {
         loginWindow && loginWindow.close();
-        createMainWindow(arg);
+        if (!mainWindow) {
+			createMainWindow();
+		}
+		if (!mainWindow.isVisible()) {
+			loadMainContents(arg);
+		}
     } else {
-        mainWindow && mainWindow.close();
-        createLoginWindow();
+        if (mainWindow) {
+            mainWindow.hide();
+            mainWindow.webContents.reload();
+        }
+        !loginWindow && createLoginWindow(true);
     }
 });
-
-function createLoginWindow() {
-    loginWindow = new BrowserWindow({ width: 453, height: 513, fullscreenable: false, maximizable: false, resizable: false });
+function sendUpdateMessage(channel, message) {
+    if (updateWindow.webContents.isLoading()) {
+        updateWindow.webContents.on("did-finish-load", function() {
+            updateWindow.webContents.send(channel, message);
+        });
+    } else {
+        updateWindow.webContents.send(channel, message);
+    }
+}
+autoUpdater.on('error', function (error) {
+    loginWindow.show();
+	// 预加载主页
+    createMainWindow(false);
+    updateWindow && updateWindow.close();
+});
+autoUpdater.on('update-available', function (info) {
+    updateWindow && updateWindow.show();
+    sendUpdateMessage('message', info);
+});
+autoUpdater.on('update-not-available', function (info) {
+    loginWindow.show();
+	// 预加载主页
+    createMainWindow(false);
+    updateWindow && updateWindow.close();
+});
+// 下载进度
+autoUpdater.on('download-progress', function (progressObj) {
+    sendUpdateMessage('downloadProgress', progressObj);
+});
+autoUpdater.on('update-downloaded', function () {
+    // 下载完自动安装
+    autoUpdater.quitAndInstall();
+});
+// 自动更新窗口
+function createUpdateWindow() {
+    updateWindow = new BrowserWindow({ width: 453, height: 538, frame: false, show: false });
+    updateWindow.loadURL(url.format({
+        pathname: path.join(__dirname, 'update.html'),
+        protocol: 'file:',
+        slashes: true
+    }));
+    updateWindow.on('closed', function () {
+        updateWindow = null;
+    });
+    autoUpdater.checkForUpdates();
+    // updateWindow.webContents.on("did-finish-load", function() {
+    //     autoUpdater.checkForUpdates();
+    // });
+}
+// 登录窗口
+function createLoginWindow(show) {
+    loginWindow = new BrowserWindow({ width: 453, height: 538, show: !!show, title: '账户登录 - U企云服', fullscreenable: false, maximizable: false, resizable: false });
     loginWindow.loadURL(url.format({
         pathname: path.join(__dirname, 'login.html'),
         protocol: 'file:',
         slashes: true
     }));
 
-    if (isLocal) {
-        loginWindow.webContents.openDevTools();
-    }
-
     loginWindow.on('closed', function () {
         loginWindow = null;
+		if (mainWindow && !mainWindow.isVisible()) {
+            mainWindow.close();
+        }
     });
 }
-
-function createMainWindow (session) {
-    mainWindow = new BrowserWindow({ width: 1280, height: 720, show: false });
-    mainWindow.once('ready-to-show', function(){
-        mainWindow.maximize();
-        mainWindow.show();
-    });
-    mainWindow.loadURL(url.format({
-        pathname: path.join(__dirname, extDir + '/index.html'),
-        protocol: 'file:',
-        slashes: true
-    }));
-
-    if (isLocal) {
-        mainWindow.webContents.openDevTools();
+// 主窗口
+function createMainWindow (show) {
+    const electronScreen = electron.screen;
+    const size = electronScreen.getPrimaryDisplay().workAreaSize;
+    mainWindow = new BrowserWindow({ width: size.width, height: size.height, show: !!show });
+	if (profile == 'dev') {
+        mainWindow.loadURL('http://127.0.0.1:1841/');
+    } else {
+        mainWindow.loadURL(url.format({
+            pathname: path.join(__dirname, extDir + '/index.html'),
+            protocol: 'file:',
+            slashes: true
+        }));
     }
-
-    mainWindow.webContents.on("did-finish-load", function() {
-        mainWindow.webContents.executeJavaScript('\
-            localStorage.setItem("app-state-session", decodeURIComponent("' + encodeURIComponent(session) + '"))');
-    });
+    
     mainWindow.on('closed', function () {
         mainWindow = null;
     });
 }
+function loadMainContents(session) {
+    mainWindow.webContents.send("session", session);
+    mainWindow.maximize();
+    mainWindow.show();
+}
 
-app.on('ready', createLoginWindow);
+function onReady() {
+    globalShortcut.register('ctrl+shift+d', function() {
+        const win = BrowserWindow.getFocusedWindow();
+        win && win.webContents.openDevTools();
+    });
+    createUpdateWindow();
+    // 预加载登录页
+    createLoginWindow(false);
+}
+
+app.on('ready', onReady);
+
+app.on('will-quit', function() {
+    globalShortcut.unregisterAll();
+});
 
 // Quit when all windows are closed, except for Mac users
 app.on('window-all-closed', function () {
     if (process.platform !== 'darwin') {
-        app.quit()
+        app.quit();
     }
 });
 
 app.on('activate', function () {
     if (mainWindow === null) {
-        createMainWindow();
+        onReady();
     }
 });

+ 57 - 10
frontend/saas-web/electron/package.json

@@ -1,21 +1,68 @@
 {
-  "name": "saas-client",
-  "version": "1.0.0",
+  "name": "UsoftchinaSaasClient",
+  "version": "0.0.1",
   "description": "saas在线进销存系统",
   "main": "./main.js",
   "scripts": {
-    "dev-start": "electron ./main.dev.js",
-    "prod-start": "electron . local",
+    "dev-start": "electron . dev",
+    "local-start": "electron . local",
     "build": "cd ../ && sencha app build --build prod --destination electron/dist/ --production",
-    "pack-win": "electron-packager . saas --overwrite --asar --platform=win32 --arch=x64 --out=out --ignore=\"(src|docs|out|.gitignore|LICENSE.md|README.md|npm-debug.log|node_modules|.idea|main.dev.js|package-lock.json|yarn.lock)\"",
-    "pack": "npm run build && npm run pack-win"
+    "pack": "npm run build && electron-builder --dir",
+    "dist": "npm run build && electron-builder"
   },
-  "author": "yingp@usoftchina.com",
+  "author": "深圳市优软科技有限公司",
   "license": "ISC",
   "dependencies": {
-    "electron": "^1.8.1"
+    "electron-updater": "^4.0.6"
   },
   "devDependencies": {
-    "electron-packager": "^9.0.1"
+    "electron": "^3.0.11",
+    "electron-builder": "^20.38.3"
+  },
+  "build": {
+    "productName": "U企云服",
+    "appId": "saas.usoftchina.com",
+    "directories": {
+      "output": "out"
+    },
+    "publish": [
+      {
+        "provider": "generic",
+        "url": "https://saas-assets.usoftchina.com"
+      }
+    ],
+    "files": [
+      "dist/**/*",
+      "lib/**/*",
+      "images/**/*",
+      "main.js",
+      "*.html"
+    ],
+    "mac": {
+      "artifactName": "${name}_setup_${version}.${ext}"
+    },
+    "win": {
+      "target": "nsis-web",
+      "artifactName": "${name}_setup_${version}.${ext}"
+    },
+    "linux": {
+      "artifactName": "${name}_setup_${version}.${ext}"
+    }
+  },
+  "nsis": {
+    "oneClick": true,
+    "perMachine": true,
+    "allowElevation": true,
+    "allowToChangeInstallationDirectory": true,
+    "createDesktopShortcut": true,
+    "runAfterFinish": true
+  },
+  "nsisWeb": {
+    "oneClick": true,
+    "perMachine": true,
+    "allowElevation": true,
+    "allowToChangeInstallationDirectory": true,
+    "createDesktopShortcut": true,
+    "runAfterFinish": true
   }
-}
+}

+ 85 - 0
frontend/saas-web/electron/update.html

@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html lang="zh_CN">
+    <head>
+        <title>软件更新 - U企云服</title>
+        <style>
+            body {
+                margin: 0;
+                font-family: 'Microsoft YaHei';
+                font-size: 16px;
+                overflow: hidden;
+            }
+            .block {
+                position: relative;
+                transition: .2s;
+                padding: 24px;
+            }
+            .progress {
+                position: relative;
+                line-height: 1;
+            }
+            .progress-circle {
+                height: 126px; 
+                width: 126px;
+                margin: 103px auto;
+            }
+            .progress-text {
+                position: absolute;
+                top: 50%;
+                left: 0;
+                width: 100%;
+                text-align: center;
+                color: #606266;
+                display: inline-block;
+                vertical-align: middle;
+                line-height: 1;
+                transform: translateY(-50%);
+            }
+            .message {
+                position: absolute;
+                bottom: 20px;
+                left: 0;
+                width: 100%;
+                text-align: center;
+                color: #9c9c9c;
+            }
+        </style>
+    </head>
+    <body>
+        <div class="block">
+            <div class="progress">
+                <div class="progress-circle">
+                    <svg viewBox="0 0 100 100">
+                        <path d="M 50 50 m 0 -47 a 47 47 0 1 1 0 94 a 47 47 0 1 1 0 -94" stroke="#e5e9f2" stroke-width="4.8" fill="none" class="progress-circle-track"></path>
+                        <path d="M 50 50 m 0 -47 a 47 47 0 1 1 0 94 a 47 47 0 1 1 0 -94" stroke-linecap="round" stroke="#20a0ff" stroke-width="4.8" fill="none" class="progress-circle-path" 
+                            style="stroke-dasharray: 299.08px, 299.08px; stroke-dashoffset: 299.08px; transition: stroke-dashoffset 0.6s ease 0s, stroke 0.6s ease 0s;"></path>
+                    </svg>
+                </div>
+                <div class="progress-text">0%</div>
+            </div>
+            <div class="message">
+                <span class="version"></span><span class="action">正在更新</span>,请稍等
+            </div>
+        </div>
+
+        <script>
+            const ipcRenderer = require('electron').ipcRenderer;
+            ipcRenderer.on("message", (event, text) => {
+                document.querySelector('.version').innerHTML = '版本' + text.version;
+            });
+            ipcRenderer.on("downloadProgress", (event, progressObj)=> {
+                const percent = Math.round(progressObj.percent || 0);
+                const pathEl = document.querySelector('.progress-circle-path');
+                pathEl.style.strokeDashoffset = 299.08*(1 - percent/100) + 'px';
+                if (percent >= 100) {
+                    pathEl.style.stroke = '#13ce66';
+                    document.querySelector('.action').innerHTML = '下载完毕,准备安装';
+                } else if (percent >= 50) {
+                    pathEl.style.stroke = '#8e71c7';
+                }
+                const textEl = document.querySelector('.progress-text');
+                textEl.innerHTML = percent >= 100 ? '√' : (percent + '%');
+            });
+        </script>       
+    </body>
+</html>

File diff suppressed because it is too large
+ 515 - 199
frontend/saas-web/electron/yarn.lock


File diff suppressed because it is too large
+ 21 - 0
frontend/saas-web/lib/echarts.common.min.js


+ 5 - 1
frontend/saas-web/overrides/data/Connection.js

@@ -18,7 +18,11 @@ Ext.define('saas.override.data.Connection', {
     privates: {
         parseBasePath: function(basePath) {
             if (Ext.isObject(basePath)) {
-                return basePath[window.location.protocol.split(":")[0]];
+                var protocol = window.location.protocol.split(":")[0];
+                if (protocol === 'file') {
+                    protocol = 'https';
+                }
+                return basePath[protocol];
             }
             return basePath;
         },

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