Commit e4c36db6 authored by neogcg's avatar neogcg

2.22

parents d39501ef 97209ebb
# just a flag
ENV = 'development'
# base api
VUE_APP_BASE_API = '/dev-api'
# just a flag
ENV = 'production'
# base api
VUE_APP_BASE_API = '/prod-api'
NODE_ENV = production
# just a flag
ENV = 'staging'
# base api
VUE_APP_BASE_API = '/stage-api'
File added
const Mock = require('mockjs')
const { param2Obj } = require('./utils')
const user = require('./user')
const table = require('./table')
const mocks = [
...user,
...table
]
// for front mock
// please use it cautiously, it will redefine XMLHttpRequest,
// which will cause many of your third-party libraries to be invalidated(like progress event).
function mockXHR() {
// mock patch
// https://github.com/nuysoft/Mock/issues/300
Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
Mock.XHR.prototype.send = function() {
if (this.custom.xhr) {
this.custom.xhr.withCredentials = this.withCredentials || false
if (this.responseType) {
this.custom.xhr.responseType = this.responseType
}
}
this.proxy_send(...arguments)
}
function XHR2ExpressReqWrap(respond) {
return function(options) {
let result = null
if (respond instanceof Function) {
const { body, type, url } = options
// https://expressjs.com/en/4x/api.html#req
result = respond({
method: type,
body: JSON.parse(body),
query: param2Obj(url)
})
} else {
result = respond
}
return Mock.mock(result)
}
}
for (const i of mocks) {
Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response))
}
}
module.exports = {
mocks,
mockXHR
}
const chokidar = require('chokidar')
const bodyParser = require('body-parser')
const chalk = require('chalk')
const path = require('path')
const Mock = require('mockjs')
const mockDir = path.join(process.cwd(), 'mock')
function registerRoutes(app) {
let mockLastIndex
const { mocks } = require('./index.js')
const mocksForServer = mocks.map(route => {
return responseFake(route.url, route.type, route.response)
})
for (const mock of mocksForServer) {
app[mock.type](mock.url, mock.response)
mockLastIndex = app._router.stack.length
}
const mockRoutesLength = Object.keys(mocksForServer).length
return {
mockRoutesLength: mockRoutesLength,
mockStartIndex: mockLastIndex - mockRoutesLength
}
}
function unregisterRoutes() {
Object.keys(require.cache).forEach(i => {
if (i.includes(mockDir)) {
delete require.cache[require.resolve(i)]
}
})
}
// for mock server
const responseFake = (url, type, respond) => {
return {
url: new RegExp(`${process.env.VUE_APP_BASE_API}${url}`),
type: type || 'get',
response(req, res) {
console.log('request invoke:' + req.path)
res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond))
}
}
}
module.exports = app => {
// parse app.body
// https://expressjs.com/en/4x/api.html#req.body
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({
extended: true
}))
const mockRoutes = registerRoutes(app)
var mockRoutesLength = mockRoutes.mockRoutesLength
var mockStartIndex = mockRoutes.mockStartIndex
// watch files, hot reload mock server
chokidar.watch(mockDir, {
ignored: /mock-server/,
ignoreInitial: true
}).on('all', (event, path) => {
if (event === 'change' || event === 'add') {
try {
// remove mock routes stack
app._router.stack.splice(mockStartIndex, mockRoutesLength)
// clear routes cache
unregisterRoutes()
const mockRoutes = registerRoutes(app)
mockRoutesLength = mockRoutes.mockRoutesLength
mockStartIndex = mockRoutes.mockStartIndex
console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed ${path}`))
} catch (error) {
console.log(chalk.redBright(error))
}
}
})
}
const Mock = require('mockjs')
const data = Mock.mock({
'items|30': [{
id: '@id',
title: '@sentence(10, 20)',
'status|1': ['published', 'draft', 'deleted'],
author: 'name',
display_time: '@datetime',
pageviews: '@integer(300, 5000)'
}]
})
module.exports = [
{
url: '/vue-admin-template/table/list',
type: 'get',
response: config => {
const items = data.items
return {
code: 20000,
data: {
total: items.length,
items: items
}
}
}
}
]
const tokens = {
admin: {
token: 'admin-token'
},
editor: {
token: 'editor-token'
}
}
const users = {
'admin-token': {
roles: ['admin'],
introduction: 'I am a super administrator',
avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
name: 'Super Admin'
},
'editor-token': {
roles: ['editor'],
introduction: 'I am an editor',
avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
name: 'Normal Editor'
}
}
module.exports = [
// user login
{
url: '/vue-admin-template/user/login',
type: 'post',
response: config => {
const { username } = config.body
const token = tokens[username]
// mock error
if (!token) {
return {
code: 60204,
message: 'Account and password are incorrect.'
}
}
return {
code: 20000,
data: token
}
}
},
// get user info
{
url: '/vue-admin-template/user/info\.*',
type: 'get',
response: config => {
const { token } = config.query
const info = users[token]
// mock error
if (!info) {
return {
code: 50008,
message: 'Login failed, unable to get user details.'
}
}
return {
code: 20000,
data: info
}
}
},
// user logout
{
url: '/vue-admin-template/user/logout',
type: 'post',
response: _ => {
return {
code: 20000,
data: 'success'
}
}
}
]
/**
* @param {string} url
* @returns {Object}
*/
function param2Obj(url) {
const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
if (!search) {
return {}
}
const obj = {}
const searchArr = search.split('&')
searchArr.forEach(v => {
const index = v.indexOf('=')
if (index !== -1) {
const name = v.substring(0, index)
const val = v.substring(index + 1, v.length)
obj[name] = val
}
})
return obj
}
module.exports = {
param2Obj
}
...@@ -2,7 +2,7 @@ import request from '@/utils/request' ...@@ -2,7 +2,7 @@ import request from '@/utils/request'
export function login(data) { export function login(data) {
return request({ return request({
url: '/vue-admin-template/user/login', url: '/user/login',
method: 'post', method: 'post',
data data
}) })
...@@ -10,7 +10,7 @@ export function login(data) { ...@@ -10,7 +10,7 @@ export function login(data) {
export function getInfo(token) { export function getInfo(token) {
return request({ return request({
url: '/vue-admin-template/user/info', url: '/user/info',
method: 'get', method: 'get',
params: { token } params: { token }
}) })
...@@ -18,7 +18,7 @@ export function getInfo(token) { ...@@ -18,7 +18,7 @@ export function getInfo(token) {
export function logout() { export function logout() {
return request({ return request({
url: '/vue-admin-template/user/logout', url: '/user/logout',
method: 'post' method: 'post'
}) })
} }
...@@ -26,6 +26,8 @@ import { mapGetters } from 'vuex' ...@@ -26,6 +26,8 @@ import { mapGetters } from 'vuex'
import Breadcrumb from '@/components/Breadcrumb' import Breadcrumb from '@/components/Breadcrumb'
import Hamburger from '@/components/Hamburger' import Hamburger from '@/components/Hamburger'
import Sidebar from './Sidebar/index.vue' import Sidebar from './Sidebar/index.vue'
import { logout } from '@/api/user'
export default { export default {
data() { data() {
let timer let timer
...@@ -51,9 +53,11 @@ export default { ...@@ -51,9 +53,11 @@ export default {
toggleSideBar() { toggleSideBar() {
this.$store.dispatch('app/toggleSideBar') this.$store.dispatch('app/toggleSideBar')
}, },
async logout() { logout() {
await this.$store.dispatch('user/logout') logout().then(() => {
this.$router.push(`/login?redirect=${this.$route.fullPath}`) this.$store.dispatch('user/logout')
this.$router.push(`/login`)
})
}, },
// 获取当前时间函数 // 获取当前时间函数
timeFormate (timeStamp) { timeFormate (timeStamp) {
......
...@@ -80,14 +80,10 @@ export default { ...@@ -80,14 +80,10 @@ export default {
this.onlyOneChild = null; this.onlyOneChild = null;
return {}; return {};
}, },
mounted() { mounted() {},
// console.log(this.$refs['subMenu']);
// console.log(document.getElementById('subid'));
},
methods: { methods: {
hasOneShowingChild(children = [], parent) { hasOneShowingChild(children = [], parent) {
const showingChildren = children.filter((item) => {
const showingChildren = children.filter(item => {
if (item.hidden) { if (item.hidden) {
return false; return false;
} else { } else {
...@@ -135,12 +131,11 @@ export default { ...@@ -135,12 +131,11 @@ export default {
width: 100%; width: 100%;
} }
} }
.el-menu--collapse .el-menu .el-submenu, .el-menu--popup{ .el-menu--collapse .el-menu .el-submenu,
min-width: 120px!important; .el-menu--popup {
min-width: 120px !important;
} }
.el-menu .el-menu--popup .el-menu--popup-bottom-start ::v-deep{ .el-menu .el-menu--popup .el-menu--popup-bottom-start ::v-deep {
width: 1020px; width: 1020px;
} }
</style> </style>
...@@ -32,7 +32,7 @@ router.beforeEach(async(to, from, next) => { ...@@ -32,7 +32,7 @@ router.beforeEach(async(to, from, next) => {
} else { } else {
try { try {
// get user info // get user info
await store.dispatch('user/getInfo') // await store.dispatch('user/getInfo')
next() next()
} catch (error) { } catch (error) {
......
import { login, logout, getInfo } from '@/api/user' import { login, getInfo } from '@/api/user'
import { getToken, setToken, removeToken } from '@/utils/auth' import { getToken, setToken, removeToken } from '@/utils/auth'
import { resetRouter } from '@/router' import { resetRouter } from '@/router'
...@@ -67,14 +67,11 @@ const actions = { ...@@ -67,14 +67,11 @@ const actions = {
// user logout // user logout
logout({ commit, state }) { logout({ commit, state }) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
logout(state.token).then(() => {
removeToken() // must remove token first removeToken() // must remove token first
resetRouter() resetRouter()
commit("SET_TOKEN", "")
commit('RESET_STATE') commit('RESET_STATE')
resolve() resolve()
}).catch(error => {
reject(error)
})
}) })
}, },
......
...@@ -2,82 +2,118 @@ import axios from 'axios' ...@@ -2,82 +2,118 @@ import axios from 'axios'
import { MessageBox, Message } from 'element-ui' import { MessageBox, Message } from 'element-ui'
import store from '@/store' import store from '@/store'
import { getToken } from '@/utils/auth' import { getToken } from '@/utils/auth'
import Vue from 'vue'
// create an axios instance // create an axios instance
const service = axios.create({ const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url baseURL: '/api/', // url = base url + request url
// withCredentials: true, // send cookies when cross-domain requests // withCredentials: true, // send cookies when cross-domain requests
timeout: 5000 // request timeout timeout: 5000 // request timeout
}) })
let loading = {}
function startLoading(el) {
if (!el) return
let target = document.querySelector(el)
if (!target || loading[el]) return
loading[el] = Vue.prototype.$loading({
lock: true,
target
})
}
function endLoading(el) {
if (el && loading[el]) {
loading[el].close()
delete loading[el]
}
}
// request interceptor // request interceptor
service.interceptors.request.use( service.interceptors.request.use(
config => { config => {
// do something before request is sent // do something before request is sent
startLoading(config.el)
if (store.getters.token) { if (store.getters.token) {
// let each request carry token config.headers['Authorization'] = getToken()
// ['X-Token'] is a custom headers key } else {
// please modify it according to the actual situation config.headers['Authorization'] = '121212'
config.headers['X-Token'] = getToken()
} }
return config return config
}, },
error => { error => {
// do something with request error // do something with request error
console.log(error) // for debug startLoading(error.request.config.el)
return Promise.reject(error) return Promise.reject(error)
} }
) )
// response interceptor // response interceptor
let errorShowing = false
service.interceptors.response.use( 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 => { response => {
const res = response.data const res = response.data.data ? response.data.data : response.data
let config = response.config
// if the custom code is not 20000, it is judged as an error. endLoading(config.el)
if (res.code !== 20000) { let resFinal = res.rsp || res || {}
Message({ let code = resFinal.errorCode || resFinal.code
message: res.message || 'Error', let message = resFinal.message || resFinal.errorMsg || resFinal.error || '接口错误'
type: 'error', if(code) {
duration: 5 * 1000 if (code == 40101) {
}) location.href = location.href.replace(/#.+/, '') + '#/login'
return
// 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',
type: 'warning'
}).then(() => {
store.dispatch('user/resetToken').then(() => {
location.reload()
})
})
} }
return Promise.reject(new Error(res.message || 'Error')) if (code == '401') {
} else { !config.silence && !errorShowing && Message.error(message)
return res errorShowing = true
setTimeout(() => { errorShowing = false }, 3000)
store.dispatch('user/resetToken')
return
} }
// if (code) {
// !config.silence && Message.error(message)
// return Promise.reject(new Error(message))
// }
}
// if (res.code !== 20000) {
// Message({
// message: res.message || 'Error',
// type: 'error',
// duration: 5 * 1000
// })
// // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
// if (res.code === 501 || res.code === 201 || 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: '重新登陆',
// cancelButtonText: '取消',
// type: 'warning'
// }).then(() => {
// store.dispatch('user/resetToken').then(() => {
// location.reload()
// })
// })
// }
// return Promise.reject(new Error(res.message || 'Error'))
// } else {
return res
// }
}, },
error => { error => {
console.log('err' + error) // for debug console.log('err' + error) // for debug
Message({ if (error.response) {
message: error.message, endLoading(error.response.config.el)
type: 'error', if (!error.response.config.silence) {
duration: 5 * 1000 Message.error(error.message)
}) }
}
// Message({
// message: error.message,
// type: 'error',
// duration: 5 * 1000
// })
return Promise.reject(error) return Promise.reject(error)
} }
) )
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
ref="username" ref="username"
v-model="loginForm.username" v-model="loginForm.username"
placeholder="用户名" placeholder="用户名"
name="username"
type="text" type="text"
tabindex="1" tabindex="1"
auto-complete="on" auto-complete="on"
...@@ -72,29 +71,18 @@ ...@@ -72,29 +71,18 @@
@click.native.prevent="handleLogin" @click.native.prevent="handleLogin"
>登录</el-button >登录</el-button
> >
<!-- <div class="tips">
<span style="margin-right:20px;">username: admin</span>
<span> password:任意6位</span>
</div> -->
</el-form> </el-form>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { validUsername } from "@/utils/validate"; import { login } from "@/api/user"
import { setToken } from "@/utils/auth"
export default { export default {
name: "Login", name: "Login",
data() { data() {
const validateUsername = (rule, value, callback) => {
if (!validUsername(value)) {
callback(new Error("请输入正确的用户名"));
} else {
callback();
}
};
const validatePassword = (rule, value, callback) => { const validatePassword = (rule, value, callback) => {
if (value.length < 6) { if (value.length < 6) {
callback(new Error("密码不能少于6位")); callback(new Error("密码不能少于6位"));
...@@ -109,7 +97,7 @@ export default { ...@@ -109,7 +97,7 @@ export default {
}, },
loginRules: { loginRules: {
username: [ username: [
{ required: true, trigger: "blur", validator: validateUsername }, { required: true, trigger: "blur", message: '请输入用户名' },
], ],
password: [ password: [
{ required: true, trigger: "blur", validator: validatePassword }, { required: true, trigger: "blur", validator: validatePassword },
...@@ -149,25 +137,46 @@ export default { ...@@ -149,25 +137,46 @@ export default {
this.$refs.password.focus(); this.$refs.password.focus();
}); });
}, },
async toLogin() {
const {
username,
password
} = this.loginForm
let { token } = await login({
userName: username,
password: password,
}, {
el: '.el-button'
})
if (!token) return
this.$store.commit("user/SET_TOKEN", token)
setToken(token)
// this.$store.commit("user/SET_NAVIGATION_SHOW", false)
this.$router.push({ path: "/" })
setTimeout(() => {
location.reload()
}, 10)
},
handleLogin() { handleLogin() {
this.$refs.loginForm.validate((valid) => { this.$refs.loginForm.validate((valid) => {
if (valid) { if (valid) {
this.loading = true; this.toLogin()
this.$store // this.loading = true;
.dispatch("user/login", this.loginForm) // this.$store
.then(() => { // .dispatch("user/login", this.loginForm)
if (this.loginForm.password == "123456") { // .then(() => {
this.$router.push({ path: this.redirect || "/" }); // if (this.loginForm.password == "123456") {
this.loading = false; // this.$router.push({ path: this.redirect || "/" });
} else { // this.loading = false;
alert("密码错误"); // } else {
this.loading = false; // alert("密码错误");
return false; // this.loading = false;
} // return false;
}) // }
.catch(() => { // })
this.loading = false; // .catch(() => {
}); // this.loading = false;
// });
} else { } else {
console.log("error submit!!"); console.log("error submit!!");
return false; return false;
......
...@@ -6,37 +6,44 @@ function resolve(dir) { ...@@ -6,37 +6,44 @@ function resolve(dir) {
return path.join(__dirname, dir) return path.join(__dirname, dir)
} }
const name = defaultSettings.title || 'vue Admin Template' // page title const name = defaultSettings.title || '漏缆故障定位监测系统' // page title
const port = process.env.port || process.env.npm_config_port || 8886 // dev port
// If your port is set to 80, const rewriteDefaultConfig = {
// use administrator privileges to execute the command line. changeOrigin: true,
// For example, Mac: sudo npm run target: 'http://8.142.143.40:8886',
// You can change the port by the following methods: // ws: true,
// port = 9528 npm run dev OR npm run dev --port = 9528 headers: {
const port = process.env.port || process.env.npm_config_port || 9528 // dev port referer: 'laddercloud.cn'
},
// onProxyRes: proxyResponse => {
// if (proxyResponse.headers['set-cookie']) {
// const cookies = proxyResponse.headers['set-cookie'].map(cookie =>
// cookie.replace(/; secure/gi, '')
// )
// proxyResponse.headers['set-cookie'] = cookies
// }
// }
}
// All configuration item explanations can be find in https://cli.vuejs.org/config/
module.exports = { module.exports = {
/**
* You will need to set publicPath if you plan to deploy your site under a sub path,
* for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/,
* then publicPath should be set to "/bar/".
* In most cases please use '/' !!!
* Detail: https://cli.vuejs.org/config/#publicpath
*/
publicPath: '/', publicPath: '/',
outputDir: 'dist', outputDir: 'dist',
assetsDir: 'static', assetsDir: 'static',
lintOnSave: process.env.NODE_ENV === 'development', lintOnSave: process.env.NODE_ENV === 'development',
productionSourceMap: false, productionSourceMap: false,
devServer: { devServer: {
index: 'index.html',
port: port, port: port,
open: true, open: true,
overlay: { overlay: {
warnings: false, warnings: false,
errors: true errors: true
}, },
before: require('./mock/mock-server.js') proxy: {
'/api': rewriteDefaultConfig
},
// before: require('./mock/mock-server.js')
}, },
configureWebpack: { configureWebpack: {
// provide the app's title in webpack's name field, so that // provide the app's title in webpack's name field, so that
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment