feat: ✨ 购物车
This commit is contained in:
parent
9308a1df85
commit
6935ad15d0
52
src/components/vk-data-input-number-box/vk-data-input-number-box.d.ts
vendored
Normal file
52
src/components/vk-data-input-number-box/vk-data-input-number-box.d.ts
vendored
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { Component } from '@uni-helper/uni-app-types'
|
||||||
|
|
||||||
|
/** 步进器 */
|
||||||
|
export type InputNumberBox = Component<InputNumberBoxProps>
|
||||||
|
|
||||||
|
/** 步进器实例 */
|
||||||
|
export type InputNumberBoxInstance = InstanceType<InputNumberBox>
|
||||||
|
|
||||||
|
/** 步进器属性 */
|
||||||
|
export type InputNumberBoxProps = {
|
||||||
|
/** 输入框初始值(默认1) */
|
||||||
|
modelValue: number
|
||||||
|
/** 用户可输入的最小值(默认0) */
|
||||||
|
min: number
|
||||||
|
/** 用户可输入的最大值(默认99999) */
|
||||||
|
max: number
|
||||||
|
/** 步长,每次加或减的值(默认1) */
|
||||||
|
step: number
|
||||||
|
/** 是否禁用操作,包括输入框,加减按钮 */
|
||||||
|
disabled: boolean
|
||||||
|
/** 输入框宽度,单位rpx(默认80) */
|
||||||
|
inputWidth: string | number
|
||||||
|
/** 输入框和按钮的高度,单位rpx(默认50) */
|
||||||
|
inputHeight: string | number
|
||||||
|
/** 输入框和按钮的背景颜色(默认#F2F3F5) */
|
||||||
|
bgColor: string
|
||||||
|
/** 步进器标识符 */
|
||||||
|
index: string
|
||||||
|
/** 输入框内容发生变化时触发 */
|
||||||
|
change: (event: InputNumberBoxEvent) => void
|
||||||
|
/** 输入框失去焦点时触发 */
|
||||||
|
blur: (event: InputNumberBoxEvent) => void
|
||||||
|
/** 点击增加按钮时触发 */
|
||||||
|
plus: (event: InputNumberBoxEvent) => void
|
||||||
|
/** 点击减少按钮时触发 */
|
||||||
|
minus: (event: InputNumberBoxEvent) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 步进器事件对象 */
|
||||||
|
export type InputNumberBoxEvent = {
|
||||||
|
/** 输入框当前值 */
|
||||||
|
value: number
|
||||||
|
/** 步进器标识符 */
|
||||||
|
index: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 全局组件类型声明 */
|
||||||
|
declare module 'vue' {
|
||||||
|
export interface GlobalComponents {
|
||||||
|
'vk-data-input-number-box': InputNumberBox
|
||||||
|
}
|
||||||
|
}
|
@ -35,6 +35,12 @@
|
|||||||
"navigationBarTitleText": "购物车"
|
"navigationBarTitleText": "购物车"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/cart/goodsCart",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "购物车"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/my/my",
|
"path": "pages/my/my",
|
||||||
"style": {
|
"style": {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import cartMain from './components/cartMain.vue'
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<view class="">test</view>
|
<cart-main />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts"></script>
|
|
||||||
|
|
||||||
<style lang="scss"></style>
|
|
||||||
|
489
src/pages/cart/components/cartMain.vue
Normal file
489
src/pages/cart/components/cartMain.vue
Normal file
@ -0,0 +1,489 @@
|
|||||||
|
<template>
|
||||||
|
<scroll-view scroll-y class="scroll-view">
|
||||||
|
<!-- 已登录: 显示购物车 -->
|
||||||
|
<template v-if="memberStore.profile">
|
||||||
|
<!-- 购物车列表 -->
|
||||||
|
<view class="cart-list" v-if="cartList.length > 0">
|
||||||
|
<!-- 优惠提示 -->
|
||||||
|
<view class="tips">
|
||||||
|
<text class="label">满减</text>
|
||||||
|
<text class="desc">满1件, 即可享受9折优惠</text>
|
||||||
|
</view>
|
||||||
|
<!-- 滑动操作分区 -->
|
||||||
|
<uni-swipe-action>
|
||||||
|
<!-- 滑动操作项 -->
|
||||||
|
<uni-swipe-action-item v-for="item in cartList" :key="item.skuId" class="cart-swipe">
|
||||||
|
<!-- 商品信息 -->
|
||||||
|
<view class="goods">
|
||||||
|
<!-- 选中状态 -->
|
||||||
|
<text
|
||||||
|
@tap="handlerSelect(item)"
|
||||||
|
class="checkbox"
|
||||||
|
:class="{ checked: item.selected }"
|
||||||
|
></text>
|
||||||
|
<navigator
|
||||||
|
:url="`/pages/goods/goods?id=${item.id}`"
|
||||||
|
hover-class="none"
|
||||||
|
class="navigator"
|
||||||
|
>
|
||||||
|
<image mode="aspectFill" class="picture" :src="item.picture"></image>
|
||||||
|
<view class="meta">
|
||||||
|
<view class="name ellipsis">{{ item.name }}</view>
|
||||||
|
<view class="attrsText ellipsis">{{ item.attrsText.replaceAll(',', ' ') }}</view>
|
||||||
|
<view class="price">{{ item.nowPrice }}</view>
|
||||||
|
</view>
|
||||||
|
</navigator>
|
||||||
|
<!-- 商品数量 -->
|
||||||
|
<view class="count">
|
||||||
|
<vk-data-input-number-box
|
||||||
|
:model-value="item.count"
|
||||||
|
:index="item.skuId"
|
||||||
|
:min="1"
|
||||||
|
:max="item.stock"
|
||||||
|
:step="1"
|
||||||
|
@change="onChangeCount(item.count, $event)"
|
||||||
|
></vk-data-input-number-box>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- 右侧删除按钮 -->
|
||||||
|
<template #right>
|
||||||
|
<view class="cart-swipe-right">
|
||||||
|
<button class="button delete-button" @tap="handlerDeleteCart(item.skuId)">
|
||||||
|
删除
|
||||||
|
</button>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</uni-swipe-action-item>
|
||||||
|
</uni-swipe-action>
|
||||||
|
</view>
|
||||||
|
<!-- 购物车空状态 -->
|
||||||
|
<view class="cart-blank" v-else>
|
||||||
|
<image src="/static/images/blank_cart.png" class="image" />
|
||||||
|
<text class="text">购物车还是空的,快来挑选好货吧</text>
|
||||||
|
<navigator open-type="switchTab" url="/pages/index/index" hover-class="none">
|
||||||
|
<button class="button">去首页看看</button>
|
||||||
|
</navigator>
|
||||||
|
</view>
|
||||||
|
<!-- 吸底工具栏 -->
|
||||||
|
<view class="toolbar">
|
||||||
|
<text class="all" :class="{ checked: allSelected }" @tap="handlerAllSelect">全选</text>
|
||||||
|
<text class="text">合计:</text>
|
||||||
|
<text class="amount">{{ totalPrice.toFixed(2) }}</text>
|
||||||
|
<view class="button-grounp">
|
||||||
|
<view
|
||||||
|
class="button payment-button"
|
||||||
|
:class="{ disabled: selectedList.length === 0 }"
|
||||||
|
@tap="handlerPay"
|
||||||
|
>
|
||||||
|
去结算({{ totalCount }})
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<!-- 未登录: 提示登录 -->
|
||||||
|
<view class="login-blank" v-else>
|
||||||
|
<text class="text">登录后可查看购物车中的商品</text>
|
||||||
|
<navigator url="/pages/login/login" hover-class="none">
|
||||||
|
<button class="button">去登录</button>
|
||||||
|
</navigator>
|
||||||
|
</view>
|
||||||
|
<!-- 猜你喜欢 -->
|
||||||
|
<XtxGuess ref="guessRef"></XtxGuess>
|
||||||
|
<!-- 底部占位空盒子 -->
|
||||||
|
<view class="toolbar-height"></view>
|
||||||
|
</scroll-view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useMemberStore } from '@/stores/modules/member'
|
||||||
|
import {
|
||||||
|
deleteMemberCartAPI,
|
||||||
|
getMemberCartAPI,
|
||||||
|
putMemberCartAPI,
|
||||||
|
putMemberCartSelectedAPI,
|
||||||
|
} from '@/services/cart'
|
||||||
|
import { onShow } from '@dcloudio/uni-app'
|
||||||
|
import type { CartItem } from '@/types/cart'
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
import type { InputNumberBoxEvent } from '@/components/vk-data-input-number-box/vk-data-input-number-box'
|
||||||
|
import { debounce } from '@/utils/debounce-throttle'
|
||||||
|
|
||||||
|
const memberStore = useMemberStore()
|
||||||
|
|
||||||
|
// 购物车列表
|
||||||
|
const cartList = ref<CartItem[]>([])
|
||||||
|
|
||||||
|
// 获取购物车列表
|
||||||
|
const getMemberCart = async () => {
|
||||||
|
const res = await getMemberCartAPI()
|
||||||
|
console.log(res)
|
||||||
|
if (res.code === '1') {
|
||||||
|
cartList.value = res.result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onShow(() => {
|
||||||
|
if (memberStore.profile) {
|
||||||
|
getMemberCart()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 删除购物车商品
|
||||||
|
const handlerDeleteCart = (skuId: string) => {
|
||||||
|
uni.showModal({
|
||||||
|
content: '确定要删除该商品吗?',
|
||||||
|
success: async (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
const res = await deleteMemberCartAPI({ ids: [skuId] })
|
||||||
|
if (res.code === '1') {
|
||||||
|
getMemberCart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改商品数量
|
||||||
|
// 添加防抖
|
||||||
|
const onChangeCount = debounce(async (count: number, event: InputNumberBoxEvent) => {
|
||||||
|
console.log(count, event)
|
||||||
|
if (count === event.value) return
|
||||||
|
const res = await putMemberCartAPI(event.index, { count: event.value })
|
||||||
|
if (res.code === '1') {
|
||||||
|
getMemberCart()
|
||||||
|
}
|
||||||
|
}, 200)
|
||||||
|
|
||||||
|
// 选中单个商品选中状态
|
||||||
|
const handlerSelect = async (item: CartItem) => {
|
||||||
|
console.log(item)
|
||||||
|
// 状态取反
|
||||||
|
item.selected = !item.selected
|
||||||
|
const res = await putMemberCartAPI(item.skuId, { selected: item.selected })
|
||||||
|
if (res.code === '1') {
|
||||||
|
getMemberCart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全选状态
|
||||||
|
const allSelected = computed(() => {
|
||||||
|
return cartList.value.length > 0 && cartList.value.every((item) => item.selected)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 全选
|
||||||
|
const handlerAllSelect = () => {
|
||||||
|
console.log('全选')
|
||||||
|
if (cartList.value.length === 0) return
|
||||||
|
// 取反
|
||||||
|
const isSelected = !allSelected.value
|
||||||
|
// 遍历购物车列表
|
||||||
|
cartList.value.forEach((item) => {
|
||||||
|
item.selected = isSelected
|
||||||
|
})
|
||||||
|
// 调用接口
|
||||||
|
putMemberCartSelectedAPI({ selected: isSelected })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选中商品列表
|
||||||
|
const selectedList = computed(() => {
|
||||||
|
return cartList.value.filter((item) => item.selected)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 选中商品总数量
|
||||||
|
const totalCount = computed(() => {
|
||||||
|
return selectedList.value.reduce((total, item) => {
|
||||||
|
return total + item.count
|
||||||
|
}, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 选中商品总价格
|
||||||
|
const totalPrice = computed(() => {
|
||||||
|
return selectedList.value.reduce((total, item) => {
|
||||||
|
return total + item.nowPrice * item.count
|
||||||
|
}, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 去结算
|
||||||
|
const handlerPay = () => {
|
||||||
|
console.log('去结算')
|
||||||
|
if (selectedList.value.length === 0) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '请选择商品',
|
||||||
|
icon: 'none',
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uni.showToast({
|
||||||
|
title: '跳转结算页面占用',
|
||||||
|
icon: 'none',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
// 根元素
|
||||||
|
:host {
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #f7f7f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 滚动容器
|
||||||
|
.scroll-view {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 购物车列表
|
||||||
|
.cart-list {
|
||||||
|
padding: 0 20rpx;
|
||||||
|
|
||||||
|
// 优惠提示
|
||||||
|
.tips {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
line-height: 1;
|
||||||
|
margin: 30rpx 10rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #666;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
color: #fff;
|
||||||
|
padding: 7rpx 15rpx 5rpx;
|
||||||
|
border-radius: 4rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
background-color: #27ba9b;
|
||||||
|
margin-right: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 购物车商品
|
||||||
|
.goods {
|
||||||
|
display: flex;
|
||||||
|
padding: 20rpx 20rpx 20rpx 80rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
background-color: #fff;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.navigator {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 80rpx;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '\e6cd';
|
||||||
|
font-family: 'erabbit' !important;
|
||||||
|
font-size: 40rpx;
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.checked::before {
|
||||||
|
content: '\e6cc';
|
||||||
|
color: #27ba9b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.picture {
|
||||||
|
width: 170rpx;
|
||||||
|
height: 170rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-left: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
height: 72rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attrsText {
|
||||||
|
line-height: 1.8;
|
||||||
|
padding: 0 15rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
align-self: flex-start;
|
||||||
|
border-radius: 4rpx;
|
||||||
|
color: #888;
|
||||||
|
background-color: #f7f7f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price {
|
||||||
|
line-height: 1;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #444;
|
||||||
|
margin-bottom: 2rpx;
|
||||||
|
color: #cf4444;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '¥';
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 商品数量
|
||||||
|
.count {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 20rpx;
|
||||||
|
right: 5rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cart-swipe {
|
||||||
|
display: block;
|
||||||
|
margin: 20rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cart-swipe-right {
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.button {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 50px;
|
||||||
|
padding: 6px;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 26rpx;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-button {
|
||||||
|
background-color: #cf4444;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 空状态
|
||||||
|
.cart-blank,
|
||||||
|
.login-blank {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 60vh;
|
||||||
|
.image {
|
||||||
|
width: 400rpx;
|
||||||
|
height: 281rpx;
|
||||||
|
}
|
||||||
|
.text {
|
||||||
|
color: #444;
|
||||||
|
font-size: 26rpx;
|
||||||
|
margin: 20rpx 0;
|
||||||
|
}
|
||||||
|
.button {
|
||||||
|
width: 240rpx !important;
|
||||||
|
height: 60rpx;
|
||||||
|
line-height: 60rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
border-radius: 60rpx;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #27ba9b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 吸底工具栏
|
||||||
|
.toolbar {
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: var(--window-bottom);
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
height: 100rpx;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
border-top: 1rpx solid #ededed;
|
||||||
|
border-bottom: 1rpx solid #ededed;
|
||||||
|
background-color: #fff;
|
||||||
|
box-sizing: content-box;
|
||||||
|
|
||||||
|
.all {
|
||||||
|
margin-left: 25rpx;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #444;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.all::before {
|
||||||
|
font-family: 'erabbit' !important;
|
||||||
|
content: '\e6cd';
|
||||||
|
font-size: 40rpx;
|
||||||
|
margin-right: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checked::before {
|
||||||
|
content: '\e6cc';
|
||||||
|
color: #27ba9b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
margin-right: 8rpx;
|
||||||
|
margin-left: 32rpx;
|
||||||
|
color: #444;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.amount {
|
||||||
|
font-size: 20px;
|
||||||
|
color: #cf4444;
|
||||||
|
|
||||||
|
.decimal {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '¥';
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-grounp {
|
||||||
|
margin-left: auto;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 72rpx;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
.button {
|
||||||
|
width: 240rpx;
|
||||||
|
margin: 0 10rpx;
|
||||||
|
border-radius: 72rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.payment-button {
|
||||||
|
background-color: #27ba9b;
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 底部占位空盒子
|
||||||
|
.toolbar-height {
|
||||||
|
height: 100rpx;
|
||||||
|
}
|
||||||
|
</style>
|
7
src/pages/cart/goodsCart.vue
Normal file
7
src/pages/cart/goodsCart.vue
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import cartMain from './components/cartMain.vue'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<cart-main />
|
||||||
|
</template>
|
@ -100,7 +100,7 @@
|
|||||||
<button class="icons-button" open-type="contact">
|
<button class="icons-button" open-type="contact">
|
||||||
<text class="icon-handset"></text>客服
|
<text class="icon-handset"></text>客服
|
||||||
</button>
|
</button>
|
||||||
<navigator class="icons-button" url="/pages/cart/cart" open-type="switchTab">
|
<navigator class="icons-button" url="/pages/cart/goodsCart" open-type="navigate">
|
||||||
<text class="icon-cart"></text>购物车
|
<text class="icon-cart"></text>购物车
|
||||||
</navigator>
|
</navigator>
|
||||||
</view>
|
</view>
|
||||||
@ -144,7 +144,7 @@ import type {
|
|||||||
SkuPopupInstance,
|
SkuPopupInstance,
|
||||||
SkuPopupLocaldata,
|
SkuPopupLocaldata,
|
||||||
} from '@/components/vk-data-goods-sku-popup/vk-data-goods-sku-popup'
|
} from '@/components/vk-data-goods-sku-popup/vk-data-goods-sku-popup'
|
||||||
import { postMemberCart } from '@/services/cart'
|
import { postMemberCartAPI } from '@/services/cart'
|
||||||
|
|
||||||
// 获取屏幕边界到安全区域距离
|
// 获取屏幕边界到安全区域距离
|
||||||
const { safeAreaInsets } = uni.getSystemInfoSync()
|
const { safeAreaInsets } = uni.getSystemInfoSync()
|
||||||
@ -256,7 +256,7 @@ const showSkuPopup = (mode: SkuMode) => {
|
|||||||
|
|
||||||
// 加入购物车
|
// 加入购物车
|
||||||
const handlerAddCart = async (e: SkuPopupEvent) => {
|
const handlerAddCart = async (e: SkuPopupEvent) => {
|
||||||
const res = await postMemberCart({
|
const res = await postMemberCartAPI({
|
||||||
skuId: e._id,
|
skuId: e._id,
|
||||||
count: e.buy_num,
|
count: e.buy_num,
|
||||||
})
|
})
|
||||||
|
@ -84,9 +84,7 @@ const loginSucess = (profile: LoginResult) => {
|
|||||||
icon: 'none',
|
icon: 'none',
|
||||||
})
|
})
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
uni.switchTab({
|
uni.navigateBack()
|
||||||
url: '/pages/my/my',
|
|
||||||
})
|
|
||||||
}, 500)
|
}, 500)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,9 +1,62 @@
|
|||||||
|
import type { CartItem } from '@/types/cart'
|
||||||
import { http } from '@/utils/http'
|
import { http } from '@/utils/http'
|
||||||
|
|
||||||
export const postMemberCart = (data: { skuId: string; count: number }) => {
|
/**
|
||||||
|
* 加入购物车
|
||||||
|
*/
|
||||||
|
export const postMemberCartAPI = (data: { skuId: string; count: number }) => {
|
||||||
return http({
|
return http({
|
||||||
url: '/member/cart',
|
url: '/member/cart',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data,
|
data,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取购物车列表
|
||||||
|
*/
|
||||||
|
export const getMemberCartAPI = () => {
|
||||||
|
return http<CartItem[]>({
|
||||||
|
url: '/member/cart',
|
||||||
|
method: 'GET',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除购物车商品
|
||||||
|
*/
|
||||||
|
export const deleteMemberCartAPI = (data: { ids: string[] }) => {
|
||||||
|
return http({
|
||||||
|
url: '/member/cart',
|
||||||
|
method: 'DELETE',
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改购物车商品数量
|
||||||
|
*/
|
||||||
|
type PutMemberCartAPIParams = {
|
||||||
|
/** 是否选中 */
|
||||||
|
selected?: boolean
|
||||||
|
/** 商品数量 */
|
||||||
|
count?: number
|
||||||
|
}
|
||||||
|
export const putMemberCartAPI = (skuId: string, data: PutMemberCartAPIParams) => {
|
||||||
|
return http({
|
||||||
|
url: `/member/cart/${skuId}`,
|
||||||
|
method: 'PUT',
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改购物车商品全选状态
|
||||||
|
*/
|
||||||
|
export const putMemberCartSelectedAPI = (data: { selected: boolean }) => {
|
||||||
|
return http({
|
||||||
|
url: '/member/cart/selected',
|
||||||
|
method: 'PUT',
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
23
src/utils/debounce-throttle.ts
Normal file
23
src/utils/debounce-throttle.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// 防抖函数
|
||||||
|
export const debounce = (fn: Function, delay: number) => {
|
||||||
|
let timer: number | null = null
|
||||||
|
return function (...args: any[]) {
|
||||||
|
if (timer) clearTimeout(timer)
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
fn(...args)
|
||||||
|
timer = null
|
||||||
|
}, delay)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 节流函数
|
||||||
|
export const throttle = (fn: Function, delay: number) => {
|
||||||
|
let timer: number | null = null
|
||||||
|
return function (...args: any[]) {
|
||||||
|
if (timer) return
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
fn(...args)
|
||||||
|
timer = null
|
||||||
|
}, delay)
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user