Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
jinli gu
RuoYi Vue
Commits
46444bd0
Commit
46444bd0
authored
Oct 08, 2019
by
RuoYi
Browse files
RuoYi-Vue 1.0
parent
5bc74554
Changes
400
Hide whitespace changes
Inline
Side-by-side
ruoyi-ui/src/assets/icons/svg/zip.svg
0 → 100644
View file @
46444bd0
<svg
width=
"128"
height=
"128"
xmlns=
"http://www.w3.org/2000/svg"
><path
d=
"M78.527 116.793c.178.008.348.024.527.024h40.233c4.711-.005 8.53-3.677 8.534-8.21V18.895c-.004-4.532-3.823-8.204-8.534-8.209H79.054c-.179 0-.353.016-.527.024V0L0 10.082v107.406l78.527 10.342v-11.037zm0-101.362c.174-.024.348-.052.527-.052h40.233c2.018 0 3.659 1.578 3.659 3.52v89.713c-.003 1.942-1.64 3.517-3.659 3.519H79.054c-.179 0-.353-.028-.527-.052V15.431zM30.262 75.757l-18.721-.46V72.37l11.3-16.673v-.148l-10.266.164v-4.51l17.504-.44v3.264L18.696 70.76v.144l11.566.176v4.678zm9.419.231l-5.823-.144V50.671l5.823-.144v25.461zm22.255-11.632c-2.168 1.922-5.353 2.76-9.02 2.736-.702.004-1.402-.04-2.097-.131v9.303l-5.997-.148V50.743c1.852-.352 4.473-.647 8.218-.743 3.838-.096 6.608.539 8.48 1.913 1.807 1.306 3.032 3.5 3.032 6.112s-.926 4.833-2.612 6.331h-.004zM53.36 54.45c-.856-.01-1.71.083-2.541.275v7.682c.523.116 1.167.152 2.06.152 3.301-.004 5.36-1.614 5.36-4.314 0-2.425-1.772-3.843-4.875-3.791l-.004-.004zm39.847-37.066h9.564v3.795h-9.564v-3.795zm-9.568 5.68h9.564v3.8h-9.564v-3.8zm9.568 6.216h9.564v3.799h-9.564V29.28zm0 12h9.564v3.794h-9.564V41.28zm-9.568-6.096h9.564v3.795h-9.564v-3.795zm9.472 47.064c2.512 0 4.921-.96 6.697-2.67 1.776-1.708 2.773-4.026 2.772-6.442l-1.748-15.263c0-5.033-2.492-9.112-7.725-9.112-5.232 0-7.72 4.079-7.72 9.112l-1.752 15.263c-.001 2.417.996 4.735 2.773 6.444 1.777 1.71 4.187 2.669 6.7 2.668h.003zm-3.135-16.75h6.27v12.743h-6.27V65.5z"
/></svg>
\ No newline at end of file
ruoyi-ui/src/assets/icons/svgo.yml
0 → 100644
View file @
46444bd0
# replace default config
# multipass: true
# full: true
plugins
:
# - name
#
# or:
# - name: false
# - name: true
#
# or:
# - name:
# param1: 1
# param2: 2
-
removeAttrs
:
attrs
:
-
'
fill'
-
'
fill-rule'
ruoyi-ui/src/assets/image/login-background.jpg
0 → 100644
View file @
46444bd0
509 KB
ruoyi-ui/src/assets/image/profile.jpg
0 → 100644
View file @
46444bd0
79.2 KB
ruoyi-ui/src/assets/logo/logo.png
0 → 100644
View file @
46444bd0
5.53 KB
ruoyi-ui/src/assets/styles/btn.scss
0 → 100644
View file @
46444bd0
@import
'./variables.scss'
;
@mixin
colorBtn
(
$color
)
{
background
:
$color
;
&
:hover
{
color
:
$color
;
&
:before
,
&
:after
{
background
:
$color
;
}
}
}
.blue-btn
{
@include
colorBtn
(
$blue
)
}
.light-blue-btn
{
@include
colorBtn
(
$light-blue
)
}
.red-btn
{
@include
colorBtn
(
$red
)
}
.pink-btn
{
@include
colorBtn
(
$pink
)
}
.green-btn
{
@include
colorBtn
(
$green
)
}
.tiffany-btn
{
@include
colorBtn
(
$tiffany
)
}
.yellow-btn
{
@include
colorBtn
(
$yellow
)
}
.pan-btn
{
font-size
:
14px
;
color
:
#fff
;
padding
:
14px
36px
;
border-radius
:
8px
;
border
:
none
;
outline
:
none
;
transition
:
600ms
ease
all
;
position
:
relative
;
display
:
inline-block
;
&
:hover
{
background
:
#fff
;
&
:before
,
&
:after
{
width
:
100%
;
transition
:
600ms
ease
all
;
}
}
&
:before
,
&
:after
{
content
:
''
;
position
:
absolute
;
top
:
0
;
right
:
0
;
height
:
2px
;
width
:
0
;
transition
:
400ms
ease
all
;
}
&
::after
{
right
:
inherit
;
top
:
inherit
;
left
:
0
;
bottom
:
0
;
}
}
.custom-button
{
display
:
inline-block
;
line-height
:
1
;
white-space
:
nowrap
;
cursor
:
pointer
;
background
:
#fff
;
color
:
#fff
;
-webkit-appearance
:
none
;
text-align
:
center
;
box-sizing
:
border-box
;
outline
:
0
;
margin
:
0
;
padding
:
10px
15px
;
font-size
:
14px
;
border-radius
:
4px
;
}
ruoyi-ui/src/assets/styles/element-ui.scss
0 → 100644
View file @
46444bd0
// cover some element-ui styles
.el-breadcrumb__inner
,
.el-breadcrumb__inner
a
{
font-weight
:
400
!
important
;
}
.el-upload
{
input
[
type
=
"file"
]
{
display
:
none
!
important
;
}
}
.el-upload__input
{
display
:
none
;
}
.cell
{
.el-tag
{
margin-right
:
0px
;
}
}
.small-padding
{
.cell
{
padding-left
:
5px
;
padding-right
:
5px
;
}
}
.fixed-width
{
.el-button--mini
{
padding
:
7px
10px
;
width
:
60px
;
}
}
.status-col
{
.cell
{
padding
:
0
10px
;
text-align
:
center
;
.el-tag
{
margin-right
:
0px
;
}
}
}
// to fixed https://github.com/ElemeFE/element/issues/2461
.el-dialog
{
transform
:
none
;
left
:
0
;
position
:
relative
;
margin
:
0
auto
;
}
// refine element ui upload
.upload-container
{
.el-upload
{
width
:
100%
;
.el-upload-dragger
{
width
:
100%
;
height
:
200px
;
}
}
}
// dropdown
.el-dropdown-menu
{
a
{
display
:
block
}
}
// fix date-picker ui bug in filter-item
.el-range-editor.el-input__inner
{
display
:
inline-flex
!
important
;
}
ruoyi-ui/src/assets/styles/element-variables.scss
0 → 100644
View file @
46444bd0
/**
* I think element-ui's default theme color is too light for long-term use.
* So I modified the default color and you can modify it to your liking.
**/
/* theme color */
$--color-primary
:
#1890ff
;
$--color-success
:
#13ce66
;
$--color-warning
:
#FFBA00
;
$--color-danger
:
#ff4949
;
// $--color-info: #1E1E1E;
$--button-font-weight
:
400
;
// $--color-text-regular: #1f2d3d;
$--border-color-light
:
#dfe4ed
;
$--border-color-lighter
:
#e6ebf5
;
$--table-border
:
1px
solid
#dfe6ec
;
/* icon font path, required */
$--font-path
:
'~element-ui/lib/theme-chalk/fonts'
;
@import
"~element-ui/packages/theme-chalk/src/index"
;
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export
{
theme
:
$--color-primary
;
}
ruoyi-ui/src/assets/styles/index.scss
0 → 100644
View file @
46444bd0
@import
'./variables.scss'
;
@import
'./mixin.scss'
;
@import
'./transition.scss'
;
@import
'./element-ui.scss'
;
@import
'./sidebar.scss'
;
@import
'./btn.scss'
;
body
{
height
:
100%
;
-moz-osx-font-smoothing
:
grayscale
;
-webkit-font-smoothing
:
antialiased
;
text-rendering
:
optimizeLegibility
;
font-family
:
Helvetica
Neue
,
Helvetica
,
PingFang
SC
,
Hiragino
Sans
GB
,
Microsoft
YaHei
,
Arial
,
sans-serif
;
}
label
{
font-weight
:
700
;
}
html
{
height
:
100%
;
box-sizing
:
border-box
;
}
#app
{
height
:
100%
;
}
*,
*
:before
,
*
:after
{
box-sizing
:
inherit
;
}
.no-padding
{
padding
:
0px
!
important
;
}
.padding-content
{
padding
:
4px
0
;
}
a
:focus
,
a
:active
{
outline
:
none
;
}
a
,
a
:focus
,
a
:hover
{
cursor
:
pointer
;
color
:
inherit
;
text-decoration
:
none
;
}
div
:focus
{
outline
:
none
;
}
.fr
{
float
:
right
;
}
.fl
{
float
:
left
;
}
.pr-5
{
padding-right
:
5px
;
}
.pl-5
{
padding-left
:
5px
;
}
.block
{
display
:
block
;
}
.pointer
{
cursor
:
pointer
;
}
.inlineBlock
{
display
:
block
;
}
.clearfix
{
&
:after
{
visibility
:
hidden
;
display
:
block
;
font-size
:
0
;
content
:
" "
;
clear
:
both
;
height
:
0
;
}
}
aside
{
background
:
#eef1f6
;
padding
:
8px
24px
;
margin-bottom
:
20px
;
border-radius
:
2px
;
display
:
block
;
line-height
:
32px
;
font-size
:
16px
;
font-family
:
-
apple-system
,
BlinkMacSystemFont
,
"Segoe UI"
,
Roboto
,
Oxygen
,
Ubuntu
,
Cantarell
,
"Fira Sans"
,
"Droid Sans"
,
"Helvetica Neue"
,
sans-serif
;
color
:
#2c3e50
;
-webkit-font-smoothing
:
antialiased
;
-moz-osx-font-smoothing
:
grayscale
;
a
{
color
:
#337ab7
;
cursor
:
pointer
;
&
:hover
{
color
:
rgb
(
32
,
160
,
255
);
}
}
}
//main-container全局样式
.app-container
{
padding
:
20px
;
}
.components-container
{
margin
:
30px
50px
;
position
:
relative
;
}
.pagination-container
{
margin-top
:
30px
;
}
.text-center
{
text-align
:
center
}
.sub-navbar
{
height
:
50px
;
line-height
:
50px
;
position
:
relative
;
width
:
100%
;
text-align
:
right
;
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
;
}
}
.link-type
,
.link-type
:focus
{
color
:
#337ab7
;
cursor
:
pointer
;
&
:hover
{
color
:
rgb
(
32
,
160
,
255
);
}
}
.filter-container
{
padding-bottom
:
10px
;
.filter-item
{
display
:
inline-block
;
vertical-align
:
middle
;
margin-bottom
:
10px
;
}
}
//refine vue-multiselect plugin
.multiselect
{
line-height
:
16px
;
}
.multiselect--active
{
z-index
:
1000
!
important
;
}
ruoyi-ui/src/assets/styles/mixin.scss
0 → 100644
View file @
46444bd0
@mixin
clearfix
{
&
:after
{
content
:
""
;
display
:
table
;
clear
:
both
;
}
}
@mixin
scrollBar
{
&
::-webkit-scrollbar-track-piece
{
background
:
#d3dce6
;
}
&
::-webkit-scrollbar
{
width
:
6px
;
}
&
::-webkit-scrollbar-thumb
{
background
:
#99a9bf
;
border-radius
:
20px
;
}
}
@mixin
relative
{
position
:
relative
;
width
:
100%
;
height
:
100%
;
}
@mixin
pct
(
$pct
)
{
width
:
#{
$pct
}
;
position
:
relative
;
margin
:
0
auto
;
}
@mixin
triangle
(
$width
,
$height
,
$color
,
$direction
)
{
$width
:
$width
/
2
;
$color-border-style
:
$height
solid
$color
;
$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
;
border-bottom
:
$transparent-border-style
;
}
}
ruoyi-ui/src/assets/styles/ruoyi.scss
0 → 100644
View file @
46444bd0
/**
* 通用css样式布局处理
* Copyright (c) 2019 ruoyi
*/
.el-table
.el-table__header-wrapper
th
{
word-break
:
break-word
;
background-color
:
#f8f8f9
;
color
:
#515a6e
;
height
:
40px
;
font-size
:
13px
;
}
.pagination-container
{
position
:
relative
;
height
:
25px
;
margin-bottom
:
10px
;
margin-top
:
15px
;
padding
:
10px
20px
!
important
;
}
.pagination-container
.el-pagination
{
right
:
0
;
position
:
absolute
;
}
.el-table
.fixed-width
.el-button--mini
{
color
:
#409EFF
;
padding-left
:
0
;
padding-right
:
0
;
width
:
inherit
;
}
.el-tree-node__content
>
.el-checkbox
{
margin-right
:
8px
;
}
.list-group-striped
>
.list-group-item
{
border-left
:
0
;
border-right
:
0
;
border-radius
:
0
;
padding-left
:
0
;
padding-right
:
0
;
}
.list-group
{
padding-left
:
0px
;
list-style
:
none
;
}
.list-group-item
{
border-bottom
:
1px
solid
#e7eaec
;
border-top
:
1px
solid
#e7eaec
;
margin-bottom
:
-1px
;
padding
:
11px
0px
;
font-size
:
13px
;
}
.pull-right
{
float
:
right
!
important
;
}
.el-card__header
{
padding
:
14px
15px
7px
;
min-height
:
40px
;
}
.el-card__body
{
padding
:
15px
20px
20px
20px
;
}
.card-box
{
padding-right
:
15px
;
padding-left
:
15px
;
margin-bottom
:
10px
;
}
/* text color */
.text-navy
{
color
:
#1ab394
;
}
.text-primary
{
color
:
inherit
;
}
.text-success
{
color
:
#1c84c6
;
}
.text-info
{
color
:
#23c6c8
;
}
.text-warning
{
color
:
#f8ac59
;
}
.text-danger
{
color
:
#ed5565
;
}
.text-muted
{
color
:
#888888
;
}
/* image */
.img-circle
{
border-radius
:
50%
;
}
.img-lg
{
width
:
120px
;
height
:
120px
;
}
.avatar-upload-preview
{
position
:
absolute
;
top
:
50%
;
transform
:
translate
(
50%
,
-50%
);
width
:
180px
;
height
:
180px
;
border-radius
:
50%
;
box-shadow
:
0
0
4px
#ccc
;
overflow
:
hidden
;
}
\ No newline at end of file
ruoyi-ui/src/assets/styles/sidebar.scss
0 → 100644
View file @
46444bd0
#app
{
.main-container
{
min-height
:
100%
;
transition
:
margin-left
.28s
;
margin-left
:
$sideBarWidth
;
position
:
relative
;
}
.sidebar-container
{
transition
:
width
0
.28s
;
width
:
$sideBarWidth
!
important
;
background-color
:
$menuBg
;
height
:
100%
;
position
:
fixed
;
font-size
:
0px
;
top
:
0
;
bottom
:
0
;
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
;
}
.el-scrollbar__bar.is-vertical
{
right
:
0px
;
}
.el-scrollbar
{
height
:
100%
;
}
&
.has-logo
{
.el-scrollbar
{
height
:
calc
(
100%
-
50px
);
}
}
.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
;
}
// menu hover
.submenu-title-noDropdown
,
.el-submenu__title
{
&
:hover
{
background-color
:
$menuHover
!
important
;
}
}
.is-active
>
.el-submenu__title
{
color
:
$subMenuActiveText
!
important
;
}
&
.nest-menu
.el-submenu
>
.el-submenu__title
,
&
.el-submenu
.el-menu-item
{
min-width
:
$sideBarWidth
!
important
;
background-color
:
$subMenuBg
!
important
;
&
:hover
{
background-color
:
$subMenuHover
!
important
;
}
}
}
.hideSidebar
{
.sidebar-container
{
width
:
54px
!
important
;
}
.main-container
{
margin-left
:
54px
;
}
.submenu-title-noDropdown
{
padding
:
0
!
important
;
position
:
relative
;
.el-tooltip
{
padding
:
0
!
important
;
.svg-icon
{
margin-left
:
20px
;
}
}
}
.el-submenu
{
overflow
:
hidden
;
&
>
.el-submenu__title
{
padding
:
0
!
important
;
.svg-icon
{
margin-left
:
20px
;
}
.el-submenu__icon-arrow
{
display
:
none
;
}
}
}
.el-menu--collapse
{
.el-submenu
{
&
>
.el-submenu__title
{
&
>
span
{
height
:
0
;
width
:
0
;
overflow
:
hidden
;
visibility
:
hidden
;
display
:
inline-block
;
}
}
}
}
}
.el-menu--collapse
.el-menu
.el-submenu
{
min-width
:
$sideBarWidth
!
important
;
}
// mobile responsive
.mobile
{
.main-container
{
margin-left
:
0px
;
}
.sidebar-container
{
transition
:
transform
.28s
;
width
:
$sideBarWidth
!
important
;
}
&
.hideSidebar
{
.sidebar-container
{
pointer-events
:
none
;
transition-duration
:
0
.3s
;
transform
:
translate3d
(
-
$sideBarWidth
,
0
,
0
);
}
}
}
.withoutAnimation
{
.main-container
,
.sidebar-container
{
transition
:
none
;
}
}
}
// when menu collapsed
.el-menu--vertical
{
&
>
.el-menu
{
.svg-icon
{
margin-right
:
16px
;
}
}
.nest-menu
.el-submenu
>
.el-submenu__title
,
.el-menu-item
{
&
:hover
{
// you can use $subMenuHover
background-color
:
$menuHover
!
important
;
}
}
// the scroll bar appears when the subMenu is too long
>
.el-menu--popup
{
max-height
:
100vh
;
overflow-y
:
auto
;
&
::-webkit-scrollbar-track-piece
{
background
:
#d3dce6
;
}
&
::-webkit-scrollbar
{
width
:
6px
;
}
&
::-webkit-scrollbar-thumb
{
background
:
#99a9bf
;
border-radius
:
20px
;
}
}
}
ruoyi-ui/src/assets/styles/transition.scss
0 → 100644
View file @
46444bd0
// global transition css
/* fade */
.fade-enter-active
,
.fade-leave-active
{
transition
:
opacity
0
.28s
;
}
.fade-enter
,
.fade-leave-active
{
opacity
:
0
;
}
/* fade-transform */
.fade-transform-leave-active
,
.fade-transform-enter-active
{
transition
:
all
.5s
;
}
.fade-transform-enter
{
opacity
:
0
;
transform
:
translateX
(
-30px
);
}
.fade-transform-leave-to
{
opacity
:
0
;
transform
:
translateX
(
30px
);
}
/* breadcrumb transition */
.breadcrumb-enter-active
,
.breadcrumb-leave-active
{
transition
:
all
.5s
;
}
.breadcrumb-enter
,
.breadcrumb-leave-active
{
opacity
:
0
;
transform
:
translateX
(
20px
);
}
.breadcrumb-move
{
transition
:
all
.5s
;
}
.breadcrumb-leave-active
{
position
:
absolute
;
}
ruoyi-ui/src/assets/styles/variables.scss
0 → 100644
View file @
46444bd0
// base color
$blue
:
#324157
;
$light-blue
:
#3A71A8
;
$red
:
#C03639
;
$pink
:
#E65D6E
;
$green
:
#30B08F
;
$tiffany
:
#4AB7BD
;
$yellow
:
#FEC171
;
$panGreen
:
#30B08F
;
// sidebar
$menuText
:
#bfcbd9
;
$menuActiveText
:
#409EFF
;
$subMenuActiveText
:
#f4f4f5
;
// https://github.com/ElemeFE/element/issues/12951
$menuBg
:
#304156
;
$menuHover
:
#263445
;
$subMenuBg
:
#1f2d3d
;
$subMenuHover
:
#001528
;
$sideBarWidth
:
200px
;
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export
{
menuText
:
$menuText
;
menuActiveText
:
$menuActiveText
;
subMenuActiveText
:
$subMenuActiveText
;
menuBg
:
$menuBg
;
menuHover
:
$menuHover
;
subMenuBg
:
$subMenuBg
;
subMenuHover
:
$subMenuHover
;
sideBarWidth
:
$sideBarWidth
;
}
ruoyi-ui/src/components/Breadcrumb/index.vue
0 → 100644
View file @
46444bd0
<
template
>
<el-breadcrumb
class=
"app-breadcrumb"
separator=
"/"
>
<transition-group
name=
"breadcrumb"
>
<el-breadcrumb-item
v-for=
"(item,index) in levelList"
:key=
"item.path"
>
<span
v-if=
"item.redirect==='noRedirect'||index==levelList.length-1"
class=
"no-redirect"
>
{{
item
.
meta
.
title
}}
</span>
<a
v-else
@
click.prevent=
"handleLink(item)"
>
{{
item
.
meta
.
title
}}
</a>
</el-breadcrumb-item>
</transition-group>
</el-breadcrumb>
</
template
>
<
script
>
import
pathToRegexp
from
'
path-to-regexp
'
export
default
{
data
()
{
return
{
levelList
:
null
}
},
watch
:
{
$route
(
route
)
{
// if you go to the redirect page, do not update the breadcrumbs
if
(
route
.
path
.
startsWith
(
'
/redirect/
'
))
{
return
}
this
.
getBreadcrumb
()
}
},
created
()
{
this
.
getBreadcrumb
()
},
methods
:
{
getBreadcrumb
()
{
// only show routes with meta.title
let
matched
=
this
.
$route
.
matched
.
filter
(
item
=>
item
.
meta
&&
item
.
meta
.
title
)
const
first
=
matched
[
0
]
if
(
!
this
.
isDashboard
(
first
))
{
matched
=
[{
path
:
'
/index
'
,
meta
:
{
title
:
'
首页
'
}}].
concat
(
matched
)
}
this
.
levelList
=
matched
.
filter
(
item
=>
item
.
meta
&&
item
.
meta
.
title
&&
item
.
meta
.
breadcrumb
!==
false
)
},
isDashboard
(
route
)
{
const
name
=
route
&&
route
.
name
if
(
!
name
)
{
return
false
}
return
name
.
trim
()
===
'
首页
'
},
pathCompile
(
path
)
{
const
{
params
}
=
this
.
$route
var
toPath
=
pathToRegexp
.
compile
(
path
)
return
toPath
(
params
)
},
handleLink
(
item
)
{
const
{
redirect
,
path
}
=
item
if
(
redirect
)
{
this
.
$router
.
push
(
redirect
)
return
}
this
.
$router
.
push
(
this
.
pathCompile
(
path
))
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.app-breadcrumb.el-breadcrumb
{
display
:
inline-block
;
font-size
:
14px
;
line-height
:
50px
;
margin-left
:
8px
;
.no-redirect
{
color
:
#97a8be
;
cursor
:
text
;
}
}
</
style
>
ruoyi-ui/src/components/Editor/index.vue
0 → 100644
View file @
46444bd0
<
template
>
<div>
<!-- 图片上传组件辅助 -->
<el-upload
class=
"avatar-uploader quill-img"
:action=
"uploadImgUrl"
name=
"file"
:headers=
"headers"
:show-file-list=
"false"
:on-success=
"quillImgSuccess"
:on-error=
"uploadError"
:before-upload=
"quillImgBefore"
accept=
'.jpg,.jpeg,.png,.gif'
></el-upload>
<!-- 富文本组件 -->
<quill-editor
class=
"editor"
v-model=
"content"
ref=
"quillEditor"
:options=
"editorOption"
@
blur=
"onEditorBlur($event)"
@
focus=
"onEditorFocus($event)"
@
change=
"onEditorChange($event)"
></quill-editor>
</div>
</
template
>
<
script
>
import
{
getToken
}
from
'
@/utils/auth
'
// 工具栏配置
const
toolbarOptions
=
[
[
"
bold
"
,
"
italic
"
,
"
underline
"
,
"
strike
"
],
// 加粗 斜体 下划线 删除线
[
"
blockquote
"
,
"
code-block
"
],
// 引用 代码块
[{
list
:
"
ordered
"
},
{
list
:
"
bullet
"
}],
// 有序、无序列表
[{
indent
:
"
-1
"
},
{
indent
:
"
+1
"
}],
// 缩进
[{
size
:
[
"
small
"
,
false
,
"
large
"
,
"
huge
"
]
}],
// 字体大小
[{
header
:
[
1
,
2
,
3
,
4
,
5
,
6
,
false
]
}],
// 标题
[{
color
:
[]
},
{
background
:
[]
}],
// 字体颜色、字体背景颜色
[{
align
:
[]
}],
// 对齐方式
[
"
clean
"
],
// 清除文本格式
[
"
link
"
,
"
image
"
,
"
video
"
]
// 链接、图片、视频
];
import
{
quillEditor
}
from
"
vue-quill-editor
"
;
import
"
quill/dist/quill.core.css
"
;
import
"
quill/dist/quill.snow.css
"
;
import
"
quill/dist/quill.bubble.css
"
;
export
default
{
props
:
{
/* 编辑器的内容 */
value
:
{
type
:
String
},
/* 图片大小 */
maxSize
:
{
type
:
Number
,
default
:
4000
//kb
}
},
components
:
{
quillEditor
},
data
()
{
return
{
content
:
this
.
value
,
uploadImgUrl
:
""
,
editorOption
:
{
placeholder
:
""
,
theme
:
"
snow
"
,
// or 'bubble'
placeholder
:
"
请输入内容
"
,
modules
:
{
toolbar
:
{
container
:
toolbarOptions
,
handlers
:
{
image
:
function
(
value
)
{
if
(
value
)
{
// 触发input框选择图片文件
document
.
querySelector
(
"
.quill-img input
"
).
click
();
}
else
{
this
.
quill
.
format
(
"
image
"
,
false
);
}
}
}
}
}
},
uploadImgUrl
:
process
.
env
.
VUE_APP_BASE_API
+
"
/common/upload
"
,
// 上传的图片服务器地址
headers
:
{
Authorization
:
'
Bearer
'
+
getToken
()
}
};
},
watch
:
{
value
:
function
()
{
this
.
content
=
this
.
value
;
}
},
methods
:
{
onEditorBlur
()
{
//失去焦点事件
},
onEditorFocus
()
{
//获得焦点事件
},
onEditorChange
()
{
//内容改变事件
this
.
$emit
(
"
input
"
,
this
.
content
);
},
// 富文本图片上传前
quillImgBefore
(
file
)
{
let
fileType
=
file
.
type
;
if
(
fileType
===
'
image/jpeg
'
||
fileType
===
'
image/png
'
){
return
true
;
}
else
{
this
.
$message
.
error
(
'
请插入图片类型文件(jpg/jpeg/png)
'
);
return
false
;
}
},
quillImgSuccess
(
res
,
file
)
{
// res为图片服务器返回的数据
// 获取富文本组件实例
let
quill
=
this
.
$refs
.
quillEditor
.
quill
;
// 如果上传成功
if
(
res
.
code
==
200
)
{
// 获取光标所在位置
let
length
=
quill
.
getSelection
().
index
;
// 插入图片 res.url为服务器返回的图片地址
quill
.
insertEmbed
(
length
,
"
image
"
,
res
.
url
);
// 调整光标到最后
quill
.
setSelection
(
length
+
1
);
}
else
{
this
.
$message
.
error
(
"
图片插入失败
"
);
}
},
// 富文本图片上传失败
uploadError
()
{
// loading动画消失
this
.
$message
.
error
(
"
图片插入失败
"
);
}
}
};
</
script
>
<
style
>
.editor
{
line-height
:
normal
!important
;
height
:
192px
;
}
.el-upload
{
display
:
none
;
}
.ql-snow
.ql-tooltip
[
data-mode
=
"link"
]
::before
{
content
:
"请输入链接地址:"
;
}
.ql-snow
.ql-tooltip.ql-editing
a
.ql-action
::after
{
border-right
:
0px
;
content
:
"保存"
;
padding-right
:
0px
;
}
.ql-snow
.ql-tooltip
[
data-mode
=
"video"
]
::before
{
content
:
"请输入视频地址:"
;
}
.ql-snow
.ql-picker.ql-size
.ql-picker-label
::before
,
.ql-snow
.ql-picker.ql-size
.ql-picker-item
::before
{
content
:
"14px"
;
}
.ql-snow
.ql-picker.ql-size
.ql-picker-label
[
data-value
=
"small"
]
::before
,
.ql-snow
.ql-picker.ql-size
.ql-picker-item
[
data-value
=
"small"
]
::before
{
content
:
"10px"
;
}
.ql-snow
.ql-picker.ql-size
.ql-picker-label
[
data-value
=
"large"
]
::before
,
.ql-snow
.ql-picker.ql-size
.ql-picker-item
[
data-value
=
"large"
]
::before
{
content
:
"18px"
;
}
.ql-snow
.ql-picker.ql-size
.ql-picker-label
[
data-value
=
"huge"
]
::before
,
.ql-snow
.ql-picker.ql-size
.ql-picker-item
[
data-value
=
"huge"
]
::before
{
content
:
"32px"
;
}
.ql-snow
.ql-picker.ql-header
.ql-picker-label
::before
,
.ql-snow
.ql-picker.ql-header
.ql-picker-item
::before
{
content
:
"文本"
;
}
.ql-snow
.ql-picker.ql-header
.ql-picker-label
[
data-value
=
"1"
]
::before
,
.ql-snow
.ql-picker.ql-header
.ql-picker-item
[
data-value
=
"1"
]
::before
{
content
:
"标题1"
;
}
.ql-snow
.ql-picker.ql-header
.ql-picker-label
[
data-value
=
"2"
]
::before
,
.ql-snow
.ql-picker.ql-header
.ql-picker-item
[
data-value
=
"2"
]
::before
{
content
:
"标题2"
;
}
.ql-snow
.ql-picker.ql-header
.ql-picker-label
[
data-value
=
"3"
]
::before
,
.ql-snow
.ql-picker.ql-header
.ql-picker-item
[
data-value
=
"3"
]
::before
{
content
:
"标题3"
;
}
.ql-snow
.ql-picker.ql-header
.ql-picker-label
[
data-value
=
"4"
]
::before
,
.ql-snow
.ql-picker.ql-header
.ql-picker-item
[
data-value
=
"4"
]
::before
{
content
:
"标题4"
;
}
.ql-snow
.ql-picker.ql-header
.ql-picker-label
[
data-value
=
"5"
]
::before
,
.ql-snow
.ql-picker.ql-header
.ql-picker-item
[
data-value
=
"5"
]
::before
{
content
:
"标题5"
;
}
.ql-snow
.ql-picker.ql-header
.ql-picker-label
[
data-value
=
"6"
]
::before
,
.ql-snow
.ql-picker.ql-header
.ql-picker-item
[
data-value
=
"6"
]
::before
{
content
:
"标题6"
;
}
.ql-snow
.ql-picker.ql-font
.ql-picker-label
::before
,
.ql-snow
.ql-picker.ql-font
.ql-picker-item
::before
{
content
:
"标准字体"
;
}
.ql-snow
.ql-picker.ql-font
.ql-picker-label
[
data-value
=
"serif"
]
::before
,
.ql-snow
.ql-picker.ql-font
.ql-picker-item
[
data-value
=
"serif"
]
::before
{
content
:
"衬线字体"
;
}
.ql-snow
.ql-picker.ql-font
.ql-picker-label
[
data-value
=
"monospace"
]
::before
,
.ql-snow
.ql-picker.ql-font
.ql-picker-item
[
data-value
=
"monospace"
]
::before
{
content
:
"等宽字体"
;
}
</
style
>
\ No newline at end of file
ruoyi-ui/src/components/Hamburger/index.vue
0 → 100644
View file @
46444bd0
<
template
>
<div
style=
"padding: 0 15px;"
@
click=
"toggleClick"
>
<svg
:class=
"
{'is-active':isActive}"
class="hamburger"
viewBox="0 0 1024 1024"
xmlns="http://www.w3.org/2000/svg"
width="64"
height="64"
>
<path
d=
"M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z"
/>
</svg>
</div>
</
template
>
<
script
>
export
default
{
name
:
'
Hamburger
'
,
props
:
{
isActive
:
{
type
:
Boolean
,
default
:
false
}
},
methods
:
{
toggleClick
()
{
this
.
$emit
(
'
toggleClick
'
)
}
}
}
</
script
>
<
style
scoped
>
.hamburger
{
display
:
inline-block
;
vertical-align
:
middle
;
width
:
20px
;
height
:
20px
;
}
.hamburger.is-active
{
transform
:
rotate
(
180deg
);
}
</
style
>
ruoyi-ui/src/components/HeaderSearch/index.vue
0 → 100644
View file @
46444bd0
<
template
>
<div
:class=
"
{'show':show}" class="header-search">
<svg-icon
class-name=
"search-icon"
icon-class=
"search"
@
click.stop=
"click"
/>
<el-select
ref=
"headerSearchSelect"
v-model=
"search"
:remote-method=
"querySearch"
filterable
default-first-option
remote
placeholder=
"Search"
class=
"header-search-select"
@
change=
"change"
>
<el-option
v-for=
"item in options"
:key=
"item.path"
:value=
"item"
:label=
"item.title.join(' > ')"
/>
</el-select>
</div>
</
template
>
<
script
>
// fuse is a lightweight fuzzy-search module
// make search results more in line with expectations
import
Fuse
from
'
fuse.js
'
import
path
from
'
path
'
export
default
{
name
:
'
HeaderSearch
'
,
data
()
{
return
{
search
:
''
,
options
:
[],
searchPool
:
[],
show
:
false
,
fuse
:
undefined
}
},
computed
:
{
routes
()
{
return
this
.
$store
.
getters
.
permission_routes
}
},
watch
:
{
routes
()
{
this
.
searchPool
=
this
.
generateRoutes
(
this
.
routes
)
},
searchPool
(
list
)
{
this
.
initFuse
(
list
)
},
show
(
value
)
{
if
(
value
)
{
document
.
body
.
addEventListener
(
'
click
'
,
this
.
close
)
}
else
{
document
.
body
.
removeEventListener
(
'
click
'
,
this
.
close
)
}
}
},
mounted
()
{
this
.
searchPool
=
this
.
generateRoutes
(
this
.
routes
)
},
methods
:
{
click
()
{
this
.
show
=
!
this
.
show
if
(
this
.
show
)
{
this
.
$refs
.
headerSearchSelect
&&
this
.
$refs
.
headerSearchSelect
.
focus
()
}
},
close
()
{
this
.
$refs
.
headerSearchSelect
&&
this
.
$refs
.
headerSearchSelect
.
blur
()
this
.
options
=
[]
this
.
show
=
false
},
change
(
val
)
{
this
.
$router
.
push
(
val
.
path
)
this
.
search
=
''
this
.
options
=
[]
this
.
$nextTick
(()
=>
{
this
.
show
=
false
})
},
initFuse
(
list
)
{
this
.
fuse
=
new
Fuse
(
list
,
{
shouldSort
:
true
,
threshold
:
0.4
,
location
:
0
,
distance
:
100
,
maxPatternLength
:
32
,
minMatchCharLength
:
1
,
keys
:
[{
name
:
'
title
'
,
weight
:
0.7
},
{
name
:
'
path
'
,
weight
:
0.3
}]
})
},
// Filter out the routes that can be displayed in the sidebar
// And generate the internationalized title
generateRoutes
(
routes
,
basePath
=
'
/
'
,
prefixTitle
=
[])
{
let
res
=
[]
for
(
const
router
of
routes
)
{
// skip hidden router
if
(
router
.
hidden
)
{
continue
}
const
data
=
{
path
:
path
.
resolve
(
basePath
,
router
.
path
),
title
:
[...
prefixTitle
]
}
if
(
router
.
meta
&&
router
.
meta
.
title
)
{
data
.
title
=
[...
data
.
title
,
router
.
meta
.
title
]
if
(
router
.
redirect
!==
'
noRedirect
'
)
{
// only push the routes with title
// special case: need to exclude parent router without redirect
res
.
push
(
data
)
}
}
// recursive child routes
if
(
router
.
children
)
{
const
tempRoutes
=
this
.
generateRoutes
(
router
.
children
,
data
.
path
,
data
.
title
)
if
(
tempRoutes
.
length
>=
1
)
{
res
=
[...
res
,
...
tempRoutes
]
}
}
}
return
res
},
querySearch
(
query
)
{
if
(
query
!==
''
)
{
this
.
options
=
this
.
fuse
.
search
(
query
)
}
else
{
this
.
options
=
[]
}
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.header-search
{
font-size
:
0
!
important
;
.search-icon
{
cursor
:
pointer
;
font-size
:
18px
;
vertical-align
:
middle
;
}
.header-search-select
{
font-size
:
18px
;
transition
:
width
0
.2s
;
width
:
0
;
overflow
:
hidden
;
background
:
transparent
;
border-radius
:
0
;
display
:
inline-block
;
vertical-align
:
middle
;
/
deep
/
.el-input__inner
{
border-radius
:
0
;
border
:
0
;
padding-left
:
0
;
padding-right
:
0
;
box-shadow
:
none
!
important
;
border-bottom
:
1px
solid
#d9d9d9
;
vertical-align
:
middle
;
}
}
&
.show
{
.header-search-select
{
width
:
210px
;
margin-left
:
10px
;
}
}
}
</
style
>
ruoyi-ui/src/components/IconSelect/index.vue
0 → 100644
View file @
46444bd0
<!-- @author zhengjie -->
<
template
>
<div
class=
"icon-body"
>
<el-input
v-model=
"name"
style=
"position: relative;"
clearable
placeholder=
"请输入图标名称"
@
clear=
"filterIcons"
@
input.native=
"filterIcons"
>
<i
slot=
"suffix"
class=
"el-icon-search el-input__icon"
/>
</el-input>
<div
class=
"icon-list"
>
<div
v-for=
"(item, index) in iconList"
:key=
"index"
@
click=
"selectedIcon(item)"
>
<svg-icon
:icon-class=
"item"
style=
"height: 30px;width: 16px;"
/>
<span>
{{
item
}}
</span>
</div>
</div>
</div>
</
template
>
<
script
>
import
icons
from
'
./requireIcons
'
export
default
{
name
:
'
IconSelect
'
,
data
()
{
return
{
name
:
''
,
iconList
:
icons
}
},
methods
:
{
filterIcons
()
{
if
(
this
.
name
)
{
this
.
iconList
=
this
.
iconList
.
filter
(
item
=>
item
.
includes
(
this
.
name
))
}
else
{
this
.
iconList
=
icons
}
},
selectedIcon
(
name
)
{
this
.
$emit
(
'
selected
'
,
name
)
document
.
body
.
click
()
},
reset
()
{
this
.
name
=
''
this
.
iconList
=
icons
}
}
}
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
.icon-body
{
width
:
100%
;
padding
:
10px
;
.icon-list
{
height
:
200px
;
overflow-y
:
scroll
;
div
{
height
:
30px
;
line-height
:
30px
;
margin-bottom
:
-5px
;
cursor
:
pointer
;
width
:
33%
;
float
:
left
;
}
span
{
display
:
inline-block
;
vertical-align
:
-0
.15em
;
fill
:
currentColor
;
overflow
:
hidden
;
}
}
}
</
style
>
ruoyi-ui/src/components/IconSelect/requireIcons.js
0 → 100644
View file @
46444bd0
const
req
=
require
.
context
(
'
../../assets/icons/svg
'
,
false
,
/
\.
svg$/
)
const
requireAll
=
requireContext
=>
requireContext
.
keys
()
const
re
=
/
\.\/(
.*
)\.
svg/
const
icons
=
requireAll
(
req
).
map
(
i
=>
{
return
i
.
match
(
re
)[
1
]
})
export
default
icons
Prev
1
2
3
4
5
6
7
8
9
10
…
20
Next
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment