Przeglądaj źródła

Merge branch 'dev' into dev_lhc

lhch2018 3 lat temu
rodzic
commit
6bd9c94fb8
7 zmienionych plików z 250 dodań i 20 usunięć
  1. 1 0
      .gitignore
  2. 3 1
      package.json
  3. 5 5
      src/api/http.js
  4. 13 0
      src/api/user.js
  5. 3 0
      src/main.js
  6. 33 0
      src/store/index.js
  7. 192 14
      src/views/login.vue

+ 1 - 0
.gitignore

@@ -12,3 +12,4 @@ yarn-error.log*
 *.ntvs*
 *.njsproj
 *.sln
+package-lock.json

+ 3 - 1
package.json

@@ -13,9 +13,11 @@
     "axios": "^0.21.4",
     "element-ui": "^2.15.5",
     "node-sass": "^6.0.1",
+    "qs": "^6.10.1",
     "vue": "^2.5.2",
     "vue-amap": "^0.5.10",
-    "vue-router": "^3.0.1"
+    "vue-router": "^3.0.1",
+    "vuex": "^3.6.2"
   },
   "devDependencies": {
     "autoprefixer": "^7.1.2",

+ 5 - 5
src/api/http.js

@@ -1,6 +1,7 @@
 import axios from 'axios';
-// const requestUrl = 'http://153.37.175.42:8086/'; // 测试内部接口
-const requestUrl = 'http://121.4.100.145:8082/'; // 测试内部接口
+import qs from 'qs';
+const requestUrl = 'http://153.37.175.42:8086/'; // 测试内部接口
+// const requestUrl = 'http://121.4.100.145:8082/'; // 测试内部接口
 //const requestUrl = 'https://api.liebaoai.cn/'; // 统一正式接口
 //创建axios实例
 const service = axios.create({
@@ -65,10 +66,9 @@ export function post(url, data = {}) {
     let sendObject = {
         url: requestUrl + url,
         method: "post",
-        headers: {},
         data: data
     };
-    sendObject.data = JSON.stringify(data);
+    sendObject.data = qs.stringify(sendObject.data);
     return service(sendObject)
 }
 
@@ -83,6 +83,6 @@ export function postJson(url, data = {}) {
         },
         data: data
     };
-    sendObject.data = JSON.stringify(data);
+    sendObject.data = qs.stringify(data);
     return service(sendObject)
 }

+ 13 - 0
src/api/user.js

@@ -0,0 +1,13 @@
+import { get, post, postJson } from './http.js';
+
+export const getPhoneCode = ( params ) => {
+  return post( 'app/login/send/sms', params )
+}
+
+export const loginPassword = ( params ) => {
+  return post( 'app/login/password', params )
+}
+
+export const loginVerification = ( params ) => {
+  return post( 'app/login/verification', params )
+}

+ 3 - 0
src/main.js

@@ -5,11 +5,13 @@ import App from './App'
 import router from './router'
 
 import Elementui from 'element-ui'
+import store from './store/index.js';
 
 import VueAMap from 'vue-amap';
 
 import {get, post, postJson} from './api/http'
 
+
 Vue.config.productionTip = false
 
 Vue.prototype.$get = get;
@@ -31,6 +33,7 @@ VueAMap.initAMapApiLoader({
 new Vue({
   el: '#app',
   router,
+  store,
   components: { App },
   template: '<App/>'
 })

+ 33 - 0
src/store/index.js

@@ -0,0 +1,33 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+
+Vue.use(Vuex);
+
+const state = {
+  userInfo: null || JSON.parse( localStorage.getItem('userInfo') )
+}
+
+const actions = {}
+
+const mutations = {
+  SET_USERINFO: ( state, userInfo ) => {
+    state.userInfo = userInfo;
+    // 防止页面刷新,导致Vuex重启
+    localStorage.setItem('userInfo', JSON.stringify(userInfo));
+  }
+}
+
+const getters = {
+  userInfo: ( state ) => {
+    return state.userInfo
+  }
+}
+
+const store = new Vuex.Store({
+  actions,
+  mutations,
+  state,
+  getters
+})
+
+export default store;

+ 192 - 14
src/views/login.vue

@@ -2,46 +2,48 @@
   <div class="login">
     <div class="login-bg" data-title="登录"></div>
     <img src="../../static/image/login-logo.png" class="login-logo" />
-    <div class="login-box">
+    <div class="login-box" v-loading="isLoading">
       <div class="login-content">
         <div class="top-icon">
           <img src="../../static/image/login-icon.png" />
         </div>
         <div class="pass-code">
-          <div class="item" :class="activeIndex == 1 ? 'active' : ''">密码登录</div>
-          <div class="item" :class="activeIndex == 2 ? 'active' : ''">验证码登录</div>
+          <div class="item" :class="activeIndex == 1 ? 'active' : ''" @click.stop=" activeIndex = 1 ">密码登录</div>
+          <div class="item" :class="activeIndex == 2 ? 'active' : ''" @click.stop=" activeIndex = 2 ">验证码登录</div>
         </div>
         <div>
           <!-- 密码登录 -->
           <div class="login-password" v-if="activeIndex == 1">
             <div class="pass-item">
               <img src="../../static/image/phone-icon.png" class="phone-icon" />
-              <el-input placeholder="请输入手机号" class="input-phone" :maxlength="11" />
+              <el-input placeholder="请输入手机号" v-model="mobile" class="input-phone" :maxlength="11" />
             </div>
             <div class="pass-item">
               <img src="../../static/image/lock-icon.png" class="lock-icon" />
-              <el-input placeholder="用户密码" class="input-phone" type="password" />
+              <el-input placeholder="用户密码" v-model="password" class="input-phone" type="password" />
             </div>
           </div>
           <!-- 验证码登录 -->
           <div class="login-password" v-else>
             <div class="pass-item">
               <img src="../../static/image/phone-icon.png" class="phone-icon" />
-              <el-input placeholder="请输入手机号" class="input-phone" :maxlength="11" />
+              <el-input placeholder="请输入手机号" v-model="mobile" class="input-phone" :maxlength="11" />
             </div>
             <div class="pass-item">
               <img src="../../static/image/code-icon.png" class="phone-icon" />
-              <el-input placeholder="验证码" class="input-phone" type="password" />
-              <div class="get-code">获取短信验证码</div>
+              <el-input placeholder="验证码" v-model="code" class="input-phone" :maxlength="4" />
+              <div class="get-code" v-if="!showCode" @click.stop="getCode">获取短信验证码</div>
+              <div class="get-code" v-else>{{ count }}秒</div>
             </div>
           </div>
         </div>
         <div class="forgot-pass">
-          <span>忘记密码?</span>
+          <span @click.stop="$router.push('/resetPassword')">忘记密码?</span>
         </div>
-        <div class="login-btn">登录</div>
+        <div class="login-btn" @click.stop="toLogin">登录</div>
         <div class="xie-yi">
-          登录注册即同意<a target="_blank" href="http://h5.liebaoai.cn/service.html">《用户协议》</a>与<a target="_blank" href="http://h5.liebaoai.cn/privacy.html">《隐私政策》</a>
+          登录注册即同意<a target="_blank" href="http://h5.liebaoai.cn/service.html">《用户协议》</a>与<a target="_blank"
+            href="http://h5.liebaoai.cn/privacy.html">《隐私政策》</a>
         </div>
       </div>
     </div>
@@ -49,11 +51,165 @@
 </template>
 
 <script>
+  import {
+    mapState,
+    mapMutations,
+    mapGetters
+  } from 'vuex';
+  import {
+    getPhoneCode,
+    loginPassword
+  } from '../api/user.js';
   export default {
     data() {
       return {
-        activeIndex: 1
+        activeIndex: 1,
+        isLoading: false, // 请求解决展示loading
+        mobile: '',
+        password: '',
+        code: '',
+        count: 60,
+        showCode: false,
+        timer: null, // 计时器
       }
+    },
+    destroyed() {
+      clearInterval(this.timer);
+      this.timer = null;
+    },
+    computed: {
+      ...mapState(['userInfo']),
+      ...mapGetters(['userInfo'])
+    },
+    created() {
+      console.log('vuex', this.userInfo)
+    },
+    methods: {
+      ...mapMutations(['SET_USERINFO']),
+      // 短信验证码登录
+      loginOfCode() {
+        let params = {
+          mobile: this.mobile,
+          code: this.code,
+          platform: 4
+        }
+        loginVerification( params ).then( res => {
+          if ( res.code == 200 ) {
+            localStorage.setItem('token', res.data.token);
+            this.SET_USERINFO( res.data.member );
+            this.$router.push('/');
+          }else {
+            return this.$message({
+              message: res.msg,
+              type: 'error'
+            })
+          }
+        } )
+      },
+      // 账号密码登录
+      loginOfPassword() {
+        let params = {
+          mobile: this.mobile,
+          password: this.password,
+          platform: 4
+        }
+        loginPassword( params ).then( res => {
+          if ( res.code == 200 ) {
+            localStorage.setItem('token', res.data.token);
+            this.SET_USERINFO( res.data.member );
+            this.$router.push('/');
+          }else {
+            return this.$message({
+              message: res.msg,
+              type: 'error'
+            })
+          }
+        } )
+      },
+      // 登录
+      toLogin() {
+        if ( !this.mobile.trim() ) {
+          return this.$message({
+            message: '手机号码不能为空',
+            type: 'error'
+          })
+        }
+        if (!this.checkPhone(this.mobile)) {
+          return this.$message({
+            message: '请输入正确的手机号',
+            type: 'error'
+          })
+        }
+        if ( this.activeIndex == 1 ) {
+          // 账号密码登录
+          if ( !this.password.trim() ) {
+            return this.$message({
+              message: '密码不能为空',
+              type: 'error'
+            })
+          }
+          this.loginOfPassword();
+        }else {
+          // 短信验证码登录
+          if ( !this.code.trim() ) {
+            return this.$message({
+              message: '验证码不能为空',
+              type: 'error'
+            })
+          }
+          this.loginOfCode();
+        }
+      },
+      checkPhone(phone) {
+        if (!(/^1\d{10}$/.test(phone))) {
+          return false;
+        } else {
+          return true
+        }
+      },
+      // 获取验证码
+      getCode() {
+        if (!this.mobile.trim()) {
+          return this.$message({
+            message: '手机号码不能为空',
+            type: 'error'
+          })
+        }
+        if (!this.checkPhone(this.mobile)) {
+          return this.$message({
+            message: '请输入正确的手机号',
+            type: 'error'
+          })
+        }
+        let params = {
+          mobile: this.mobile,
+          type: 1
+        };
+        this.isLoading = true;
+        getPhoneCode(params).then(res => {
+          if (res.code == 200) {
+            this.isLoading = false;
+            this.showCode = true;
+            this.$message({
+              message: '验证码发送成功',
+              type: 'success'
+            })
+            this.timer = setInterval(() => {
+              this.count--;
+              if (this.count <= 1) {
+                this.showCode = false;
+                clearInterval(this.timer);
+              }
+            }, 1000)
+          } else {
+            this.isLoading = false;
+            return this.$message({
+              message: res.msg,
+              type: 'error'
+            })
+          }
+        })
+      },
     }
   }
 </script>
@@ -62,10 +218,12 @@
   /deep/ .el-input__inner {
     border: none !important;
   }
+
   .login {
     position: relative;
     width: 100%;
     height: 100%;
+
     .login-bg {
       position: fixed;
       height: 100%;
@@ -74,6 +232,7 @@
       background-attachment: fixed;
       background: url("/static/image/login-bg.png") no-repeat #010836;
     }
+
     .login-logo {
       width: 158px;
       height: 24px;
@@ -81,14 +240,16 @@
       top: 32px;
       left: 32px;
     }
+
     .login-box {
       position: relative;
       z-index: 200;
       height: 100vh;
       display: flex;
       display: -webkit-flex;
-      align-items:center;
-      justify-content:center;
+      align-items: center;
+      justify-content: center;
+
       .login-content {
         background-color: #fff;
         border-radius: 14px;
@@ -96,28 +257,34 @@
         box-sizing: border-box;
         align-self: center;
         padding: 30px;
+
         .top-icon {
           width: 100%;
           text-align: center;
           font-size: 0;
           padding-top: 14px;
+
           img {
             width: 194px;
             height: 52px;
           }
         }
+
         .pass-code {
           display: flex;
           padding-top: 44px;
+
           .item {
             font-size: 16px;
             font-family: PingFang SC;
             font-weight: 400;
             color: #565656;
             cursor: pointer;
+
             &:nth-child(1) {
               margin-right: 30px;
             }
+
             &.active {
               font-weight: bold;
               color: #111111;
@@ -126,26 +293,32 @@
             }
           }
         }
+
         .login-password {
           padding-top: 30px;
+
           .pass-item {
             display: flex;
             align-items: center;
             padding-bottom: 2px;
             border-bottom: 1px solid #eee;
+
             .phone-icon {
               width: 14px;
               height: 17px;
               margin-right: 16px;
             }
+
             .lock-icon {
               width: 16px;
               height: 18px;
               margin-right: 14px;
             }
+
             .input-phone {
               flex: 1;
             }
+
             .get-code {
               min-width: 120px;
               box-sizing: border-box;
@@ -159,6 +332,7 @@
             }
           }
         }
+
         .forgot-pass {
           text-align: right;
           font-size: 14px;
@@ -166,10 +340,12 @@
           font-weight: 400;
           color: #8590A6;
           padding-top: 10px;
+
           span {
             cursor: pointer;
           }
         }
+
         .login-btn {
           height: 36px;
           line-height: 36px;
@@ -183,6 +359,7 @@
           margin-top: 20px;
           cursor: pointer;
         }
+
         .xie-yi {
           font-size: 12px;
           font-family: PingFang SC;
@@ -190,6 +367,7 @@
           color: #808080;
           text-align: center;
           margin-top: 20px;
+
           a {
             text-decoration: none;
             color: #175199;