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
6f0ebe3e
Commit
6f0ebe3e
authored
Nov 17, 2018
by
Junling Bu
Browse files
chore[litemall-admin]: 管理后台基于的vue-element-admin框架更新至3.9.3
parent
cffdc561
Changes
156
Show whitespace changes
Inline
Side-by-side
litemall-admin/src/styles/element-ui.scss
View file @
6f0ebe3e
...
...
@@ -44,7 +44,7 @@
}
}
//暂时性解决di
ola
g 问题 https://github.com/ElemeFE/element/issues/2461
//暂时性解决di
alo
g 问题 https://github.com/ElemeFE/element/issues/2461
.el-dialog
{
transform
:
none
;
left
:
0
;
...
...
@@ -52,6 +52,17 @@
margin
:
0
auto
;
}
//文章页textarea修改样式
.article-textarea
{
textarea
{
padding-right
:
40px
;
resize
:
none
;
border
:
none
;
border-radius
:
0px
;
border-bottom
:
1px
solid
#bfcbd9
;
}
}
//element ui upload
.upload-container
{
.el-upload
{
...
...
@@ -62,3 +73,10 @@
}
}
}
//dropdown
.el-dropdown-menu
{
a
{
display
:
block
}
}
litemall-admin/src/styles/sidebar.scss
View file @
6f0ebe3e
...
...
@@ -2,99 +2,132 @@
// 主体区域
.main-container
{
min-height
:
100%
;
transition
:
margin-left
0
.28s
;
transition
:
margin-left
.28s
;
margin-left
:
180px
;
}
// 侧边栏
position
:
relative
;
}
// 侧边栏
.sidebar-container
{
transition
:
width
0
.28s
;
width
:
180px
!
important
;
width
:
180px
!
important
;
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__view
{
height
:
100%
;
}
}
.el-scrollbar__bar.is-vertical
{
right
:
0px
;
}
.is-horizontal
{
display
:
none
;
}
a
{
display
:
inline-block
;
width
:
100%
;
overflow
:
hidden
;
}
.svg-icon
{
margin-right
:
16px
;
}
.el-menu
{
border
:
none
;
width
:
100%
;
height
:
100%
;
width
:
100%
!
important
;
}
.is-active
>
.el-submenu__title
{
color
:
#f4f4f5
!
important
;
}
}
.hideSidebar
{
.sidebar-container
,
.sidebar-container
.el-menu
{
width
:
36px
!
important
;
// overflow: inherit;
.sidebar-container
{
width
:
36px
!
important
;
}
.main-container
{
margin-left
:
36px
;
}
}
.hideSidebar
{
.submenu-title-noDropdown
{
padding-left
:
10px
!
important
;
padding-left
:
10px
!
important
;
position
:
relative
;
span
{
.el-tooltip
{
padding
:
0
10px
!
important
;
}
}
.el-submenu
{
overflow
:
hidden
;
&
>
.el-submenu__title
{
padding-left
:
10px
!
important
;
.el-submenu__icon-arrow
{
display
:
none
;
}
}
}
.el-menu--collapse
{
.el-submenu
{
&
>
.el-submenu__title
{
&
>
span
{
height
:
0
;
width
:
0
;
overflow
:
hidden
;
visibility
:
hidden
;
transition
:
opacity
.3s
cubic-bezier
(
.55
,
0
,
.1
,
1
);
opacity
:
0
;
display
:
inline-block
;
}
&
:hover
{
span
{
display
:
block
;
border-radius
:
3px
;
z-index
:
1002
;
width
:
140px
;
height
:
56px
;
visibility
:
visible
;
position
:
absolute
;
right
:
-145px
;
text-align
:
left
;
text-indent
:
20px
;
top
:
0px
;
background-color
:
$subMenuBg
!
important
;
opacity
:
1
;
}
}
}
.el-submenu
{
&
>
.el-submenu__title
{
padding-left
:
10px
!
important
;
&
>
span
{
display
:
none
;
}
.el-submenu__icon-arrow
{
display
:
none
;
.sidebar-container
.nest-menu
.el-submenu
>
.el-submenu__title
,
.sidebar-container
.el-submenu
.el-menu-item
{
min-width
:
180px
!
important
;
background-color
:
$subMenuBg
!
important
;
&
:hover
{
background-color
:
$menuHover
!
important
;
}
}
.nest-menu
{
.el-submenu__icon-arrow
{
display
:
block
!
important
;
.el-menu--collapse
.el-menu
.el-submenu
{
min-width
:
180px
!
important
;
}
//适配移动端
.mobile
{
.main-container
{
margin-left
:
0px
;
}
.sidebar-container
{
transition
:
transform
.28s
;
width
:
180px
!
important
;
}
span
{
display
:
inline-block
!
important
;
&
.hideSidebar
{
.sidebar-container
{
transition-duration
:
0
.3s
;
transform
:
translate3d
(
-180px
,
0
,
0
);
}
}
}
.withoutAnimation
{
.main-container
,
.sidebar-container
{
transition
:
none
;
}
.nest-menu
.el-submenu
>
.el-submenu__title
,
.el-submenu
.el-menu-item
{
min-width
:
180px
!
important
;
background-color
:
$subMenuBg
!
important
;
&
:hover
{
background-color
:
$menuHover
!
important
;
}
}
.el-menu--vertical
{
&
>
.el-menu
{
.svg-icon
{
margin-right
:
16px
;
}
.el-menu--collapse
.el-menu
.el-submenu
{
min-width
:
180px
!
important
;
}
}
litemall-admin/src/styles/transition.scss
View file @
6f0ebe3e
...
...
@@ -11,7 +11,21 @@
opacity
:
0
;
}
/*fade*/
/*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
;
...
...
litemall-admin/src/utils/clipboard.js
0 → 100644
View file @
6f0ebe3e
import
Vue
from
'
vue
'
import
Clipboard
from
'
clipboard
'
function
clipboardSuccess
()
{
Vue
.
prototype
.
$message
({
message
:
'
Copy successfully
'
,
type
:
'
success
'
,
duration
:
1500
})
}
function
clipboardError
()
{
Vue
.
prototype
.
$message
({
message
:
'
Copy failed
'
,
type
:
'
error
'
})
}
export
default
function
handleClipboard
(
text
,
event
)
{
const
clipboard
=
new
Clipboard
(
event
.
target
,
{
text
:
()
=>
text
})
clipboard
.
on
(
'
success
'
,
()
=>
{
clipboardSuccess
()
clipboard
.
off
(
'
error
'
)
clipboard
.
off
(
'
success
'
)
clipboard
.
destroy
()
})
clipboard
.
on
(
'
error
'
,
()
=>
{
clipboardError
()
clipboard
.
off
(
'
error
'
)
clipboard
.
off
(
'
success
'
)
clipboard
.
destroy
()
})
clipboard
.
onClick
(
event
)
}
litemall-admin/src/utils/createUniqueString.js
0 → 100644
View file @
6f0ebe3e
/**
* Created by jiachenpan on 17/3/8.
*/
export
default
function
createUniqueString
()
{
const
timestamp
=
+
new
Date
()
+
''
const
randomNum
=
parseInt
((
1
+
Math
.
random
())
*
65536
)
+
''
return
(
+
(
randomNum
+
timestamp
)).
toString
(
32
)
}
litemall-admin/src/utils/i18n.js
0 → 100644
View file @
6f0ebe3e
// translate router.meta.title, be used in breadcrumb sidebar tagsview
export
function
generateTitle
(
title
)
{
const
hasKey
=
this
.
$te
(
'
route.
'
+
title
)
if
(
hasKey
)
{
// $t :this method from vue-i18n, inject in @/lang/index.js
const
translatedTitle
=
this
.
$t
(
'
route.
'
+
title
)
return
translatedTitle
}
return
title
}
litemall-admin/src/utils/index.js
View file @
6f0ebe3e
...
...
@@ -25,7 +25,8 @@ export function parseTime(time, cFormat) {
}
const
time_str
=
format
.
replace
(
/{
(
y|m|d|h|i|s|a
)
+}/g
,
(
result
,
key
)
=>
{
let
value
=
formatObj
[
key
]
if
(
key
===
'
a
'
)
return
[
'
一
'
,
'
二
'
,
'
三
'
,
'
四
'
,
'
五
'
,
'
六
'
,
'
日
'
][
value
-
1
]
// Note: getDay() returns 0 on Sunday
if
(
key
===
'
a
'
)
{
return
[
'
日
'
,
'
一
'
,
'
二
'
,
'
三
'
,
'
四
'
,
'
五
'
,
'
六
'
][
value
]
}
if
(
result
.
length
>
0
&&
value
<
10
)
{
value
=
'
0
'
+
value
}
...
...
@@ -43,7 +44,8 @@ export function formatTime(time, option) {
if
(
diff
<
30
)
{
return
'
刚刚
'
}
else
if
(
diff
<
3600
)
{
// less 1 hour
}
else
if
(
diff
<
3600
)
{
// less 1 hour
return
Math
.
ceil
(
diff
/
60
)
+
'
分钟前
'
}
else
if
(
diff
<
3600
*
24
)
{
return
Math
.
ceil
(
diff
/
3600
)
+
'
小时前
'
...
...
@@ -53,7 +55,17 @@ export function formatTime(time, option) {
if
(
option
)
{
return
parseTime
(
time
,
option
)
}
else
{
return
d
.
getMonth
()
+
1
+
'
月
'
+
d
.
getDate
()
+
'
日
'
+
d
.
getHours
()
+
'
时
'
+
d
.
getMinutes
()
+
'
分
'
return
(
d
.
getMonth
()
+
1
+
'
月
'
+
d
.
getDate
()
+
'
日
'
+
d
.
getHours
()
+
'
时
'
+
d
.
getMinutes
()
+
'
分
'
)
}
}
...
...
@@ -81,9 +93,11 @@ export function getQueryObject(url) {
export
function
getByteLen
(
val
)
{
let
len
=
0
for
(
let
i
=
0
;
i
<
val
.
length
;
i
++
)
{
if
(
val
[
i
].
match
(
/
[^\x
00-
\x
ff
]
/
i
g
)
!=
null
)
{
if
(
val
[
i
].
match
(
/
[^\x
00-
\x
ff
]
/g
i
)
!=
null
)
{
len
+=
1
}
else
{
len
+=
0.5
}
}
else
{
len
+=
0.5
}
}
return
Math
.
floor
(
len
)
}
...
...
@@ -100,11 +114,12 @@ export function cleanArray(actual) {
export
function
param
(
json
)
{
if
(
!
json
)
return
''
return
cleanArray
(
Object
.
keys
(
json
).
map
(
key
=>
{
return
cleanArray
(
Object
.
keys
(
json
).
map
(
key
=>
{
if
(
json
[
key
]
===
undefined
)
return
''
return
encodeURIComponent
(
key
)
+
'
=
'
+
encodeURIComponent
(
json
[
key
]
)
})
).
join
(
'
&
'
)
return
encodeURIComponent
(
key
)
+
'
=
'
+
encodeURIComponent
(
json
[
key
])
}
)
).
join
(
'
&
'
)
}
export
function
param2Obj
(
url
)
{
...
...
@@ -112,7 +127,14 @@ export function param2Obj(url) {
if
(
!
search
)
{
return
{}
}
return
JSON
.
parse
(
'
{"
'
+
decodeURIComponent
(
search
).
replace
(
/"/g
,
'
\\
"
'
).
replace
(
/&/g
,
'
","
'
).
replace
(
/=/g
,
'
":"
'
)
+
'
"}
'
)
return
JSON
.
parse
(
'
{"
'
+
decodeURIComponent
(
search
)
.
replace
(
/"/g
,
'
\\
"
'
)
.
replace
(
/&/g
,
'
","
'
)
.
replace
(
/=/g
,
'
":"
'
)
+
'
"}
'
)
}
export
function
html2Text
(
val
)
{
...
...
@@ -131,31 +153,17 @@ export function objectMerge(target, source) {
if
(
Array
.
isArray
(
source
))
{
return
source
.
slice
()
}
for
(
const
property
in
source
)
{
if
(
source
.
hasOwnProperty
(
property
))
{
Object
.
keys
(
source
).
forEach
(
property
=>
{
const
sourceProperty
=
source
[
property
]
if
(
typeof
sourceProperty
===
'
object
'
)
{
target
[
property
]
=
objectMerge
(
target
[
property
],
sourceProperty
)
continue
}
}
else
{
target
[
property
]
=
sourceProperty
}
}
}
)
return
target
}
export
function
scrollTo
(
element
,
to
,
duration
)
{
if
(
duration
<=
0
)
return
const
difference
=
to
-
element
.
scrollTop
const
perTick
=
difference
/
duration
*
10
setTimeout
(()
=>
{
console
.
log
(
new
Date
())
element
.
scrollTop
=
element
.
scrollTop
+
perTick
if
(
element
.
scrollTop
===
to
)
return
scrollTo
(
element
,
to
,
duration
-
10
)
},
10
)
}
export
function
toggleClass
(
element
,
className
)
{
if
(
!
element
||
!
className
)
{
return
...
...
@@ -165,7 +173,9 @@ export function toggleClass(element, className) {
if
(
nameIndex
===
-
1
)
{
classString
+=
''
+
className
}
else
{
classString
=
classString
.
substr
(
0
,
nameIndex
)
+
classString
.
substr
(
nameIndex
+
className
.
length
)
classString
=
classString
.
substr
(
0
,
nameIndex
)
+
classString
.
substr
(
nameIndex
+
className
.
length
)
}
element
.
className
=
classString
}
...
...
@@ -179,7 +189,8 @@ export const pickerOptions = [
end
.
setTime
(
start
.
getTime
())
picker
.
$emit
(
'
pick
'
,
[
start
,
end
])
}
},
{
},
{
text
:
'
最近一周
'
,
onClick
(
picker
)
{
const
end
=
new
Date
(
new
Date
().
toDateString
())
...
...
@@ -187,7 +198,8 @@ export const pickerOptions = [
start
.
setTime
(
end
.
getTime
()
-
3600
*
1000
*
24
*
7
)
picker
.
$emit
(
'
pick
'
,
[
start
,
end
])
}
},
{
},
{
text
:
'
最近一个月
'
,
onClick
(
picker
)
{
const
end
=
new
Date
(
new
Date
().
toDateString
())
...
...
@@ -195,7 +207,8 @@ export const pickerOptions = [
start
.
setTime
(
start
.
getTime
()
-
3600
*
1000
*
24
*
30
)
picker
.
$emit
(
'
pick
'
,
[
start
,
end
])
}
},
{
},
{
text
:
'
最近三个月
'
,
onClick
(
picker
)
{
const
end
=
new
Date
(
new
Date
().
toDateString
())
...
...
@@ -203,7 +216,8 @@ export const pickerOptions = [
start
.
setTime
(
start
.
getTime
()
-
3600
*
1000
*
24
*
90
)
picker
.
$emit
(
'
pick
'
,
[
start
,
end
])
}
}]
}
]
export
function
getTime
(
type
)
{
if
(
type
===
'
start
'
)
{
...
...
@@ -248,20 +262,30 @@ export function debounce(func, wait, immediate) {
}
}
/**
* This is just a simple version of deep copy
* Has a lot of edge cases bug
* If you want to use a perfect deep copy, use lodash's _.cloneDeep
*/
export
function
deepClone
(
source
)
{
if
(
!
source
&&
typeof
source
!==
'
object
'
)
{
throw
new
Error
(
'
error arguments
'
,
'
shallowClone
'
)
}
const
targetObj
=
source
.
constructor
===
Array
?
[]
:
{}
for
(
const
keys
in
source
)
{
if
(
source
.
hasOwnProperty
(
keys
))
{
Object
.
keys
(
source
).
forEach
(
keys
=>
{
if
(
source
[
keys
]
&&
typeof
source
[
keys
]
===
'
object
'
)
{
targetObj
[
keys
]
=
source
[
keys
].
constructor
===
Array
?
[]
:
{}
targetObj
[
keys
]
=
deepClone
(
source
[
keys
])
}
else
{
targetObj
[
keys
]
=
source
[
keys
]
}
}
}
})
return
targetObj
}
export
function
uniqueArr
(
arr
)
{
return
Array
.
from
(
new
Set
(
arr
))
}
export
function
isExternal
(
path
)
{
return
/^
(
https
?
:|mailto:|tel:
)
/
.
test
(
path
)
}
litemall-admin/src/utils/permission.js
0 → 100644
View file @
6f0ebe3e
import
store
from
'
@/store
'
/**
* @param {Array} value
* @returns {Boolean}
* @example see @/views/permission/directive.vue
*/
export
default
function
checkPermission
(
value
)
{
if
(
value
&&
value
instanceof
Array
&&
value
.
length
>
0
)
{
const
roles
=
store
.
getters
&&
store
.
getters
.
roles
const
permissionRoles
=
value
const
hasPermission
=
roles
.
some
(
role
=>
{
return
permissionRoles
.
includes
(
role
)
})
if
(
!
hasPermission
)
{
return
false
}
return
true
}
else
{
console
.
error
(
`need roles! Like v-permission="['admin','editor']"`
)
return
false
}
}
litemall-admin/src/utils/request.js
View file @
6f0ebe3e
...
...
@@ -5,24 +5,28 @@ import { getToken } from '@/utils/auth'
// create an axios instance
const
service
=
axios
.
create
({
baseURL
:
process
.
env
.
BASE_API
,
// api
的
base_url
baseURL
:
process
.
env
.
BASE_API
,
// api
的
base_url
timeout
:
5000
// request timeout
})
// request interceptor
service
.
interceptors
.
request
.
use
(
config
=>
{
service
.
interceptors
.
request
.
use
(
config
=>
{
// Do something before request is sent
if
(
store
.
getters
.
token
)
{
config
.
headers
[
'
Admin-Token
'
]
=
getToken
()
// 让每个请求携带token-- ['Admin-Token']为自定义key 请根据实际情况自行修改
// 让每个请求携带token-- ['Admin-Token']为自定义key 请根据实际情况自行修改
config
.
headers
[
'
Admin-Token
'
]
=
getToken
()
}
return
config
},
error
=>
{
},
error
=>
{
// Do something with request error
console
.
log
(
error
)
// for debug
Promise
.
reject
(
error
)
})
}
)
// respone interceptor
// respon
s
e interceptor
service
.
interceptors
.
response
.
use
(
response
=>
{
const
res
=
response
.
data
...
...
litemall-admin/src/utils/scrollTo.js
0 → 100644
View file @
6f0ebe3e
Math
.
easeInOutQuad
=
function
(
t
,
b
,
c
,
d
)
{
t
/=
d
/
2
if
(
t
<
1
)
{
return
c
/
2
*
t
*
t
+
b
}
t
--
return
-
c
/
2
*
(
t
*
(
t
-
2
)
-
1
)
+
b
}
// requestAnimationFrame for Smart Animating http://goo.gl/sx5sts
var
requestAnimFrame
=
(
function
()
{
return
window
.
requestAnimationFrame
||
window
.
webkitRequestAnimationFrame
||
window
.
mozRequestAnimationFrame
||
function
(
callback
)
{
window
.
setTimeout
(
callback
,
1000
/
60
)
}
})()
// because it's so fucking difficult to detect the scrolling element, just move them all
function
move
(
amount
)
{
document
.
documentElement
.
scrollTop
=
amount
document
.
body
.
parentNode
.
scrollTop
=
amount
document
.
body
.
scrollTop
=
amount
}
function
position
()
{
return
document
.
documentElement
.
scrollTop
||
document
.
body
.
parentNode
.
scrollTop
||
document
.
body
.
scrollTop
}
export
function
scrollTo
(
to
,
duration
,
callback
)
{
const
start
=
position
()
const
change
=
to
-
start
const
increment
=
20
let
currentTime
=
0
duration
=
(
typeof
(
duration
)
===
'
undefined
'
)
?
500
:
duration
var
animateScroll
=
function
()
{
// increment the time
currentTime
+=
increment
// find the value with the quadratic in-out easing function
var
val
=
Math
.
easeInOutQuad
(
currentTime
,
start
,
change
,
duration
)
// move the document.body
move
(
val
)
// do the animation unless its over
if
(
currentTime
<
duration
)
{
requestAnimFrame
(
animateScroll
)
}
else
{
if
(
callback
&&
typeof
(
callback
)
===
'
function
'
)
{
// the animation is done so lets callback
callback
()
}
}
}
animateScroll
()
}
litemall-admin/src/utils/validate.js
View file @
6f0ebe3e
...
...
@@ -2,6 +2,11 @@
* Created by jiachenpan on 16/11/18.
*/
export
function
isvalidUsername
(
str
)
{
const
valid_map
=
[
'
admin
'
,
'
editor
'
]
return
valid_map
.
indexOf
(
str
.
trim
())
>=
0
}
/* 合法uri*/
export
function
validateURL
(
textval
)
{
const
urlregex
=
/^
(
https
?
|ftp
)
:
\/\/([
a-zA-Z0-9.-
]
+
(
:
[
a-zA-Z0-9.&%$-
]
+
)
*@
)
*
((
25
[
0-5
]
|2
[
0-4
][
0-9
]
|1
[
0-9
]{2}
|
[
1-9
][
0-9
]?)(\.(
25
[
0-5
]
|2
[
0-4
][
0-9
]
|1
[
0-9
]{2}
|
[
1-9
]?[
0-9
])){3}
|
([
a-zA-Z0-9-
]
+
\.)
*
[
a-zA-Z0-9-
]
+
\.(
com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|
[
a-zA-Z
]{2}))(
:
[
0-9
]
+
)
*
(\/(
$|
[
a-zA-Z0-9.,?'
\\
+&%$#=~_-
]
+
))
*$/
...
...
@@ -21,7 +26,7 @@ export function validateUpperCase(str) {
}
/* 大小写字母*/
export
function
validatAlphabets
(
str
)
{
export
function
validat
e
Alphabets
(
str
)
{
const
reg
=
/^
[
A-Za-z
]
+$/
return
reg
.
test
(
str
)
}
...
...
@@ -35,4 +40,3 @@ export function validateEmail(email) {
const
re
=
/^
(([^
<>()
\[\]\\
.,;:
\s
@"
]
+
(\.[^
<>()
\[\]\\
.,;:
\s
@"
]
+
)
*
)
|
(
".+"
))
@
((\[[
0-9
]{1,3}\.[
0-9
]{1,3}\.[
0-9
]{1,3}\.[
0-9
]{1,3}\])
|
(([
a-zA-Z
\-
0-9
]
+
\.)
+
[
a-zA-Z
]{2,}))
$/
return
re
.
test
(
email
)
}
litemall-admin/src/vendor/Blob.js
deleted
100644 → 0
View file @
cffdc561
/* eslint-disable */
/* Blob.js
* A Blob implementation.
* 2014-05-27
*
* By Eli Grey, http://eligrey.com
* By Devin Samarin, https://github.com/eboyjr
* License: X11/MIT
* See LICENSE.md
*/
/*global self, unescape */
/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
plusplus: true */
/*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */
(
function
(
view
)
{
"
use strict
"
;
view
.
URL
=
view
.
URL
||
view
.
webkitURL
;
if
(
view
.
Blob
&&
view
.
URL
)
{
try
{
new
Blob
;
return
;
}
catch
(
e
)
{}
}
// Internally we use a BlobBuilder implementation to base Blob off of
// in order to support older browsers that only have BlobBuilder
var
BlobBuilder
=
view
.
BlobBuilder
||
view
.
WebKitBlobBuilder
||
view
.
MozBlobBuilder
||
(
function
(
view
)
{
var
get_class
=
function
(
object
)
{
return
Object
.
prototype
.
toString
.
call
(
object
).
match
(
/^
\[
object
\s(
.*
)\]
$/
)[
1
];
}
,
FakeBlobBuilder
=
function
BlobBuilder
()
{
this
.
data
=
[];
}
,
FakeBlob
=
function
Blob
(
data
,
type
,
encoding
)
{
this
.
data
=
data
;
this
.
size
=
data
.
length
;
this
.
type
=
type
;
this
.
encoding
=
encoding
;
}
,
FBB_proto
=
FakeBlobBuilder
.
prototype
,
FB_proto
=
FakeBlob
.
prototype
,
FileReaderSync
=
view
.
FileReaderSync
,
FileException
=
function
(
type
)
{
this
.
code
=
this
[
this
.
name
=
type
];
}
,
file_ex_codes
=
(
"
NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR
"
+
"
NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR
"
).
split
(
"
"
)
,
file_ex_code
=
file_ex_codes
.
length
,
real_URL
=
view
.
URL
||
view
.
webkitURL
||
view
,
real_create_object_URL
=
real_URL
.
createObjectURL
,
real_revoke_object_URL
=
real_URL
.
revokeObjectURL
,
URL
=
real_URL
,
btoa
=
view
.
btoa
,
atob
=
view
.
atob
,
ArrayBuffer
=
view
.
ArrayBuffer
,
Uint8Array
=
view
.
Uint8Array
;
FakeBlob
.
fake
=
FB_proto
.
fake
=
true
;
while
(
file_ex_code
--
)
{
FileException
.
prototype
[
file_ex_codes
[
file_ex_code
]]
=
file_ex_code
+
1
;
}
if
(
!
real_URL
.
createObjectURL
)
{
URL
=
view
.
URL
=
{};
}
URL
.
createObjectURL
=
function
(
blob
)
{
var
type
=
blob
.
type
,
data_URI_header
;
if
(
type
===
null
)
{
type
=
"
application/octet-stream
"
;
}
if
(
blob
instanceof
FakeBlob
)
{
data_URI_header
=
"
data:
"
+
type
;
if
(
blob
.
encoding
===
"
base64
"
)
{
return
data_URI_header
+
"
;base64,
"
+
blob
.
data
;
}
else
if
(
blob
.
encoding
===
"
URI
"
)
{
return
data_URI_header
+
"
,
"
+
decodeURIComponent
(
blob
.
data
);
}
if
(
btoa
)
{
return
data_URI_header
+
"
;base64,
"
+
btoa
(
blob
.
data
);
}
else
{
return
data_URI_header
+
"
,
"
+
encodeURIComponent
(
blob
.
data
);
}
}
else
if
(
real_create_object_URL
)
{
return
real_create_object_URL
.
call
(
real_URL
,
blob
);
}
};
URL
.
revokeObjectURL
=
function
(
object_URL
)
{
if
(
object_URL
.
substring
(
0
,
5
)
!==
"
data:
"
&&
real_revoke_object_URL
)
{
real_revoke_object_URL
.
call
(
real_URL
,
object_URL
);
}
};
FBB_proto
.
append
=
function
(
data
/*, endings*/
)
{
var
bb
=
this
.
data
;
// decode data to a binary string
if
(
Uint8Array
&&
(
data
instanceof
ArrayBuffer
||
data
instanceof
Uint8Array
))
{
var
str
=
""
,
buf
=
new
Uint8Array
(
data
)
,
i
=
0
,
buf_len
=
buf
.
length
;
for
(;
i
<
buf_len
;
i
++
)
{
str
+=
String
.
fromCharCode
(
buf
[
i
]);
}
bb
.
push
(
str
);
}
else
if
(
get_class
(
data
)
===
"
Blob
"
||
get_class
(
data
)
===
"
File
"
)
{
if
(
FileReaderSync
)
{
var
fr
=
new
FileReaderSync
;
bb
.
push
(
fr
.
readAsBinaryString
(
data
));
}
else
{
// async FileReader won't work as BlobBuilder is sync
throw
new
FileException
(
"
NOT_READABLE_ERR
"
);
}
}
else
if
(
data
instanceof
FakeBlob
)
{
if
(
data
.
encoding
===
"
base64
"
&&
atob
)
{
bb
.
push
(
atob
(
data
.
data
));
}
else
if
(
data
.
encoding
===
"
URI
"
)
{
bb
.
push
(
decodeURIComponent
(
data
.
data
));
}
else
if
(
data
.
encoding
===
"
raw
"
)
{
bb
.
push
(
data
.
data
);
}
}
else
{
if
(
typeof
data
!==
"
string
"
)
{
data
+=
""
;
// convert unsupported types to strings
}
// decode UTF-16 to binary string
bb
.
push
(
unescape
(
encodeURIComponent
(
data
)));
}
};
FBB_proto
.
getBlob
=
function
(
type
)
{
if
(
!
arguments
.
length
)
{
type
=
null
;
}
return
new
FakeBlob
(
this
.
data
.
join
(
""
),
type
,
"
raw
"
);
};
FBB_proto
.
toString
=
function
()
{
return
"
[object BlobBuilder]
"
;
};
FB_proto
.
slice
=
function
(
start
,
end
,
type
)
{
var
args
=
arguments
.
length
;
if
(
args
<
3
)
{
type
=
null
;
}
return
new
FakeBlob
(
this
.
data
.
slice
(
start
,
args
>
1
?
end
:
this
.
data
.
length
)
,
type
,
this
.
encoding
);
};
FB_proto
.
toString
=
function
()
{
return
"
[object Blob]
"
;
};
FB_proto
.
close
=
function
()
{
this
.
size
=
this
.
data
.
length
=
0
;
};
return
FakeBlobBuilder
;
}(
view
));
view
.
Blob
=
function
Blob
(
blobParts
,
options
)
{
var
type
=
options
?
(
options
.
type
||
""
)
:
""
;
var
builder
=
new
BlobBuilder
();
if
(
blobParts
)
{
for
(
var
i
=
0
,
len
=
blobParts
.
length
;
i
<
len
;
i
++
)
{
builder
.
append
(
blobParts
[
i
]);
}
}
return
builder
.
getBlob
(
type
);
};
}(
typeof
self
!==
"
undefined
"
&&
self
||
typeof
window
!==
"
undefined
"
&&
window
||
this
.
content
||
this
));
litemall-admin/src/vendor/Export2Excel.js
View file @
6f0ebe3e
/* eslint-disable */
require
(
'
script-loader!file-saver
'
);
require
(
'
script-loader!@/vendor/Blob
'
);
import
XLSX
from
'
xlsx
'
function
generateArray
(
table
)
{
...
...
@@ -29,15 +28,24 @@ function generateArray(table) {
if
(
rowspan
||
colspan
)
{
rowspan
=
rowspan
||
1
;
colspan
=
colspan
||
1
;
ranges
.
push
({
s
:
{
r
:
R
,
c
:
outRow
.
length
},
e
:
{
r
:
R
+
rowspan
-
1
,
c
:
outRow
.
length
+
colspan
-
1
}});
ranges
.
push
({
s
:
{
r
:
R
,
c
:
outRow
.
length
},
e
:
{
r
:
R
+
rowspan
-
1
,
c
:
outRow
.
length
+
colspan
-
1
}
;
});
};
//Handle Value
outRow
.
push
(
cellValue
!==
""
?
cellValue
:
null
);
//Handle Colspan
if
(
colspan
)
for
(
var
k
=
0
;
k
<
colspan
-
1
;
++
k
)
outRow
.
push
(
null
);
if
(
colspan
)
for
(
var
k
=
0
;
k
<
colspan
-
1
;
++
k
)
outRow
.
push
(
null
);
}
out
.
push
(
outRow
);
}
...
...
@@ -52,16 +60,30 @@ function datenum(v, date1904) {
function
sheet_from_array_of_arrays
(
data
,
opts
)
{
var
ws
=
{};
var
range
=
{
s
:
{
c
:
10000000
,
r
:
10000000
},
e
:
{
c
:
0
,
r
:
0
}};
var
range
=
{
s
:
{
c
:
10000000
,
r
:
10000000
},
e
:
{
c
:
0
,
r
:
0
}
};
for
(
var
R
=
0
;
R
!=
data
.
length
;
++
R
)
{
for
(
var
C
=
0
;
C
!=
data
[
R
].
length
;
++
C
)
{
if
(
range
.
s
.
r
>
R
)
range
.
s
.
r
=
R
;
if
(
range
.
s
.
c
>
C
)
range
.
s
.
c
=
C
;
if
(
range
.
e
.
r
<
R
)
range
.
e
.
r
=
R
;
if
(
range
.
e
.
c
<
C
)
range
.
e
.
c
=
C
;
var
cell
=
{
v
:
data
[
R
][
C
]};
var
cell
=
{
v
:
data
[
R
][
C
]
};
if
(
cell
.
v
==
null
)
continue
;
var
cell_ref
=
XLSX
.
utils
.
encode_cell
({
c
:
C
,
r
:
R
});
var
cell_ref
=
XLSX
.
utils
.
encode_cell
({
c
:
C
,
r
:
R
});
if
(
typeof
cell
.
v
===
'
number
'
)
cell
.
t
=
'
n
'
;
else
if
(
typeof
cell
.
v
===
'
boolean
'
)
cell
.
t
=
'
b
'
;
...
...
@@ -69,8 +91,7 @@ function sheet_from_array_of_arrays(data, opts) {
cell
.
t
=
'
n
'
;
cell
.
z
=
XLSX
.
SSF
.
_table
[
14
];
cell
.
v
=
datenum
(
cell
.
v
);
}
else
cell
.
t
=
'
s
'
;
}
else
cell
.
t
=
'
s
'
;
ws
[
cell_ref
]
=
cell
;
}
...
...
@@ -101,7 +122,8 @@ export function export_table_to_excel(id) {
var
data
=
oo
[
0
];
var
ws_name
=
"
SheetJS
"
;
var
wb
=
new
Workbook
(),
ws
=
sheet_from_array_of_arrays
(
data
);
var
wb
=
new
Workbook
(),
ws
=
sheet_from_array_of_arrays
(
data
);
/* add ranges to worksheet */
// ws['!cols'] = ['apple', 'banan'];
...
...
@@ -111,32 +133,50 @@ export function export_table_to_excel(id) {
wb
.
SheetNames
.
push
(
ws_name
);
wb
.
Sheets
[
ws_name
]
=
ws
;
var
wbout
=
XLSX
.
write
(
wb
,
{
bookType
:
'
xlsx
'
,
bookSST
:
false
,
type
:
'
binary
'
});
var
wbout
=
XLSX
.
write
(
wb
,
{
bookType
:
'
xlsx
'
,
bookSST
:
false
,
type
:
'
binary
'
});
saveAs
(
new
Blob
([
s2ab
(
wbout
)],
{
type
:
"
application/octet-stream
"
}),
"
test.xlsx
"
)
saveAs
(
new
Blob
([
s2ab
(
wbout
)],
{
type
:
"
application/octet-stream
"
}),
"
test.xlsx
"
)
}
export
function
export_json_to_excel
(
th
,
jsonData
,
defaultTitle
)
{
export
function
export_json_to_excel
({
header
,
data
,
filename
,
autoWidth
=
true
,
bookType
=
'
xlsx
'
}
=
{})
{
/* original data */
var
data
=
jsonD
ata
;
data
.
unshift
(
t
h
);
filename
=
filename
||
'
excel-list
'
data
=
[...
d
ata
]
data
.
unshift
(
h
eader
);
var
ws_name
=
"
SheetJS
"
;
var
wb
=
new
Workbook
(),
ws
=
sheet_from_array_of_arrays
(
data
);
var
wb
=
new
Workbook
(),
ws
=
sheet_from_array_of_arrays
(
data
);
if
(
autoWidth
)
{
/*设置worksheet每列的最大宽度*/
const
colWidth
=
data
.
map
(
row
=>
row
.
map
(
val
=>
{
/*先判断是否为null/undefined*/
if
(
val
==
null
)
{
return
{
'
wch
'
:
10
};
return
{
'
wch
'
:
10
};
}
/*再判断是否为中文*/
else
if
(
val
.
toString
().
charCodeAt
(
0
)
>
255
)
{
return
{
'
wch
'
:
val
.
toString
().
length
*
2
};
return
{
'
wch
'
:
val
.
toString
().
length
*
2
};
}
else
{
return
{
'
wch
'
:
val
.
toString
().
length
};
return
{
'
wch
'
:
val
.
toString
().
length
};
}
}))
/*以第一行为初始值*/
...
...
@@ -149,14 +189,20 @@ export function export_json_to_excel(th, jsonData, defaultTitle) {
}
}
ws
[
'
!cols
'
]
=
result
;
}
/* add worksheet to workbook */
wb
.
SheetNames
.
push
(
ws_name
);
wb
.
Sheets
[
ws_name
]
=
ws
;
var
wbout
=
XLSX
.
write
(
wb
,
{
bookType
:
'
xlsx
'
,
bookSST
:
false
,
type
:
'
binary
'
});
var
title
=
defaultTitle
||
'
excel-list
'
saveAs
(
new
Blob
([
s2ab
(
wbout
)],
{
type
:
"
application/octet-stream
"
}),
title
+
"
.xlsx
"
)
var
wbout
=
XLSX
.
write
(
wb
,
{
bookType
:
bookType
,
bookSST
:
false
,
type
:
'
binary
'
});
saveAs
(
new
Blob
([
s2ab
(
wbout
)],
{
type
:
"
application/octet-stream
"
}),
`
${
filename
}
.
${
bookType
}
`
);
}
function
formatJson
(
jsonSource
,
jsonFillter
)
{
...
...
@@ -165,7 +211,7 @@ function formatJson(jsonSource, jsonFillter) {
}))
}
export
function
export_json_to_excel2
(
th
,
jsonSource
,
jsonFillter
,
defaultTitl
e
)
{
export
function
export_json_to_excel2
(
th
,
jsonSource
,
jsonFillter
,
nam
e
)
{
const
data
=
formatJson
(
jsonSource
,
jsonFillter
)
export_json_to_excel
(
th
,
data
,
defaultTitle
)
export_json_to_excel
(
{
header
:
th
,
data
,
filename
:
name
}
)
}
\ No newline at end of file
litemall-admin/src/vendor/Export2Zip.js
0 → 100644
View file @
6f0ebe3e
/* eslint-disable */
require
(
'
script-loader!file-saver
'
);
import
JSZip
from
'
jszip
'
export
function
export_txt_to_zip
(
th
,
jsonData
,
txtName
,
zipName
)
{
const
zip
=
new
JSZip
()
const
txt_name
=
txtName
||
'
file
'
const
zip_name
=
zipName
||
'
file
'
const
data
=
jsonData
let
txtData
=
`
${
th
}
\r\n`
data
.
forEach
((
row
)
=>
{
let
tempStr
=
''
tempStr
=
row
.
toString
()
txtData
+=
`
${
tempStr
}
\r\n`
})
zip
.
file
(
`
${
txt_name
}
.txt`
,
txtData
)
zip
.
generateAsync
({
type
:
"
blob
"
}).
then
((
blob
)
=>
{
saveAs
(
blob
,
`
${
zip_name
}
.zip`
)
},
(
err
)
=>
{
alert
(
'
导出失败
'
)
})
}
litemall-admin/src/views/dashboard/index.vue
View file @
6f0ebe3e
<
template
>
<el-row
class=
"panel-group"
:gutter=
"40"
>
<div
class=
"dashboard-editor-container"
>
<el-row
:gutter=
"40"
class=
"panel-group"
>
<el-col
:xs=
"12"
:sm=
"12"
:lg=
"6"
class=
"card-panel-col"
>
<div
class=
'
card-panel
'
@
click=
"handleSetLineChartData('newVisitis')"
>
<div
class=
"
card-panel
"
@
click=
"handleSetLineChartData('newVisitis')"
>
<div
class=
"card-panel-icon-wrapper icon-people"
>
<svg-icon
icon-class=
"peoples"
class-name=
"card-panel-icon"
/>
</div>
<div
class=
"card-panel-description"
>
<div
class=
"card-panel-text"
>
用户数量
</div>
<count-to
class=
"card-panel-num"
:start
V
al=
"0"
:end
V
al=
"userTotal"
:duration=
"2600"
></count-to
>
<count-to
:start
-v
al=
"0"
:end
-v
al=
"userTotal"
:duration=
"2600"
class=
"card-panel-num"
/
>
</div>
</div>
</el-col>
<el-col
:xs=
"12"
:sm=
"12"
:lg=
"6"
class=
"card-panel-col"
>
<div
class=
"card-panel"
@
click=
"handleSetLineChartData('messages')"
>
<div
class=
"card-panel-icon-wrapper icon-message"
>
<svg-icon
icon-class=
"
shoppingCard
"
class-name=
"card-panel-icon"
/>
<svg-icon
icon-class=
"
message
"
class-name=
"card-panel-icon"
/>
</div>
<div
class=
"card-panel-description"
>
<div
class=
"card-panel-text"
>
商品数量
</div>
<count-to
class=
"card-panel-num"
:start
V
al=
"0"
:end
V
al=
"goodsTotal"
:duration=
"3000"
></count-to
>
<count-to
:start
-v
al=
"0"
:end
-v
al=
"goodsTotal"
:duration=
"3000"
class=
"card-panel-num"
/
>
</div>
</div>
</el-col>
...
...
@@ -29,7 +31,7 @@
</div>
<div
class=
"card-panel-description"
>
<div
class=
"card-panel-text"
>
货品数量
</div>
<count-to
class=
"card-panel-num"
:start
V
al=
"0"
:end
V
al=
"productTotal"
:duration=
"3200"
></count-to
>
<count-to
:start
-v
al=
"0"
:end
-v
al=
"productTotal"
:duration=
"3200"
class=
"card-panel-num"
/
>
</div>
</div>
</el-col>
...
...
@@ -40,11 +42,12 @@
</div>
<div
class=
"card-panel-description"
>
<div
class=
"card-panel-text"
>
订单数量
</div>
<count-to
class=
"card-panel-num"
:start
V
al=
"0"
:end
V
al=
"orderTotal"
:duration=
"3600"
></count-to
>
<count-to
:start
-v
al=
"0"
:end
-v
al=
"orderTotal"
:duration=
"3600"
class=
"card-panel-num"
/
>
</div>
</div>
</el-col>
</el-row>
</div>
</
template
>
<
script
>
...
...
@@ -63,11 +66,6 @@ export default {
orderTotal
:
0
}
},
methods
:
{
handleSetLineChartData
(
type
)
{
this
.
$emit
(
'
handleSetLineChartData
'
,
type
)
}
},
created
()
{
info
(
this
.
listQuery
).
then
(
response
=>
{
this
.
userTotal
=
response
.
data
.
data
.
userTotal
...
...
@@ -75,11 +73,26 @@ export default {
this
.
productTotal
=
response
.
data
.
data
.
productTotal
this
.
orderTotal
=
response
.
data
.
data
.
orderTotal
})
},
methods
:
{
handleSetLineChartData
(
type
)
{
this
.
$emit
(
'
handleSetLineChartData
'
,
type
)
}
}
}
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
.dashboard-editor-container
{
padding
:
32px
;
background-color
:
rgb
(
240
,
242
,
245
);
.chart-wrapper
{
background
:
#fff
;
padding
:
16px
16px
0
;
margin-bottom
:
32px
;
}
}
.panel-group
{
margin-top
:
18px
;
...
...
litemall-admin/src/views/error/401.vue
→
litemall-admin/src/views/error
Page
/401.vue
View file @
6f0ebe3e
<
template
>
<div
class=
"errPage-container"
>
<el-button
@
click=
"back"
icon=
'
arrow-left
'
class=
"pan-back-btn"
>
返回
</el-button>
<el-button
icon=
"
arrow-left
"
class=
"pan-back-btn"
@
click=
"back"
>
返回
</el-button>
<el-row>
<el-col
:span=
"12"
>
<h1
class=
"text-jumbo text-ginormous"
>
Oops!
</h1>
gif来源
<a
href=
'
https://zh.airbnb.com/
'
target=
'
_blank
'
>
airbnb
</a>
页面
gif来源
<a
href=
"
https://zh.airbnb.com/
"
target=
"
_blank
"
>
airbnb
</a>
页面
<h2>
你没有权限去该页面
</h2>
<h6>
如有不满请联系你领导
</h6>
<ul
class=
"list-unstyled"
>
...
...
@@ -13,15 +13,15 @@
<router-link
to=
"/dashboard"
>
回首页
</router-link>
</li>
<li
class=
"link-type"
><a
href=
"https://www.taobao.com/"
>
随便看看
</a></li>
<li><a
@
click.prevent=
"dialogVisible=true"
href=
"#"
>
点我看图
</a></li>
<li><a
href=
"#"
@
click.prevent=
"dialogVisible=true"
>
点我看图
</a></li>
</ul>
</el-col>
<el-col
:span=
"12"
>
<img
:src=
"errGif"
width=
"313"
height=
"428"
alt=
"Girl has dropped her ice cream."
>
</el-col>
</el-row>
<el-dialog
title=
"随便看"
:visible.sync=
"dialogVisible"
>
<img
class=
"pan-img"
:src=
"ewizardClap"
>
<el-dialog
:visible.sync=
"dialogVisible"
title=
"随便看"
>
<img
:src=
"ewizardClap"
class=
"pan-img"
>
</el-dialog>
</div>
</
template
>
...
...
@@ -30,7 +30,7 @@
import
errGif
from
'
@/assets/401_images/401.gif
'
export
default
{
name
:
'
p
age401
'
,
name
:
'
P
age401
'
,
data
()
{
return
{
errGif
:
errGif
+
'
?
'
+
+
new
Date
(),
...
...
@@ -53,10 +53,12 @@ export default {
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
.errPage-container
{
width
:
800px
;
max-width
:
100%
;
margin
:
100px
auto
;
.pan-back-btn
{
background
:
#008489
;
color
:
#fff
;
border
:
none
!
important
;
}
.pan-gif
{
margin
:
0
auto
;
...
...
@@ -65,6 +67,7 @@ export default {
.pan-img
{
display
:
block
;
margin
:
0
auto
;
width
:
100%
;
}
.text-jumbo
{
font-size
:
60px
;
...
...
litemall-admin/src/views/error/404.vue
→
litemall-admin/src/views/error
Page
/404.vue
View file @
6f0ebe3e
<
template
>
<div
style=
"background:#f0f2f5;margin-top: -20px;height:100%;
"
>
<div
class=
"wscn-http404-container
"
>
<div
class=
"wscn-http404"
>
<div
class=
"pic-404"
>
<img
class=
"pic-404__parent"
:
src=
"
img_404
"
alt=
"404"
>
<img
class=
"pic-404__child left"
:
src=
"
img_
404_cloud"
alt=
"404"
>
<img
class=
"pic-404__child mid"
:
src=
"
img_
404_cloud"
alt=
"404"
>
<img
class=
"pic-404__child right"
:
src=
"
img_
404_cloud"
alt=
"404"
>
<img
class=
"pic-404__parent"
src=
"
@/assets/404_images/404.png
"
alt=
"404"
>
<img
class=
"pic-404__child left"
src=
"
@/assets/404_images/
404_cloud
.png
"
alt=
"404"
>
<img
class=
"pic-404__child mid"
src=
"
@/assets/404_images/
404_cloud
.png
"
alt=
"404"
>
<img
class=
"pic-404__child right"
src=
"
@/assets/404_images/
404_cloud
.png
"
alt=
"404"
>
</div>
<div
class=
"bullshit"
>
<div
class=
"bullshit__oops"
>
OOPS!
</div>
<div
class=
"bullshit__info"
>
版权所有
<a
class=
'
link-type
'
href=
'
https://wallstreetcn.com
'
target=
'
_blank
'
>
华尔街见闻
</a>
<a
class=
"
link-type
"
href=
"
https://wallstreetcn.com
"
target=
"
_blank
"
>
华尔街见闻
</a>
</div>
<div
class=
"bullshit__headline"
>
{{
message
}}
</div>
<div
class=
"bullshit__info"
>
请检查您输入的网址是否正确,请点击以下按钮返回主页或者发送错误报告
</div>
<a
href=
"
/
"
class=
"bullshit__return-home"
>
返回首页
</a>
<a
href=
""
class=
"bullshit__return-home"
>
返回首页
</a>
</div>
</div>
</div>
</
template
>
<
script
>
import
img_404
from
'
@/assets/404_images/404.png
'
import
img_404_cloud
from
'
@/assets/404_images/404_cloud.png
'
export
default
{
name
:
'
page404
'
,
data
()
{
return
{
img_404
,
img_404_cloud
}
},
name
:
'
Page404
'
,
computed
:
{
message
()
{
return
'
特朗普
说这个页面你不能进......
'
return
'
网管
说这个页面你不能进......
'
}
}
}
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scoped
>
.wscn-http404-container
{
transform
:
translate
(
-50%
,-
50%
);
position
:
absolute
;
top
:
40%
;
left
:
50%
;
}
.wscn-http404
{
position
:
relative
;
width
:
1200px
;
margin
:
20px
auto
60px
;
padding
:
0
100px
;
padding
:
0
50px
;
overflow
:
hidden
;
.pic-404
{
position
:
relative
;
float
:
left
;
width
:
600px
;
padding
:
150px
0
;
overflow
:
hidden
;
&
__parent
{
width
:
100%
;
...
...
@@ -163,7 +159,7 @@ export default {
position
:
relative
;
float
:
left
;
width
:
300px
;
padding
:
15
0px
0
;
padding
:
3
0px
0
;
overflow
:
hidden
;
&
__oops
{
font-size
:
32px
;
...
...
@@ -179,7 +175,8 @@ export default {
&
__headline
{
font-size
:
20px
;
line-height
:
24px
;
color
:
#1482f0
;
color
:
#222
;
font-weight
:
bold
;
opacity
:
0
;
margin-bottom
:
10px
;
animation-name
:
slideUp
;
...
...
litemall-admin/src/views/goods/comment.vue
View file @
6f0ebe3e
<
template
>
<div
class=
"app-container
calendar-list-container
"
>
<div
class=
"app-container"
>
<!-- 查询和其他操作 -->
<div
class=
"filter-container"
>
<el-input
clearable
class=
"filter-item"
style=
"width: 200px;"
placeholder=
"请输入用户ID"
v-model=
"listQuery.userId"
>
</el-input>
<el-input
clearable
class=
"filter-item"
style=
"width: 200px;"
placeholder=
"请输入商品ID"
v-model=
"listQuery.valueId"
>
</el-input>
<el-input
v-model=
"listQuery.userId"
clearable
class=
"filter-item"
style=
"width: 200px;"
placeholder=
"请输入用户ID"
/>
<el-input
v-model=
"listQuery.valueId"
clearable
class=
"filter-item"
style=
"width: 200px;"
placeholder=
"请输入商品ID"
/>
<el-button
class=
"filter-item"
type=
"primary"
icon=
"el-icon-search"
@
click=
"handleFilter"
>
查找
</el-button>
<el-button
class=
"filter-item"
type=
"primary"
icon=
"el-icon-download"
@
click=
"handleDownload"
:loading=
"downloadLoading"
>
导出
</el-button>
<el-button
:loading=
"downloadLoading"
class=
"filter-item"
type=
"primary"
icon=
"el-icon-download"
@
click=
"handleDownload"
>
导出
</el-button>
</div>
<!-- 查询结果 -->
<el-table
size=
"small"
:data=
"list"
v-loading=
"listLoading
"
element-loading-text=
"正在查询中。。。"
border
fit
highlight-current-row
>
<el-table
v-loading=
"listLoading"
:data=
"list"
size=
"small
"
element-loading-text=
"正在查询中。。。"
border
fit
highlight-current-row
>
<el-table-column
align=
"center"
label=
"用户ID"
prop=
"userId"
>
</el-table-column>
<el-table-column
align=
"center"
label=
"用户ID"
prop=
"userId"
/>
<el-table-column
align=
"center"
label=
"商品ID"
prop=
"valueId"
>
</el-table-column>
<el-table-column
align=
"center"
label=
"商品ID"
prop=
"valueId"
/>
<el-table-column
align=
"center"
label=
"打分"
prop=
"star"
>
</el-table-column>
<el-table-column
align=
"center"
label=
"打分"
prop=
"star"
/>
<el-table-column
align=
"center"
label=
"评论内容"
prop=
"content"
>
</el-table-column>
<el-table-column
align=
"center"
label=
"评论内容"
prop=
"content"
/>
<el-table-column
align=
"center"
label=
"评论图片"
prop=
"picUrls"
>
<template
slot-scope=
"scope"
>
<img
v-for=
"item in scope.row.picUrls"
:key=
"item"
:src=
"item"
width=
"40"
/
>
<img
v-for=
"item in scope.row.picUrls"
:key=
"item"
:src=
"item"
width=
"40"
>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"时间"
prop=
"addTime"
>
</el-table-column>
<el-table-column
align=
"center"
label=
"时间"
prop=
"addTime"
/>
<el-table-column
align=
"center"
label=
"操作"
width=
"200"
class-name=
"small-padding fixed-width"
>
<
template
slot-scope=
"scope"
>
...
...
@@ -43,18 +36,13 @@
</el-table-column>
</el-table>
<!-- 分页 -->
<div
class=
"pagination-container"
>
<el-pagination
background
@
size-change=
"handleSizeChange"
@
current-change=
"handleCurrentChange"
:current-page=
"listQuery.page"
:page-sizes=
"[10,20,30,50]"
:page-size=
"listQuery.limit"
layout=
"total, sizes, prev, pager, next, jumper"
:total=
"total"
>
</el-pagination>
</div>
<pagination
v-show=
"total>0"
:total=
"total"
:page.sync=
"listQuery.page"
:limit.sync=
"listQuery.limit"
@
pagination=
"getList"
/>
<!-- 评论回复 -->
<el-dialog
title=
"回复"
:visible.sync=
"replyFormVisible"
>
<el-form
ref=
"replyForm"
:model=
"replyForm"
status-icon
label-position=
"left"
label-width=
"100px"
style=
'
width: 400px; margin-left:50px;
'
>
<el-dialog
:visible.sync=
"replyFormVisible"
title=
"回复"
>
<el-form
ref=
"replyForm"
:model=
"replyForm"
status-icon
label-position=
"left"
label-width=
"100px"
style=
"
width: 400px; margin-left:50px;
"
>
<el-form-item
label=
"回复内容"
prop=
"content"
>
<el-input
type=
"textarea"
:autosize=
"{ minRows: 4, maxRows: 8}"
v-model=
"replyForm.content"
></el-input
>
<el-input
:autosize=
"{ minRows: 4, maxRows: 8}"
v-model=
"replyForm.content"
type=
"textarea"
/
>
</el-form-item>
</el-form>
<div
slot=
"footer"
class=
"dialog-footer"
>
...
...
@@ -69,9 +57,11 @@
<
script
>
import
{
listComment
,
deleteComment
}
from
'
@/api/comment
'
import
{
replyComment
}
from
'
@/api/order
'
import
Pagination
from
'
@/components/Pagination
'
// Secondary package based on el-pagination
export
default
{
name
:
'
Comment
'
,
components
:
{
Pagination
},
data
()
{
return
{
list
:
undefined
,
...
...
@@ -113,14 +103,6 @@ export default {
this
.
listQuery
.
page
=
1
this
.
getList
()
},
handleSizeChange
(
val
)
{
this
.
listQuery
.
limit
=
val
this
.
getList
()
},
handleCurrentChange
(
val
)
{
this
.
listQuery
.
page
=
val
this
.
getList
()
},
handleReply
(
row
)
{
this
.
replyForm
=
{
commentId
:
row
.
id
,
content
:
''
}
this
.
replyFormVisible
=
true
...
...
litemall-admin/src/views/goods/create.vue
View file @
6f0ebe3e
<
template
>
<div
class=
"app-container
calendar-list-container
"
>
<div
class=
"app-container"
>
<el-card
class=
"box-card"
>
<h3>
商品介绍
</h3>
<el-form
:rules=
"rule
s"
ref=
"good
s"
:model=
"goods"
label-width=
"150px"
>
<el-form
ref=
"goods"
:rules=
"rules"
:model=
"goods"
label-width=
"150px"
>
<el-form-item
label=
"商品编号"
prop=
"goodsSn"
>
<el-input
v-model=
"goods.goodsSn"
></el-input
>
<el-input
v-model=
"goods.goodsSn"
/
>
</el-form-item>
<el-form-item
label=
"商品名称"
prop=
"name"
>
<el-input
v-model=
"goods.name"
></el-input
>
<el-input
v-model=
"goods.name"
/
>
</el-form-item>
<el-form-item
label=
"专柜价格"
prop=
"counterPrice"
>
<el-input
v-model=
"goods.counterPrice"
placeholder=
"0.00"
>
...
...
@@ -40,105 +40,139 @@
</el-form-item>
<el-form-item
label=
"商品图片"
>
<el-upload
class=
"avatar-uploader"
:action=
"uploadPath"
list-type=
"picture-card"
:show-file-list=
"false"
:headers=
"headers"
accept=
".jpg,.jpeg,.png,.gif"
:on-success=
"uploadPicUrl"
>
<el-upload
:action=
"uploadPath"
:show-file-list=
"false"
:headers=
"headers"
:on-success=
"uploadPicUrl"
class=
"avatar-uploader"
list-type=
"picture-card"
accept=
".jpg,.jpeg,.png,.gif"
>
<img
v-if=
"goods.picUrl"
:src=
"goods.picUrl"
class=
"avatar"
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
></i
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
/
>
</el-upload>
</el-form-item>
<el-form-item
label=
"宣传画廊"
>
<el-upload
:action=
"uploadPath"
:limit=
"5"
multiple
accept=
".jpg,.jpeg,.png,.gif"
list-type=
"picture-card"
:headers=
"headers"
:on-exceed=
"uploadOverrun"
:on-success=
"handleGalleryUrl"
:on-remove=
"handleRemove"
>
<i
class=
"el-icon-plus"
></i>
<el-upload
:action=
"uploadPath"
:limit=
"5"
:headers=
"headers"
:on-exceed=
"uploadOverrun"
:on-success=
"handleGalleryUrl"
:on-remove=
"handleRemove"
multiple
accept=
".jpg,.jpeg,.png,.gif"
list-type=
"picture-card"
>
<i
class=
"el-icon-plus"
/>
</el-upload>
</el-form-item>
<el-form-item
label=
"商品单位"
>
<el-input
v-model=
"goods.unit"
placeholder=
"件 / 个 / 盒"
></el-input
>
<el-input
v-model=
"goods.unit"
placeholder=
"件 / 个 / 盒"
/
>
</el-form-item>
<el-form-item
label=
"关键字"
>
<el-tag
:key=
"tag"
v-for=
"tag in keywords"
closable
type=
"primary"
@
close=
"handleClose(tag)"
>
{{tag}}
<el-tag
v-for=
"tag in keywords"
:key=
"tag"
closable
type=
"primary"
@
close=
"handleClose(tag)"
>
{{
tag
}}
</el-tag>
<el-input
class=
"input-new-keyword"
v-if=
"newKeywordVisible"
v-model=
"newKeyword"
ref=
"newKeywordInput"
size=
"small"
@
keyup.enter.native=
"handleInputConfirm"
@
blur=
"handleInputConfirm"
>
</el-input>
<el-input
v-if=
"newKeywordVisible"
ref=
"newKeywordInput"
v-model=
"newKeyword"
class=
"input-new-keyword"
size=
"small"
@
keyup.enter.native=
"handleInputConfirm"
@
blur=
"handleInputConfirm"
/>
<el-button
v-else
class=
"button-new-keyword"
size=
"small"
type=
"primary"
@
click=
"showInput"
>
+ 增加
</el-button>
</el-form-item>
<el-form-item
label=
"所属分类"
>
<el-cascader
expand-trigger=
"hover"
:options=
"categoryList"
@
change=
"handleCategoryChange"
></el-cascader
>
<el-cascader
:options=
"categoryList"
expand-trigger=
"hover"
@
change=
"handleCategoryChange"
/
>
</el-form-item>
<el-form-item
label=
"所属品牌商"
>
<el-select
v-model=
"goods.brandId"
>
<el-option
v-for=
"item in brandList"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
>
</el-option>
<el-option
v-for=
"item in brandList"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
</el-form-item>
<el-form-item
label=
"商品简介"
>
<el-input
v-model=
"goods.brief"
></el-input
>
<el-input
v-model=
"goods.brief"
/
>
</el-form-item>
<el-form-item
label=
"商品详细介绍"
>
<editor
:init=
"editorInit"
v-model=
"goods.detail"
></editor
>
<editor
:init=
"editorInit"
v-model=
"goods.detail"
/
>
</el-form-item>
</el-form>
</el-card>
<el-card
class=
"box-card"
>
<h3>
商品规格
</h3>
<el-row
type=
"flex"
align=
"middle"
:gutter=
"20"
style=
"padding:20px 0;"
>
<el-row
:gutter=
"20"
type=
"flex"
align=
"middle"
style=
"padding:20px 0;"
>
<el-col
:span=
"10"
>
<el-radio-group
v-model=
"multipleSpec"
@
change=
"specChanged"
>
<el-radio-button
:label=
"false"
>
默认标准规格
</el-radio-button>
<el-radio-button
:label=
"true"
>
多规格支持
</el-radio-button>
</el-radio-group>
</el-col>
<el-col
:span=
"10"
v-if=
"multipleSpec"
>
<el-button
:plain=
"true"
@
click=
"handleSpecificationShow"
type=
"primary"
>
添加
</el-button>
<el-col
v-if=
"multipleSpec"
:span=
"10"
>
<el-button
:plain=
"true"
type=
"primary"
@
click=
"handleSpecificationShow"
>
添加
</el-button>
</el-col>
</el-row>
<el-table
:data=
"specifications"
>
<el-table-column
property=
"specification"
label=
"规格名"
></el-table-column
>
<el-table-column
property=
"specification"
label=
"规格名"
/
>
<el-table-column
property=
"value"
label=
"规格值"
>
<
template
slot-scope=
"scope"
>
<el-tag
type=
"primary"
>
{{
scope
.
row
.
value
}}
{{
scope
.
row
.
value
}}
</el-tag>
</
template
>
</el-table-column>
<el-table-column
property=
"picUrl"
label=
"规格图片"
>
<
template
slot-scope=
"scope"
>
<img
:src=
"scope.row.picUrl"
width=
"40"
v-if=
"scope.row.picUrl"
/
>
<img
v-if=
"scope.row.picUrl"
:src=
"scope.row.picUrl"
width=
"40"
>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"操作"
width=
"250"
class-name=
"small-padding fixed-width"
v-if=
"multipleSpec"
>
<el-table-column
v-if=
"multipleSpec"
align=
"center"
label=
"操作"
width=
"250"
class-name=
"small-padding fixed-width"
>
<
template
slot-scope=
"scope"
>
<el-button
type=
"danger"
size=
"mini"
@
click=
"handleSpecificationDelete(scope.row)"
>
删除
</el-button>
</
template
>
</el-table-column>
</el-table>
<el-dialog
title=
"设置规格"
:visible.sync=
"specVisiable"
>
<el-form
:rules=
"rules"
ref=
"specForm"
:model=
"specForm"
status-icon
label-position=
"left"
label-width=
"100px"
style=
'width: 400px; margin-left:50px;'
>
<el-dialog
:visible.sync=
"specVisiable"
title=
"设置规格"
>
<el-form
ref=
"specForm"
:rules=
"rules"
:model=
"specForm"
status-icon
label-position=
"left"
label-width=
"100px"
style=
"width: 400px; margin-left:50px;"
>
<el-form-item
label=
"规格名"
prop=
"specification"
>
<el-input
v-model=
"specForm.specification"
></el-input
>
<el-input
v-model=
"specForm.specification"
/
>
</el-form-item>
<el-form-item
label=
"规格值"
prop=
"value"
>
<el-input
v-model=
"specForm.value"
></el-input
>
<el-input
v-model=
"specForm.value"
/
>
</el-form-item>
<el-form-item
label=
"规格图片"
prop=
"picUrl"
>
<el-upload
class=
"avatar-uploader"
:action=
'uploadPath'
list-type=
"picture-card"
:show-file-list=
"false"
:headers=
"headers"
accept=
".jpg,.jpeg,.png,.gif"
:on-success=
"uploadSpecPicUrl"
>
<el-upload
:action=
"uploadPath"
:show-file-list=
"false"
:headers=
"headers"
:on-success=
"uploadSpecPicUrl"
class=
"avatar-uploader"
list-type=
"picture-card"
accept=
".jpg,.jpeg,.png,.gif"
>
<img
v-if=
"specForm.picUrl"
:src=
"specForm.picUrl"
class=
"avatar"
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
></i
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
/
>
</el-upload>
</el-form-item>
</el-form>
...
...
@@ -154,18 +188,16 @@
<el-table
:data=
"products"
>
<el-table-column
property=
"value"
label=
"货品规格"
>
<
template
slot-scope=
"scope"
>
<el-tag
:key=
"tag"
v-for=
"tag in scope.row.specifications"
>
{{
tag
}}
<el-tag
v-for=
"tag in scope.row.specifications"
:key=
"tag"
>
{{
tag
}}
</el-tag>
</
template
>
</el-table-column>
<el-table-column
property=
"price"
width=
"100"
label=
"货品售价"
>
</el-table-column>
<el-table-column
property=
"number"
width=
"100"
label=
"货品数量"
>
</el-table-column>
<el-table-column
property=
"price"
width=
"100"
label=
"货品售价"
/>
<el-table-column
property=
"number"
width=
"100"
label=
"货品数量"
/>
<el-table-column
property=
"url"
width=
"100"
label=
"货品图片"
>
<
template
slot-scope=
"scope"
>
<img
:src=
"scope.row.url"
width=
"40"
v-if=
"scope.row.url"
/
>
<img
v-if=
"scope.row.url"
:src=
"scope.row.url"
width=
"40"
>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"操作"
width=
"100"
class-name=
"small-padding fixed-width"
>
...
...
@@ -175,25 +207,36 @@
</el-table-column>
</el-table>
<el-dialog
title=
"设置货品"
:visible.sync=
"productVisiable"
>
<el-form
ref=
"productForm"
:model=
"productForm"
status-icon
label-position=
"left"
label-width=
"100px"
style=
'width: 400px; margin-left:50px;'
>
<el-dialog
:visible.sync=
"productVisiable"
title=
"设置货品"
>
<el-form
ref=
"productForm"
:model=
"productForm"
status-icon
label-position=
"left"
label-width=
"100px"
style=
"width: 400px; margin-left:50px;"
>
<el-form-item
label=
"货品规格列"
prop=
"specifications"
>
<el-tag
:key=
"tag"
v-for=
"tag in productForm.specifications"
>
{{tag}}
<el-tag
v-for=
"tag in productForm.specifications"
:key=
"tag"
>
{{
tag
}}
</el-tag>
</el-form-item>
<el-form-item
label=
"货品售价"
prop=
"price"
>
<el-input
v-model=
"productForm.price"
></el-input
>
<el-input
v-model=
"productForm.price"
/
>
</el-form-item>
<el-form-item
label=
"货品数量"
prop=
"number"
>
<el-input
v-model=
"productForm.number"
></el-input
>
<el-input
v-model=
"productForm.number"
/
>
</el-form-item>
<el-form-item
label=
"货品图片"
prop=
"url"
>
<el-upload
class=
"avatar-uploader"
:action=
'uploadPath'
list-type=
"picture-card"
:show-file-list=
"false"
:headers=
"headers"
accept=
".jpg,.jpeg,.png,.gif"
:on-success=
"uploadProductUrl"
>
<el-upload
:action=
"uploadPath"
:show-file-list=
"false"
:headers=
"headers"
:on-success=
"uploadProductUrl"
class=
"avatar-uploader"
list-type=
"picture-card"
accept=
".jpg,.jpeg,.png,.gif"
>
<img
v-if=
"productForm.url"
:src=
"productForm.url"
class=
"avatar"
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
></i
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
/
>
</el-upload>
</el-form-item>
</el-form>
...
...
@@ -206,12 +249,10 @@
<el-card
class=
"box-card"
>
<h3>
商品参数
</h3>
<el-button
:plain=
"true"
@
click=
"handleAttributeShow"
type=
"primary"
>
添加
</el-button>
<el-button
:plain=
"true"
type=
"primary"
@
click=
"handleAttributeShow"
>
添加
</el-button>
<el-table
:data=
"attributes"
>
<el-table-column
property=
"attribute"
label=
"商品参数名称"
>
</el-table-column>
<el-table-column
property=
"value"
label=
"商品参数值"
>
</el-table-column>
<el-table-column
property=
"attribute"
label=
"商品参数名称"
/>
<el-table-column
property=
"value"
label=
"商品参数值"
/>
<el-table-column
align=
"center"
label=
"操作"
width=
"100"
class-name=
"small-padding fixed-width"
>
<
template
slot-scope=
"scope"
>
<el-button
type=
"danger"
size=
"mini"
@
click=
"handleAttributeDelete(scope.row)"
>
删除
</el-button>
...
...
@@ -219,14 +260,19 @@
</el-table-column>
</el-table>
<el-dialog
title=
"设置商品参数"
:visible.sync=
"attributeVisiable"
>
<el-form
ref=
"attributeForm"
:model=
"attributeForm"
status-icon
label-position=
"left"
label-width=
"100px"
style=
'width: 400px; margin-left:50px;'
>
<el-dialog
:visible.sync=
"attributeVisiable"
title=
"设置商品参数"
>
<el-form
ref=
"attributeForm"
:model=
"attributeForm"
status-icon
label-position=
"left"
label-width=
"100px"
style=
"width: 400px; margin-left:50px;"
>
<el-form-item
label=
"商品参数名称"
prop=
"attribute"
>
<el-input
v-model=
"attributeForm.attribute"
></el-input
>
<el-input
v-model=
"attributeForm.attribute"
/
>
</el-form-item>
<el-form-item
label=
"商品参数值"
prop=
"value"
>
<el-input
v-model=
"attributeForm.value"
></el-input
>
<el-input
v-model=
"attributeForm.value"
/
>
</el-form-item>
</el-form>
<div
slot=
"footer"
class=
"dialog-footer"
>
...
...
@@ -238,7 +284,7 @@
<div
class=
"op-container"
>
<el-button
@
click=
"handleCancel"
>
取消
</el-button>
<el-button
@
click=
"handlePublish"
type=
"primary"
>
上架
</el-button>
<el-button
type=
"primary"
@
click=
"handlePublish"
>
上架
</el-button>
</div>
</div>
...
...
@@ -288,22 +334,15 @@
</
style
>
<
script
>
import
{
publishGoods
,
listCatAndBrand
}
from
'
@/api/goods
'
import
{
createStorage
,
uploadPath
}
from
'
@/api/storage
'
import
Editor
from
'
@tinymce/tinymce-vue
'
import
{
MessageBox
}
from
'
element-ui
'
import
{
getToken
}
from
'
@/utils/auth
'
import
{
publishGoods
,
listCatAndBrand
}
from
'
@/api/goods
'
import
{
createStorage
,
uploadPath
}
from
'
@/api/storage
'
import
Editor
from
'
@tinymce/tinymce-vue
'
import
{
MessageBox
}
from
'
element-ui
'
import
{
getToken
}
from
'
@/utils/auth
'
export
default
{
export
default
{
name
:
'
GoodsCreate
'
,
components
:
{
Editor
},
computed
:
{
headers
()
{
return
{
'
Admin-Token
'
:
getToken
()
}
}
},
data
()
{
return
{
...
...
@@ -345,6 +384,13 @@
}
}
},
computed
:
{
headers
()
{
return
{
'
Admin-Token
'
:
getToken
()
}
}
},
created
()
{
this
.
init
()
},
...
...
@@ -563,5 +609,5 @@
this
.
attributes
.
splice
(
index
,
1
)
}
}
}
}
</
script
>
litemall-admin/src/views/goods/edit.vue
View file @
6f0ebe3e
<
template
>
<div
class=
"app-container
calendar-list-container
"
>
<div
class=
"app-container"
>
<el-card
class=
"box-card"
>
<h3>
商品介绍
</h3>
<el-form
:rules=
"rule
s"
ref=
"good
s"
:model=
"goods"
label-width=
"150px"
>
<el-form
ref=
"goods"
:rules=
"rules"
:model=
"goods"
label-width=
"150px"
>
<el-form-item
label=
"商品编号"
prop=
"goodsSn"
>
<el-input
v-model=
"goods.goodsSn"
></el-input
>
<el-input
v-model=
"goods.goodsSn"
/
>
</el-form-item>
<el-form-item
label=
"商品名称"
prop=
"name"
>
<el-input
v-model=
"goods.name"
></el-input
>
<el-input
v-model=
"goods.name"
/
>
</el-form-item>
<el-form-item
label=
"专柜价格"
prop=
"counterPrice"
>
<el-input
v-model=
"goods.counterPrice"
placeholder=
"0.00"
>
...
...
@@ -40,68 +40,66 @@
</el-form-item>
<el-form-item
label=
"商品图片"
>
<el-upload
class=
"avatar-uploader"
:headers=
"headers"
:action=
'
uploadPath
'
list-type=
"picture-card"
:show-file-list=
"false
"
accept=
".jpg,.jpeg,.png,.gif"
:on-success=
"uploadPicUrl"
>
<el-upload
:headers=
"headers"
:action=
"
uploadPath
"
:show-file-list=
"false"
:on-success=
"uploadPicUrl"
class=
"avatar-uploader"
list-type=
"picture-card
"
accept=
".jpg,.jpeg,.png,.gif"
>
<img
v-if=
"goods.picUrl"
:src=
"goods.picUrl"
class=
"avatar"
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
></i
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
/
>
</el-upload>
</el-form-item>
<el-form-item
label=
"宣传画廊"
>
<el-upload
:action=
'
uploadPath
'
:headers=
"headers"
:limit=
'5'
multiple
accept=
".jpg,.jpeg,.png,.gif
"
:file-list=
"galleryFileList"
list-type=
"picture-card"
:on-exceed=
'
uploadOverrun
'
:on-success=
"handleGalleryUrl"
:on-remove=
"handleRemove"
>
<i
class=
"el-icon-plus"
></i
>
<el-upload
:action=
"
uploadPath
"
:headers=
"headers"
:limit=
"5
"
:file-list=
"galleryFileList"
:on-exceed=
"
uploadOverrun
"
:on-success=
"handleGalleryUrl"
:on-remove=
"handleRemove"
multiple
accept=
".jpg,.jpeg,.png,.gif"
list-type=
"picture-card"
>
<i
class=
"el-icon-plus"
/
>
</el-upload>
</el-form-item>
<el-form-item
label=
"商品单位"
>
<el-input
v-model=
"goods.unit"
placeholder=
"件 / 个 / 盒"
></el-input
>
<el-input
v-model=
"goods.unit"
placeholder=
"件 / 个 / 盒"
/
>
</el-form-item>
<el-form-item
label=
"关键字"
>
<el-tag
:key=
"tag"
v-for=
"tag in keywords"
closable
type=
"primary"
@
close=
"handleClose(tag)"
>
{{tag}}
<el-tag
v-for=
"tag in keywords"
:key=
"tag"
closable
type=
"primary"
@
close=
"handleClose(tag)"
>
{{
tag
}}
</el-tag>
<el-input
class=
"input-new-keyword"
v-if=
"newKeywordVisible"
v-model=
"newKeyword"
ref=
"newKeywordInput"
size=
"small"
@
keyup.enter.native=
"handleInputConfirm"
@
blur=
"handleInputConfirm"
>
</el-input>
<el-input
v-if=
"newKeywordVisible"
ref=
"newKeywordInput"
v-model=
"newKeyword"
class=
"input-new-keyword"
size=
"small"
@
keyup.enter.native=
"handleInputConfirm"
@
blur=
"handleInputConfirm"
/>
<el-button
v-else
class=
"button-new-keyword"
size=
"small"
type=
"primary"
@
click=
"showInput"
>
+ 增加
</el-button>
</el-form-item>
<el-form-item
label=
"所属分类"
>
<el-cascader
expand-trigger=
"hover"
:options=
"categoryList"
v-model=
"categoryIds"
@
change=
"handleCategoryChange"
></el-cascader
>
<el-cascader
:options=
"categoryList"
v-model=
"categoryIds"
expand-trigger=
"hover"
@
change=
"handleCategoryChange"
/
>
</el-form-item>
<el-form-item
label=
"所属品牌商"
>
<el-select
v-model=
"goods.brandId"
>
<el-option
v-for=
"item in brandList"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
>
</el-option>
<el-option
v-for=
"item in brandList"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
</el-form-item>
<el-form-item
label=
"商品简介"
>
<el-input
v-model=
"goods.brief"
></el-input
>
<el-input
v-model=
"goods.brief"
/
>
</el-form-item>
<el-form-item
label=
"商品详细介绍"
>
<editor
:init=
"editorInit"
v-model=
"goods.detail"
></editor
>
<editor
:init=
"editorInit"
v-model=
"goods.detail"
/
>
</el-form-item>
</el-form>
</el-card>
<el-card
class=
"box-card"
>
<h3>
商品规格
</h3>
<el-button
:plain=
"true"
@
click=
"handleSpecificationShow"
type=
"primary"
>
添加
</el-button>
<el-button
:plain=
"true"
type=
"primary"
@
click=
"handleSpecificationShow"
>
添加
</el-button>
<el-table
:data=
"specifications"
>
<el-table-column
property=
"specification"
label=
"规格名"
></el-table-column
>
<el-table-column
property=
"specification"
label=
"规格名"
/
>
<el-table-column
property=
"value"
label=
"规格值"
>
<
template
slot-scope=
"scope"
>
<el-tag
type=
"primary"
>
{{
scope
.
row
.
value
}}
{{
scope
.
row
.
value
}}
</el-tag>
</
template
>
</el-table-column>
<el-table-column
property=
"picUrl"
label=
"规格图片"
>
<
template
slot-scope=
"scope"
>
<img
:src=
"scope.row.picUrl"
width=
"40"
v-if=
"scope.row.picUrl"
/
>
<img
v-if=
"scope.row.picUrl"
:src=
"scope.row.picUrl"
width=
"40"
>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"操作"
width=
"250"
class-name=
"small-padding fixed-width"
>
...
...
@@ -111,18 +109,18 @@
</el-table-column>
</el-table>
<el-dialog
title=
"设置规格"
:visible.sync=
"specVisiable"
>
<el-form
:rules=
"rules"
ref=
"specForm
"
:model=
"specForm"
status-icon
label-position=
"left"
label-width=
"100px"
style=
'
width: 400px; margin-left:50px;
'
>
<el-dialog
:visible.sync=
"specVisiable"
title=
"设置规格"
>
<el-form
ref=
"specForm"
:rules=
"rules
"
:model=
"specForm"
status-icon
label-position=
"left"
label-width=
"100px"
style=
"
width: 400px; margin-left:50px;
"
>
<el-form-item
label=
"规格名"
prop=
"specification"
>
<el-input
v-model=
"specForm.specification"
></el-input
>
<el-input
v-model=
"specForm.specification"
/
>
</el-form-item>
<el-form-item
label=
"规格值"
prop=
"value"
>
<el-input
v-model=
"specForm.value"
></el-input
>
<el-input
v-model=
"specForm.value"
/
>
</el-form-item>
<el-form-item
label=
"规格图片"
prop=
"picUrl"
>
<el-upload
class=
"avatar-uploader"
:headers=
"headers"
:action=
'
uploadPath
'
list-type=
"picture-card"
:show-file-list=
"false"
accept=
".jpg,.jpeg,.png,.gif"
:on-success=
"uploadSpecPicUrl
"
>
<el-upload
:headers=
"headers"
:action=
"
uploadPath
"
:show-file-list=
"false"
:on-success=
"uploadSpecPicUrl"
class=
"avatar-uploader"
list-type=
"picture-card"
accept=
".jpg,.jpeg,.png,.gif
"
>
<img
v-if=
"specForm.picUrl"
:src=
"specForm.picUrl"
class=
"avatar"
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
></i
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
/
>
</el-upload>
</el-form-item>
</el-form>
...
...
@@ -138,18 +136,16 @@
<el-table
:data=
"products"
>
<el-table-column
property=
"value"
label=
"货品规格"
>
<
template
slot-scope=
"scope"
>
<el-tag
:key=
"tag"
v-for=
"tag in scope.row.specifications"
>
{{
tag
}}
<el-tag
v-for=
"tag in scope.row.specifications"
:key=
"tag"
>
{{
tag
}}
</el-tag>
</
template
>
</el-table-column>
<el-table-column
property=
"price"
width=
"100"
label=
"货品售价"
>
</el-table-column>
<el-table-column
property=
"number"
width=
"100"
label=
"货品数量"
>
</el-table-column>
<el-table-column
property=
"price"
width=
"100"
label=
"货品售价"
/>
<el-table-column
property=
"number"
width=
"100"
label=
"货品数量"
/>
<el-table-column
property=
"url"
width=
"100"
label=
"货品图片"
>
<
template
slot-scope=
"scope"
>
<img
:src=
"scope.row.url"
width=
"40"
v-if=
"scope.row.url"
/
>
<img
v-if=
"scope.row.url"
:src=
"scope.row.url"
width=
"40"
>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"操作"
width=
"100"
class-name=
"small-padding fixed-width"
>
...
...
@@ -159,23 +155,23 @@
</el-table-column>
</el-table>
<el-dialog
title=
"设置货品"
:visible.sync=
"productVisiable"
>
<el-form
ref=
"productForm"
:model=
"productForm"
status-icon
label-position=
"left"
label-width=
"100px"
style=
'
width: 400px; margin-left:50px;
'
>
<el-dialog
:visible.sync=
"productVisiable"
title=
"设置货品"
>
<el-form
ref=
"productForm"
:model=
"productForm"
status-icon
label-position=
"left"
label-width=
"100px"
style=
"
width: 400px; margin-left:50px;
"
>
<el-form-item
label=
"货品规格列"
prop=
"specifications"
>
<el-tag
:key=
"tag"
v-for=
"tag in productForm.specifications"
>
{{tag}}
<el-tag
v-for=
"tag in productForm.specifications"
:key=
"tag"
>
{{
tag
}}
</el-tag>
</el-form-item>
<el-form-item
label=
"货品售价"
prop=
"price"
>
<el-input
v-model=
"productForm.price"
></el-input
>
<el-input
v-model=
"productForm.price"
/
>
</el-form-item>
<el-form-item
label=
"货品数量"
prop=
"number"
>
<el-input
v-model=
"productForm.number"
></el-input
>
<el-input
v-model=
"productForm.number"
/
>
</el-form-item>
<el-form-item
label=
"货品图片"
prop=
"url"
>
<el-upload
class=
"avatar-uploader"
:headers=
"headers"
:action=
'
uploadPath
'
list-type=
"picture-card"
:show-file-list=
"false"
accept=
".jpg,.jpeg,.png,.gif"
:on-success=
"uploadProductUrl
"
>
<el-upload
:headers=
"headers"
:action=
"
uploadPath
"
:show-file-list=
"false"
:on-success=
"uploadProductUrl"
class=
"avatar-uploader"
list-type=
"picture-card"
accept=
".jpg,.jpeg,.png,.gif
"
>
<img
v-if=
"productForm.url"
:src=
"productForm.url"
class=
"avatar"
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
></i
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
/
>
</el-upload>
</el-form-item>
</el-form>
...
...
@@ -188,12 +184,10 @@
<el-card
class=
"box-card"
>
<h3>
商品参数
</h3>
<el-button
:plain=
"true"
@
click=
"handleAttributeShow"
type=
"primary"
>
添加
</el-button>
<el-button
:plain=
"true"
type=
"primary"
@
click=
"handleAttributeShow"
>
添加
</el-button>
<el-table
:data=
"attributes"
>
<el-table-column
property=
"attribute"
label=
"商品参数名称"
>
</el-table-column>
<el-table-column
property=
"value"
label=
"商品参数值"
>
</el-table-column>
<el-table-column
property=
"attribute"
label=
"商品参数名称"
/>
<el-table-column
property=
"value"
label=
"商品参数值"
/>
<el-table-column
align=
"center"
label=
"操作"
width=
"100"
class-name=
"small-padding fixed-width"
>
<
template
slot-scope=
"scope"
>
<el-button
type=
"danger"
size=
"mini"
@
click=
"handleAttributeDelete(scope.row)"
>
删除
</el-button>
...
...
@@ -201,13 +195,13 @@
</el-table-column>
</el-table>
<el-dialog
title=
"设置商品参数"
:visible.sync=
"attributeVisiable"
>
<el-form
ref=
"attributeForm"
:model=
"attributeForm"
status-icon
label-position=
"left"
label-width=
"100px"
style=
'
width: 400px; margin-left:50px;
'
>
<el-dialog
:visible.sync=
"attributeVisiable"
title=
"设置商品参数"
>
<el-form
ref=
"attributeForm"
:model=
"attributeForm"
status-icon
label-position=
"left"
label-width=
"100px"
style=
"
width: 400px; margin-left:50px;
"
>
<el-form-item
label=
"商品参数名称"
prop=
"attribute"
>
<el-input
v-model=
"attributeForm.attribute"
></el-input
>
<el-input
v-model=
"attributeForm.attribute"
/
>
</el-form-item>
<el-form-item
label=
"商品参数值"
prop=
"value"
>
<el-input
v-model=
"attributeForm.value"
></el-input
>
<el-input
v-model=
"attributeForm.value"
/
>
</el-form-item>
</el-form>
<div
slot=
"footer"
class=
"dialog-footer"
>
...
...
@@ -219,47 +213,47 @@
<div
class=
"op-container"
>
<el-button
@
click=
"handleCancel"
>
取消
</el-button>
<el-button
@
click=
"handleEdit"
type=
"primary"
>
更新商品
</el-button>
<el-button
type=
"primary"
@
click=
"handleEdit"
>
更新商品
</el-button>
</div>
</div>
</template>
<
style
>
.el-card
{
.el-card
{
margin-bottom
:
10px
;
}
.el-tag
+
.el-tag
{
}
.el-tag
+
.el-tag
{
margin-left
:
10px
;
}
.input-new-keyword
{
}
.input-new-keyword
{
width
:
90px
;
margin-left
:
10px
;
vertical-align
:
bottom
;
}
.avatar-uploader
.el-upload
{
}
.avatar-uploader
.el-upload
{
border
:
1px
dashed
#d9d9d9
;
border-radius
:
6px
;
cursor
:
pointer
;
position
:
relative
;
overflow
:
hidden
;
}
.avatar-uploader
.el-upload
:hover
{
}
.avatar-uploader
.el-upload
:hover
{
border-color
:
#20a0ff
;
}
.avatar-uploader-icon
{
}
.avatar-uploader-icon
{
font-size
:
28px
;
color
:
#8c939d
;
width
:
120px
;
height
:
120px
;
line-height
:
120px
;
text-align
:
center
;
}
.avatar
{
}
.avatar
{
width
:
120px
;
height
:
120px
;
display
:
block
;
}
}
</
style
>
<
script
>
...
...
@@ -272,13 +266,6 @@ import { getToken } from '@/utils/auth'
export
default
{
name
:
'
GoodsEdit
'
,
components
:
{
Editor
},
computed
:
{
headers
()
{
return
{
'
Admin-Token
'
:
getToken
()
}
}
},
data
()
{
return
{
uploadPath
,
...
...
@@ -294,32 +281,56 @@ export default {
specForm
:
{
specification
:
''
,
value
:
''
,
picUrl
:
''
},
specifications
:
[{
specification
:
'
规格
'
,
value
:
'
标准
'
,
picUrl
:
''
}],
productVisiable
:
false
,
productForm
:
{
id
:
0
,
specifications
:
[],
price
:
0.00
,
number
:
0
,
url
:
''
},
products
:
[{
id
:
0
,
specifications
:
[
'
标准
'
],
price
:
0.00
,
number
:
0
,
url
:
''
}],
productForm
:
{
id
:
0
,
specifications
:
[],
price
:
0.0
,
number
:
0
,
url
:
''
},
products
:
[
{
id
:
0
,
specifications
:
[
'
标准
'
],
price
:
0.0
,
number
:
0
,
url
:
''
}
],
attributeVisiable
:
false
,
attributeForm
:
{
attribute
:
''
,
value
:
''
},
attributes
:
[],
rules
:
{
goodsSn
:
[{
required
:
true
,
message
:
'
商品编号不能为空
'
,
trigger
:
'
blur
'
}],
goodsSn
:
[
{
required
:
true
,
message
:
'
商品编号不能为空
'
,
trigger
:
'
blur
'
}
],
name
:
[{
required
:
true
,
message
:
'
商品名称不能为空
'
,
trigger
:
'
blur
'
}]
},
editorInit
:
{
language
:
'
zh_CN
'
,
convert_urls
:
false
,
plugins
:
[
'
advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools importcss insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount
'
],
toolbar
:
[
'
searchreplace 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 insertdatetime media table emoticons forecolor backcolor fullscreen
'
],
plugins
:
[
'
advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools importcss insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount
'
],
toolbar
:
[
'
searchreplace 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 insertdatetime media table emoticons forecolor backcolor fullscreen
'
],
images_upload_handler
:
function
(
blobInfo
,
success
,
failure
)
{
const
formData
=
new
FormData
()
formData
.
append
(
'
file
'
,
blobInfo
.
blob
())
createStorage
(
formData
).
then
(
res
=>
{
createStorage
(
formData
)
.
then
(
res
=>
{
success
(
res
.
data
.
data
.
url
)
}).
catch
(()
=>
{
})
.
catch
(()
=>
{
failure
(
'
上传失败,请重新上传
'
)
})
}
}
}
},
computed
:
{
headers
()
{
return
{
'
Admin-Token
'
:
getToken
()
}
}
},
created
()
{
this
.
init
()
},
...
...
@@ -363,13 +374,15 @@ export default {
products
:
this
.
products
,
attributes
:
this
.
attributes
}
editGoods
(
finalGoods
).
then
(
response
=>
{
editGoods
(
finalGoods
)
.
then
(
response
=>
{
this
.
$notify
.
success
({
title
:
'
成功
'
,
message
:
'
创建成功
'
})
this
.
$router
.
push
({
path
:
'
/goods/list
'
})
}).
catch
(
response
=>
{
})
.
catch
(
response
=>
{
MessageBox
.
alert
(
'
业务错误:
'
+
response
.
data
.
errmsg
,
'
警告
'
,
{
confirmButtonText
:
'
确定
'
,
type
:
'
error
'
...
...
@@ -429,8 +442,12 @@ export default {
},
specChanged
:
function
(
label
)
{
if
(
label
===
false
)
{
this
.
specifications
=
[{
specification
:
'
规格
'
,
value
:
'
标准
'
,
picUrl
:
''
}]
this
.
products
=
[{
id
:
0
,
specifications
:
[
'
标准
'
],
price
:
0.00
,
number
:
0
,
url
:
''
}]
this
.
specifications
=
[
{
specification
:
'
规格
'
,
value
:
'
标准
'
,
picUrl
:
''
}
]
this
.
products
=
[
{
id
:
0
,
specifications
:
[
'
标准
'
],
price
:
0.0
,
number
:
0
,
url
:
''
}
]
}
else
{
this
.
specifications
=
[]
this
.
products
=
[]
...
...
@@ -503,7 +520,13 @@ export default {
var
z
=
specValues
[
x
][
combination
[
x
]]
specifications
.
push
(
this
.
specifications
[
z
].
value
)
}
products
[
productsIndex
]
=
{
id
:
productsIndex
,
specifications
:
specifications
,
price
:
0.00
,
number
:
0
,
url
:
''
}
products
[
productsIndex
]
=
{
id
:
productsIndex
,
specifications
:
specifications
,
price
:
0.0
,
number
:
0
,
url
:
''
}
productsIndex
++
index
++
...
...
Prev
1
2
3
4
5
6
7
8
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