Kaynağa Gözat

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

rainco 7 yıl önce
ebeveyn
işleme
a776a375f3
28 değiştirilmiş dosya ile 724 ekleme ve 26 silme
  1. 2 2
      applications/operation/operation-server/src/main/resources/mapper/AccoutMapper.xml
  2. 2 2
      applications/operation/operation-server/src/main/resources/mapper/CompanyMapper.xml
  3. 1 0
      applications/transfers/pom.xml
  4. 43 0
      applications/transfers/transfers-auth/pom.xml
  5. 15 0
      applications/transfers/transfers-auth/src/main/java/com/usoftchina/saas/transfers/auth/EnableOpenApiAuthClient.java
  6. 15 0
      applications/transfers/transfers-auth/src/main/java/com/usoftchina/saas/transfers/auth/annotation/IgnoreOpenApiAuth.java
  7. 49 0
      applications/transfers/transfers-auth/src/main/java/com/usoftchina/saas/transfers/auth/configuration/OpenApiConfig.java
  8. 29 0
      applications/transfers/transfers-auth/src/main/java/com/usoftchina/saas/transfers/auth/configuration/OpenApiConfiguration.java
  9. 107 0
      applications/transfers/transfers-auth/src/main/java/com/usoftchina/saas/transfers/auth/interceptor/OpenApiAuthInterceptor.java
  10. 4 0
      applications/transfers/transfers-server/pom.xml
  11. 2 0
      applications/transfers/transfers-server/src/main/java/com/usoftchina/saas/transfers/TransfersApplication.java
  12. 2 0
      applications/transfers/transfers-server/src/main/java/com/usoftchina/saas/transfers/controller/TransfersController.java
  13. 12 1
      base-servers/account/account-dto/src/main/java/com/usoftchina/saas/account/dto/CompanyDTO.java
  14. 9 0
      base-servers/account/account-server/src/main/java/com/usoftchina/saas/account/po/Company.java
  15. 2 1
      base-servers/account/account-server/src/main/resources/mapper/CompanyMapper.xml
  16. 26 0
      frontend/operation-web/app/util/BaseUtil.js
  17. 103 0
      frontend/operation-web/app/view/auth/ReLogin.js
  18. 15 0
      frontend/operation-web/app/view/auth/ReLogin.scss
  19. 103 0
      frontend/operation-web/app/view/auth/ReLoginController.js
  20. 1 1
      frontend/operation-web/overrides/data/Connection.js
  21. 3 3
      frontend/saas-portal-web/src/components/conenter/enterprise.vue
  22. 5 5
      frontend/saas-portal-web/src/components/conenter/home.vue
  23. 2 2
      frontend/saas-portal-web/static/css/main.css
  24. 19 0
      frontend/saas-web/app/Application.scss
  25. 2 1
      frontend/saas-web/app/view/main/MainContainerWrap.js
  26. 139 5
      frontend/saas-web/app/view/purchase/quotationList/DataList.js
  27. 7 3
      frontend/saas-web/app/view/purchase/sendQuotation/DataList.js
  28. 5 0
      pom.xml

+ 2 - 2
applications/operation/operation-server/src/main/resources/mapper/AccoutMapper.xml

@@ -44,7 +44,7 @@
         <if test="con != null">
             ${con}
         </if>
-    </where>
+    </where> order by id desc
     </select>
     <select id="getLogin" parameterType="string" resultMap="loginMap">
         SELECT * FROM (select account_id  ,count(account_id) login_num,max(ac_account.realname) username,max(login_time) lastesttime, max(ac_account.mobile) mobile from saas_auth.au_authorize_log left join saas_account.ac_account on account_id= ac_account.id  where login_time >  date_sub(now(),interval 3 MONTH) GROUP BY account_id order by lastesttime desc
@@ -53,7 +53,7 @@
             <if test="con != null">
                 ${con}
             </if>
-        </where>
+        </where>  order by account_id desc
     </select>
 
     <select id="getConpanyAnalyze" parameterType="string" resultMap="companymap">

+ 2 - 2
applications/operation/operation-server/src/main/resources/mapper/CompanyMapper.xml

@@ -14,13 +14,13 @@
     </resultMap>
 
     <select id="findCompanyByCondition" parameterType="string" resultMap="baseMap">
-         select name,business_code,address,tel,fax,realname,mobile,ac_company.create_time,ac_company.uu from saas_account.ac_company
+         select ac_company.id,name,business_code,address,tel,fax,realname,mobile,ac_company.create_time,ac_company.uu from saas_account.ac_company
         left join saas_account.ac_account on ac_account.id = ac_company.creator_id
         <where>
             <if test="con != null">
                 ${con}
             </if>
-        </where>
+        </where> order by id desc
     </select>
 
 

+ 1 - 0
applications/transfers/pom.xml

@@ -17,6 +17,7 @@
         <module>transfers-server</module>
         <module>mall-api</module>
         <module>transfers-dto</module>
+        <module>transfers-auth</module>
     </modules>
 
 </project>

+ 43 - 0
applications/transfers/transfers-auth/pom.xml

@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>transfers</artifactId>
+        <groupId>com.usoftchina.saas</groupId>
+        <version>1.0.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>transfers-auth</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-netflix-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-webmvc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.usoftchina.saas</groupId>
+            <artifactId>auth-common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <scope>compile</scope>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>io.github.openfeign</groupId>
+            <artifactId>feign-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.usoftchina.saas</groupId>
+            <artifactId>account-api</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>

+ 15 - 0
applications/transfers/transfers-auth/src/main/java/com/usoftchina/saas/transfers/auth/EnableOpenApiAuthClient.java

@@ -0,0 +1,15 @@
+package com.usoftchina.saas.transfers.auth;
+
+
+import com.usoftchina.saas.transfers.auth.configuration.OpenApiConfiguration;
+import org.springframework.context.annotation.Import;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Import(OpenApiConfiguration.class)
+@Documented
+@Inherited
+public @interface EnableOpenApiAuthClient {
+}

+ 15 - 0
applications/transfers/transfers-auth/src/main/java/com/usoftchina/saas/transfers/auth/annotation/IgnoreOpenApiAuth.java

@@ -0,0 +1,15 @@
+package com.usoftchina.saas.transfers.auth.annotation;
+
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 对外接口忽略鉴权
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(value={ElementType.METHOD,ElementType.TYPE})
+public @interface IgnoreOpenApiAuth {
+}

+ 49 - 0
applications/transfers/transfers-auth/src/main/java/com/usoftchina/saas/transfers/auth/configuration/OpenApiConfig.java

@@ -0,0 +1,49 @@
+package com.usoftchina.saas.transfers.auth.configuration;
+import org.springframework.beans.factory.annotation.Value;
+/**
+ * @author: guq
+ * @create: 2019-01-10 15:58
+ **/
+public class OpenApiConfig {
+
+    @Value("${openapi.signatureParam:_signature}")
+    private String signatureParam;
+    @Value("${openapi.timestampParam:_timestamp}")
+    private String timestampParam;
+    @Value("${openaip.companyuu:access_id}")
+    private String companyuu;
+    @Value("${openapi.timeout:60000}")
+    private int timeout;
+
+    public String getCompanyuu() {
+        return companyuu;
+    }
+
+    public void setCompanyuu(String companyuu) {
+        this.companyuu = companyuu;
+    }
+
+    public String getSignatureParam() {
+        return signatureParam;
+    }
+
+    public void setSignatureParam(String signatureParam) {
+        this.signatureParam = signatureParam;
+    }
+
+    public String getTimestampParam() {
+        return timestampParam;
+    }
+
+    public void setTimestampParam(String timestampParam) {
+        this.timestampParam = timestampParam;
+    }
+
+    public int getTimeout() {
+        return timeout;
+    }
+
+    public void setTimeout(int timeout) {
+        this.timeout = timeout;
+    }
+}

+ 29 - 0
applications/transfers/transfers-auth/src/main/java/com/usoftchina/saas/transfers/auth/configuration/OpenApiConfiguration.java

@@ -0,0 +1,29 @@
+package com.usoftchina.saas.transfers.auth.configuration;
+
+import com.usoftchina.saas.transfers.auth.interceptor.OpenApiAuthInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * @author: guq
+ * @create: 2019-01-10 16:04
+ **/
+@Configuration
+public class OpenApiConfiguration implements WebMvcConfigurer {
+    @Bean
+    public OpenApiConfig openApiConfig() {
+        return new OpenApiConfig();
+    }
+
+    @Bean
+    public OpenApiAuthInterceptor openApiAuthInterceptor() {
+        return new OpenApiAuthInterceptor();
+    }
+
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        registry.addInterceptor(openApiAuthInterceptor());
+    }
+}

+ 107 - 0
applications/transfers/transfers-auth/src/main/java/com/usoftchina/saas/transfers/auth/interceptor/OpenApiAuthInterceptor.java

@@ -0,0 +1,107 @@
+package com.usoftchina.saas.transfers.auth.interceptor;
+
+import com.usoftchina.saas.account.api.CompanyApi;
+import com.usoftchina.saas.account.dto.CompanyDTO;
+import com.usoftchina.saas.base.Result;
+import com.usoftchina.saas.transfers.auth.annotation.IgnoreOpenApiAuth;
+import com.usoftchina.saas.transfers.auth.configuration.OpenApiConfig;
+import com.usoftchina.saas.utils.StringUtils;
+import com.usoftchina.saas.utils.http.HmacUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+/**
+ * @author: guq
+ * @create: 2019-01-10 16:05
+ **/
+public class OpenApiAuthInterceptor extends HandlerInterceptorAdapter{
+
+    @Autowired
+    private OpenApiConfig openApiConfig;
+
+    @Autowired
+    private CompanyApi companyApi;
+
+    // 已使用签名
+    private Map<String, Long> signatureCache = new ConcurrentHashMap<>();
+
+    private static Logger logger = LoggerFactory.getLogger(OpenApiAuthInterceptor.class);
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        if (handler instanceof HandlerMethod) {
+            HandlerMethod handlerMethod = (HandlerMethod) handler;
+            // 配置该注解,说明不进行用户拦截
+            IgnoreOpenApiAuth annotation = handlerMethod.getBeanType().getAnnotation(IgnoreOpenApiAuth.class);
+            if (annotation == null) {
+                annotation = handlerMethod.getMethodAnnotation(IgnoreOpenApiAuth.class);
+            }
+            if (annotation != null) {
+                return super.preHandle(request, response, handler);
+            }
+
+            String sign = request.getParameter(openApiConfig.getSignatureParam());
+            String companyuu = request.getParameter(openApiConfig.getCompanyuu());
+            if (!StringUtils.isEmpty(sign) && StringUtils.isEmpty(companyuu)) {
+                String urlMessage = request.getRequestURL() + "?"
+                        + request.getQueryString().substring(0, request.getQueryString().indexOf(openApiConfig.getSignatureParam()) - 1);
+
+                logger.info("urlMessage:{}", urlMessage);
+                String servletPath = request.getServletPath();
+                logger.info("servletPath:{}", servletPath);
+
+                boolean check = false;
+                //获取密钥
+                Result<CompanyDTO> companyResult = companyApi.getCompanyByUu(Long.valueOf(companyuu));
+                if (companyResult.isSuccess()) {
+                    String localSign = null;
+
+                    localSign = companyResult.getData().getAccessKey() == null ? HmacUtils.encode(urlMessage) :
+                                HmacUtils.encode(urlMessage, companyResult.getData().getAccessKey());
+
+                    if (servletPath.indexOf("openapi") > -1) {
+                        check = sign.equals(localSign);
+                    }
+
+                    if (check) {
+                        String timestamp = request.getParameter(openApiConfig.getTimestampParam());
+                        long now = System.currentTimeMillis();
+                        if (!StringUtils.isEmpty(timestamp) && Math.abs(now - Long.parseLong(timestamp)) <= openApiConfig.getTimeout()
+                                && !signatureCache.containsKey(sign)) {
+                            // 加入历史记录
+                            signatureCache.put(sign, now);
+                            return true;
+                        }
+                    }
+                }
+            }
+            response.setStatus(HttpStatus.FORBIDDEN.value());
+            return false;
+        } else {
+        }
+        return super.preHandle(request, response, handler);
+    }
+
+    /**
+     * 清除签名池历史记录
+     */
+    @Scheduled(cron = "0 0/3 * * * ?")
+    public void clearCache() {
+        long now = System.currentTimeMillis();
+        for (String key : signatureCache.keySet()) {
+            long time = signatureCache.get(key);
+            if (now - time > openApiConfig.getTimeout()) {
+                signatureCache.remove(key);
+            }
+        }
+    }
+}

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

@@ -65,6 +65,10 @@
             <groupId>org.mybatis.spring.boot</groupId>
             <artifactId>mybatis-spring-boot-starter</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.usoftchina.saas</groupId>
+            <artifactId>transfers-auth</artifactId>
+        </dependency>
     </dependencies>
 
     <build>

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

@@ -1,5 +1,6 @@
 package com.usoftchina.saas.transfers;
 
+import com.usoftchina.saas.transfers.auth.EnableOpenApiAuthClient;
 import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -10,6 +11,7 @@ import org.springframework.cloud.openfeign.EnableFeignClients;
 @EnableEurekaClient
 @EnableFeignClients("com.usoftchina.saas")
 @MapperScan("com.usoftchina.saas.transfers.mapper")
+@EnableOpenApiAuthClient
 public class TransfersApplication {
     public static void main(String[] args) {
         SpringApplication.run(TransfersApplication.class, args);

+ 2 - 0
applications/transfers/transfers-server/src/main/java/com/usoftchina/saas/transfers/controller/TransfersController.java

@@ -1,6 +1,7 @@
 package com.usoftchina.saas.transfers.controller;
 
 import com.usoftchina.saas.base.Result;
+import com.usoftchina.saas.transfers.auth.annotation.IgnoreOpenApiAuth;
 import com.usoftchina.saas.transfers.service.SendService;
 import com.usoftchina.saas.utils.StringUtils;
 import com.usoftchina.saas.transfers.dto.MessageInfo;
@@ -16,6 +17,7 @@ import org.springframework.web.bind.annotation.RestController;
  **/
 @RestController
 @RequestMapping("/send")
+@IgnoreOpenApiAuth
 public class TransfersController {
 
     @Autowired

+ 12 - 1
base-servers/account/account-dto/src/main/java/com/usoftchina/saas/account/dto/CompanyDTO.java

@@ -27,7 +27,18 @@ public class CompanyDTO implements Serializable{
     private String dcName;
     private String tel;
     private String fax;
-    private String signet;      //电子章
+    private String signet;
+    private String accessKey;
+
+    public String getAccessKey() {
+        return accessKey;
+    }
+
+    public void setAccessKey(String accessKey) {
+        this.accessKey = accessKey;
+    }
+
+    //电子章
     private List<Map<String, FileInfoDTO>> fileInfoList;
 
     public List<Map<String, FileInfoDTO>> getFileInfoList() {

+ 9 - 0
base-servers/account/account-server/src/main/java/com/usoftchina/saas/account/po/Company.java

@@ -73,6 +73,15 @@ public class Company implements Serializable {
     private Date updateTime;
     private long updaterId;
     private Long uu;
+    private String accessKey;
+
+    public String getAccessKey() {
+        return accessKey;
+    }
+
+    public void setAccessKey(String accessKey) {
+        this.accessKey = accessKey;
+    }
 
     public String getName() {
         return name;

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

@@ -18,6 +18,7 @@
         <result column="uu" jdbcType="VARCHAR" property="uu"/>
         <result column="logo_url" jdbcType="VARCHAR" property="logoUrl"/>
         <result column="dc_name" jdbcType="VARCHAR" property="dcName"/>
+        <result column="access_key" jdbcType="VARCHAR" property="accessKey"/>
     </resultMap>
     <resultMap id="BaseResultMap" type="com.usoftchina.saas.account.vo.CompanyBaseVO">
         <id column="id" jdbcType="BIGINT" property="id"/>
@@ -26,7 +27,7 @@
         <result column="dc_name" jdbcType="VARCHAR" property="dcName"/>
     </resultMap>
     <sql id="baseColumns">
-        id,name,business_code,address,uu,creator_id,create_time,updater_id,update_time,fax,tel,signet,uu,logo_url,dc_name
+        id,name,business_code,address,uu,creator_id,create_time,updater_id,update_time,fax,tel,signet,uu,logo_url,dc_name,access_key
     </sql>
     <insert id="insert" parameterType="com.usoftchina.saas.account.po.Company"
             useGeneratedKeys="true" keyProperty="id">

+ 26 - 0
frontend/operation-web/app/util/BaseUtil.js

@@ -215,6 +215,32 @@ Ext.define('saas.util.BaseUtil', {
             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);
+        },
+
+        showLoginWin: function() {
+            var main = Ext.getCmp('rootView'),
+            win = Ext.getCmp('relogin');
+
+            if(!win) {
+                win = main.add({
+                    xtype: 'relogin'
+                });
+            }
+
+            win.show();
+        },
+
+        hashcode: function(obj) {
+            let str = JSON.stringify(obj);
+            let hash = 0,
+                i, chr, len;
+            if (str.length === 0) return hash;
+            for (i = 0, len = str.length; i < len; i++) {
+                chr = str.charCodeAt(i);
+                hash = ((hash << 5) - hash) + chr;
+                hash |= 0;
+            }
+            return hash;
         }
     }
 });

+ 103 - 0
frontend/operation-web/app/view/auth/ReLogin.js

@@ -0,0 +1,103 @@
+/**
+ * 重新登录弹窗
+ */
+Ext.define('saas.view.auth.ReLogin', {
+    extend: 'Ext.window.Window',
+    xtype: 'relogin',
+    id: 'relogin',
+
+    controller: 'relogin',
+
+    title: '重新登录',
+    cls: 'x-window-dbfind x-relogin-win',
+    layout: 'fit',
+    modal: true,
+    width: 350,
+    bodyPadding: 20,
+
+    items: [{
+        xtype: 'form',
+        reference: 'reloginform',
+        defaults: {
+            anchor: '100%',
+            labelWidth: 120
+        },
+        items: [{
+            xtype: 'displayfield',
+            height: 32,
+            cls: 'infoLabel',
+            value: '会话已过期,请重新登录',
+        }, {
+            xtype: 'textfield',
+            name: 'username',
+            emptyText: '请输入账号/邮箱/手机号',
+            fieldLabel: '账号',
+            bind: '{account.username}',
+            readOnly: true,
+            hideLabel: true,
+            allowBlank: false
+        }, {
+            xtype: 'textfield',
+            hideLabel: true,
+            fieldLabel: '密码',
+            emptyText: '密码',
+            inputType: 'password',
+            name: 'password',
+            // bind: '{password}',
+            allowBlank: false,
+            enableKeyEvents: true,
+            listeners: {
+                keydown: {
+                    fn: function(th, e, eOpts) {
+                        if(e.keyCode == 13) {
+                            this.up('relogin').getController().onLogin();
+                        }
+                    }
+                }
+            }
+        }, {
+            xtype: 'container',
+            layout: 'hbox',
+            items: [{
+                xtype: 'checkboxfield',
+                flex: 1,
+                cls: 'form-panel-font-color rememberMeCheckbox',
+                height: 30,
+                name: 'remember',
+                bind: '{remember}',
+                boxLabel: '记住密码'
+            }, {
+                xtype: 'box',
+                // html: '<a href="#passwordreset" class="link-forgot-password"> 忘记密码 ?</a>'
+            }]
+        }, {
+            xtype: 'container',
+            layout: {
+                type: 'hbox',
+                pack: 'center'
+            },
+            items: [{
+                xtype: 'button',
+                text: '登录',
+                formBind: true,
+                width: 68,
+                margin: '0 12 0 0',
+                listeners: {
+                    click: 'onLogin'
+                }
+            }, {
+                xtype: 'button',
+                text: '取消',
+                width: 68,
+                margin: '0 0 0 12',
+                listeners: {
+                    click: 'onCancel'
+                }
+            }]
+        }]
+    }],
+
+    listeners: {
+        afterrender: 'onAfterRender',
+    }
+});

+ 15 - 0
frontend/operation-web/app/view/auth/ReLogin.scss

@@ -0,0 +1,15 @@
+.x-relogin-win {
+    .infoLabel {
+        .x-form-display-field {
+            font-size: 14px;
+            vertical-align: middle;
+            line-height: 32px;
+            color: red;
+        }
+    }
+    .rememberMeCheckbox {
+        .x-form-checkbox-default,.x-form-cb-label-default.x-form-cb-label-after {
+            margin: 0;
+        }
+    }
+}

+ 103 - 0
frontend/operation-web/app/view/auth/ReLoginController.js

@@ -0,0 +1,103 @@
+Ext.define('saas.view.auth.ReLoginController', {
+    extend: 'Ext.app.ViewController',
+    alias: 'controller.relogin',
+
+    init: function () {
+        this.callParent(arguments);
+    },
+
+    onAfterRender: function() {
+        var me = this,
+        view = me.getView(),
+        model = me.getViewModel(),
+        remember = model.get('remember'),
+        password = model.get('repassword'),
+        lastSuccess = model.get('lastSuccess'),
+        form = me.lookup('reloginform'),
+        passwordField = form.getForm().findField('password');
+
+        if(remember && lastSuccess) {
+            passwordField.setValue(password);
+        }
+    },
+
+    onLogin: function () {
+        var me = this,
+            view = me.getView(),
+            viewModel = me.getViewModel(),
+            companyId = saas.util.BaseUtil.getCurrentUser().companyId,
+            form = me.lookup('reloginform'),
+            values = form.getValues();
+
+        if(!form.isValid()) {
+            return;
+        }
+
+        view.mask('请稍等...');
+
+        saas.model.Session.login(values.username, values.password, companyId)
+        .then(function (session) {
+            view.isMasked() && view.unmask();
+            viewModel.set('session', session);
+
+            session.get('account').companyId = companyId;
+            
+            me.successReLogin();
+            me.fireEvent('login', session);
+            return session;
+        })
+        .then(function(session) {
+            let headers = Ext.Ajax.getDefaultHeaders() || {};
+            
+            headers['Authorization'] = session.data.token;
+            Ext.Ajax.setDefaultHeaders(headers);
+
+            saas.util.State.set('session', session.data);
+
+            let sessionStr = session.data ? JSON.stringify(session.data) : '';
+
+            if (typeof require === 'function') {
+                let ipc = require('electron').ipcRenderer;
+                ipc.send('session.change', sessionStr);
+            }else {
+                //解析session 把data作为sessionStr
+                sessionStr = session ? JSON.stringify(session.data) : '';
+                const frame = window.frames[window.frames.length - 1];
+                frame.postMessage(sessionStr, '*');
+            }
+            return session;
+        })
+        .catch(function (error) {
+            view.isMasked() && view.unmask();
+            console.error(error);
+            saas.util.BaseUtil.showErrorToast('登录失败: ' + error.message);
+            me.failureReLogin();
+        });
+    },
+
+    successReLogin: function() {
+        var me = this,
+            view = me.getView(),
+            form = me.lookup('reloginform'),
+            values = form.getValues();
+            viewModel = me.getViewModel();
+
+        viewModel.set('repassword', values.password);
+        viewModel.set('lastSuccess', true);
+        view.close();
+    },
+
+    failureReLogin: function() {
+        var me = this,
+        viewModel = me.getViewModel();
+
+        viewModel.set('lastSuccess', false);
+    },
+
+    onCancel: function() {
+        var me = this,
+        view = me.getView();
+
+        view.close();
+    },
+});

+ 1 - 1
frontend/operation-web/overrides/data/Connection.js

@@ -60,7 +60,7 @@ Ext.define('saas.override.data.Connection', {
 
         if(res && res.code == 40001) {
             // 如果token超时则显示重新登陆弹窗
-            // saas.util.BaseUtil.showLoginWin();
+            saas.util.BaseUtil.showLoginWin();
             throw new Error('会话已过期');
         }
 

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

@@ -451,17 +451,17 @@ import { setTimeout } from 'timers';
             },
             // 特色
             feature(){
-                this.$router.push({name: 'Home', params: {isfeature: 730}});
+                this.$router.push({name: 'Home', params: {isfeature: 690}});
                 this.setTurnHome();
             },
             //功能
             service(){
-                this.$router.push({name: 'Home', params: {isfeature: 3670}});
+                this.$router.push({name: 'Home', params: {isfeature: 3530}});
                 this.setTurnHome();
             },
             // 下载
             download(){
-                this.$router.push({name: 'Home', params: {isfeature: 4400}});
+                this.$router.push({name: 'Home', params: {isfeature: 4190}});
                 this.setTurnHome();
             },
             gohome(e){

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

@@ -156,7 +156,7 @@
       </section>
 
       <!-- Service section 功能-->
-      <section id="service" style="padding-top: 0px">
+      <section id="service" style="padding-top: 0px;margin-top:-100px">
         <div class="container" style="position: relative;">
           <img class="gn-beijing" src="/static/img/gongneng/xu xian@3x.png" alt="">
           <div class="row">
@@ -256,7 +256,7 @@
       <!-- end Service section -->
       <!-- 下载 -->
       <section>
-        <div class="container ts-worp">
+        <div class="container ts-worp" style="padding-top: 30px;">
           <div class="section-title text-center" style="margin-bottom: 50px">
             <p class="ts-title">下载</p>
             <p class="ts-text">下载U企云服客户端</p>
@@ -583,17 +583,17 @@
       },
       //特色
       feature2(){
-        document.documentElement.scrollTop = 730;
+        document.documentElement.scrollTop = 690;
         this.setTurnHome();
       },
       //功能
       service2(){
-        document.documentElement.scrollTop = 3670;
+        document.documentElement.scrollTop = 3530;
         this.setTurnHome();
       },
       // 下载
       download(){
-        document.documentElement.scrollTop = 4400;
+        document.documentElement.scrollTop = 4190;
         // $('html,body').animate({
         //       scrollTop: 4400
         // },2000);

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

@@ -171,7 +171,7 @@ main > section {
     width: 100%;
     padding: 0;
     margin: 0;
-    padding-top: 100px;
+    padding-top: 60px;
 }
 .ts-box {
     overflow: hidden;
@@ -397,7 +397,7 @@ main > section {
     font-size: 14px;
     color: #fff;
     cursor: pointer;
-    opacity: 0.9;
+    opacity: 0.8;
 }
 .footer-section ul>li:hover a{
     text-decoration: underline ;

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

@@ -616,6 +616,25 @@ input::-webkit-input-placeholder {
 
 .x-quotation-detail{
   width: 1105px !important;
+  .x-grid-row{
+    border-color:#fff !important;
+    background-color: #fff !important;
+  }
+  .x-grid-item-selected{
+    border-color:#fff !important;
+    background-color: #fff !important;
+  }
+}
+
+.x-quotation-main{
+  .x-grid-row{
+    border-color:#fff !important;
+    background-color: #fff !important;
+  }
+  .x-grid-item-selected{
+    border-color:#fff !important;
+    background-color: #fff !important;
+  }
 }
 
 .x-btn-quotation{

+ 2 - 1
frontend/saas-web/app/view/main/MainContainerWrap.js

@@ -34,11 +34,12 @@ Ext.define('saas.view.main.MainContainerWrap', {
                 closeTabText: '关闭当前页',
                 closeAllTabsText: '关闭全部页',
                 closeOthersTabsText: '关闭其他页'
-            })],
+            }), new Ext.ux.TabReorderer()],
             items: [{
                 iconCls: 'x-sa sa-home',
                 title: '首页',
                 closable: false,
+                reorderable: false,
                 // margin: '16 0 16 16',
                 // scrollable: true,
                 // bodyPadding: '0 16 0 0',

+ 139 - 5
frontend/saas-web/app/view/purchase/quotationList/DataList.js

@@ -6,9 +6,10 @@ Ext.define('saas.view.purchase.quotationList.DataList', {
     viewModel: 'purchase-quotationList-datalist',
     autoScroll: true,
     frame:true,
+    cls:'x-quotation-main',
     layout:'fit',
     
-    dataUrl:'http://10.1.80.23:8560/api/purchase/purchase/inquiry/list',                 
+    dataUrl:'/api/purchase/purchase/inquiry/list',                 
     quotationListUrl:'/api/commons/number/delete/',
 
     plugins: [{
@@ -111,7 +112,133 @@ Ext.define('saas.view.purchase.quotationList.DataList', {
             }, {
                 width: 200,
                 text: '操作',
-                dataIndex: 'agreed'
+                dataIndex: 'agreed',
+                renderer:function(val, meta, record,x,y,store, view){
+                    var id = record.get('id');
+                    window.sendMessage = function(id,status,refusereason){
+                        var params = {
+                            id:id,
+                            status:status,
+                            refusereason:refusereason
+                        };
+                        Ext.Ajax.request({  
+                            url : '/api/purchase/purchase/inquiry/deal',
+                            timeout: 8000,  
+                            headers:{
+                                'Access-Control-Allow-Origin': '*',
+                                'Authorization':  saas.util.State.get('session').token,
+                                "Content-Type": 'application/json;charset=UTF-8'
+                            },
+                            method: 'POST',
+                            params:JSON.stringify(params),
+                            success: function(response, o){
+                                var res = Ext.decode(response.responseText);
+                                if(res.success){
+                                    saas.util.BaseUtil.showSuccessToast('操作成功');
+                                }else{
+                                    saas.util.BaseUtil.showErrorToast('操作失败:'+res.message);
+                                }
+                            },
+                            failure: function (response, opts) {
+                                saas.util.BaseUtil.showErrorToast('操作失败,请重试');
+                            }
+                        });
+                    };
+
+                    window.checkPrice = function(status,id){
+                        if(status=='0'){
+                            var panel = view.ownerCt.ownerCmp.ownerCt;
+                            var win = Ext.create('Ext.window.Window', {  
+                                renderTo: panel.getEl(),
+                                cls:'x-window-dbfind', 
+                                height: 100,
+                                width: 450,
+                                modal:true,
+                                title: '提示',
+                                bodyPadding: 10,
+                                constrain: true,
+                                closable: true,
+                                layout: {
+                                    type: 'vbox',
+                                    align: 'center'
+                                },
+                                items:[{
+                                    xtype:'panel',
+                                    layout:'hbox',
+                                    items:[{
+                                        margin:'0 10 0 0',
+                                        labelWidth:60,
+                                        xtype : "textfield", 
+                                        name : "refusereason",
+                                        fieldLabel : "拒绝信息"
+                                    },{
+                                        margin:'0 0 0 5',
+                                        xtype:'button',
+                                        text:'确认',
+                                        handler:function(b){
+                                            var refusereason = b.ownerCt.down('[name=refusereason]').value;
+                                            window.sendMessage(id,status,refusereason);
+                                            b.ownerCt.ownerCt.close();
+                                        }
+                                    }]
+                                }]
+                            });
+                            win.show();
+                        }else if(status=='1'){
+                            window.sendMessage(id,status,'');
+                        }
+                    }
+
+                    window.showRefuse = function(msg){
+                        var panel = view.ownerCt.ownerCmp.ownerCt;
+                        var win = Ext.create('Ext.window.Window', {  
+                            renderTo: panel.getEl(),
+                            cls:'x-window-dbfind', 
+                            height: 100,
+                            width: 450,
+                            modal:true,
+                            title: '查看',
+                            bodyPadding: 10,
+                            constrain: true,
+                            closable: true,
+                            layout: {
+                                type: 'vbox',
+                                align: 'center'
+                            },
+                            items:[{
+                                xtype:'panel',
+                                layout:'hbox',
+                                items:[{
+                                    margin:'0 10 0 0',
+                                    labelWidth:60,
+                                    xtype : "displayfield", 
+                                    name : "refusereason",
+                                    fieldLabel : "拒绝信息",
+                                    value:msg
+                                }]
+                            }]
+                        });
+                        win.show();
+                    }
+                    if((!val||val=='')&&val!=0){
+                        //未采纳状态
+                        return '<div style="width:100%;vertical-align: middle;    text-align: center;">'+
+                                    "<input type='button' value='采纳' name='agree' style='border: 1px solid;color:#34baf6;cursor:pointer;background:#fff;' onClick='window.checkPrice(1,"+id+")'>"+
+                                    "<input type='button' value='拒绝' name='disagree' style='margin:0 0 0 20px;border: 1px solid;color:#ff0000;cursor:pointer;background:#fff;' onClick='window.checkPrice(0,"+id+")'>"+
+                                '</div>';
+                    }else if(val==1||val=='1'){
+                        return '<div style="color:#34baf6;width:100%;vertical-align: middle;    text-align: center;">已采纳</div>'
+                    }else if(val==0||val=='0'){
+                        var refusereason = record.get('refusereason');
+                        if(!refusereason||refusereason==''){
+                            return '<div style="color:#ff6c00;width:100%;vertical-align: middle;    text-align: center;">已拒绝</div>'
+                        }else{
+                            return  '<div style="width:100%;vertical-align: middle; text-align: center;">'+
+                                        "<input type='button' value='查看拒绝理由' name='showRefuse' style='border: 1px solid;color:#ff6c00;cursor:pointer;background:#fff;' onClick='window.showRefuse("+refusereason+")'></input>"+
+                                    '</div>';
+                        }
+                    }
+                }
             }]
         }
     }],
@@ -254,8 +381,15 @@ Ext.define('saas.view.purchase.quotationList.DataList', {
         width : 160.0
     },{
         text : '报价状态', 
-        dataIndex : 'quoted',
-        width : 110.0
+        dataIndex : 'qutations',
+        width : 110.0,
+        renderer:function(val, meta, record,x,y,store, view){
+            if(!val||val==0||val.length==0){
+                return '否'
+            }else{
+                return '是'
+            }
+        }
     }, {
         dataIndex: '',
         flex: 1
@@ -341,7 +475,7 @@ Ext.define('saas.view.purchase.quotationList.DataList', {
             gridBodyBox = grid.body.dom.getBoundingClientRect(),
             gridBodyBoxHeight = gridBodyBox.height;
 
-            var pageSize = Math.floor(gridBodyBoxHeight / 32);
+            var pageSize = Math.floor(gridBodyBoxHeight / 33);
 
             store.setPageSize(pageSize);
 

+ 7 - 3
frontend/saas-web/app/view/purchase/sendQuotation/DataList.js

@@ -11,7 +11,7 @@ Ext.define('saas.view.purchase.sendQuotation.DataList', {
     layout:'fit',
     
     dataUrl:'/api/document/product/list',                 
-    sendQuotationUrl:'http://10.1.80.23:8560/api/purchase/purchase/inquiry/send',
+    sendQuotationUrl:'/api/purchase/purchase/inquiry/send',
 
     plugins: [{
         ptype: 'menuclipboard'
@@ -190,9 +190,13 @@ Ext.define('saas.view.purchase.sendQuotation.DataList', {
             })
             .then(function(res) {
                 grid.setLoading(false);
-                saas.util.BaseUtil.showSuccessToast('操作成功');
-                debugger
+                if(res.data.length>0){
+                    saas.util.BaseUtil.showErrorToast('询价结果: 成功'+(data.length-res.data.length) +'条,失败'+res.data.length+'条');
+                }else{
+                    saas.util.BaseUtil.showSuccessToast('询价成功'+data.length+'条');
+                }
                 grid.store.load();
+                grid.selModel.deselectAll();
             })
             .catch(function(e) {
                 grid.setLoading(false);

+ 5 - 0
pom.xml

@@ -342,6 +342,11 @@
                 <artifactId>datacenter-client</artifactId>
                 <version>${project.release.version}</version>
             </dependency>
+            <dependency>
+                <groupId>com.usoftchina.saas</groupId>
+                <artifactId>transfers-auth</artifactId>
+                <version>${project.release.version}</version>
+            </dependency>
             <!-- file upload -->
             <dependency>
                 <groupId>io.github.openfeign.form</groupId>