<script>
import { defineComponent, reactive, onMounted, computed, ref } from "vue";
import {
getSearchList,
getUpdateCheck,
getDelete,
changNumberValue,
getInventory,
} from "./service";
import { useRouter } from "vue-router";
import defaultSvg from "~/assets/icons/icon-nograph.svg";
import { ElImage } from "~/components/el";
import { useGoodsSearchKeyStore } from "~/store/goods";
import { message, notification } from "ant-design-vue";
export default defineComponent({
setup() {
let shopCart = reactive({
dataSource: [],
});
let allChecked = ref(false);
const useGoodsSearchKey = useGoodsSearchKeyStore();
let loading = ref(false);
let WithIconType = ref("success");
// 明细数量变更
const changeProductCount = (item, type) => {
if (type === "sub" && item.num > 1) {
item.num--;
item.totalPrice = (item.price * item.num).toFixed(2);
inventory(item);
}
if (type === "add") {
item.num++;
item.totalPrice = (item.price * item.num).toFixed(2);
inventory(item);
}
if (type === "change") {
if (item.num == "" || item.num == null) {
item.num = 1;
inventory(item);
// return;
} else {
if (item.num == 0) {
item.num = 1;
inventory(item);
}
inventory(item);
}
}
};
// 库存接口
const inventory = async (item) => {
let params = {
ouId: item.ouId,
skuIds: [item.itemId],
};
const res = await getInventory(params);
if (res.code === 200 && res.success) {
let arr = res.data || [];
arr.forEach((el) => {
if (item.num > el.avalQty) {
item.num = el.avalQty;
changNumber(item);
notification.warning({
message: "温馨提示",
description: `不能超过最大库存${el.avalQty}`,
});
} else {
changNumber(item);
}
});
}
};
// 改变商品数量接口
const changNumber = async (item) => {
let params = {
num: item.num,
skuId: item.itemId,
};
const res = await changNumberValue(params);
if (res.success) {
WatchCartNum();
}
};
// 数量变化的时候调用购物车数量执行接口
const WatchCartNum = () => {
let sum = 0;
shopCart.dataSource?.forEach((item) => {
if (item?.itemList && item?.itemList.length > 0) {
item?.itemList.forEach((el) => {
sum += el.num;
});
}
});
useGoodsSearchKey.set_num(sum);
};
// 计算属性--计算总价
let priceTotal = computed(() => {
let totalNum = 0;
shopCart.dataSource?.forEach((item) => {
if (item?.itemList.length > 0) {
item?.itemList.forEach((el) => {
if (el.itemCheck) {
totalNum += el.num * el.price;
}
});
}
});
return totalNum.toFixed(2);
});
// 计算属性-- 判断选中的件数 和
let checkNum = computed(() => {
let checkNumber = 0;
shopCart.dataSource?.forEach((item) => {
if (item?.itemList && item?.itemList.length > 0) {
item?.itemList.forEach((el) => {
if (el.itemCheck) {
checkNumber += 1;
}
});
}
});
return checkNumber;
});
// 公司选中的时候改变明细选中状态
const selectShopItems = async (item) => {
let cartItemCheckParamVOS = [];
item?.itemList?.forEach((i) => {
if (item.check === false) {
cartItemCheckParamVOS.push({
check: true,
skuId: i.itemId,
});
} else {
cartItemCheckParamVOS.push({
check: false,
skuId: i.itemId,
});
}
});
const res = await getUpdateCheck(cartItemCheckParamVOS);
if (res.success) {
item.check = !item.check;
item?.itemList.forEach((p) => {
p.itemCheck = item.check;
});
selectAll(item);
} else {
item.check = item.check;
// let checkCompany = item?.itemList.every((s) => s.itemCheck === true);
// item.check = checkCompany;
item?.itemList.forEach((p) => {
p.itemCheck = item.check;
});
selectAll(item);
}
};
// 明细选中
const checkItem = async (el, item) => {
let cartItemCheckParamVOS = [];
item?.itemList?.forEach((i) => {
if (i.itemId == el.itemId) {
cartItemCheckParamVOS.push({
check: !i.itemCheck,
skuId: i.itemId,
});
} else {
cartItemCheckParamVOS.push({
check: i.itemCheck,
skuId: i.itemId,
});
}
});
// 更新商品选中状态接口
const res = await getUpdateCheck(cartItemCheckParamVOS);
if (res.success) {
el.itemCheck = !el.itemCheck;
let checkCompany = item?.itemList.every((s) => s.itemCheck === true);
item.check = checkCompany;
selectAll(item);
} else {
el.itemCheck = el.itemCheck;
let checkCompany = item?.itemList.every((s) => s.itemCheck === true);
item.check = checkCompany;
selectAll(item);
}
};
// 选中公司名称判断全选按钮是否选中
const selectAll = async (itemDate) => {
let checkAll = shopCart.dataSource.every((item) => item.check === true);
allChecked.value = checkAll;
};
// 全选
const checkAll = async (e) => {
let checkAllData = [];
if (allChecked.value) {
shopCart?.dataSource?.map((item) => {
item?.itemList.forEach((p) => {
checkAllData.push({
check: true,
skuId: p.itemId,
});
});
});
} else {
shopCart.dataSource?.map((item) => {
item?.itemList.forEach((p) => {
checkAllData.push({
check: false,
skuId: p.itemId,
});
});
});
}
const res = await getUpdateCheck(checkAllData);
if (res.success) {
shopCart?.dataSource?.forEach((item) => {
item.check = e.target.checked;
item?.itemList.forEach((p) => {
p.itemCheck = e.target.checked;
});
});
} else {
shopCart?.dataSource?.forEach((item) => {
item.check = item.check;
item?.itemList.forEach((p) => {
p.itemCheck = p.itemCheck;
});
});
}
};
// 删除明细行
const handRemove = async (item, itemId) => {
let params = [itemId];
const res = await getDelete(params);
if (res.success) {
searchCartList();
}
};
// 删除全部
const removeAll = async () => {
let skuIds = [];
shopCart.dataSource?.forEach((item) => {
if (item?.itemList.length > 0) {
item?.itemList?.forEach((el) => {
if (el.itemCheck) {
skuIds.push(el.itemId);
}
});
}
});
const res = await getDelete(skuIds);
if (res.success) {
// 删除成功之后调取 获取 购物车的接口数据达到刷新页面的效果
searchCartList();
}
};
// 去结算
const router = useRouter();
const settleAccount = () => {
if (checkNum.value > 0) {
router.push({
path: "/settleAccount",
});
} else {
notification["warning"]({
message: "温馨提示",
description: "请选择要结算的数据",
duration: 2,
});
}
};
// 继续购物
const goShopHome = () => {
router.push({
path: "/home",
});
};
// 商品名称进入详情页面
const handleDetail = (id) => {
router.push({
path: "/itemGoodsDetail",
query: {
id: id,
},
});
};
const searchCartList = async () => {
loading.value = true;
let res = await getSearchList();
loading.value = false;
if (res.success) {
shopCart.dataSource = res.data?.cartItemList || [];
WatchCartNum();
} else {
shopCart.dataSource = [];
}
};
onMounted(() => {
searchCartList(); //获取购物车数据
});
return {
shopCart,
allChecked,
priceTotal,
defaultSvg,
checkNum,
loading,
changeProductCount,
selectShopItems,
checkAll,
handRemove,
removeAll,
checkItem,
goShopHome,
settleAccount,
handleDetail,
};
},
});
</script>
<template>
<a-spin :spinning="loading" size="large" wrapperClassName="el-spin">
<div class="shopCart">
<div v-if="shopCart?.dataSource.length > 0">
<a-row class="shopHead">
<a-col :span="1">
<a-checkbox v-model:checked="allChecked" @change="checkAll">
<!-- 全选 -->
</a-checkbox>
</a-col>
<a-col :span="1">序号 </a-col>
<a-col :span="11" class="colSpan">商品</a-col>
<a-col :span="2" class="colSpan">单价</a-col>
<a-col :span="4" class="colSpan">数量</a-col>
<a-col :span="2" class="colSpan">小计</a-col>
<a-col :span="2" class="colSpan">操作</a-col>
</a-row>
<a-row
v-for="item in shopCart.dataSource"
:key="item.id"
class="shopMessage"
>
<a-col :span="24" class="company">
<a-checkbox :checked="item.check" @click="selectShopItems(item)">
{
{ item.sellerName }}
</a-checkbox>
</a-col>
<a-col v-for="(el, i) in item.itemList" :key="el.itemId" :span="24">
<a-row>
<a-col :span="1" class="checkboxStyle">
<a-checkbox
:checked="el.itemCheck"
@click="checkItem(el, item)"
/>
</a-col>
<a-col :span="1" class="checkboxStyle">
{
{ i + 1 }}
</a-col>
<a-col :span="11" class="shopMsg">
<ElImage
class="imgStyle"
:value="el.image != '' ? el.image : defaultSvg"
:preview="false"
style="height: 100%; width: 80px"
/>
<div class="ShopDiv">
<p
:title="el.spuName"
@click="handleDetail(el.spuId)"
style="cursor: pointer"
>
{
{ el.spuName }}
</p>
<p>
<span class="pSpan" v-if="el.itemName" :title="el.itemName">
款式:{
{ el.itemName }}
</span>
<span
class="pSpan"
v-if="el.skuProps.length > 0"
style="margin-left: 3px"
>
<span v-for="(f, i) in el.skuProps" :key="i">
{
{ f.name }} : {
{ f.value }}
</span>
</span>
<!-- <span class="pSpan" v-if="el.itemSpec">
颜色:{
{ el.itemSpec }}
</span> -->
<span class="pSpan" v-if="el.itemSpec == null">
规格:默认
</span>
</p>
</div>
</a-col>
<a-col :span="2" class="itemCol">
<span>{
{ el.price }}</span>
</a-col>
<a-col :span="4" class="itemCol">
<div
style="text-align: center; height: 28px; line-height: 28px"
>
<a-button
@click="changeProductCount(el, 'sub')"
class="itemCol-button1"
>
<span style="margin-left: -5px">—</span>
</a-button>
<a-input-number
v-model:value="el.num"
:controls="false"
@change="changeProductCount(el, 'change')"
style="margin-top: 2px"
/>
<a-button
@click="changeProductCount(el, 'add')"
class="itemCol-button1"
>
<span class="itemCol-button1-span2"> + </span>
</a-button>
</div>
</a-col>
<a-col :span="2" class="itemCol" style="color: #f51d29">
¥<span>{
{ (el.price * el.num).toFixed(2) }}</span>
</a-col>
<a-col :span="2" class="itemCol">
<a-button type="text" @click="handRemove(el, el.itemId)">
删除
</a-button>
</a-col>
</a-row>
</a-col>
</a-row>
<a-row class="shopFooter">
<a-col :span="2">
<a-checkbox v-model:checked="allChecked" @change="checkAll">
全选
</a-checkbox>
</a-col>
<a-col :span="3" class="colSpan"> 已选择 {
{ checkNum }} 件 </a-col>
<a-col
:span="3"
class="colSpan"
@click="removeAll()"
style="cursor: pointer"
>删除选中</a-col
>
<a-col :span="2" />
<a-col :span="2" />
<a-col :span="2" />
<a-col :span="6" class="colSpan">
总价(不含邮费):{
{ priceTotal }}
</a-col>
<a-col :span="4" class="colSpan">
<a-button @click="goShopHome"> 继续购物 </a-button>
<a-button type="primary" danger @click="settleAccount">
去结算
</a-button>
</a-col>
</a-row>
</div>
<div v-if="shopCart?.dataSource.length == 0">
<div class="noGoods">
<div class="noGoods-img">
<img src="/src/assets/icons/empty-shopping.svg" alt="未找到结果" />
</div>
<div class="noGoods-txt">暂无数据</div>
<div class="noGoods-explain">
<span class="noGoods-explain-span">
您可以:
<br />
1、尽量描述清楚您需要搜索的商品,缩短或修改您的搜索词,重新搜索。
<br />
2、<a href="/home">去首页</a>
</span>
</div>
</div>
</div>
</div>
</a-spin>
</template>
<style lang="scss" scoped>
p{
margin: 0;
padding: 0;
}
.shopCart{
padding-top: 30px ;
height: calc(100% - 30px);
margin: auto;
min-width: 1200px;
width: 1200px;
.shopHead{
height: 40px;
background: #F8F8F8;
line-height: 40px;
padding: 0 20px;
.colSpan{
text-align: center;
}
}
.cloudt-layout-row{
row-gap: 0px;
margin: 10px 0;
}
.shopMessage{
padding: 0 20px;
}
.checkboxStyle{
display: flex;
align-items: center;
}
.company{
line-height: 60px;
}
.shopMsg{
display: flex;
width: 80px;
height: 80px;
}
.imgStyle{
width: 80px;
height: 80px;
object-fit: contain;
}
.ShopDiv{
width: calc(100% - 100px);
margin-left: 20px;
.pSpan{
font-size: 12px;
color: #999999;
line-height: 20px;
font-weight: 400;
// padding: 5px;
}
}
.itemCol{
display: flex;
justify-content: center;
align-items: center;
font-size: 12px;
line-height: 20px;
font-weight: 600;
.itemCol-button1{
background: #fafafa;
border: 1px solid #e5e5e5;
width: 10px;
.itemCol-button1-span2{
margin-left: -10px;
font-size: 21px;
margin-top: -16px;
width: 20px;
height: 20px;
line-height: 20px;
}
}
}
.shopFooter{
height: 40px;
background: #F8F8F8;
line-height: 40px;
padding: 0px 20px;
margin-top:10px;
.colSpan{
text-align: center;
}
}
}
// .cloudt-layout-input-number-input{
// text-align: center !important;
// }
.cloudt-layout-input-number-input{
width: 100%;
height: 30px;
padding: 0 11px;
text-align: center !important;
background-color: transparent;
border: 0;
border-radius: 2px;
outline: 0;
transition: all 0.3s linear;
appearance: textfield !important;
}
.cloudt-layout-input-number-input-wrap{
margin-top:-1px;
}
.noGoods {
min-width: 400px;
margin-top: 80px;
.noGoods-img {
width: 160px;
height: 160px;
margin: auto;
}
.noGoods-txt {
margin: 40px 0;
font-family: PingFangSC-Semibold;
font-size: 16px;
color: #333333;
line-height: 24px;
font-weight: 600;
text-align: center;
}
.noGoods-explain {
display: flex;
font-family: PingFangSC-Regular;
font-size: 14px;
color: #333333;
line-height: 22px;
font-weight: 400;
.noGoods-explain-span {
margin: auto;
text-align: left;
}
}
}
</style>
Vue3 implements the shopping cart function and changes the selected state after calling the selected state interface
Guess you like
Origin blog.csdn.net/lzfengquan/article/details/128785809
Recommended
Ranking