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
e9d284f5
Commit
e9d284f5
authored
Dec 01, 2019
by
Junling Bu
Browse files
fix[litemall-admin, litemall-admin-api]: #293
parent
e56e155e
Changes
11
Hide whitespace changes
Inline
Side-by-side
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/service/AdminGoodsService.java
View file @
e9d284f5
...
...
@@ -37,13 +37,14 @@ public class AdminGoodsService {
private
LitemallCategoryService
categoryService
;
@Autowired
private
LitemallBrandService
brandService
;
@Autowired
private
LitemallCartService
cartService
;
@Autowired
private
QCodeService
qCodeService
;
public
Object
list
(
String
goodsSn
,
String
name
,
public
Object
list
(
Integer
goodsId
,
String
goodsSn
,
String
name
,
Integer
page
,
Integer
limit
,
String
sort
,
String
order
)
{
List
<
LitemallGoods
>
goodsList
=
goodsService
.
querySelective
(
goodsSn
,
name
,
page
,
limit
,
sort
,
order
);
List
<
LitemallGoods
>
goodsList
=
goodsService
.
querySelective
(
goodsId
,
goodsSn
,
name
,
page
,
limit
,
sort
,
order
);
return
ResponseUtil
.
okList
(
goodsList
);
}
...
...
@@ -119,19 +120,25 @@ public class AdminGoodsService {
/**
* 编辑商品
* <p>
* TODO
* 目前商品修改的逻辑是
* 1. 更新litemall_goods表
* 2. 逻辑删除litemall_goods_specification、litemall_goods_attribute、litemall_goods_product
* 3. 添加litemall_goods_specification、litemall_goods_attribute、litemall_goods_product
* <p>
* 这里商品三个表的数据采用删除再添加的策略是因为
* 商品编辑页面,支持管理员添加删除商品规格、添加删除商品属性,因此这里仅仅更新是不可能的,
* 只能删除三个表旧的数据,然后添加新的数据。
* 但是这里又会引入新的问题,就是存在订单商品货品ID指向了失效的商品货品表。
* 因此这里会拒绝管理员编辑商品,如果订单或购物车中存在商品。
* 所以这里可能需要重新设计。
*
* NOTE:
* 由于商品涉及到四个表,特别是litemall_goods_product表依赖litemall_goods_specification表,
* 这导致允许所有字段都是可编辑会带来一些问题,因此这里商品编辑功能是受限制:
* (1)litemall_goods表可以编辑字段;
* (2)litemall_goods_specification表只能编辑pic_url字段,其他操作不支持;
* (3)litemall_goods_product表只能编辑price, number和url字段,其他操作不支持;
* (4)litemall_goods_attribute表支持编辑、添加和删除操作。
*
* NOTE2:
* 前后端这里使用了一个小技巧:
* 如果前端传来的update_time字段是空,则说明前端已经更新了某个记录,则这个记录会更新;
* 否则说明这个记录没有编辑过,无需更新该记录。
*
* NOTE3:
* (1)购物车缓存了一些商品信息,因此需要及时更新。
* 目前这些字段是goods_sn, goods_name, price, pic_url。
* (2)但是订单里面的商品信息则是不会更新。
* 如果订单是未支付订单,此时仍然以旧的价格支付。
*/
@Transactional
public
Object
update
(
GoodsAllinone
goodsAllinone
)
{
...
...
@@ -145,8 +152,6 @@ public class AdminGoodsService {
LitemallGoodsSpecification
[]
specifications
=
goodsAllinone
.
getSpecifications
();
LitemallGoodsProduct
[]
products
=
goodsAllinone
.
getProducts
();
Integer
id
=
goods
.
getId
();
//将生成的分享图片地址写入数据库
String
url
=
qCodeService
.
createGoodShareImage
(
goods
.
getId
().
toString
(),
goods
.
getPicUrl
(),
goods
.
getName
());
goods
.
setShareUrl
(
url
);
...
...
@@ -157,26 +162,42 @@ public class AdminGoodsService {
}
Integer
gid
=
goods
.
getId
();
specificationService
.
deleteByGid
(
gid
);
attributeService
.
deleteByGid
(
gid
);
productService
.
deleteByGid
(
gid
);
// 商品规格表litemall_goods_specification
for
(
LitemallGoodsSpecification
specification
:
specifications
)
{
specification
.
setGoodsId
(
goods
.
getId
());
specificationService
.
add
(
specification
);
// 目前只支持更新规格表的图片字段
if
(
specification
.
getUpdateTime
()
==
null
){
specification
.
setSpecification
(
null
);
specification
.
setValue
(
null
);
specificationService
.
updateById
(
specification
);
}
}
// 商品货品表litemall_product
for
(
LitemallGoodsProduct
product
:
products
)
{
if
(
product
.
getUpdateTime
()
==
null
)
{
productService
.
updateById
(
product
);
}
}
// 商品参数表litemall_goods_attribute
for
(
LitemallGoodsAttribute
attribute
:
attributes
)
{
attribute
.
setGoodsId
(
goods
.
getId
());
attributeService
.
add
(
attribute
);
if
(
attribute
.
getId
()
==
null
||
attribute
.
getId
().
equals
(
0
)){
attribute
.
setGoodsId
(
goods
.
getId
());
attributeService
.
add
(
attribute
);
}
else
if
(
attribute
.
getDeleted
()){
attributeService
.
deleteByGid
(
attribute
.
getId
());
}
else
if
(
attribute
.
getUpdateTime
()
==
null
){
attributeService
.
updateById
(
attribute
);
}
}
// 商品货品表litemall_product
// 这里需要注意的是购物车litemall_cart有些字段是拷贝商品的一些字段,因此需要及时更新
// 目前这些字段是goods_sn, goods_name, price, pic_url
for
(
LitemallGoodsProduct
product
:
products
)
{
product
.
setGoodsId
(
goods
.
getId
());
productService
.
add
(
product
);
cartService
.
updateProduct
(
product
.
getId
(),
goods
.
getGoodsSn
(),
goods
.
getName
(),
product
.
getPrice
(),
product
.
getUrl
());
}
return
ResponseUtil
.
ok
();
...
...
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/web/AdminGoodsController.java
View file @
e9d284f5
...
...
@@ -27,6 +27,7 @@ public class AdminGoodsController {
/**
* 查询商品
*
* @param goodsId
* @param goodsSn
* @param name
* @param page
...
...
@@ -38,12 +39,12 @@ public class AdminGoodsController {
@RequiresPermissions
(
"admin:goods:list"
)
@RequiresPermissionsDesc
(
menu
=
{
"商品管理"
,
"商品管理"
},
button
=
"查询"
)
@GetMapping
(
"/list"
)
public
Object
list
(
String
goodsSn
,
String
name
,
public
Object
list
(
Integer
goodsId
,
String
goodsSn
,
String
name
,
@RequestParam
(
defaultValue
=
"1"
)
Integer
page
,
@RequestParam
(
defaultValue
=
"10"
)
Integer
limit
,
@Sort
@RequestParam
(
defaultValue
=
"add_time"
)
String
sort
,
@Order
@RequestParam
(
defaultValue
=
"desc"
)
String
order
)
{
return
adminGoodsService
.
list
(
goodsSn
,
name
,
page
,
limit
,
sort
,
order
);
return
adminGoodsService
.
list
(
goodsId
,
goodsSn
,
name
,
page
,
limit
,
sort
,
order
);
}
@GetMapping
(
"/catAndBrand"
)
...
...
litemall-admin/src/views/goods/create.vue
View file @
e9d284f5
...
...
@@ -5,10 +5,10 @@
<h3>
商品介绍
</h3>
<el-form
ref=
"goods"
:rules=
"rules"
:model=
"goods"
label-width=
"150px"
>
<el-form-item
label=
"商品编号"
prop=
"goodsSn"
>
<el-input
v-model=
"goods.goodsSn"
/>
<el-input
v-model=
"goods.goodsSn"
/>
</el-form-item>
<el-form-item
label=
"商品名称"
prop=
"name"
>
<el-input
v-model=
"goods.name"
/>
<el-input
v-model=
"goods.name"
/>
</el-form-item>
<el-form-item
label=
"专柜价格"
prop=
"counterPrice"
>
<el-input
v-model=
"goods.counterPrice"
placeholder=
"0.00"
>
...
...
@@ -46,9 +46,10 @@
:headers=
"headers"
:on-success=
"uploadPicUrl"
class=
"avatar-uploader"
accept=
".jpg,.jpeg,.png,.gif"
>
accept=
".jpg,.jpeg,.png,.gif"
>
<img
v-if=
"goods.picUrl"
:src=
"goods.picUrl"
class=
"avatar"
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
/>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
/>
</el-upload>
</el-form-item>
...
...
@@ -62,13 +63,14 @@
:on-remove=
"handleRemove"
multiple
accept=
".jpg,.jpeg,.png,.gif"
list-type=
"picture-card"
>
<i
class=
"el-icon-plus"
/>
list-type=
"picture-card"
>
<i
class=
"el-icon-plus"
/>
</el-upload>
</el-form-item>
<el-form-item
label=
"商品单位"
>
<el-input
v-model=
"goods.unit"
placeholder=
"件 / 个 / 盒"
/>
<el-input
v-model=
"goods.unit"
placeholder=
"件 / 个 / 盒"
/>
</el-form-item>
<el-form-item
label=
"关键字"
>
...
...
@@ -82,26 +84,27 @@
class=
"input-new-keyword"
@
keyup.enter.native=
"handleInputConfirm"
@
blur=
"handleInputConfirm"
/>
@
blur=
"handleInputConfirm"
/>
<el-button
v-else
class=
"button-new-keyword"
type=
"primary"
@
click=
"showInput"
>
+ 增加
</el-button>
</el-form-item>
<el-form-item
label=
"所属分类"
>
<el-cascader
:options=
"categoryList"
expand-trigger=
"hover"
@
change=
"handleCategoryChange"
/>
<el-cascader
:options=
"categoryList"
expand-trigger=
"hover"
@
change=
"handleCategoryChange"
/>
</el-form-item>
<el-form-item
label=
"所属品牌商"
>
<el-select
v-model=
"goods.brandId"
>
<el-option
v-for=
"item in brandList"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
<el-option
v-for=
"item in brandList"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
</el-form-item>
<el-form-item
label=
"商品简介"
>
<el-input
v-model=
"goods.brief"
/>
<el-input
v-model=
"goods.brief"
/>
</el-form-item>
<el-form-item
label=
"商品详细介绍"
>
<editor
:init=
"editorInit"
v-model=
"goods.detail"
/>
<editor
v-model=
"goods.detail"
:init=
"editorInit"
/>
</el-form-item>
</el-form>
</el-card>
...
...
@@ -121,7 +124,7 @@
</el-row>
<el-table
:data=
"specifications"
>
<el-table-column
property=
"specification"
label=
"规格名"
/>
<el-table-column
property=
"specification"
label=
"规格名"
/>
<el-table-column
property=
"value"
label=
"规格值"
>
<
template
slot-scope=
"scope"
>
<el-tag
type=
"primary"
>
...
...
@@ -139,7 +142,8 @@
align=
"center"
label=
"操作"
width=
"250"
class-name=
"small-padding fixed-width"
>
class-name=
"small-padding fixed-width"
>
<
template
slot-scope=
"scope"
>
<el-button
type=
"danger"
size=
"mini"
@
click=
"handleSpecificationDelete(scope.row)"
>
删除
</el-button>
</
template
>
...
...
@@ -154,12 +158,13 @@
status-icon
label-position=
"left"
label-width=
"100px"
style=
"width: 400px; margin-left:50px;"
>
style=
"width: 400px; margin-left:50px;"
>
<el-form-item
label=
"规格名"
prop=
"specification"
>
<el-input
v-model=
"specForm.specification"
/>
<el-input
v-model=
"specForm.specification"
/>
</el-form-item>
<el-form-item
label=
"规格值"
prop=
"value"
>
<el-input
v-model=
"specForm.value"
/>
<el-input
v-model=
"specForm.value"
/>
</el-form-item>
<el-form-item
label=
"规格图片"
prop=
"picUrl"
>
<el-upload
...
...
@@ -168,9 +173,10 @@
:headers=
"headers"
:on-success=
"uploadSpecPicUrl"
class=
"avatar-uploader"
accept=
".jpg,.jpeg,.png,.gif"
>
accept=
".jpg,.jpeg,.png,.gif"
>
<img
v-if=
"specForm.picUrl"
:src=
"specForm.picUrl"
class=
"avatar"
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
/>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
/>
</el-upload>
</el-form-item>
</el-form>
...
...
@@ -191,8 +197,8 @@
</el-tag>
</
template
>
</el-table-column>
<el-table-column
property=
"price"
width=
"100"
label=
"货品售价"
/>
<el-table-column
property=
"number"
width=
"100"
label=
"货品数量"
/>
<el-table-column
property=
"price"
width=
"100"
label=
"货品售价"
/>
<el-table-column
property=
"number"
width=
"100"
label=
"货品数量"
/>
<el-table-column
property=
"url"
width=
"100"
label=
"货品图片"
>
<
template
slot-scope=
"scope"
>
<img
v-if=
"scope.row.url"
:src=
"scope.row.url"
width=
"40"
>
...
...
@@ -205,24 +211,25 @@
</el-table-column>
</el-table>
<el-dialog
:visible.sync=
"productVisiable"
title=
"
设置
货品"
>
<el-dialog
:visible.sync=
"productVisiable"
title=
"
添加
货品"
>
<el-form
ref=
"productForm"
:model=
"productForm"
status-icon
label-position=
"left"
label-width=
"100px"
style=
"width: 400px; margin-left:50px;"
>
style=
"width: 400px; margin-left:50px;"
>
<el-form-item
label=
"货品规格列"
prop=
"specifications"
>
<el-tag
v-for=
"tag in productForm.specifications"
:key=
"tag"
>
{{ tag }}
</el-tag>
</el-form-item>
<el-form-item
label=
"货品售价"
prop=
"price"
>
<el-input
v-model=
"productForm.price"
/>
<el-input
v-model=
"productForm.price"
/>
</el-form-item>
<el-form-item
label=
"货品数量"
prop=
"number"
>
<el-input
v-model=
"productForm.number"
/>
<el-input
v-model=
"productForm.number"
/>
</el-form-item>
<el-form-item
label=
"货品图片"
prop=
"url"
>
<el-upload
...
...
@@ -231,9 +238,10 @@
:headers=
"headers"
:on-success=
"uploadProductUrl"
class=
"avatar-uploader"
accept=
".jpg,.jpeg,.png,.gif"
>
accept=
".jpg,.jpeg,.png,.gif"
>
<img
v-if=
"productForm.url"
:src=
"productForm.url"
class=
"avatar"
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
/>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
/>
</el-upload>
</el-form-item>
</el-form>
...
...
@@ -248,8 +256,8 @@
<h3>
商品参数
</h3>
<el-button
:plain=
"true"
type=
"primary"
@
click=
"handleAttributeShow"
>
添加
</el-button>
<el-table
:data=
"attributes"
>
<el-table-column
property=
"attribute"
label=
"商品参数名称"
/>
<el-table-column
property=
"value"
label=
"商品参数值"
/>
<el-table-column
property=
"attribute"
label=
"商品参数名称"
/>
<el-table-column
property=
"value"
label=
"商品参数值"
/>
<el-table-column
align=
"center"
label=
"操作"
width=
"100"
class-name=
"small-padding fixed-width"
>
<
template
slot-scope=
"scope"
>
<el-button
type=
"danger"
size=
"mini"
@
click=
"handleAttributeDelete(scope.row)"
>
删除
</el-button>
...
...
@@ -257,19 +265,20 @@
</el-table-column>
</el-table>
<el-dialog
:visible.sync=
"attributeVisiable"
title=
"
设置
商品参数"
>
<el-dialog
:visible.sync=
"attributeVisiable"
title=
"
添加
商品参数"
>
<el-form
ref=
"attributeForm"
:model=
"attributeForm"
status-icon
label-position=
"left"
label-width=
"100px"
style=
"width: 400px; margin-left:50px;"
>
style=
"width: 400px; margin-left:50px;"
>
<el-form-item
label=
"商品参数名称"
prop=
"attribute"
>
<el-input
v-model=
"attributeForm.attribute"
/>
<el-input
v-model=
"attributeForm.attribute"
/>
</el-form-item>
<el-form-item
label=
"商品参数值"
prop=
"value"
>
<el-input
v-model=
"attributeForm.value"
/>
<el-input
v-model=
"attributeForm.value"
/>
</el-form-item>
</el-form>
<div
slot=
"footer"
class=
"dialog-footer"
>
...
...
@@ -368,6 +377,7 @@ export default {
},
editorInit
:
{
language
:
'
zh_CN
'
,
height
:
500
,
convert_urls
:
false
,
plugins
:
[
'
advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools importcss insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount
'
],
toolbar
:
[
'
searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript code codesample
'
,
'
hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen
'
],
...
...
litemall-admin/src/views/goods/edit.vue
View file @
e9d284f5
...
...
@@ -4,11 +4,14 @@
<el-card
class=
"box-card"
>
<h3>
商品介绍
</h3>
<el-form
ref=
"goods"
:rules=
"rules"
:model=
"goods"
label-width=
"150px"
>
<el-form-item
label=
"商品
编号
"
prop=
"
goodsSn
"
>
<el-input
v-model=
"goods.
goodsSn"
/>
<el-form-item
label=
"商品
ID
"
prop=
"
id
"
>
<el-input
v-model=
"goods.
id"
disabled
/>
</el-form-item>
<el-form-item
label=
"商品名称"
prop=
"name"
>
<el-input
v-model=
"goods.name"
/>
<el-input
v-model=
"goods.name"
/>
</el-form-item>
<el-form-item
label=
"商品编号"
prop=
"goodsSn"
>
<el-input
v-model=
"goods.goodsSn"
/>
</el-form-item>
<el-form-item
label=
"专柜价格"
prop=
"counterPrice"
>
<el-input
v-model=
"goods.counterPrice"
placeholder=
"0.00"
>
...
...
@@ -46,9 +49,10 @@
:show-file-list=
"false"
:on-success=
"uploadPicUrl"
class=
"avatar-uploader"
accept=
".jpg,.jpeg,.png,.gif"
>
accept=
".jpg,.jpeg,.png,.gif"
>
<img
v-if=
"goods.picUrl"
:src=
"goods.picUrl"
class=
"avatar"
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
/>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
/>
</el-upload>
</el-form-item>
...
...
@@ -63,50 +67,49 @@
:on-remove=
"handleRemove"
multiple
accept=
".jpg,.jpeg,.png,.gif"
list-type=
"picture-card"
>
<i
class=
"el-icon-plus"
/>
list-type=
"picture-card"
>
<i
class=
"el-icon-plus"
/>
</el-upload>
</el-form-item>
<el-form-item
label=
"商品单位"
>
<el-input
v-model=
"goods.unit"
placeholder=
"件 / 个 / 盒"
/>
<el-input
v-model=
"goods.unit"
placeholder=
"件 / 个 / 盒"
/>
</el-form-item>
<el-form-item
label=
"关键字"
>
<el-tag
v-for=
"tag in keywords"
:key=
"tag"
closable
type=
"primary"
@
close=
"handleClose(tag)"
>
{{ tag }}
</el-tag>
<el-input
v-if=
"newKeywordVisible"
ref=
"newKeywordInput"
v-model=
"newKeyword"
class=
"input-new-keyword"
@
keyup.enter.native=
"handleInputConfirm"
@
blur=
"handleInputConfirm"
/>
<el-input
v-if=
"newKeywordVisible"
ref=
"newKeywordInput"
v-model=
"newKeyword"
class=
"input-new-keyword"
@
keyup.enter.native=
"handleInputConfirm"
@
blur=
"handleInputConfirm"
/>
<el-button
v-else
class=
"button-new-keyword"
type=
"primary"
@
click=
"showInput"
>
+ 增加
</el-button>
</el-form-item>
<el-form-item
label=
"所属分类"
>
<el-cascader
:options=
"categoryList
"
v-model=
"categoryIds
"
expand-trigger=
"hover"
@
change=
"handleCategoryChange"
/>
<el-cascader
v-model=
"categoryIds"
:options=
"categoryList"
expand-trigger=
"hover"
@
change=
"handleCategoryChange"
/>
</el-form-item>
<el-form-item
label=
"所属品牌商"
>
<el-select
v-model=
"goods.brandId"
>
<el-option
v-for=
"item in brandList"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
<el-option
v-for=
"item in brandList"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
</el-form-item>
<el-form-item
label=
"商品简介"
>
<el-input
v-model=
"goods.brief"
/>
<el-input
v-model=
"goods.brief"
/>
</el-form-item>
<el-form-item
label=
"商品详细介绍"
>
<editor
:init=
"editorInit"
v-model=
"goods.detail"
/>
<editor
v-model=
"goods.detail"
:init=
"editorInit"
/>
</el-form-item>
</el-form>
</el-card>
<el-card
class=
"box-card"
>
<h3>
商品规格
</h3>
<el-button
:plain=
"true"
type=
"primary"
@
click=
"handleSpecificationShow"
>
添加
</el-button>
<el-table
:data=
"specifications"
>
<el-table-column
property=
"specification"
label=
"规格名"
/>
<el-table-column
property=
"value"
label=
"规格值"
>
<el-table-column
property=
"value"
label=
"规格值"
>
<
template
slot-scope=
"scope"
>
<el-tag
type=
"primary"
>
{{
scope
.
row
.
value
}}
...
...
@@ -118,9 +121,9 @@
<img
v-if=
"scope.row.picUrl"
:src=
"scope.row.picUrl"
width=
"40"
>
</
template
>
</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=
"
danger
"
size=
"mini"
@
click=
"handleSpecification
Delete
(scope.row)"
>
删除
</el-button>
<el-button
type=
"
primary
"
size=
"mini"
@
click=
"handleSpecification
Show
(scope.row)"
>
设置
</el-button>
</
template
>
</el-table-column>
</el-table>
...
...
@@ -128,10 +131,10 @@
<el-dialog
:visible.sync=
"specVisiable"
title=
"设置规格"
>
<el-form
ref=
"specForm"
:rules=
"rules"
:model=
"specForm"
status-icon
label-position=
"left"
label-width=
"100px"
style=
"width: 400px; margin-left:50px;"
>
<el-form-item
label=
"规格名"
prop=
"specification"
>
<el-input
v-model=
"specForm.specification"
/>
<el-input
v-model=
"specForm.specification"
disabled
/>
</el-form-item>
<el-form-item
label=
"规格值"
prop=
"value"
>
<el-input
v-model=
"specForm.value"
/>
<el-input
v-model=
"specForm.value"
disabled
/>
</el-form-item>
<el-form-item
label=
"规格图片"
prop=
"picUrl"
>
<el-upload
...
...
@@ -140,15 +143,16 @@
:show-file-list=
"false"
:on-success=
"uploadSpecPicUrl"
class=
"avatar-uploader"
accept=
".jpg,.jpeg,.png,.gif"
>
accept=
".jpg,.jpeg,.png,.gif"
>
<img
v-if=
"specForm.picUrl"
:src=
"specForm.picUrl"
class=
"avatar"
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
/>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
/>
</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=
"handleSpecification
Add
"
>
确定
</el-button>
<el-button
type=
"primary"
@
click=
"handleSpecification
Edit
"
>
确定
</el-button>
</div>
</el-dialog>
</el-card>
...
...
@@ -156,28 +160,28 @@
<el-card
class=
"box-card"
>
<h3>
商品库存
</h3>
<el-table
:data=
"products"
>
<el-table-column
property=
"value"
label=
"货品规格"
>
<el-table-column
property=
"value"
label=
"货品规格"
>
<
template
slot-scope=
"scope"
>
<el-tag
v-for=
"tag in scope.row.specifications"
:key=
"tag"
>
{{
tag
}}
</el-tag>
</
template
>
</el-table-column>
<el-table-column
property=
"price"
width=
"100"
label=
"货品售价"
/>
<el-table-column
property=
"number"
width=
"100"
label=
"货品数量"
/>
<el-table-column
property=
"url"
width=
"100"
label=
"货品图片"
>
<el-table-column
property=
"price"
label=
"货品售价"
/>
<el-table-column
property=
"number"
label=
"货品数量"
/>
<el-table-column
property=
"url"
label=
"货品图片"
>
<
template
slot-scope=
"scope"
>
<img
v-if=
"scope.row.url"
:src=
"scope.row.url"
width=
"40"
>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"操作"
width=
"
1
00"
class-name=
"small-padding fixed-width"
>
<el-table-column
align=
"center"
label=
"操作"
width=
"
2
00"
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
:visible.sync=
"productVisiable"
title=
"
设置
货品"
>
<el-dialog
:visible.sync=
"productVisiable"
title=
"
编辑
货品"
>
<el-form
ref=
"productForm"
:model=
"productForm"
status-icon
label-position=
"left"
label-width=
"100px"
style=
"width: 400px; margin-left:50px;"
>
<el-form-item
label=
"货品规格列"
prop=
"specifications"
>
<el-tag
v-for=
"tag in productForm.specifications"
:key=
"tag"
>
...
...
@@ -185,10 +189,10 @@
</el-tag>
</el-form-item>
<el-form-item
label=
"货品售价"
prop=
"price"
>
<el-input
v-model=
"productForm.price"
/>
<el-input
v-model=
"productForm.price"
/>
</el-form-item>
<el-form-item
label=
"货品数量"
prop=
"number"
>
<el-input
v-model=
"productForm.number"
/>
<el-input
v-model=
"productForm.number"
/>
</el-form-item>
<el-form-item
label=
"货品图片"
prop=
"url"
>
<el-upload
...
...
@@ -197,9 +201,10 @@
:show-file-list=
"false"
:on-success=
"uploadProductUrl"
class=
"avatar-uploader"
accept=
".jpg,.jpeg,.png,.gif"
>
accept=
".jpg,.jpeg,.png,.gif"
>
<img
v-if=
"productForm.url"
:src=
"productForm.url"
class=
"avatar"
>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
/>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
/>
</el-upload>
</el-form-item>
</el-form>
...
...
@@ -212,29 +217,31 @@
<el-card
class=
"box-card"
>
<h3>
商品参数
</h3>
<el-button
:plain=
"true"
type=
"primary"
@
click=
"handleAttributeShow"
>
添加
</el-button>
<el-table
:data=
"attributes"
>
<el-table-column
property=
"attribute"
label=
"商品参数名称"
/>
<el-table-column
property=
"value"
label=
"商品参数值"
/>
<el-table-column
align=
"center"
label=
"操作"
width=
"
1
00"
class-name=
"small-padding fixed-width"
>
<el-button
type=
"primary"
@
click=
"handleAttributeShow"
>
添加
</el-button>
<el-table
:data=
"attributes
Data
"
>
<el-table-column
property=
"attribute"
label=
"商品参数名称"
/>
<el-table-column
property=
"value"
label=
"商品参数值"
/>
<el-table-column
align=
"center"
label=
"操作"
width=
"
2
00"
class-name=
"small-padding fixed-width"
>
<
template
slot-scope=
"scope"
>
<el-button
type=
"primary"
size=
"mini"
@
click=
"handleAttributeShow(scope.row)"
>
设置
</el-button>
<el-button
type=
"danger"
size=
"mini"
@
click=
"handleAttributeDelete(scope.row)"
>
删除
</el-button>
</
template
>
</el-table-column>
</el-table>
<el-dialog
:visible.sync=
"attributeVisiable"
title=
"
设置商品参数
"
>
<el-dialog
:visible.sync=
"attributeVisiable"
:
title=
"
attributeAdd ? '添加商品参数' : '编辑商品参数'
"
>
<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
v-model=
"attributeForm.attribute"
/>
</el-form-item>
<el-form-item
label=
"商品参数值"
prop=
"value"
>
<el-input
v-model=
"attributeForm.value"
/>
<el-input
v-model=
"attributeForm.value"
/>
</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>
<el-button
v-if=
"attributeAdd"
type=
"primary"
@
click=
"handleAttributeAdd"
>
确定
</el-button>
<el-button
v-else
type=
"primary"
@
click=
"handleAttributeEdit"
>
确定
</el-button>
</div>
</el-dialog>
</el-card>
...
...
@@ -282,6 +289,10 @@
height
:
145px
;
display
:
block
;
}
.op-container
{
display
:
flex
;
justify-content
:
center
;
}
</
style
>
<
script
>
...
...
@@ -320,16 +331,15 @@ export default {
{
id
:
0
,
specifications
:
[
'
标准
'
],
price
:
0.0
,
number
:
0
,
url
:
''
}
],
attributeVisiable
:
false
,
attributeAdd
:
true
,
attributeForm
:
{
attribute
:
''
,
value
:
''
},
attributes
:
[],
rules
:
{
goodsSn
:
[
{
required
:
true
,
message
:
'
商品编号不能为空
'
,
trigger
:
'
blur
'
}
],
name
:
[{
required
:
true
,
message
:
'
商品名称不能为空
'
,
trigger
:
'
blur
'
}]
},
editorInit
:
{
language
:
'
zh_CN
'
,
height
:
'
400px
'
,
convert_urls
:
false
,
plugins
:
[
'
advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools importcss insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount
'
...
...
@@ -357,6 +367,16 @@ export default {
return
{
'
X-Litemall-Admin-Token
'
:
getToken
()
}
},
attributesData
()
{
var
attributesData
=
[]
for
(
var
i
=
0
;
i
<
this
.
attributes
.
length
;
i
++
)
{
if
(
this
.
attributes
[
i
].
deleted
)
{
continue
}
attributesData
.
push
(
this
.
attributes
[
i
])
}
return
attributesData
}
},
created
()
{
...
...
@@ -488,99 +508,20 @@ export default {
uploadSpecPicUrl
:
function
(
response
)
{
this
.
specForm
.
picUrl
=
response
.
data
.
url
},
handleSpecificationShow
()
{
this
.
specForm
=
{
specification
:
''
,
value
:
''
,
picUrl
:
''
}
handleSpecificationShow
(
row
)
{
this
.
specForm
=
Object
.
assign
({},
row
)
this
.
specVisiable
=
true
},
handleSpecification
Add
()
{
var
index
=
this
.
specifications
.
length
-
1
handleSpecification
Edit
()
{
this
.
specForm
.
updateTime
=
''
for
(
var
i
=
0
;
i
<
this
.
specifications
.
length
;
i
++
)
{
const
v
=
this
.
specifications
[
i
]
if
(
v
.
specification
===
this
.
specForm
.
specification
)
{
index
=
i
if
(
v
.
id
===
this
.
specForm
.
id
)
{
this
.
specifications
.
splice
(
i
,
1
,
this
.
specForm
)
break
}
}
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.0
,
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
)
...
...
@@ -590,6 +531,7 @@ export default {
this
.
productForm
.
url
=
response
.
data
.
url
},
handleProductEdit
()
{
this
.
productForm
.
updateTime
=
''
for
(
var
i
=
0
;
i
<
this
.
products
.
length
;
i
++
)
{
const
v
=
this
.
products
[
i
]
if
(
v
.
id
===
this
.
productForm
.
id
)
{
...
...
@@ -599,17 +541,34 @@ export default {
}
this
.
productVisiable
=
false
},
handleAttributeShow
()
{
this
.
attributeForm
=
{}
handleAttributeShow
(
row
)
{
if
(
row
.
id
)
{
this
.
attributeForm
=
Object
.
assign
({},
row
)
this
.
attributeAdd
=
false
}
else
{
this
.
attributeForm
=
{}
this
.
attributeAdd
=
true
}
this
.
attributeVisiable
=
true
},
handleAttributeAdd
()
{
this
.
attributes
.
unshift
(
this
.
attributeForm
)
this
.
attributeVisiable
=
false
},
handleAttributeEdit
()
{
// 这是一个trick,设置updateTime的值为空,告诉后端这个记录已编辑需要更新。
this
.
attributeForm
.
updateTime
=
''
for
(
var
i
=
0
;
i
<
this
.
attributes
.
length
;
i
++
)
{
const
v
=
this
.
attributes
[
i
]
if
(
v
.
id
===
this
.
attributeForm
.
id
)
{
this
.
attributes
.
splice
(
i
,
1
,
this
.
attributeForm
)
break
}
}
this
.
attributeVisiable
=
false
},
handleAttributeDelete
(
row
)
{
const
index
=
this
.
attributes
.
indexOf
(
row
)
this
.
attributes
.
splice
(
index
,
1
)
row
.
deleted
=
true
}
}
}
...
...
litemall-admin/src/views/goods/list.vue
View file @
e9d284f5
...
...
@@ -3,8 +3,9 @@
<!-- 查询和其他操作 -->
<div
class=
"filter-container"
>
<el-input
v-model=
"listQuery.goodsSn"
clearable
class=
"filter-item"
style=
"width: 200px;"
placeholder=
"请输入商品编号"
/>
<el-input
v-model=
"listQuery.name"
clearable
class=
"filter-item"
style=
"width: 200px;"
placeholder=
"请输入商品名称"
/>
<el-input
v-model=
"listQuery.goodsId"
clearable
class=
"filter-item"
style=
"width: 160px;"
placeholder=
"请输入商品ID"
/>
<el-input
v-model=
"listQuery.goodsSn"
clearable
class=
"filter-item"
style=
"width: 160px;"
placeholder=
"请输入商品编号"
/>
<el-input
v-model=
"listQuery.name"
clearable
class=
"filter-item"
style=
"width: 160px;"
placeholder=
"请输入商品名称"
/>
<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
:loading=
"downloadLoading"
class=
"filter-item"
type=
"primary"
icon=
"el-icon-download"
@
click=
"handleDownload"
>
导出
</el-button>
...
...
@@ -16,6 +17,9 @@
<el-table-column
type=
"expand"
>
<template
slot-scope=
"props"
>
<el-form
label-position=
"left"
class=
"table-expand"
>
<el-form-item
label=
"商品编号"
>
<span>
{{
props
.
row
.
goodsSn
}}
</span>
</el-form-item>
<el-form-item
label=
"宣传画廊"
>
<img
v-for=
"pic in props.row.gallery"
:key=
"pic"
:src=
"pic"
class=
"gallery"
>
</el-form-item>
...
...
@@ -34,16 +38,14 @@
<el-form-item
label=
"品牌商ID"
>
<span>
{{
props
.
row
.
brandId
}}
</span>
</el-form-item>
<el-form-item
label=
"商品ID"
>
<span>
{{
props
.
row
.
id
}}
</span>
</el-form-item>
</el-form>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"商品
编号
"
prop=
"
goodsSn"
/>
<el-table-column
align=
"center"
label=
"商品
ID
"
prop=
"
id"
/>
<el-table-column
align=
"center"
min-width=
"100"
label=
"名称"
prop=
"name"
/>
<el-table-column
align=
"center"
min-width=
"100"
label=
"名称"
prop=
"name"
/>
<el-table-column
align=
"center"
property=
"iconUrl"
label=
"图片"
>
<
template
slot-scope=
"scope"
>
...
...
@@ -60,15 +62,15 @@
<el-table-column
align=
"center"
label=
"详情"
prop=
"detail"
>
<
template
slot-scope=
"scope"
>
<el-dialog
:visible.sync=
"detailDialogVisible"
title=
"商品详情"
>
<div
v-html=
"goodsDetail"
/>
<div
v-html=
"goodsDetail"
/>
</el-dialog>
<el-button
type=
"primary"
size=
"mini"
@
click=
"showDetail(scope.row.detail)"
>
查看
</el-button>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"专柜价格"
prop=
"counterPrice"
/>
<el-table-column
align=
"center"
label=
"专柜价格"
prop=
"counterPrice"
/>
<el-table-column
align=
"center"
label=
"当前价格"
prop=
"retailPrice"
/>
<el-table-column
align=
"center"
label=
"当前价格"
prop=
"retailPrice"
/>
<el-table-column
align=
"center"
label=
"是否新品"
prop=
"isNew"
>
<
template
slot-scope=
"scope"
>
...
...
litemall-core/src/main/java/org/linlinjava/litemall/core/express/ExpressService.java
View file @
e9d284f5
...
...
@@ -61,6 +61,10 @@ public class ExpressService {
* @return
*/
public
ExpressInfo
getExpressInfo
(
String
expCode
,
String
expNo
)
{
if
(!
properties
.
isEnable
())
{
return
null
;
}
try
{
String
result
=
getOrderTracesByJson
(
expCode
,
expNo
);
ObjectMapper
objMap
=
new
ObjectMapper
();
...
...
@@ -80,10 +84,6 @@ public class ExpressService {
* @throws Exception
*/
private
String
getOrderTracesByJson
(
String
expCode
,
String
expNo
)
throws
Exception
{
if
(!
properties
.
isEnable
())
{
return
null
;
}
String
requestData
=
"{'OrderCode':'','ShipperCode':'"
+
expCode
+
"','LogisticCode':'"
+
expNo
+
"'}"
;
Map
<
String
,
String
>
params
=
new
HashMap
<
String
,
String
>();
...
...
litemall-db/src/main/java/org/linlinjava/litemall/db/service/LitemallCartService.java
View file @
e9d284f5
...
...
@@ -8,6 +8,7 @@ import org.springframework.stereotype.Service;
import
org.springframework.util.StringUtils
;
import
javax.annotation.Resource
;
import
java.math.BigDecimal
;
import
java.time.LocalDateTime
;
import
java.util.List
;
...
...
@@ -102,4 +103,15 @@ public class LitemallCartService {
example
.
or
().
andGoodsIdEqualTo
(
goodsId
).
andCheckedEqualTo
(
true
).
andDeletedEqualTo
(
false
);
return
cartMapper
.
countByExample
(
example
)
!=
0
;
}
public
void
updateProduct
(
Integer
id
,
String
goodsSn
,
String
goodsName
,
BigDecimal
price
,
String
url
)
{
LitemallCart
cart
=
new
LitemallCart
();
cart
.
setPrice
(
price
);
cart
.
setPicUrl
(
url
);
cart
.
setGoodsSn
(
goodsSn
);
cart
.
setGoodsName
(
goodsName
);
LitemallCartExample
example
=
new
LitemallCartExample
();
example
.
or
().
andProductIdEqualTo
(
id
);
cartMapper
.
updateByExampleSelective
(
cart
,
example
);
}
}
litemall-db/src/main/java/org/linlinjava/litemall/db/service/LitemallGoodsAttributeService.java
View file @
e9d284f5
...
...
@@ -35,4 +35,9 @@ public class LitemallGoodsAttributeService {
example
.
or
().
andGoodsIdEqualTo
(
gid
);
goodsAttributeMapper
.
logicalDeleteByExample
(
example
);
}
public
void
updateById
(
LitemallGoodsAttribute
attribute
)
{
attribute
.
setUpdateTime
(
LocalDateTime
.
now
());
goodsAttributeMapper
.
updateByPrimaryKeySelective
(
attribute
);
}
}
litemall-db/src/main/java/org/linlinjava/litemall/db/service/LitemallGoodsProductService.java
View file @
e9d284f5
...
...
@@ -57,4 +57,9 @@ public class LitemallGoodsProductService {
public
int
reduceStock
(
Integer
id
,
Short
num
){
return
goodsProductMapper
.
reduceStock
(
id
,
num
);
}
public
void
updateById
(
LitemallGoodsProduct
product
)
{
product
.
setUpdateTime
(
LocalDateTime
.
now
());
litemallGoodsProductMapper
.
updateByPrimaryKeySelective
(
product
);
}
}
\ No newline at end of file
litemall-db/src/main/java/org/linlinjava/litemall/db/service/LitemallGoodsService.java
View file @
e9d284f5
...
...
@@ -127,10 +127,13 @@ public class LitemallGoodsService {
return
goodsMapper
.
selectByExampleSelective
(
example
,
columns
);
}
public
List
<
LitemallGoods
>
querySelective
(
String
goodsSn
,
String
name
,
Integer
page
,
Integer
size
,
String
sort
,
String
order
)
{
public
List
<
LitemallGoods
>
querySelective
(
Integer
goodsId
,
String
goodsSn
,
String
name
,
Integer
page
,
Integer
size
,
String
sort
,
String
order
)
{
LitemallGoodsExample
example
=
new
LitemallGoodsExample
();
LitemallGoodsExample
.
Criteria
criteria
=
example
.
createCriteria
();
if
(
goodsId
!=
null
)
{
criteria
.
andIdEqualTo
(
goodsId
);
}
if
(!
StringUtils
.
isEmpty
(
goodsSn
))
{
criteria
.
andGoodsSnEqualTo
(
goodsSn
);
}
...
...
litemall-db/src/main/java/org/linlinjava/litemall/db/service/LitemallGoodsSpecificationService.java
View file @
e9d284f5
...
...
@@ -80,6 +80,11 @@ public class LitemallGoodsSpecificationService {
return
specificationVoList
;
}
public
void
updateById
(
LitemallGoodsSpecification
specification
)
{
specification
.
setUpdateTime
(
LocalDateTime
.
now
());
goodsSpecificationMapper
.
updateByPrimaryKeySelective
(
specification
);
}
private
class
VO
{
private
String
name
;
private
List
<
LitemallGoodsSpecification
>
valueList
;
...
...
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