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
b68151cb
Unverified
Commit
b68151cb
authored
Jul 13, 2018
by
Menethil
Committed by
GitHub
Jul 13, 2018
Browse files
Merge pull request #1 from linlinjava/master
update
parents
126d027a
02679509
Changes
251
Show whitespace changes
Inline
Side-by-side
litemall-admin/src/api/cart.js
deleted
100644 → 0
View file @
126d027a
import
request
from
'
@/utils/request
'
export
function
listCart
(
query
)
{
return
request
({
url
:
'
/cart/list
'
,
method
:
'
get
'
,
params
:
query
})
}
export
function
createCart
(
data
)
{
return
request
({
url
:
'
/cart/create
'
,
method
:
'
post
'
,
data
})
}
export
function
readCart
(
data
)
{
return
request
({
url
:
'
/cart/read
'
,
method
:
'
get
'
,
data
})
}
export
function
updateCart
(
data
)
{
return
request
({
url
:
'
/cart/update
'
,
method
:
'
post
'
,
data
})
}
export
function
deleteCart
(
data
)
{
return
request
({
url
:
'
/cart/delete
'
,
method
:
'
post
'
,
data
})
}
litemall-admin/src/api/goods-attribute.js
deleted
100644 → 0
View file @
126d027a
import
request
from
'
@/utils/request
'
export
function
listGoodsAttribute
(
query
)
{
return
request
({
url
:
'
/goods-attribute/list
'
,
method
:
'
get
'
,
params
:
query
})
}
export
function
createGoodsAttribute
(
data
)
{
return
request
({
url
:
'
/goods-attribute/create
'
,
method
:
'
post
'
,
data
})
}
export
function
readGoodsAttribute
(
data
)
{
return
request
({
url
:
'
/goods-attribute/read
'
,
method
:
'
get
'
,
data
})
}
export
function
updateGoodsAttribute
(
data
)
{
return
request
({
url
:
'
/goods-attribute/update
'
,
method
:
'
post
'
,
data
})
}
export
function
deleteGoodsAttribute
(
data
)
{
return
request
({
url
:
'
/goods-attribute/delete
'
,
method
:
'
post
'
,
data
})
}
litemall-admin/src/api/goods-specification.js
deleted
100644 → 0
View file @
126d027a
import
request
from
'
@/utils/request
'
export
function
listGoodsSpecification
(
query
)
{
return
request
({
url
:
'
/goods-specification/list
'
,
method
:
'
get
'
,
params
:
query
})
}
export
function
createGoodsSpecification
(
data
)
{
return
request
({
url
:
'
/goods-specification/create
'
,
method
:
'
post
'
,
data
})
}
export
function
readGoodsSpecification
(
data
)
{
return
request
({
url
:
'
/goods-specification/read
'
,
method
:
'
get
'
,
data
})
}
export
function
updateGoodsSpecification
(
data
)
{
return
request
({
url
:
'
/goods-specification/update
'
,
method
:
'
post
'
,
data
})
}
export
function
deleteGoodsSpecification
(
data
)
{
return
request
({
url
:
'
/goods-specification/delete
'
,
method
:
'
post
'
,
data
})
}
export
function
listGoodsSpecificationVo
(
query
)
{
return
request
({
url
:
'
/goods-specification/volist
'
,
method
:
'
get
'
,
params
:
query
})
}
litemall-admin/src/api/goods.js
View file @
b68151cb
...
...
@@ -8,7 +8,15 @@ export function listGoods(query) {
})
}
export
function
createGoods
(
data
)
{
export
function
deleteGoods
(
data
)
{
return
request
({
url
:
'
/goods/delete
'
,
method
:
'
post
'
,
data
})
}
export
function
publishGoods
(
data
)
{
return
request
({
url
:
'
/goods/create
'
,
method
:
'
post
'
,
...
...
@@ -16,15 +24,15 @@ export function createGoods(data) {
})
}
export
function
read
Goods
(
d
ata
)
{
export
function
detail
Goods
(
i
d
)
{
return
request
({
url
:
'
/goods/
read
'
,
url
:
'
/goods/
detail
'
,
method
:
'
get
'
,
data
params
:
{
id
}
})
}
export
function
update
Goods
(
data
)
{
export
function
edit
Goods
(
data
)
{
return
request
({
url
:
'
/goods/update
'
,
method
:
'
post
'
,
...
...
@@ -32,10 +40,9 @@ export function updateGoods(data) {
})
}
export
function
deleteGoods
(
data
)
{
export
function
listCatAndBrand
(
)
{
return
request
({
url
:
'
/goods/delete
'
,
method
:
'
post
'
,
data
url
:
'
/goods/catAndBrand
'
,
method
:
'
get
'
})
}
litemall-admin/src/api/order.js
View file @
b68151cb
...
...
@@ -8,33 +8,17 @@ export function listOrder(query) {
})
}
export
function
create
Order
(
data
)
{
export
function
ship
Order
(
data
)
{
return
request
({
url
:
'
/order/
create
'
,
url
:
'
/order/
ship
'
,
method
:
'
post
'
,
data
})
}
export
function
re
a
dOrder
(
data
)
{
export
function
re
fun
dOrder
(
data
)
{
return
request
({
url
:
'
/order/read
'
,
method
:
'
get
'
,
data
})
}
export
function
updateOrder
(
data
)
{
return
request
({
url
:
'
/order/update
'
,
method
:
'
post
'
,
data
})
}
export
function
deleteOrder
(
data
)
{
return
request
({
url
:
'
/order/delete
'
,
url
:
'
/order/refund
'
,
method
:
'
post
'
,
data
})
...
...
litemall-admin/src/api/product.js
deleted
100644 → 0
View file @
126d027a
import
request
from
'
@/utils/request
'
export
function
listProduct
(
query
)
{
return
request
({
url
:
'
/product/list
'
,
method
:
'
get
'
,
params
:
query
})
}
export
function
createProduct
(
data
)
{
return
request
({
url
:
'
/product/create
'
,
method
:
'
post
'
,
data
})
}
export
function
readProduct
(
data
)
{
return
request
({
url
:
'
/product/read
'
,
method
:
'
get
'
,
data
})
}
export
function
updateProduct
(
data
)
{
return
request
({
url
:
'
/product/update
'
,
method
:
'
post
'
,
data
})
}
export
function
deleteProduct
(
data
)
{
return
request
({
url
:
'
/product/delete
'
,
method
:
'
post
'
,
data
})
}
litemall-admin/src/api/stat.js
0 → 100644
View file @
b68151cb
import
request
from
'
@/utils/request
'
export
function
statUser
(
query
)
{
return
request
({
url
:
'
/stat/user
'
,
method
:
'
get
'
,
params
:
query
})
}
export
function
statOrder
(
query
)
{
return
request
({
url
:
'
/stat/order
'
,
method
:
'
get
'
,
params
:
query
})
}
export
function
statGoods
(
query
)
{
return
request
({
url
:
'
/stat/goods
'
,
method
:
'
get
'
,
params
:
query
})
}
litemall-admin/src/api/storage.js
View file @
b68151cb
...
...
@@ -60,3 +60,6 @@ export function deleteStorage(data) {
data
})
}
const
uploadPath
=
process
.
env
.
OS_API
+
'
/storage/create
'
export
{
uploadPath
}
litemall-admin/src/directive/sticky.js
deleted
100644 → 0
View file @
126d027a
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
deleted
100644 → 0
View file @
126d027a
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
deleted
100644 → 0
View file @
126d027a
.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
deleted
100644 → 0
View file @
126d027a
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
)
}
}
litemall-admin/src/permission.js
View file @
b68151cb
...
...
@@ -14,7 +14,7 @@ function hasPermission(roles, permissionRoles) {
return
roles
.
some
(
role
=>
permissionRoles
.
indexOf
(
role
)
>=
0
)
}
const
whiteList
=
[
'
/login
'
,
'
/authredirect
'
]
// no redirect whitelist
const
whiteList
=
[
'
/login
'
]
// no redirect whitelist
router
.
beforeEach
((
to
,
from
,
next
)
=>
{
NProgress
.
start
()
// start progress bar
...
...
@@ -33,7 +33,7 @@ router.beforeEach((to, from, next) => {
})
}).
catch
(()
=>
{
store
.
dispatch
(
'
FedLogOut
'
).
then
(()
=>
{
Message
.
error
(
'
Verification failed, please login again
'
)
Message
.
error
(
'
验证失败,请输入正确的用户名和密码
'
)
next
({
path
:
'
/login
'
})
})
})
...
...
litemall-admin/src/router/index.js
View file @
b68151cb
...
...
@@ -29,7 +29,6 @@ import Layout from '../views/layout/Layout'
**/
export
const
constantRouterMap
=
[
{
path
:
'
/login
'
,
component
:
_import
(
'
login/index
'
),
hidden
:
true
},
{
path
:
'
/authredirect
'
,
component
:
_import
(
'
login/authredirect
'
),
hidden
:
true
},
{
path
:
'
/404
'
,
component
:
_import
(
'
error/404
'
),
hidden
:
true
},
{
path
:
'
/401
'
,
component
:
_import
(
'
error/401
'
),
hidden
:
true
},
{
...
...
@@ -66,8 +65,7 @@ export const asyncRouterMap = [
{
path
:
'
address
'
,
component
:
_import
(
'
user/address
'
),
name
:
'
address
'
,
meta
:
{
title
:
'
收货地址
'
,
noCache
:
true
}},
{
path
:
'
collect
'
,
component
:
_import
(
'
user/collect
'
),
name
:
'
collect
'
,
meta
:
{
title
:
'
会员收藏
'
,
noCache
:
true
}},
{
path
:
'
footprint
'
,
component
:
_import
(
'
user/footprint
'
),
name
:
'
footprint
'
,
meta
:
{
title
:
'
会员足迹
'
,
noCache
:
true
}},
{
path
:
'
history
'
,
component
:
_import
(
'
user/history
'
),
name
:
'
history
'
,
meta
:
{
title
:
'
搜索历史
'
,
noCache
:
true
}},
{
path
:
'
cart
'
,
component
:
_import
(
'
user/cart
'
),
name
:
'
cart
'
,
meta
:
{
title
:
'
购物车
'
,
noCache
:
true
}}
{
path
:
'
history
'
,
component
:
_import
(
'
user/history
'
),
name
:
'
history
'
,
meta
:
{
title
:
'
搜索历史
'
,
noCache
:
true
}}
]
},
...
...
@@ -100,13 +98,13 @@ export const asyncRouterMap = [
icon
:
'
chart
'
},
children
:
[
{
path
:
'
goods
'
,
component
:
_import
(
'
goods/goods
'
),
name
:
'
goods
'
,
meta
:
{
title
:
'
商品管理
'
,
noCache
:
true
}},
{
path
:
'
attribute
'
,
component
:
_import
(
'
goods/attribute
'
),
name
:
'
attribute
'
,
meta
:
{
title
:
'
商品参数
'
,
noCache
:
true
}},
{
path
:
'
specification
'
,
component
:
_import
(
'
goods/specification
'
),
name
:
'
specification
'
,
meta
:
{
title
:
'
商品规格
'
,
noCache
:
true
}},
{
path
:
'
product
'
,
component
:
_import
(
'
goods/product
'
),
name
:
'
product
'
,
meta
:
{
title
:
'
货品管理
'
,
noCache
:
true
}},
{
path
:
'
comment
'
,
component
:
_import
(
'
goods/comment
'
),
name
:
'
comment
'
,
meta
:
{
title
:
'
用户评论
'
,
noCache
:
true
}}
{
path
:
'
list
'
,
component
:
_import
(
'
goods/list
'
),
name
:
'
goodsList
'
,
meta
:
{
title
:
'
商品列表
'
,
noCache
:
true
}},
{
path
:
'
create
'
,
component
:
_import
(
'
goods/create
'
),
name
:
'
goodsCreate
'
,
meta
:
{
title
:
'
商品上架
'
,
noCache
:
true
}},
{
path
:
'
edit
'
,
component
:
_import
(
'
goods/edit
'
),
name
:
'
goodsEdit
'
,
meta
:
{
title
:
'
商品编辑
'
,
noCache
:
true
},
hidden
:
true
},
{
path
:
'
comment
'
,
component
:
_import
(
'
goods/comment
'
),
name
:
'
goodsComment
'
,
meta
:
{
title
:
'
商品评论
'
,
noCache
:
true
}}
]
},
{
path
:
'
/promotion
'
,
component
:
Layout
,
...
...
@@ -121,6 +119,7 @@ export const asyncRouterMap = [
{
path
:
'
topic
'
,
component
:
_import
(
'
promotion/topic
'
),
name
:
'
topic
'
,
meta
:
{
title
:
'
专题管理
'
,
noCache
:
true
}}
]
},
{
path
:
'
/sys
'
,
component
:
Layout
,
...
...
@@ -136,5 +135,21 @@ export const asyncRouterMap = [
]
},
{
path
:
'
/stat
'
,
component
:
Layout
,
redirect
:
'
noredirect
'
,
name
:
'
statManage
'
,
meta
:
{
title
:
'
统计
'
,
icon
:
'
chart
'
},
children
:
[
{
path
:
'
user
'
,
component
:
_import
(
'
stat/user
'
),
name
:
'
statUser
'
,
meta
:
{
title
:
'
用户统计
'
,
noCache
:
true
}},
{
path
:
'
order
'
,
component
:
_import
(
'
stat/order
'
),
name
:
'
statOrder
'
,
meta
:
{
title
:
'
订单统计
'
,
noCache
:
true
}},
{
path
:
'
goods
'
,
component
:
_import
(
'
stat/goods
'
),
name
:
'
statGoods
'
,
meta
:
{
title
:
'
商品统计
'
,
noCache
:
true
}}
]
},
{
path
:
'
*
'
,
redirect
:
'
/404
'
,
hidden
:
true
}
]
litemall-admin/src/utils/request.js
View file @
b68151cb
...
...
@@ -26,22 +26,32 @@ service.interceptors.request.use(config => {
service
.
interceptors
.
response
.
use
(
response
=>
{
const
res
=
response
.
data
if
(
res
.
errno
===
502
)
{
MessageBox
.
alert
(
'
系统内部错误,请联系管理员维护
'
,
'
错误
'
,
{
if
(
res
.
errno
===
501
)
{
MessageBox
.
alert
(
'
系统未登录,请重新登录
'
,
'
未登录
'
,
{
confirmButtonText
:
'
确定
'
,
type
:
'
error
'
})
return
Promise
.
reject
(
'
error
'
)
}
else
if
(
res
.
errno
!==
0
)
{
MessageBox
.
alert
(
'
超时自动退出系统,请重新登录
'
,
'
已退出
'
,
{
confirmButtonText
:
'
重新登录
'
,
type
:
'
error
'
}).
then
(()
=>
{
store
.
dispatch
(
'
FedLogOut
'
).
then
(()
=>
{
location
.
reload
()
})
})
return
Promise
.
reject
(
'
error
'
)
}
else
if
(
res
.
errno
===
502
)
{
MessageBox
.
alert
(
'
系统内部错误,请联系管理员维护
'
,
'
错误
'
,
{
confirmButtonText
:
'
确定
'
,
type
:
'
error
'
})
return
Promise
.
reject
(
'
error
'
)
}
else
if
(
res
.
errno
===
503
)
{
MessageBox
.
alert
(
'
请求业务目前未支持
'
,
'
警告
'
,
{
confirmButtonText
:
'
确定
'
,
type
:
'
error
'
})
return
Promise
.
reject
(
'
error
'
)
}
else
if
(
res
.
errno
!==
0
)
{
// 非5xx的错误属于业务错误,留给具体页面处理
return
Promise
.
reject
(
response
)
}
else
{
return
response
}
...
...
litemall-admin/src/views/goods/attribute.vue
deleted
100644 → 0
View file @
126d027a
<
template
>
<div
class=
"app-container calendar-list-container"
>
<!-- 查询和其他操作 -->
<div
class=
"filter-container"
>
<el-input
clearable
class=
"filter-item"
style=
"width: 200px;"
placeholder=
"请输入商品ID"
v-model=
"listQuery.goodsId"
>
</el-input>
<el-button
class=
"filter-item"
type=
"primary"
v-waves
icon=
"el-icon-search"
@
click=
"handleFilter"
>
查找
</el-button>
<el-button
class=
"filter-item"
type=
"primary"
@
click=
"handleCreate"
icon=
"el-icon-edit"
>
添加
</el-button>
<el-button
class=
"filter-item"
type=
"primary"
:loading=
"downloadLoading"
v-waves
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-column
align=
"center"
width=
"150px"
label=
"商品参数ID"
prop=
"id"
sortable
>
</el-table-column>
<el-table-column
align=
"center"
min-width=
"100px"
label=
"商品ID"
prop=
"goodsId"
>
</el-table-column>
<el-table-column
align=
"center"
min-width=
"100px"
label=
"商品参数名称"
prop=
"attribute"
>
</el-table-column>
<el-table-column
align=
"center"
min-width=
"200px"
label=
"商品参数值"
prop=
"value"
>
</el-table-column>
<el-table-column
align=
"center"
label=
"操作"
width=
"250"
class-name=
"small-padding fixed-width"
>
<template
slot-scope=
"scope"
>
<el-button
type=
"primary"
size=
"mini"
@
click=
"handleUpdate(scope.row)"
>
编辑
</el-button>
<el-button
type=
"danger"
size=
"mini"
@
click=
"handleDelete(scope.row)"
>
删除
</el-button>
</
template
>
</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>
<!-- 添加或修改对话框 -->
<el-dialog
:title=
"textMap[dialogStatus]"
:visible.sync=
"dialogFormVisible"
>
<el-form
:rules=
"rules"
ref=
"dataForm"
:model=
"dataForm"
status-icon
label-position=
"left"
label-width=
"100px"
style=
'width: 400px; margin-left:50px;'
>
<el-form-item
label=
"商品ID"
prop=
"goodsId"
>
<el-input
v-model=
"dataForm.goodsId"
></el-input>
</el-form-item>
<el-form-item
label=
"商品参数名"
prop=
"attribute"
>
<el-input
v-model=
"dataForm.attribute"
></el-input>
</el-form-item>
<el-form-item
label=
"商品参数值"
prop=
"value"
>
<el-input
v-model=
"dataForm.value"
></el-input>
</el-form-item>
</el-form>
<div
slot=
"footer"
class=
"dialog-footer"
>
<el-button
@
click=
"dialogFormVisible = false"
>
取消
</el-button>
<el-button
v-if=
"dialogStatus=='create'"
type=
"primary"
@
click=
"createData"
>
确定
</el-button>
<el-button
v-else
type=
"primary"
@
click=
"updateData"
>
确定
</el-button>
</div>
</el-dialog>
</div>
</template>
<
script
>
import
{
listGoodsAttribute
,
createGoodsAttribute
,
updateGoodsAttribute
,
deleteGoodsAttribute
}
from
'
@/api/goods-attribute
'
import
waves
from
'
@/directive/waves
'
// 水波纹指令
export
default
{
name
:
'
GoodsAttribute
'
,
directives
:
{
waves
},
data
()
{
return
{
list
:
null
,
total
:
null
,
listLoading
:
true
,
listQuery
:
{
page
:
1
,
limit
:
10
,
goodsId
:
undefined
,
sort
:
'
+id
'
},
dataForm
:
{
id
:
undefined
,
goodsId
:
undefined
,
attribute
:
undefined
,
value
:
undefined
},
dialogFormVisible
:
false
,
dialogStatus
:
''
,
textMap
:
{
update
:
'
编辑
'
,
create
:
'
创建
'
},
rules
:
{
goodsId
:
[{
required
:
true
,
message
:
'
商品ID不能为空
'
,
trigger
:
'
blur
'
}],
attribute
:
[{
required
:
true
,
message
:
'
商品参数名称不能为空
'
,
trigger
:
'
blur
'
}],
value
:
[{
required
:
true
,
message
:
'
商品参数值不能为空
'
,
trigger
:
'
blur
'
}]
},
downloadLoading
:
false
}
},
created
()
{
this
.
getList
()
},
methods
:
{
getList
()
{
this
.
listLoading
=
true
listGoodsAttribute
(
this
.
listQuery
).
then
(
response
=>
{
this
.
list
=
response
.
data
.
data
.
items
this
.
total
=
response
.
data
.
data
.
total
this
.
listLoading
=
false
}).
catch
(()
=>
{
this
.
list
=
[]
this
.
total
=
0
this
.
listLoading
=
false
})
},
handleFilter
()
{
this
.
listQuery
.
page
=
1
this
.
getList
()
},
handleSizeChange
(
val
)
{
this
.
listQuery
.
limit
=
val
this
.
getList
()
},
handleCurrentChange
(
val
)
{
this
.
listQuery
.
page
=
val
this
.
getList
()
},
resetForm
()
{
this
.
dataForm
=
{
id
:
undefined
,
goodsId
:
undefined
,
attribute
:
undefined
,
value
:
undefined
}
},
handleCreate
()
{
this
.
resetForm
()
this
.
dialogStatus
=
'
create
'
this
.
dialogFormVisible
=
true
this
.
$nextTick
(()
=>
{
this
.
$refs
[
'
dataForm
'
].
clearValidate
()
})
},
createData
()
{
this
.
$refs
[
'
dataForm
'
].
validate
((
valid
)
=>
{
if
(
valid
)
{
createGoodsAttribute
(
this
.
dataForm
).
then
(
response
=>
{
this
.
list
.
unshift
(
response
.
data
.
data
)
this
.
dialogFormVisible
=
false
this
.
$notify
({
title
:
'
成功
'
,
message
:
'
创建成功
'
,
type
:
'
success
'
,
duration
:
2000
})
})
}
})
},
handleUpdate
(
row
)
{
this
.
dataForm
=
Object
.
assign
({},
row
)
this
.
dialogStatus
=
'
update
'
this
.
dialogFormVisible
=
true
this
.
$nextTick
(()
=>
{
this
.
$refs
[
'
dataForm
'
].
clearValidate
()
})
},
updateData
()
{
this
.
$refs
[
'
dataForm
'
].
validate
((
valid
)
=>
{
if
(
valid
)
{
updateGoodsAttribute
(
this
.
dataForm
).
then
(()
=>
{
for
(
const
v
of
this
.
list
)
{
if
(
v
.
id
===
this
.
dataForm
.
id
)
{
const
index
=
this
.
list
.
indexOf
(
v
)
this
.
list
.
splice
(
index
,
1
,
this
.
dataForm
)
break
}
}
this
.
dialogFormVisible
=
false
this
.
$notify
({
title
:
'
成功
'
,
message
:
'
更新成功
'
,
type
:
'
success
'
,
duration
:
2000
})
})
}
})
},
handleDelete
(
row
)
{
deleteGoodsAttribute
(
row
).
then
(
response
=>
{
this
.
$notify
({
title
:
'
成功
'
,
message
:
'
删除成功
'
,
type
:
'
success
'
,
duration
:
2000
})
const
index
=
this
.
list
.
indexOf
(
row
)
this
.
list
.
splice
(
index
,
1
)
})
},
handleDownload
()
{
this
.
downloadLoading
=
true
import
(
'
@/vendor/Export2Excel
'
).
then
(
excel
=>
{
const
tHeader
=
[
'
商品参数ID
'
,
'
商品ID
'
,
'
商品参数名称
'
,
'
商品参数值
'
]
const
filterVal
=
[
'
id
'
,
'
goodsId
'
,
'
attribute
'
,
'
value
'
]
excel
.
export_json_to_excel2
(
tHeader
,
this
.
list
,
filterVal
,
'
商品参数信息
'
)
this
.
downloadLoading
=
false
})
}
}
}
</
script
>
litemall-admin/src/views/goods/comment.vue
View file @
b68151cb
...
...
@@ -7,33 +7,33 @@
</el-input>
<el-input
clearable
class=
"filter-item"
style=
"width: 200px;"
placeholder=
"请输入商品ID"
v-model=
"listQuery.valueId"
>
</el-input>
<el-button
class=
"filter-item"
type=
"primary"
v-waves
icon=
"el-icon-search"
@
click=
"handleFilter"
>
查找
</el-button>
<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-edit"
@
click=
"handleCreate"
>
添加
</el-button>
<el-button
class=
"filter-item"
type=
"primary"
v-waves
icon=
"el-icon-download"
@
click=
"handleDownload"
:loading=
"downloadLoading"
>
导出
</el-button>
<el-button
class=
"filter-item"
type=
"primary"
icon=
"el-icon-download"
@
click=
"handleDownload"
:loading=
"downloadLoading"
>
导出
</el-button>
</div>
<!-- 查询结果 -->
<el-table
size=
"small"
:data=
"list"
v-loading=
"listLoading"
element-loading-text=
"正在查询中。。。"
border
fit
highlight-current-row
>
<el-table-column
align=
"center"
width=
"150px"
label=
"
评论
ID"
prop=
"
id"
sortable
>
<el-table-column
align=
"center"
label=
"
用户
ID"
prop=
"
userId"
>
</el-table-column>
<el-table-column
align=
"center"
width=
"100px"
label=
"
用户
ID"
prop=
"
user
Id"
>
<el-table-column
align=
"center"
label=
"
商品
ID"
prop=
"
value
Id"
>
</el-table-column>
<el-table-column
align=
"center"
width=
"100px"
label=
"
商品ID
"
prop=
"
valueId
"
>
<el-table-column
align=
"center"
label=
"
评论内容
"
prop=
"
content
"
>
</el-table-column>
<el-table-column
align=
"center"
min-width=
"200px"
label=
"评论
内容
"
prop=
"
content
"
>
</el-table-column
>
<el-table-column
align=
"center"
min-width=
"200px"
label=
"评论图片"
prop=
"picUrls"
>
<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"
/>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
min-width=
"100px"
label=
"时间"
prop=
"addTime"
>
<el-table-column
align=
"center"
label=
"时间"
prop=
"addTime"
>
</el-table-column>
<el-table-column
align=
"center"
label=
"操作"
width=
"2
5
0"
class-name=
"small-padding fixed-width"
>
<el-table-column
align=
"center"
label=
"操作"
width=
"2
0
0"
class-name=
"small-padding fixed-width"
>
<
template
slot-scope=
"scope"
>
<el-button
type=
"primary"
size=
"mini"
@
click=
"handleUpdate(scope.row)"
>
编辑
</el-button>
<el-button
type=
"danger"
size=
"mini"
@
click=
"handleDelete(scope.row)"
>
删除
</el-button>
...
...
@@ -98,13 +98,9 @@
<
script
>
import
{
listComment
,
createComment
,
updateComment
,
deleteComment
}
from
'
@/api/comment
'
import
{
createStorage
}
from
'
@/api/storage
'
import
waves
from
'
@/directive/waves
'
// 水波纹指令
export
default
{
name
:
'
Comment
'
,
directives
:
{
waves
},
data
()
{
return
{
list
:
undefined
,
...
...
@@ -115,7 +111,8 @@ export default {
limit
:
20
,
userId
:
undefined
,
valueId
:
undefined
,
sort
:
'
+id
'
sort
:
'
add_time
'
,
order
:
'
desc
'
},
dataForm
:
{
id
:
undefined
,
...
...
@@ -123,8 +120,7 @@ export default {
valueId
:
undefined
,
content
:
undefined
,
hasPicture
:
false
,
picUrls
:
[],
addTime
:
undefined
picUrls
:
[]
},
dialogFormVisible
:
false
,
dialogStatus
:
''
,
...
...
@@ -174,8 +170,7 @@ export default {
userId
:
undefined
,
valueId
:
undefined
,
content
:
undefined
,
picUrls
:
[],
addTime
:
undefined
picUrls
:
[]
}
},
handleCreate
()
{
...
...
litemall-admin/src/views/goods/create.vue
0 → 100644
View file @
b68151cb
<
template
>
<div
class=
"app-container calendar-list-container"
>
<el-card
class=
"box-card"
>
<h3>
商品介绍
</h3>
<el-form
:rules=
"rules"
ref=
"goods"
:model=
"goods"
label-width=
"150px"
>
<el-form-item
label=
"商品编号"
prop=
"goodsSn"
>
<el-input
v-model=
"goods.goodsSn"
></el-input>
</el-form-item>
<el-form-item
label=
"商品名称"
prop=
"name"
>
<el-input
v-model=
"goods.name"
></el-input>
</el-form-item>
<el-form-item
label=
"专柜价格"
prop=
"counterPrice"
>
<el-input
v-model=
"goods.counterPrice"
placeholder=
"0.00"
>
<template
slot=
"append"
>
元
</
template
>
</el-input>
</el-form-item>
<el-form-item
label=
"当前价格"
prop=
"retailPrice"
>
<el-input
v-model=
"goods.retailPrice"
placeholder=
"0.00"
>
<
template
slot=
"append"
>
元
</
template
>
</el-input>
</el-form-item>
<el-form-item
label=
"是否新品"
prop=
"isNew"
>
<el-radio-group
v-model=
"goods.isNew"
>
<el-radio
:label=
"true"
>
新品
</el-radio>
<el-radio
:label=
"false"
>
非新品
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label=
"是否热卖"
prop=
"isHot"
>
<el-radio-group
v-model=
"goods.isHot"
>
<el-radio
:label=
"false"
>
普通
</el-radio>
<el-radio
:label=
"true"
>
热卖
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label=
"是否在售"
prop=
"isOnSale"
>
<el-radio-group
v-model=
"goods.isOnSale"
>
<el-radio
:label=
"true"
>
在售
</el-radio>
<el-radio
:label=
"false"
>
未售
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label=
"商品图片"
>
<el-upload
class=
"avatar-uploader"
:action=
"uploadPath"
list-type=
"picture-card"
:show-file-list=
"false"
accept=
".jpg,.jpeg,.png,.gif"
:on-success=
"uploadPicUrl"
>
<img
v-if=
"goods.picUrl"
:src=
"goods.picUrl"
class=
"avatar"
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
></i>
</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"
:on-exceed=
"uploadOverrun"
:on-success=
"handleGalleryUrl"
:on-remove=
"handleRemove"
>
<i
class=
"el-icon-plus"
></i>
</el-upload>
</el-form-item>
<el-form-item
label=
"商品单位"
>
<el-input
v-model=
"goods.unit"
placeholder=
"件 / 个 / 盒"
></el-input>
</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>
<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-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-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-select>
</el-form-item>
<el-form-item
label=
"商品简介"
>
<el-input
v-model=
"goods.brief"
></el-input>
</el-form-item>
<el-form-item
label=
"商品详细介绍"
>
<editor
:init=
"editorInit"
v-model=
"goods.desc"
></editor>
</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-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>
</el-row>
<el-table
:data=
"specifications"
>
<el-table-column
property=
"specification"
label=
"规格名"
></el-table-column>
<el-table-column
property=
"value"
label=
"规格值"
>
<
template
slot-scope=
"scope"
>
<el-tag
type=
"primary"
>
{{
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"
/>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"操作"
width=
"250"
class-name=
"small-padding fixed-width"
v-if=
"multipleSpec"
>
<
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-form-item
label=
"规格名"
prop=
"specification"
>
<el-input
v-model=
"specForm.specification"
></el-input>
</el-form-item>
<el-form-item
label=
"规格值"
prop=
"value"
>
<el-input
v-model=
"specForm.value"
></el-input>
</el-form-item>
<el-form-item
label=
"规格图片"
prop=
"picUrl"
>
<el-upload
class=
"avatar-uploader"
:action=
'uploadPath'
list-type=
"picture-card"
:show-file-list=
"false"
accept=
".jpg,.jpeg,.png,.gif"
:on-success=
"uploadSpecPicUrl"
>
<img
v-if=
"specForm.picUrl"
:src=
"specForm.picUrl"
class=
"avatar"
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
></i>
</el-upload>
</el-form-item>
</el-form>
<div
slot=
"footer"
class=
"dialog-footer"
>
<el-button
@
click=
"specVisiable = false"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"handleSpecificationAdd"
>
确定
</el-button>
</div>
</el-dialog>
</el-card>
<el-card
class=
"box-card"
>
<h3>
商品库存
</h3>
<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>
</
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=
"url"
width=
"100"
label=
"货品图片"
>
<
template
slot-scope=
"scope"
>
<img
:src=
"scope.row.url"
width=
"40"
v-if=
"scope.row.url"
/>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"操作"
width=
"100"
class-name=
"small-padding fixed-width"
>
<
template
slot-scope=
"scope"
>
<el-button
type=
"primary"
size=
"mini"
@
click=
"handleProductShow(scope.row)"
>
设置
</el-button>
</
template
>
</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-form-item
label=
"货品规格列"
prop=
"specifications"
>
<el-tag
:key=
"tag"
v-for=
"tag in productForm.specifications"
>
{{tag}}
</el-tag>
</el-form-item>
<el-form-item
label=
"货品售价"
prop=
"price"
>
<el-input
v-model=
"productForm.price"
></el-input>
</el-form-item>
<el-form-item
label=
"货品数量"
prop=
"number"
>
<el-input
v-model=
"productForm.number"
></el-input>
</el-form-item>
<el-form-item
label=
"货品图片"
prop=
"url"
>
<el-upload
class=
"avatar-uploader"
:action=
'uploadPath'
list-type=
"picture-card"
:show-file-list=
"false"
accept=
".jpg,.jpeg,.png,.gif"
:on-success=
"uploadProductUrl"
>
<img
v-if=
"productForm.url"
:src=
"productForm.url"
class=
"avatar"
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
></i>
</el-upload>
</el-form-item>
</el-form>
<div
slot=
"footer"
class=
"dialog-footer"
>
<el-button
@
click=
"productVisiable = false"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"handleProductEdit"
>
确定
</el-button>
</div>
</el-dialog>
</el-card>
<el-card
class=
"box-card"
>
<h3>
商品参数
</h3>
<el-button
:plain=
"true"
@
click=
"handleAttributeShow"
type=
"primary"
>
添加
</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
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>
</
template
>
</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-form-item
label=
"商品参数名称"
prop=
"attribute"
>
<el-input
v-model=
"attributeForm.attribute"
></el-input>
</el-form-item>
<el-form-item
label=
"商品参数值"
prop=
"value"
>
<el-input
v-model=
"attributeForm.value"
></el-input>
</el-form-item>
</el-form>
<div
slot=
"footer"
class=
"dialog-footer"
>
<el-button
@
click=
"attributeVisiable = false"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"handleAttributeAdd"
>
确定
</el-button>
</div>
</el-dialog>
</el-card>
<div
class=
"op-container"
>
<el-button
@
click=
"handleCancel"
>
取消
</el-button>
<el-button
@
click=
"handlePublish"
type=
"primary"
>
上架
</el-button>
</div>
</div>
</template>
<
style
>
.el-card
{
margin-bottom
:
10px
;
}
.el-tag
+
.el-tag
{
margin-left
:
10px
;
}
.input-new-keyword
{
width
:
90px
;
margin-left
:
10px
;
vertical-align
:
bottom
;
}
.avatar-uploader
.el-upload
{
border
:
1px
dashed
#d9d9d9
;
border-radius
:
6px
;
cursor
:
pointer
;
position
:
relative
;
overflow
:
hidden
;
}
.avatar-uploader
.el-upload
:hover
{
border-color
:
#20a0ff
;
}
.avatar-uploader-icon
{
font-size
:
28px
;
color
:
#8c939d
;
width
:
120px
;
height
:
120px
;
line-height
:
120px
;
text-align
:
center
;
}
.avatar
{
width
:
120px
;
height
:
120px
;
display
:
block
;
}
</
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
'
export
default
{
name
:
'
GoodsCreate
'
,
components
:
{
Editor
},
data
()
{
return
{
uploadPath
,
newKeywordVisible
:
false
,
newKeyword
:
''
,
keywords
:
[],
categoryList
:
[],
brandList
:
[],
goods
:
{
picUrl
:
''
,
gallery
:
[]
},
specVisiable
:
false
,
specForm
:
{
specification
:
''
,
value
:
''
,
picUrl
:
''
},
multipleSpec
:
false
,
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
:
''
}],
attributeVisiable
:
false
,
attributeForm
:
{
attribute
:
''
,
value
:
''
},
attributes
:
[],
rules
:
{
goodsSn
:
[{
required
:
true
,
message
:
'
商品编号不能为空
'
,
trigger
:
'
blur
'
}],
name
:
[{
required
:
true
,
message
:
'
商品名称不能为空
'
,
trigger
:
'
blur
'
}]
},
editorInit
:
{
language
:
'
zh_CN
'
,
plugins
:
[
'
advlist anchor autolink autoresize autosave emoticons fullscreen hr image imagetools importcss insertdatetime legacyoutput link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace tabfocus table template textcolor textpattern visualblocks visualchars wordcount
'
],
toolbar
:
[
'
bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript
'
,
'
hr bullist numlist link image charmap preview anchor pagebreak fullscreen media table emoticons forecolor backcolor
'
],
images_upload_handler
:
function
(
blobInfo
,
success
,
failure
)
{
const
formData
=
new
FormData
()
formData
.
append
(
'
file
'
,
blobInfo
.
blob
())
createStorage
(
formData
).
then
(
res
=>
{
success
(
res
.
data
.
data
.
url
)
}).
catch
(()
=>
{
failure
(
'
上传失败,请重新上传
'
)
})
}
}
}
},
created
()
{
this
.
init
()
},
methods
:
{
init
:
function
()
{
listCatAndBrand
().
then
(
response
=>
{
this
.
categoryList
=
response
.
data
.
data
.
categoryList
this
.
brandList
=
response
.
data
.
data
.
brandList
})
},
handleCategoryChange
(
value
)
{
this
.
goods
.
categoryId
=
value
[
value
.
length
-
1
]
},
handleCancel
:
function
()
{
this
.
$router
.
push
({
path
:
'
/goods/goods
'
})
},
handlePublish
:
function
()
{
const
finalGoods
=
{
goods
:
this
.
goods
,
specifications
:
this
.
specifications
,
products
:
this
.
products
,
attributes
:
this
.
attributes
}
publishGoods
(
finalGoods
).
then
(
response
=>
{
this
.
$notify
({
title
:
'
成功
'
,
message
:
'
创建成功
'
,
type
:
'
success
'
,
duration
:
2000
})
this
.
$router
.
push
({
path
:
'
/goods/list
'
})
}).
catch
(
response
=>
{
MessageBox
.
alert
(
'
业务错误:
'
+
response
.
data
.
errmsg
,
'
警告
'
,
{
confirmButtonText
:
'
确定
'
,
type
:
'
error
'
})
})
},
handleClose
(
tag
)
{
this
.
keywords
.
splice
(
this
.
keywords
.
indexOf
(
tag
),
1
)
this
.
goods
.
keywords
=
this
.
keywords
.
toString
()
},
showInput
()
{
this
.
newKeywordVisible
=
true
this
.
$nextTick
(
_
=>
{
this
.
$refs
.
newKeywordInput
.
$refs
.
input
.
focus
()
})
},
handleInputConfirm
()
{
const
newKeyword
=
this
.
newKeyword
if
(
newKeyword
)
{
this
.
keywords
.
push
(
newKeyword
)
this
.
goods
.
keywords
=
this
.
keywords
.
toString
()
}
this
.
newKeywordVisible
=
false
this
.
newKeyword
=
''
},
uploadPicUrl
:
function
(
response
)
{
this
.
goods
.
picUrl
=
response
.
data
.
url
},
uploadOverrun
:
function
()
{
this
.
$message
({
type
:
'
error
'
,
message
:
'
上传文件个数超出限制!最多上传5张图片!
'
})
},
handleGalleryUrl
(
response
,
file
,
fileList
)
{
if
(
response
.
errno
===
0
)
{
this
.
goods
.
gallery
.
push
(
response
.
data
.
url
)
}
},
handleRemove
:
function
(
file
,
fileList
)
{
for
(
var
i
=
0
;
i
<
this
.
goods
.
gallery
.
length
;
i
++
)
{
// 这里存在两种情况
// 1. 如果所删除图片是刚刚上传的图片,那么图片地址是file.response.data.url
// 此时的file.url虽然存在,但是是本机地址,而不是远程地址。
// 2. 如果所删除图片是后台返回的已有图片,那么图片地址是file.url
var
url
if
(
file
.
response
===
undefined
)
{
url
=
file
.
url
}
else
{
url
=
file
.
response
.
data
.
url
}
if
(
this
.
goods
.
gallery
[
i
]
===
url
)
{
this
.
goods
.
gallery
.
splice
(
i
,
1
)
}
}
},
specChanged
:
function
(
label
)
{
if
(
label
===
false
)
{
this
.
specifications
=
[{
specification
:
'
规格
'
,
value
:
'
标准
'
,
picUrl
:
''
}]
this
.
products
=
[{
id
:
0
,
specifications
:
[
'
标准
'
],
price
:
0.00
,
number
:
0
,
url
:
''
}]
}
else
{
this
.
specifications
=
[]
this
.
products
=
[]
}
},
uploadSpecPicUrl
:
function
(
response
)
{
this
.
specForm
.
picUrl
=
response
.
data
.
url
},
handleSpecificationShow
()
{
this
.
specForm
=
{}
this
.
specVisiable
=
true
},
handleSpecificationAdd
()
{
var
index
=
this
.
specifications
.
length
-
1
for
(
var
i
=
0
;
i
<
this
.
specifications
.
length
;
i
++
)
{
const
v
=
this
.
specifications
[
i
]
if
(
v
.
specification
===
this
.
specForm
.
specification
)
{
index
=
i
}
}
this
.
specifications
.
splice
(
index
+
1
,
0
,
this
.
specForm
)
this
.
specVisiable
=
false
this
.
specToProduct
()
},
handleSpecificationDelete
(
row
)
{
const
index
=
this
.
specifications
.
indexOf
(
row
)
this
.
specifications
.
splice
(
index
,
1
)
this
.
specToProduct
()
},
specToProduct
()
{
if
(
this
.
specifications
.
length
===
0
)
{
return
}
// 根据specifications创建临时规格列表
var
specValues
=
[]
var
spec
=
this
.
specifications
[
0
].
specification
var
values
=
[]
values
.
push
(
0
)
for
(
var
i
=
1
;
i
<
this
.
specifications
.
length
;
i
++
)
{
const
aspec
=
this
.
specifications
[
i
].
specification
if
(
aspec
===
spec
)
{
values
.
push
(
i
)
}
else
{
specValues
.
push
(
values
)
spec
=
aspec
values
=
[]
values
.
push
(
i
)
}
}
specValues
.
push
(
values
)
// 根据临时规格列表生产货品规格
// 算法基于 https://blog.csdn.net/tyhj_sf/article/details/53893125
var
productsIndex
=
0
var
products
=
[]
var
combination
=
[]
var
n
=
specValues
.
length
for
(
var
s
=
0
;
s
<
n
;
s
++
)
{
combination
[
s
]
=
0
}
var
index
=
0
var
isContinue
=
false
do
{
var
specifications
=
[]
for
(
var
x
=
0
;
x
<
n
;
x
++
)
{
var
z
=
specValues
[
x
][
combination
[
x
]]
specifications
.
push
(
this
.
specifications
[
z
].
value
)
}
products
[
productsIndex
]
=
{
id
:
productsIndex
,
specifications
:
specifications
,
price
:
0.00
,
number
:
0
,
url
:
''
}
productsIndex
++
index
++
combination
[
n
-
1
]
=
index
for
(
var
j
=
n
-
1
;
j
>=
0
;
j
--
)
{
if
(
combination
[
j
]
>=
specValues
[
j
].
length
)
{
combination
[
j
]
=
0
index
=
0
if
(
j
-
1
>=
0
)
{
combination
[
j
-
1
]
=
combination
[
j
-
1
]
+
1
}
}
}
isContinue
=
false
for
(
var
p
=
0
;
p
<
n
;
p
++
)
{
if
(
combination
[
p
]
!==
0
)
{
isContinue
=
true
}
}
}
while
(
isContinue
)
this
.
products
=
products
},
handleProductShow
(
row
)
{
this
.
productForm
=
Object
.
assign
({},
row
)
this
.
productVisiable
=
true
},
uploadProductUrl
:
function
(
response
)
{
this
.
productForm
.
url
=
response
.
data
.
url
},
handleProductEdit
()
{
for
(
var
i
=
0
;
i
<
this
.
products
.
length
;
i
++
)
{
const
v
=
this
.
products
[
i
]
if
(
v
.
id
===
this
.
productForm
.
id
)
{
this
.
products
.
splice
(
i
,
1
,
this
.
productForm
)
break
}
}
this
.
productVisiable
=
false
},
handleAttributeShow
()
{
this
.
attributeForm
=
{}
this
.
attributeVisiable
=
true
},
handleAttributeAdd
()
{
this
.
attributes
.
unshift
(
this
.
attributeForm
)
this
.
attributeVisiable
=
false
},
handleAttributeDelete
(
row
)
{
const
index
=
this
.
attributes
.
indexOf
(
row
)
this
.
attributes
.
splice
(
index
,
1
)
}
}
}
</
script
>
\ No newline at end of file
litemall-admin/src/views/goods/edit.vue
0 → 100644
View file @
b68151cb
<
template
>
<div
class=
"app-container calendar-list-container"
>
<el-card
class=
"box-card"
>
<h3>
商品介绍
</h3>
<el-form
:rules=
"rules"
ref=
"goods"
:model=
"goods"
label-width=
"150px"
>
<el-form-item
label=
"商品编号"
prop=
"goodsSn"
>
<el-input
v-model=
"goods.goodsSn"
></el-input>
</el-form-item>
<el-form-item
label=
"商品名称"
prop=
"name"
>
<el-input
v-model=
"goods.name"
></el-input>
</el-form-item>
<el-form-item
label=
"专柜价格"
prop=
"counterPrice"
>
<el-input
v-model=
"goods.counterPrice"
placeholder=
"0.00"
>
<template
slot=
"append"
>
元
</
template
>
</el-input>
</el-form-item>
<el-form-item
label=
"当前价格"
prop=
"retailPrice"
>
<el-input
v-model=
"goods.retailPrice"
placeholder=
"0.00"
>
<
template
slot=
"append"
>
元
</
template
>
</el-input>
</el-form-item>
<el-form-item
label=
"是否新品"
prop=
"isNew"
>
<el-radio-group
v-model=
"goods.isNew"
>
<el-radio
:label=
"true"
>
新品
</el-radio>
<el-radio
:label=
"false"
>
非新品
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label=
"是否热卖"
prop=
"isHot"
>
<el-radio-group
v-model=
"goods.isHot"
>
<el-radio
:label=
"false"
>
普通
</el-radio>
<el-radio
:label=
"true"
>
热卖
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label=
"是否在售"
prop=
"isOnSale"
>
<el-radio-group
v-model=
"goods.isOnSale"
>
<el-radio
:label=
"true"
>
在售
</el-radio>
<el-radio
:label=
"false"
>
未售
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label=
"商品图片"
>
<el-upload
class=
"avatar-uploader"
:action=
'uploadPath'
list-type=
"picture-card"
:show-file-list=
"false"
accept=
".jpg,.jpeg,.png,.gif"
:on-success=
"uploadPicUrl"
>
<img
v-if=
"goods.picUrl"
:src=
"goods.picUrl"
class=
"avatar"
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
></i>
</el-upload>
</el-form-item>
<el-form-item
label=
"宣传画廊"
>
<el-upload
:action=
'uploadPath'
: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>
</el-form-item>
<el-form-item
label=
"商品单位"
>
<el-input
v-model=
"goods.unit"
placeholder=
"件 / 个 / 盒"
></el-input>
</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>
<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-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-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-select>
</el-form-item>
<el-form-item
label=
"商品简介"
>
<el-input
v-model=
"goods.brief"
></el-input>
</el-form-item>
<el-form-item
label=
"商品详细介绍"
>
<editor
:init=
"editorInit"
v-model=
"goods.desc"
></editor>
</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-table
:data=
"specifications"
>
<el-table-column
property=
"specification"
label=
"规格名"
></el-table-column>
<el-table-column
property=
"value"
label=
"规格值"
>
<
template
slot-scope=
"scope"
>
<el-tag
type=
"primary"
>
{{
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"
/>
</
template
>
</el-table-column>
<el-table-column
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-form-item
label=
"规格名"
prop=
"specification"
>
<el-input
v-model=
"specForm.specification"
></el-input>
</el-form-item>
<el-form-item
label=
"规格值"
prop=
"value"
>
<el-input
v-model=
"specForm.value"
></el-input>
</el-form-item>
<el-form-item
label=
"规格图片"
prop=
"picUrl"
>
<el-upload
class=
"avatar-uploader"
:action=
'uploadPath'
list-type=
"picture-card"
:show-file-list=
"false"
accept=
".jpg,.jpeg,.png,.gif"
:on-success=
"uploadSpecPicUrl"
>
<img
v-if=
"specForm.picUrl"
:src=
"specForm.picUrl"
class=
"avatar"
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
></i>
</el-upload>
</el-form-item>
</el-form>
<div
slot=
"footer"
class=
"dialog-footer"
>
<el-button
@
click=
"specVisiable = false"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"handleSpecificationAdd"
>
确定
</el-button>
</div>
</el-dialog>
</el-card>
<el-card
class=
"box-card"
>
<h3>
商品库存
</h3>
<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>
</
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=
"url"
width=
"100"
label=
"货品图片"
>
<
template
slot-scope=
"scope"
>
<img
:src=
"scope.row.url"
width=
"40"
v-if=
"scope.row.url"
/>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"操作"
width=
"100"
class-name=
"small-padding fixed-width"
>
<
template
slot-scope=
"scope"
>
<el-button
type=
"primary"
size=
"mini"
@
click=
"handleProductShow(scope.row)"
>
设置
</el-button>
</
template
>
</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-form-item
label=
"货品规格列"
prop=
"specifications"
>
<el-tag
:key=
"tag"
v-for=
"tag in productForm.specifications"
>
{{tag}}
</el-tag>
</el-form-item>
<el-form-item
label=
"货品售价"
prop=
"price"
>
<el-input
v-model=
"productForm.price"
></el-input>
</el-form-item>
<el-form-item
label=
"货品数量"
prop=
"number"
>
<el-input
v-model=
"productForm.number"
></el-input>
</el-form-item>
<el-form-item
label=
"货品图片"
prop=
"url"
>
<el-upload
class=
"avatar-uploader"
:action=
'uploadPath'
list-type=
"picture-card"
:show-file-list=
"false"
accept=
".jpg,.jpeg,.png,.gif"
:on-success=
"uploadProductUrl"
>
<img
v-if=
"productForm.url"
:src=
"productForm.url"
class=
"avatar"
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
></i>
</el-upload>
</el-form-item>
</el-form>
<div
slot=
"footer"
class=
"dialog-footer"
>
<el-button
@
click=
"productVisiable = false"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"handleProductEdit"
>
确定
</el-button>
</div>
</el-dialog>
</el-card>
<el-card
class=
"box-card"
>
<h3>
商品参数
</h3>
<el-button
:plain=
"true"
@
click=
"handleAttributeShow"
type=
"primary"
>
添加
</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
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>
</
template
>
</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-form-item
label=
"商品参数名称"
prop=
"attribute"
>
<el-input
v-model=
"attributeForm.attribute"
></el-input>
</el-form-item>
<el-form-item
label=
"商品参数值"
prop=
"value"
>
<el-input
v-model=
"attributeForm.value"
></el-input>
</el-form-item>
</el-form>
<div
slot=
"footer"
class=
"dialog-footer"
>
<el-button
@
click=
"attributeVisiable = false"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"handleAttributeAdd"
>
确定
</el-button>
</div>
</el-dialog>
</el-card>
<div
class=
"op-container"
>
<el-button
@
click=
"handleCancel"
>
取消
</el-button>
<el-button
@
click=
"handleEdit"
type=
"primary"
>
更新商品
</el-button>
</div>
</div>
</template>
<
style
>
.el-card
{
margin-bottom
:
10px
;
}
.el-tag
+
.el-tag
{
margin-left
:
10px
;
}
.input-new-keyword
{
width
:
90px
;
margin-left
:
10px
;
vertical-align
:
bottom
;
}
.avatar-uploader
.el-upload
{
border
:
1px
dashed
#d9d9d9
;
border-radius
:
6px
;
cursor
:
pointer
;
position
:
relative
;
overflow
:
hidden
;
}
.avatar-uploader
.el-upload
:hover
{
border-color
:
#20a0ff
;
}
.avatar-uploader-icon
{
font-size
:
28px
;
color
:
#8c939d
;
width
:
120px
;
height
:
120px
;
line-height
:
120px
;
text-align
:
center
;
}
.avatar
{
width
:
120px
;
height
:
120px
;
display
:
block
;
}
</
style
>
<
script
>
import
{
detailGoods
,
editGoods
,
listCatAndBrand
}
from
'
@/api/goods
'
import
{
createStorage
,
uploadPath
}
from
'
@/api/storage
'
import
Editor
from
'
@tinymce/tinymce-vue
'
import
{
MessageBox
}
from
'
element-ui
'
export
default
{
name
:
'
GoodsEdit
'
,
components
:
{
Editor
},
data
()
{
return
{
uploadPath
,
newKeywordVisible
:
false
,
newKeyword
:
''
,
keywords
:
[],
galleryFileList
:
[],
categoryList
:
[],
brandList
:
[],
categoryIds
:
[],
goods
:
{
gallery
:
[]
},
specVisiable
:
false
,
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
:
''
}],
attributeVisiable
:
false
,
attributeForm
:
{
attribute
:
''
,
value
:
''
},
attributes
:
[],
rules
:
{
goodsSn
:
[{
required
:
true
,
message
:
'
商品编号不能为空
'
,
trigger
:
'
blur
'
}],
name
:
[{
required
:
true
,
message
:
'
商品名称不能为空
'
,
trigger
:
'
blur
'
}]
},
editorInit
:
{
language
:
'
zh_CN
'
,
plugins
:
[
'
advlist anchor autolink autoresize autosave emoticons fullscreen hr image imagetools importcss insertdatetime legacyoutput link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace tabfocus table template textcolor textpattern visualblocks visualchars wordcount
'
],
toolbar
:
[
'
bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript
'
,
'
hr bullist numlist link image charmap preview anchor pagebreak fullscreen media table emoticons forecolor backcolor
'
],
images_upload_handler
:
function
(
blobInfo
,
success
,
failure
)
{
const
formData
=
new
FormData
()
formData
.
append
(
'
file
'
,
blobInfo
.
blob
())
createStorage
(
formData
).
then
(
res
=>
{
success
(
res
.
data
.
data
.
url
)
}).
catch
(()
=>
{
failure
(
'
上传失败,请重新上传
'
)
})
}
}
}
},
created
()
{
this
.
init
()
},
methods
:
{
init
:
function
()
{
if
(
this
.
$route
.
query
.
id
==
null
)
{
return
}
const
goodsId
=
this
.
$route
.
query
.
id
detailGoods
(
goodsId
).
then
(
response
=>
{
this
.
goods
=
response
.
data
.
data
.
goods
this
.
specifications
=
response
.
data
.
data
.
specifications
this
.
products
=
response
.
data
.
data
.
products
this
.
attributes
=
response
.
data
.
data
.
attributes
this
.
categoryIds
=
response
.
data
.
data
.
categoryIds
this
.
galleryFileList
=
[]
for
(
var
i
=
0
;
i
<
this
.
goods
.
gallery
.
length
;
i
++
)
{
this
.
galleryFileList
.
push
({
url
:
this
.
goods
.
gallery
[
i
]
})
}
})
listCatAndBrand
().
then
(
response
=>
{
this
.
categoryList
=
response
.
data
.
data
.
categoryList
this
.
brandList
=
response
.
data
.
data
.
brandList
})
},
handleCategoryChange
(
value
)
{
this
.
goods
.
categoryId
=
value
[
value
.
length
-
1
]
},
handleCancel
:
function
()
{
this
.
$router
.
push
({
path
:
'
/goods/list
'
})
},
handleEdit
:
function
()
{
const
finalGoods
=
{
goods
:
this
.
goods
,
specifications
:
this
.
specifications
,
products
:
this
.
products
,
attributes
:
this
.
attributes
}
editGoods
(
finalGoods
).
then
(
response
=>
{
this
.
$notify
({
title
:
'
成功
'
,
message
:
'
创建成功
'
,
type
:
'
success
'
,
duration
:
2000
})
this
.
$router
.
push
({
path
:
'
/goods/list
'
})
}).
catch
(
response
=>
{
MessageBox
.
alert
(
'
业务错误:
'
+
response
.
data
.
errmsg
,
'
警告
'
,
{
confirmButtonText
:
'
确定
'
,
type
:
'
error
'
})
})
},
handleClose
(
tag
)
{
this
.
keywords
.
splice
(
this
.
keywords
.
indexOf
(
tag
),
1
)
this
.
goods
.
keywords
=
this
.
keywords
.
toString
()
},
showInput
()
{
this
.
newKeywordVisible
=
true
this
.
$nextTick
(
_
=>
{
this
.
$refs
.
newKeywordInput
.
$refs
.
input
.
focus
()
})
},
handleInputConfirm
()
{
const
newKeyword
=
this
.
newKeyword
if
(
newKeyword
)
{
this
.
keywords
.
push
(
newKeyword
)
this
.
goods
.
keywords
=
this
.
keywords
.
toString
()
}
this
.
newKeywordVisible
=
false
this
.
newKeyword
=
''
},
uploadPicUrl
:
function
(
response
)
{
this
.
goods
.
picUrl
=
response
.
data
.
url
},
uploadOverrun
:
function
()
{
this
.
$message
({
type
:
'
error
'
,
message
:
'
上传文件个数超出限制!最多上传5张图片!
'
})
},
handleGalleryUrl
(
response
,
file
,
fileList
)
{
if
(
response
.
errno
===
0
)
{
this
.
goods
.
gallery
.
push
(
response
.
data
.
url
)
}
},
handleRemove
:
function
(
file
,
fileList
)
{
for
(
var
i
=
0
;
i
<
this
.
goods
.
gallery
.
length
;
i
++
)
{
// 这里存在两种情况
// 1. 如果所删除图片是刚刚上传的图片,那么图片地址是file.response.data.url
// 此时的file.url虽然存在,但是是本机地址,而不是远程地址。
// 2. 如果所删除图片是后台返回的已有图片,那么图片地址是file.url
var
url
if
(
file
.
response
===
undefined
)
{
url
=
file
.
url
}
else
{
url
=
file
.
response
.
data
.
url
}
if
(
this
.
goods
.
gallery
[
i
]
===
url
)
{
this
.
goods
.
gallery
.
splice
(
i
,
1
)
}
}
},
specChanged
:
function
(
label
)
{
if
(
label
===
false
)
{
this
.
specifications
=
[{
specification
:
'
规格
'
,
value
:
'
标准
'
,
picUrl
:
''
}]
this
.
products
=
[{
id
:
0
,
specifications
:
[
'
标准
'
],
price
:
0.00
,
number
:
0
,
url
:
''
}]
}
else
{
this
.
specifications
=
[]
this
.
products
=
[]
}
},
uploadSpecPicUrl
:
function
(
response
)
{
this
.
specForm
.
picUrl
=
response
.
data
.
url
},
handleSpecificationShow
()
{
this
.
specForm
=
{}
this
.
specVisiable
=
true
},
handleSpecificationAdd
()
{
var
index
=
this
.
specifications
.
length
-
1
for
(
var
i
=
0
;
i
<
this
.
specifications
.
length
;
i
++
)
{
const
v
=
this
.
specifications
[
i
]
if
(
v
.
specification
===
this
.
specForm
.
specification
)
{
index
=
i
}
}
this
.
specifications
.
splice
(
index
+
1
,
0
,
this
.
specForm
)
this
.
specVisiable
=
false
this
.
specToProduct
()
},
handleSpecificationDelete
(
row
)
{
const
index
=
this
.
specifications
.
indexOf
(
row
)
this
.
specifications
.
splice
(
index
,
1
)
this
.
specToProduct
()
},
specToProduct
()
{
if
(
this
.
specifications
.
length
===
0
)
{
return
}
// 根据specifications创建临时规格列表
var
specValues
=
[]
var
spec
=
this
.
specifications
[
0
].
specification
var
values
=
[]
values
.
push
(
0
)
for
(
var
i
=
1
;
i
<
this
.
specifications
.
length
;
i
++
)
{
const
aspec
=
this
.
specifications
[
i
].
specification
if
(
aspec
===
spec
)
{
values
.
push
(
i
)
}
else
{
specValues
.
push
(
values
)
spec
=
aspec
values
=
[]
values
.
push
(
i
)
}
}
specValues
.
push
(
values
)
// 根据临时规格列表生产货品规格
// 算法基于 https://blog.csdn.net/tyhj_sf/article/details/53893125
var
productsIndex
=
0
var
products
=
[]
var
combination
=
[]
var
n
=
specValues
.
length
for
(
var
s
=
0
;
s
<
n
;
s
++
)
{
combination
[
s
]
=
0
}
var
index
=
0
var
isContinue
=
false
do
{
var
specifications
=
[]
for
(
var
x
=
0
;
x
<
n
;
x
++
)
{
var
z
=
specValues
[
x
][
combination
[
x
]]
specifications
.
push
(
this
.
specifications
[
z
].
value
)
}
products
[
productsIndex
]
=
{
id
:
productsIndex
,
specifications
:
specifications
,
price
:
0.00
,
number
:
0
,
url
:
''
}
productsIndex
++
index
++
combination
[
n
-
1
]
=
index
for
(
var
j
=
n
-
1
;
j
>=
0
;
j
--
)
{
if
(
combination
[
j
]
>=
specValues
[
j
].
length
)
{
combination
[
j
]
=
0
index
=
0
if
(
j
-
1
>=
0
)
{
combination
[
j
-
1
]
=
combination
[
j
-
1
]
+
1
}
}
}
isContinue
=
false
for
(
var
p
=
0
;
p
<
n
;
p
++
)
{
if
(
combination
[
p
]
!==
0
)
{
isContinue
=
true
}
}
}
while
(
isContinue
)
this
.
products
=
products
},
handleProductShow
(
row
)
{
this
.
productForm
=
Object
.
assign
({},
row
)
this
.
productVisiable
=
true
},
uploadProductUrl
:
function
(
response
)
{
this
.
productForm
.
url
=
response
.
data
.
url
},
handleProductEdit
()
{
for
(
var
i
=
0
;
i
<
this
.
products
.
length
;
i
++
)
{
const
v
=
this
.
products
[
i
]
if
(
v
.
id
===
this
.
productForm
.
id
)
{
this
.
products
.
splice
(
i
,
1
,
this
.
productForm
)
break
}
}
this
.
productVisiable
=
false
},
handleAttributeShow
()
{
this
.
attributeForm
=
{}
this
.
attributeVisiable
=
true
},
handleAttributeAdd
()
{
this
.
attributes
.
unshift
(
this
.
attributeForm
)
this
.
attributeVisiable
=
false
},
handleAttributeDelete
(
row
)
{
const
index
=
this
.
attributes
.
indexOf
(
row
)
this
.
attributes
.
splice
(
index
,
1
)
}
}
}
</
script
>
\ No newline at end of file
litemall-admin/src/views/goods/goods.vue
deleted
100644 → 0
View file @
126d027a
<
template
>
<div
class=
"app-container calendar-list-container"
>
<!-- 查询和其他操作 -->
<div
class=
"filter-container"
>
<el-input
clearable
class=
"filter-item"
style=
"width: 200px;"
placeholder=
"请输入商品编号"
v-model=
"listQuery.goodsSn"
>
</el-input>
<el-input
clearable
class=
"filter-item"
style=
"width: 200px;"
placeholder=
"请输入商品名称"
v-model=
"listQuery.name"
>
</el-input>
<el-button
class=
"filter-item"
type=
"primary"
v-waves
icon=
"el-icon-search"
@
click=
"handleFilter"
>
查找
</el-button>
<el-button
class=
"filter-item"
type=
"primary"
@
click=
"handleCreate"
icon=
"el-icon-edit"
>
添加
</el-button>
<el-button
class=
"filter-item"
type=
"primary"
:loading=
"downloadLoading"
v-waves
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-column
type=
"expand"
>
<template
slot-scope=
"props"
>
<el-form
label-position=
"left"
class=
"demo-table-expand"
>
<el-form-item
label=
"首页主图"
>
<span>
{{
props
.
row
.
listPicUrl
}}
</span>
</el-form-item>
<el-form-item
label=
"宣传画廊"
>
<span>
{{
props
.
row
.
gallery
}}
</span>
</el-form-item>
<el-form-item
label=
"商品介绍"
>
<span>
{{
props
.
row
.
goodsBrief
}}
</span>
</el-form-item>
<el-form-item
label=
"商品详细介绍"
>
<span>
{{
props
.
row
.
goodsDesc
}}
</span>
</el-form-item>
<el-form-item
label=
"商品主图"
>
<span>
{{
props
.
row
.
primaryPicUrl
}}
</span>
</el-form-item>
<el-form-item
label=
"商品单位"
>
<span>
{{
props
.
row
.
goodsUnit
}}
</span>
</el-form-item>
<el-form-item
label=
"关键字"
>
<span>
{{
props
.
row
.
keyword
}}
</span>
</el-form-item>
<el-form-item
label=
"类目ID"
>
<span>
{{
props
.
row
.
categoryId
}}
</span>
</el-form-item>
<el-form-item
label=
"品牌商ID"
>
<span>
{{
props
.
row
.
brandId
}}
</span>
</el-form-item>
</el-form>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
width=
"100px"
label=
"商品ID"
prop=
"id"
sortable
>
</el-table-column>
<el-table-column
align=
"center"
min-width=
"100px"
label=
"商品编号"
prop=
"goodsSn"
>
</el-table-column>
<el-table-column
align=
"center"
min-width=
"100px"
label=
"名称"
prop=
"name"
>
</el-table-column>
<el-table-column
align=
"center"
min-width=
"100px"
label=
"专柜价格"
prop=
"counterPrice"
>
</el-table-column>
<el-table-column
align=
"center"
min-width=
"100px"
label=
"当前价格"
prop=
"retailPrice"
>
</el-table-column>
<el-table-column
align=
"center"
min-width=
"100px"
label=
"是否新品"
prop=
"isNew"
>
<
template
slot-scope=
"scope"
>
<el-tag
:type=
"scope.row.isNew ? 'success' : 'error' "
>
{{
scope
.
row
.
isNew
?
'
新品
'
:
'
非新品
'
}}
</el-tag>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
min-width=
"100px"
label=
"是否热品"
prop=
"isHot"
>
<
template
slot-scope=
"scope"
>
<el-tag
:type=
"scope.row.isHot ? 'success' : 'error' "
>
{{
scope
.
row
.
isHot
?
'
热品
'
:
'
非热品
'
}}
</el-tag>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
min-width=
"100px"
label=
"是否在售"
prop=
"isOnSale"
>
<
template
slot-scope=
"scope"
>
<el-tag
:type=
"scope.row.isOnSale ? 'success' : 'error' "
>
{{
scope
.
row
.
isOnSale
?
'
在售
'
:
'
未售
'
}}
</el-tag>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"操作"
width=
"250"
class-name=
"small-padding fixed-width"
>
<
template
slot-scope=
"scope"
>
<el-button
type=
"primary"
size=
"mini"
@
click=
"handleUpdate(scope.row)"
>
编辑
</el-button>
<el-button
type=
"danger"
size=
"mini"
@
click=
"handleDelete(scope.row)"
>
删除
</el-button>
</
template
>
</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>
<el-tooltip
placement=
"top"
content=
"返回顶部"
>
<back-to-top
:visibilityHeight=
"100"
></back-to-top>
</el-tooltip>
<!-- 添加或修改对话框 -->
<el-dialog
:title=
"textMap[dialogStatus]"
:visible.sync=
"dialogFormVisible"
>
<el-form
:rules=
"rules"
ref=
"dataForm"
:model=
"dataForm"
status-icon
label-position=
"left"
label-width=
"100px"
style=
'width: 400px; margin-left:50px;'
>
<el-form-item
label=
"商品编号"
prop=
"goodsSn"
>
<el-input
v-model=
"dataForm.goodsSn"
></el-input>
</el-form-item>
<el-form-item
label=
"商品名称"
prop=
"name"
>
<el-input
v-model=
"dataForm.name"
></el-input>
</el-form-item>
<el-form-item
label=
"专柜价格"
prop=
"counterPrice"
>
<el-input
v-model=
"dataForm.counterPrice"
></el-input>
</el-form-item>
<el-form-item
label=
"当前价格"
prop=
"retailPrice"
>
<el-input
v-model=
"dataForm.retailPrice"
></el-input>
</el-form-item>
<el-form-item
label=
"是否新品"
prop=
"isNew"
>
<el-select
v-model=
"dataForm.isNew"
placeholder=
"请选择"
>
<el-option
label=
"新品"
:value=
"true"
>
</el-option>
<el-option
label=
"新品"
:value=
"false"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item
label=
"是否热品"
prop=
"isHot"
>
<el-select
v-model=
"dataForm.isHot"
placeholder=
"请选择"
>
<el-option
label=
"热品"
:value=
"true"
>
</el-option>
<el-option
label=
"非热品"
:value=
"false"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item
label=
"是否在售"
prop=
"isOnSale"
>
<el-select
v-model=
"dataForm.isOnSale"
placeholder=
"请选择"
>
<el-option
label=
"在售"
:value=
"true"
>
</el-option>
<el-option
label=
"未售"
:value=
"false"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item
label=
"首页主图"
>
<el-input
v-model=
"dataForm.listPicUrl"
></el-input>
</el-form-item>
<el-form-item
label=
"宣传画廊"
>
<el-input
v-model=
"dataForm.gallery"
></el-input>
</el-form-item>
<el-form-item
label=
"商品介绍"
>
<el-input
v-model=
"dataForm.goodsBrief"
></el-input>
</el-form-item>
<el-form-item
style=
"width: 700px;"
label=
"商品详细介绍"
>
<editor
:init=
"editorInit"
v-model=
"dataForm.goodsDesc"
></editor>
</el-form-item>
<el-form-item
label=
"商品主图"
>
<el-input
v-model=
"dataForm.primaryPicUrl"
></el-input>
</el-form-item>
<el-form-item
label=
"商品单位"
>
<el-input
v-model=
"dataForm.goodsUnit"
></el-input>
</el-form-item>
<el-form-item
label=
"关键字"
>
<el-input
v-model=
"dataForm.keyword"
></el-input>
</el-form-item>
<el-form-item
label=
"类目ID"
>
<el-input
v-model=
"dataForm.categoryId"
></el-input>
</el-form-item>
<el-form-item
label=
"品牌商ID"
>
<el-input
v-model=
"dataForm.brandId"
></el-input>
</el-form-item>
</el-form>
<div
slot=
"footer"
class=
"dialog-footer"
>
<el-button
@
click=
"dialogFormVisible = false"
>
取消
</el-button>
<el-button
v-if=
"dialogStatus=='create'"
type=
"primary"
@
click=
"createData"
>
确定
</el-button>
<el-button
v-else
type=
"primary"
@
click=
"updateData"
>
确定
</el-button>
</div>
</el-dialog>
</div>
</template>
<
style
>
.demo-table-expand
{
font-size
:
0
;
}
.demo-table-expand
label
{
width
:
200px
;
color
:
#99a9bf
;
}
.demo-table-expand
.el-form-item
{
margin-right
:
0
;
margin-bottom
:
0
;
}
.el-dialog
{
width
:
800px
;
}
</
style
>
<
script
>
import
{
listGoods
,
createGoods
,
updateGoods
,
deleteGoods
}
from
'
@/api/goods
'
import
{
createStorage
}
from
'
@/api/storage
'
import
waves
from
'
@/directive/waves
'
// 水波纹指令
import
BackToTop
from
'
@/components/BackToTop
'
import
Editor
from
'
@tinymce/tinymce-vue
'
export
default
{
name
:
'
Goods
'
,
components
:
{
BackToTop
,
Editor
},
directives
:
{
waves
},
data
()
{
return
{
list
:
undefined
,
total
:
undefined
,
listLoading
:
true
,
listQuery
:
{
page
:
1
,
limit
:
20
,
goodsSn
:
undefined
,
name
:
undefined
,
sort
:
'
+id
'
},
dataForm
:
{
id
:
undefined
,
goodsSn
:
undefined
,
name
:
undefined
,
counterPrice
:
undefined
,
retailPrice
:
undefined
,
isHot
:
false
,
isNew
:
true
,
isOnSale
:
true
,
listPicUrl
:
undefined
,
primaryPicUrl
:
undefined
,
goodsBrief
:
undefined
,
goodsDesc
:
''
,
keywords
:
undefined
,
gallery
:
undefined
,
categoryId
:
undefined
,
brandId
:
undefined
},
dialogFormVisible
:
false
,
dialogStatus
:
''
,
textMap
:
{
update
:
'
编辑
'
,
create
:
'
创建
'
},
rules
:
{
goodsSn
:
[{
required
:
true
,
message
:
'
商品编号不能为空
'
,
trigger
:
'
blur
'
}],
name
:
[{
required
:
true
,
message
:
'
商品名称不能为空
'
,
trigger
:
'
blur
'
}]
},
downloadLoading
:
false
,
editorInit
:
{
language
:
'
zh_CN
'
,
plugins
:
[
'
advlist anchor autolink autoresize autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools importcss insertdatetime legacyoutput link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace tabfocus table template textcolor textpattern visualblocks visualchars wordcount
'
],
toolbar
:
[
'
bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript
'
,
'
hr bullist numlist link image charmap preview anchor pagebreak fullscreen media table emoticons forecolor backcolor
'
],
images_upload_handler
:
function
(
blobInfo
,
success
,
failure
)
{
const
formData
=
new
FormData
()
formData
.
append
(
'
file
'
,
blobInfo
.
blob
())
createStorage
(
formData
).
then
(
res
=>
{
success
(
res
.
data
.
data
.
url
)
}).
catch
(()
=>
{
failure
(
'
上传失败,请重新上传
'
)
})
}
}
}
},
created
()
{
this
.
getList
()
},
methods
:
{
getList
()
{
this
.
listLoading
=
true
listGoods
(
this
.
listQuery
).
then
(
response
=>
{
this
.
list
=
response
.
data
.
data
.
items
this
.
total
=
response
.
data
.
data
.
total
this
.
listLoading
=
false
}).
catch
(()
=>
{
this
.
list
=
[]
this
.
total
=
0
this
.
listLoading
=
false
})
},
handleFilter
()
{
this
.
listQuery
.
page
=
1
this
.
getList
()
},
handleSizeChange
(
val
)
{
this
.
listQuery
.
limit
=
val
this
.
getList
()
},
handleCurrentChange
(
val
)
{
this
.
listQuery
.
page
=
val
this
.
getList
()
},
resetForm
()
{
this
.
dataForm
=
{
id
:
undefined
,
goodsSn
:
undefined
,
name
:
undefined
,
counterPrice
:
undefined
,
retailPrice
:
undefined
,
isHot
:
false
,
isNew
:
true
,
isOnSale
:
true
,
listPicUrl
:
undefined
,
primaryPicUrl
:
undefined
,
goodsBrief
:
undefined
,
goodsDesc
:
''
,
keywords
:
undefined
,
gallery
:
undefined
,
categoryId
:
undefined
,
brandId
:
undefined
}
},
filterLevel
(
value
,
row
)
{
return
row
.
level
===
value
},
handleCreate
()
{
this
.
resetForm
()
this
.
dialogStatus
=
'
create
'
this
.
dialogFormVisible
=
true
this
.
$nextTick
(()
=>
{
this
.
$refs
[
'
dataForm
'
].
clearValidate
()
})
},
createData
()
{
this
.
$refs
[
'
dataForm
'
].
validate
((
valid
)
=>
{
if
(
valid
)
{
createGoods
(
this
.
dataForm
).
then
(
response
=>
{
this
.
list
.
unshift
(
response
.
data
.
data
)
this
.
dialogFormVisible
=
false
this
.
$notify
({
title
:
'
成功
'
,
message
:
'
创建成功
'
,
type
:
'
success
'
,
duration
:
2000
})
})
}
})
},
handleUpdate
(
row
)
{
this
.
dataForm
=
Object
.
assign
({},
row
)
this
.
dialogStatus
=
'
update
'
this
.
dialogFormVisible
=
true
this
.
$nextTick
(()
=>
{
this
.
$refs
[
'
dataForm
'
].
clearValidate
()
})
},
updateData
()
{
this
.
$refs
[
'
dataForm
'
].
validate
((
valid
)
=>
{
if
(
valid
)
{
updateGoods
(
this
.
dataForm
).
then
(()
=>
{
for
(
const
v
of
this
.
list
)
{
if
(
v
.
id
===
this
.
dataForm
.
id
)
{
const
index
=
this
.
list
.
indexOf
(
v
)
this
.
list
.
splice
(
index
,
1
,
this
.
dataForm
)
break
}
}
this
.
dialogFormVisible
=
false
this
.
$notify
({
title
:
'
成功
'
,
message
:
'
更新成功
'
,
type
:
'
success
'
,
duration
:
2000
})
})
}
})
},
handleDelete
(
row
)
{
deleteGoods
(
row
).
then
(
response
=>
{
this
.
$notify
({
title
:
'
成功
'
,
message
:
'
删除成功
'
,
type
:
'
success
'
,
duration
:
2000
})
const
index
=
this
.
list
.
indexOf
(
row
)
this
.
list
.
splice
(
index
,
1
)
})
},
handleDownload
()
{
this
.
downloadLoading
=
true
import
(
'
@/vendor/Export2Excel
'
).
then
(
excel
=>
{
const
tHeader
=
[
'
商品ID
'
,
'
商品编号
'
,
'
名称
'
,
'
专柜价格
'
,
'
当前价格
'
,
'
是否新品
'
,
'
是否热品
'
,
'
是否在售
'
,
'
首页主图
'
,
'
宣传画廊
'
,
'
商品介绍
'
,
'
详细介绍
'
,
'
商品主图
'
,
'
商品单位
'
,
'
关键字
'
,
'
类目ID
'
,
'
品牌商ID
'
]
const
filterVal
=
[
'
id
'
,
'
goodsSn
'
,
'
name
'
,
'
counterPrice
'
,
'
retailPrice
'
,
'
isNew
'
,
'
isHot
'
,
'
isOnSale
'
,
'
listPicUrl
'
,
'
gallery
'
,
'
goodsBrief
'
,
'
goodsDesc
'
,
'
primaryPicUrl
'
,
'
goodsUnit
'
,
'
keywords
'
,
'
categoryId
'
,
'
brandId
'
]
excel
.
export_json_to_excel2
(
tHeader
,
this
.
list
,
filterVal
,
'
商品信息
'
)
this
.
downloadLoading
=
false
})
}
}
}
</
script
>
\ No newline at end of file
Prev
1
2
3
4
5
6
7
…
13
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