Commit 508d71474f01eb94f185082d8fbede933606e6a0

Authored by Adam
Exists in master

Merge branch 'master' into 'master'

Master

See merge request !4
mock/mock-server.js
1 const chokidar = require('chokidar') 1 const chokidar = require('chokidar')
2 const bodyParser = require('body-parser') 2 const bodyParser = require('body-parser')
3 const chalk = require('chalk') 3 const chalk = require('chalk')
4 const path = require('path') 4 const path = require('path')
5 5
6 const mockDir = path.join(process.cwd(), 'mock') 6 const mockDir = path.join(process.cwd(), 'mock')
7 7
8 function registerRoutes(app) { 8 function registerRoutes(app) {
9 let mockLastIndex 9 let mockLastIndex
10 const { default: mocks } = require('./index.js') 10 const { default: mocks } = require('./index.js')
11 for (const mock of mocks) { 11 for (const mock of mocks) {
12 app[mock.type](mock.url, mock.response) 12 app[mock.type](mock.url, mock.response)
13 mockLastIndex = app._router.stack.length 13 mockLastIndex = app._router.stack.length
14 } 14 }
15 const mockRoutesLength = Object.keys(mocks).length 15 const mockRoutesLength = Object.keys(mocks).length
16 return { 16 return {
17 mockRoutesLength: mockRoutesLength, 17 mockRoutesLength: mockRoutesLength,
18 mockStartIndex: mockLastIndex - mockRoutesLength 18 mockStartIndex: mockLastIndex - mockRoutesLength
19 } 19 }
20 } 20 }
21 21
22 function unregisterRoutes() { 22 function unregisterRoutes() {
23 Object.keys(require.cache).forEach(i => { 23 Object.keys(require.cache).forEach(i => {
24 if (i.includes(mockDir)) { 24 if (i.includes(mockDir)) {
25 delete require.cache[require.resolve(i)] 25 delete require.cache[require.resolve(i)]
26 } 26 }
27 }) 27 })
28 } 28 }
29 29
30 module.exports = app => { 30 module.exports = app => {
31 // es6 polyfill 31 // es6 polyfill
32 require('@babel/register') 32 require('@babel/register')
33 33
34 // parse app.body 34 // parse app.body
35 // https://expressjs.com/en/4x/api.html#req.body 35 // https://expressjs.com/en/4x/api.html#req.body
36 app.use(bodyParser.json()) 36 app.use(bodyParser.json())
37 app.use(bodyParser.urlencoded({ 37 app.use(bodyParser.urlencoded({
38 extended: true 38 extended: true
39 })) 39 }))
40 40
41 const mockRoutes = registerRoutes(app) 41 const mockRoutes = registerRoutes(app)
42 var mockRoutesLength = mockRoutes.mockRoutesLength 42 var mockRoutesLength = mockRoutes.mockRoutesLength
43 var mockStartIndex = mockRoutes.mockStartIndex 43 var mockStartIndex = mockRoutes.mockStartIndex
44 44
45 // watch files, hot reload mock server 45 // watch files, hot reload mock server
46 chokidar.watch(mockDir, { 46 chokidar.watch(mockDir, {
47 ignored: /mock-server/, 47 ignored: /mock-server/,
48 ignoreInitial: true 48 ignoreInitial: true
49 }).on('all', (event, path) => { 49 }).on('all', (event, path) => {
50 if (event === 'change' || event === 'add') { 50 if (event === 'change' || event === 'add') {
51 try { 51 try {
52 // remove mock routes stack 52 // remove mock routes stack
53 app._router.stack.splice(mockStartIndex, mockRoutesLength) 53 app._router.stack.splice(mockStartIndex, mockRoutesLength)
54 54
55 // clear routes cache 55 // clear routes cache
56 unregisterRoutes() 56 unregisterRoutes()
57 57
58 const mockRoutes = registerRoutes(app) 58 const mockRoutes = registerRoutes(app)
59 mockRoutesLength = mockRoutes.mockRoutesLength 59 mockRoutesLength = mockRoutes.mockRoutesLength
60 mockStartIndex = mockRoutes.mockStartIndex 60 mockStartIndex = mockRoutes.mockStartIndex
61 61
62 console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed ${path}`)) 62 console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed ${path}`))
63 } catch (error) { 63 } catch (error) {
64 console.log(chalk.redBright(error)) 64 console.error(chalk.redBright(error))
65 } 65 }
66 } 66 }
67 }) 67 })
68 } 68 }
69 69
1
2 const tokens = { 1 const tokens = {
3 admin: { 2 admin: {
4 token: 'admin-token' 3 token: 'admin-token'
5 }, 4 },
6 assistant: { 5 assistant: {
7 token: 'assistant-token' 6 token: 'assistant-token'
8 }, 7 },
9 editor: { 8 runner: {
10 token: 'editor-token' 9 token: 'runner-token'
11 }, 10 },
12 shoper: { 11 shoper: {
13 token: 'shoper-token' 12 token: 'shoper-token'
14 } 13 }
15 } 14 }
16 15
17 const users = { 16 const users = {
18 'admin-token': {//管理员 17 'admin-token': { //管理员
19 roles: ['admin'], 18 roles: ['admin'],
20 introduction: 'I am a super administrator', 19 introduction: 'I am a super administrator',
21 avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', 20 avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
22 name: 'Super Admin' 21 name: 'Super Admin'
23 }, 22 },
24 'assistant-token': {//管理员助理 23 'assistant-token': { //管理员助理
25 roles: ['assistant'], 24 roles: ['assistant'],
26 introduction: 'I am a assistant of administrator', 25 introduction: 'I am a assistant of administrator',
27 avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', 26 avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
28 name: 'Super Admin' 27 name: 'assistant Admin'
29 }, 28 },
30 'editor-token': {//运营人员 29 'runner-token': { //运营人员
31 roles: ['editor'], 30 roles: ['runner'],
32 introduction: 'I am an editor', 31 introduction: 'I am an runner',
33 avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', 32 avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
34 name: 'Normal Editor' 33 name: 'Normal runner'
35 }, 34 },
36 'shoper-token': {//供应商 35 'shoper-token': { //供应商
37 roles: ['shoper'], 36 roles: ['shoper'],
38 introduction: 'I am an shoper', 37 introduction: 'I am an shoper',
39 avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', 38 avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
40 name: 'Normal Editor' 39 name: 'Normal shoper'
41 } 40 }
42 } 41 }
43 42
44 export default [ 43 export default [{ // user login
45 // user login
46 {
47 url: '/yp/user/login', 44 url: '/yp/user/login',
48 type: 'post', 45 type: 'post',
49 response: config => { 46 response: config => {
50 const { username } = config.body 47 console.log('config-------->', config.body);
51 const token = tokens[username] 48 const {
52 // mock error 49 username,
53 if (!token) { 50 password
51 } = config.body;
52 if (username == 'admin' && password == '111111') {
53 const token = tokens[username];
54 if (!token) {
55 return {
56 code: 60204,
57 message: 'Account and password are incorrect.'
58 }
59 } else {
60 return {
61 code: 20000,
62 data: token
63 }
64 }
65 } else {
54 return { 66 return {
55 code: 60204, 67 code: 60204,
56 message: 'Account and password are incorrect.' 68 message: 'Account and password are incorrect.'
57 } 69 }
58 } 70 }
59
60 return {
61 code: 20000,
62 data: token
63 }
64 } 71 }
65 }, 72 },
66 73
67 // get user info 74 // get user info
68 { 75 {
69 url: '/yp/user/info\.*', 76 url: '/yp/user/info\.*',
70 type: 'get', 77 type: 'get',
71 response: config => { 78 response: config => {
72 const { token } = config.query 79 const {
80 token
81 } = config.query
73 const info = users[token] 82 const info = users[token]
74 83
75 // mock error 84 // mock error
76 if (!info) { 85 if (!info) {
77 return { 86 return {
78 code: 50008, 87 code: 50008,
79 message: 'Login failed, unable to get user details.' 88 message: 'Login failed, unable to get user details.'
80 } 89 }
81 } 90 }
82 91
83 return { 92 return {
84 code: 20000, 93 code: 20000,
85 data: info 94 data: info
86 } 95 }
87 } 96 }
88 }, 97 },
89 98
90 // user logout 99 // user logout
91 { 100 {
92 url: '/yp/user/logout', 101 url: '/yp/user/logout',
93 type: 'post', 102 type: 'post',
94 response: _ => { 103 response: _ => {
1 import request from '@/utils/request' 1 import request from '@/utils/request'
2 // var qs = require('Qs');
2 3
3 export function login(data) { 4 export function login(data) {
4 console.log('login....', data) 5 console.log('login.1111...', data)
5 return request({ 6 return request({
6 url: '/yp/user/login', 7 // url: '/yp/user/login',
8 url: '/yp.user.login.php',
7 method: 'post', 9 method: 'post',
8 data 10 headers: {
9 }) 11 'Content-type': 'application/x-www-form-urlencoded'
12 },
13 data,
14 // responseType: 'text/plain',
15 // onDownloadProgress: false,
16 // onUploadProgress: true,
17 // proxy: {}
18 });
10 } 19 }
11 20
12 export function getInfo(token) { 21 export function getInfo(token) {
13 console.log('getInfo....', token) 22 console.log('getInfo....', token)
14 return request({ 23 return request({
15 url: '/yp/user/info', 24 url: '/yp/user/info',
16 method: 'get', 25 method: 'get',
17 params: { token } 26 params: {
27 token
28 }
18 }) 29 })
19 } 30 }
20 31
21 export function list(token) { 32 export function list(token) {
22 console.log('listUser....', token) 33 console.log('listUser....', token)
23 return request({ 34 return request({
24 url: '/yp/user/list', 35 url: '/yp/user/list',
25 method: 'get', 36 method: 'get',
26 params: { token } 37 params: {
38 token
39 }
27 }) 40 })
28 } 41 }
29 42
30 export function add(token) { 43 export function add(token) {
31 console.log('addUser....', token) 44 console.log('addUser....', token)
32 return request({ 45 return request({
33 url: '/yp/user/add', 46 url: '/yp/user/add',
34 method: 'get', 47 method: 'get',
35 params: { token } 48 params: {
49 token
50 }
36 }) 51 })
37 } 52 }
38 53
39 export function modi(token) { 54 export function modi(token) {
40 console.log('modiUser....', token) 55 console.log('modiUser....', token)
41 return request({ 56 return request({
42 url: '/yp/user/modi', 57 url: '/yp/user/modi',
43 method: 'get', 58 method: 'get',
44 params: { token } 59 params: {
60 token
61 }
45 }) 62 })
46 } 63 }
47 64
48 export function logout() { 65 export function logout() {
49 console.log('logout....') 66 console.log('logout....')
50 return request({ 67 return request({
51 url: '/yp/user/logout', 68 url: '/yp/user/logout',
52 method: 'post' 69 method: 'post'
53 }) 70 })
54 } 71 }
55 72
src/store/modules/user.js
1 import { login, logout, getInfo } from '@/api/user' 1 import { login, logout, getInfo } from '@/api/user'
2 import { getToken, setToken, removeToken } from '@/utils/auth' 2 import { getToken, setToken, removeToken } from '@/utils/auth'
3 import { resetRouter } from '@/router' 3 import { resetRouter } from '@/router'
4 4
5 const getDefaultState = () => { 5 const getDefaultState = () => {
6 return { 6 return {
7 token: getToken(), 7 token: getToken(),
8 name: '', 8 name: '',
9 avatar: '', 9 avatar: '',
10 roles: [] 10 roles: []
11 } 11 }
12 } 12 }
13 13
14 const state = getDefaultState() 14 const state = getDefaultState()
15 15
16 const mutations = { 16 const mutations = {
17 RESET_STATE: (state) => { 17 RESET_STATE: (state) => {
18 Object.assign(state, getDefaultState()) 18 Object.assign(state, getDefaultState())
19 }, 19 },
20 SET_TOKEN: (state, token) => { 20 SET_TOKEN: (state, token) => {
21 state.token = token 21 state.token = token
22 }, 22 },
23 SET_NAME: (state, name) => { 23 SET_NAME: (state, name) => {
24 state.name = name 24 state.name = name
25 }, 25 },
26 SET_AVATAR: (state, avatar) => { 26 SET_AVATAR: (state, avatar) => {
27 state.avatar = avatar 27 state.avatar = avatar
28 }, 28 },
29 SET_ROLES: (state, roles) => { 29 SET_ROLES: (state, roles) => {
30 state.roles = roles 30 state.roles = roles
31 } 31 }
32 } 32 }
33 33
34 const actions = { 34 const actions = {
35 // user login 35 // user login
36 login({ commit }, userInfo) { 36 login({ commit }, userInfo) {
37 const { username, password } = userInfo 37 const { username, password } = userInfo
38 return new Promise((resolve, reject) => { 38 return new Promise((resolve, reject) => {
39 login({ username: username.trim(), password: password }).then(response => { 39 login({ username: username.trim(), password: password }).then(response => {
40 const { data } = response 40 const { data } = response
41 console.log('action------->login------->处理', data);
41 commit('SET_TOKEN', data.token) 42 commit('SET_TOKEN', data.token)
42 setToken(data.token) 43 setToken(data.token)
43 resolve() 44 resolve()
44 }).catch(error => { 45 }).catch(error => {
45 reject(error) 46 reject(error)
46 }) 47 })
47 }) 48 })
48 }, 49 },
49 50
50 // get user info 51 // get user info
51 getInfo({ commit, state }) { 52 getInfo({ commit, state }) {
52 return new Promise((resolve, reject) => { 53 return new Promise((resolve, reject) => {
53 getInfo(state.token).then(response => { 54 getInfo(state.token).then(response => {
54 const { data } = response 55 const { data } = response
55
56 if (!data) { 56 if (!data) {
57 reject('Verification failed, please Login again.') 57 reject('Verification failed, please Login again.')
58 } 58 }
59
60 const { roles, name, avatar } = data 59 const { roles, name, avatar } = data
61
62 // roles must be a non-empty array 60 // roles must be a non-empty array
63 if (!roles || roles.length <= 0) { 61 if (!roles || roles.length <= 0) {
64 reject('getInfo: roles must be a non-null array!') 62 reject('getInfo: roles must be a non-null array!')
65 } 63 }
66
67 commit('SET_ROLES', roles) 64 commit('SET_ROLES', roles)
68 commit('SET_NAME', name) 65 commit('SET_NAME', name)
69 commit('SET_AVATAR', avatar) 66 commit('SET_AVATAR', avatar)
70 resolve(data) 67 resolve(data)
71 }).catch(error => { 68 }).catch(error => {
72 reject(error) 69 reject(error)
73 }) 70 })
74 }) 71 })
75 }, 72 },
76 73
77 // user logout 74 // user logout
78 logout({ commit, state }) { 75 logout({ commit, state }) {
79 return new Promise((resolve, reject) => { 76 return new Promise((resolve, reject) => {
80 logout(state.token).then(() => { 77 logout(state.token).then(() => {
81 removeToken() // must remove token first 78 removeToken() // must remove token first
82 resetRouter() 79 resetRouter()
83 commit('RESET_STATE') 80 commit('RESET_STATE')
84 resolve() 81 resolve()
85 }).catch(error => { 82 }).catch(error => {
86 reject(error) 83 reject(error)
87 }) 84 })
88 }) 85 })
89 }, 86 },
90 87
91 // remove token 88 // remove token
92 resetToken({ commit }) { 89 resetToken({ commit }) {
93 return new Promise(resolve => { 90 return new Promise(resolve => {
94 removeToken() // must remove token first 91 removeToken() // must remove token first
95 commit('RESET_STATE') 92 commit('RESET_STATE')
96 resolve() 93 resolve()
97 }) 94 })
98 } 95 }
99 } 96 }
100 97
101 export default { 98 export default {
102 namespaced: true, 99 namespaced: true,
103 state, 100 state,
104 mutations, 101 mutations,
105 actions 102 actions
106 } 103 }
107 104
src/utils/request.js
1 import axios from 'axios' 1 import axios from 'axios'
2 import { MessageBox, Message } from 'element-ui' 2 import {
3 MessageBox,
4 Message
5 } from 'element-ui'
3 import store from '@/store' 6 import store from '@/store'
4 import { getToken } from '@/utils/auth' 7 import {
8 getToken
9 } from '@/utils/auth'
5 10
6 // create an axios instance 11 // create an axios instance
7 // 创建axios实例 12 // 创建axios实例
8 const service = axios.create({ 13 const service = axios.create({
14 // baseURL: '', // url = base url + request url
9 baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url 15 baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
10 // withCredentials: true, // send cookies when cross-domain requests 16 // withCredentials: true, // send cookies when cross-domain requests
11 timeout: 5000 // request timeout 17 timeout: 5000, // request timeout
18 headers: {
19 'Content-Type': 'application/x-www-form-urlencoded'
20 }
12 }) 21 })
13 22
14 // request interceptor 23 // request interceptor
15 // request拦截器 24 // request拦截器
16 service.interceptors.request.use( 25 service.interceptors.request.use(
17 config => { 26 config => {
18 // do something before request is sent 27 // do something before request is sent
19 console.log('do something before request is sent') 28 // console.log('do something before request is sent')
20 if (store.getters.token) { 29 if (store.getters.token) {
21 console.log('[X-Token] is a custom headers key') 30 // console.log('[X-Token] is a custom headers key')
22 // let each request carry token 31 // let each request carry token
23 // ['X-Token'] is a custom headers key 32 // ['X-Token'] is a custom headers key
24 // please modify it according to the actual situation 33 // please modify it according to the actual situation
25 config.headers['X-Token'] = getToken() 34 config.headers['X-Token'] = getToken();
35 config.headers['Content-Type'] = 'application/x-www-form-urlencoded';
36 // var token = getToken()
37 // Object.assign(config.headers, { 'token': token })
26 } 38 }
27 return config 39 return config
28 }, 40 },
29 error => { 41 error => {
30 console.log('do something with request error') 42 // console.log('do something with request error')
31 // do something with request error 43 // do something with request error
32 console.log(error) // for debug 44 console.error(error) // for debug
33 return Promise.reject(error) 45 return Promise.reject(error)
34 } 46 }
35 ) 47 )
36 48
37 // response interceptor 49 // response interceptor
38 // respone拦截器 50 // respone拦截器
39 service.interceptors.response.use( 51 service.interceptors.response.use(
40 /** 52 /**
41 * If you want to get http information such as headers or status 53 * If you want to get http information such as headers or status
42 * Please return response => response 54 * Please return response => response
43 */ 55 */
44 56
45 /** 57 /**
46 * Determine the request status by custom code 58 * Determine the request status by custom code
47 * Here is just an example 59 * Here is just an example
48 * You can also judge the status by HTTP Status Code 60 * You can also judge the status by HTTP Status Code
49 */ 61 */
50 response => { 62 response => {
51 const res = response.data 63 const res = response.data
64 console.log('返回的数据-------->', res);
52 /** 65 /**
53 * 下面的注释为通过response自定义code来标示请求状态,当code返回如下情况为权限有问题,登出并返回到登录页 66 * 下面的注释为通过response自定义code来标示请求状态,当code返回如下情况为权限有问题,登出并返回到登录页
54 * 如通过xmlhttprequest 状态码标识 逻辑可写在下面error中 67 * 如通过xmlhttprequest 状态码标识 逻辑可写在下面error中
55 */ 68 */
56 console.log('if the custom code is not 20000, it is judged as an error.') 69 // console.log('if the custom code is not 20000, it is judged as an error.')
57 // if the custom code is not 20000, it is judged as an error.
58 if (res.code !== 20000) { 70 if (res.code !== 20000) {
59 Message({ 71 Message({
60 message: res.message || 'Error', 72 message: res.message || 'Error',
61 type: 'error', 73 type: 'error',
62 duration: 5 * 1000 74 duration: 5 * 1000
63 }) 75 })
64 76
65 // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
66 // 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了; 77 // 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了;
67 if (res.code === 50008 || res.code === 50012 || res.code === 50014) { 78 if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
68 // to re-login 79 // to re-login
69 // MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', { 80 // MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
70 MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', { 81 MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', {
71 // confirmButtonText: 'Re-Login', 82 // confirmButtonText: 'Re-Login',
72 confirmButtonText: '重新登录', 83 confirmButtonText: '重新登录',
73 // cancelButtonText: 'Cancel', 84 // cancelButtonText: 'Cancel',
74 cancelButtonText: '取消', 85 cancelButtonText: '取消',
75 type: 'warning' 86 type: 'warning'
76 }).then(() => { 87 }).then(() => {
77 store.dispatch('user/resetToken').then(() => { 88 store.dispatch('user/resetToken').then(() => {
78 location.reload()// 为了重新实例化vue-router对象 避免bug 89 location.reload() // 为了重新实例化vue-router对象 避免bug
79 }) 90 })
80 }) 91 })
81 } 92 }
82 return Promise.reject(new Error(res.message || 'Error')) 93 return Promise.reject(new Error(res.message || 'Error'))
83 } else { 94 } else {
84 return res 95 // const token = res.data.token;
96 console.log('进入20000号判断-------->', res);
97 return res;
85 } 98 }
86 }, 99 },
87 error => { 100 error => {
88 console.log('err' + error) // for debug 101 console.error('===============发生错误!!!!!===============' + error) // for debug
89 Message({ 102 Message({
90 message: error.message, 103 message: error.message,
91 type: 'error', 104 type: 'error',
92 duration: 5 * 1000 105 duration: 5 * 1000
93 }) 106 })
94 return Promise.reject(error) 107 return Promise.reject(error)
95 } 108 }
96 ) 109 )
97 110
src/views/login/index.vue
1 <template> 1 <template>
2 <div class="login-container"> 2 <div class="login-container">
3 <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on" label-position="left"> 3 <el-form
4 4 ref="loginForm"
5 :model="loginForm"
6 :rules="loginRules"
7 class="login-form"
8 auto-complete="on"
9 label-position="left"
10 >
5 <div class="title-container"> 11 <div class="title-container">
6 <h3 class="title">Login Form</h3> 12 <h3 class="title">鱼皮系统</h3>
7 </div> 13 </div>
8 14
9 <el-form-item prop="username"> 15 <el-form-item prop="username">
10 <span class="svg-container"> 16 <span class="svg-container">
11 <svg-icon icon-class="user" /> 17 <svg-icon icon-class="user" />
12 </span> 18 </span>
13 <el-input 19 <el-input
14 ref="username" 20 ref="username"
15 v-model="loginForm.username" 21 v-model="loginForm.username"
16 placeholder="Username" 22 placeholder="Username"
17 name="username" 23 name="username"
18 type="text" 24 type="text"
19 tabindex="1" 25 tabindex="1"
20 auto-complete="on" 26 auto-complete="on"
21 /> 27 />
22 </el-form-item> 28 </el-form-item>
23 29
24 <el-form-item prop="password"> 30 <el-form-item prop="password">
25 <span class="svg-container"> 31 <span class="svg-container">
26 <svg-icon icon-class="password" /> 32 <svg-icon icon-class="password" />
27 </span> 33 </span>
28 <el-input 34 <el-input
29 :key="passwordType" 35 :key="passwordType"
30 ref="password" 36 ref="password"
31 v-model="loginForm.password" 37 v-model="loginForm.password"
32 :type="passwordType" 38 :type="passwordType"
33 placeholder="Password" 39 placeholder="Password"
34 name="password" 40 name="password"
35 tabindex="2" 41 tabindex="2"
36 auto-complete="on" 42 auto-complete="on"
37 @keyup.enter.native="handleLogin" 43 @keyup.enter.native="handleLogin"
38 /> 44 />
39 <span class="show-pwd" @click="showPwd"> 45 <span class="show-pwd" @click="showPwd">
40 <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" /> 46 <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
41 </span> 47 </span>
42 </el-form-item> 48 </el-form-item>
43 <!-- <el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">reg</el-button> --> 49 <!-- <el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">reg</el-button> -->
44 <el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">Login</el-button> 50 <el-button
51 :loading="loading"
52 type="primary"
53 style="width:100%;margin-bottom:30px;"
54 @click.native.prevent="handleLogin"
55 >Login</el-button>
45 56
46 <div class="tips"> 57 <div class="tips">
47 <span style="margin-right:20px;">username: admin</span> 58 <span style="margin-right:20px;">username: admin</span>
48 <span> password: any</span> 59 <span>password: any</span>
49 </div> 60 </div>
50
51 </el-form> 61 </el-form>
52 </div> 62 </div>
53 </template> 63 </template>
54 64
55 <script> 65 <script>
56 import { validUsername } from '@/utils/validate' 66 import { validUsername } from "@/utils/validate";
57 67
58 export default { 68 export default {
59 name: 'Login', 69 name: "Login",
60 data() { 70 data() {
61 const validateUsername = (rule, value, callback) => { 71 const validateUsername = (rule, value, callback) => {
62 if (!validUsername(value)) { 72 if (!validUsername(value)) {
63 callback(new Error('Please enter the correct user name')) 73 callback(new Error("Please enter the correct user name"));
64 } else { 74 } else {
65 callback() 75 callback();
66 } 76 }
67 } 77 };
68 const validatePassword = (rule, value, callback) => { 78 const validatePassword = (rule, value, callback) => {
69 if (value.length < 6) { 79 if (value.length < 6) {
70 callback(new Error('The password can not be less than 6 digits')) 80 callback(new Error("The password can not be less than 6 digits"));
71 } else { 81 } else {
72 callback() 82 callback();
73 } 83 }
74 } 84 };
75 return { 85 return {
76 loginForm: { 86 loginForm: {
77 username: 'admin', 87 username: "admin",
78 password: '111111' 88 password: "111111"
79 }, 89 },
80 loginRules: { 90 loginRules: {
81 username: [{ required: true, trigger: 'blur', validator: validateUsername }], 91 username: [
82 password: [{ required: true, trigger: 'blur', validator: validatePassword }] 92 { required: true, trigger: "blur", validator: validateUsername }
93 ],
94 password: [
95 { required: true, trigger: "blur", validator: validatePassword }
96 ]
83 }, 97 },
84 loading: false, 98 loading: false,
85 passwordType: 'password', 99 passwordType: "password",
86 redirect: undefined 100 redirect: undefined
87 } 101 };
88 }, 102 },
89 watch: { 103 watch: {
90 $route: { 104 $route: {
91 handler: function(route) { 105 handler: function(route) {
92 this.redirect = route.query && route.query.redirect 106 this.redirect = route.query && route.query.redirect;
93 }, 107 },
94 immediate: true 108 immediate: true
95 } 109 }
96 }, 110 },
97 methods: { 111 methods: {
98 showPwd() { 112 showPwd() {
99 if (this.passwordType === 'password') { 113 if (this.passwordType === "password") {
100 this.passwordType = '' 114 this.passwordType = "";
101 } else { 115 } else {
102 this.passwordType = 'password' 116 this.passwordType = "password";
103 } 117 }
104 this.$nextTick(() => { 118 this.$nextTick(() => {
105 this.$refs.password.focus() 119 this.$refs.password.focus();
106 }) 120 });
107 }, 121 },
108 handleLogin() { 122 handleLogin() {
109 this.$refs.loginForm.validate(valid => { 123 this.$refs.loginForm.validate(valid => {
110 if (valid) { 124 if (valid) {
111 this.loading = true 125 this.loading = true;
112 this.$store.dispatch('user/login', this.loginForm).then(() => { 126 this.$store
113 this.$router.push({ path: this.redirect || '/' }) 127 .dispatch("user/login", this.loginForm)
114 this.loading = false 128 .then(() => {
115 }).catch(() => { 129 this.$router.push({ path: this.redirect || "/" });
116 this.loading = false 130 this.loading = false;
117 }) 131 console.log('this.redirect', this.$router);
132 })
133 .catch(res => {
134 console.log("res error------------>", res);
135 this.loading = false;
136 });
118 } else { 137 } else {
119 console.log('error submit!!') 138 console.log("error submit!!");
120 return false 139 return false;
121 } 140 }
122 }) 141 });
123 } 142 }
124 } 143 }
125 } 144 };
126 </script> 145 </script>
127 146
128 <style lang="scss"> 147 <style lang="scss">
129 /* 修复input 背景不协调 和光标变色 */ 148 /* 修复input 背景不协调 和光标变色 */
130 /* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */ 149 /* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
131 150
132 $bg:#283443; 151 $bg: #283443;
133 $light_gray:#fff; 152 $light_gray: #fff;
134 $cursor: #fff; 153 $cursor: #fff;
135 154
136 @supports (-webkit-mask: none) and (not (cater-color: $cursor)) { 155 @supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
137 .login-container .el-input input { 156 .login-container .el-input input {
138 color: $cursor; 157 color: $cursor;
139 } 158 }
140 } 159 }
141 160
142 /* reset element-ui css */ 161 /* reset element-ui css */
143 .login-container { 162 .login-container {
144 .el-input { 163 .el-input {
145 display: inline-block; 164 display: inline-block;
146 height: 47px; 165 height: 47px;
147 width: 85%; 166 width: 85%;
148 167
149 input { 168 input {
150 background: transparent; 169 background: transparent;
151 border: 0px; 170 border: 0px;
152 -webkit-appearance: none; 171 -webkit-appearance: none;
153 border-radius: 0px; 172 border-radius: 0px;
154 padding: 12px 5px 12px 15px; 173 padding: 12px 5px 12px 15px;
155 color: $light_gray; 174 color: $light_gray;
156 height: 47px; 175 height: 47px;
157 caret-color: $cursor; 176 caret-color: $cursor;
158 177
159 &:-webkit-autofill { 178 &:-webkit-autofill {
160 box-shadow: 0 0 0px 1000px $bg inset !important; 179 box-shadow: 0 0 0px 1000px $bg inset !important;
161 -webkit-text-fill-color: $cursor !important; 180 -webkit-text-fill-color: $cursor !important;
162 } 181 }
163 } 182 }
164 } 183 }
165 184
166 .el-form-item { 185 .el-form-item {
167 border: 1px solid rgba(255, 255, 255, 0.1); 186 border: 1px solid rgba(255, 255, 255, 0.1);
168 background: rgba(0, 0, 0, 0.1); 187 background: rgba(0, 0, 0, 0.1);
169 border-radius: 5px; 188 border-radius: 5px;
170 color: #454545; 189 color: #454545;
171 } 190 }
172 } 191 }
173 </style> 192 </style>
174 193
175 <style lang="scss" scoped> 194 <style lang="scss" scoped>
176 $bg:#2d3a4b; 195 $bg: #2d3a4b;
177 $dark_gray:#889aa4; 196 $dark_gray: #889aa4;
178 $light_gray:#eee; 197 $light_gray: #eee;
179 198
180 .login-container { 199 .login-container {
181 min-height: 100%; 200 min-height: 100%;
182 width: 100%; 201 width: 100%;
183 background-color: $bg; 202 background-color: $bg;
184 overflow: hidden; 203 overflow: hidden;
185 204
186 .login-form { 205 .login-form {
187 position: relative; 206 position: relative;
188 width: 520px; 207 width: 520px;
189 max-width: 100%; 208 max-width: 100%;
190 padding: 160px 35px 0; 209 padding: 160px 35px 0;
191 margin: 0 auto; 210 margin: 0 auto;
192 overflow: hidden; 211 overflow: hidden;
193 } 212 }
194 213
195 .tips { 214 .tips {
196 font-size: 14px; 215 font-size: 14px;
197 color: #fff; 216 color: #fff;
198 margin-bottom: 10px; 217 margin-bottom: 10px;
199 218
200 span { 219 span {
201 &:first-of-type { 220 &:first-of-type {
202 margin-right: 16px; 221 margin-right: 16px;
203 } 222 }
204 } 223 }
205 } 224 }
206 225
207 .svg-container { 226 .svg-container {
208 padding: 6px 5px 6px 15px; 227 padding: 6px 5px 6px 15px;
209 color: $dark_gray; 228 color: $dark_gray;
210 vertical-align: middle; 229 vertical-align: middle;
211 width: 30px; 230 width: 30px;
212 display: inline-block; 231 display: inline-block;
213 } 232 }
214 233
215 .title-container { 234 .title-container {
216 position: relative; 235 position: relative;
217 236
218 .title { 237 .title {
219 font-size: 26px; 238 font-size: 26px;
220 color: $light_gray; 239 color: $light_gray;
221 margin: 0px auto 40px auto; 240 margin: 0px auto 40px auto;
222 text-align: center; 241 text-align: center;
223 font-weight: bold; 242 font-weight: bold;
224 } 243 }
225 } 244 }
226 245
227 .show-pwd { 246 .show-pwd {
228 position: absolute; 247 position: absolute;
229 right: 10px; 248 right: 10px;
230 top: 7px; 249 top: 7px;
231 font-size: 16px; 250 font-size: 16px;
232 color: $dark_gray; 251 color: $dark_gray;
233 cursor: pointer; 252 cursor: pointer;
234 user-select: none; 253 user-select: none;
235 } 254 }
236 } 255 }
237 </style> 256 </style>
1 'use strict' 1 'use strict'
2 const path = require('path') 2 const path = require('path')
3 const defaultSettings = require('./src/settings.js') 3 const defaultSettings = require('./src/settings.js')
4 4
5 function resolve(dir) { 5 function resolve(dir) {
6 return path.join(__dirname, dir) 6 return path.join(__dirname, dir)
7 } 7 }
8 8
9 const name = defaultSettings.title || 'vue Admin Template' // page title 9 const name = defaultSettings.title || 'vue Admin Template' // page title
10 10
11 // If your port is set to 80, 11 // If your port is set to 80,
12 // use administrator privileges to execute the command line. 12 // use administrator privileges to execute the command line.
13 // For example, Mac: sudo npm run 13 // For example, Mac: sudo npm run
14 // You can change the port by the following methods: 14 // You can change the port by the following methods:
15 // port = 9528 npm run dev OR npm run dev --port = 9528 15 // port = 9528 npm run dev OR npm run dev --port = 9528
16 const port = process.env.port || process.env.npm_config_port || 9528 // dev port 16 const port = process.env.port || process.env.npm_config_port || 9528 // dev port
17 17
18 // All configuration item explanations can be find in https://cli.vuejs.org/config/ 18 // All configuration item explanations can be find in https://cli.vuejs.org/config/
19 module.exports = { 19 module.exports = {
20 /** 20 /**
21 * You will need to set publicPath if you plan to deploy your site under a sub path, 21 * You will need to set publicPath if you plan to deploy your site under a sub path,
22 * for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/, 22 * for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/,
23 * then publicPath should be set to "/bar/". 23 * then publicPath should be set to "/bar/".
24 * In most cases please use '/' !!! 24 * In most cases please use '/' !!!
25 * Detail: https://cli.vuejs.org/config/#publicpath 25 * Detail: https://cli.vuejs.org/config/#publicpath
26 */ 26 */
27 publicPath: '/', 27 publicPath: '/',
28 outputDir: 'dist', 28 outputDir: 'dist',
29 assetsDir: 'static', 29 assetsDir: 'static',
30 lintOnSave: process.env.NODE_ENV === 'development', 30 lintOnSave: process.env.NODE_ENV === 'development',
31 productionSourceMap: false, 31 productionSourceMap: false,
32 devServer: { 32 devServer: {
33 port: port, 33 port: port,
34 open: true, 34 open: true,
35 overlay: { 35 overlay: {
36 warnings: false, 36 warnings: false,
37 errors: true 37 errors: true
38 }, 38 },
39 before: require('./mock/mock-server.js') 39 before: require('./mock/mock-server.js')
40 }, 40 },
41 configureWebpack: { 41 configureWebpack: {
42 // provide the app's title in webpack's name field, so that 42 // provide the app's title in webpack's name field, so that
43 // it can be accessed in index.html to inject the correct title. 43 // it can be accessed in index.html to inject the correct title.
44 name: name, 44 name: name,
45 resolve: { 45 resolve: {
46 alias: { 46 alias: {
47 '@': resolve('src') 47 '@': resolve('src')
48 } 48 }
49 } 49 }
50 }, 50 },
51 chainWebpack(config) { 51 chainWebpack(config) {
52 config.plugins.delete('preload') // TODO: need test 52 config.plugins.delete('preload') // TODO: need test
53 config.plugins.delete('prefetch') // TODO: need test 53 config.plugins.delete('prefetch') // TODO: need test
54 54
55 // set svg-sprite-loader 55 // set svg-sprite-loader
56 config.module 56 config.module
57 .rule('svg') 57 .rule('svg')
58 .exclude.add(resolve('src/icons')) 58 .exclude.add(resolve('src/icons'))
59 .end() 59 .end()
60 config.module 60 config.module
61 .rule('icons') 61 .rule('icons')
62 .test(/\.svg$/) 62 .test(/\.svg$/)
63 .include.add(resolve('src/icons')) 63 .include.add(resolve('src/icons'))
64 .end() 64 .end()
65 .use('svg-sprite-loader') 65 .use('svg-sprite-loader')
66 .loader('svg-sprite-loader') 66 .loader('svg-sprite-loader')
67 .options({ 67 .options({
68 symbolId: 'icon-[name]' 68 symbolId: 'icon-[name]'
69 }) 69 })
70 .end() 70 .end()
71 71
72 // set preserveWhitespace 72 // set preserveWhitespace
73 config.module 73 config.module
74 .rule('vue') 74 .rule('vue')
75 .use('vue-loader') 75 .use('vue-loader')
76 .loader('vue-loader') 76 .loader('vue-loader')
77 .tap(options => { 77 .tap(options => {
78 options.compilerOptions.preserveWhitespace = true 78 options.compilerOptions.preserveWhitespace = true
79 return options 79 return options
80 }) 80 })
81 .end() 81 .end()
82 82
83 config 83 config
84 // https://webpack.js.org/configuration/devtool/#development 84 // https://webpack.js.org/configuration/devtool/#development
85 .when(process.env.NODE_ENV === 'development', 85 .when(process.env.NODE_ENV === 'development',
86 config => config.devtool('cheap-source-map') 86 config => config.devtool('cheap-source-map')
87 ) 87 )
88 88
89 config 89 config
90 .when(process.env.NODE_ENV !== 'development', 90 .when(process.env.NODE_ENV !== 'development',
91 config => { 91 config => {
92 config 92 config
93 .plugin('ScriptExtHtmlWebpackPlugin') 93 .plugin('ScriptExtHtmlWebpackPlugin')
94 .after('html') 94 .after('html')
95 .use('script-ext-html-webpack-plugin', [{ 95 .use('script-ext-html-webpack-plugin', [{
96 // `runtime` must same as runtimeChunk name. default is `runtime` 96 // `runtime` must same as runtimeChunk name. default is `runtime`
97 inline: /runtime\..*\.js$/ 97 inline: /runtime\..*\.js$/
98 }]) 98 }])
99 .end() 99 .end()
100 config 100 config
101 .optimization.splitChunks({ 101 .optimization.splitChunks({
102 chunks: 'all', 102 chunks: 'all',
103 cacheGroups: { 103 cacheGroups: {
104 libs: { 104 libs: {
105 name: 'chunk-libs', 105 name: 'chunk-libs',
106 test: /[\\/]node_modules[\\/]/, 106 test: /[\\/]node_modules[\\/]/,
107 priority: 10, 107 priority: 10,
108 chunks: 'initial' // only package third parties that are initially dependent 108 chunks: 'initial' // only package third parties that are initially dependent
109 }, 109 },
110 elementUI: { 110 elementUI: {
111 name: 'chunk-elementUI', // split elementUI into a single package 111 name: 'chunk-elementUI', // split elementUI into a single package
112 priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app 112 priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
113 test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm 113 test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
114 }, 114 },
115 commons: { 115 commons: {
116 name: 'chunk-commons', 116 name: 'chunk-commons',
117 test: resolve('src/components'), // can customize your rules 117 test: resolve('src/components'), // can customize your rules
118 minChunks: 3, // minimum common number 118 minChunks: 3, // minimum common number
119 priority: 5, 119 priority: 5,
120 reuseExistingChunk: true 120 reuseExistingChunk: true
121 } 121 }
122 } 122 }
123 }) 123 })
124 config.optimization.runtimeChunk('single') 124 config.optimization.runtimeChunk('single')
125 } 125 }
126 ) 126 )
127 } 127 }
128 } 128 }
129 129