commit
80355eb6b8
|
@ -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))
|
||||||
|
|
|
@ -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}`))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
|
@ -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
|
|
||||||
]
|
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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
|
||||||
},
|
},
|
||||||
|
|
|
@ -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
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue