From 0bf61aac535b7799a0f17573741fee507003a7e4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=8A=B1=E8=A3=A4=E8=A1=A9?= <panfree23@gmail.com>
Date: Wed, 10 Jun 2020 21:47:50 +0800
Subject: [PATCH 01/10] chore: turn on the preload

---
 vue.config.js | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/vue.config.js b/vue.config.js
index ba5be418..aabbf651 100644
--- a/vue.config.js
+++ b/vue.config.js
@@ -49,8 +49,11 @@ module.exports = {
     }
   },
   chainWebpack(config) {
-    config.plugins.delete('preload') // TODO: need test
-    config.plugins.delete('prefetch') // TODO: need test
+    // it can improve the speed of the first screen, it is recommended to turn on preload
+    // config.plugins.delete('preload')
+
+    // when there are many pages, it will cause too many meaningless requests
+    config.plugins.delete('prefetch') //
 
     // set svg-sprite-loader
     config.module

From d3bd933a8e314e5e51d48125dbcda9e3df8ee673 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=8A=B1=E8=A3=A4=E8=A1=A9?= <panfree23@gmail.com>
Date: Thu, 11 Jun 2020 11:40:53 +0800
Subject: [PATCH 02/10] refactor: change mock files to commonjs (#3246)

---
 mock/article.js       |  4 ++--
 mock/index.js         | 19 ++++++++++--------
 mock/mock-server.js   |  5 +----
 mock/remote-search.js |  4 ++--
 mock/role/index.js    |  8 ++++----
 mock/role/routes.js   |  9 +++++++--
 mock/user.js          |  2 +-
 mock/utils.js         | 46 +++++++++++++++++++++++++++++++++++++++++++
 package.json          |  2 --
 9 files changed, 74 insertions(+), 25 deletions(-)
 create mode 100644 mock/utils.js

diff --git a/mock/article.js b/mock/article.js
index 50218ae4..23d8ba51 100644
--- a/mock/article.js
+++ b/mock/article.js
@@ -1,4 +1,4 @@
-import Mock from 'mockjs'
+const Mock = require('mockjs')
 
 const List = []
 const count = 100
@@ -27,7 +27,7 @@ for (let i = 0; i < count; i++) {
   }))
 }
 
-export default [
+module.exports = [
   {
     url: '/vue-element-admin/article/list',
     type: 'get',
diff --git a/mock/index.js b/mock/index.js
index 196e2927..2eed65db 100644
--- a/mock/index.js
+++ b/mock/index.js
@@ -1,10 +1,10 @@
-import Mock from 'mockjs'
-import { param2Obj } from '../src/utils'
+const Mock = require('mockjs')
+const { param2Obj } = require('./utils')
 
-import user from './user'
-import role from './role'
-import article from './article'
-import search from './remote-search'
+const user = require('./user')
+const role = require('./role')
+const article = require('./article')
+const search = require('./remote-search')
 
 const mocks = [
   ...user,
@@ -16,7 +16,7 @@ const mocks = [
 // 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() {
+function mockXHR() {
   // mock patch
   // https://github.com/nuysoft/Mock/issues/300
   Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
@@ -54,4 +54,7 @@ export function mockXHR() {
   }
 }
 
-export default mocks
+module.exports = {
+  mocks,
+  mockXHR
+}
diff --git a/mock/mock-server.js b/mock/mock-server.js
index 806fdacc..8941ec0f 100644
--- a/mock/mock-server.js
+++ b/mock/mock-server.js
@@ -8,7 +8,7 @@ const mockDir = path.join(process.cwd(), 'mock')
 
 function registerRoutes(app) {
   let mockLastIndex
-  const { default: mocks } = require('./index.js')
+  const { mocks } = require('./index.js')
   const mocksForServer = mocks.map(route => {
     return responseFake(route.url, route.type, route.response)
   })
@@ -44,9 +44,6 @@ const responseFake = (url, type, respond) => {
 }
 
 module.exports = app => {
-  // es6 polyfill
-  require('@babel/register')
-
   // parse app.body
   // https://expressjs.com/en/4x/api.html#req.body
   app.use(bodyParser.json())
diff --git a/mock/remote-search.js b/mock/remote-search.js
index 60809cb8..8fc49267 100644
--- a/mock/remote-search.js
+++ b/mock/remote-search.js
@@ -1,4 +1,4 @@
-import Mock from 'mockjs'
+const Mock = require('mockjs')
 
 const NameList = []
 const count = 100
@@ -10,7 +10,7 @@ for (let i = 0; i < count; i++) {
 }
 NameList.push({ name: 'mock-Pan' })
 
-export default [
+module.exports = [
   // username search
   {
     url: '/vue-element-admin/search/user',
diff --git a/mock/role/index.js b/mock/role/index.js
index d957493b..4643f006 100644
--- a/mock/role/index.js
+++ b/mock/role/index.js
@@ -1,6 +1,6 @@
-import Mock from 'mockjs'
-import { deepClone } from '../../src/utils/index.js'
-import { asyncRoutes, constantRoutes } from './routes.js'
+const Mock = require('mockjs')
+const { deepClone } = require('../utils')
+const { asyncRoutes, constantRoutes } = require('./routes.js')
 
 const routes = deepClone([...constantRoutes, ...asyncRoutes])
 
@@ -35,7 +35,7 @@ const roles = [
   }
 ]
 
-export default [
+module.exports = [
   // mock get all routes form server
   {
     url: '/vue-element-admin/routes',
diff --git a/mock/role/routes.js b/mock/role/routes.js
index d718919c..d33f1624 100644
--- a/mock/role/routes.js
+++ b/mock/role/routes.js
@@ -1,6 +1,6 @@
 // Just a mock data
 
-export const constantRoutes = [
+const constantRoutes = [
   {
     path: '/redirect',
     component: 'layout/Layout',
@@ -72,7 +72,7 @@ export const constantRoutes = [
   }
 ]
 
-export const asyncRoutes = [
+const asyncRoutes = [
   {
     path: '/permission',
     component: 'layout/Layout',
@@ -523,3 +523,8 @@ export const asyncRoutes = [
 
   { path: '*', redirect: '/404', hidden: true }
 ]
+
+module.exports = {
+  constantRoutes,
+  asyncRoutes
+}
diff --git a/mock/user.js b/mock/user.js
index 859bd6f3..d82e079d 100644
--- a/mock/user.js
+++ b/mock/user.js
@@ -23,7 +23,7 @@ const users = {
   }
 }
 
-export default [
+module.exports = [
   // user login
   {
     url: '/vue-element-admin/user/login',
diff --git a/mock/utils.js b/mock/utils.js
new file mode 100644
index 00000000..5bd2d2c9
--- /dev/null
+++ b/mock/utils.js
@@ -0,0 +1,46 @@
+/**
+ * @param {string} url
+ * @returns {Object}
+ */
+function param2Obj(url) {
+  const search = url.split('?')[1]
+  if (!search) {
+    return {}
+  }
+  return JSON.parse(
+    '{"' +
+      decodeURIComponent(search)
+        .replace(/"/g, '\\"')
+        .replace(/&/g, '","')
+        .replace(/=/g, '":"')
+        .replace(/\+/g, ' ') +
+      '"}'
+  )
+}
+
+/**
+ * This is just a simple version of deep copy
+ * Has a lot of edge cases bug
+ * If you want to use a perfect deep copy, use lodash's _.cloneDeep
+ * @param {Object} source
+ * @returns {Object}
+ */
+function deepClone(source) {
+  if (!source && typeof source !== 'object') {
+    throw new Error('error arguments', 'deepClone')
+  }
+  const targetObj = source.constructor === Array ? [] : {}
+  Object.keys(source).forEach(keys => {
+    if (source[keys] && typeof source[keys] === 'object') {
+      targetObj[keys] = deepClone(source[keys])
+    } else {
+      targetObj[keys] = source[keys]
+    }
+  })
+  return targetObj
+}
+
+module.exports = {
+  param2Obj,
+  deepClone
+}
diff --git a/package.json b/package.json
index 22ebe91e..cded3a4f 100644
--- a/package.json
+++ b/package.json
@@ -72,8 +72,6 @@
     "xlsx": "0.14.1"
   },
   "devDependencies": {
-    "@babel/core": "7.0.0",
-    "@babel/register": "7.0.0",
     "@vue/cli-plugin-babel": "3.5.3",
     "@vue/cli-plugin-eslint": "^3.9.1",
     "@vue/cli-plugin-unit-jest": "3.5.3",

From fc68f56d130387b0f0320f8611d8e33e76525376 Mon Sep 17 00:00:00 2001
From: Cat73 <Cat7373@users.noreply.github.com>
Date: Thu, 11 Jun 2020 13:57:41 +0800
Subject: [PATCH 03/10] feat[Menu]: menu icon support el-icon(#3048)

---
 src/layout/components/Sidebar/Item.vue | 14 +++++++++++++-
 src/router/index.js                    |  6 +++---
 src/styles/sidebar.scss                | 17 +++++++++++++++++
 3 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/src/layout/components/Sidebar/Item.vue b/src/layout/components/Sidebar/Item.vue
index b515f615..aa1f5da4 100644
--- a/src/layout/components/Sidebar/Item.vue
+++ b/src/layout/components/Sidebar/Item.vue
@@ -17,7 +17,11 @@ export default {
     const vnodes = []
 
     if (icon) {
-      vnodes.push(<svg-icon icon-class={icon}/>)
+      if (icon.includes('el-icon')) {
+        vnodes.push(<i class={[icon, 'sub-el-icon']} />)
+      } else {
+        vnodes.push(<svg-icon icon-class={icon}/>)
+      }
     }
 
     if (title) {
@@ -27,3 +31,11 @@ export default {
   }
 }
 </script>
+
+<style scoped>
+.sub-el-icon {
+  color: currentColor;
+  width: 1em;
+  height: 1em;
+}
+</style>
diff --git a/src/router/index.js b/src/router/index.js
index 2e522b2a..9c05f896 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -25,7 +25,7 @@ import nestedRouter from './modules/nested'
  * 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'/'el-icon-x' the icon show in the sidebar
     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)
@@ -197,14 +197,14 @@ export const asyncRoutes = [
     name: 'Example',
     meta: {
       title: 'Example',
-      icon: 'example'
+      icon: 'el-icon-s-help'
     },
     children: [
       {
         path: 'create',
         component: () => import('@/views/example/create'),
         name: 'CreateArticle',
-        meta: { title: 'Create Article', icon: 'edit' }
+        meta: { title: 'Create Article', icon: 'el-icon-s-help' }
       },
       {
         path: 'edit/:id(\\d+)',
diff --git a/src/styles/sidebar.scss b/src/styles/sidebar.scss
index 3dad4c39..94760cc7 100644
--- a/src/styles/sidebar.scss
+++ b/src/styles/sidebar.scss
@@ -57,6 +57,11 @@
       margin-right: 16px;
     }
 
+    .sub-el-icon {
+      margin-right: 12px;
+      margin-left: -2px;
+    }
+
     .el-menu {
       border: none;
       height: 100%;
@@ -105,6 +110,10 @@
         .svg-icon {
           margin-left: 20px;
         }
+
+        .sub-el-icon {
+          margin-left: 19px;
+        }
       }
     }
 
@@ -118,6 +127,10 @@
           margin-left: 20px;
         }
 
+        .sub-el-icon {
+          margin-left: 19px;
+        }
+
         .el-submenu__icon-arrow {
           display: none;
         }
@@ -178,6 +191,10 @@
     .svg-icon {
       margin-right: 16px;
     }
+    .sub-el-icon {
+      margin-right: 12px;
+      margin-left: -2px;
+    }
   }
 
   .nest-menu .el-submenu>.el-submenu__title,

From a50180f6538aba51074f0152157075337e73a4fd Mon Sep 17 00:00:00 2001
From: MaYuanhai <414199639@qq.com>
Date: Thu, 11 Jun 2020 20:18:23 +0800
Subject: [PATCH 04/10] fix[utils]: param2Obj bug when url params includes
 ==(#3100)

---
 src/utils/index.js                 | 28 +++++++++++++++-------------
 tests/unit/utils/param2Obj.spec.js | 14 ++++++++++++++
 2 files changed, 29 insertions(+), 13 deletions(-)
 create mode 100644 tests/unit/utils/param2Obj.spec.js

diff --git a/src/utils/index.js b/src/utils/index.js
index 96ee6e7f..50da2621 100644
--- a/src/utils/index.js
+++ b/src/utils/index.js
@@ -162,19 +162,21 @@ export function param(json) {
  * @returns {Object}
  */
 export function param2Obj(url) {
-  const search = url.split('?')[1]
-  if (!search) {
-    return {}
-  }
-  return JSON.parse(
-    '{"' +
-      decodeURIComponent(search)
-        .replace(/"/g, '\\"')
-        .replace(/&/g, '","')
-        .replace(/=/g, '":"')
-        .replace(/\+/g, ' ') +
-      '"}'
-  )
+    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
 }
 
 /**
diff --git a/tests/unit/utils/param2Obj.spec.js b/tests/unit/utils/param2Obj.spec.js
new file mode 100644
index 00000000..e106ed88
--- /dev/null
+++ b/tests/unit/utils/param2Obj.spec.js
@@ -0,0 +1,14 @@
+import { param2Obj } from '@/utils/index.js'
+describe('Utils:param2Obj', () => {
+  const url = 'https://github.com/PanJiaChen/vue-element-admin?name=bill&age=29&sex=1&field=dGVzdA==&key=%E6%B5%8B%E8%AF%95'
+
+  it('param2Obj test', () => {
+    expect(param2Obj(url)).toEqual({
+      name: 'bill',
+      age: '29',
+      sex: '1',
+      field: window.btoa('test'),
+      key: '测试'
+    })
+  })
+})

From 7702b3d809a312feb2a9eb7c7a70fef3ea0628b8 Mon Sep 17 00:00:00 2001
From: Silentdoer <1010993610@qq.com>
Date: Thu, 11 Jun 2020 20:24:17 +0800
Subject: [PATCH 05/10] perf: remove unused showdown
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: 花裤衩 <panfree23@gmail.com>
---
 package.json | 1 -
 1 file changed, 1 deletion(-)

diff --git a/package.json b/package.json
index cded3a4f..482d5a48 100644
--- a/package.json
+++ b/package.json
@@ -60,7 +60,6 @@
     "path-to-regexp": "2.4.0",
     "screenfull": "4.2.0",
     "script-loader": "0.7.2",
-    "showdown": "1.9.0",
     "sortablejs": "1.8.4",
     "tui-editor": "1.3.3",
     "vue": "2.6.10",

From a87218e2663210be30171b92b29e5ea894f12085 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=8A=B1=E8=A3=A4=E8=A1=A9?= <panfree23@gmail.com>
Date: Thu, 11 Jun 2020 20:51:10 +0800
Subject: [PATCH 06/10] perf: lint code

---
 src/utils/index.js | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/src/utils/index.js b/src/utils/index.js
index 50da2621..3225d3c4 100644
--- a/src/utils/index.js
+++ b/src/utils/index.js
@@ -162,21 +162,21 @@ export function param(json) {
  * @returns {Object}
  */
 export function param2Obj(url) {
-    const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
-    if (!search) {
-        return {}
+  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
     }
-    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
+  })
+  return obj
 }
 
 /**

From 4e7665c07226cf3bc3278a9af1bf60fe6782cb7d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=8A=B1=E8=A3=A4=E8=A1=A9?= <panfree23@gmail.com>
Date: Thu, 11 Jun 2020 21:02:18 +0800
Subject: [PATCH 07/10] fix[v-permission]: support dynamic set roles (#3251)

---
 src/directive/permission/permission.js | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/src/directive/permission/permission.js b/src/directive/permission/permission.js
index b27f24da..49d1f889 100644
--- a/src/directive/permission/permission.js
+++ b/src/directive/permission/permission.js
@@ -1,11 +1,11 @@
 import store from '@/store'
 
-export default {
-  inserted(el, binding, vnode) {
-    const { value } = binding
-    const roles = store.getters && store.getters.roles
+function checkPermission(el, binding) {
+  const { value } = binding
+  const roles = store.getters && store.getters.roles
 
-    if (value && value instanceof Array && value.length > 0) {
+  if (value && value instanceof Array) {
+    if (value.length > 0) {
       const permissionRoles = value
 
       const hasPermission = roles.some(role => {
@@ -15,8 +15,17 @@ export default {
       if (!hasPermission) {
         el.parentNode && el.parentNode.removeChild(el)
       }
-    } else {
-      throw new Error(`need roles! Like v-permission="['admin','editor']"`)
     }
+  } else {
+    throw new Error(`need roles! Like v-permission="['admin','editor']"`)
+  }
+}
+
+export default {
+  inserted(el, binding) {
+    checkPermission(el, binding)
+  },
+  update(el, binding) {
+    checkPermission(el, binding)
   }
 }

From 1c943509f9788297f0ddc188208f9501648c8e7f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=8A=B1=E8=A3=A4=E8=A1=A9?= <panfree23@gmail.com>
Date: Fri, 12 Jun 2020 10:18:05 +0800
Subject: [PATCH 08/10] chore: update element-ui to 2.13.2

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 482d5a48..7f8e8d31 100644
--- a/package.json
+++ b/package.json
@@ -49,7 +49,7 @@
     "driver.js": "0.9.5",
     "dropzone": "5.5.1",
     "echarts": "4.2.1",
-    "element-ui": "2.13.0",
+    "element-ui": "2.13.2",
     "file-saver": "2.0.1",
     "fuse.js": "3.4.4",
     "js-cookie": "2.2.0",

From 6d88db5c73ea54063190830da3d1a40421c51bf3 Mon Sep 17 00:00:00 2001
From: qige2016 <286882998@qq.com>
Date: Mon, 15 Jun 2020 12:00:17 +0800
Subject: [PATCH 09/10] fix[plop]: set trim => trim() (#3254)

notEmpty
---
 plop-templates/utils.js | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/plop-templates/utils.js b/plop-templates/utils.js
index 0310ca02..04987539 100644
--- a/plop-templates/utils.js
+++ b/plop-templates/utils.js
@@ -1,9 +1,2 @@
-exports.notEmpty = name => {
-  return v => {
-    if (!v || v.trim === '') {
-      return `${name} is required`
-    } else {
-      return true
-    }
-  }
-}
+exports.notEmpty = name => v =>
+  !v || v.trim() === '' ? `${name} is required` : true

From 435db380d3d26a902d6c03092f1aeb2d316b26b1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=8A=B1=E8=A3=A4=E8=A1=A9?= <panfree23@gmail.com>
Date: Mon, 15 Jun 2020 17:18:55 +0800
Subject: [PATCH 10/10] fix some typos

---
 mock/utils.js       | 22 ++++++++++++----------
 src/router/index.js |  2 +-
 vue.config.js       |  2 +-
 3 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/mock/utils.js b/mock/utils.js
index 5bd2d2c9..f909a293 100644
--- a/mock/utils.js
+++ b/mock/utils.js
@@ -3,19 +3,21 @@
  * @returns {Object}
  */
 function param2Obj(url) {
-  const search = url.split('?')[1]
+  const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
   if (!search) {
     return {}
   }
-  return JSON.parse(
-    '{"' +
-      decodeURIComponent(search)
-        .replace(/"/g, '\\"')
-        .replace(/&/g, '","')
-        .replace(/=/g, '":"')
-        .replace(/\+/g, ' ') +
-      '"}'
-  )
+  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
 }
 
 /**
diff --git a/src/router/index.js b/src/router/index.js
index 9c05f896..2be959d2 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -204,7 +204,7 @@ export const asyncRoutes = [
         path: 'create',
         component: () => import('@/views/example/create'),
         name: 'CreateArticle',
-        meta: { title: 'Create Article', icon: 'el-icon-s-help' }
+        meta: { title: 'Create Article', icon: 'edit' }
       },
       {
         path: 'edit/:id(\\d+)',
diff --git a/vue.config.js b/vue.config.js
index aabbf651..6733dd50 100644
--- a/vue.config.js
+++ b/vue.config.js
@@ -53,7 +53,7 @@ module.exports = {
     // config.plugins.delete('preload')
 
     // when there are many pages, it will cause too many meaningless requests
-    config.plugins.delete('prefetch') //
+    config.plugins.delete('prefetch')
 
     // set svg-sprite-loader
     config.module