Merge pull request #3 from PanJiaChen/master

update
This commit is contained in:
MaYuanhai 2019-04-08 13:49:42 +08:00 committed by GitHub
commit 80355eb6b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 130 additions and 59 deletions

View File

@ -1,11 +1,23 @@
import Mock from 'mockjs' import Mock from 'mockjs'
import mocks from './mocks'
import { param2Obj } from '../src/utils' import { param2Obj } from '../src/utils'
const MOCK_API_BASE = '/mock' import user from './user'
import role from './role'
import article from './article'
import search from './remoteSearch'
const mocks = [
...user,
...role,
...article,
...search
]
// 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).
export function mockXHR() { export function mockXHR() {
// 修复在使用 MockJS 情况下,设置 withCredentials = true且未被拦截的跨域请求丢失 Cookies 的问题 // mock patch
// https://github.com/nuysoft/Mock/issues/300 // https://github.com/nuysoft/Mock/issues/300
Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
Mock.XHR.prototype.send = function() { Mock.XHR.prototype.send = function() {
@ -42,9 +54,10 @@ export function mockXHR() {
} }
} }
// for mock server
const responseFake = (url, type, respond) => { const responseFake = (url, type, respond) => {
return { return {
url: new RegExp(`${MOCK_API_BASE}${url}`), url: new RegExp(`/mock${url}`),
type: type || 'get', type: type || 'get',
response(req, res) { response(req, res) {
res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond)) res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond))

79
mock/mock-server.js Normal file
View File

@ -0,0 +1,79 @@
const chokidar = require('chokidar')
const bodyParser = require('body-parser')
const chalk = require('chalk')
function registerRoutes(app) {
const { default: mocks } = require('./index.js')
for (const mock of mocks) {
app[mock.type](mock.url, mock.response)
}
return {
mockRoutesLength: Object.keys(mocks).length
}
}
function unregisterRoutes() {
Object.keys(require.cache).forEach(i => {
if (i.includes('/mock')) {
delete require.cache[require.resolve(i)]
}
})
}
function getPath(path) {
var match = path.toString()
.replace('\\/?', '')
.replace('(?=\\/|$)', '$')
.match(/^\/\^((?:\\[.*+?^${}()|[\]\\\/]|[^.*+?^${}()|[\]\\\/])*)\$\//)
return match
? match[1].replace(/\\(.)/g, '$1').split('/')
: path.toString()
}
function getMockRoutesIndex(app) {
for (let index = 0; index <= app._router.stack.length; index++) {
const r = app._router.stack[index]
if (r.route && r.route.path) {
const path = getPath(r.route.path)
if (path.includes('mock')) {
return index
}
}
}
}
module.exports = app => {
// es6 polyfill
require('@babel/register')
// parse app.body
// http://expressjs.com/en/4x/api.html#req.body
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({
extended: true
}))
const { mockRoutesLength } = registerRoutes(app)
// watch files, hot reload mock server
chokidar.watch(('./mock'), {
ignored: 'mock/mock-server.js',
persistent: true,
ignoreInitial: true
}).on('all', (event, path) => {
if (event === 'change' || event === 'add') {
// find mock routes stack index
const index = getMockRoutesIndex(app)
// remove mock routes stack
app._router.stack.splice(index, mockRoutesLength)
// clear routes cache
unregisterRoutes()
registerRoutes(app)
console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed ${path}`))
}
})
}

View File

@ -1,12 +0,0 @@
import user from './user'
import role from './role'
import article from './article'
import search from './remoteSearch'
export default [
...user,
...role,
...article,
...search
]

View File

@ -82,6 +82,7 @@
"babel-eslint": "10.0.1", "babel-eslint": "10.0.1",
"babel-jest": "23.6.0", "babel-jest": "23.6.0",
"chalk": "2.4.2", "chalk": "2.4.2",
"chokidar": "2.1.5",
"connect": "3.6.6", "connect": "3.6.6",
"eslint": "5.15.3", "eslint": "5.15.3",
"eslint-plugin-vue": "5.2.2", "eslint-plugin-vue": "5.2.2",

View File

@ -3,7 +3,7 @@
<logo v-if="showLogo" :collapse="isCollapse" /> <logo v-if="showLogo" :collapse="isCollapse" />
<el-scrollbar wrap-class="scrollbar-wrapper"> <el-scrollbar wrap-class="scrollbar-wrapper">
<el-menu <el-menu
:default-active="$route.path" :default-active="activeMenu"
:collapse="isCollapse" :collapse="isCollapse"
:background-color="variables.menuBg" :background-color="variables.menuBg"
:text-color="variables.menuText" :text-color="variables.menuText"
@ -30,6 +30,15 @@ export default {
'permission_routes', 'permission_routes',
'sidebar' 'sidebar'
]), ]),
activeMenu() {
const route = this.$route
const { meta, path } = route
// if set path, the sidebar will highlight the path you set
if (meta.activeMenu) {
return meta.activeMenu
}
return path
},
showLogo() { showLogo() {
return this.$store.state.settings.sidebarLogo return this.$store.state.settings.sidebarLogo
}, },

View File

@ -12,32 +12,32 @@ import chartsRouter from './modules/charts'
import tableRouter from './modules/table' import tableRouter from './modules/table'
import nestedRouter from './modules/nested' import nestedRouter from './modules/nested'
/** note: sub-menu only appear when children.length>=1
* detail see https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
**/
/** /**
* hidden: true if `hidden:true` will not show in the sidebar(default is false) * Note: sub-menu only appear when route children.length >= 1
* alwaysShow: true if set true, will always show the root menu, whatever its child routes length * Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
* if not set alwaysShow, only more than one route under the children *
* it will becomes nested mode, otherwise not show the root menu * hidden: true if set true, item will not show in the sidebar(default is false)
* redirect: noredirect if `redirect:noredirect` will no redirect in the breadcrumb * alwaysShow: true if set true, will always show the root menu
* name:'router-name' the name is used by <keep-alive> (must set!!!) * if not set alwaysShow, when item has more than one children route,
* meta : { * it will becomes nested mode, otherwise not show the root menu
roles: ['admin','editor'] will control the page roles (you can set multiple roles) * redirect: noredirect if `redirect:noredirect` will no redirect in the breadcrumb
title: 'title' the name show in sub-menu and breadcrumb (recommend set) * name:'router-name' the name is used by <keep-alive> (must set!!!)
* meta : {
roles: ['admin','editor'] control the page roles (you can set multiple roles)
title: 'title' the name show in sidebar and breadcrumb (recommend set)
icon: 'svg-name' the icon show in the sidebar icon: 'svg-name' the icon show in the sidebar
noCache: true if true, the page will no be cached(default is false) noCache: true if set true, the page will no be cached(default is false)
breadcrumb: false if false, the item will hidden in breadcrumb(default is true) affix: true if set true, the tag will affix in the tags-view
affix: true if true, the tag will affix in the tags-view breadcrumb: false if set false, the item will hidden in breadcrumb(default is true)
activeMenu: '/example/list' if set path, the sidebar will highlight the path you set
} }
**/ */
/** /**
* constantRoutes * constantRoutes
* a base page that does not have permission requirements * a base page that does not have permission requirements
* all roles can be accessed * all roles can be accessed
* */ */
export const constantRoutes = [ export const constantRoutes = [
{ {
path: '/redirect', path: '/redirect',
@ -113,7 +113,7 @@ export const constantRoutes = [
/** /**
* asyncRoutes * asyncRoutes
* the routes that need to be dynamically loaded based on user roles * the routes that need to be dynamically loaded based on user roles
*/ */
export const asyncRoutes = [ export const asyncRoutes = [
{ {
path: '/permission', path: '/permission',
@ -195,7 +195,7 @@ export const asyncRoutes = [
path: 'edit/:id(\\d+)', path: 'edit/:id(\\d+)',
component: () => import('@/views/example/edit'), component: () => import('@/views/example/edit'),
name: 'EditArticle', name: 'EditArticle',
meta: { title: 'editArticle', noCache: true }, meta: { title: 'editArticle', noCache: true, activeMenu: '/example/list' },
hidden: true hidden: true
}, },
{ {

View File

@ -28,10 +28,6 @@
.scrollbar-wrapper { .scrollbar-wrapper {
overflow-x: hidden !important; overflow-x: hidden !important;
.el-scrollbar__view {
height: 100%;
}
} }
.el-scrollbar__bar.is-vertical { .el-scrollbar__bar.is-vertical {

View File

@ -43,7 +43,7 @@ service.interceptors.response.use(
const res = response.data const res = response.data
if (res.code !== 20000) { if (res.code !== 20000) {
Message({ Message({
message: res.message, message: res.message || 'error',
type: 'error', type: 'error',
duration: 5 * 1000 duration: 5 * 1000
}) })
@ -61,7 +61,7 @@ service.interceptors.response.use(
}) })
}) })
} }
return Promise.reject('error') return Promise.reject(res.message || 'error')
} else { } else {
return res return res
} }

View File

@ -41,22 +41,7 @@ module.exports = {
} }
} }
}, },
after(app) { after: require('./mock/mock-server.js')
require('@babel/register')
const bodyParser = require('body-parser')
// parse app.body
// http://expressjs.com/en/4x/api.html#req.body
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({
extended: true
}))
const { default: mocks } = require('./mock')
for (const mock of mocks) {
app[mock.type](mock.url, mock.response)
}
}
}, },
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