Browse Source

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

hy 7 years ago
parent
commit
cb9f0a0dcc
39 changed files with 1030 additions and 87 deletions
  1. 6 6
      applications/commons/commons-server/src/main/java/com/usoftchina/saas/commons/service/impl/ExcelServiceImpl.java
  2. 82 0
      applications/operation/operation-auth-server/pom.xml
  3. 6 0
      applications/operation/operation-auth-server/src/main/docker/Dockerfile
  4. 23 0
      applications/operation/operation-auth-server/src/main/java/com/usoftchina/saas/operation/auth/OperationAuthApplication.java
  5. 58 0
      applications/operation/operation-auth-server/src/main/java/com/usoftchina/saas/operation/auth/config/AuthConfig.java
  6. 104 0
      applications/operation/operation-auth-server/src/main/java/com/usoftchina/saas/operation/auth/controller/AuthController.java
  7. 17 0
      applications/operation/operation-auth-server/src/main/java/com/usoftchina/saas/operation/auth/mapper/AuthorizeLogMapper.java
  8. 117 0
      applications/operation/operation-auth-server/src/main/java/com/usoftchina/saas/operation/auth/po/AuthorizeLog.java
  9. 68 0
      applications/operation/operation-auth-server/src/main/java/com/usoftchina/saas/operation/auth/service/AuthorizeCountService.java
  10. 17 0
      applications/operation/operation-auth-server/src/main/java/com/usoftchina/saas/operation/auth/service/AuthorizeLogService.java
  11. 26 0
      applications/operation/operation-auth-server/src/main/java/com/usoftchina/saas/operation/auth/service/impl/AuthorizeLogServiceImpl.java
  12. 86 0
      applications/operation/operation-auth-server/src/main/resources/application.yml
  13. BIN
      applications/operation/operation-auth-server/src/main/resources/auth/pri.key
  14. 12 0
      applications/operation/operation-auth-server/src/main/resources/config/application-docker-dev.yml
  15. 23 0
      applications/operation/operation-auth-server/src/main/resources/config/application-docker-prod.yml
  16. 10 0
      applications/operation/operation-auth-server/src/main/resources/config/application-docker.yml
  17. 115 0
      applications/operation/operation-auth-server/src/main/resources/logback-spring.xml
  18. 9 0
      applications/operation/operation-auth-server/src/main/resources/mapper/AuthorizeLogMapper.xml
  19. 15 0
      applications/operation/operation-server/pom.xml
  20. 20 0
      applications/operation/pom.xml
  21. 1 0
      applications/pom.xml
  22. 4 0
      applications/transfers/transfers-server/pom.xml
  23. 57 0
      applications/transfers/transfers-server/src/main/java/com/usoftchina/saas/transfers/po/BrokerMessagelog.java
  24. 7 0
      base-servers/auth/auth-dto/src/main/java/com/usoftchina/saas/auth/dto/AuthDTO.java
  25. 3 3
      base-servers/auth/auth-server/src/main/java/com/usoftchina/saas/auth/controller/AuthController.java
  26. 8 0
      base-servers/gateway-server/src/main/java/com/usoftchina/saas/gateway/config/AuthFilter.java
  27. 13 0
      base-servers/gateway-server/src/main/resources/application.yml
  28. 16 0
      framework/core/src/main/java/com/usoftchina/saas/utils/RegexpUtils.java
  29. 1 0
      frontend/saas-portal-web/src/components/conenter/addenterprise.vue
  30. 12 31
      frontend/saas-portal-web/src/components/conenter/invitation.vue
  31. 0 0
      frontend/saas-portal-web/static/js/stomp.min.js
  32. 4 6
      frontend/saas-web/app/view/core/dbfind/DbfindTrigger.js
  33. 39 4
      frontend/saas-web/app/view/core/form/SettingWin.js
  34. 4 0
      frontend/saas-web/app/view/core/form/SettingWin.scss
  35. 10 3
      frontend/saas-web/app/view/core/form/SettingWinController.js
  36. 28 13
      frontend/saas-web/app/view/main/Navigation.js
  37. 1 1
      frontend/saas-web/app/view/money/verification/FormPanel.js
  38. 0 12
      frontend/saas-web/app/view/money/verification/FormPanelController.js
  39. 8 8
      frontend/saas-web/app/view/stock/report/Prodiodetail.js

+ 6 - 6
applications/commons/commons-server/src/main/java/com/usoftchina/saas/commons/service/impl/ExcelServiceImpl.java

@@ -177,7 +177,7 @@ public class ExcelServiceImpl implements ExcelService{
                            //取编号字段
                            if (set.isCodefield() && !"".equals(value)) {
                                mainData = new JSONObject();
-                               codeValue = value;
+                               codeValue = RegexpUtils.replaceSpecialCharacter(value);
                                difference = true;
                                validateCode.add(codeValue);
                                dd.setDd_codevalue(codeValue);
@@ -409,12 +409,12 @@ public class ExcelServiceImpl implements ExcelService{
 
     public static Object getCellFormatValue(Cell cell){
         Object cellValue = null;
-        if(cell!=null){
+        if(cell != null){
             //判断cell类型
             switch(cell.getCellType()){
                 case Cell.CELL_TYPE_NUMERIC:{
                     cellValue = String.valueOf(cell.getNumericCellValue());
-                    cellValue = RegexpUtils.replaceSpecialCharacter(cellValue);
+                    cellValue = RegexpUtils.replaceSpecialCharacterNotcodefield(cellValue);
                     //判断是否为INT类型
                     if (Double.valueOf(cellValue.toString()).intValue() - Double.valueOf(cellValue.toString()) == 0) {
                         return cellValue.toString().substring(0, cellValue.toString().indexOf("."));
@@ -426,17 +426,17 @@ public class ExcelServiceImpl implements ExcelService{
                     if(DateUtil.isCellDateFormatted(cell)){
                         //转换为日期格式YYYY-mm-dd
                         cellValue = cell.getDateCellValue();
-                        cellValue = RegexpUtils.replaceSpecialCharacter(cellValue);
+                        cellValue = RegexpUtils.replaceSpecialCharacterNotcodefield(cellValue);
                     }else{
                         //数字
                         cellValue = String.valueOf(cell.getNumericCellValue());
-                        cellValue = RegexpUtils.replaceSpecialCharacter(cellValue);
+                        cellValue = RegexpUtils.replaceSpecialCharacterNotcodefield(cellValue);
                     }
                     break;
                 }
                 case Cell.CELL_TYPE_STRING:{
                     cellValue = cell.getRichStringCellValue().getString();
-                    cellValue = RegexpUtils.replaceSpecialCharacter(cellValue);
+                    cellValue = RegexpUtils.replaceSpecialCharacterNotcodefield(cellValue);
                     break;
                 }
                 default:

+ 82 - 0
applications/operation/operation-auth-server/pom.xml

@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>operation</artifactId>
+        <groupId>com.usoftchina.saas</groupId>
+        <version>1.0.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>operation-auth-server</artifactId>
+    <dependencies>
+        <dependency>
+            <groupId>com.usoftchina.saas</groupId>
+            <artifactId>auth-dto</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.usoftchina.saas</groupId>
+            <artifactId>auth-common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.usoftchina.saas</groupId>
+            <artifactId>account-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.usoftchina.saas</groupId>
+            <artifactId>server-starter</artifactId>
+        </dependency>
+        <!-- db -->
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.mybatis.spring.boot</groupId>
+            <artifactId>mybatis-spring-boot-starter</artifactId>
+        </dependency>
+        <!-- api doc -->
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger-ui</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger2</artifactId>
+        </dependency>
+
+        <!-- sleuth -->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-zipkin</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.amqp</groupId>
+            <artifactId>spring-rabbit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>net.logstash.logback</groupId>
+            <artifactId>logstash-logback-encoder</artifactId>
+        </dependency>
+        <!-- test -->
+        <dependency>
+            <groupId>com.usoftchina.saas</groupId>
+            <artifactId>test-starter</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>com.spotify</groupId>
+                <artifactId>docker-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 6 - 0
applications/operation/operation-auth-server/src/main/docker/Dockerfile

@@ -0,0 +1,6 @@
+FROM frolvlad/alpine-oraclejdk8:slim
+VOLUME /tmp
+ADD operation-auth-server-1.0.0-SNAPSHOT.jar app.jar
+RUN sh -c 'touch /app.jar'
+ENV JAVA_OPTS=""
+ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]

+ 23 - 0
applications/operation/operation-auth-server/src/main/java/com/usoftchina/saas/operation/auth/OperationAuthApplication.java

@@ -0,0 +1,23 @@
+package com.usoftchina.saas.operation.auth;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+
+/**
+ * @author yingp
+ * @date 2019/1/3
+ */
+@SpringBootApplication
+@EnableEurekaClient
+@EnableFeignClients(basePackages = {
+        "com.usoftchina.saas.account.api"
+})
+@MapperScan(basePackages = "com.usoftchina.saas.operation.auth.mapper")
+public class OperationAuthApplication {
+    public static void main(String[] args) {
+        SpringApplication.run(OperationAuthApplication.class, args);
+    }
+}

+ 58 - 0
applications/operation/operation-auth-server/src/main/java/com/usoftchina/saas/operation/auth/config/AuthConfig.java

@@ -0,0 +1,58 @@
+package com.usoftchina.saas.operation.auth.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+import java.util.List;
+
+/**
+ * @author yingp
+ * @date 2019/1/3
+ */
+@ConfigurationProperties("auth")
+public class AuthConfig {
+    private String privateKey;
+    private String authHeader = "Authorization";
+    private List<Long> companies;
+    private int expire = 18000;
+    private int maxErrors = 5;
+
+    public String getPrivateKey() {
+        return privateKey;
+    }
+
+    public void setPrivateKey(String privateKey) {
+        this.privateKey = privateKey;
+    }
+
+    public String getAuthHeader() {
+        return authHeader;
+    }
+
+    public void setAuthHeader(String authHeader) {
+        this.authHeader = authHeader;
+    }
+
+    public List<Long> getCompanies() {
+        return companies;
+    }
+
+    public void setCompanies(List<Long> companies) {
+        this.companies = companies;
+    }
+
+    public int getExpire() {
+        return expire;
+    }
+
+    public void setExpire(int expire) {
+        this.expire = expire;
+    }
+
+    public int getMaxErrors() {
+        return maxErrors;
+    }
+
+    public void setMaxErrors(int maxErrors) {
+        this.maxErrors = maxErrors;
+    }
+}

+ 104 - 0
applications/operation/operation-auth-server/src/main/java/com/usoftchina/saas/operation/auth/controller/AuthController.java

@@ -0,0 +1,104 @@
+package com.usoftchina.saas.operation.auth.controller;
+
+import com.usoftchina.saas.account.api.AccountApi;
+import com.usoftchina.saas.account.dto.AccountDTO;
+import com.usoftchina.saas.account.dto.CompanyBaseDTO;
+import com.usoftchina.saas.auth.common.jwt.JwtHelper;
+import com.usoftchina.saas.auth.common.jwt.JwtInfo;
+import com.usoftchina.saas.auth.common.jwt.JwtToken;
+import com.usoftchina.saas.auth.dto.AuthDTO;
+import com.usoftchina.saas.auth.dto.TokenDTO;
+import com.usoftchina.saas.base.Result;
+import com.usoftchina.saas.cache.CacheKeyHelper;
+import com.usoftchina.saas.exception.ExceptionCode;
+import com.usoftchina.saas.operation.auth.config.AuthConfig;
+import com.usoftchina.saas.operation.auth.po.AuthorizeLog;
+import com.usoftchina.saas.operation.auth.service.AuthorizeCountService;
+import com.usoftchina.saas.operation.auth.service.AuthorizeLogService;
+import com.usoftchina.saas.utils.BeanMapper;
+import com.usoftchina.saas.utils.CollectionUtils;
+import com.usoftchina.saas.utils.RedisUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Optional;
+
+/**
+ * @author yingp
+ * @date 2019/1/3
+ */
+@RestController
+@RequestMapping
+@EnableConfigurationProperties(AuthConfig.class)
+public class AuthController {
+
+    @Autowired
+    private AccountApi accountApi;
+
+    @Autowired
+    private AuthConfig authConfig;
+
+    @Autowired
+    private AuthorizeCountService authorizeCountService;
+
+    @Autowired
+    private AuthorizeLogService authorizeLogService;
+
+    /**
+     * 登录认证获取token
+     *
+     * @param username
+     * @param password
+     * @return
+     */
+    @PostMapping("/authorize")
+    public Result<AuthDTO> authorize(HttpServletRequest request, @RequestParam String username, @RequestParam String password) {
+        // 非法操作(登录失败次数过多...)导致被冻结
+        if (authorizeCountService.isFrozen(username)) {
+            return Result.error(ExceptionCode.AUTH_FROZEN);
+        }
+        Result<AccountDTO> result = accountApi.validByUsernameAndPwd(username, password);
+        if (result.isSuccess()) {
+            authorizeCountService.clear(username);
+
+            AccountDTO accountDTO = result.getData();
+            if (!CollectionUtils.isEmpty(accountDTO.getCompanies())) {
+                return Result.error(ExceptionCode.USER_NOT_ENABLE);
+            }
+            // 是否绑定到了允许登录运营系统的公司
+            Optional<CompanyBaseDTO> companyDTO = accountDTO.getCompanies().stream()
+                    .filter(c -> authConfig.getCompanies().stream().anyMatch(id -> id.equals(c.getId())))
+                    .findFirst();
+            if (!companyDTO.isPresent()) {
+                return Result.error(ExceptionCode.USER_NOT_ENABLE);
+            }
+            Long companyId = companyDTO.get().getId();
+            String appId = "operation";
+
+            JwtInfo info = new JwtInfo(appId, companyId, accountDTO.getId(), accountDTO.getUsername(), accountDTO.getRealname());
+            JwtToken jwtToken = JwtHelper.generateToken(info, authConfig.getPrivateKey(), authConfig.getExpire());
+            TokenDTO tokenDTO = BeanMapper.map(jwtToken, TokenDTO.class);
+            // 登录成功记入redis
+            String key = CacheKeyHelper.generatePublicKey(tokenDTO.getToken());
+            RedisUtil.set(key, info, authConfig.getExpire());
+            // 登录日志
+            authorizeLogService.save(AuthorizeLog.from(request)
+                    .setAccountId(accountDTO.getId())
+                    .setAppId(appId).build());
+            return Result.success(new AuthDTO(tokenDTO, accountDTO, companyId));
+        } else {
+            // 失败次数超过最大限制
+            if (authorizeCountService.increaseAndGet(username) > authConfig.getMaxErrors()) {
+                return Result.error(ExceptionCode.AUTH_MAX_ERRORS);
+            }
+        }
+        return Result.error(result.getCode(), result.getMessage());
+    }
+
+
+}

+ 17 - 0
applications/operation/operation-auth-server/src/main/java/com/usoftchina/saas/operation/auth/mapper/AuthorizeLogMapper.java

@@ -0,0 +1,17 @@
+package com.usoftchina.saas.operation.auth.mapper;
+
+import com.usoftchina.saas.operation.auth.po.AuthorizeLog;
+
+/**
+ * @author yingp
+ * @date 2018/11/6
+ */
+public interface AuthorizeLogMapper {
+    /**
+     * 保存
+     *
+     * @param authorizeLog
+     * @return
+     */
+    int insert(AuthorizeLog authorizeLog);
+}

+ 117 - 0
applications/operation/operation-auth-server/src/main/java/com/usoftchina/saas/operation/auth/po/AuthorizeLog.java

@@ -0,0 +1,117 @@
+package com.usoftchina.saas.operation.auth.po;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @author yingp
+ * @date 2018/11/6
+ */
+public class AuthorizeLog implements Serializable{
+    private Long id;
+    private Long accountId;
+    private String clientIp;
+    private String userAgent;
+    private Date loginTime;
+    private String appId;
+
+    public AuthorizeLog() {
+    }
+
+    public AuthorizeLog(Long accountId, String clientIp, String userAgent, String appId) {
+        this.accountId = accountId;
+        this.clientIp = clientIp;
+        this.userAgent = userAgent;
+        this.loginTime = new Date();
+        this.appId = appId;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Long getAccountId() {
+        return accountId;
+    }
+
+    public void setAccountId(Long accountId) {
+        this.accountId = accountId;
+    }
+
+    public String getClientIp() {
+        return clientIp;
+    }
+
+    public void setClientIp(String clientIp) {
+        this.clientIp = clientIp;
+    }
+
+    public String getUserAgent() {
+        return userAgent;
+    }
+
+    public void setUserAgent(String userAgent) {
+        this.userAgent = userAgent;
+    }
+
+    public Date getLoginTime() {
+        return loginTime;
+    }
+
+    public void setLoginTime(Date loginTime) {
+        this.loginTime = loginTime;
+    }
+
+    public String getAppId() {
+        return appId;
+    }
+
+    public void setAppId(String appId) {
+        this.appId = appId;
+    }
+
+    public static Builder from(HttpServletRequest request) {
+        return new Builder(request);
+    }
+
+    public static class Builder {
+        private Long accountId;
+        private String clientIp;
+        private String userAgent;
+        private String appId;
+
+        public Builder(HttpServletRequest request) {
+            this.clientIp = request.getRemoteAddr();
+            this.userAgent = request.getHeader("User-Agent");
+        }
+
+        public Builder setAccountId(Long accountId) {
+            this.accountId = accountId;
+            return this;
+        }
+
+        public Builder setClientIp(String clientIp) {
+            this.clientIp = clientIp;
+            return this;
+        }
+
+        public Builder setUserAgent(String userAgent) {
+            this.userAgent = userAgent;
+            return this;
+        }
+
+        public Builder setAppId(String appId) {
+            this.appId = appId;
+            return this;
+        }
+
+        public AuthorizeLog build() {
+            return new AuthorizeLog(accountId, clientIp, userAgent, appId);
+        }
+    }
+}

+ 68 - 0
applications/operation/operation-auth-server/src/main/java/com/usoftchina/saas/operation/auth/service/AuthorizeCountService.java

@@ -0,0 +1,68 @@
+package com.usoftchina.saas.operation.auth.service;
+
+import com.usoftchina.saas.cache.CacheKeyHelper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Service;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 登录失败记录
+ *
+ * @author yingp
+ * @date 2018/11/6
+ */
+@Service
+public class AuthorizeCountService {
+
+    @Autowired
+    private StringRedisTemplate redisTemplate;
+
+    @Value("${auth.max-errors:5}")
+    private int maxErrors;
+
+    /**
+     * 账户锁定时间
+     */
+    @Value("${auth.error-lock-time:30}")
+    private int lockTime;
+
+    /**
+     * 记录一次
+     *
+     * @param username
+     * @return
+     */
+    public Long increaseAndGet(String username) {
+        String key = generateKey(username);
+        Long value = redisTemplate.opsForValue().increment(key, 1);
+        redisTemplate.expire(key, lockTime, TimeUnit.MINUTES);
+        return value;
+    }
+
+    private String generateKey(String username) {
+        return CacheKeyHelper.generatePrivateKey("auth", "authorize", username);
+    }
+
+    /**
+     * 清零
+     *
+     * @param username
+     */
+    public void clear(String username) {
+        redisTemplate.delete(generateKey(username));
+    }
+
+    /**
+     * 账户是否冻结
+     *
+     * @param username
+     * @return
+     */
+    public boolean isFrozen(String username) {
+        Object value = redisTemplate.opsForValue().get(generateKey(username));
+        return null != value && Integer.parseInt(value.toString()) > maxErrors;
+    }
+}

+ 17 - 0
applications/operation/operation-auth-server/src/main/java/com/usoftchina/saas/operation/auth/service/AuthorizeLogService.java

@@ -0,0 +1,17 @@
+package com.usoftchina.saas.operation.auth.service;
+
+import com.usoftchina.saas.operation.auth.po.AuthorizeLog;
+
+/**
+ * @author yingp
+ * @date 2018/11/6
+ */
+public interface AuthorizeLogService {
+    /**
+     * 保存
+     *
+     * @param authorizeLog
+     * @return
+     */
+    boolean save(AuthorizeLog authorizeLog);
+}

+ 26 - 0
applications/operation/operation-auth-server/src/main/java/com/usoftchina/saas/operation/auth/service/impl/AuthorizeLogServiceImpl.java

@@ -0,0 +1,26 @@
+package com.usoftchina.saas.operation.auth.service.impl;
+
+import com.usoftchina.saas.operation.auth.mapper.AuthorizeLogMapper;
+import com.usoftchina.saas.operation.auth.po.AuthorizeLog;
+import com.usoftchina.saas.operation.auth.service.AuthorizeLogService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author yingp
+ * @date 2018/11/6
+ */
+@Service
+public class AuthorizeLogServiceImpl implements AuthorizeLogService {
+
+    @Autowired
+    private AuthorizeLogMapper authorizeLogMapper;
+
+    @Override
+    @Async
+    public boolean save(AuthorizeLog authorizeLog) {
+        return authorizeLogMapper.insert(authorizeLog) > 0;
+    }
+
+}

+ 86 - 0
applications/operation/operation-auth-server/src/main/resources/application.yml

@@ -0,0 +1,86 @@
+spring:
+  profiles:
+    active: dev
+  application:
+    name: operation-auth-server
+  security:
+    user:
+      name: admin
+      password: select111***
+  rabbitmq:
+    host: 10.1.81.75
+    port: 5672
+    virtual-host: dev
+    username: saas
+    password: select123***
+  zipkin:
+    sender:
+      type: rabbit
+    locator:
+      discovery:
+        enabled: true
+  sleuth:
+    sampler:
+      probability: 1.0
+  datasource:
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    url: jdbc:mysql://10.1.81.79:3306/saas_auth?characterEncoding=utf-8&useSSL=false
+    username: root
+    password: select111***
+    hikari:
+      minimum-idle: 5
+      maximum-pool-size: 50
+      idle-timeout: 30000
+      max-lifetime: 1800000
+      connection-timeout: 30000
+  redis:
+    host: 10.1.81.62
+    port: 6379
+  jackson:
+    date-format: yyyy-MM-dd HH:mm:ss
+    time-zone: GMT+8
+eureka:
+  instance:
+    leaseRenewalIntervalInSeconds: 10
+    health-check-url-path: /actuator/health
+    status-page-url-path: /actuator/info
+    prefer-ip-address: true
+    metadata-map:
+      user.name: ${spring.security.user.name}
+      user.password: ${spring.security.user.password}
+  client:
+    registryFetchIntervalSeconds: 5
+    serviceUrl:
+      defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@10.1.81.61:8510/eureka/
+server:
+  port: 9020
+  tomcat:
+    uri-encoding: UTF-8
+management:
+  endpoints:
+    web:
+      exposure:
+        include: "*"
+  endpoint:
+    health:
+      show-details: always
+    shutdown:
+      enabled: true
+    restart:
+      enabled: true
+info:
+  name: '@project.artifactId@'
+  description: '@project.description@'
+  version: '@project.version@'
+  spring-boot-version: '@spring.boot.version@'
+  spring-cloud-version: '@spring.cloud.version@'
+mybatis:
+  type-aliases-package: com.usoftchina.saas.operation.auth.po
+  mapper-locations: classpath:mapper/*.xml
+auth:
+  private-key: auth/pri.key
+  companies:
+    - 71
+ribbon:
+  ReadTimeout: 5000
+  ConnectTimeout: 5000

BIN
applications/operation/operation-auth-server/src/main/resources/auth/pri.key


+ 12 - 0
applications/operation/operation-auth-server/src/main/resources/config/application-docker-dev.yml

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

+ 23 - 0
applications/operation/operation-auth-server/src/main/resources/config/application-docker-prod.yml

@@ -0,0 +1,23 @@
+eureka:
+  instance:
+    hostname: saas-operation-auth-server
+    prefer-ip-address: false
+  client:
+    serviceUrl:
+      defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@saas-eureka-server:8500/eureka/
+spring:
+  rabbitmq:
+    host: 10.10.100.103
+    port: 5672
+    virtual-host: docker
+    username: saas
+    password: select123***
+  datasource:
+    url: jdbc:mysql://10.10.100.18:3306/saas_auth?characterEncoding=utf-8&useSSL=false
+    username: saas
+    password: select111***
+  redis:
+    host: 10.10.100.173
+    port: 6379
+logging:
+  destination: 10.10.100.160:5000

+ 10 - 0
applications/operation/operation-auth-server/src/main/resources/config/application-docker.yml

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

+ 115 - 0
applications/operation/operation-auth-server/src/main/resources/logback-spring.xml

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

+ 9 - 0
applications/operation/operation-auth-server/src/main/resources/mapper/AuthorizeLogMapper.xml

@@ -0,0 +1,9 @@
+<?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.operation.auth.mapper.AuthorizeLogMapper">
+    <insert id="insert">
+        insert into au_authorize_log(app_id,account_id,client_ip,user_agent,login_time)
+        values (#{appId,jdbcType=VARCHAR}, #{accountId,jdbcType=BIGINT}, #{clientIp,jdbcType=VARCHAR},
+        #{userAgent,jdbcType=VARCHAR}, #{loginTime,jdbcType=TIMESTAMP})
+    </insert>
+</mapper>

+ 15 - 0
applications/operation/operation-server/pom.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>operation</artifactId>
+        <groupId>com.usoftchina.saas</groupId>
+        <version>1.0.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>operation-server</artifactId>
+
+
+</project>

+ 20 - 0
applications/operation/pom.xml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>applications</artifactId>
+        <groupId>com.usoftchina.saas</groupId>
+        <version>1.0.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>operation</artifactId>
+    <packaging>pom</packaging>
+    <description>operation system</description>
+    <modules>
+        <module>operation-auth-server</module>
+        <module>operation-server</module>
+    </modules>
+
+</project>

+ 1 - 0
applications/pom.xml

@@ -20,6 +20,7 @@
         <module>document</module>
         <module>commons</module>
         <module>transfers</module>
+        <module>operation</module>
     </modules>
 
 

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

@@ -25,6 +25,10 @@
             <groupId>org.springframework.amqp</groupId>
             <artifactId>spring-rabbit</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-amqp</artifactId>
+        </dependency>
         <dependency>
             <groupId>net.logstash.logback</groupId>
             <artifactId>logstash-logback-encoder</artifactId>

+ 57 - 0
applications/transfers/transfers-server/src/main/java/com/usoftchina/saas/transfers/po/BrokerMessagelog.java

@@ -1,8 +1,65 @@
 package com.usoftchina.saas.transfers.po;
 
+import java.util.Date;
+
 /**
  * @author: guq
  * @create: 2018-12-29 09:46
  **/
 public class BrokerMessagelog {
+
+    private Long id;
+    private String messageId;
+    private String message;
+    private Integer tryCount;
+    private String status;
+    private Date createTime;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getMessageId() {
+        return messageId;
+    }
+
+    public void setMessageId(String messageId) {
+        this.messageId = messageId;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public Integer getTryCount() {
+        return tryCount;
+    }
+
+    public void setTryCount(Integer tryCount) {
+        this.tryCount = tryCount;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
 }

+ 7 - 0
base-servers/auth/auth-dto/src/main/java/com/usoftchina/saas/auth/dto/AuthDTO.java

@@ -33,6 +33,12 @@ public class AuthDTO implements Serializable{
         this.account = account;
     }
 
+    public AuthDTO(TokenDTO token, AccountDTO account, Long companyId) {
+        this.token = token;
+        this.account = account;
+        this.companyId = companyId;
+    }
+
     public AccountDTO getAccount() {
         return account;
     }
@@ -54,6 +60,7 @@ public class AuthDTO implements Serializable{
         return "AuthDTO{" +
                 "token=" + token +
                 ", account=" + account +
+                ", companyId=" + companyId +
                 '}';
     }
 }

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

@@ -94,7 +94,8 @@ public class AuthController {
      * @return
      */
     @PostMapping("/authorize")
-    public Result<AuthDTO> authorize(HttpServletRequest request, @RequestParam String username, @RequestParam String password) {
+    public Result<AuthDTO> authorize(HttpServletRequest request, @RequestParam String username, @RequestParam String password,
+                                     @RequestParam(value = "companyId", required = false) Long companyId) {
         // 非法操作(登录失败次数过多...)导致被冻结
         if (authorizeCountService.isFrozen(username)) {
             return Result.error(ExceptionCode.AUTH_FROZEN);
@@ -104,8 +105,7 @@ public class AuthController {
             authorizeCountService.clear(username);
 
             AccountDTO accountDTO = result.getData();
-            Long companyId = null;
-            if (!CollectionUtils.isEmpty(accountDTO.getCompanies())) {
+            if (null == companyId && !CollectionUtils.isEmpty(accountDTO.getCompanies())) {
                 companyId = accountDTO.getCompanies().get(0).getId();
             }
             // TODO

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

@@ -19,7 +19,9 @@ import com.usoftchina.saas.exception.ExceptionCode;
 import com.usoftchina.saas.gateway.error.PermissionException;
 import com.usoftchina.saas.gateway.util.AntPathRequestMatcher;
 import com.usoftchina.saas.utils.CollectionUtils;
+import com.usoftchina.saas.utils.JsonUtils;
 import com.usoftchina.saas.utils.RedisUtil;
+import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
@@ -57,6 +59,8 @@ public class AuthFilter implements GlobalFilter, Ordered {
     @Autowired
     private AuthApi authApi;
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(AuthFilter.class);
+
     @Override
     public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
         try {
@@ -118,6 +122,8 @@ public class AuthFilter implements GlobalFilter, Ordered {
      * @param accountDTO
      */
     private void checkPermission(ServerHttpRequest request, JwtInfo jwt, AccountDTO accountDTO) {
+        LOGGER.info("JwtInfo: " + JsonUtils.toJsonString(jwt));
+        LOGGER.info("accountDTO:" + JsonUtils.toJsonString(accountDTO));
         if (!accountDTO.isAdmin(jwt.getCompanyId())) {
             // 非管理账户,需要鉴权
             List<UrlResourceDTO> resources = ResourceCache.current().getUrlResources();
@@ -129,6 +135,8 @@ public class AuthFilter implements GlobalFilter, Ordered {
                 }).collect(Collectors.toList());
                 if (!CollectionUtils.isEmpty(permissions)) {
                     Set<Long> resourceIds = accountDTO.getResources(jwt.getAppId(), jwt.getCompanyId());
+                    LOGGER.info("permissions: " + permissions);
+                    LOGGER.info("resourceIds: " + resourceIds);
                     boolean permitted = false;
                     if (null != resourceIds) {
                         // 权限匹配

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

@@ -108,6 +108,18 @@ spring:
         uri: lb:ws://SOCKET-SERVER
         predicates:
         - Path=/ws/**
+      - id: OPERATION-AUTH-SERVER
+        uri: lb://OPERATION-AUTH-SERVER
+        predicates:
+        - Path=/api/oper_auth/**
+        filters:
+        - RewritePath=/api/oper_auth/(?<segment>.*), /$\{segment}
+      - id: OPERATION-SERVER
+        uri: lb://OPERATION-SERVER
+        predicates:
+        - Path=/api/operation/**
+        filters:
+        - RewritePath=/api/operation/(?<segment>.*), /$\{segment}
   redis:
     host: 10.1.81.62
     port: 6379
@@ -193,6 +205,7 @@ auth:
     - /api/commons/share/submit
     - /api/account/role/list/**
     - /api/account/account/share/join
+    - /api/oper_auth/authorize
   cookie:
     name: uid
     secret-key: 0taQcW073Z7G628g5H

+ 16 - 0
framework/core/src/main/java/com/usoftchina/saas/utils/RegexpUtils.java

@@ -13,6 +13,7 @@ public class RegexpUtils {
     private static final String EMAIL_EXP = "^\\w+([-.]\\w+)*@\\w+([-]\\w+)*\\.(\\w+([-]\\w+)*\\.)*[a-z]{2,4}$";
     private static final String SPECCHARACTER_EXP = "[\\\\s~·`!!@#¥$%^……&*(())\\\\-——\\\\-_=+【\\\\[\\\\]】{{}}\\\\|、\\\\\\\\;;::‘'“”\\\",,《<。.》>、/??]";
     private static final String SPECIALCHARACTER_EXP = "[`~!@#$%^&*()+=|{}':;',\\[\\]<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、?\"]";
+    private static final String NOTCODEFIELF_EXP = "[`@#$%^&*|{}':;',\\[\\]/?@#¥%……&*+|【】‘;:”“’。,、?\"]";
     /**
      * 匹配手机号码
      *
@@ -81,4 +82,19 @@ public class RegexpUtils {
         Matcher m = p.matcher(obj.toString().trim());
         return m.replaceAll("");
     }
+
+
+    /**
+     * 特殊字符替换 非编号字段
+     * @param obj
+     * @return
+     */
+    public static String replaceSpecialCharacterNotcodefield(Object obj){
+        if (StringUtils.isEmpty(obj)) {
+            return "";
+        }
+        Pattern p = Pattern.compile(NOTCODEFIELF_EXP);
+        Matcher m = p.matcher(obj.toString().trim());
+        return m.replaceAll("");
+    }
 }

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

@@ -492,6 +492,7 @@ import { setTimeout, clearTimeout } from 'timers';
                                     document.documentElement.scrollTop = 0;
                                     let session = Session.get();
                                     session.account.realname = name;
+                                    session.account.email = email;
                                     Session.set(session);
                                     // this.$router.push({name:'company'})
                                     this.$router.push({path: '/enterprise'});

+ 12 - 31
frontend/saas-portal-web/src/components/conenter/invitation.vue

@@ -2,9 +2,7 @@
     <div class="invitation">
         <div class="zhezhao" v-if="istanchaung"></div>
         <div class="Popup" v-if="istanchaung">
-        <!-- <div class="Popup"> -->
             <div class="shang">
-                <!-- <img src="/static/img/caidian2x.png" alt=""> -->
                 <img src="/static/img/tijiao.png" alt="">
                 <img class="xs" @click="hidden" src="/static/img/assets/chahao.png" alt="">
             </div>
@@ -54,6 +52,7 @@
 <script>
 import Session from '@/utils/session'
 import { setTimeout } from 'timers';
+import { log } from 'util';
     export default {
         data(){
             return {
@@ -170,10 +169,7 @@ import { setTimeout } from 'timers';
                     let phone = this.$refs.phone.value;//手机 
                     this.$ajax({
                         url: this.$url.api+'/api/commons/share/getSmsCode'+`?mobile=${phone}`,//http://192.168.253.31:8560
-                        method:'POST',
-                        headers:{
-                            "Authorization":Session.getToken(),
-                        }
+                        method:'POST'
                     })
                     .then(res=>{
                         if (res.data.success) {
@@ -216,9 +212,6 @@ import { setTimeout } from 'timers';
                             roleId:roleid,
                             validCode:Verification,
                         },
-                        headers:{
-                            "Authorization":Session.getToken(),
-                        }
                     })
                     .then(res=>{
                         if (res.data.success) {
@@ -251,9 +244,6 @@ import { setTimeout } from 'timers';
                 let companyId = this.enterprise.companyId;
                 this.$ajax({
                     url: this.$url.api+'/api/account/role/list/'+companyId,
-                    headers:{
-                        "Authorization":Session.getToken(),
-                    }
                 })
                 .then(res=>{
                     if (res.data.success) {
@@ -261,32 +251,23 @@ import { setTimeout } from 'timers';
                     }
                 })
             },
-            //获取页面参数
-            param(){
+            //同步获取页面参数
+            param: async function () {
                 let url1 = window.location.href;
                 let param = url1.substring(url1.lastIndexOf('=')+1, url1.length);
-                this.$ajax({
+                let data = await this.$ajax({
                     url: this.$url.api+"/api/commons/share/valid/param?param="+param,
                     method:'POST',
                     headers:{
-                        "Authorization":Session.getToken(),
                         "Content-Type":"application/x-www-form-urlencoded",
                     }
-                })
-                .then(res=>{
-                    if (res.data.success) {
-                        this.enterprise = res.data.data;
-                        //获取角色
-                        setTimeout(()=>{
-                            this.role()
-                        },800)
-                    } else {
-                        this.$message.error({
-                            message:res.data.message,
-                            });
-                        this.$router.push({path:'/failure'})
-                    }
-                })
+                });
+                if (data.data.success) {
+                    this.enterprise = data.data.data;
+                    this.role();//获取角色
+                } else {
+                    this.$router.push({path:'/failure'})
+                }
             },
             //关闭弹窗
             hidden(){

File diff suppressed because it is too large
+ 0 - 0
frontend/saas-portal-web/static/js/stomp.min.js


+ 4 - 6
frontend/saas-web/app/view/core/dbfind/DbfindTrigger.js

@@ -255,15 +255,13 @@ Ext.define('saas.view.core.dbfind.DbfindTrigger', {
                             var item = dbfinds[index];
                             var field = me.ownerCt.down('[name=' + item.to + ']');
                             if (field) {
-                                if (field.xtype == 'dbfindtrigger') {
+                                let xtypes = field.getXTypes().split('/');
+                                if (xtypes.indexOf('dbfindtrigger') != -1) {
                                     field.setValue(null);
                                     field.lastTriggerValue = null;
                                 } else {
-                                    if (field.xtype.indexOf('hidden') > -1) {
-                                        field.setValue(0);
-                                    } else {
-                                        field.setValue(null);
-                                    }
+                                    field.setValue(null);
+                                    field.publishState('value', null);
                                 }
                             }
                         }

+ 39 - 4
frontend/saas-web/app/view/core/form/SettingWin.js

@@ -25,7 +25,14 @@ Ext.define('saas.view.core.form.SettingWin', {
             text: '序号',
             dataIndex: 'index',
             align: 'center',
-            width: 80
+            width: 80,
+            renderer: function(v, m, r) {
+                m.tdCls = 'x-cell-index'; 
+                if(r.get('locked')) {
+                    m.tdCls += ' x-cell-index-locek'; 
+                }
+                return v;
+            }
         }, {
             text: '标识名称',
             dataIndex: 'name',
@@ -49,6 +56,22 @@ Ext.define('saas.view.core.form.SettingWin', {
             width: 150,
             editor: {
                 xtype: 'textfield',
+                maxLength: 10,
+                validator: function (val) {
+                    var grid = this.up('grid'),
+                    store = grid.store,
+                    s = grid.getSelection()[0],
+                    errMsg = "显示名称不能重复",
+                    count = 0;
+
+                    store.each(function(r) {
+                        if(s.data.alias != val && r.get('alias') == val) {
+                            count++;
+                        }
+                    });
+
+                    return (!val || count < 1) ? true : errMsg;
+                }
             }
         }, {
             text: '类型',
@@ -154,11 +177,12 @@ Ext.define('saas.view.core.form.SettingWin', {
                             containerScroll: true,
                             dragGroup: 'dd-grid-group',
                             dropGroup: 'dd-grid-group',
-                            dragText: '移动到此位置'
+                            dragText: '移动到此位置',
                         }
                     },
         
                     listeners: {
+                        beforedrop: 'onBeforeDrop',
                         drop: 'onDrop'
                     }
                 },
@@ -172,7 +196,9 @@ Ext.define('saas.view.core.form.SettingWin', {
                         { name: 'alias', type: 'string' },
                         { name: 'type', type: 'string' },
                         { name: 'enable', type: 'boolean' },
-                        { name: 'width', type: 'float'}
+                        { name: 'width', type: 'float'},
+                        { name: 'disabled', type: 'boolean'},
+                        { name: 'locked', type: 'boolean'},
                     ],
                     data: [],
                 }),
@@ -254,7 +280,8 @@ Ext.define('saas.view.core.form.SettingWin', {
                 alias: me.getFieldAlias(item, settype),
                 type: me.getFieldType(item, settype),
                 enable: !item.hidden,
-                width: me.getFieldWidth(item, settype)
+                width: me.getFieldWidth(item, settype),
+                locked: me.getFieldLocked(item, settype)
             }
         });
 
@@ -362,6 +389,14 @@ Ext.define('saas.view.core.form.SettingWin', {
         return width;
     },
 
+    getFieldLocked: function(item, settype) {
+        var locked = false;
+        if(settype != 'main') {
+            locked = !!item.locked;
+        }
+        return locked;
+    },
+
     isContainsAny: function (arr1, arr2) {
         for (var i = 0; i < arr2.length; i++) {
             var a2 = arr2[i];

+ 4 - 0
frontend/saas-web/app/view/core/form/SettingWin.scss

@@ -13,6 +13,10 @@
         font-weight: bold;
     }
 
+    .x-cell-index-locek {
+        opacity: 0.3;
+    }
+
     .x-keyboard-mode .x-grid-item-focused,
     .x-cell-required {
         &>div {

+ 10 - 3
frontend/saas-web/app/view/core/form/SettingWinController.js

@@ -8,18 +8,16 @@ Ext.define('saas.view.core.form.SettingWinController', {
     },
 
     isEnableDisabled: function(view, rowIdx, colIdx, item, record) {
-        return !record.data.allowBlank;
+        return !record.data.allowBlank || record.get('disabled');
     },
 
     onBeforeEdit: function(editor, context, eOpts) {
         let record = context.record,
         column = context.column,
-        disabled = record.get('disabled'),
         type = record.get('type'),
         flag = true;
 
         if(
-            (disabled && column.dataIndex == 'enable') ||
             ['grid'].indexOf(type) != -1 ||
             (['group'].indexOf(type) != -1 && column.dataIndex == 'width')
         ) {
@@ -36,6 +34,15 @@ Ext.define('saas.view.core.form.SettingWinController', {
         }
     },
 
+    onBeforeDrop: function(node, data, overModel, dropPosition, dropHandlers, eOpts) {
+        var fdata = data.records[0].data,
+        tdata = overModel.data,
+        fLocked = fdata.locked,
+        tLocked = tdata.locked;
+        
+        return !fLocked && !tLocked;
+    },
+
     onDrop: function() {
         var me = this,
         win = me.getView(),

+ 28 - 13
frontend/saas-web/app/view/main/Navigation.js

@@ -43,9 +43,22 @@ Ext.define('saas.view.main.Navigation', {
             singleSelect: true,
             itemSelector: '.x-navitem',
             listeners: {
-                itemmouseenter: me.showNavMenu,
-                itemmouseleave: me.hideNavMenu,
-                itemClick: me.clickNavMenu,
+                itemmouseenter: function(navView, record, navItem, index, e, eOpts) {
+                    window.clearTimeout(me.Timer);
+                    me.Timer = setTimeout(function() {
+                        me.showNavMenu(navView, record, navItem, index, e, eOpts);
+                    }, 80);
+                },
+                itemmouseleave: function(view, record, item, index, e, eOpts) {
+                    window.clearTimeout(me.Timer);
+                    me.hideNavMenu(view, record, item, index, e, eOpts);
+                },
+                itemClick: function(navView, record, navItem, index, e, eOpts) {
+                    window.clearTimeout(me.Timer);
+                    me.Timer = setTimeout(function() {
+                        me.showNavMenu(navView, record, navItem, index, e, eOpts);
+                    }, 20);
+                },
                 scope: me
             }
         });
@@ -58,10 +71,10 @@ Ext.define('saas.view.main.Navigation', {
         me.callParent();
     },
 
-    clickNavMenu: function (view, record, item, index, e, eOpts) {
-        var me = this;
-        this.showNavMenu(view, record, item, index, e, eOpts);
-    },
+    // clickNavMenu: function (view, record, item, index, e, eOpts) {
+    //     var me = this;
+    //     this.showNavMenu(view, record, item, index, e, eOpts);
+    // },
 
     showNavMenu: function (navView, record, navItem, index, e, eOpts) {
         var me = this,
@@ -200,15 +213,17 @@ Ext.define('saas.view.main.Navigation', {
 
     hideNavMenu: function (view, record, item, index, e, eOpts) {
         var recData = record.data,
-            cx = e.browserEvent.clientX,
-            cy = e.browserEvent.clientY,
-            itemBox = item.getBoundingClientRect(),
             id = recData.id,
             menuId = 'navMenu-' + id,
-            menu = Ext.getCmp(menuId);
+            menu = Ext.getCmp(menuId),
+            cx, cy, itemBox;
+
+        if (menu) {
+            cx = e.browserEvent.clientX,
+            cy = e.browserEvent.clientY,
+            itemBox = item.getBoundingClientRect();
 
-        if (cx <= itemBox.left || cy <= itemBox.top || (cy >= (itemBox.top + itemBox.height) && cx <= (itemBox.left + itemBox.width - 10))) {
-            if (menu) {
+            if (cx <= itemBox.left || cy <= itemBox.top || (cy >= (itemBox.top + itemBox.height) && cx <= (itemBox.left + itemBox.width - 10))) {
                 menu.hide();
             }
         }

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

@@ -603,7 +603,7 @@ Ext.define('saas.view.money.verification.FormPanel', {
                     }, {
                         xtype: 'hidden',
                         name: 'vc_vendid',
-                        fieldLabel: '供应商ID',
+                        fieldLabel: '供应商',
                         listeners: {
                             change: 'clearDetail1'
                         }

+ 0 - 12
frontend/saas-web/app/view/money/verification/FormPanelController.js

@@ -623,18 +623,6 @@ Ext.define('saas.view.money.verification.FormPanelController', {
         })
         .catch(function(e) {
             form.setLoading(false);
-            // if(res.data) {
-            //     var id = localJson.data.id;
-            //     var code = localJson.data.code;
-                
-            //     form.initId = id;
-
-            //     var newId = form.xtype + '-' + id;
-            //     var newTitle = form._title + '(' + code + ')';
-
-            //     saas.util.BaseUtil.refreshTabTitle(newId, newTitle);
-            //     saas.util.FormUtil.loadData(form);
-            // }
             saas.util.BaseUtil.showErrorToast('审核失败: ' +  e.message);
             form.fireEvent('afteraudit', false, form);
         });

+ 8 - 8
frontend/saas-web/app/view/stock/report/Prodiodetail.js

@@ -53,14 +53,6 @@ Ext.define('saas.view.stock.report.Prodiodetail', {
         text: 'id',
         dataIndex: 'id',
         hidden: true
-    }, {
-        text: '单号',
-        dataIndex: 'pi_inoutno',
-        width: 150
-    }, {
-        text: '业务类型',
-        dataIndex: 'pi_class',
-        width: 100
     }, {
         text: '单据日期',
         dataIndex: 'pi_date',
@@ -78,6 +70,14 @@ Ext.define('saas.view.stock.report.Prodiodetail', {
         renderer: function(v) {
             return saas.util.BaseUtil.numberFormat(v, 0, false);
         }
+    }, {
+        text: '单号',
+        dataIndex: 'pi_inoutno',
+        width: 150
+    }, {
+        text: '业务类型',
+        dataIndex: 'pi_class',
+        width: 100
     }, {
         text: '物料编号',
         dataIndex: 'pd_prodcode',

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