同步修改精简版

master
toesbieya 6 years ago
parent c44753a0ce
commit b449fbfa7b
  1. 250
      vue/full/src/asset/style/element-ui.scss
  2. 2
      vue/template/element-ui-personal/style/message.scss
  3. 9
      vue/template/package-lock.json
  4. 3
      vue/template/package.json
  5. 93
      vue/template/src/asset/style/cover/element-ui.scss
  6. 7
      vue/template/src/asset/style/cover/var.scss
  7. 2
      vue/template/src/asset/style/display.scss
  8. 19
      vue/template/src/asset/style/index.scss
  9. 32
      vue/template/src/asset/style/mixin.scss
  10. 2
      vue/template/src/asset/style/nprogress.scss
  11. 222
      vue/template/src/asset/style/transition.scss
  12. 59
      vue/template/src/asset/style/var.scss
  13. 11
      vue/template/src/component/checkbox/ImgCheckbox.vue
  14. 4
      vue/template/src/component/menu/ContextMenu/index.vue
  15. 4
      vue/template/src/component/menu/NavMenu/index.vue
  16. 2
      vue/template/src/component/menu/NavMenu/style.scss
  17. 2
      vue/template/src/component/menu/NavMenu/theme-dark.scss
  18. 2
      vue/template/src/component/menu/NavMenu/theme-light.scss
  19. 12
      vue/template/src/config/index.js
  20. 82
      vue/template/src/directive/dragDialog.js
  21. 5
      vue/template/src/directive/index.js
  22. 4
      vue/template/src/layout/component/Aside/component/MenuSearch.vue
  23. 3
      vue/template/src/layout/component/Aside/style.scss
  24. 6
      vue/template/src/layout/component/Aside/theme-dark.scss
  25. 6
      vue/template/src/layout/component/Aside/theme-light.scss
  26. 2
      vue/template/src/layout/component/Logo.vue
  27. 2
      vue/template/src/layout/component/Navbar/style.scss
  28. 2
      vue/template/src/layout/component/Navbar/theme-dark.scss
  29. 4
      vue/template/src/layout/component/Navbar/theme-light.scss
  30. 4
      vue/template/src/layout/component/Page/component/BackToTop.vue
  31. 5
      vue/template/src/layout/component/Page/component/PageFooter.vue
  32. 8
      vue/template/src/layout/component/Page/component/PageHeader.vue
  33. 8
      vue/template/src/layout/component/Page/component/TagsView/style.scss
  34. 50
      vue/template/src/layout/component/Page/index.vue
  35. 23
      vue/template/src/layout/component/Page/style.scss
  36. 34
      vue/template/src/layout/component/SettingDrawer.vue
  37. 13
      vue/template/src/layout/mixin/decideRouterTransition.js
  38. 2
      vue/template/src/layout/store/app.js
  39. 17
      vue/template/src/layout/store/page.js
  40. 10
      vue/template/src/layout/store/tagsView.js
  41. 1
      vue/template/src/main.js
  42. 5
      vue/template/src/router/guardian/accessControl.js
  43. 11
      vue/template/src/router/module/example/child/directive.js
  44. 89
      vue/template/src/store/module/resource.js
  45. 32
      vue/template/src/store/module/user.js
  46. 17
      vue/template/src/util/auth.js
  47. 4
      vue/template/src/util/browser.js
  48. 2
      vue/template/src/view/_app/login/index.vue
  49. 44
      vue/template/src/view/_app/login/style.scss
  50. 7
      vue/template/src/view/_common/ExceptionPage/style.scss
  51. 2
      vue/template/src/view/_common/SkeletonPage/style.scss
  52. 4
      vue/template/src/view/example/component/skeletonPage.vue
  53. 25
      vue/template/src/view/example/directive/dragDialogPage.vue
  54. 12
      vue/template/vue.config.js

@ -1,250 +0,0 @@
// cover some element-ui styles
.el-alert {
&--info.is-light {
color: #606266;
background-color: #f0faff;
border: 1px solid #abdcff;
.el-icon-info {
color: $--color-primary;
}
}
}
.el-button {
[class*="el-icon-"] + span {
margin-left: 7px;
}
//按钮新增类型type=dashed
&.el-button--dashed {
border-style: dashed;
}
&.el-button--small {
font-size: 14px;
padding: 8px 15px;
&.is-circle {
padding: 8px;
}
}
}
.el-card {
overflow: visible;
.el-card__body {
height: 100%;
@include clearfix;
}
.el-card__header + .el-card__body {
height: calc(100% - 55px);
}
}
.el-date-editor.el-input,
.el-date-editor--daterange {
width: 100% !important;
}
.el-dialog {
@include deep-shadow;
margin-bottom: 0;
min-width: 384px;
.el-dialog__header {
border-bottom: 1px solid #EBEEF5;
padding: 17px;
.el-dialog__title {
line-height: inherit;
color: inherit;
font-size: inherit;
}
.el-dialog__headerbtn {
top: 18px;
}
}
.el-dialog__footer {
border-top: 1px solid #EBEEF5;
padding: 10px 16px;
}
.el-scrollbar__wrap {
//53 for dialog header,53 for dialog footer
max-height: calc(100vh - 53px - 53px - #{$dialog-top * 2});
}
}
.el-drawer {
&__body {
overflow-y: overlay;
}
}
.el-loading-mask {
background: #ffffff;
color: $--color-primary;
}
.el-menu {
width: 100%;
border: none !important;
overflow: hidden;
&::-webkit-scrollbar {
display: none;
}
//子级菜单激活时父级同样高亮
.el-menu-item.is-active,
.is-active > .el-submenu__title {
color: $--color-primary !important;
}
//箭头图标与字体同色
.el-submenu__title i {
color: inherit;
}
//原先垂直时右侧展开箭头偏上
.el-submenu__icon-arrow {
margin-top: -4px;
}
//弹出菜单
&.el-menu--popup {
max-height: 88vh;
min-width: 160px;
padding: 0;
margin-bottom: 0.5vh;
overflow-y: auto;
.el-menu-item,
.el-submenu__title {
padding: 0 $menu-padding;
}
}
&--horizontal > .el-menu-item:not(.is-disabled):hover,
&--horizontal > .el-menu-item:not(.is-disabled):focus,
&--horizontal > .el-submenu .el-submenu__title:hover,
&--horizontal .el-menu .el-menu-item,
&--horizontal .el-menu .el-submenu__title {
background-color: inherit;
}
}
.el-message {
@include deep-shadow;
@include max-width-on-mobile;
border-width: 0;
.el-message__icon, .el-message__content {
color: #ffffff !important;
}
&.el-message--success {
background: $--color-success;
}
&.el-message--info {
background: $--color-primary;
}
&.el-message--warning {
background: $--color-warning;
}
&.el-message--error {
background: $--color-danger;
}
}
.el-message-box {
position: relative;
@include deep-shadow;
@include max-width-on-mobile;
}
.el-notification {
@include deep-shadow;
.el-notification__icon.el-icon-info {
color: $--color-primary;
}
}
.el-pagination {
text-align: right;
.el-pagination__editor.el-input {
margin: 0 5px;
}
.el-table + & {
padding-top: 20px;
}
}
.el-scrollbar {
height: 100%;
.el-scrollbar__wrap {
-webkit-overflow-scrolling: touch;
}
}
.el-select {
width: 100%;
}
.el-steps {
&.el-steps--horizontal {
.el-step__line {
left: 57%;
right: -43%;
}
}
}
.el-table {
thead {
color: #303133
}
thead > tr > th {
background: #fbfbfb;
}
}
.el-textarea {
.el-input__count {
background: transparent;
}
}
.el-upload {
$size: 100px;
&-list__item-thumbnail {
object-fit: cover;
}
&.el-upload--picture-card {
height: $size;
width: $size;
line-height: $size;
}
&-list .el-upload-list__item {
height: $size;
width: $size;
}
}

@ -23,7 +23,7 @@
left: 10px;
right: 10px;
animation: el-message-progress linear;
background: currentColor;
background-color: currentColor;
opacity: .3;
transform-origin: 0 50%;
transform: scaleX(0);

@ -11560,15 +11560,6 @@
}
}
},
"webpack-theme-color-replacer": {
"version": "1.3.14",
"resolved": "https://registry.npm.taobao.org/webpack-theme-color-replacer/download/webpack-theme-color-replacer-1.3.14.tgz",
"integrity": "sha1-K9ybKecIqpDKVq/OZJVWksUFC4s=",
"dev": true,
"requires": {
"webpack-sources": "*"
}
},
"websocket-driver": {
"version": "0.6.5",
"resolved": "https://registry.npm.taobao.org/websocket-driver/download/websocket-driver-0.6.5.tgz",

@ -24,8 +24,7 @@
"sass-loader": "^8.0.2",
"svg-sprite-loader": "^4.3.0",
"svgo": "^1.3.2",
"vue-template-compiler": "^2.6.11",
"webpack-theme-color-replacer": "^1.3.14"
"vue-template-compiler": "^2.6.11"
},
"postcss": {
"plugins": {

@ -0,0 +1,93 @@
// cover some element-ui styles
.el-backtop {
border-radius: 0;
}
.el-drawer {
&__body {
overflow-y: overlay;
}
}
.el-menu {
width: 100%;
border: none !important;
overflow: hidden;
&::-webkit-scrollbar {
display: none;
}
//子级菜单激活时父级同样高亮
.el-menu-item.is-active,
.is-active > .el-submenu__title {
color: $--color-primary !important;
}
//箭头图标与字体同色
.el-submenu__title i {
color: inherit;
}
//原先垂直时右侧展开箭头偏上
.el-submenu__icon-arrow {
margin-top: -4px;
}
//弹出菜单
&.el-menu--popup {
max-height: 88vh;
min-width: 160px;
padding: 0;
margin-bottom: 0.5vh;
overflow-y: auto;
.el-menu-item,
.el-submenu__title {
padding: 0 $menu-padding;
}
}
&--horizontal > .el-menu-item:not(.is-disabled):hover,
&--horizontal > .el-menu-item:not(.is-disabled):focus,
&--horizontal > .el-submenu .el-submenu__title:hover,
&--horizontal .el-menu .el-menu-item,
&--horizontal .el-menu .el-submenu__title {
background-color: inherit;
}
}
.el-message {
@include deep-shadow;
@include max-width-on-mobile;
border-width: 0;
.el-message__icon,
.el-message__content {
color: $--color-white !important;
}
&.el-message--success {
background-color: $--color-success;
}
&.el-message--info {
background-color: $--color-primary;
}
&.el-message--warning {
background-color: $--color-warning;
}
&.el-message--error {
background-color: $--color-danger;
}
}
.el-scrollbar {
height: 100%;
.el-scrollbar__wrap {
-webkit-overflow-scrolling: touch;
}
}

@ -0,0 +1,7 @@
/*仅覆盖element-ui中的预设变量,不会被使用*/
//el-menu的hover背景颜色
$--menu-item-hover-fill: none;
//引入element的scss时需要覆盖字体路径
$--font-path: '~element-ui/lib/theme-chalk/fonts';

@ -1,4 +1,4 @@
@media only screen and (max-width: 768px) {
@media only screen and (max-width: $--sm) {
.hidden-xs {
display: none !important
}

@ -1,11 +1,13 @@
@import "~normalize.css/normalize.css";
@import "./variables";
@import "~element-ui/packages/theme-chalk/src/index";
@import "./var.scss";
@import "./cover/var.scss";
@import "./mixin.scss";
@import "~element-ui/packages/theme-chalk/src/index.scss";
@import "~@ele/style/index.scss";
@import "./element-ui";
@import './display';
@import "./transition";
@import "./nprogress";
@import "./cover/element-ui.scss";
@import './display.scss';
@import "./transition.scss";
@import "./nprogress.scss";
body {
height: 100%;
@ -59,7 +61,7 @@ a:hover {
background-color: rgba($--color-primary, 0.8);
&:hover {
background-color: rgba($--color-primary, 1);
background-color: $--color-primary;
}
}
}
@ -72,10 +74,11 @@ a:hover {
align-content: space-between;
}
//仅用于演示用例
.tip-row {
position: relative;
z-index: 1;
background: #fafafa;
background-color: #fafafa;
padding: 8px 24px;
margin-bottom: 20px;
border-radius: 2px;

@ -0,0 +1,32 @@
@mixin clearfix {
&::after {
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0;
}
}
@mixin deep-shadow {
box-shadow: 0 3px 5px -1px rgba(0, 0, 0, 0.2), 0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 18px 0 rgba(0, 0, 0, 0.12);
}
@mixin mobile {
@media (max-width: $max-mobile-width) {
@content
}
}
@mixin pc {
@media (min-width: $max-mobile-width) {
@content
}
}
@mixin max-width-on-mobile {
@include mobile {
max-width: 384px;
}
}

@ -2,7 +2,7 @@
#nprogress {
.bar {
background: $--color-primary;
background-color: $--color-primary;
.peg {
box-shadow: 0 0 10px $--color-primary, 0 0 5px $--color-primary;;

@ -1,5 +1,3 @@
$transition-easing: cubic-bezier(0.215, 0.61, 0.355, 1);
.right-out,
.left-out {
&-leave-active,
@ -31,223 +29,3 @@ $transition-easing: cubic-bezier(0.215, 0.61, 0.355, 1);
transform: translateX(-30px);
}
}
.slide-right,
.slide-left,
.slide-up,
.slide-down,
.jump-right,
.jump-left,
.jump-up,
.jump-down,
.fade,
.scale,
.rotate,
.flip {
&-leave-active {
position: absolute
}
}
.slide-right,
.slide-left,
.slide-up,
.slide-down {
&-enter-active,
&-leave-active {
transition: transform .3s $transition-easing
}
}
.slide-right {
&-enter {
transform: translate3d(-100%, 0, 0);
}
&-leave-to {
transform: translate3d(100%, 0, 0);
}
}
.slide-left {
&-enter {
transform: translate3d(100%, 0, 0);
}
&-leave-to {
transform: translate3d(-100%, 0, 0);
}
}
.slide-up {
&-enter {
transform: translate3d(0, 100%, 0)
}
&-leave-to {
transform: translate3d(0, -100%, 0)
}
}
.slide-down {
&-enter {
transform: translate3d(0, -100%, 0)
}
&-leave-to {
transform: translate3d(0, 100%, 0)
}
}
.jump-right,
.jump-left,
.jump-up,
.jump-down {
&-enter-active,
&-leave-active {
transition: opacity .3s, transform .3s
}
&-enter,
&-leave-to {
opacity: 0
}
}
.jump-right {
&-enter {
transform: translate3d(-15px, 0, 0)
}
&-leave-to {
transform: translate3d(15px, 0, 0)
}
}
.jump-left {
&-enter {
transform: translate3d(15px, 0, 0)
}
&-leave-to {
transform: translateX(-15px)
}
}
.jump-up {
&-enter {
transform: translate3d(0, 15px, 0)
}
&-leave-to {
transform: translate3d(0, -15px, 0)
}
}
.jump-down {
&-enter {
transform: translate3d(0, -15px, 0)
}
&-leave-to {
transform: translate3d(15px, 0, 0)
}
}
.fade {
&-enter-active,
&-leave-active {
transition: opacity .3s ease-out
}
&-enter,
&-leave,
&-leave-to {
opacity: 0
}
}
.scale {
&-enter-active,
&-leave-active {
transition: opacity .3s, transform .3s $transition-easing
}
&-enter,
&-leave,
&-leave-to {
opacity: 0;
transform: scale3d(0, 0, 1)
}
}
.rotate {
&-enter-active,
&-leave-active {
transition: opacity .3s, transform .3s $transition-easing;
transform-style: preserve-3d
}
&-enter,
&-leave,
&-leave-to {
opacity: 0;
transform: scale3d(0, 0, 1) rotate3d(0, 0, 1, 90deg)
}
}
.flip-right,
.flip-left,
.flip-up,
.flip-down {
&-enter-active,
&-leave-active {
transition: transform .3s;
backface-visibility: hidden
}
&-enter-to,
&-leave {
transform: perspective(400px) rotate3d(1, 1, 0, 0deg)
}
}
.flip-right {
&-enter {
transform: perspective(400px) rotate3d(0, 1, 0, -180deg)
}
&-leave-to {
transform: perspective(400px) rotate3d(0, 1, 0, 180deg)
}
}
.flip-left {
&-enter {
transform: perspective(400px) rotate3d(0, 1, 0, 180deg)
}
&-leave-to {
transform: perspective(400px) rotate3d(0, 1, 0, -180deg)
}
}
.flip-up {
&-enter {
transform: perspective(400px) rotate3d(1, 0, 0, -180deg)
}
&-leave-to {
transform: perspective(400px) rotate3d(1, 0, 0, 180deg)
}
}
.flip-down {
&-enter {
transform: perspective(400px) rotate3d(1, 0, 0, 180deg)
}
&-leave-to {
transform: perspective(400px) rotate3d(1, 0, 0, -180deg)
}
}

@ -1,52 +1,15 @@
@import "~element-ui/packages/theme-chalk/src/common/var";
//设定移动端的最大宽度只能是number类型
$max-mobile-width: 500px;
//覆盖element颜色
$--color-primary: #1890ff; //这里如果有改动需要同时修改vue.config.js中ThemeColorReplacer的配置
$--color-primary: #1890ff;
$--color-success: #21BA45;
$--color-warning: #FF5722;
$--color-danger: #F44336;
$--color-info: #009688;
//覆盖el-menu的hover背景颜色
$--menu-item-hover-fill: none;
//引入element的scss时需要覆盖字体路径
$--font-path: '~element-ui/lib/theme-chalk/fonts';
@mixin clearfix {
&::after {
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0;
}
}
@mixin deep-shadow {
box-shadow: 0 3px 5px -1px rgba(0, 0, 0, 0.2), 0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 18px 0 rgba(0, 0, 0, 0.12);
}
@mixin mobile {
@media (max-width: $max-mobile-width) {
@content
}
}
@mixin pc {
@media (min-width: $max-mobile-width) {
@content
}
}
@mixin max-width-on-mobile {
@include mobile {
max-width: 384px;
}
}
//菜单中icon的大小
$menu-icon-size: 14px;
//菜单中icon和文字的距离
@ -60,7 +23,7 @@ $sub-menu-background-dark: darken($menu-background-dark, 5%);
//暗色主菜单的背景色用于双层侧边栏的主菜单和顶部导航栏
$root-menu-background-dark: #1F293D;
//亮色菜单的文字颜色
$menu-text-color-light: #303133;
$menu-text-color-light: $--color-text-primary;
//暗色菜单的文字颜色
$menu-text-color-dark: rgba(255, 255, 255, .65);
//亮色菜单的文字hover颜色
@ -89,17 +52,19 @@ $navbar-item-hover-color-dark: lighten($root-menu-background-dark, 5%);
//多页签栏高度
$tags-view-height: 32px;
//页头
$page-header-line-height: 26px;
//页头高用于max-view-height
$page-header-height: 44px;
//页头的上下padding
$page-header-padding: 12px;
//路由页面的margin
$page-view-margin: 24px;
//亮色边框的颜色使用的element-ui原定义
$border-color-light: #dcdfe6;
//暗色边框的颜色
$border-color-dark: darken($root-menu-background-dark, 5%);
//页脚高度用于max-view-height
$page-footer-height: 64px;
//暗色边框的颜色用于nav-menu和侧边栏
$--border-color-dark: darken($root-menu-background-dark, 5%);
//dialog距离顶部的距离用于<el-dialog>的top属性<el-dialog>中滚动区域的最大高度
$dialog-top: 100px;

@ -6,13 +6,16 @@ export default {
mixins: [common],
props: ['img'],
props: {
img: String,
label: String
},
render() {
return (
<div class="img-checkbox" on-click={this.click}>
<div class="img-checkbox" title={this.label} on-click={this.click}>
<img src={this.img}/>
{this.checked && <i class="el-icon-check"/>}
{this.checked && <i className="el-icon-check"/>}
</div>
)
}
@ -20,7 +23,7 @@ export default {
</script>
<style lang="scss">
@import "~@/asset/style/variables.scss";
@import "~@/asset/style/var";
.img-checkbox {
width: 55px;

@ -86,11 +86,11 @@ export default {
</script>
<style lang="scss">
@import "~@/asset/style/variables.scss";
@import "~@/asset/style/var";
.context-menu {
margin: 0;
background: $menu-background-dark;
background-color: $menu-background-dark;
z-index: 10;
position: fixed;
list-style-type: none;

@ -1,9 +1,9 @@
<script type="text/jsx">
import cssVariables from '@/asset/style/variables.scss'
import cssVar from '@/asset/style/var.scss'
import Item from './item'
import {isEmpty, deepClone, trim} from "@/util"
const inlineIndent = parseFloat(cssVariables.menuPadding)
const inlineIndent = parseFloat(cssVar.menuPadding)
export default {
name: 'NavMenu',

@ -1,4 +1,4 @@
@import "~@/asset/style/variables.scss";
@import "~@/asset/style/var";
.el-menu {
//图标的大小

@ -28,7 +28,7 @@
//设置了显示弹出菜单的父级
&.el-menu--popup .popover-menu__title {
color: $menu-text-hover-color-dark;
border-bottom-color: $border-color-dark;
border-bottom-color: $--border-color-dark;
}
}
}

@ -16,7 +16,7 @@
//弹出菜单的父级
&.el-menu--popup .popover-menu__title {
color: $menu-text-hover-color-light;
border-bottom-color: $border-color-light;
border-bottom-color: $--border-color-light;
}
}
}

@ -12,17 +12,7 @@ module.exports = {
//路由配置
route: {
//路由模式,['hash','history']
mode: 'history',
//路由过渡动画设置,关联transition.css
animate: {
//当未启用多页签时的路由动画
default: 'el-fade-in-linear',
//要访问的tab顺序高于上一个访问的tab时的路由动画
next: 'left-out',
//要访问的tab顺序不高于上一个访问的tab时的路由动画
prev: 'right-out',
}
mode: 'history'
},
//本地存储配置

@ -1,82 +0,0 @@
export default {
bind(el, bind, vnode) {
const dialogHeaderEl = el.querySelector('.el-dialog__header')
const dragDom = el.querySelector('.el-dialog')
dialogHeaderEl.style.setProperty('cursor', 'move')
dialogHeaderEl.addEventListener('mousedown', e => {
// 鼠标按下,计算当前元素距离可视区的距离
const disX = e.clientX - dialogHeaderEl.offsetLeft
const disY = e.clientY - dialogHeaderEl.offsetTop
const dragDomWidth = dragDom.offsetWidth
const dragDomHeight = dragDom.offsetHeight
const screenWidth = document.body.clientWidth
const screenHeight = document.body.clientHeight
const minDragDomLeft = dragDom.offsetLeft
const maxDragDomLeft = screenWidth - minDragDomLeft - dragDomWidth
const minDragDomTop = dragDom.offsetTop
const maxDragDomTop = screenHeight - minDragDomTop - dragDomHeight
// 获取到的值带px 正则匹配替换
let {left: styL, top: styT} = window.getComputedStyle(dragDom)
if (styL.includes('%')) {
styL = +document.body.clientWidth * (+styL.replace(/%/g, '') / 100)
styT = +document.body.clientHeight * (+styT.replace(/%/g, '') / 100)
}
else {
styL = +styL.replace(/px/g, '')
styT = +styT.replace(/px/g, '')
}
function onMousemove(e) {
// 通过事件委托,计算移动的距离
let left = e.clientX - disX
let top = e.clientY - disY
// 边界处理
if (-(left) > minDragDomLeft) {
left = -minDragDomLeft
}
else if (left > maxDragDomLeft) {
left = maxDragDomLeft
}
if (-(top) > minDragDomTop) {
top = -minDragDomTop
}
else if (top > maxDragDomTop) {
top = maxDragDomTop
}
// 移动当前元素
dragDom.style.setProperty('left', `${left + styL}px`)
dragDom.style.setProperty('top', `${top + styT}px`)
}
function onMouseup() {
window.removeEventListener('mousemove', onMousemove)
window.removeEventListener('mouseup', onMouseup)
}
window.addEventListener('mousemove', onMousemove)
window.addEventListener('mouseup', onMouseup)
})
function resetStyle() {
dragDom.style.removeProperty('left')
dragDom.style.removeProperty('top')
}
//当dialog关闭时恢复原位
vnode.componentInstance.$on('closed', resetStyle)
vnode.componentInstance.$once('hook:beforeDestroy', () => {
vnode.componentInstance.$off('closed', resetStyle)
})
}
}

@ -1,5 +0,0 @@
import Vue from 'vue'
import dragDialog from './dragDialog'
Vue.directive('drag-dialog', dragDialog)

@ -36,7 +36,7 @@ export default {
</script>
<style lang="scss">
@import "~@/asset/style/variables.scss";
@import "~@/asset/style/var";
//
.collapse .aside-search {
@ -50,7 +50,7 @@ export default {
//
.dark .aside-search .el-input__inner {
border: none;
color: #ffffff;
color: $--color-white;
background-color: lighten($menu-background-dark, 5%);
}
</style>

@ -1,4 +1,5 @@
@import "~@/asset/style/variables.scss";
@import "~@/asset/style/var";
@import "~@/asset/style/mixin.scss";
.aside {
display: flex;

@ -10,15 +10,15 @@
}
.root-sidebar {
border-right-color: $border-color-dark;
border-right-color: $--border-color-dark;
}
.sub-sidebar-title {
color: #ffffff;
color: $--color-white;
}
.hamburger {
border-top-color: $border-color-dark;
border-top-color: $--border-color-dark;
i {
color: $menu-text-color-dark;

@ -1,11 +1,11 @@
.aside.light {
.root-sidebar {
background-color: #ffffff;
border-right-color: $border-color-light;
background-color: $--color-white;
border-right-color: $--border-color-light;
}
.hamburger {
border-top-color: $border-color-light;
border-top-color: $--border-color-light;
i {
color: $menu-text-color-light;

@ -26,7 +26,7 @@ export default {
</script>
<style lang="scss">
@import "~@/asset/style/variables.scss";
@import "~@/asset/style/var";
$logoSize: 30px;

@ -1,4 +1,4 @@
@import "~@/asset/style/variables.scss";
@import "~@/asset/style/var";
.navbar {
display: flex;

@ -5,7 +5,7 @@
color: $navbar-item-color-dark;
&:hover {
background: $navbar-item-hover-color-dark;
background-color: $navbar-item-hover-color-dark;
}
}
}

@ -1,11 +1,11 @@
.navbar.light {
background-color: #ffffff;
background-color: $--color-white;
.navbar-item {
color: $navbar-item-color-light;
&:hover {
background: $navbar-item-hover-color-light;
background-color: $navbar-item-hover-color-light;
}
}
}

@ -5,9 +5,7 @@ export default {
render() {
return (
<el-backtop target=".page-main .scroll-container" visibility-height={400} bottom={66}>
<div class="back-to-top">
<v-icon icon="el-icon-top"/>
</div>
<v-icon icon="el-icon-top"/>
</el-backtop>
)
}

@ -13,10 +13,11 @@ export default {
</script>
<style lang="scss">
@import "~@/asset/style/variables.scss";
@import "~@/asset/style/var";
.page-footer {
padding: 48px $page-view-margin $page-view-margin $page-view-margin;
height: $page-footer-height;
padding: $page-view-margin;
text-align: center;
.copyright {

@ -32,7 +32,7 @@ export default {
</script>
<style lang="scss">
@import "~@/asset/style/variables.scss";
@import "~@/asset/style/var";
.page-header {
display: flex;
@ -40,16 +40,16 @@ export default {
align-items: center;
flex-wrap: nowrap;
font-size: 14px;
line-height: $page-header-line-height;
height: $page-header-height;
padding: $page-header-padding $page-view-margin $page-header-padding $page-view-margin;
> .el-breadcrumb .no-redirect {
color: #909399;
color: $--color-text-secondary;
cursor: text;
}
&-title {
color: #303133;
color: $--color-text-primary;
font-weight: 600;
font-size: 18px;
overflow: hidden;

@ -1,4 +1,4 @@
@import "~@/asset/style/variables.scss";
@import "~@/asset/style/var";
.tags-view-container {
height: $tags-view-height;
@ -21,10 +21,10 @@
cursor: pointer;
height: #{$tags-view-height - $margin * 2};
line-height: #{$tags-view-height - $margin * 2 - $border-width * 2};
color: #909399;
color: $--color-text-secondary;
background-color: #ffffff;
border-radius: 3px;
border: $border-width solid $border-color-light;
border: $border-width solid $--border-color-base;
padding: 0 12px;
font-size: 12px;
margin: $margin;
@ -54,7 +54,7 @@
color: $--color-primary;
&::before {
background: $--color-primary;
background-color: $--color-primary;
}
}

@ -17,13 +17,17 @@ export default {
return pageGetters.showPageHeader && this.$route.meta.pageHeader !== false
},
pageClass() {
return {'scroll-container': true, 'has-page-header': this.renderPageHeader}
return {
'scroll-container': true,
'has-page-header': this.renderPageHeader,
'has-page-footer': true
}
}
},
render() {
const {showIframe, iframeList, currentIframe} = pageGetters
const {cachedViews, transitionName, enabled} = tagsViewGetters
const {transition, showIframe, iframeList, currentIframe} = pageGetters
const {cachedViews, enabled} = tagsViewGetters
return (
<main class="page-main">
@ -34,7 +38,7 @@ export default {
<page-view
include={cachedViews}
transition-name={transitionName}
transition-name={transition.curr}
cacheable={enabled}
/>
@ -47,7 +51,7 @@ export default {
id={src}
key={src}
src={src}
frameborder="0"
frameBorder="0"
height="100%"
width="100%"
/>
@ -60,38 +64,4 @@ export default {
}
</script>
<style lang="scss">
@import "~@/asset/style/variables.scss";
.page-main {
display: flex;
flex-direction: column;
flex: 1;
position: relative;
overflow: hidden;
background-color: #f0f2f5;
> .scroll-container {
display: flex;
flex: 1;
flex-direction: column;
overflow-y: overlay;
overflow-x: inherit;
> .page-view {
margin: $page-view-margin;
flex: 1;
}
}
.back-to-top {
height: 100%;
width: 100%;
background-color: #f2f5f6;
box-shadow: 0 0 6px rgba(0, 0, 0, .12);
text-align: center;
line-height: 40px;
color: #1989fa;
}
}
</style>
<style lang="scss" src="./style.scss"></style>

@ -0,0 +1,23 @@
@import "~@/asset/style/var";
.page-main {
display: flex;
flex-direction: column;
flex: 1;
position: relative;
overflow: hidden;
background-color: #f0f2f5;
> .scroll-container {
display: flex;
flex: 1;
flex-direction: column;
overflow-y: overlay;
overflow-x: inherit;
> .page-view {
margin: $page-view-margin;
flex: 1;
}
}
}

@ -7,20 +7,13 @@
@close="$emit('input', false)"
>
<div class="drawer-container">
<el-divider>主题色</el-divider>
<div class="drawer-item">
<checkbox-group :value="appGetters.color" @input="changeThemeColor">
<color-checkbox v-for="i in colors" :key="i" :value="i"/>
</checkbox-group>
</div>
<el-divider>导航模式</el-divider>
<div class="drawer-item">
<checkbox-group :value="appGetters.navMode" @input="changeNavMode">
<img-checkbox
v-for="{title, value, img} in navModes"
v-for="{label, value, img} in navModes"
:key="value"
:title="title"
:label="label"
:value="value"
:img="img"
/>
@ -131,8 +124,6 @@
</template>
<script>
import client from 'webpack-theme-color-replacer/client'
import forElementUI from 'webpack-theme-color-replacer/forElementUI'
import CheckboxGroup from "@/component/checkbox/Group"
import ColorCheckbox from "@/component/checkbox/ColorCheckbox"
import ImgCheckbox from "@/component/checkbox/ImgCheckbox"
@ -155,25 +146,24 @@ export default {
return {
appGetters, asideGetters, navbarGetters, pageGetters, tagsViewGetters,
colors: ['#f5222d', '#fa541c', '#fadb14', '#3eaf7c', '#13c2c2', '#1890ff', '#722ed1', '#eb2f96'],
navModes: [
{
title: '侧边栏导航',
label: '侧边栏导航',
value: 'aside',
img: 'https://gw.alipayobjects.com/zos/antfincdn/XwFOFbLkSM/LCkqqYNmvBEbokSDscrm.svg'
},
{
title: '顶部导航',
label: '顶部导航',
value: 'head',
img: 'https://gw.alipayobjects.com/zos/antfincdn/URETY8%24STp/KDNDBbriJhLwuqMoxcAr.svg'
},
{
title: '混合导航',
label: '混合导航',
value: 'mix',
img: 'https://gw.alipayobjects.com/zos/antfincdn/x8Ob%26B8cy8/LCkqqYNmvBEbokSDscrm.svg'
},
{
title: '双层侧边栏导航',
label: '双层侧边栏导航',
value: 'aside-two-part',
img: 'https://gw.alipayobjects.com/zos/antfincdn/XwFOFbLkSM/LCkqqYNmvBEbokSDscrm.svg'
}
@ -181,7 +171,6 @@ export default {
setting: {
app: {
color: '#1890ff',
navMode: 'mix'
},
page: {
@ -238,10 +227,6 @@ export default {
setLocalPersonalSettings(this.setting)
},
changeThemeColor(v) {
client.changer.changeColor({newColors: forElementUI.getElementUISeries(v)})
appMutations.color(v)
},
changeNavMode(v) {
appMutations.navMode(v)
},
@ -315,14 +300,13 @@ export default {
setLocalPersonalSettings(this.setting)
this.syncLayoutStore()
//
this.changeThemeColor(this.setting.app.color)
}
}
</script>
<style lang="scss" scoped>
@import "~@/asset/style/var";
.drawer-container {
padding: 24px;
font-size: 14px;
@ -332,7 +316,7 @@ export default {
.drawer-item {
display: flex;
justify-content: space-between;
color: #606266;
color: $--color-text-regular;
font-size: 14px;
padding: 12px 0;
}

@ -1,7 +1,4 @@
import {route as routeConfig} from '@/config'
import {mutations as tagsViewMutations} from "@/layout/store/tagsView"
const {animate} = routeConfig
import {getters as pageGetters, mutations as pageViewMutations} from "@/layout/store/page"
export default {
watch: {
@ -13,7 +10,9 @@ export default {
methods: {
//根据访问的tab页的左右顺序来确定路由动画
decideRouteTransition(to, from) {
let transitionName = animate.prev
const {next, prev} = pageGetters.transition
let transitionName = prev
//这里认为页签数量不会太多,所以为了可读性使用两次循环查找
const fromIndex = this.visitedViews.findIndex(i => i.path === from.path)
@ -21,10 +20,10 @@ export default {
//新开tab也认为顺序高于上一个tab
if (toIndex === -1 || fromIndex < toIndex) {
transitionName = animate.next
transitionName = next
}
tagsViewMutations.transitionName(transitionName)
pageViewMutations.transition({curr: transitionName})
},
}
}

@ -17,8 +17,6 @@ const state = {
//所有的树形菜单,每个元素为顶部菜单,顶部菜单的子级(如果有)为侧边栏菜单
menus: [],
//主题色
color: '#1890ff',
//导航模式,'aside'、'aside-two-part'、'head'、'mix'
navMode: 'mix'
}

@ -6,6 +6,18 @@ import {bindThis} from "@/util"
import {createGetters, createMutations} from "@/util/observable"
const state = {
//路由过渡动画
transition: {
//当未启用多页签时的路由动画
default: 'el-fade-in-linear',
//要访问的tab顺序高于上一个访问的tab时的路由动画
next: 'left-out',
//要访问的tab顺序不高于上一个访问的tab时的路由动画
prev: 'right-out',
//当前使用的路由动画
curr: 'el-fade-in-linear'
},
/*iframe的控制*/
showIframe: false,
currentIframe: '',
@ -28,6 +40,11 @@ export const getters = createGetters(store)
export const mutations = bindThis({
...createMutations(store),
//修改transition时使用Object.assign
transition(obj) {
Object.assign(store.transition, obj)
},
addIframe(src) {
!store.iframeList.includes(src) && store.iframeList.push(src)
},

@ -2,8 +2,7 @@
* 多页签的响应式数据
*/
import Vue from 'vue'
import {route as routeConfig} from "@/config"
import {mutations as pageMutations} from "@/layout/store/page"
import {getters as pageGetters, mutations as pageMutations} from "@/layout/store/page"
import {getRouterViewCacheKey} from "@/layout/util"
import {bindThis} from "@/util"
import {createGetters, createMutations} from "@/util/observable"
@ -20,10 +19,7 @@ const state = {
visitedViews: [],
//缓存的页签,用于<keep-router-view-alive/>:include
cachedViews: [],
//路由过渡动画名称
transitionName: routeConfig.animate.default
cachedViews: []
}
const store = Vue.observable(state)
@ -42,7 +38,7 @@ export const mutations = bindThis({
store.enabled = v
if (!v) {
this.transitionName(routeConfig.animate.default)
pageMutations.transition({curr: pageGetters.transition.default})
this.delAllTagAndCache()
}
},

@ -6,7 +6,6 @@ import App from '@/App'
import store from '@/store'
import router from '@/router'
import '@/asset/icon'
import '@/directive'
import filters from './filter'
Vue.use(Element)

@ -1,6 +1,5 @@
import store from "@/store"
import {isEmpty} from "@/util"
import {auth, needAuth} from "@/util/auth"
import {isLogin, auth, needAuth} from "@/util/auth"
const noLoginList = ['/login', '/register', '/403', '/404', '/500']
@ -11,7 +10,7 @@ const beforeEach = async (to, from, next) => {
}
//未登录时返回登录页
if (isEmpty(store.state.user.id, store.state.user.token)) {
if (!isLogin()) {
return next({path: '/login', query: {redirect: to.fullPath}})
}

@ -1,11 +0,0 @@
export default {
path: 'directive',
meta: {title: '全局指令', icon: 'el-icon-s-grid', alwaysShow: true},
children: [
{
path: 'dragDialog',
component: 'example/directive/dragDialog',
meta: {title: '可拖拽dialog'}
}
]
}

@ -4,40 +4,33 @@ import {addDynamicRoutes} from '@/router'
import {getDynamicRoutes} from '@/router/define'
import {metaExtend} from "@/router/util"
import {isEmpty, deepClone} from "@/util"
import {needAuth, auth} from "@/util/auth" // 此处存在循环引用?
import {needAuth, auth} from "@/util/auth" //此处存在循环引用?
import {shakeTree} from "@/util/tree"
import {isExternal} from "@/util/validate"
const state = {
//权限映射表:<权限路径,权限id>,用于util.auth
resourceMap: {},
//判断权限是否已经初始化
init: false
}
const mutations = {
resource(state, {data, admin}) {
state.resourceMap = {}
},
init(state, sign) {
state.init = sign
}
}
const actions = {
init({state, commit}, {admin}) {
init({state, commit}) {
return new Promise(resolve => {
commit('resource', {data: [], admin})
const routes = getDynamicRoutes()
metaExtend(routes)
//动态添加路由,这里不需要进行权限过滤
//可能存在多次调用的情况,所以仅在第一次调用时添加进vue-router
!state.init && addDynamicRoutes(routes)
//生成经过权限过滤后的菜单
//生成经过权限过滤后的菜单,并传递给layout的store
appMutations.menus(getAuthorizedMenus(routes))
//设置初始化完成的标志
@ -51,54 +44,56 @@ const actions = {
//获取经过权限控制后的菜单
function getAuthorizedMenus(menus) {
menus = deepClone(menus)
clean(menus)
addFullPath(menus)
return shakeTree(menus, i => {
//非叶子节点时,当定义了children属性却没有子节点时移除
if (i.children && i.children.length === 0) {
return false
}
return !needAuth(i) || auth(i.fullPath)
})
}
//删除不显示的菜单(没有children且没有meta.title)
function clean(menus) {
for (let i = menus.length - 1; i >= 0; i--) {
const {children = [], meta: {title, alwaysShow, hidden} = {}} = menus[i]
//删除不显示的菜单(没有children且没有meta.title)
function clean(menus) {
for (let i = menus.length - 1; i >= 0; i--) {
const {children = [], meta: {title, alwaysShow, hidden} = {}} = menus[i]
if (hidden) {
menus.splice(i, 1)
continue
}
if (hidden) {
menus.splice(i, 1)
continue
}
if (children.length === 0) {
if (isEmpty(title)) {
menus.splice(i, 1)
}
continue
}
if (children.length === 0) {
if (isEmpty(title)) {
clean(children)
if (children.length === 0 && !alwaysShow) {
menus.splice(i, 1)
}
continue
//移除类似首页那样的无标题父级节点
if (isEmpty(title)) {
menus.splice(i, 1, ...children)
}
}
}
clean(children)
//菜单添加全路径
function addFullPath(routes, basePath = '/') {
routes.forEach(route => {
//外链保持原样
route.fullPath = isExternal(route.path) ? route.path : path.resolve(basePath, route.path)
route.children && addFullPath(route.children, route.fullPath)
})
}
if (children.length === 0 && !alwaysShow) {
menus.splice(i, 1)
}
clean(menus)
addFullPath(menus)
//移除类似首页那样的无标题父级节点
if (isEmpty(title)) {
menus.splice(i, 1, ...children)
return shakeTree(menus, i => {
//非叶子节点时,当定义了children属性却没有子节点时移除
if (i.children && i.children.length === 0) {
return false
}
}
}
//菜单添加全路径
function addFullPath(routes, basePath = '/') {
routes.forEach(route => {
//外链保持原样
route.fullPath = isExternal(route.path) ? route.path : path.resolve(basePath, route.path)
route.children && addFullPath(route.children, route.fullPath)
return !needAuth(i) || auth(i.fullPath)
})
}

@ -25,33 +25,29 @@ const mutations = createMutations(state, true)
const actions = {
login({commit, dispatch}, userInfo) {
const {username, password} = userInfo
if (username !== 'admin') {
elError('登录时请用admin作为用户名!')
return Promise.reject()
}
const user = {id: 1, admin: true, name: username, avatar: null, token: 'token'}
commit('$all', user)
setUser(user)
return Promise.resolve()
},
logout({commit, state, dispatch}) {
return new Promise((resolve, reject) => {
if (state.prepareLogout) return Promise.reject()
commit('prepareLogout', true)
commit('resource/init', false, {root: true})
Promise.all([
dispatch('removeUser'),
tagsViewMutations.delAllTagAndCache()
])
.then(() => {
resolve()
window.location.reload()
})
.finally(() => commit('prepareLogout', false))
})
if (state.prepareLogout) return Promise.reject()
commit('prepareLogout', true)
return Promise.all([
dispatch('removeUser'),
tagsViewMutations.delAllTagAndCache()
])
.then(() => window.location.reload())
.finally(() => commit('prepareLogout', false))
},
//刷新本地存储中保存的用户数据
refresh({state}) {
setUser(state)
},

@ -27,13 +27,7 @@ export function needAuth(route) {
* @return {boolean}
*/
export function auth(path) {
if (store.state.user.admin === true) return true
const resourceMap = store.state.resource.resourceMap
if (!(path in resourceMap)) return true
const resources = store.state.user.resources
return resources && path in resources
return true
}
/**
@ -53,3 +47,12 @@ export function wic(apiMap) {
return attrs
}
/**
* 判断是否已登录已登录则返回true
*
* @return {boolean}
*/
export function isLogin() {
return !isEmpty(store.state.user.token)
}

@ -1,6 +1,6 @@
import cssVariables from '@/asset/style/variables.scss'
import cssVar from '@/asset/style/var.scss'
const maxMobileWidth = parseFloat(cssVariables.maxMobileWidth)
const maxMobileWidth = parseFloat(cssVar.maxMobileWidth)
/**
* 根据body宽度判断是否为移动端是则返回true

@ -1,5 +1,7 @@
<template>
<div class="login-page">
<canvas id="login-background"/>
<div class="login-container" @click.stop>
<div class="title">
{{ title }}

@ -1,16 +1,20 @@
@import "~@/asset/style/variables.scss";
$bg: #283443;
$light_gray: #ffffff;
$dark_gray: #889aa4;
$cursor: #ffffff;
@import "~@/asset/style/var";
.login-page {
$background-color: #2d3a4b;
display: flex;
flex-direction: column;
height: 100%;
overflow: auto;
background: #2d3a4b;
canvas {
position: absolute;
height: 100%;
width: 100%;
z-index: -1;
background-color: $background-color;
}
.login-container {
flex: 1;
@ -25,14 +29,22 @@ $cursor: #ffffff;
margin-bottom: 40px;
cursor: pointer;
font-size: 26px;
color: #eee;
color: #ffffff;
font-weight: bold;
position: relative;
.set-animation {
position: absolute;
top: 115px;
font-size: 18px;
right: 10px;
cursor: pointer;
}
}
.svg-container {
padding: 6px 5px 6px 0;
color: $dark_gray;
color: $--color-text-secondary;
vertical-align: middle;
display: inline-block;
}
@ -42,7 +54,7 @@ $cursor: #ffffff;
right: 10px;
top: 7px;
font-size: 16px;
color: $dark_gray;
color: $--color-text-secondary;
cursor: pointer;
user-select: none;
}
@ -53,26 +65,20 @@ $cursor: #ffffff;
width: 85%;
input {
background: transparent;
background-color: transparent;
border: 0;
-webkit-appearance: none;
border-radius: 0;
padding: 12px 5px 12px 15px;
color: $light_gray;
color: #ffffff;
height: 47px;
caret-color: $cursor;
&:-webkit-autofill {
box-shadow: 0 0 0 1000px $bg inset !important;
-webkit-text-fill-color: $cursor !important;
}
}
}
.el-form-item {
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 5px;
background: rgba(0, 0, 0, 0.1);
background-color: rgba(0, 0, 0, 0.1);
margin-bottom: 22px;
}

@ -1,4 +1,5 @@
@import "~@/asset/style/variables.scss";
@import "~@/asset/style/var";
@import "~@/asset/style/mixin.scss";
.exception {
width: 100%;
@ -16,7 +17,7 @@
.content {
h1 {
color: #434e59;
color: $--color-text-primary;
font-size: 72px;
font-weight: 600;
line-height: 72px;
@ -24,7 +25,7 @@
}
.desc {
color: rgba(0, 0, 0, .45);
color: $--color-text-secondary;
font-size: 20px;
line-height: 28px;
margin-bottom: 16px;

@ -1,4 +1,4 @@
@import "~@/asset/style/variables.scss";
@import "~@/asset/style/var";
.skeleton-page-wrapper {
margin: $page-view-margin;

@ -40,14 +40,14 @@ export default {
</script>
<style lang="scss" scoped>
@import "~@/asset/style/variables.scss";
@import "~@/asset/style/var";
.q-skeleton + .q-skeleton {
margin-top: 20px;
}
.bg-primary {
background: $--color-primary;
background-color: $--color-primary;
}
.bg-info {

@ -1,25 +0,0 @@
<template>
<div>
<div class="tip-row">
可拖拽的dialog
</div>
<el-button @click="value = true">打开dialog</el-button>
<el-dialog v-drag-dialog :visible.sync="value" title="我可以拖动">
<div>蛤蛤</div>
</el-dialog>
</div>
</template>
<script>
export default {
name: "dragDialogPage",
data() {
return {
value: false
}
}
}
</script>

@ -1,8 +1,6 @@
'use strict'
const path = require('path')
const settings = require('./src/config')
const ThemeColorReplacer = require('webpack-theme-color-replacer')
const forElementUI = require('webpack-theme-color-replacer/forElementUI')
function resolve(dir) {
return path.join(__dirname, dir)
@ -33,15 +31,7 @@ module.exports = {
'@': resolve('src'),
'@ele': resolve('element-ui-personal')
}
},
plugins: [
new ThemeColorReplacer({
fileName: 'css/theme-colors.[contenthash:8].css',
matchColors: forElementUI.getElementUISeries('#1890ff'),
changeSelector: forElementUI.changeSelector,
injectCss: true
})
]
}
},
chainWebpack(config) {
config.plugins.delete('preload')

Loading…
Cancel
Save