diff --git a/README.md b/README.md index d0ff7d74..cf67c757 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ Become a sponsor and get your logo on our README on GitHub with a link to your s - Multiple dynamic themes - Dynamic sidebar (supports multi-level routing) - Dynamic breadcrumb - - Tags-view(Tab page Support right-click operation) + - Tags-view (Tab page Support right-click operation) - Svg Sprite - Mock data - Screenfull diff --git a/README.zh-CN.md b/README.zh-CN.md index 55882115..d6cacf56 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -40,7 +40,7 @@ - [Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki) -- [Donate](https://panjiachen.github.io/vue-element-admin-site/zh/donate/) +- [Donate](https://panjiachen.gitee.io/vue-element-admin-site/zh/donate) - [Gitee](https://panjiachen.gitee.io/vue-element-admin/) 国内用户可访问该地址在线预览 @@ -214,6 +214,8 @@ Detailed changes for each release are documented in the [release notes](https:// 如果你觉得这个项目帮助到了你,你可以帮作者买一杯果汁表示鼓励 :tropical_drink: ![donate](https://panjiachen.github.io/donate/donation.png) +[更多捐赠方式](https://panjiachen.gitee.io/vue-element-admin-site/zh/donate) + [Paypal Me](https://www.paypal.me/panfree23) ## Browsers support diff --git a/build/webpack.prod.conf.js b/build/webpack.prod.conf.js index 946a134a..4f84e0c6 100644 --- a/build/webpack.prod.conf.js +++ b/build/webpack.prod.conf.js @@ -150,7 +150,6 @@ if (config.build.productionGzip) { webpackConfig.plugins.push( new CompressionWebpackPlugin({ - asset: '[path].gz[query]', algorithm: 'gzip', test: new RegExp( '\\.(' + config.build.productionGzipExtensions.join('|') + ')$' diff --git a/package.json b/package.json index 8cc2c747..acf86dd1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue-element-admin", - "version": "3.9.3", + "version": "3.10.0", "description": "A magical vue admin. Typical templates for enterprise applications. Newest development stack of vue. Lots of awesome features", "author": "Pan ", "license": "MIT", @@ -77,6 +77,7 @@ "babel-preset-env": "1.7.0", "babel-preset-stage-2": "6.24.1", "chalk": "2.4.1", + "compression-webpack-plugin": "2.0.0", "copy-webpack-plugin": "4.5.2", "cross-env": "5.2.0", "css-loader": "1.0.0", @@ -117,7 +118,7 @@ "webpack": "4.16.5", "webpack-bundle-analyzer": "2.13.1", "webpack-cli": "3.1.0", - "webpack-dev-server": "3.1.5", + "webpack-dev-server": "3.1.14", "webpack-merge": "4.1.4" }, "engines": { diff --git a/src/components/ThemePicker/index.vue b/src/components/ThemePicker/index.vue index e797d6c2..5d1ff8bd 100644 --- a/src/components/ThemePicker/index.vue +++ b/src/components/ThemePicker/index.vue @@ -18,7 +18,8 @@ export default { } }, watch: { - theme(val, oldVal) { + theme(val) { + const oldVal = this.theme if (typeof val !== 'string') return const themeCluster = this.getThemeCluster(val.replace('#', '')) const originalCluster = this.getThemeCluster(oldVal.replace('#', '')) diff --git a/src/lang/en.js b/src/lang/en.js index 656b746b..2af355b1 100644 --- a/src/lang/en.js +++ b/src/lang/en.js @@ -87,7 +87,8 @@ export default { }, permission: { roles: 'Your roles', - switchRoles: 'Switch roles' + switchRoles: 'Switch roles', + tips: 'In some cases it is not suitable to use v-permission, such as element Tab component or el-table-column and other asynchronous rendering dom cases which can only be achieved by manually setting the v-if.' }, guide: { description: 'The guide page is useful for some people who entered the project for the first time. You can briefly introduce the features of the project. Demo is based on ', diff --git a/src/lang/es.js b/src/lang/es.js index 69218ad2..1268f083 100755 --- a/src/lang/es.js +++ b/src/lang/es.js @@ -87,7 +87,8 @@ export default { }, permission: { roles: 'Tus permisos', - switchRoles: 'Cambiar permisos' + switchRoles: 'Cambiar permisos', + tips: 'In some cases it is not suitable to use v-permission, such as element Tab component or el-table-column and other asynchronous rendering dom cases which can only be achieved by manually setting the v-if.' }, guide: { description: 'The guide page is useful for some people who entered the project for the first time. You can briefly introduce the features of the project. Demo is based on ', diff --git a/src/lang/zh.js b/src/lang/zh.js index 021a5fa7..4371713f 100644 --- a/src/lang/zh.js +++ b/src/lang/zh.js @@ -87,7 +87,8 @@ export default { }, permission: { roles: '你的权限', - switchRoles: '切换权限' + switchRoles: '切换权限', + tips: '在某些情况下,不适合使用 v-permission。例如:Element-UI 的 Tab 组件或 el-table-column 以及其它动态渲染 dom 的场景。你只能通过手动设置 v-if 来实现。' }, guide: { description: '引导页对于一些第一次进入项目的人很有用,你可以简单介绍下项目的功能。本 Demo 是基于', diff --git a/src/permission.js b/src/permission.js index 81f9d113..e556cb00 100644 --- a/src/permission.js +++ b/src/permission.js @@ -33,7 +33,7 @@ router.beforeEach((to, from, next) => { }) }).catch((err) => { store.dispatch('FedLogOut').then(() => { - Message.error(err || 'Verification failed, please login again') + Message.error(err) next({ path: '/' }) }) }) diff --git a/src/store/modules/app.js b/src/store/modules/app.js index bc4fb478..fba4b05c 100644 --- a/src/store/modules/app.js +++ b/src/store/modules/app.js @@ -3,7 +3,7 @@ import Cookies from 'js-cookie' const app = { state: { sidebar: { - opened: !+Cookies.get('sidebarStatus'), + opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true, withoutAnimation: false }, device: 'desktop', @@ -12,16 +12,16 @@ const app = { }, mutations: { TOGGLE_SIDEBAR: state => { + state.sidebar.opened = !state.sidebar.opened + state.sidebar.withoutAnimation = false if (state.sidebar.opened) { Cookies.set('sidebarStatus', 1) } else { Cookies.set('sidebarStatus', 0) } - state.sidebar.opened = !state.sidebar.opened - state.sidebar.withoutAnimation = false }, CLOSE_SIDEBAR: (state, withoutAnimation) => { - Cookies.set('sidebarStatus', 1) + Cookies.set('sidebarStatus', 0) state.sidebar.opened = false state.sidebar.withoutAnimation = withoutAnimation }, diff --git a/src/store/modules/user.js b/src/store/modules/user.js index 0f7e2296..38e81a36 100644 --- a/src/store/modules/user.js +++ b/src/store/modules/user.js @@ -63,15 +63,16 @@ const user = { GetUserInfo({ commit, state }) { return new Promise((resolve, reject) => { getUserInfo(state.token).then(response => { - if (!response.data) { // 由于mockjs 不支持自定义状态码只能这样hack - reject('error') + // 由于mockjs 不支持自定义状态码只能这样hack + if (!response.data) { + reject('Verification failed, please login again.') } const data = response.data if (data.roles && data.roles.length > 0) { // 验证返回的roles是否是一个非空数组 commit('SET_ROLES', data.roles) } else { - reject('getInfo: roles must be a non-null array !') + reject('getInfo: roles must be a non-null array!') } commit('SET_NAME', data.name) diff --git a/src/styles/btn.scss b/src/styles/btn.scss index 0c5ee768..e6ba1a8e 100644 --- a/src/styles/btn.scss +++ b/src/styles/btn.scss @@ -2,8 +2,10 @@ @mixin colorBtn($color) { background: $color; + &:hover { color: $color; + &:before, &:after { background: $color; @@ -49,14 +51,17 @@ transition: 600ms ease all; position: relative; display: inline-block; + &:hover { background: #fff; + &:before, &:after { width: 100%; transition: 600ms ease all; } } + &:before, &:after { content: ''; @@ -67,6 +72,7 @@ width: 0; transition: 400ms ease all; } + &::after { right: inherit; top: inherit; @@ -91,4 +97,3 @@ font-size: 14px; border-radius: 4px; } - diff --git a/src/styles/element-ui.scss b/src/styles/element-ui.scss index dc59591e..494dcfa4 100644 --- a/src/styles/element-ui.scss +++ b/src/styles/element-ui.scss @@ -1,82 +1,85 @@ - //覆盖一些element-ui样式 +//覆盖一些element-ui样式 - .el-breadcrumb__inner, .el-breadcrumb__inner a{ - font-weight: 400!important; +.el-breadcrumb__inner, +.el-breadcrumb__inner a { + font-weight: 400 !important; } - .el-upload { - input[type="file"] { - display: none !important; - } - } +.el-upload { + input[type="file"] { + display: none !important; + } +} - .el-upload__input { - display: none; - } +.el-upload__input { + display: none; +} - .cell { - .el-tag { - margin-right: 0px; - } - } +.cell { + .el-tag { + margin-right: 0px; + } +} - .small-padding { - .cell { - padding-left: 5px; - padding-right: 5px; - } - } +.small-padding { + .cell { + padding-left: 5px; + padding-right: 5px; + } +} - .fixed-width{ - .el-button--mini{ +.fixed-width { + .el-button--mini { padding: 7px 10px; width: 60px; } - } +} - .status-col { - .cell { - padding: 0 10px; - text-align: center; - .el-tag { - margin-right: 0px; - } - } - } +.status-col { + .cell { + padding: 0 10px; + text-align: center; - //暂时性解决dialog 问题 https://github.com/ElemeFE/element/issues/2461 - .el-dialog { - transform: none; - left: 0; - position: relative; - margin: 0 auto; - } + .el-tag { + margin-right: 0px; + } + } +} - //文章页textarea修改样式 - .article-textarea { - textarea { - padding-right: 40px; - resize: none; - border: none; - border-radius: 0px; - border-bottom: 1px solid #bfcbd9; - } - } +//暂时性解决dialog 问题 https://github.com/ElemeFE/element/issues/2461 +.el-dialog { + transform: none; + left: 0; + position: relative; + margin: 0 auto; +} - //element ui upload - .upload-container { - .el-upload { - width: 100%; - .el-upload-dragger { - width: 100%; - height: 200px; - } - } - } +//文章页textarea修改样式 +.article-textarea { + textarea { + padding-right: 40px; + resize: none; + border: none; + border-radius: 0px; + border-bottom: 1px solid #bfcbd9; + } +} + +//element ui upload +.upload-container { + .el-upload { + width: 100%; + + .el-upload-dragger { + width: 100%; + height: 200px; + } + } +} //dropdown - .el-dropdown-menu{ - a{ +.el-dropdown-menu { + a { display: block } } diff --git a/src/styles/index.scss b/src/styles/index.scss index b6fd924e..93f2157e 100644 --- a/src/styles/index.scss +++ b/src/styles/index.scss @@ -22,7 +22,7 @@ html { box-sizing: border-box; } -#app{ +#app { height: 100%; } @@ -53,9 +53,9 @@ a:hover { text-decoration: none; } -div:focus{ +div:focus { outline: none; - } +} .fr { float: right; @@ -104,23 +104,26 @@ code { line-height: 36px; font-size: 15px; font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif; + a { color: #337ab7; cursor: pointer; + &:hover { color: rgb(32, 160, 255); } } } -.warn-content{ - background: rgba(66,185,131,.1); +.warn-content { + background: rgba(66, 185, 131, .1); border-radius: 2px; padding: 16px; padding: 1rem; line-height: 1.6rem; word-spacing: .05rem; - a{ + + a { color: #42b983; font-weight: 600; } @@ -153,13 +156,16 @@ code { padding-right: 20px; transition: 600ms ease position; background: linear-gradient(90deg, rgba(32, 182, 249, 1) 0%, rgba(32, 182, 249, 1) 0%, rgba(33, 120, 241, 1) 100%, rgba(33, 120, 241, 1) 100%); + .subtitle { font-size: 20px; color: #fff; } + &.draft { background: #d0d0d0; } + &.deleted { background: #d0d0d0; } @@ -169,6 +175,7 @@ code { .link-type:focus { color: #337ab7; cursor: pointer; + &:hover { color: rgb(32, 160, 255); } @@ -176,6 +183,7 @@ code { .filter-container { padding-bottom: 10px; + .filter-item { display: inline-block; vertical-align: middle; diff --git a/src/styles/mixin.scss b/src/styles/mixin.scss index 822ab92a..06fa0612 100644 --- a/src/styles/mixin.scss +++ b/src/styles/mixin.scss @@ -10,9 +10,11 @@ &::-webkit-scrollbar-track-piece { background: #d3dce6; } + &::-webkit-scrollbar { width: 6px; } + &::-webkit-scrollbar-thumb { background: #99a9bf; border-radius: 20px; @@ -37,21 +39,25 @@ $transparent-border-style: $width solid transparent; height: 0; width: 0; + @if $direction==up { border-bottom: $color-border-style; border-left: $transparent-border-style; border-right: $transparent-border-style; } + @else if $direction==right { border-left: $color-border-style; border-top: $transparent-border-style; border-bottom: $transparent-border-style; } + @else if $direction==down { border-top: $color-border-style; border-left: $transparent-border-style; border-right: $transparent-border-style; } + @else if $direction==left { border-right: $color-border-style; border-top: $transparent-border-style; diff --git a/src/styles/sidebar.scss b/src/styles/sidebar.scss index faa7366e..723f9a12 100644 --- a/src/styles/sidebar.scss +++ b/src/styles/sidebar.scss @@ -1,15 +1,17 @@ #app { - // 主体区域 + + // 主体区域 Main container .main-container { min-height: 100%; transition: margin-left .28s; - margin-left: 180px; + margin-left: $sideBarWidth; position: relative; } - // 侧边栏 + + // 侧边栏 Sidebar container .sidebar-container { transition: width 0.28s; - width: 180px !important; + width: $sideBarWidth !important; height: 100%; position: fixed; font-size: 0px; @@ -18,62 +20,79 @@ left: 0; z-index: 1001; overflow: hidden; + //reset element-ui css .horizontal-collapse-transition { transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out; } + .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 { right: 0px; } + .is-horizontal { display: none; } + a { display: inline-block; width: 100%; overflow: hidden; } + .svg-icon { margin-right: 16px; } + .el-menu { border: none; height: 100%; width: 100% !important; } - .is-active > .el-submenu__title{ - color: #f4f4f5!important; + + .is-active>.el-submenu__title { + color: #f4f4f5 !important; } } + .hideSidebar { .sidebar-container { width: 36px !important; } + .main-container { margin-left: 36px; } + .submenu-title-noDropdown { padding-left: 10px !important; position: relative; + .el-tooltip { padding: 0 10px !important; } } + .el-submenu { overflow: hidden; + &>.el-submenu__title { padding-left: 10px !important; + .el-submenu__icon-arrow { display: none; } } } + .el-menu--collapse { .el-submenu { &>.el-submenu__title { @@ -88,35 +107,42 @@ } } } + .sidebar-container .nest-menu .el-submenu>.el-submenu__title, .sidebar-container .el-submenu .el-menu-item { - min-width: 180px !important; + min-width: $sideBarWidth !important; background-color: $subMenuBg !important; + &:hover { background-color: $menuHover !important; } } + .el-menu--collapse .el-menu .el-submenu { - min-width: 180px !important; + min-width: $sideBarWidth !important; } - //适配移动端 + // 适配移动端, Mobile responsive .mobile { .main-container { margin-left: 0px; } + .sidebar-container { transition: transform .28s; - width: 180px !important; + width: $sideBarWidth !important; } + &.hideSidebar { .sidebar-container { transition-duration: 0.3s; - transform: translate3d(-180px, 0, 0); + transform: translate3d(-$sideBarWidth, 0, 0); } } } + .withoutAnimation { + .main-container, .sidebar-container { transition: none; @@ -124,9 +150,9 @@ } } -.el-menu--vertical{ - & >.el-menu{ - .svg-icon{ +.el-menu--vertical { + &>.el-menu { + .svg-icon { margin-right: 16px; } } diff --git a/src/styles/transition.scss b/src/styles/transition.scss index 04e16279..ab68317d 100644 --- a/src/styles/transition.scss +++ b/src/styles/transition.scss @@ -16,10 +16,12 @@ .fade-transform-enter-active { transition: all .5s; } + .fade-transform-enter { opacity: 0; transform: translateX(-30px); } + .fade-transform-leave-to { opacity: 0; transform: translateX(30px); @@ -44,4 +46,3 @@ .breadcrumb-leave-active { position: absolute; } - diff --git a/src/styles/variables.scss b/src/styles/variables.scss index acc77a82..09c3e9b0 100644 --- a/src/styles/variables.scss +++ b/src/styles/variables.scss @@ -1,3 +1,4 @@ +// base color $blue:#324157; $light-blue:#3A71A8; $red:#C03639; @@ -11,3 +12,4 @@ $panGreen: #30B08F; $menuBg:#304156; $subMenuBg:#1f2d3d; $menuHover:#001528; +$sideBarWidth: 180px; diff --git a/src/views/permission/directive.vue b/src/views/permission/directive.vue index 2817f1c5..df277ddc 100644 --- a/src/views/permission/directive.vue +++ b/src/views/permission/directive.vue @@ -2,29 +2,53 @@
- - Only - admin can see this - - - Only - editor can see this - - - Both - admin and - editor can see this - +
+ + Only + admin can see this + + v-permission="['admin']" +
+ +
+ + Only + editor can see this + + v-permission="['editor']" +
+ +
+ + Both + admin and + editor can see this + + v-permission="['admin','editor']" +
-
- In some cases it is not suitable to use v-permission, such as element Tab component which can only be achieved by manually setting the v-if. +
+ + {{ $t('permission.tips') }}
e.g.
- - Admin can see this - Editor can see this - Both admin or editor can see this + + + + Admin can see this + v-if="checkPermission(['admin'])" + + + + Editor can see this + v-if="checkPermission(['editor'])" + + + + Both admin or editor can see this + v-if="checkPermission(['admin','editor'])" +
@@ -57,14 +81,17 @@ export default{ .app-container { /deep/ .permission-alert { width: 320px; - margin-top: 30px; + margin-top: 15px; background-color: #f0f9eb; color: #67c23a; padding: 8px 16px; border-radius: 4px; - display: block; + display: inline-block; } - /deep/ .permission-tag{ + /deep/ .permission-sourceCode { + margin-left: 15px; + } + /deep/ .permission-tag { background-color: #ecf5ff; } }