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
ad82b780
Commit
ad82b780
authored
Jun 26, 2018
by
Junling Bu
Browse files
feat[litemall-admin, litemall-admin-api]:商品上架页面。
在这一个页面同时添加商品相关的四个表,包括商品基本信息、商品规格、商品货品、商品参数。
parent
897980ed
Changes
15
Hide whitespace changes
Inline
Side-by-side
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/dao/GoodsAllinone.java
0 → 100644
View file @
ad82b780
package
org.linlinjava.litemall.admin.dao
;
import
org.linlinjava.litemall.db.domain.LitemallGoods
;
import
org.linlinjava.litemall.db.domain.LitemallGoodsAttribute
;
import
org.linlinjava.litemall.db.domain.LitemallGoodsSpecification
;
import
org.linlinjava.litemall.db.domain.LitemallProduct
;
public
class
GoodsAllinone
{
LitemallGoods
goods
;
LitemallGoodsSpecification
[]
specifications
;
LitemallGoodsAttribute
[]
attributes
;
// 这里采用 Product 再转换到 LitemallProduct
Product
[]
products
;
public
LitemallGoods
getGoods
()
{
return
goods
;
}
public
Product
[]
getProducts
()
{
return
products
;
}
public
void
setProducts
(
Product
[]
products
)
{
this
.
products
=
products
;
}
public
void
setGoods
(
LitemallGoods
goods
)
{
this
.
goods
=
goods
;
}
public
LitemallGoodsSpecification
[]
getSpecifications
()
{
return
specifications
;
}
public
void
setSpecifications
(
LitemallGoodsSpecification
[]
specifications
)
{
this
.
specifications
=
specifications
;
}
public
LitemallGoodsAttribute
[]
getAttributes
()
{
return
attributes
;
}
public
void
setAttributes
(
LitemallGoodsAttribute
[]
attributes
)
{
this
.
attributes
=
attributes
;
}
}
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/dao/Product.java
0 → 100644
View file @
ad82b780
package
org.linlinjava.litemall.admin.dao
;
import
java.math.BigDecimal
;
public
class
Product
{
String
[]
specifications
;
BigDecimal
price
;
Integer
number
;
String
url
;
public
String
[]
getSpecifications
()
{
return
specifications
;
}
public
void
setSpecifications
(
String
[]
specifications
)
{
this
.
specifications
=
specifications
;
}
public
BigDecimal
getPrice
()
{
return
price
;
}
public
void
setPrice
(
BigDecimal
price
)
{
this
.
price
=
price
;
}
public
Integer
getNumber
()
{
return
number
;
}
public
void
setNumber
(
Integer
number
)
{
this
.
number
=
number
;
}
public
String
getUrl
()
{
return
url
;
}
public
void
setUrl
(
String
url
)
{
this
.
url
=
url
;
}
}
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/util/CatVo.java
0 → 100644
View file @
ad82b780
package
org.linlinjava.litemall.admin.util
;
import
java.util.List
;
public
class
CatVo
{
private
Integer
value
=
null
;
private
String
label
=
null
;
private
List
children
=
null
;
public
Integer
getValue
()
{
return
value
;
}
public
void
setValue
(
Integer
value
)
{
this
.
value
=
value
;
}
public
String
getLabel
()
{
return
label
;
}
public
void
setLabel
(
String
label
)
{
this
.
label
=
label
;
}
public
List
getChildren
()
{
return
children
;
}
public
void
setChildren
(
List
children
)
{
this
.
children
=
children
;
}
}
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/web/AdminCategoryController.java
View file @
ad82b780
...
...
@@ -3,6 +3,7 @@ package org.linlinjava.litemall.admin.web;
import
org.apache.commons.logging.Log
;
import
org.apache.commons.logging.LogFactory
;
import
org.linlinjava.litemall.admin.annotation.LoginAdmin
;
import
org.linlinjava.litemall.admin.util.CatVo
;
import
org.linlinjava.litemall.db.domain.LitemallCategory
;
import
org.linlinjava.litemall.db.service.LitemallCategoryService
;
import
org.linlinjava.litemall.core.util.ResponseUtil
;
...
...
@@ -10,6 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.web.bind.annotation.*
;
import
java.time.LocalDateTime
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
...
...
@@ -98,4 +100,35 @@ public class AdminCategoryController {
return
ResponseUtil
.
ok
(
data
);
}
@GetMapping
(
"/list2"
)
public
Object
list2
(
@LoginAdmin
Integer
adminId
)
{
if
(
adminId
==
null
)
{
return
ResponseUtil
.
unlogin
();
}
List
<
LitemallCategory
>
l1CatList
=
categoryService
.
queryL1
();
List
<
CatVo
>
list
=
new
ArrayList
<>(
l1CatList
.
size
());
for
(
LitemallCategory
l1
:
l1CatList
){
CatVo
l1CatVo
=
new
CatVo
();
l1CatVo
.
setValue
(
l1
.
getId
());
l1CatVo
.
setLabel
(
l1
.
getName
());
List
<
LitemallCategory
>
l2CatList
=
categoryService
.
queryByPid
(
l1
.
getId
());
List
<
CatVo
>
children
=
new
ArrayList
<>(
l2CatList
.
size
());
for
(
LitemallCategory
l2
:
l2CatList
)
{
CatVo
l2CatVo
=
new
CatVo
();
l2CatVo
.
setValue
(
l2
.
getId
());
l2CatVo
.
setLabel
(
l2
.
getName
());
children
.
add
(
l2CatVo
);
}
l1CatVo
.
setChildren
(
children
);
list
.
add
(
l1CatVo
);
}
return
ResponseUtil
.
ok
(
list
);
}
}
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/web/AdminGoodsController.java
View file @
ad82b780
package
org.linlinjava.litemall.admin.web
;
import
io.swagger.models.auth.In
;
import
org.apache.commons.logging.Log
;
import
org.apache.commons.logging.LogFactory
;
import
org.linlinjava.litemall.admin.annotation.LoginAdmin
;
import
org.linlinjava.litemall.admin.dao.GoodsAllinone
;
import
org.linlinjava.litemall.admin.dao.Product
;
import
org.linlinjava.litemall.db.domain.LitemallGoods
;
import
org.linlinjava.litemall.db.domain.LitemallGoodsAttribute
;
import
org.linlinjava.litemall.db.domain.LitemallGoodsSpecification
;
import
org.linlinjava.litemall.db.domain.LitemallProduct
;
import
org.linlinjava.litemall.db.service.LitemallGoodsAttributeService
;
import
org.linlinjava.litemall.db.service.LitemallGoodsService
;
import
org.linlinjava.litemall.core.util.ResponseUtil
;
import
org.linlinjava.litemall.db.service.LitemallGoodsSpecificationService
;
import
org.linlinjava.litemall.db.service.LitemallProductService
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.transaction.PlatformTransactionManager
;
import
org.springframework.transaction.TransactionDefinition
;
import
org.springframework.transaction.TransactionStatus
;
import
org.springframework.transaction.support.DefaultTransactionDefinition
;
import
org.springframework.web.bind.annotation.*
;
import
java.math.BigDecimal
;
import
java.time.LocalDateTime
;
import
java.util.Arrays
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
...
...
@@ -18,8 +34,17 @@ import java.util.Map;
public
class
AdminGoodsController
{
private
final
Log
logger
=
LogFactory
.
getLog
(
AdminGoodsController
.
class
);
@Autowired
private
PlatformTransactionManager
txManager
;
@Autowired
private
LitemallGoodsService
goodsService
;
@Autowired
private
LitemallGoodsSpecificationService
specificationService
;
@Autowired
private
LitemallGoodsAttributeService
attributeService
;
@Autowired
private
LitemallProductService
productService
;
@GetMapping
(
"/list"
)
public
Object
list
(
@LoginAdmin
Integer
adminId
,
...
...
@@ -81,4 +106,73 @@ public class AdminGoodsController {
return
ResponseUtil
.
ok
();
}
@PostMapping
(
"/publish"
)
public
Object
publish
(
@LoginAdmin
Integer
adminId
,
@RequestBody
GoodsAllinone
goodsAllinone
){
if
(
adminId
==
null
){
return
ResponseUtil
.
unlogin
();
}
LitemallGoods
goods
=
goodsAllinone
.
getGoods
();
LitemallGoodsAttribute
[]
attributes
=
goodsAllinone
.
getAttributes
();
LitemallGoodsSpecification
[]
specifications
=
goodsAllinone
.
getSpecifications
();
Product
[]
products
=
goodsAllinone
.
getProducts
();
String
name
=
goods
.
getName
();
if
(
goodsService
.
checkExistByName
(
name
)){
return
ResponseUtil
.
fail
(
403
,
"商品名已经存在"
);
}
// 开启事务管理
DefaultTransactionDefinition
def
=
new
DefaultTransactionDefinition
();
def
.
setPropagationBehavior
(
TransactionDefinition
.
PROPAGATION_REQUIRED
);
TransactionStatus
status
=
txManager
.
getTransaction
(
def
);
try
{
// 商品基本信息表litemall_goods
goods
.
setAddTime
(
LocalDateTime
.
now
());
goodsService
.
add
(
goods
);
// 商品规格表litemall_goods_specification
Map
<
String
,
Integer
>
specIds
=
new
HashMap
<>();
for
(
LitemallGoodsSpecification
specification
:
specifications
){
specification
.
setGoodsId
(
goods
.
getId
());
specification
.
setAddTime
(
LocalDateTime
.
now
());
specificationService
.
add
(
specification
);
specIds
.
put
(
specification
.
getValue
(),
specification
.
getId
());
}
// 商品参数表litemall_goods_attribute
for
(
LitemallGoodsAttribute
attribute
:
attributes
){
attribute
.
setGoodsId
(
goods
.
getId
());
attribute
.
setAddTime
(
LocalDateTime
.
now
());
attributeService
.
add
(
attribute
);
}
// 商品货品表litemall_product
for
(
Product
product
:
products
){
LitemallProduct
litemallProduct
=
new
LitemallProduct
();
litemallProduct
.
setRetailPrice
(
product
.
getPrice
());
litemallProduct
.
setGoodsNumber
(
product
.
getNumber
());
litemallProduct
.
setUrl
(
product
.
getUrl
());
litemallProduct
.
setGoodsId
(
goods
.
getId
());
litemallProduct
.
setAddTime
(
LocalDateTime
.
now
());
String
[]
values
=
product
.
getSpecifications
();
Integer
[]
ids
=
new
Integer
[
values
.
length
];
for
(
int
i
=
0
;
i
<
values
.
length
;
i
++){
ids
[
i
]
=
specIds
.
get
(
values
[
i
]);
}
Arrays
.
sort
(
ids
);
litemallProduct
.
setGoodsSpecificationIds
(
ids
);
productService
.
add
(
litemallProduct
);
}
}
catch
(
Exception
ex
)
{
txManager
.
rollback
(
status
);
logger
.
error
(
"系统内部错误"
,
ex
);
}
txManager
.
commit
(
status
);
return
ResponseUtil
.
ok
();
}
}
litemall-admin/src/api/category.js
View file @
ad82b780
...
...
@@ -46,3 +46,11 @@ export function deleteCategory(data) {
data
})
}
export
function
listCategory2
(
query
)
{
return
request
({
url
:
'
/category/list2
'
,
method
:
'
get
'
,
params
:
query
})
}
litemall-admin/src/api/goods.js
View file @
ad82b780
...
...
@@ -39,3 +39,11 @@ export function deleteGoods(data) {
data
})
}
export
function
publishGoods
(
data
)
{
return
request
({
url
:
'
/goods/publish
'
,
method
:
'
post
'
,
data
})
}
litemall-admin/src/api/storage.js
View file @
ad82b780
...
...
@@ -64,3 +64,6 @@ export function deleteStorage(data) {
export
function
getUploadApi
(
data
)
{
return
process
.
env
.
OS_API
+
'
/storage/create
'
}
const
uploadPath
=
process
.
env
.
OS_API
+
'
/storage/create
'
export
{
uploadPath
}
litemall-admin/src/router/index.js
View file @
ad82b780
...
...
@@ -98,6 +98,7 @@ export const asyncRouterMap = [
icon
:
'
chart
'
},
children
:
[
{
path
:
'
publish
'
,
component
:
_import
(
'
goods/publish
'
),
name
:
'
publish
'
,
meta
:
{
title
:
'
商品上架
'
,
noCache
:
true
}},
{
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
}},
...
...
litemall-admin/src/utils/request.js
View file @
ad82b780
...
...
@@ -50,7 +50,8 @@ service.interceptors.response.use(
})
return
Promise
.
reject
(
'
error
'
)
}
else
if
(
res
.
errno
!==
0
)
{
return
Promise
.
reject
(
'
error
'
)
// 非5xx的错误属于业务错误,留给具体页面处理
return
Promise
.
reject
(
response
)
}
else
{
return
response
}
...
...
litemall-admin/src/views/goods/goods.vue
View file @
ad82b780
...
...
@@ -181,8 +181,7 @@
</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>
<el-button
type=
"primary"
@
click=
"updateData"
>
确定
</el-button>
</div>
</el-dialog>
...
...
@@ -208,7 +207,7 @@
</
style
>
<
script
>
import
{
listGoods
,
createGoods
,
updateGoods
,
deleteGoods
}
from
'
@/api/goods
'
import
{
listGoods
,
updateGoods
,
deleteGoods
}
from
'
@/api/goods
'
import
{
createStorage
,
getUploadApi
}
from
'
@/api/storage
'
import
waves
from
'
@/directive/waves
'
// 水波纹指令
import
BackToTop
from
'
@/components/BackToTop
'
...
...
@@ -359,28 +358,7 @@ export default {
}
},
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
})
})
}
})
this
.
$router
.
push
({
path
:
'
/goods/publish
'
})
},
handleUpdate
(
row
)
{
this
.
dataForm
=
Object
.
assign
({},
row
)
...
...
litemall-admin/src/views/goods/product.vue
View file @
ad82b780
...
...
@@ -6,7 +6,6 @@
<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"
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>
</div>
...
...
@@ -42,7 +41,6 @@
<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>
...
...
@@ -54,20 +52,8 @@
</el-pagination>
</div>
<el-dialog
title=
"添加货品"
:visible.sync=
"createDialogFormVisible"
>
<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>
<div
slot=
"footer"
class=
"dialog-footer"
>
<el-button
@
click=
"createDialogFormVisible = false"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"createData"
>
确定
</el-button>
</div>
</el-dialog>
<!-- 修改对话框 -->
<el-dialog
title=
"
修改
货品"
:visible.sync=
"editDialogFormVisible"
>
<el-dialog
title=
"
编辑商品
货品"
:visible.sync=
"editDialogFormVisible"
>
<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"
:disabled=
"true"
></el-input>
...
...
@@ -112,7 +98,7 @@
</
style
>
<
script
>
import
{
listProduct
,
createProduct
,
updateProduct
,
dele
teProduct
}
from
'
@/api/product
'
import
{
listProduct
,
upda
teProduct
}
from
'
@/api/product
'
import
{
createStorage
}
from
'
@/api/storage
'
import
waves
from
'
@/directive/waves
'
// 水波纹指令
...
...
@@ -133,7 +119,6 @@ export default {
goodsId
:
undefined
,
sort
:
'
+id
'
},
createDialogFormVisible
:
false
,
editDialogFormVisible
:
false
,
dataForm
:
{
id
:
undefined
,
...
...
@@ -197,29 +182,6 @@ export default {
this
.
$message
.
error
(
'
上传失败,请重新上传
'
)
})
},
handleCreate
()
{
this
.
resetForm
()
this
.
createDialogFormVisible
=
true
this
.
$nextTick
(()
=>
{
this
.
$refs
[
'
dataForm
'
].
clearValidate
()
})
},
createData
()
{
this
.
$refs
[
'
dataForm
'
].
validate
((
valid
)
=>
{
if
(
valid
)
{
createProduct
(
this
.
dataForm
).
then
(
response
=>
{
this
.
getList
()
this
.
createDialogFormVisible
=
false
this
.
$notify
({
title
:
'
成功
'
,
message
:
'
创建成功
'
,
type
:
'
success
'
,
duration
:
2000
})
})
}
})
},
handleUpdate
(
row
)
{
this
.
dataForm
=
Object
.
assign
({},
row
)
this
.
editDialogFormVisible
=
true
...
...
@@ -249,18 +211,6 @@ export default {
}
})
},
handleDelete
(
row
)
{
deleteProduct
(
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
=>
{
...
...
litemall-admin/src/views/goods/publish.vue
0 → 100644
View file @
ad82b780
<
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=
"uploadListPicUrl"
>
<img
v-if=
"goods.listPicUrl"
:src=
"goods.listPicUrl"
class=
"avatar"
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
></i>
</el-upload>
</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=
"uploadPrimaryPicUrl"
>
<img
v-if=
"goods.primaryPicUrl"
:src=
"goods.primaryPicUrl"
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.goodsUnit"
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-input
v-model=
"goods.brandId"
></el-input>
</el-form-item>
<el-form-item
label=
"商品简介"
>
<el-input
v-model=
"goods.goodsBrief"
></el-input>
</el-form-item>
<el-form-item
label=
"商品详细介绍"
>
<editor
:init=
"editorInit"
v-model=
"goods.goodsDesc"
></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=
"price"
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=
"picUrl"
>
<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
}
from
'
@/api/goods
'
import
{
createStorage
,
uploadPath
}
from
'
@/api/storage
'
import
{
listCategory2
}
from
'
@/api/category
'
import
Editor
from
'
@tinymce/tinymce-vue
'
import
{
MessageBox
}
from
'
element-ui
'
export
default
{
name
:
'
GoodsAdd
'
,
components
:
{
Editor
},
data
()
{
return
{
uploadPath
,
newKeywordVisible
:
false
,
newKeyword
:
''
,
keywords
:
[],
galleryFileList
:
[],
categoryList
:
[],
goods
:
{
id
:
undefined
,
goodsSn
:
undefined
,
name
:
undefined
,
counterPrice
:
undefined
,
retailPrice
:
undefined
,
isHot
:
false
,
isNew
:
true
,
isOnSale
:
true
,
listPicUrl
:
undefined
,
primaryPicUrl
:
undefined
,
goodsBrief
:
undefined
,
goodsDesc
:
''
,
keywords
:
''
,
gallery
:
[],
categoryId
:
undefined
,
brandId
:
undefined
},
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
.
getCatList
()
},
methods
:
{
getCatList
:
function
()
{
listCategory2
().
then
(
response
=>
{
this
.
categoryList
=
response
.
data
.
data
})
},
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/goods
'
})
}).
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
=
''
},
uploadPrimaryPicUrl
:
function
(
response
)
{
this
.
goods
.
primaryPicUrl
=
response
.
data
.
url
},
uploadListPicUrl
:
function
(
response
)
{
this
.
goods
.
listPicUrl
=
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/specification.vue
View file @
ad82b780
...
...
@@ -6,7 +6,6 @@
<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>
...
...
@@ -30,7 +29,6 @@
<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>
...
...
@@ -42,8 +40,8 @@
</el-pagination>
</div>
<!--
添加或
修改对话框 -->
<el-dialog
:
title=
"
textMap[dialogStatus]
"
:visible.sync=
"dialogFormVisible"
>
<!-- 修改对话框 -->
<el-dialog
title=
"
编辑商品规格
"
: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>
...
...
@@ -60,8 +58,7 @@
</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>
<el-button
type=
"primary"
@
click=
"updateData"
>
确定
</el-button>
</div>
</el-dialog>
...
...
@@ -69,7 +66,7 @@
</template>
<
script
>
import
{
listGoodsSpecification
,
createGoodsSpecification
,
updateGoodsSpecification
,
dele
teGoodsSpecification
}
from
'
@/api/goods-specification
'
import
{
listGoodsSpecification
,
upda
teGoodsSpecification
}
from
'
@/api/goods-specification
'
import
waves
from
'
@/directive/waves
'
// 水波纹指令
export
default
{
...
...
@@ -97,10 +94,6 @@ export default {
},
dialogFormVisible
:
false
,
dialogStatus
:
''
,
textMap
:
{
update
:
'
编辑
'
,
create
:
'
创建
'
},
rules
:
{
goodsId
:
[{
required
:
true
,
message
:
'
商品ID不能为空
'
,
trigger
:
'
blur
'
}],
specification
:
[{
required
:
true
,
message
:
'
商品规格名称不能为空
'
,
trigger
:
'
blur
'
}],
...
...
@@ -146,30 +139,6 @@ export default {
picUrl
:
undefined
}
},
handleCreate
()
{
this
.
resetForm
()
this
.
dialogStatus
=
'
create
'
this
.
dialogFormVisible
=
true
this
.
$nextTick
(()
=>
{
this
.
$refs
[
'
dataForm
'
].
clearValidate
()
})
},
createData
()
{
this
.
$refs
[
'
dataForm
'
].
validate
((
valid
)
=>
{
if
(
valid
)
{
createGoodsSpecification
(
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
'
...
...
@@ -200,18 +169,6 @@ export default {
}
})
},
handleDelete
(
row
)
{
deleteGoodsSpecification
(
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
=>
{
...
...
litemall-db/src/main/java/org/linlinjava/litemall/db/service/LitemallGoodsService.java
View file @
ad82b780
...
...
@@ -207,4 +207,10 @@ public class LitemallGoodsService {
}
return
cats
;
}
public
boolean
checkExistByName
(
String
name
)
{
LitemallGoodsExample
example
=
new
LitemallGoodsExample
();
example
.
or
().
andNameEqualTo
(
name
).
andDeletedEqualTo
(
false
);
return
goodsMapper
.
countByExample
(
example
)
!=
0
;
}
}
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