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
Litemall
Commits
6c14c43c
Commit
6c14c43c
authored
Mar 23, 2018
by
Junling Bu
Browse files
V 0.1.0, 项目架构基本完成。
parents
Changes
346
Show whitespace changes
Inline
Side-by-side
Too many changes to show.
To preserve performance only
20 of 346+
files are displayed.
Plain diff
Email patch
litemall-admin/src/components/Charts/keyboard.vue
0 → 100644
View file @
6c14c43c
<
template
>
<div
:class=
"className"
:id=
"id"
:style=
"
{height:height,width:width}">
</div>
</
template
>
<
script
>
import
echarts
from
'
echarts
'
export
default
{
props
:
{
className
:
{
type
:
String
,
default
:
'
chart
'
},
id
:
{
type
:
String
,
default
:
'
chart
'
},
width
:
{
type
:
String
,
default
:
'
200px
'
},
height
:
{
type
:
String
,
default
:
'
200px
'
}
},
data
()
{
return
{
chart
:
null
}
},
mounted
()
{
this
.
initChart
()
},
beforeDestroy
()
{
if
(
!
this
.
chart
)
{
return
}
this
.
chart
.
dispose
()
this
.
chart
=
null
},
methods
:
{
initChart
()
{
this
.
chart
=
echarts
.
init
(
document
.
getElementById
(
this
.
id
))
const
xAxisData
=
[]
const
data
=
[]
const
data2
=
[]
for
(
let
i
=
0
;
i
<
50
;
i
++
)
{
xAxisData
.
push
(
i
)
data
.
push
((
Math
.
sin
(
i
/
5
)
*
(
i
/
5
-
10
)
+
i
/
6
)
*
5
)
data2
.
push
((
Math
.
sin
(
i
/
5
)
*
(
i
/
5
+
10
)
+
i
/
6
)
*
3
)
}
this
.
chart
.
setOption
(
{
backgroundColor
:
'
#08263a
'
,
xAxis
:
[{
show
:
false
,
data
:
xAxisData
},
{
show
:
false
,
data
:
xAxisData
}],
visualMap
:
{
show
:
false
,
min
:
0
,
max
:
50
,
dimension
:
0
,
inRange
:
{
color
:
[
'
#4a657a
'
,
'
#308e92
'
,
'
#b1cfa5
'
,
'
#f5d69f
'
,
'
#f5898b
'
,
'
#ef5055
'
]
}
},
yAxis
:
{
axisLine
:
{
show
:
false
},
axisLabel
:
{
textStyle
:
{
color
:
'
#4a657a
'
}
},
splitLine
:
{
show
:
true
,
lineStyle
:
{
color
:
'
#08263f
'
}
},
axisTick
:
{
show
:
false
}
},
series
:
[{
name
:
'
back
'
,
type
:
'
bar
'
,
data
:
data2
,
z
:
1
,
itemStyle
:
{
normal
:
{
opacity
:
0.4
,
barBorderRadius
:
5
,
shadowBlur
:
3
,
shadowColor
:
'
#111
'
}
}
},
{
name
:
'
Simulate Shadow
'
,
type
:
'
line
'
,
data
,
z
:
2
,
showSymbol
:
false
,
animationDelay
:
0
,
animationEasing
:
'
linear
'
,
animationDuration
:
1200
,
lineStyle
:
{
normal
:
{
color
:
'
transparent
'
}
},
areaStyle
:
{
normal
:
{
color
:
'
#08263a
'
,
shadowBlur
:
50
,
shadowColor
:
'
#000
'
}
}
},
{
name
:
'
front
'
,
type
:
'
bar
'
,
data
,
xAxisIndex
:
1
,
z
:
3
,
itemStyle
:
{
normal
:
{
barBorderRadius
:
5
}
}
}],
animationEasing
:
'
elasticOut
'
,
animationEasingUpdate
:
'
elasticOut
'
,
animationDelay
(
idx
)
{
return
idx
*
20
},
animationDelayUpdate
(
idx
)
{
return
idx
*
20
}
})
}
}
}
</
script
>
litemall-admin/src/components/Charts/lineMarker.vue
0 → 100644
View file @
6c14c43c
<
template
>
<div
:class=
"className"
:id=
"id"
:style=
"
{height:height,width:width}">
</div>
</
template
>
<
script
>
import
echarts
from
'
echarts
'
export
default
{
props
:
{
className
:
{
type
:
String
,
default
:
'
chart
'
},
id
:
{
type
:
String
,
default
:
'
chart
'
},
width
:
{
type
:
String
,
default
:
'
200px
'
},
height
:
{
type
:
String
,
default
:
'
200px
'
}
},
data
()
{
return
{
chart
:
null
}
},
mounted
()
{
this
.
initChart
()
},
beforeDestroy
()
{
if
(
!
this
.
chart
)
{
return
}
this
.
chart
.
dispose
()
this
.
chart
=
null
},
methods
:
{
initChart
()
{
this
.
chart
=
echarts
.
init
(
document
.
getElementById
(
this
.
id
))
this
.
chart
.
setOption
({
backgroundColor
:
'
#394056
'
,
title
:
{
top
:
20
,
text
:
'
Requests
'
,
textStyle
:
{
fontWeight
:
'
normal
'
,
fontSize
:
16
,
color
:
'
#F1F1F3
'
},
left
:
'
1%
'
},
tooltip
:
{
trigger
:
'
axis
'
,
axisPointer
:
{
lineStyle
:
{
color
:
'
#57617B
'
}
}
},
legend
:
{
top
:
20
,
icon
:
'
rect
'
,
itemWidth
:
14
,
itemHeight
:
5
,
itemGap
:
13
,
data
:
[
'
CMCC
'
,
'
CTCC
'
,
'
CUCC
'
],
right
:
'
4%
'
,
textStyle
:
{
fontSize
:
12
,
color
:
'
#F1F1F3
'
}
},
grid
:
{
top
:
100
,
left
:
'
3%
'
,
right
:
'
4%
'
,
bottom
:
'
2%
'
,
containLabel
:
true
},
xAxis
:
[{
type
:
'
category
'
,
boundaryGap
:
false
,
axisLine
:
{
lineStyle
:
{
color
:
'
#57617B
'
}
},
data
:
[
'
13:00
'
,
'
13:05
'
,
'
13:10
'
,
'
13:15
'
,
'
13:20
'
,
'
13:25
'
,
'
13:30
'
,
'
13:35
'
,
'
13:40
'
,
'
13:45
'
,
'
13:50
'
,
'
13:55
'
]
}],
yAxis
:
[{
type
:
'
value
'
,
name
:
'
(%)
'
,
axisTick
:
{
show
:
false
},
axisLine
:
{
lineStyle
:
{
color
:
'
#57617B
'
}
},
axisLabel
:
{
margin
:
10
,
textStyle
:
{
fontSize
:
14
}
},
splitLine
:
{
lineStyle
:
{
color
:
'
#57617B
'
}
}
}],
series
:
[{
name
:
'
CMCC
'
,
type
:
'
line
'
,
smooth
:
true
,
symbol
:
'
circle
'
,
symbolSize
:
5
,
showSymbol
:
false
,
lineStyle
:
{
normal
:
{
width
:
1
}
},
areaStyle
:
{
normal
:
{
color
:
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
0
,
1
,
[{
offset
:
0
,
color
:
'
rgba(137, 189, 27, 0.3)
'
},
{
offset
:
0.8
,
color
:
'
rgba(137, 189, 27, 0)
'
}],
false
),
shadowColor
:
'
rgba(0, 0, 0, 0.1)
'
,
shadowBlur
:
10
}
},
itemStyle
:
{
normal
:
{
color
:
'
rgb(137,189,27)
'
,
borderColor
:
'
rgba(137,189,2,0.27)
'
,
borderWidth
:
12
}
},
data
:
[
220
,
182
,
191
,
134
,
150
,
120
,
110
,
125
,
145
,
122
,
165
,
122
]
},
{
name
:
'
CTCC
'
,
type
:
'
line
'
,
smooth
:
true
,
symbol
:
'
circle
'
,
symbolSize
:
5
,
showSymbol
:
false
,
lineStyle
:
{
normal
:
{
width
:
1
}
},
areaStyle
:
{
normal
:
{
color
:
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
0
,
1
,
[{
offset
:
0
,
color
:
'
rgba(0, 136, 212, 0.3)
'
},
{
offset
:
0.8
,
color
:
'
rgba(0, 136, 212, 0)
'
}],
false
),
shadowColor
:
'
rgba(0, 0, 0, 0.1)
'
,
shadowBlur
:
10
}
},
itemStyle
:
{
normal
:
{
color
:
'
rgb(0,136,212)
'
,
borderColor
:
'
rgba(0,136,212,0.2)
'
,
borderWidth
:
12
}
},
data
:
[
120
,
110
,
125
,
145
,
122
,
165
,
122
,
220
,
182
,
191
,
134
,
150
]
},
{
name
:
'
CUCC
'
,
type
:
'
line
'
,
smooth
:
true
,
symbol
:
'
circle
'
,
symbolSize
:
5
,
showSymbol
:
false
,
lineStyle
:
{
normal
:
{
width
:
1
}
},
areaStyle
:
{
normal
:
{
color
:
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
0
,
1
,
[{
offset
:
0
,
color
:
'
rgba(219, 50, 51, 0.3)
'
},
{
offset
:
0.8
,
color
:
'
rgba(219, 50, 51, 0)
'
}],
false
),
shadowColor
:
'
rgba(0, 0, 0, 0.1)
'
,
shadowBlur
:
10
}
},
itemStyle
:
{
normal
:
{
color
:
'
rgb(219,50,51)
'
,
borderColor
:
'
rgba(219,50,51,0.2)
'
,
borderWidth
:
12
}
},
data
:
[
220
,
182
,
125
,
145
,
122
,
191
,
134
,
150
,
120
,
110
,
165
,
122
]
}]
})
}
}
}
</
script
>
litemall-admin/src/components/Charts/mixChart.vue
0 → 100644
View file @
6c14c43c
<
template
>
<div
:class=
"className"
:id=
"id"
:style=
"
{height:height,width:width}">
</div>
</
template
>
<
script
>
import
echarts
from
'
echarts
'
export
default
{
props
:
{
className
:
{
type
:
String
,
default
:
'
chart
'
},
id
:
{
type
:
String
,
default
:
'
chart
'
},
width
:
{
type
:
String
,
default
:
'
200px
'
},
height
:
{
type
:
String
,
default
:
'
200px
'
}
},
data
()
{
return
{
chart
:
null
}
},
mounted
()
{
this
.
initChart
()
this
.
chart
=
null
},
beforeDestroy
()
{
if
(
!
this
.
chart
)
{
return
}
this
.
chart
.
dispose
()
this
.
chart
=
null
},
methods
:
{
initChart
()
{
this
.
chart
=
echarts
.
init
(
document
.
getElementById
(
this
.
id
))
const
xData
=
(
function
()
{
const
data
=
[]
for
(
let
i
=
1
;
i
<
13
;
i
++
)
{
data
.
push
(
i
+
'
month
'
)
}
return
data
}())
this
.
chart
.
setOption
({
backgroundColor
:
'
#344b58
'
,
title
:
{
text
:
'
statistics
'
,
x
:
'
20
'
,
top
:
'
20
'
,
textStyle
:
{
color
:
'
#fff
'
,
fontSize
:
'
22
'
},
subtextStyle
:
{
color
:
'
#90979c
'
,
fontSize
:
'
16
'
}
},
tooltip
:
{
trigger
:
'
axis
'
,
axisPointer
:
{
textStyle
:
{
color
:
'
#fff
'
}
}
},
grid
:
{
borderWidth
:
0
,
top
:
110
,
bottom
:
95
,
textStyle
:
{
color
:
'
#fff
'
}
},
legend
:
{
x
:
'
5%
'
,
top
:
'
10%
'
,
textStyle
:
{
color
:
'
#90979c
'
},
data
:
[
'
female
'
,
'
male
'
,
'
average
'
]
},
calculable
:
true
,
xAxis
:
[{
type
:
'
category
'
,
axisLine
:
{
lineStyle
:
{
color
:
'
#90979c
'
}
},
splitLine
:
{
show
:
false
},
axisTick
:
{
show
:
false
},
splitArea
:
{
show
:
false
},
axisLabel
:
{
interval
:
0
},
data
:
xData
}],
yAxis
:
[{
type
:
'
value
'
,
splitLine
:
{
show
:
false
},
axisLine
:
{
lineStyle
:
{
color
:
'
#90979c
'
}
},
axisTick
:
{
show
:
false
},
axisLabel
:
{
interval
:
0
},
splitArea
:
{
show
:
false
}
}],
dataZoom
:
[{
show
:
true
,
height
:
30
,
xAxisIndex
:
[
0
],
bottom
:
30
,
start
:
10
,
end
:
80
,
handleIcon
:
'
path://M306.1,413c0,2.2-1.8,4-4,4h-59.8c-2.2,0-4-1.8-4-4V200.8c0-2.2,1.8-4,4-4h59.8c2.2,0,4,1.8,4,4V413z
'
,
handleSize
:
'
110%
'
,
handleStyle
:
{
color
:
'
#d3dee5
'
},
textStyle
:
{
color
:
'
#fff
'
},
borderColor
:
'
#90979c
'
},
{
type
:
'
inside
'
,
show
:
true
,
height
:
15
,
start
:
1
,
end
:
35
}],
series
:
[{
name
:
'
female
'
,
type
:
'
bar
'
,
stack
:
'
total
'
,
barMaxWidth
:
35
,
barGap
:
'
10%
'
,
itemStyle
:
{
normal
:
{
color
:
'
rgba(255,144,128,1)
'
,
label
:
{
show
:
true
,
textStyle
:
{
color
:
'
#fff
'
},
position
:
'
insideTop
'
,
formatter
(
p
)
{
return
p
.
value
>
0
?
p
.
value
:
''
}
}
}
},
data
:
[
709
,
1917
,
2455
,
2610
,
1719
,
1433
,
1544
,
3285
,
5208
,
3372
,
2484
,
4078
]
},
{
name
:
'
male
'
,
type
:
'
bar
'
,
stack
:
'
total
'
,
itemStyle
:
{
normal
:
{
color
:
'
rgba(0,191,183,1)
'
,
barBorderRadius
:
0
,
label
:
{
show
:
true
,
position
:
'
top
'
,
formatter
(
p
)
{
return
p
.
value
>
0
?
p
.
value
:
''
}
}
}
},
data
:
[
327
,
1776
,
507
,
1200
,
800
,
482
,
204
,
1390
,
1001
,
951
,
381
,
220
]
},
{
name
:
'
average
'
,
type
:
'
line
'
,
stack
:
'
total
'
,
symbolSize
:
10
,
symbol
:
'
circle
'
,
itemStyle
:
{
normal
:
{
color
:
'
rgba(252,230,48,1)
'
,
barBorderRadius
:
0
,
label
:
{
show
:
true
,
position
:
'
top
'
,
formatter
(
p
)
{
return
p
.
value
>
0
?
p
.
value
:
''
}
}
}
},
data
:
[
1036
,
3693
,
2962
,
3810
,
2519
,
1915
,
1748
,
4675
,
6209
,
4323
,
2865
,
4298
]
}
]
})
}
}
}
</
script
>
litemall-admin/src/components/Hamburger/index.vue
0 → 100644
View file @
6c14c43c
<
template
>
<div>
<svg
t=
"1492500959545"
@
click=
"toggleClick"
class=
"wscn-icon hamburger"
:class=
"
{'is-active':isActive}" style="" viewBox="0 0 1024 1024"
version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1691" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64">
<path
d=
"M966.8023 568.849776 57.196677 568.849776c-31.397081 0-56.850799-25.452695-56.850799-56.850799l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 543.397081 998.200404 568.849776 966.8023 568.849776z"
p-id=
"1692"
></path>
<path
d=
"M966.8023 881.527125 57.196677 881.527125c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 856.07443 998.200404 881.527125 966.8023 881.527125z"
p-id=
"1693"
></path>
<path
d=
"M966.8023 256.17345 57.196677 256.17345c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.850799 56.850799-56.850799l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.850799l0 0C1023.653099 230.720755 998.200404 256.17345 966.8023 256.17345z"
p-id=
"1694"
></path>
</svg>
</div>
</
template
>
<
script
>
export
default
{
name
:
'
hamburger
'
,
props
:
{
isActive
:
{
type
:
Boolean
,
default
:
false
},
toggleClick
:
{
type
:
Function
,
default
:
null
}
}
}
</
script
>
<
style
scoped
>
.hamburger
{
display
:
inline-block
;
cursor
:
pointer
;
width
:
20px
;
height
:
20px
;
transform
:
rotate
(
90deg
);
transition
:
.38s
;
transform-origin
:
50%
50%
;
}
.hamburger.is-active
{
transform
:
rotate
(
0deg
);
}
</
style
>
litemall-admin/src/components/Screenfull/index.vue
0 → 100644
View file @
6c14c43c
<
template
>
<div>
<svg
t=
"1508738709248"
@
click=
'click'
class=
"screenfull-svg"
viewBox=
"0 0 1024 1024"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
p-id=
"2069"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
width=
"32"
height=
"32"
>
<path
d=
"M333.493443 428.647617 428.322206 333.832158 262.572184 168.045297 366.707916 64.444754 64.09683 64.444754 63.853283 366.570793 167.283957 262.460644Z"
p-id=
"2070"
></path>
<path
d=
"M854.845439 760.133334 688.61037 593.95864 593.805144 688.764889 759.554142 854.56096 655.44604 958.161503 958.055079 958.161503 958.274066 656.035464Z"
p-id=
"2071"
></path>
<path
d=
"M688.535669 428.550403 854.31025 262.801405 957.935352 366.921787 957.935352 64.34754 655.809313 64.081481 759.919463 167.535691 593.70793 333.731874Z"
p-id=
"2072"
></path>
<path
d=
"M333.590658 594.033341 167.8171 759.804852 64.218604 655.67219 64.218604 958.270996 366.342596 958.502263 262.234493 855.071589 428.421466 688.86108Z"
p-id=
"2073"
></path>
</svg>
</div>
</
template
>
<
script
>
import
screenfull
from
'
screenfull
'
export
default
{
name
:
'
screenfull
'
,
props
:
{
width
:
{
type
:
Number
,
default
:
22
},
height
:
{
type
:
Number
,
default
:
22
},
fill
:
{
type
:
String
,
default
:
'
#48576a
'
}
},
data
()
{
return
{
isFullscreen
:
false
}
},
methods
:
{
click
()
{
if
(
!
screenfull
.
enabled
)
{
this
.
$message
({
message
:
'
you browser can not work
'
,
type
:
'
warning
'
})
return
false
}
screenfull
.
toggle
()
}
}
}
</
script
>
<
style
scoped
>
.screenfull-svg
{
display
:
inline-block
;
cursor
:
pointer
;
fill
:
#5a5e66
;
;
width
:
20px
;
height
:
20px
;
vertical-align
:
10px
;
}
</
style
>
litemall-admin/src/components/ScrollBar/index.vue
0 → 100644
View file @
6c14c43c
<
template
>
<div
class=
"scroll-container"
ref=
"scrollContainer"
@
wheel.prevent=
"handleScroll"
>
<div
class=
"scroll-wrapper"
ref=
"scrollWrapper"
:style=
"
{top: top + 'px'}">
<slot></slot>
</div>
</div>
</
template
>
<
script
>
const
delta
=
15
export
default
{
name
:
'
scrollBar
'
,
data
()
{
return
{
top
:
0
}
},
methods
:
{
handleScroll
(
e
)
{
const
eventDelta
=
e
.
wheelDelta
||
-
e
.
deltaY
*
3
const
$container
=
this
.
$refs
.
scrollContainer
const
$containerHeight
=
$container
.
offsetHeight
const
$wrapper
=
this
.
$refs
.
scrollWrapper
const
$wrapperHeight
=
$wrapper
.
offsetHeight
if
(
eventDelta
>
0
)
{
this
.
top
=
Math
.
min
(
0
,
this
.
top
+
eventDelta
)
}
else
{
if
(
$containerHeight
-
delta
<
$wrapperHeight
)
{
if
(
this
.
top
<
-
(
$wrapperHeight
-
$containerHeight
+
delta
))
{
this
.
top
=
this
.
top
}
else
{
this
.
top
=
Math
.
max
(
this
.
top
+
eventDelta
,
$containerHeight
-
$wrapperHeight
-
delta
)
}
}
else
{
this
.
top
=
0
}
}
}
}
}
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
@import
'../../styles/variables.scss'
;
.scroll-container
{
position
:
relative
;
width
:
100%
;
height
:
100%
;
background-color
:
$menuBg
;
.scroll-wrapper
{
position
:
absolute
;
width
:
100%
!
important
;
}
}
</
style
>
litemall-admin/src/components/ScrollPane/index.vue
0 → 100644
View file @
6c14c43c
<
template
>
<div
class=
"scroll-container"
ref=
"scrollContainer"
@
wheel.prevent=
"handleScroll"
>
<div
class=
"scroll-wrapper"
ref=
"scrollWrapper"
:style=
"
{left: left + 'px'}">
<slot></slot>
</div>
</div>
</
template
>
<
script
>
const
padding
=
15
// tag's padding
export
default
{
name
:
'
scrollPane
'
,
data
()
{
return
{
left
:
0
}
},
methods
:
{
handleScroll
(
e
)
{
const
eventDelta
=
e
.
wheelDelta
||
-
e
.
deltaY
*
3
const
$container
=
this
.
$refs
.
scrollContainer
const
$containerWidth
=
$container
.
offsetWidth
const
$wrapper
=
this
.
$refs
.
scrollWrapper
const
$wrapperWidth
=
$wrapper
.
offsetWidth
if
(
eventDelta
>
0
)
{
this
.
left
=
Math
.
min
(
0
,
this
.
left
+
eventDelta
)
}
else
{
if
(
$containerWidth
-
padding
<
$wrapperWidth
)
{
if
(
this
.
left
<
-
(
$wrapperWidth
-
$containerWidth
+
padding
))
{
this
.
left
=
this
.
left
}
else
{
this
.
left
=
Math
.
max
(
this
.
left
+
eventDelta
,
$containerWidth
-
$wrapperWidth
-
padding
)
}
}
else
{
this
.
left
=
0
}
}
},
moveToTarget
(
$target
)
{
const
$container
=
this
.
$refs
.
scrollContainer
const
$containerWidth
=
$container
.
offsetWidth
const
$targetLeft
=
$target
.
offsetLeft
const
$targetWidth
=
$target
.
offsetWidth
if
(
$targetLeft
<
-
this
.
left
)
{
// tag in the left
this
.
left
=
-
$targetLeft
+
padding
}
else
if
(
$targetLeft
+
padding
>
-
this
.
left
&&
$targetLeft
+
$targetWidth
<
-
this
.
left
+
$containerWidth
-
padding
)
{
// tag in the current view
// eslint-disable-line
}
else
{
// tag in the right
this
.
left
=
-
(
$targetLeft
-
(
$containerWidth
-
$targetWidth
)
+
padding
)
}
}
}
}
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
.scroll-container
{
white-space
:
nowrap
;
position
:
relative
;
overflow
:
hidden
;
width
:
100%
;
.scroll-wrapper
{
position
:
absolute
;
}
}
</
style
>
litemall-admin/src/components/Sticky/index.vue
0 → 100644
View file @
6c14c43c
<
template
>
<div
:style=
"
{height:height+'px',zIndex:zIndex}">
<div
:class=
"className"
:style=
"
{top:stickyTop+'px',zIndex:zIndex,position:position,width:width,height:height+'px'}">
<slot>
<div>
sticky
</div>
</slot>
</div>
</div>
</
template
>
<
script
>
export
default
{
name
:
'
Sticky
'
,
props
:
{
stickyTop
:
{
type
:
Number
,
default
:
0
},
zIndex
:
{
type
:
Number
,
default
:
1
},
className
:
{
type
:
String
}
},
data
()
{
return
{
active
:
false
,
position
:
''
,
currentTop
:
''
,
width
:
undefined
,
height
:
undefined
,
child
:
null
,
stickyHeight
:
0
}
},
mounted
()
{
this
.
height
=
this
.
$el
.
getBoundingClientRect
().
height
window
.
addEventListener
(
'
scroll
'
,
this
.
handleScroll
)
},
activated
()
{
this
.
handleScroll
()
},
destroyed
()
{
window
.
removeEventListener
(
'
scroll
'
,
this
.
handleScroll
)
},
methods
:
{
sticky
()
{
if
(
this
.
active
)
{
return
}
this
.
position
=
'
fixed
'
this
.
active
=
true
this
.
width
=
this
.
width
+
'
px
'
},
reset
()
{
if
(
!
this
.
active
)
{
return
}
this
.
position
=
''
this
.
width
=
'
auto
'
this
.
active
=
false
},
handleScroll
()
{
this
.
width
=
this
.
$el
.
getBoundingClientRect
().
width
const
offsetTop
=
this
.
$el
.
getBoundingClientRect
().
top
if
(
offsetTop
<=
this
.
stickyTop
)
{
this
.
sticky
()
return
}
this
.
reset
()
}
}
}
</
script
>
litemall-admin/src/components/SvgIcon/index.vue
0 → 100644
View file @
6c14c43c
<
template
>
<svg
:class=
"svgClass"
aria-hidden=
"true"
>
<use
:xlink:href=
"iconName"
></use>
</svg>
</
template
>
<
script
>
export
default
{
name
:
'
svg-icon
'
,
props
:
{
iconClass
:
{
type
:
String
,
required
:
true
},
className
:
{
type
:
String
}
},
computed
:
{
iconName
()
{
return
`#icon-
${
this
.
iconClass
}
`
},
svgClass
()
{
if
(
this
.
className
)
{
return
'
svg-icon
'
+
this
.
className
}
else
{
return
'
svg-icon
'
}
}
}
}
</
script
>
<
style
scoped
>
.svg-icon
{
width
:
1em
;
height
:
1em
;
vertical-align
:
-0.15em
;
fill
:
currentColor
;
overflow
:
hidden
;
}
</
style
>
litemall-admin/src/components/Tinymce/components/editorImage.vue
0 → 100644
View file @
6c14c43c
<
template
>
<div
class=
"upload-container"
>
<el-button
icon=
'el-icon-upload'
size=
"mini"
:style=
"
{background:color,borderColor:color}" @click=" dialogVisible=true" type="primary">上传图片
</el-button>
<el-dialog
:visible.sync=
"dialogVisible"
>
<el-upload
class=
"editor-slide-upload"
action=
"https://httpbin.org/post"
:multiple=
"true"
:file-list=
"fileList"
:show-file-list=
"true"
list-type=
"picture-card"
:on-remove=
"handleRemove"
:on-success=
"handleSuccess"
:before-upload=
"beforeUpload"
>
<el-button
size=
"small"
type=
"primary"
>
点击上传
</el-button>
</el-upload>
<el-button
@
click=
"dialogVisible = false"
>
取 消
</el-button>
<el-button
type=
"primary"
@
click=
"handleSubmit"
>
确 定
</el-button>
</el-dialog>
</div>
</
template
>
<
script
>
// import { getToken } from 'api/qiniu'
export
default
{
name
:
'
editorSlideUpload
'
,
props
:
{
color
:
{
type
:
String
,
default
:
'
#1890ff
'
}
},
data
()
{
return
{
dialogVisible
:
false
,
listObj
:
{},
fileList
:
[]
}
},
methods
:
{
checkAllSuccess
()
{
return
Object
.
keys
(
this
.
listObj
).
every
(
item
=>
this
.
listObj
[
item
].
hasSuccess
)
},
handleSubmit
()
{
const
arr
=
Object
.
keys
(
this
.
listObj
).
map
(
v
=>
this
.
listObj
[
v
])
if
(
!
this
.
checkAllSuccess
())
{
this
.
$message
(
'
请等待所有图片上传成功 或 出现了网络问题,请刷新页面重新上传!
'
)
return
}
console
.
log
(
arr
)
this
.
$emit
(
'
successCBK
'
,
arr
)
this
.
listObj
=
{}
this
.
fileList
=
[]
this
.
dialogVisible
=
false
},
handleSuccess
(
response
,
file
)
{
const
uid
=
file
.
uid
const
objKeyArr
=
Object
.
keys
(
this
.
listObj
)
for
(
let
i
=
0
,
len
=
objKeyArr
.
length
;
i
<
len
;
i
++
)
{
if
(
this
.
listObj
[
objKeyArr
[
i
]].
uid
===
uid
)
{
this
.
listObj
[
objKeyArr
[
i
]].
url
=
response
.
files
.
file
this
.
listObj
[
objKeyArr
[
i
]].
hasSuccess
=
true
return
}
}
},
handleRemove
(
file
)
{
const
uid
=
file
.
uid
const
objKeyArr
=
Object
.
keys
(
this
.
listObj
)
for
(
let
i
=
0
,
len
=
objKeyArr
.
length
;
i
<
len
;
i
++
)
{
if
(
this
.
listObj
[
objKeyArr
[
i
]].
uid
===
uid
)
{
delete
this
.
listObj
[
objKeyArr
[
i
]]
return
}
}
},
beforeUpload
(
file
)
{
const
_self
=
this
const
_URL
=
window
.
URL
||
window
.
webkitURL
const
fileName
=
file
.
uid
this
.
listObj
[
fileName
]
=
{}
return
new
Promise
((
resolve
,
reject
)
=>
{
const
img
=
new
Image
()
img
.
src
=
_URL
.
createObjectURL
(
file
)
img
.
onload
=
function
()
{
_self
.
listObj
[
fileName
]
=
{
hasSuccess
:
false
,
uid
:
file
.
uid
,
width
:
this
.
width
,
height
:
this
.
height
}
}
resolve
(
true
)
})
}
}
}
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
.upload-container
{
.editor-slide-upload
{
margin-bottom
:
20px
;
}
}
</
style
>
litemall-admin/src/components/Tinymce/index.vue
0 → 100644
View file @
6c14c43c
<
template
>
<div
class=
"tinymce-container editor-container"
>
<textarea
class=
"tinymce-textarea"
:id=
"tinymceId"
></textarea>
<div
class=
"editor-custom-btn-container"
>
<editorImage
color=
"#1890ff"
class=
"editor-upload-btn"
@
successCBK=
"imageSuccessCBK"
></editorImage>
</div>
</div>
</
template
>
<
script
>
import
editorImage
from
'
./components/editorImage
'
import
plugins
from
'
./plugins
'
import
toolbar
from
'
./toolbar
'
export
default
{
name
:
'
tinymce
'
,
components
:
{
editorImage
},
props
:
{
id
:
{
type
:
String
},
value
:
{
type
:
String
,
default
:
''
},
toolbar
:
{
type
:
Array
,
required
:
false
,
default
()
{
return
[]
}
},
menubar
:
{
default
:
'
file edit insert view format table
'
},
height
:
{
type
:
Number
,
required
:
false
,
default
:
360
}
},
data
()
{
return
{
hasChange
:
false
,
hasInit
:
false
,
tinymceId
:
this
.
id
||
'
vue-tinymce-
'
+
+
new
Date
()
}
},
watch
:
{
value
(
val
)
{
if
(
!
this
.
hasChange
&&
this
.
hasInit
)
{
this
.
$nextTick
(()
=>
window
.
tinymce
.
get
(
this
.
tinymceId
).
setContent
(
val
))
}
}
},
mounted
()
{
this
.
initTinymce
()
},
activated
()
{
this
.
initTinymce
()
},
deactivated
()
{
this
.
destroyTinymce
()
},
methods
:
{
initTinymce
()
{
const
_this
=
this
window
.
tinymce
.
init
({
selector
:
`#
${
this
.
tinymceId
}
`
,
height
:
this
.
height
,
body_class
:
'
panel-body
'
,
object_resizing
:
false
,
toolbar
:
this
.
toolbar
.
length
>
0
?
this
.
toolbar
:
toolbar
,
menubar
:
this
.
menubar
,
plugins
:
plugins
,
end_container_on_empty_block
:
true
,
powerpaste_word_import
:
'
clean
'
,
code_dialog_height
:
450
,
code_dialog_width
:
1000
,
advlist_bullet_styles
:
'
square
'
,
advlist_number_styles
:
'
default
'
,
imagetools_cors_hosts
:
[
'
www.tinymce.com
'
,
'
codepen.io
'
],
default_link_target
:
'
_blank
'
,
link_title
:
false
,
init_instance_callback
:
editor
=>
{
if
(
_this
.
value
)
{
editor
.
setContent
(
_this
.
value
)
}
_this
.
hasInit
=
true
editor
.
on
(
'
NodeChange Change KeyUp
'
,
()
=>
{
this
.
hasChange
=
true
this
.
$emit
(
'
input
'
,
editor
.
getContent
({
format
:
'
raw
'
}))
})
}
// 整合七牛上传
// images_dataimg_filter(img) {
// setTimeout(() => {
// const $image = $(img);
// $image.removeAttr('width');
// $image.removeAttr('height');
// if ($image[0].height && $image[0].width) {
// $image.attr('data-wscntype', 'image');
// $image.attr('data-wscnh', $image[0].height);
// $image.attr('data-wscnw', $image[0].width);
// $image.addClass('wscnph');
// }
// }, 0);
// return img
// },
// images_upload_handler(blobInfo, success, failure, progress) {
// progress(0);
// const token = _this.$store.getters.token;
// getToken(token).then(response => {
// const url = response.data.qiniu_url;
// const formData = new FormData();
// formData.append('token', response.data.qiniu_token);
// formData.append('key', response.data.qiniu_key);
// formData.append('file', blobInfo.blob(), url);
// upload(formData).then(() => {
// success(url);
// progress(100);
// })
// }).catch(err => {
// failure('出现未知问题,刷新页面,或者联系程序员')
// console.log(err);
// });
// },
})
},
destroyTinymce
()
{
if
(
window
.
tinymce
.
get
(
this
.
tinymceId
))
{
window
.
tinymce
.
get
(
this
.
tinymceId
).
destroy
()
}
},
setContent
(
value
)
{
window
.
tinymce
.
get
(
this
.
tinymceId
).
setContent
(
value
)
},
getContent
()
{
window
.
tinymce
.
get
(
this
.
tinymceId
).
getContent
()
},
imageSuccessCBK
(
arr
)
{
const
_this
=
this
arr
.
forEach
(
v
=>
{
window
.
tinymce
.
get
(
_this
.
tinymceId
).
insertContent
(
`<img class="wscnph" src="
${
v
.
url
}
" >`
)
})
}
},
destroyed
()
{
this
.
destroyTinymce
()
}
}
</
script
>
<
style
scoped
>
.tinymce-container
{
position
:
relative
}
.tinymce-textarea
{
visibility
:
hidden
;
z-index
:
-1
;
}
.editor-custom-btn-container
{
position
:
absolute
;
right
:
4px
;
top
:
4px
;
/*z-index: 2005;*/
}
.editor-upload-btn
{
display
:
inline-block
;
}
</
style
>
litemall-admin/src/components/Tinymce/plugins.js
0 → 100644
View file @
6c14c43c
// Any plugins you want to use has to be imported
// Detail plugins list see https://www.tinymce.com/docs/plugins/
// Custom builds see https://www.tinymce.com/download/custom-builds/
const
plugins
=
[
'
advlist anchor autolink autoresize autosave bbcode code codesample colorpicker colorpicker contextmenu directionality emoticons fullpage fullscreen hr image imagetools importcss insertdatetime legacyoutput link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount
'
]
export
default
plugins
litemall-admin/src/components/Tinymce/toolbar.js
0 → 100644
View file @
6c14c43c
// Here is a list of the toolbar
// Detail list see https://www.tinymce.com/docs/advanced/editor-control-identifiers/#toolbarcontrols
const
toolbar
=
[
'
bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript code codesample
'
,
'
hr bullist numlist link image charmap preview anchor pagebreak fullscreen insertdatetime media table emoticons forecolor backcolor
'
]
export
default
toolbar
litemall-admin/src/components/Upload/singleImage.vue
0 → 100644
View file @
6c14c43c
<
template
>
<div
class=
"upload-container"
>
<el-upload
class=
"image-uploader"
:data=
"dataObj"
drag
:multiple=
"false"
:show-file-list=
"false"
action=
"https://httpbin.org/post"
:on-success=
"handleImageScucess"
>
<i
class=
"el-icon-upload"
></i>
<div
class=
"el-upload__text"
>
将文件拖到此处,或
<em>
点击上传
</em></div>
</el-upload>
<div
class=
"image-preview"
>
<div
class=
"image-preview-wrapper"
v-show=
"imageUrl.length>1"
>
<img
:src=
"imageUrl+'?imageView2/1/w/200/h/200'"
>
<div
class=
"image-preview-action"
>
<i
@
click=
"rmImage"
class=
"el-icon-delete"
></i>
</div>
</div>
</div>
</div>
</
template
>
<
script
>
// 预览效果见付费文章
import
{
getToken
}
from
'
@/api/qiniu
'
export
default
{
name
:
'
singleImageUpload
'
,
props
:
{
value
:
String
},
computed
:
{
imageUrl
()
{
return
this
.
value
}
},
data
()
{
return
{
tempUrl
:
''
,
dataObj
:
{
token
:
''
,
key
:
''
}
}
},
methods
:
{
rmImage
()
{
this
.
emitInput
(
''
)
},
emitInput
(
val
)
{
this
.
$emit
(
'
input
'
,
val
)
},
handleImageScucess
()
{
this
.
emitInput
(
this
.
tempUrl
)
},
beforeUpload
()
{
const
_self
=
this
return
new
Promise
((
resolve
,
reject
)
=>
{
getToken
().
then
(
response
=>
{
const
key
=
response
.
data
.
qiniu_key
const
token
=
response
.
data
.
qiniu_token
_self
.
_data
.
dataObj
.
token
=
token
_self
.
_data
.
dataObj
.
key
=
key
this
.
tempUrl
=
response
.
data
.
qiniu_url
resolve
(
true
)
}).
catch
(
err
=>
{
console
.
log
(
err
)
reject
(
false
)
})
})
}
}
}
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
@import
"src/styles/mixin.scss"
;
.upload-container
{
width
:
100%
;
position
:
relative
;
@include
clearfix
;
.image-uploader
{
width
:
60%
;
float
:
left
;
}
.image-preview
{
width
:
200px
;
height
:
200px
;
position
:
relative
;
border
:
1px
dashed
#d9d9d9
;
float
:
left
;
margin-left
:
50px
;
.image-preview-wrapper
{
position
:
relative
;
width
:
100%
;
height
:
100%
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.image-preview-action
{
position
:
absolute
;
width
:
100%
;
height
:
100%
;
left
:
0
;
top
:
0
;
cursor
:
default
;
text-align
:
center
;
color
:
#fff
;
opacity
:
0
;
font-size
:
20px
;
background-color
:
rgba
(
0
,
0
,
0
,
.5
);
transition
:
opacity
.3s
;
cursor
:
pointer
;
text-align
:
center
;
line-height
:
200px
;
.el-icon-delete
{
font-size
:
36px
;
}
}
&
:hover
{
.image-preview-action
{
opacity
:
1
;
}
}
}
}
</
style
>
litemall-admin/src/components/Upload/singleImage2.vue
0 → 100644
View file @
6c14c43c
<
template
>
<div
class=
"singleImageUpload2 upload-container"
>
<el-upload
class=
"image-uploader"
:data=
"dataObj"
drag
:multiple=
"false"
:show-file-list=
"false"
action=
"https://httpbin.org/post"
:on-success=
"handleImageScucess"
>
<i
class=
"el-icon-upload"
></i>
<div
class=
"el-upload__text"
>
Drag或
<em>
点击上传
</em></div>
</el-upload>
<div
v-show=
"imageUrl.length>0"
class=
"image-preview"
>
<div
class=
"image-preview-wrapper"
v-show=
"imageUrl.length>1"
>
<img
:src=
"imageUrl"
>
<div
class=
"image-preview-action"
>
<i
@
click=
"rmImage"
class=
"el-icon-delete"
></i>
</div>
</div>
</div>
</div>
</
template
>
<
script
>
import
{
getToken
}
from
'
@/api/qiniu
'
export
default
{
name
:
'
singleImageUpload2
'
,
props
:
{
value
:
String
},
computed
:
{
imageUrl
()
{
return
this
.
value
}
},
data
()
{
return
{
tempUrl
:
''
,
dataObj
:
{
token
:
''
,
key
:
''
}
}
},
methods
:
{
rmImage
()
{
this
.
emitInput
(
''
)
},
emitInput
(
val
)
{
this
.
$emit
(
'
input
'
,
val
)
},
handleImageScucess
()
{
this
.
emitInput
(
this
.
tempUrl
)
},
beforeUpload
()
{
const
_self
=
this
return
new
Promise
((
resolve
,
reject
)
=>
{
getToken
().
then
(
response
=>
{
const
key
=
response
.
data
.
qiniu_key
const
token
=
response
.
data
.
qiniu_token
_self
.
_data
.
dataObj
.
token
=
token
_self
.
_data
.
dataObj
.
key
=
key
this
.
tempUrl
=
response
.
data
.
qiniu_url
resolve
(
true
)
}).
catch
(()
=>
{
reject
(
false
)
})
})
}
}
}
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
.upload-container
{
width
:
100%
;
height
:
100%
;
position
:
relative
;
.image-uploader
{
height
:
100%
;
}
.image-preview
{
width
:
100%
;
height
:
100%
;
position
:
absolute
;
left
:
0px
;
top
:
0px
;
border
:
1px
dashed
#d9d9d9
;
.image-preview-wrapper
{
position
:
relative
;
width
:
100%
;
height
:
100%
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.image-preview-action
{
position
:
absolute
;
width
:
100%
;
height
:
100%
;
left
:
0
;
top
:
0
;
cursor
:
default
;
text-align
:
center
;
color
:
#fff
;
opacity
:
0
;
font-size
:
20px
;
background-color
:
rgba
(
0
,
0
,
0
,
.5
);
transition
:
opacity
.3s
;
cursor
:
pointer
;
text-align
:
center
;
line-height
:
200px
;
.el-icon-delete
{
font-size
:
36px
;
}
}
&
:hover
{
.image-preview-action
{
opacity
:
1
;
}
}
}
}
</
style
>
litemall-admin/src/components/Upload/singleImage3.vue
0 → 100644
View file @
6c14c43c
<
template
>
<div
class=
"upload-container"
>
<el-upload
class=
"image-uploader"
:data=
"dataObj"
drag
:multiple=
"false"
:show-file-list=
"false"
action=
"https://httpbin.org/post"
:on-success=
"handleImageScucess"
>
<i
class=
"el-icon-upload"
></i>
<div
class=
"el-upload__text"
>
将文件拖到此处,或
<em>
点击上传
</em></div>
</el-upload>
<div
class=
"image-preview image-app-preview"
>
<div
class=
"image-preview-wrapper"
v-show=
"imageUrl.length>1"
>
<img
:src=
"imageUrl"
>
<div
class=
"image-preview-action"
>
<i
@
click=
"rmImage"
class=
"el-icon-delete"
></i>
</div>
</div>
</div>
<div
class=
"image-preview"
>
<div
class=
"image-preview-wrapper"
v-show=
"imageUrl.length>1"
>
<img
:src=
"imageUrl"
>
<div
class=
"image-preview-action"
>
<i
@
click=
"rmImage"
class=
"el-icon-delete"
></i>
</div>
</div>
</div>
</div>
</
template
>
<
script
>
import
{
getToken
}
from
'
@/api/qiniu
'
export
default
{
name
:
'
singleImageUpload3
'
,
props
:
{
value
:
String
},
computed
:
{
imageUrl
()
{
return
this
.
value
}
},
data
()
{
return
{
tempUrl
:
''
,
dataObj
:
{
token
:
''
,
key
:
''
}
}
},
methods
:
{
rmImage
()
{
this
.
emitInput
(
''
)
},
emitInput
(
val
)
{
this
.
$emit
(
'
input
'
,
val
)
},
handleImageScucess
(
file
)
{
this
.
emitInput
(
file
.
files
.
file
)
},
beforeUpload
()
{
const
_self
=
this
return
new
Promise
((
resolve
,
reject
)
=>
{
getToken
().
then
(
response
=>
{
const
key
=
response
.
data
.
qiniu_key
const
token
=
response
.
data
.
qiniu_token
_self
.
_data
.
dataObj
.
token
=
token
_self
.
_data
.
dataObj
.
key
=
key
this
.
tempUrl
=
response
.
data
.
qiniu_url
resolve
(
true
)
}).
catch
(
err
=>
{
console
.
log
(
err
)
reject
(
false
)
})
})
}
}
}
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
@import
"src/styles/mixin.scss"
;
.upload-container
{
width
:
100%
;
position
:
relative
;
@include
clearfix
;
.image-uploader
{
width
:
35%
;
float
:
left
;
}
.image-preview
{
width
:
200px
;
height
:
200px
;
position
:
relative
;
border
:
1px
dashed
#d9d9d9
;
float
:
left
;
margin-left
:
50px
;
.image-preview-wrapper
{
position
:
relative
;
width
:
100%
;
height
:
100%
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.image-preview-action
{
position
:
absolute
;
width
:
100%
;
height
:
100%
;
left
:
0
;
top
:
0
;
cursor
:
default
;
text-align
:
center
;
color
:
#fff
;
opacity
:
0
;
font-size
:
20px
;
background-color
:
rgba
(
0
,
0
,
0
,
.5
);
transition
:
opacity
.3s
;
cursor
:
pointer
;
text-align
:
center
;
line-height
:
200px
;
.el-icon-delete
{
font-size
:
36px
;
}
}
&
:hover
{
.image-preview-action
{
opacity
:
1
;
}
}
}
.image-app-preview
{
width
:
320px
;
height
:
180px
;
position
:
relative
;
border
:
1px
dashed
#d9d9d9
;
float
:
left
;
margin-left
:
50px
;
.app-fake-conver
{
height
:
44px
;
position
:
absolute
;
width
:
100%
;
// background: rgba(0, 0, 0, .1);
text-align
:
center
;
line-height
:
64px
;
color
:
#fff
;
}
}
}
</
style
>
litemall-admin/src/directive/sticky.js
0 → 100644
View file @
6c14c43c
const
vueSticky
=
{}
let
listenAction
vueSticky
.
install
=
Vue
=>
{
Vue
.
directive
(
'
sticky
'
,
{
inserted
(
el
,
binding
)
{
const
params
=
binding
.
value
||
{}
const
stickyTop
=
params
.
stickyTop
||
0
const
zIndex
=
params
.
zIndex
||
1000
const
elStyle
=
el
.
style
elStyle
.
position
=
'
-webkit-sticky
'
elStyle
.
position
=
'
sticky
'
// if the browser support css sticky(Currently Safari, Firefox and Chrome Canary)
// if (~elStyle.position.indexOf('sticky')) {
// elStyle.top = `${stickyTop}px`;
// elStyle.zIndex = zIndex;
// return
// }
const
elHeight
=
el
.
getBoundingClientRect
().
height
const
elWidth
=
el
.
getBoundingClientRect
().
width
elStyle
.
cssText
=
`top:
${
stickyTop
}
px; z-index:
${
zIndex
}
`
const
parentElm
=
el
.
parentNode
||
document
.
documentElement
const
placeholder
=
document
.
createElement
(
'
div
'
)
placeholder
.
style
.
display
=
'
none
'
placeholder
.
style
.
width
=
`
${
elWidth
}
px`
placeholder
.
style
.
height
=
`
${
elHeight
}
px`
parentElm
.
insertBefore
(
placeholder
,
el
)
let
active
=
false
const
getScroll
=
(
target
,
top
)
=>
{
const
prop
=
top
?
'
pageYOffset
'
:
'
pageXOffset
'
const
method
=
top
?
'
scrollTop
'
:
'
scrollLeft
'
let
ret
=
target
[
prop
]
if
(
typeof
ret
!==
'
number
'
)
{
ret
=
window
.
document
.
documentElement
[
method
]
}
return
ret
}
const
sticky
=
()
=>
{
if
(
active
)
{
return
}
if
(
!
elStyle
.
height
)
{
elStyle
.
height
=
`
${
el
.
offsetHeight
}
px`
}
elStyle
.
position
=
'
fixed
'
elStyle
.
width
=
`
${
elWidth
}
px`
placeholder
.
style
.
display
=
'
inline-block
'
active
=
true
}
const
reset
=
()
=>
{
if
(
!
active
)
{
return
}
elStyle
.
position
=
''
placeholder
.
style
.
display
=
'
none
'
active
=
false
}
const
check
=
()
=>
{
const
scrollTop
=
getScroll
(
window
,
true
)
const
offsetTop
=
el
.
getBoundingClientRect
().
top
if
(
offsetTop
<
stickyTop
)
{
sticky
()
}
else
{
if
(
scrollTop
<
elHeight
+
stickyTop
)
{
reset
()
}
}
}
listenAction
=
()
=>
{
check
()
}
window
.
addEventListener
(
'
scroll
'
,
listenAction
)
},
unbind
()
{
window
.
removeEventListener
(
'
scroll
'
,
listenAction
)
}
})
}
export
default
vueSticky
litemall-admin/src/directive/waves/index.js
0 → 100644
View file @
6c14c43c
import
waves
from
'
./waves
'
const
install
=
function
(
Vue
)
{
Vue
.
directive
(
'
waves
'
,
waves
)
}
if
(
window
.
Vue
)
{
window
.
waves
=
waves
Vue
.
use
(
install
);
// eslint-disable-line
}
waves
.
install
=
install
export
default
waves
litemall-admin/src/directive/waves/waves.css
0 → 100644
View file @
6c14c43c
.waves-ripple
{
position
:
absolute
;
border-radius
:
100%
;
background-color
:
rgba
(
0
,
0
,
0
,
0.15
);
background-clip
:
padding-box
;
pointer-events
:
none
;
-webkit-user-select
:
none
;
-moz-user-select
:
none
;
-ms-user-select
:
none
;
user-select
:
none
;
-webkit-transform
:
scale
(
0
);
-ms-transform
:
scale
(
0
);
transform
:
scale
(
0
);
opacity
:
1
;
}
.waves-ripple.z-active
{
opacity
:
0
;
-webkit-transform
:
scale
(
2
);
-ms-transform
:
scale
(
2
);
transform
:
scale
(
2
);
-webkit-transition
:
opacity
1.2s
ease-out
,
-webkit-transform
0.6s
ease-out
;
transition
:
opacity
1.2s
ease-out
,
-webkit-transform
0.6s
ease-out
;
transition
:
opacity
1.2s
ease-out
,
transform
0.6s
ease-out
;
transition
:
opacity
1.2s
ease-out
,
transform
0.6s
ease-out
,
-webkit-transform
0.6s
ease-out
;
}
\ No newline at end of file
litemall-admin/src/directive/waves/waves.js
0 → 100644
View file @
6c14c43c
import
'
./waves.css
'
export
default
{
bind
(
el
,
binding
)
{
el
.
addEventListener
(
'
click
'
,
e
=>
{
const
customOpts
=
Object
.
assign
({},
binding
.
value
)
const
opts
=
Object
.
assign
({
ele
:
el
,
// 波纹作用元素
type
:
'
hit
'
,
// hit点击位置扩散center中心点扩展
color
:
'
rgba(0, 0, 0, 0.15)
'
// 波纹颜色
},
customOpts
)
const
target
=
opts
.
ele
if
(
target
)
{
target
.
style
.
position
=
'
relative
'
target
.
style
.
overflow
=
'
hidden
'
const
rect
=
target
.
getBoundingClientRect
()
let
ripple
=
target
.
querySelector
(
'
.waves-ripple
'
)
if
(
!
ripple
)
{
ripple
=
document
.
createElement
(
'
span
'
)
ripple
.
className
=
'
waves-ripple
'
ripple
.
style
.
height
=
ripple
.
style
.
width
=
Math
.
max
(
rect
.
width
,
rect
.
height
)
+
'
px
'
target
.
appendChild
(
ripple
)
}
else
{
ripple
.
className
=
'
waves-ripple
'
}
switch
(
opts
.
type
)
{
case
'
center
'
:
ripple
.
style
.
top
=
(
rect
.
height
/
2
-
ripple
.
offsetHeight
/
2
)
+
'
px
'
ripple
.
style
.
left
=
(
rect
.
width
/
2
-
ripple
.
offsetWidth
/
2
)
+
'
px
'
break
default
:
ripple
.
style
.
top
=
(
e
.
pageY
-
rect
.
top
-
ripple
.
offsetHeight
/
2
-
document
.
body
.
scrollTop
)
+
'
px
'
ripple
.
style
.
left
=
(
e
.
pageX
-
rect
.
left
-
ripple
.
offsetWidth
/
2
-
document
.
body
.
scrollLeft
)
+
'
px
'
}
ripple
.
style
.
backgroundColor
=
opts
.
color
ripple
.
className
=
'
waves-ripple z-active
'
return
false
}
},
false
)
}
}
Prev
1
…
3
4
5
6
7
8
9
10
11
…
18
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