diff --git a/mock/index.js b/mock/index.js
index 7d9609ab..08cdc471 100644
--- a/mock/index.js
+++ b/mock/index.js
@@ -1,11 +1,23 @@
import Mock from 'mockjs'
-import mocks from './mocks'
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() {
- // 修复在使用 MockJS 情况下,设置 withCredentials = true,且未被拦截的跨域请求丢失 Cookies 的问题
+ // mock patch
// https://github.com/nuysoft/Mock/issues/300
Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
Mock.XHR.prototype.send = function() {
@@ -42,9 +54,10 @@ export function mockXHR() {
}
}
+// for mock server
const responseFake = (url, type, respond) => {
return {
- url: new RegExp(`${MOCK_API_BASE}${url}`),
+ url: new RegExp(`/mock${url}`),
type: type || 'get',
response(req, res) {
res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond))
diff --git a/mock/mock-server.js b/mock/mock-server.js
new file mode 100644
index 00000000..99346afb
--- /dev/null
+++ b/mock/mock-server.js
@@ -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}`))
+ }
+ })
+}
diff --git a/mock/mocks.js b/mock/mocks.js
deleted file mode 100644
index 84a25ddc..00000000
--- a/mock/mocks.js
+++ /dev/null
@@ -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
-]
-
diff --git a/package.json b/package.json
index 12bf3ffc..f8f98543 100644
--- a/package.json
+++ b/package.json
@@ -82,6 +82,7 @@
"babel-eslint": "10.0.1",
"babel-jest": "23.6.0",
"chalk": "2.4.2",
+ "chokidar": "2.1.5",
"connect": "3.6.6",
"eslint": "5.15.3",
"eslint-plugin-vue": "5.2.2",
diff --git a/src/layout/components/Sidebar/index.vue b/src/layout/components/Sidebar/index.vue
index f02a4819..773cd5c8 100644
--- a/src/layout/components/Sidebar/index.vue
+++ b/src/layout/components/Sidebar/index.vue
@@ -3,7 +3,7 @@
=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)
-* alwaysShow: true if set true, will always show the root menu, whatever its child routes length
-* if not set alwaysShow, only more than one route under the children
-* it will becomes nested mode, otherwise not show the root menu
-* redirect: noredirect if `redirect:noredirect` will no redirect in the breadcrumb
-* name:'router-name' the name is used by (must set!!!)
-* meta : {
- roles: ['admin','editor'] will control the page roles (you can set multiple roles)
- title: 'title' the name show in sub-menu and breadcrumb (recommend set)
+ * Note: sub-menu only appear when route children.length >= 1
+ * Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
+ *
+ * hidden: true if set true, item will not show in the sidebar(default is false)
+ * alwaysShow: true if set true, will always show the root menu
+ * if not set alwaysShow, when item has more than one children route,
+ * it will becomes nested mode, otherwise not show the root menu
+ * redirect: noredirect if `redirect:noredirect` will no redirect in the breadcrumb
+ * name:'router-name' the name is used by (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
- noCache: true if 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 true, the tag will affix in the tags-view
+ noCache: true if set true, the page will no be cached(default is false)
+ affix: true if set 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
* a base page that does not have permission requirements
* all roles can be accessed
- * */
+ */
export const constantRoutes = [
{
path: '/redirect',
@@ -113,7 +113,7 @@ export const constantRoutes = [
/**
* asyncRoutes
* the routes that need to be dynamically loaded based on user roles
-*/
+ */
export const asyncRoutes = [
{
path: '/permission',
@@ -195,7 +195,7 @@ export const asyncRoutes = [
path: 'edit/:id(\\d+)',
component: () => import('@/views/example/edit'),
name: 'EditArticle',
- meta: { title: 'editArticle', noCache: true },
+ meta: { title: 'editArticle', noCache: true, activeMenu: '/example/list' },
hidden: true
},
{
diff --git a/src/styles/sidebar.scss b/src/styles/sidebar.scss
index 5911eb85..e0accb83 100644
--- a/src/styles/sidebar.scss
+++ b/src/styles/sidebar.scss
@@ -28,10 +28,6 @@
.scrollbar-wrapper {
overflow-x: hidden !important;
-
- .el-scrollbar__view {
- height: 100%;
- }
}
.el-scrollbar__bar.is-vertical {
diff --git a/src/utils/request.js b/src/utils/request.js
index b043c933..d2422c46 100644
--- a/src/utils/request.js
+++ b/src/utils/request.js
@@ -43,7 +43,7 @@ service.interceptors.response.use(
const res = response.data
if (res.code !== 20000) {
Message({
- message: res.message,
+ message: res.message || 'error',
type: 'error',
duration: 5 * 1000
})
@@ -61,7 +61,7 @@ service.interceptors.response.use(
})
})
}
- return Promise.reject('error')
+ return Promise.reject(res.message || 'error')
} else {
return res
}
diff --git a/vue.config.js b/vue.config.js
index 7b9d2dbb..d3a08991 100644
--- a/vue.config.js
+++ b/vue.config.js
@@ -41,22 +41,7 @@ module.exports = {
}
}
},
- after(app) {
- 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)
- }
- }
+ after: require('./mock/mock-server.js')
},
configureWebpack: {
// provide the app's title in webpack's name field, so that