后端 + 前端:购物车详情
parent
fa5ea5dfd9
commit
b2abc625d1
|
@ -67,6 +67,26 @@ export function countCart() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function listCart() {
|
||||||
|
return request({
|
||||||
|
url: '/order-api/users/cart/list',
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateCartSelected(skuIds, selected) {
|
||||||
|
return request({
|
||||||
|
url: '/order-api/users/cart/update_selected',
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
skuIds: skuIds.join(','),
|
||||||
|
selected,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 物流信息
|
// 物流信息
|
||||||
|
|
||||||
export function getLogisticsInfo(params) {
|
export function getLogisticsInfo(params) {
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
</template>
|
</template>
|
||||||
<template slot="tags">
|
<template slot="tags">
|
||||||
<p class="price" v-if="product.price!=null && product.price !== ''">
|
<p class="price" v-if="product.price!=null && product.price !== ''">
|
||||||
¥<span>{{product.price}}</span>
|
¥<span>{{product.price / 100.00}}</span>
|
||||||
<!-- TODO 芋艿 暂时去掉 -->
|
<!-- TODO 芋艿 暂时去掉 -->
|
||||||
<!-- <van-tag v-if="product.tags!=null" v-for="tag in product.tags" :key="tag" plain type="danger">-->
|
<!-- <van-tag v-if="product.tags!=null" v-for="tag in product.tags" :key="tag" plain type="danger">-->
|
||||||
<!-- {{tag}}-->
|
<!-- {{tag}}-->
|
||||||
|
|
|
@ -3,17 +3,17 @@
|
||||||
<headerNav title="购物车"/>
|
<headerNav title="购物车"/>
|
||||||
<van-cell value="编辑商品" class="head">
|
<van-cell value="编辑商品" class="head">
|
||||||
<template slot="title">
|
<template slot="title">
|
||||||
<van-checkbox v-model="checkedAll" >全选</van-checkbox>
|
<van-checkbox v-model="checkedAll" @change="onSelectAll" >全选</van-checkbox>
|
||||||
</template>
|
</template>
|
||||||
</van-cell>
|
</van-cell>
|
||||||
|
|
||||||
<van-checkbox-group class="card-goods" v-model="checkedGoods">
|
<van-checkbox-group class="card-goods" v-model="checkedItemIds" @change="onItemSelectedChange">
|
||||||
|
|
||||||
<div class="promotion-group">
|
<div class="promotion-group">
|
||||||
<div v-for="(item,index) in goods" :key="index" class="card-goods__item">
|
<!-- <div v-for="(item,index) in goods" :key="index" class="card-goods__item">-->
|
||||||
<van-checkbox :name="item.id"></van-checkbox>
|
<!-- <van-checkbox :name="item.id" />-->
|
||||||
|
|
||||||
<product-card :product='item' :iscard='false' >
|
<!-- <product-card :product='item' :iscard='false' >-->
|
||||||
<!-- <template slot>-->
|
<!-- <template slot>-->
|
||||||
<!-- <van-cell value="修改" >-->
|
<!-- <van-cell value="修改" >-->
|
||||||
<!-- <template slot="title">-->
|
<!-- <template slot="title">-->
|
||||||
|
@ -22,11 +22,20 @@
|
||||||
<!-- </template>-->
|
<!-- </template>-->
|
||||||
<!-- </van-cell>-->
|
<!-- </van-cell>-->
|
||||||
<!-- </template>-->
|
<!-- </template>-->
|
||||||
</product-card>
|
<!-- </product-card>-->
|
||||||
</div>
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<div v-for="(itemGroup, i) in itemGroups" class="card-goods__item">
|
||||||
|
<div class="card" v-for="(item, j) in itemGroup.items" :key="j">
|
||||||
|
<van-checkbox :key="item.id" :name="item.id" v-model="item.selected" style="position: relative;" />
|
||||||
|
<product-card :product='convertProduct(item)'/>
|
||||||
|
</div>
|
||||||
|
<div style="height:15px;"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- <div class="promotion-group">-->
|
<!-- <div class="promotion-group">-->
|
||||||
|
|
||||||
<!-- <van-cell is-link class="head">-->
|
<!-- <van-cell is-link class="head">-->
|
||||||
<!-- <template slot="title">-->
|
<!-- <template slot="title">-->
|
||||||
|
@ -38,13 +47,13 @@
|
||||||
|
|
||||||
<div style="height:50px;"></div>
|
<div style="height:50px;"></div>
|
||||||
<van-submit-bar
|
<van-submit-bar
|
||||||
:price="totalPrice"
|
:price="fee.presentTotal"
|
||||||
:disabled="!checkedGoods.length"
|
:disabled="!checkedItemIds || !checkedItemIds.length"
|
||||||
:button-text="submitBarText"
|
:button-text="submitBarText"
|
||||||
@submit="onSubmit"
|
@submit="onSubmit"
|
||||||
>
|
>
|
||||||
<template slot>
|
<template slot>
|
||||||
<van-checkbox v-model="checkedAll" >全选</van-checkbox>
|
<van-checkbox v-model="checkedAll" @change="onSelectAll">全选</van-checkbox>
|
||||||
</template>
|
</template>
|
||||||
</van-submit-bar>
|
</van-submit-bar>
|
||||||
</div>
|
</div>
|
||||||
|
@ -52,62 +61,123 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
import {listCart, updateCartSelected} from "../../api/order";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
checkedAll:true,
|
itemGroups: [],
|
||||||
checkedGoods: ['1', '2', '3'],
|
fee: {
|
||||||
goods: [{
|
originalTotal: undefined,
|
||||||
id: '1',
|
discountTotal: undefined,
|
||||||
title: '星巴克(Starbucks)星冰乐 轻盈香草味 咖啡饮料 281ml*6瓶礼盒装低脂减糖',
|
postageTotal: undefined,
|
||||||
desc: '3.18kg/件',
|
presentTotal: undefined,
|
||||||
price: '200.00',
|
},
|
||||||
quantity: 1,
|
checkedItemIds: undefined, // 通过计算得出
|
||||||
picUrls: ['https://img.yzcdn.cn/public_files/2017/10/24/2f9a36046449dafb8608e99990b3c205.jpeg'],
|
oldCheckedItemIds: undefined, // 因为 vue 是双向绑定,用于解决 change 的时候,拿不到老值
|
||||||
imageTag:'比加入时降5元',
|
checkedAll: undefined, // 通过计算得出
|
||||||
}, {
|
}
|
||||||
id: '2',
|
|
||||||
title: '陕西蜜梨',
|
|
||||||
desc: '约600g',
|
|
||||||
price: '690.00',
|
|
||||||
quantity: 1,
|
|
||||||
picUrls: ['https://img.yzcdn.cn/public_files/2017/10/24/f6aabd6ac5521195e01e8e89ee9fc63f.jpeg'],
|
|
||||||
gift: [
|
|
||||||
{
|
|
||||||
title: "星巴克(Starbucks)星冰乐小熊吊饰星巴克(Starbucks)星冰乐小熊吊饰",
|
|
||||||
quantity: 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "星巴克(Starbucks)星冰乐小熊吊饰星巴克(Starbucks)星冰乐小熊吊饰",
|
|
||||||
quantity: 1
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}, {
|
|
||||||
id: '3',
|
|
||||||
title: '美国伽力果',
|
|
||||||
desc: '约680g/3个',
|
|
||||||
price: '2680.00',
|
|
||||||
quantity: 1,
|
|
||||||
picUrls: ['https://img.yzcdn.cn/public_files/2017/10/24/320454216bbe9e25c7651e1fa51b31fd.jpeg']
|
|
||||||
}]
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
submitBarText() {
|
submitBarText() {
|
||||||
const count = this.checkedGoods.length;
|
const count = this.checkedItemIds ? this.checkedItemIds.length : 0;
|
||||||
return '结算' + (count ? `(${count})` : '');
|
return '结算' + (count ? `(${count})` : '');
|
||||||
},
|
},
|
||||||
totalPrice() {
|
|
||||||
return this.goods.reduce((total, item) => total + (this.checkedGoods.indexOf(item.id) !== -1 ? parseFloat(item.price): 0), 0);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
calCheckedItemIds() {
|
||||||
|
// debugger;
|
||||||
|
let itemIds = [];
|
||||||
|
let checkedAll = true;
|
||||||
|
for (let i in this.itemGroups) {
|
||||||
|
let items = this.itemGroups[i].items;
|
||||||
|
for (let j in items) {
|
||||||
|
if (items[j].selected) {
|
||||||
|
itemIds.push(items[j].id);
|
||||||
|
} else {
|
||||||
|
checkedAll = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 赋值给 checkedItemIds、oldCheckedItemIds、checkedAll
|
||||||
|
this.checkedItemIds = itemIds;
|
||||||
|
this.oldCheckedItemIds = itemIds;
|
||||||
|
this.checkedAll = checkedAll;
|
||||||
|
},
|
||||||
|
getItemIds() {
|
||||||
|
let itemIds = [];
|
||||||
|
for (let i in this.itemGroups) {
|
||||||
|
let items = this.itemGroups[i].items;
|
||||||
|
for (let j in items) {
|
||||||
|
itemIds.push(items[j].id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return itemIds;
|
||||||
|
},
|
||||||
|
handleData(data) {
|
||||||
|
this.itemGroups = data.itemGroups;
|
||||||
|
this.fee = data.fee;
|
||||||
|
// 计算 checkedItemIds + checkedAll
|
||||||
|
this.calCheckedItemIds();
|
||||||
|
},
|
||||||
|
onItemSelectedChange(newVal) {
|
||||||
|
if (!this.checkedItemIds) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// debugger;
|
||||||
|
let selected;
|
||||||
|
let diffItemIds;
|
||||||
|
if (newVal.length > this.oldCheckedItemIds.length) { // 新增
|
||||||
|
selected = true;
|
||||||
|
let that = this;
|
||||||
|
diffItemIds = [...newVal].filter(function(val) {
|
||||||
|
return that.oldCheckedItemIds.indexOf(val) < 0; // 找不到
|
||||||
|
});
|
||||||
|
} else if (newVal.length < this.oldCheckedItemIds.length) { // 减少
|
||||||
|
selected = false;
|
||||||
|
diffItemIds = [...this.oldCheckedItemIds].filter(function(val) {
|
||||||
|
return newVal.indexOf(val) < 0; // 找不到
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
updateCartSelected(diffItemIds, selected).then(data => {
|
||||||
|
this.handleData(data);
|
||||||
|
})
|
||||||
|
// debugger;
|
||||||
|
},
|
||||||
|
onSelectAll(newVal) {
|
||||||
|
if (this.checkedAll === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
updateCartSelected(this.getItemIds(), newVal).then(data => {
|
||||||
|
this.handleData(data);
|
||||||
|
})
|
||||||
|
},
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
|
|
||||||
this.$router.push('/order')
|
this.$router.push('/order')
|
||||||
|
},
|
||||||
|
convertProduct(item) {
|
||||||
|
// debugger;
|
||||||
|
return {
|
||||||
|
...item.spu,
|
||||||
|
quantity: item.buyQuantity,
|
||||||
|
price: item.price,
|
||||||
|
sku: {
|
||||||
|
...item,
|
||||||
|
spu: undefined,
|
||||||
|
},
|
||||||
|
selected: item.selected,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
// 获得购物车列表
|
||||||
|
listCart().then(data => {
|
||||||
|
this.handleData(data);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -3,18 +3,20 @@ package cn.iocoder.mall.order.application.controller.users;
|
||||||
import cn.iocoder.common.framework.vo.CommonResult;
|
import cn.iocoder.common.framework.vo.CommonResult;
|
||||||
import cn.iocoder.mall.order.api.CartService;
|
import cn.iocoder.mall.order.api.CartService;
|
||||||
import cn.iocoder.mall.order.api.OrderService;
|
import cn.iocoder.mall.order.api.OrderService;
|
||||||
|
import cn.iocoder.mall.order.api.bo.CalcOrderPriceBO;
|
||||||
import cn.iocoder.mall.order.api.bo.CartItemBO;
|
import cn.iocoder.mall.order.api.bo.CartItemBO;
|
||||||
|
import cn.iocoder.mall.order.api.dto.CalcOrderPriceDTO;
|
||||||
|
import cn.iocoder.mall.order.application.convert.CartConvert;
|
||||||
|
import cn.iocoder.mall.order.application.vo.UsersCartDetailVO;
|
||||||
import cn.iocoder.mall.order.application.vo.UsersOrderConfirmCreateVO;
|
import cn.iocoder.mall.order.application.vo.UsersOrderConfirmCreateVO;
|
||||||
import cn.iocoder.mall.user.sdk.context.UserSecurityContextHolder;
|
import cn.iocoder.mall.user.sdk.context.UserSecurityContextHolder;
|
||||||
import com.alibaba.dubbo.config.annotation.Reference;
|
import com.alibaba.dubbo.config.annotation.Reference;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("users/cart")
|
@RequestMapping("users/cart")
|
||||||
|
@ -26,8 +28,8 @@ public class UsersCartController {
|
||||||
private OrderService orderService;
|
private OrderService orderService;
|
||||||
|
|
||||||
@PostMapping("add")
|
@PostMapping("add")
|
||||||
public CommonResult<Integer> add(@Param("skuId") Integer skuId,
|
public CommonResult<Integer> add(@RequestParam("skuId") Integer skuId,
|
||||||
@Param("quantity") Integer quantity) {
|
@RequestParam("quantity") Integer quantity) {
|
||||||
// 添加到购物车
|
// 添加到购物车
|
||||||
CommonResult<Boolean> addResult = cartService.add(UserSecurityContextHolder.getContext().getUserId(),
|
CommonResult<Boolean> addResult = cartService.add(UserSecurityContextHolder.getContext().getUserId(),
|
||||||
skuId, quantity);
|
skuId, quantity);
|
||||||
|
@ -40,8 +42,8 @@ public class UsersCartController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("update_quantity")
|
@PostMapping("update_quantity")
|
||||||
public CommonResult<Integer> updateQuantity(@Param("skuId") Integer skuId,
|
public CommonResult<UsersCartDetailVO> updateQuantity(@RequestParam("skuId") Integer skuId, // TODO 芋艿,先暂用这个 VO 。等促销活动出来后,做调整
|
||||||
@Param("quantity") Integer quantity) {
|
@RequestParam("quantity") Integer quantity) {
|
||||||
// 添加到购物车
|
// 添加到购物车
|
||||||
CommonResult<Boolean> updateQuantityResult = cartService.updateQuantity(UserSecurityContextHolder.getContext().getUserId(),
|
CommonResult<Boolean> updateQuantityResult = cartService.updateQuantity(UserSecurityContextHolder.getContext().getUserId(),
|
||||||
skuId, quantity);
|
skuId, quantity);
|
||||||
|
@ -49,24 +51,22 @@ public class UsersCartController {
|
||||||
if (updateQuantityResult.isError()) {
|
if (updateQuantityResult.isError()) {
|
||||||
return CommonResult.error(updateQuantityResult);
|
return CommonResult.error(updateQuantityResult);
|
||||||
}
|
}
|
||||||
// 获得目前购物车商品总数量
|
// 获得目前购物车明细
|
||||||
// TODO 芋艿,需要改成价格计算
|
return getCartDetail();
|
||||||
return cartService.count(UserSecurityContextHolder.getContext().getUserId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("update_selected")
|
@PostMapping("update_selected")
|
||||||
public CommonResult<Integer> updateSelected(@Param("skuId") Integer skuId,
|
public CommonResult<UsersCartDetailVO> updateSelected(@RequestParam("skuIds") Set<Integer> skuIds, // TODO 芋艿,先暂用这个 VO 。等促销活动出来后,做调整
|
||||||
@Param("selected") Boolean selected) {
|
@RequestParam("selected") Boolean selected) {
|
||||||
// 添加到购物车
|
// 添加到购物车
|
||||||
CommonResult<Boolean> updateSelectedResult = cartService.updateSelected(UserSecurityContextHolder.getContext().getUserId(),
|
CommonResult<Boolean> updateSelectedResult = cartService.updateSelected(UserSecurityContextHolder.getContext().getUserId(),
|
||||||
skuId, selected);
|
skuIds, selected);
|
||||||
// 添加失败,则直接返回错误
|
// 添加失败,则直接返回错误
|
||||||
if (updateSelectedResult.isError()) {
|
if (updateSelectedResult.isError()) {
|
||||||
return CommonResult.error(updateSelectedResult);
|
return CommonResult.error(updateSelectedResult);
|
||||||
}
|
}
|
||||||
// 获得目前购物车商品总数量
|
// 获得目前购物车明细
|
||||||
// TODO 芋艿,需要改成价格计算
|
return getCartDetail();
|
||||||
return cartService.count(UserSecurityContextHolder.getContext().getUserId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("count")
|
@GetMapping("count")
|
||||||
|
@ -75,25 +75,33 @@ public class UsersCartController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
public CommonResult<UsersOrderConfirmCreateVO> list() {
|
public CommonResult<UsersCartDetailVO> list() { // TODO 芋艿,先暂用这个 VO 。等促销活动出来后,做调整
|
||||||
// 获得购物车中所有的
|
return getCartDetail();
|
||||||
List<CartItemBO> cartItems = cartService.list(UserSecurityContextHolder.getContext().getUserId(), null);
|
}
|
||||||
|
|
||||||
|
private CommonResult<UsersCartDetailVO> getCartDetail() {
|
||||||
|
// 获得购物车中选中的
|
||||||
|
List<CartItemBO> cartItems = cartService.list(UserSecurityContextHolder.getContext().getUserId(), null).getData();
|
||||||
// 购物车为空时,构造空的 UsersOrderConfirmCreateVO 返回
|
// 购物车为空时,构造空的 UsersOrderConfirmCreateVO 返回
|
||||||
if (cartItems.isEmpty()) {
|
if (cartItems.isEmpty()) {
|
||||||
UsersOrderConfirmCreateVO result = new UsersOrderConfirmCreateVO();
|
UsersCartDetailVO result = new UsersCartDetailVO();
|
||||||
result.setItemGroups(Collections.emptyList());
|
result.setItemGroups(Collections.emptyList());
|
||||||
result.setFee(new UsersOrderConfirmCreateVO.Fee(0, 0, 0, 0));
|
result.setFee(new UsersCartDetailVO.Fee(0, 0, 0, 0));
|
||||||
return CommonResult.success(result);
|
return CommonResult.success(result);
|
||||||
}
|
}
|
||||||
// 购物车非空时,获得具体结果
|
// 计算商品价格
|
||||||
|
CommonResult<CalcOrderPriceBO> calcOrderPriceResult = list0(cartItems);
|
||||||
return null;
|
if (calcOrderPriceResult.isError()) {
|
||||||
|
return CommonResult.error(calcOrderPriceResult);
|
||||||
|
}
|
||||||
|
// 执行数据拼装
|
||||||
|
return CommonResult.success(CartConvert.INSTANCE.convert2(calcOrderPriceResult.getData()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/confirm_create_order")
|
@GetMapping("/confirm_create_order")
|
||||||
public CommonResult<UsersOrderConfirmCreateVO> getConfirmCreateOrder() {
|
public CommonResult<UsersOrderConfirmCreateVO> getConfirmCreateOrder() {
|
||||||
// 获得购物车中选中的
|
// 获得购物车中选中的
|
||||||
List<CartItemBO> cartItems = cartService.list(UserSecurityContextHolder.getContext().getUserId(), true);
|
List<CartItemBO> cartItems = cartService.list(UserSecurityContextHolder.getContext().getUserId(), true).getData();
|
||||||
// 购物车为空时,构造空的 UsersOrderConfirmCreateVO 返回
|
// 购物车为空时,构造空的 UsersOrderConfirmCreateVO 返回
|
||||||
if (cartItems.isEmpty()) {
|
if (cartItems.isEmpty()) {
|
||||||
UsersOrderConfirmCreateVO result = new UsersOrderConfirmCreateVO();
|
UsersOrderConfirmCreateVO result = new UsersOrderConfirmCreateVO();
|
||||||
|
@ -101,9 +109,24 @@ public class UsersCartController {
|
||||||
result.setFee(new UsersOrderConfirmCreateVO.Fee(0, 0, 0, 0));
|
result.setFee(new UsersOrderConfirmCreateVO.Fee(0, 0, 0, 0));
|
||||||
return CommonResult.success(result);
|
return CommonResult.success(result);
|
||||||
}
|
}
|
||||||
// 购物车非空时,获得具体结果
|
// 计算商品价格
|
||||||
// return CommonResult.success(CartConvert.INSTANCE.convert(calcOrderPriceResult.getData()));
|
CommonResult<CalcOrderPriceBO> calcOrderPriceResult = list0(cartItems);
|
||||||
return null;
|
if (calcOrderPriceResult.isError()) {
|
||||||
|
return CommonResult.error(calcOrderPriceResult);
|
||||||
|
}
|
||||||
|
// 执行数据拼装
|
||||||
|
return CommonResult.success(CartConvert.INSTANCE.convert(calcOrderPriceResult.getData()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private CommonResult<CalcOrderPriceBO> list0(List<CartItemBO> cartItems) {
|
||||||
|
// 创建计算的 DTO
|
||||||
|
CalcOrderPriceDTO calcOrderPriceDTO = new CalcOrderPriceDTO()
|
||||||
|
.setItems(new ArrayList<>(cartItems.size()));
|
||||||
|
for (CartItemBO item : cartItems) {
|
||||||
|
calcOrderPriceDTO.getItems().add(new CalcOrderPriceDTO.Item(item.getSkuId(), item.getQuantity(), item.getSelected()));
|
||||||
|
}
|
||||||
|
// 执行计算
|
||||||
|
return cartService.calcOrderPrice(calcOrderPriceDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommonResult<Object> confirmOrder() {
|
public CommonResult<Object> confirmOrder() {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package cn.iocoder.mall.order.application.convert;
|
package cn.iocoder.mall.order.application.convert;
|
||||||
|
|
||||||
import cn.iocoder.mall.order.api.bo.CalcOrderPriceBO;
|
import cn.iocoder.mall.order.api.bo.CalcOrderPriceBO;
|
||||||
|
import cn.iocoder.mall.order.application.vo.UsersCartDetailVO;
|
||||||
import cn.iocoder.mall.order.application.vo.UsersOrderConfirmCreateVO;
|
import cn.iocoder.mall.order.application.vo.UsersOrderConfirmCreateVO;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
@ -12,4 +13,6 @@ public interface CartConvert {
|
||||||
|
|
||||||
UsersOrderConfirmCreateVO convert(CalcOrderPriceBO calcOrderPriceBO);
|
UsersOrderConfirmCreateVO convert(CalcOrderPriceBO calcOrderPriceBO);
|
||||||
|
|
||||||
|
UsersCartDetailVO convert2(CalcOrderPriceBO calcOrderPriceBO);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
package cn.iocoder.mall.order.application.vo;
|
|
||||||
|
|
||||||
public class FeeMessageVO {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 总价
|
|
||||||
*/
|
|
||||||
private Integer originalTotal;
|
|
||||||
/**
|
|
||||||
* 优惠总价
|
|
||||||
*
|
|
||||||
* 注意,满多少元包邮,不算在优惠中。
|
|
||||||
*/
|
|
||||||
private Integer discountTotal;
|
|
||||||
/**
|
|
||||||
* 邮费
|
|
||||||
*/
|
|
||||||
private Integer postageTotal;
|
|
||||||
/**
|
|
||||||
* 最终价格
|
|
||||||
*
|
|
||||||
* 计算公式 = 总价 - 优惠总价 + 邮费
|
|
||||||
*/
|
|
||||||
private Integer presentTotal;
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,167 @@
|
||||||
|
package cn.iocoder.mall.order.application.vo;
|
||||||
|
|
||||||
|
import cn.iocoder.mall.product.api.bo.ProductAttrAndValuePairBO;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@ApiModel(value = "购物车明细 VO")
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class UsersCartDetailVO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品分组数组
|
||||||
|
*/
|
||||||
|
private List<ItemGroup> itemGroups;
|
||||||
|
/**
|
||||||
|
* 费用
|
||||||
|
*/
|
||||||
|
private Fee fee;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品分组
|
||||||
|
*
|
||||||
|
* 多个商品,参加同一个活动,从而形成分组。
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public static class ItemGroup {
|
||||||
|
|
||||||
|
// TODO 优惠活动
|
||||||
|
private Object activity;
|
||||||
|
/**
|
||||||
|
* 商品数组
|
||||||
|
*/
|
||||||
|
private List<Sku> items;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public static class Sku {
|
||||||
|
|
||||||
|
// SKU 自带信息
|
||||||
|
/**
|
||||||
|
* sku 编号
|
||||||
|
*/
|
||||||
|
private Integer id;
|
||||||
|
/**
|
||||||
|
* SPU 信息
|
||||||
|
*/
|
||||||
|
private Spu spu;
|
||||||
|
/**
|
||||||
|
* 图片地址
|
||||||
|
*/
|
||||||
|
private String picURL;
|
||||||
|
/**
|
||||||
|
* 规格值数组
|
||||||
|
*/
|
||||||
|
private List<ProductAttrAndValuePairBO> attrs; // TODO 后面改下
|
||||||
|
/**
|
||||||
|
* 价格,单位:分
|
||||||
|
*/
|
||||||
|
private Integer price;
|
||||||
|
/**
|
||||||
|
* 库存数量
|
||||||
|
*/
|
||||||
|
private Integer quantity;
|
||||||
|
|
||||||
|
// 非 SKU 自带信息
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 购买数量
|
||||||
|
*/
|
||||||
|
private Integer buyQuantity;
|
||||||
|
/**
|
||||||
|
* 是否选中
|
||||||
|
*/
|
||||||
|
private Boolean selected;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public static class Spu {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SPU 编号
|
||||||
|
*/
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
// ========== 基本信息 =========
|
||||||
|
/**
|
||||||
|
* SPU 名字
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 分类编号
|
||||||
|
*/
|
||||||
|
private Integer cid;
|
||||||
|
/**
|
||||||
|
* 商品主图地址
|
||||||
|
*
|
||||||
|
* 数组,以逗号分隔
|
||||||
|
*
|
||||||
|
* 建议尺寸:800*800像素,你可以拖拽图片调整顺序,最多上传15张
|
||||||
|
*/
|
||||||
|
private List<String> picUrls;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 费用(合计)
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public static class Fee {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 总价
|
||||||
|
*/
|
||||||
|
private Integer originalTotal;
|
||||||
|
/**
|
||||||
|
* 优惠总价
|
||||||
|
*
|
||||||
|
* 注意,满多少元包邮,不算在优惠中。
|
||||||
|
*/
|
||||||
|
private Integer discountTotal;
|
||||||
|
/**
|
||||||
|
* 邮费
|
||||||
|
*/
|
||||||
|
private Integer postageTotal;
|
||||||
|
/**
|
||||||
|
* 最终价格
|
||||||
|
*
|
||||||
|
* 计算公式 = 总价 - 优惠总价 + 邮费
|
||||||
|
*/
|
||||||
|
private Integer presentTotal;
|
||||||
|
|
||||||
|
public Fee() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Fee(Integer originalTotal, Integer discountTotal, Integer postageTotal, Integer presentTotal) {
|
||||||
|
this.originalTotal = originalTotal;
|
||||||
|
this.discountTotal = discountTotal;
|
||||||
|
this.postageTotal = postageTotal;
|
||||||
|
this.presentTotal = presentTotal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮费信息
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public static class Postage {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 需要满足多少钱,可以包邮。单位:分
|
||||||
|
*/
|
||||||
|
private Integer threshold;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +0,0 @@
|
||||||
package cn.iocoder.mall.order.application.vo;
|
|
||||||
|
|
||||||
public class UsersCartItemVO {
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
package cn.iocoder.mall.order.application.vo;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class UsersCartListVO {
|
|
||||||
|
|
||||||
private List<UsersCartItemVO> items;
|
|
||||||
|
|
||||||
private FeeMessageVO feeMessage;
|
|
||||||
|
|
||||||
}
|
|
|
@ -8,6 +8,7 @@ import cn.iocoder.mall.order.api.bo.OrderCreateBO;
|
||||||
import cn.iocoder.mall.order.api.dto.CalcOrderPriceDTO;
|
import cn.iocoder.mall.order.api.dto.CalcOrderPriceDTO;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface CartService {
|
public interface CartService {
|
||||||
|
@ -38,11 +39,11 @@ public interface CartService {
|
||||||
* 购物车更新商品是否选中
|
* 购物车更新商品是否选中
|
||||||
*
|
*
|
||||||
* @param userId 用户编号
|
* @param userId 用户编号
|
||||||
* @param skuId 商品 SKU 编号
|
* @param skuIds 商品 SKU 编号数组
|
||||||
* @param selected 是否选中
|
* @param selected 是否选中
|
||||||
* @return 是否成功
|
* @return 是否成功
|
||||||
*/
|
*/
|
||||||
CommonResult<Boolean> updateSelected(Integer userId, Integer skuId, Boolean selected);
|
CommonResult<Boolean> updateSelected(Integer userId, Collection<Integer> skuIds, Boolean selected);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 购物车删除商品
|
* 购物车删除商品
|
||||||
|
@ -77,7 +78,7 @@ public interface CartService {
|
||||||
* @param selected 是否选中。若为空,则不进行筛选
|
* @param selected 是否选中。若为空,则不进行筛选
|
||||||
* @return 购物车中商品列表信息
|
* @return 购物车中商品列表信息
|
||||||
*/
|
*/
|
||||||
List<CartItemBO> list(Integer userId, @Nullable Boolean selected);
|
CommonResult<List<CartItemBO>> list(Integer userId, @Nullable Boolean selected);
|
||||||
|
|
||||||
// ========== 购物车与订单相关的逻辑 ==========
|
// ========== 购物车与订单相关的逻辑 ==========
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@ package cn.iocoder.mall.order.api.bo;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 购物车的商品信息 DO
|
* 购物车的商品信息 DO
|
||||||
*/
|
*/
|
||||||
|
@ -10,6 +12,89 @@ import lombok.experimental.Accessors;
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
public class CartItemBO {
|
public class CartItemBO {
|
||||||
|
|
||||||
|
// ========= 基础字段 BEGIN =========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编号,唯一自增。
|
||||||
|
*/
|
||||||
|
private Integer id;
|
||||||
|
/**
|
||||||
|
* 状态
|
||||||
|
*
|
||||||
|
* 1-正常
|
||||||
|
* 2-主动删除
|
||||||
|
* 3-下单删除
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
/**
|
||||||
|
* 是否选中
|
||||||
|
*/
|
||||||
|
private Boolean selected;
|
||||||
|
|
||||||
|
// ========= 基础字段 END =========
|
||||||
|
|
||||||
|
// ========= 买家信息 BEGIN =========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户编号
|
||||||
|
*/
|
||||||
|
private Integer userId;
|
||||||
|
// /**
|
||||||
|
// * 会话 key
|
||||||
|
// */
|
||||||
|
// private String nobody;
|
||||||
|
|
||||||
|
// ========= 买家信息 END =========
|
||||||
|
|
||||||
|
// ========= 商品信息 BEGIN =========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品 SPU 编号
|
||||||
|
*/
|
||||||
|
private Integer spuId;
|
||||||
|
/**
|
||||||
|
* 商品 SKU 编号
|
||||||
|
*/
|
||||||
|
private Integer skuId;
|
||||||
|
/**
|
||||||
|
* 商品购买数量
|
||||||
|
*/
|
||||||
|
private Integer quantity;
|
||||||
|
|
||||||
|
// TODO 冗余字段
|
||||||
|
|
||||||
|
|
||||||
|
// ========= 商品信息 END =========
|
||||||
|
|
||||||
|
// ========= 交易信息 BEGIN =========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单编号
|
||||||
|
*/
|
||||||
|
private Integer orderId;
|
||||||
|
/**
|
||||||
|
* 订单创建时间
|
||||||
|
*/
|
||||||
|
private Date orderCreateTime;
|
||||||
|
|
||||||
|
// ========= 交易信息 BEGIN =========
|
||||||
|
|
||||||
|
// ========= 优惠信息 BEGIN =========
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 商品营销活动编号
|
||||||
|
// */
|
||||||
|
// private Integer activityId;
|
||||||
|
// /**
|
||||||
|
// * 商品营销活动类型
|
||||||
|
// */
|
||||||
|
// private Integer activityType;
|
||||||
|
|
||||||
|
// ========= 优惠信息 END =========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
package cn.iocoder.mall.order.biz.convert;
|
package cn.iocoder.mall.order.biz.convert;
|
||||||
|
|
||||||
import cn.iocoder.mall.order.api.bo.CalcOrderPriceBO;
|
import cn.iocoder.mall.order.api.bo.CalcOrderPriceBO;
|
||||||
|
import cn.iocoder.mall.order.api.bo.CartItemBO;
|
||||||
|
import cn.iocoder.mall.order.biz.dataobject.CartItemDO;
|
||||||
import cn.iocoder.mall.product.api.bo.ProductSkuDetailBO;
|
import cn.iocoder.mall.product.api.bo.ProductSkuDetailBO;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface CartConvert {
|
public interface CartConvert {
|
||||||
|
|
||||||
|
@ -12,4 +16,6 @@ public interface CartConvert {
|
||||||
|
|
||||||
CalcOrderPriceBO.Item convert(ProductSkuDetailBO sku);
|
CalcOrderPriceBO.Item convert(ProductSkuDetailBO sku);
|
||||||
|
|
||||||
|
List<CartItemBO> convert(List<CartItemDO> items);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,9 @@ public interface CartMapper {
|
||||||
Integer selectQuantitySumByUserIdAndStatus(@Param("userId") Integer userId,
|
Integer selectQuantitySumByUserIdAndStatus(@Param("userId") Integer userId,
|
||||||
@Param("status") Integer status);
|
@Param("status") Integer status);
|
||||||
|
|
||||||
// List<CartItemDO> selectListByStatus(@Param("status") Integer status);
|
List<CartItemDO> selectByUserIdAndStatusAndSelected(@Param("userId") Integer userId,
|
||||||
|
@Param("status") Integer status,
|
||||||
|
@Param("selected") Boolean selected);
|
||||||
//
|
//
|
||||||
// List<CartItemDO> selectListByTitleLike(@Param("title") String title,
|
// List<CartItemDO> selectListByTitleLike(@Param("title") String title,
|
||||||
// @Param("offset") Integer offset,
|
// @Param("offset") Integer offset,
|
||||||
|
@ -36,4 +38,8 @@ public interface CartMapper {
|
||||||
int updateQuantity(@Param("id") Integer id,
|
int updateQuantity(@Param("id") Integer id,
|
||||||
@Param("quantityIncr") Integer quantityIncr);
|
@Param("quantityIncr") Integer quantityIncr);
|
||||||
|
|
||||||
|
int updateListSelected(@Param("userId") Integer userId,
|
||||||
|
@Param("skuIds") Collection<Integer> skuIds,
|
||||||
|
@Param("selected") Boolean selected);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,10 +44,6 @@ public class CartItemDO extends BaseDO {
|
||||||
* 用户编号
|
* 用户编号
|
||||||
*/
|
*/
|
||||||
private Integer userId;
|
private Integer userId;
|
||||||
// /**
|
|
||||||
// * 会话 key
|
|
||||||
// */
|
|
||||||
// private String nobody;
|
|
||||||
|
|
||||||
// ========= 买家信息 END =========
|
// ========= 买家信息 END =========
|
||||||
|
|
||||||
|
|
|
@ -114,15 +114,9 @@ public class CartServiceImpl implements CartService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommonResult<Boolean> updateSelected(Integer userId, Integer skuId, Boolean selected) {
|
public CommonResult<Boolean> updateSelected(Integer userId, Collection<Integer> skuIds, Boolean selected) {
|
||||||
// 查询 CartItemDO
|
// 更新 CartItemDO 们
|
||||||
CartItemDO item = cartMapper.selectByUserIdAndSkuIdAndStatus(userId, skuId, CartItemStatusEnum.ENABLE.getValue());
|
cartMapper.updateListSelected(userId, skuIds, selected);
|
||||||
if (item == null) {
|
|
||||||
return ServiceExceptionUtil.error(OrderErrorCodeEnum.CARD_ITEM_NOT_FOUND.getCode());
|
|
||||||
}
|
|
||||||
// 更新 CartItemDO
|
|
||||||
CartItemDO updateCartItem = new CartItemDO().setId(item.getId()).setSelected(selected);
|
|
||||||
cartMapper.update(updateCartItem);
|
|
||||||
// 返回成功
|
// 返回成功
|
||||||
return CommonResult.success(true);
|
return CommonResult.success(true);
|
||||||
}
|
}
|
||||||
|
@ -143,8 +137,9 @@ public class CartServiceImpl implements CartService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<CartItemBO> list(Integer userId, Boolean selected) {
|
public CommonResult<List<CartItemBO>> list(Integer userId, Boolean selected) {
|
||||||
return null;
|
List<CartItemDO> items = cartMapper.selectByUserIdAndStatusAndSelected(userId, CartItemStatusEnum.ENABLE.getValue(), selected);
|
||||||
|
return CommonResult.success(CartConvert.INSTANCE.convert(items));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -38,6 +38,18 @@
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectByUserIdAndStatusAndSelected" resultType="CartItemDO">
|
||||||
|
SELECT
|
||||||
|
<include refid="FIELDS" />
|
||||||
|
FROM cart_item
|
||||||
|
WHERE user_id = #{userId}
|
||||||
|
AND status = #{status}
|
||||||
|
<if test="selected != null">
|
||||||
|
AND selected = #{selected}
|
||||||
|
</if>
|
||||||
|
-- AND deleted = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="selectQuantitySumByUserIdAndStatus" resultType="Integer">
|
<select id="selectQuantitySumByUserIdAndStatus" resultType="Integer">
|
||||||
SELECT
|
SELECT
|
||||||
SUM(quantity)
|
SUM(quantity)
|
||||||
|
@ -96,4 +108,15 @@
|
||||||
WHERE id = #{id}
|
WHERE id = #{id}
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
|
<update id="updateListSelected">
|
||||||
|
UPDATE cart_item
|
||||||
|
SET selected = #{selected}
|
||||||
|
WHERE user_id = #{userId}
|
||||||
|
AND sku_id IN
|
||||||
|
<foreach item="skuId" collection="skuIds" separator="," open="(" close=")" index="">
|
||||||
|
#{skuId}
|
||||||
|
</foreach>
|
||||||
|
-- AND deleted = 0
|
||||||
|
</update>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
Loading…
Reference in New Issue