Ver Fonte

09/17 11:29

登录功能完成
mo há 5 anos atrás
pai
commit
94ead8468e

+ 1 - 1
.env.development

@@ -2,7 +2,7 @@
 ENV = 'development'
 
 # base api
-VUE_APP_BASE_API = '/dev-api'
+VUE_APP_BASE_API = 'api'
 
 # vue-cli uses the VUE_CLI_BABEL_TRANSPILE_MODULES environment variable,
 # to control whether the babel-plugin-dynamic-import-node plugin is enabled.

+ 1 - 1
.env.production

@@ -2,5 +2,5 @@
 ENV = 'production'
 
 # base api
-VUE_APP_BASE_API = '/prod-api'
+VUE_APP_BASE_API = 'api'
 

+ 1 - 0
package.json

@@ -22,6 +22,7 @@
     "normalize.css": "7.0.0",
     "nprogress": "0.2.0",
     "path-to-regexp": "2.4.0",
+    "qs": "^6.8.0",
     "vue": "2.6.10",
     "vue-router": "3.0.6",
     "vuex": "3.1.0"

+ 9 - 9
src/api/user.js

@@ -1,24 +1,24 @@
 import request from '@/utils/request'
 
-export function login(data) {
+export function login (data) {
   return request({
-    url: '/user/login',
+    url: '/api-auth/usernameLogin',
+    // url: '/user/login',
     method: 'post',
     data
   })
 }
 
-export function getInfo(token) {
+export function getInfo () {
   return request({
-    url: '/user/info',
-    method: 'get',
-    params: { token }
+    url: '/api-auth/api/queryUserInfo',
+    method: 'get'
   })
 }
-
-export function logout() {
+// 登出
+export function logout () {
   return request({
-    url: '/user/logout',
+    url: '/api-auth/exit',
     method: 'post'
   })
 }

BIN
src/assets/images/base/login-bg.png


BIN
src/assets/images/base/login-logo.png


+ 1 - 1
src/layout/components/Navbar.vue

@@ -34,7 +34,7 @@
           </a>
           <el-dropdown-item divided>
             <span style="display:block;"
-                  @click="logout">Log Out</span>
+                  @click="logout">登出</span>
           </el-dropdown-item>
         </el-dropdown-menu>
       </el-dropdown>

+ 2 - 0
src/main.js

@@ -16,6 +16,8 @@ import router from './router'
 import '@/icons' // icon
 import '@/permission' // permission control
 
+
+
 /**
  * If you don't want to use mock-server
  * you want to use MockJs for mock api

+ 4 - 5
src/permission.js

@@ -10,7 +10,7 @@ NProgress.configure({ showSpinner: false }) // NProgress Configuration
 
 const whiteList = ['/login'] // no redirect whitelist
 
-router.beforeEach(async(to, from, next) => {
+router.beforeEach(async (to, from, next) => {
   // start progress bar
   NProgress.start()
 
@@ -19,21 +19,20 @@ router.beforeEach(async(to, from, next) => {
 
   // determine whether the user has logged in
   const hasToken = getToken()
-
   if (hasToken) {
     if (to.path === '/login') {
-      // if is logged in, redirect to the home page
+      // 如果有tonken直接跳转到首页
       next({ path: '/' })
       NProgress.done()
     } else {
       const hasGetUserInfo = store.getters.name
+      // 有名字 说明有用户信息 跳走
       if (hasGetUserInfo) {
         next()
       } else {
         try {
-          // get user info
+          // 异步获取用户信息
           await store.dispatch('user/getInfo')
-
           next()
         } catch (error) {
           // remove token and go to login page to re-login

+ 28 - 20
src/store/modules/user.js

@@ -1,7 +1,7 @@
 import { login, logout, getInfo } from '@/api/user'
 import { getToken, setToken, removeToken } from '@/utils/auth'
 import { resetRouter } from '@/router'
-
+import qs from 'qs'
 const state = {
   token: getToken(),
   name: '',
@@ -22,45 +22,53 @@ const mutations = {
 
 const actions = {
   // user login
-  login({ commit }, userInfo) {
+  login ({ commit }, userInfo) {
     const { username, password } = userInfo
     return new Promise((resolve, reject) => {
-      login({ username: username.trim(), password: password }).then(response => {
+      //qs.stringify({ username: username.trim(), password: password, clientId: 'app', clientSecret: 'app' })
+      // { username: username.trim(), password: password }
+      login(qs.stringify({ username: username.trim(), password: password, clientId: 'app', clientSecret: 'app' })).then(response => {
         const { data } = response
-        commit('SET_TOKEN', data.token)
-        setToken(data.token)
-        resolve()
+        if (response.code == 200) {
+          let token = data.token_type + ' ' + data.access_token;
+          commit('SET_TOKEN', token)
+          setToken(token)
+          resolve()
+        }
+        // console.log(response);
+
       }).catch(error => {
         reject(error)
       })
     })
   },
 
-  // get user info
-  getInfo({ commit, state }) {
+  // get 获取用户信息
+  getInfo ({ commit, state }) {
     return new Promise((resolve, reject) => {
       getInfo(state.token).then(response => {
-        const { data } = response
-
-        if (!data) {
-          reject('Verification failed, please Login again.')
+        // if (response.code == 200) {
+        const data = response
+        if (!data.data) {
+          reject('获取用户信息错误,请重新登录')
         }
-
-        const { name, avatar } = data
-
-        commit('SET_NAME', name)
+        const username = data.data.username;
+        const avatar = data.data.avatar;
+        // const { name, avatar } = data
+        commit('SET_NAME', username)
         commit('SET_AVATAR', avatar)
         resolve(data)
+        // }
       }).catch(error => {
         reject(error)
       })
     })
   },
 
-  // user logout
-  logout({ commit, state }) {
+  // 登出
+  logout ({ commit }) {
     return new Promise((resolve, reject) => {
-      logout(state.token).then(() => {
+      logout().then(() => {
         commit('SET_TOKEN', '')
         removeToken()
         resetRouter()
@@ -72,7 +80,7 @@ const actions = {
   },
 
   // remove token
-  resetToken({ commit }) {
+  resetToken ({ commit }) {
     return new Promise(resolve => {
       commit('SET_TOKEN', '')
       removeToken()

+ 4 - 4
src/utils/auth.js

@@ -1,15 +1,15 @@
 import Cookies from 'js-cookie'
 
-const TokenKey = 'vue_admin_template_token'
+const TokenKey = 'dy_admin_token'
 
-export function getToken() {
+export function getToken () {
   return Cookies.get(TokenKey)
 }
 
-export function setToken(token) {
+export function setToken (token) {
   return Cookies.set(TokenKey, token)
 }
 
-export function removeToken() {
+export function removeToken () {
   return Cookies.remove(TokenKey)
 }

+ 32 - 33
src/utils/request.js

@@ -1,83 +1,82 @@
 import axios from 'axios'
-import { MessageBox, Message } from 'element-ui'
+import { Message } from 'element-ui'
 import store from '@/store'
 import { getToken } from '@/utils/auth'
+import { Loading } from 'element-ui'
+let loading        //定义loading变量
+
+function startLoading () {    //使用Element loading-start 方法
+  loading = Loading.service({ fullscreen: true, text: '努力加载中', spinner: 'el-icon-loading', background: 'rgba(0, 0, 0, 0.8)' });
+}
+function endLoading () {    //使用Element loading-close 方法
+  loading.close()
+}
 
 // create an axios instance
 const service = axios.create({
-  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
+  baseURL: '', // url = base url + request url
   // withCredentials: true, // send cookies when cross-domain requests
   timeout: 5000 // request timeout
 })
-
+// { fullscreen: true, text: '努力加载中', spinner: 'el-icon-loading' }
 // request interceptor
 service.interceptors.request.use(
   config => {
     // do something before request is sent
-
+    startLoading();
     if (store.getters.token) {
       // let each request carry token
       // ['X-Token'] is a custom headers key
       // please modify it according to the actual situation
-      config.headers['X-Token'] = getToken()
+      config.headers['Authorization'] = getToken()
     }
     return config
   },
   error => {
     // do something with request error
-    console.log(error) // for debug
+    // console.log(error) // for debug
     return Promise.reject(error)
   }
 )
 
 // response interceptor
 service.interceptors.response.use(
-  /**
-   * If you want to get http information such as headers or status
-   * Please return  response => response
-  */
-
-  /**
-   * Determine the request status by custom code
-   * Here is just an example
-   * You can also judge the status by HTTP Status Code
-   */
-  response => {
-    const res = response.data
-
-    // if the custom code is not 20000, it is judged as an error.
-    if (res.code !== 20000) {
+  res => {
+    //res.code !== 200
+    let data = JSON.parse(JSON.stringify(res.data))
+    if (data.code != 200) {
       Message({
-        message: res.message || 'Error',
+        message: data.msg || `请求失败code码为${res.code}`,
         type: 'error',
         duration: 5 * 1000
       })
 
       // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
-      if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
-        // to re-login
-        MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
-          confirmButtonText: 'Re-Login',
-          cancelButtonText: 'Cancel',
+      if (res.code === 401 || res.code === 403) {
+        this.$message({
+          message: '登录超时请重新登录',
           type: 'warning'
-        }).then(() => {
-          store.dispatch('user/resetToken').then(() => {
-            location.reload()
-          })
+        })
+        store.dispatch('user/resetToken').then(() => {
+          location.reload()
         })
       }
+      endLoading()
       return Promise.reject(new Error(res.message || 'Error'))
     } else {
-      return res
+      endLoading();
+      return data
+
     }
   },
   error => {
-    console.log('err' + error) // for debug
+    // console.log('err' + error) // for debug
     Message({
       message: error.message,
       type: 'error',
       duration: 5 * 1000
     })
+    endLoading()
     return Promise.reject(error)
   }
 )

+ 123 - 27
src/views/login/index.vue

@@ -7,31 +7,36 @@
              auto-complete="on"
              label-position="left">
       <div class="title-container">
-        <h3 class="title">大雅乐盟后台管理系统</h3>
+        <img src="@/assets/images/base/login-logo.png"
+             alt="">
       </div>
 
-      <el-form-item prop="username">
+      <el-form-item prop="username"
+                    class='logitem'>
         <span class="svg-container">
           <svg-icon icon-class="user" />
         </span>
         <el-input ref="username"
                   v-model="loginForm.username"
-                  placeholder="Username"
+                  placeholder="请输入用户名"
+                  class='login-input'
                   name="username"
                   type="text"
                   tabindex="1"
                   auto-complete="on" />
       </el-form-item>
 
-      <el-form-item prop="password">
+      <el-form-item prop="password"
+                    class='logitem'>
         <span class="svg-container">
           <svg-icon icon-class="password" />
         </span>
         <el-input :key="passwordType"
                   ref="password"
+                  class='login-input'
                   v-model="loginForm.password"
                   :type="passwordType"
-                  placeholder="Password"
+                  placeholder="请输入密码"
                   name="password"
                   tabindex="2"
                   auto-complete="on"
@@ -42,14 +47,14 @@
         </span>
       </el-form-item>
 
-      <el-button :loading="loading"
-                 type="primary"
-                 style="width:100%;margin-bottom:30px;"
-                 @click.native.prevent="handleLogin">登录</el-button>
-
-      <div class="tips">
-        <span style="margin-right:20px;">username: admin</span>
-        <span>password: any</span>
+      <div class="loginBtn"
+           style="width:100%;margin-bottom:30px;"
+           @click="handleLogin">登录</div>
+      <div class='remberBox'
+           @click='saveUserInfo'>
+        <div class="dotWrap">
+          <div :class="isSaveUserInfo?'active':''"></div>
+        </div>记住密码
       </div>
     </el-form>
   </div>
@@ -63,22 +68,22 @@ export default {
   data () {
     const validateUsername = (rule, value, callback) => {
       if (!validUsername(value)) {
-        callback(new Error("Please enter the correct user name"));
+        callback(new Error("请输入用户名"));
       } else {
         callback();
       }
     };
     const validatePassword = (rule, value, callback) => {
       if (value.length < 6) {
-        callback(new Error("The password can not be less than 6 digits"));
+        callback(new Error("密码必须大于六位"));
       } else {
         callback();
       }
     };
     return {
       loginForm: {
-        username: "admin",
-        password: "111111"
+        username: "",
+        password: ""
       },
       loginRules: {
         username: [
@@ -90,9 +95,14 @@ export default {
       },
       loading: false,
       passwordType: "password",
-      redirect: undefined
+      redirect: undefined,
+      isSaveUserInfo: true
     };
   },
+  mounted () {
+    this.loginForm.username = localStorage.getItem('username');
+    this.loginForm.password = localStorage.getItem('password');
+  },
   watch: {
     $route: {
       handler: function (route) {
@@ -113,23 +123,34 @@ export default {
       });
     },
     handleLogin () {
+      // 判断是否点击了记住密码 =>  存储密码
+      if (this.isSaveUserInfo) {
+        localStorage.setItem('username', this.loginForm.username);
+        localStorage.setItem('password', this.loginForm.password);
+      } else {
+        localStorage.setItem('username', '');
+        localStorage.setItem('password', '');
+      }
       this.$refs.loginForm.validate(valid => {
+
         if (valid) {
-          this.loading = true;
+
           this.$store
             .dispatch("user/login", this.loginForm)
             .then(() => {
+              console.log('登录成功');
               this.$router.push({ path: this.redirect || "/" });
-              this.loading = false;
             })
             .catch(() => {
-              this.loading = false;
             });
         } else {
-          console.log("error submit!!");
+          console.log("登录错误");
           return false;
         }
       });
+    },
+    saveUserInfo () {
+      this.isSaveUserInfo = !this.isSaveUserInfo;
     }
   }
 };
@@ -138,7 +159,70 @@ export default {
 <style lang="scss">
 /* 修复input 背景不协调 和光标变色 */
 /* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
+.loginBtn {
+  background-color: #777 !important;
+  text-align: center;
+  width: 100%;
+  height: 51px;
+  line-height: 51px;
+  color: #fff;
+  border-radius: 25px;
+  cursor: pointer;
+  margin-bottom: 10px !important;
+}
+::-webkit-input-placeholder {
+  /* WebKit browsers */
+  color: #444;
+  font-size: 16px;
+}
+
+::-moz-placeholder {
+  /* Mozilla Firefox 19+ */
+  color: #444;
+  font-size: 16px;
+}
 
+:-ms-input-placeholder {
+  /* Internet Explorer 10+ */
+  color: #444;
+  font-size: 16px;
+}
+.logitem {
+  border-radius: 25px !important;
+  border: 1px solid #444 !important;
+  background-color: transparent !important;
+}
+.login-container .el-input input {
+  color: #444 !important;
+  caret-color: #444 !important;
+}
+.remberBox {
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-end;
+  margin-bottom: 50px;
+  align-items: center;
+  cursor: pointer;
+  .dotWrap {
+    width: 18px;
+    height: 18px;
+    border: 1px solid #444;
+    border-radius: 50%;
+    margin-right: 8px;
+    position: relative;
+    overflow: hidden;
+    .active {
+      width: 10px;
+      height: 10px;
+      background-color: #444;
+      border-radius: 50%;
+      overflow: hidden;
+      position: absolute;
+      top: 3px;
+      left: 3px;
+    }
+  }
+}
 $bg: #283443;
 $light_gray: #fff;
 $cursor: #fff;
@@ -190,16 +274,22 @@ $light_gray: #eee;
 .login-container {
   min-height: 100%;
   width: 100%;
-  background-color: $bg;
+  // background-color: $bg;
+  background: url("../../assets/images/base/login-bg.png") no-repeat 100% 100%;
+  background-size: cover;
   overflow: hidden;
 
   .login-form {
     position: relative;
-    width: 520px;
+    width: 26%;
     max-width: 100%;
-    padding: 160px 35px 0;
-    margin: 0 auto;
+    padding: 0px 35px;
+    margin: 12% auto 0;
     overflow: hidden;
+    background-color: #fff;
+    opacity: 0.85;
+    box-shadow: 0px 0px 12px 0px rgba(0, 0, 0, 0.66);
+    border-radius: 20px;
   }
 
   .tips {
@@ -224,7 +314,13 @@ $light_gray: #eee;
 
   .title-container {
     position: relative;
-
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    padding: 30px 0;
+    img {
+      width: 30%;
+    }
     .title {
       font-size: 26px;
       color: $light_gray;

+ 16 - 16
vue.config.js

@@ -2,7 +2,7 @@
 const path = require('path')
 const defaultSettings = require('./src/settings.js')
 
-function resolve(dir) {
+function resolve (dir) {
   return path.join(__dirname, dir)
 }
 
@@ -13,7 +13,7 @@ const name = defaultSettings.title || 'vue Admin Template' // page title
 // For example, Mac: sudo npm run
 // You can change the port by the following methods:
 // port = 9528 npm run dev OR npm run dev --port = 9528
-const port = process.env.port || process.env.npm_config_port || 9528 // dev port
+// const port = process.env.port || process.env.npm_config_port || 9528 // dev port
 
 // All configuration item explanations can be find in https://cli.vuejs.org/config/
 module.exports = {
@@ -27,27 +27,27 @@ module.exports = {
   publicPath: './',
   outputDir: 'dist',
   assetsDir: 'static',
-  lintOnSave: process.env.NODE_ENV === 'development',
+  lintOnSave: false,
   productionSourceMap: false,
   devServer: {
-    port: port,
+    // port: port,
     open: true,
-    overlay: {
-      warnings: false,
-      errors: true
-    },
+    // overlay: {
+    //   warnings: false,
+    //   errors: true
+    // },
     proxy: {
       // change xxx-api/login => mock/login
       // detail: https://cli.vuejs.org/config/#devserver-proxy
-      [process.env.VUE_APP_BASE_API]: {
-        target: `http://127.0.0.1:${port}/mock`,
+      '/api-auth': {
+        target: 'http://47.99.212.176:8000',
         changeOrigin: true,
         pathRewrite: {
-          ['^' + process.env.VUE_APP_BASE_API]: ''
+          '^api-auth': ''
         }
-      }
+      },
+
     },
-    after: require('./mock/mock-server.js')
   },
   configureWebpack: {
     // provide the app's title in webpack's name field, so that
@@ -59,7 +59,7 @@ module.exports = {
       }
     }
   },
-  chainWebpack(config) {
+  chainWebpack (config) {
     config.plugins.delete('preload') // TODO: need test
     config.plugins.delete('prefetch') // TODO: need test
 
@@ -92,7 +92,7 @@ module.exports = {
       .end()
 
     config
-    // https://webpack.js.org/configuration/devtool/#development
+      // https://webpack.js.org/configuration/devtool/#development
       .when(process.env.NODE_ENV === 'development',
         config => config.devtool('cheap-source-map')
       )
@@ -104,7 +104,7 @@ module.exports = {
             .plugin('ScriptExtHtmlWebpackPlugin')
             .after('html')
             .use('script-ext-html-webpack-plugin', [{
-            // `runtime` must same as runtimeChunk name. default is `runtime`
+              // `runtime` must same as runtimeChunk name. default is `runtime`
               inline: /runtime\..*\.js$/
             }])
             .end()