Compare commits

..

No commits in common. "master" and "4.3.0" have entirely different histories.

18 changed files with 76 additions and 166 deletions

View File

@ -3,3 +3,12 @@ ENV = 'development'
# base api # base api
VUE_APP_BASE_API = '/dev-api' VUE_APP_BASE_API = '/dev-api'
# vue-cli uses the VUE_CLI_BABEL_TRANSPILE_MODULES environment variable,
# to control whether the babel-plugin-dynamic-import-node plugin is enabled.
# It only does one thing by converting all import() to require().
# This configuration can significantly increase the speed of hot updates,
# when you have a large number of pages.
# Detail: https://github.com/vuejs/vue-cli/blob/dev/packages/@vue/babel-preset-app/index.js
VUE_CLI_BABEL_TRANSPILE_MODULES = true

View File

@ -8,15 +8,6 @@
目前版本为 `v4.0+` 基于 `vue-cli` 进行构建,若你想使用旧版本,可以切换分支到[tag/3.11.0](https://github.com/PanJiaChen/vue-admin-template/tree/tag/3.11.0),它不依赖 `vue-cli` 目前版本为 `v4.0+` 基于 `vue-cli` 进行构建,若你想使用旧版本,可以切换分支到[tag/3.11.0](https://github.com/PanJiaChen/vue-admin-template/tree/tag/3.11.0),它不依赖 `vue-cli`
<p align="center">
<b>SPONSORED BY</b>
</p>
<p align="center">
<a href="https://finclip.com?from=vue_element" title="FinClip" target="_blank">
<img height="200px" src="https://gitee.com/panjiachen/gitee-cdn/raw/master/vue%E8%B5%9E%E5%8A%A9.png" title="FinClip">
</a>
</p>
## Extra ## Extra
如果你想要根据用户角色来动态生成侧边栏和 router你可以使用该分支[permission-control](https://github.com/PanJiaChen/vue-admin-template/tree/permission-control) 如果你想要根据用户角色来动态生成侧边栏和 router你可以使用该分支[permission-control](https://github.com/PanJiaChen/vue-admin-template/tree/permission-control)

View File

@ -9,17 +9,9 @@ English | [简体中文](./README-zh.md)
**The current version is `v4.0+` build on `vue-cli`. If you want to use the old version , you can switch branch to [tag/3.11.0](https://github.com/PanJiaChen/vue-admin-template/tree/tag/3.11.0), it does not rely on `vue-cli`** **The current version is `v4.0+` build on `vue-cli`. If you want to use the old version , you can switch branch to [tag/3.11.0](https://github.com/PanJiaChen/vue-admin-template/tree/tag/3.11.0), it does not rely on `vue-cli`**
<p align="center">
<b>SPONSORED BY</b>
</p>
<p align="center">
<a href="https://finclip.com?from=vue_element" title="FinClip" target="_blank">
<img height="200px" src="https://gitee.com/panjiachen/gitee-cdn/raw/master/vue%E8%B5%9E%E5%8A%A9.png" title="FinClip">
</a>
</p>
## Build Setup ## Build Setup
```bash ```bash
# clone the project # clone the project
git clone https://github.com/PanJiaChen/vue-admin-template.git git clone https://github.com/PanJiaChen/vue-admin-template.git

View File

@ -1,14 +1,5 @@
module.exports = { module.exports = {
presets: [ presets: [
// https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app '@vue/app'
'@vue/cli-plugin-babel/preset' ]
],
'env': {
'development': {
// babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require().
// This plugin can significantly increase the speed of hot updates, when you have a large number of pages.
// https://panjiachen.github.io/vue-element-admin-site/guide/advanced/lazy-loading.html
'plugins': ['dynamic-import-node']
}
}
} }

View File

@ -1,8 +1,8 @@
const Mock = require('mockjs') import Mock from 'mockjs'
const { param2Obj } = require('./utils') import { param2Obj } from '../src/utils'
const user = require('./user') import user from './user'
const table = require('./table') import table from './table'
const mocks = [ const mocks = [
...user, ...user,
@ -12,7 +12,7 @@ const mocks = [
// for front mock // for front mock
// please use it cautiously, it will redefine XMLHttpRequest, // please use it cautiously, it will redefine XMLHttpRequest,
// which will cause many of your third-party libraries to be invalidated(like progress event). // which will cause many of your third-party libraries to be invalidated(like progress event).
function mockXHR() { export function mockXHR() {
// mock patch // 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
@ -50,8 +50,4 @@ function mockXHR() {
} }
} }
module.exports = { export default mocks
mocks,
mockXHR
}

View File

@ -8,7 +8,7 @@ const mockDir = path.join(process.cwd(), 'mock')
function registerRoutes(app) { function registerRoutes(app) {
let mockLastIndex let mockLastIndex
const { mocks } = require('./index.js') const { default: mocks } = require('./index.js')
const mocksForServer = mocks.map(route => { const mocksForServer = mocks.map(route => {
return responseFake(route.url, route.type, route.response) return responseFake(route.url, route.type, route.response)
}) })
@ -44,6 +44,9 @@ const responseFake = (url, type, respond) => {
} }
module.exports = app => { module.exports = app => {
// es6 polyfill
require('@babel/register')
// parse app.body // parse app.body
// https://expressjs.com/en/4x/api.html#req.body // https://expressjs.com/en/4x/api.html#req.body
app.use(bodyParser.json()) app.use(bodyParser.json())

View File

@ -1,4 +1,4 @@
const Mock = require('mockjs') import Mock from 'mockjs'
const data = Mock.mock({ const data = Mock.mock({
'items|30': [{ 'items|30': [{
@ -11,7 +11,7 @@ const data = Mock.mock({
}] }]
}) })
module.exports = [ export default [
{ {
url: '/vue-admin-template/table/list', url: '/vue-admin-template/table/list',
type: 'get', type: 'get',

View File

@ -23,7 +23,7 @@ const users = {
} }
} }
module.exports = [ export default [
// user login // user login
{ {
url: '/vue-admin-template/user/login', url: '/vue-admin-template/user/login',

View File

@ -1,25 +0,0 @@
/**
* @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
}

View File

@ -1,22 +1,22 @@
{ {
"name": "vue-admin-template", "name": "vue-admin-template",
"version": "4.4.0", "version": "4.3.0",
"description": "A vue admin template with Element UI & axios & iconfont & permission control & lint", "description": "A vue admin template with Element UI & axios & iconfont & permission control & lint",
"author": "Pan <panfree23@gmail.com>", "author": "Pan <panfree23@gmail.com>",
"license": "MIT",
"scripts": { "scripts": {
"dev": "vue-cli-service serve", "dev": "vue-cli-service serve",
"build:prod": "vue-cli-service build", "build:prod": "vue-cli-service build",
"build:stage": "vue-cli-service build --mode staging", "build:stage": "vue-cli-service build --mode staging",
"preview": "node build/index.js --preview", "preview": "node build/index.js --preview",
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
"lint": "eslint --ext .js,.vue src", "lint": "eslint --ext .js,.vue src",
"test:unit": "jest --clearCache && vue-cli-service test:unit", "test:unit": "jest --clearCache && vue-cli-service test:unit",
"test:ci": "npm run lint && npm run test:unit" "test:ci": "npm run lint && npm run test:unit",
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml"
}, },
"dependencies": { "dependencies": {
"axios": "0.18.1", "axios": "0.18.1",
"core-js": "3.6.5", "element-ui": "2.13.0",
"element-ui": "2.13.2",
"js-cookie": "2.2.0", "js-cookie": "2.2.0",
"normalize.css": "7.0.0", "normalize.css": "7.0.0",
"nprogress": "0.2.0", "nprogress": "0.2.0",
@ -26,37 +26,38 @@
"vuex": "3.1.0" "vuex": "3.1.0"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "4.4.4", "@babel/core": "7.0.0",
"@vue/cli-plugin-eslint": "4.4.4", "@babel/register": "7.0.0",
"@vue/cli-plugin-unit-jest": "4.4.4", "@vue/cli-plugin-babel": "3.6.0",
"@vue/cli-service": "4.4.4", "@vue/cli-plugin-eslint": "^3.9.1",
"@vue/cli-plugin-unit-jest": "3.6.3",
"@vue/cli-service": "3.6.0",
"@vue/test-utils": "1.0.0-beta.29", "@vue/test-utils": "1.0.0-beta.29",
"autoprefixer": "9.5.1", "autoprefixer": "^9.5.1",
"babel-eslint": "10.1.0", "babel-core": "7.0.0-bridge.0",
"babel-eslint": "10.0.1",
"babel-jest": "23.6.0", "babel-jest": "23.6.0",
"babel-plugin-dynamic-import-node": "2.3.3",
"chalk": "2.4.2", "chalk": "2.4.2",
"connect": "3.6.6", "connect": "3.6.6",
"eslint": "6.7.2", "eslint": "5.15.3",
"eslint-plugin-vue": "6.2.2", "eslint-plugin-vue": "5.2.2",
"html-webpack-plugin": "3.2.0", "html-webpack-plugin": "3.2.0",
"mockjs": "1.0.1-beta3", "mockjs": "1.0.1-beta3",
"runjs": "4.3.2", "runjs": "^4.3.2",
"sass": "1.26.8", "sass": "^1.26.8",
"sass-loader": "8.0.2", "sass-loader": "^7.1.0",
"script-ext-html-webpack-plugin": "2.1.3", "script-ext-html-webpack-plugin": "2.1.3",
"serve-static": "1.13.2", "serve-static": "^1.13.2",
"svg-sprite-loader": "4.1.3", "svg-sprite-loader": "4.1.3",
"svgo": "1.2.2", "svgo": "1.2.2",
"vue-template-compiler": "2.6.10" "vue-template-compiler": "2.6.10"
}, },
"browserslist": [
"> 1%",
"last 2 versions"
],
"engines": { "engines": {
"node": ">=8.9", "node": ">=8.9",
"npm": ">= 3.0.0" "npm": ">= 3.0.0"
}, },
"license": "MIT" "browserslist": [
"> 1%",
"last 2 versions"
]
} }

View File

@ -17,11 +17,7 @@ export default {
const vnodes = [] const vnodes = []
if (icon) { if (icon) {
if (icon.includes('el-icon')) { vnodes.push(<svg-icon icon-class={icon}/>)
vnodes.push(<i class={[icon, 'sub-el-icon']} />)
} else {
vnodes.push(<svg-icon icon-class={icon}/>)
}
} }
if (title) { if (title) {
@ -31,11 +27,3 @@ export default {
} }
} }
</script> </script>
<style scoped>
.sub-el-icon {
color: currentColor;
width: 1em;
height: 1em;
}
</style>

View File

@ -19,7 +19,7 @@ import Layout from '@/layout'
* meta : { * meta : {
roles: ['admin','editor'] control the page roles (you can set multiple roles) roles: ['admin','editor'] control the page roles (you can set multiple roles)
title: 'title' the name show in sidebar and breadcrumb (recommend set) title: 'title' the name show in sidebar and breadcrumb (recommend set)
icon: 'svg-name'/'el-icon-x' the icon show in the sidebar icon: 'svg-name' the icon show in the sidebar
breadcrumb: false if set false, the item will hidden in breadcrumb(default is true) 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 activeMenu: '/example/list' if set path, the sidebar will highlight the path you set
} }
@ -60,7 +60,7 @@ export const constantRoutes = [
component: Layout, component: Layout,
redirect: '/example/table', redirect: '/example/table',
name: 'Example', name: 'Example',
meta: { title: 'Example', icon: 'el-icon-s-help' }, meta: { title: 'Example', icon: 'example' },
children: [ children: [
{ {
path: 'table', path: 'table',
@ -143,7 +143,6 @@ export const constantRoutes = [
{ {
path: 'menu2', path: 'menu2',
component: () => import('@/views/nested/menu2/index'), component: () => import('@/views/nested/menu2/index'),
name: 'Menu2',
meta: { title: 'menu2' } meta: { title: 'menu2' }
} }
] ]

View File

@ -10,7 +10,6 @@ const state = {
const mutations = { const mutations = {
CHANGE_SETTING: (state, { key, value }) => { CHANGE_SETTING: (state, { key, value }) => {
// eslint-disable-next-line no-prototype-builtins
if (state.hasOwnProperty(key)) { if (state.hasOwnProperty(key)) {
state[key] = value state[key] = value
} }

View File

@ -50,7 +50,7 @@ const actions = {
const { data } = response const { data } = response
if (!data) { if (!data) {
return reject('Verification failed, please Login again.') reject('Verification failed, please Login again.')
} }
const { name, avatar } = data const { name, avatar } = data

View File

@ -57,11 +57,6 @@
margin-right: 16px; margin-right: 16px;
} }
.sub-el-icon {
margin-right: 12px;
margin-left: -2px;
}
.el-menu { .el-menu {
border: none; border: none;
height: 100%; height: 100%;
@ -110,10 +105,6 @@
.svg-icon { .svg-icon {
margin-left: 20px; margin-left: 20px;
} }
.sub-el-icon {
margin-left: 19px;
}
} }
} }
@ -127,10 +118,6 @@
margin-left: 20px; margin-left: 20px;
} }
.sub-el-icon {
margin-left: 19px;
}
.el-submenu__icon-arrow { .el-submenu__icon-arrow {
display: none; display: none;
} }
@ -191,10 +178,6 @@
.svg-icon { .svg-icon {
margin-right: 16px; margin-right: 16px;
} }
.sub-el-icon {
margin-right: 12px;
margin-left: -2px;
}
} }
.nest-menu .el-submenu>.el-submenu__title, .nest-menu .el-submenu>.el-submenu__title,

View File

@ -99,19 +99,17 @@ export function formatTime(time, option) {
* @returns {Object} * @returns {Object}
*/ */
export function param2Obj(url) { export function param2Obj(url) {
const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ') const search = url.split('?')[1]
if (!search) { if (!search) {
return {} return {}
} }
const obj = {} return JSON.parse(
const searchArr = search.split('&') '{"' +
searchArr.forEach(v => { decodeURIComponent(search)
const index = v.indexOf('=') .replace(/"/g, '\\"')
if (index !== -1) { .replace(/&/g, '","')
const name = v.substring(0, index) .replace(/=/g, '":"')
const val = v.substring(index + 1, v.length) .replace(/\+/g, ' ') +
obj[name] = val '"}'
} )
})
return obj
} }

View File

@ -1,14 +0,0 @@
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: '测试'
})
})
})

View File

@ -49,19 +49,8 @@ module.exports = {
} }
}, },
chainWebpack(config) { chainWebpack(config) {
// it can improve the speed of the first screen, it is recommended to turn on preload config.plugins.delete('preload') // TODO: need test
config.plugin('preload').tap(() => [ config.plugins.delete('prefetch') // TODO: need test
{
rel: 'preload',
// to ignore runtime.js
// https://github.com/vuejs/vue-cli/blob/dev/packages/@vue/cli-service/lib/config/app.js#L171
fileBlacklist: [/\.map$/, /hot-update\.js$/, /runtime\..*\.js$/],
include: 'initial'
}
])
// when there are many pages, it will cause too many meaningless requests
config.plugins.delete('prefetch')
// set svg-sprite-loader // set svg-sprite-loader
config.module config.module
@ -80,6 +69,17 @@ module.exports = {
}) })
.end() .end()
// set preserveWhitespace
config.module
.rule('vue')
.use('vue-loader')
.loader('vue-loader')
.tap(options => {
options.compilerOptions.preserveWhitespace = true
return options
})
.end()
config config
.when(process.env.NODE_ENV !== 'development', .when(process.env.NODE_ENV !== 'development',
config => { config => {
@ -115,7 +115,6 @@ module.exports = {
} }
} }
}) })
// https:// webpack.js.org/configuration/optimization/#optimizationruntimechunk
config.optimization.runtimeChunk('single') config.optimization.runtimeChunk('single')
} }
) )