2025-10-24
购物车
This commit is contained in:
11
api/mall.js
11
api/mall.js
@@ -9,11 +9,16 @@ export const mallAPI = {
|
||||
getCategory: () => http.get(baseUrl + '/api/category'),
|
||||
getMallDetail: (id) => http.get(baseUrl + '/api/products/' + id),
|
||||
getRecommended: (id) => http.get(baseUrl + `/api/products/${id}/recommended`), // 推荐商品
|
||||
addCart: (data) => http.post(baseUrl +"/api/cart/add", data), // 添加购物车
|
||||
createOrder: (data) => http.post(baseUrl + `/api/orders/create-from-cart`,data), // 创建订单
|
||||
createOrder: (data) => http.post(baseUrl + `/api/orders/create-from-cart`, data), // 创建订单
|
||||
getOrder: (orderId) => http.get(baseUrl + `/api/orders/pending-payment/${orderId}`), // 获取订单
|
||||
payment: (data) => http.post(baseUrl + "/api/orders/confirm-payment", data), // 支付订单
|
||||
getCouponList: (uid) => http.get(baseUrl + `/api/coupon/user/${uid}`)
|
||||
getCouponList: (uid) => http.get(baseUrl + `/api/coupon/user/${uid}`), // 获取优惠券列表
|
||||
|
||||
// 购物车
|
||||
getCartList: () => http.get(baseUrl + "/api/cart"), // 获取购物车列表
|
||||
addCart: (data) => http.post(baseUrl + "/api/cart/add", data), // 添加购物车
|
||||
editCartQuantity: (item) => http.put(baseUrl + `/api/cart/${item.id}`, {quantity: item.quantity}), // 修改数量
|
||||
deleteCart: (id) => http.delete(baseUrl + `/api/cart/${id}`), // 删除
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
36
pages.json
36
pages.json
@@ -138,41 +138,37 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/home/pay",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "确认订单",
|
||||
"path": "pages/home/pay",
|
||||
"style": {
|
||||
"navigationBarTitleText": "确认订单",
|
||||
"backgroundColor": "#E4ECFF",
|
||||
"enablePullDownRefresh": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/my/order",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "我的订单"
|
||||
"path": "pages/my/order",
|
||||
"style": {
|
||||
"navigationBarTitleText": "我的订单"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/home/mallSearch",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "搜索商品",
|
||||
"path": "pages/home/mallSearch",
|
||||
"style": {
|
||||
"navigationBarTitleText": "搜索商品",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/my/getCoupons",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "领券中心"
|
||||
"path": "pages/my/getCoupons",
|
||||
"style": {
|
||||
"navigationBarTitleText": "领券中心"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/my/car",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "购物车"
|
||||
"path": "pages/my/car",
|
||||
"style": {
|
||||
"navigationBarTitleText": "购物车",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
@@ -351,7 +351,7 @@
|
||||
if (res.success) {
|
||||
msgRef.value.show({
|
||||
title: '已加入购物车',
|
||||
type: 'error'
|
||||
type: 'success'
|
||||
})
|
||||
} else {
|
||||
msgRef.value.show({
|
||||
|
||||
@@ -174,20 +174,6 @@
|
||||
uni.navigateBack();
|
||||
}
|
||||
|
||||
const instance = getCurrentInstance();
|
||||
const scrollHeight = ref(0)
|
||||
const loadHeight = () => {
|
||||
uni.getSystemInfo({
|
||||
success(res) {
|
||||
let screenHeight = res.screenHeight
|
||||
uni.createSelectorQuery().in(instance.proxy).select("#boxBottom").boundingClientRect((
|
||||
data) => {
|
||||
scrollHeight.value = screenHeight - data.height
|
||||
}).exec()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 收获地址
|
||||
const showSelectAddress = ref(false)
|
||||
const addressOptions = ref([])
|
||||
@@ -487,7 +473,6 @@
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
loadHeight()
|
||||
userId.value = uni.getStorageSync("user").id
|
||||
loadData()
|
||||
loadCoupon()
|
||||
|
||||
285
pages/my/car.vue
285
pages/my/car.vue
@@ -1,22 +1,283 @@
|
||||
<template>
|
||||
<view>
|
||||
|
||||
<view class="cart-container">
|
||||
<u-navbar id="uNavbarId" back-text="购物车" :back-text-style="navBarTitle"
|
||||
:background="{background: 'transparent' }" :border-bottom="false" back-icon-color="#000" title-color="#000">
|
||||
<template v-slot:right>
|
||||
<view class="right-menu">
|
||||
<view @click="handleManage">
|
||||
{{isManage?'退出管理':'管理'}}
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</u-navbar>
|
||||
|
||||
<scroll-view scroll-y="true" :style="'height:'+scrollHeight+'px'">
|
||||
<view class="cart-list">
|
||||
<view class="cart-item" v-for="item in cartList">
|
||||
<view class="left">
|
||||
<u-checkbox v-model="item.isCheck" shape="circle" active-color="#305def"></u-checkbox>
|
||||
<image style="height: 160rpx;width: 160rpx;" :src="getImageUrl(item.product.image_url)" mode="">
|
||||
</image>
|
||||
</view>
|
||||
<u-row class="right">
|
||||
<u-col :span="10">
|
||||
<view>{{item.product.name}}</view>
|
||||
<view>
|
||||
<image class="icon" src="/static/icon/rongdou.png" mode=""></image>
|
||||
{{item.product.rongdou_price}}
|
||||
</view>
|
||||
<view>
|
||||
<image class="icon" src="/static/icon/jifen.png" mode=""></image>
|
||||
{{item.product.points_price}}
|
||||
</view>
|
||||
<view>
|
||||
<u-number-box bg-color="#E3ECFF" v-model="item.quantity"
|
||||
@change="handleChangeQuantity(item)" :min="1"
|
||||
:max="item.product.stock"></u-number-box>
|
||||
</view>
|
||||
</u-col>
|
||||
<u-col :span="2" text-align="right">
|
||||
<template v-if="!isManage">
|
||||
x{{item.quantity}}
|
||||
</template>
|
||||
<template v-else>
|
||||
<image @click="handleDeleteCart([item])" style="width: 40rpx;height: 40rpx;"
|
||||
src="/static/icon/delete.png" mode="">
|
||||
</image>
|
||||
</template>
|
||||
</u-col>
|
||||
</u-row>
|
||||
</view>
|
||||
<view class="box-div">
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="box-bottom" id="boxBottom">
|
||||
<u-checkbox v-model="isAllCheck" shape="circle" @change="handleSelectAll">全选</u-checkbox>
|
||||
<view class="right">
|
||||
合计:豆{{rongdou}} 分{{point}}
|
||||
<u-button class="u-m-l-10" @click="handleSubmit">{{isManage?'删除':'结算'}}</u-button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 确认是否删除 -->
|
||||
<u-modal v-model="showDel" content="是否删除选中的商品" :show-cancel-button="true" @confirm="handleDel"></u-modal>
|
||||
<!-- 提示 -->
|
||||
<u-toast ref="msgRef" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
computed,
|
||||
onMounted,
|
||||
ref,
|
||||
getCurrentInstance
|
||||
} from 'vue';
|
||||
import {
|
||||
mallAPI
|
||||
} from '../../api/mall.js';
|
||||
import {
|
||||
getImageUrl
|
||||
} from '../../util/common.js'
|
||||
|
||||
const msgRef = ref()
|
||||
|
||||
const instance = getCurrentInstance();
|
||||
const scrollHeight = ref(0)
|
||||
const loadHeight = () => {
|
||||
uni.getSystemInfo({
|
||||
success(res) {
|
||||
let screenHeight = res.screenHeight
|
||||
uni.createSelectorQuery().in(instance.proxy).select("#uNavbarId").boundingClientRect((
|
||||
data) => {
|
||||
scrollHeight.value = screenHeight - data.height
|
||||
}).exec()
|
||||
uni.createSelectorQuery().in(instance.proxy).select("#boxBottom").boundingClientRect((
|
||||
data) => {
|
||||
scrollHeight.value = scrollHeight - data.height
|
||||
}).exec()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
const navBarTitle = {
|
||||
fontWeight: '510',
|
||||
fontStyle: 'Medium',
|
||||
fontSize: '40rpx',
|
||||
lineHeight: '52px'
|
||||
}
|
||||
|
||||
const isManage = ref(false)
|
||||
|
||||
const handleManage = () => {
|
||||
isManage.value = !isManage.value
|
||||
}
|
||||
|
||||
const isAllCheck = computed(() => {
|
||||
if (cartList.value.length == 0) return false
|
||||
let tmpData = cartList.value.filter(item => item.isCheck)
|
||||
calculate()
|
||||
if (tmpData.length == cartList.value.length) return true
|
||||
else return false
|
||||
})
|
||||
|
||||
const handleSelectAll = () => {
|
||||
if (isAllCheck.value) cartList.value.forEach(item => item.isCheck = false)
|
||||
else cartList.value.forEach(item => item.isCheck = true)
|
||||
calculate()
|
||||
}
|
||||
|
||||
const handleChangeQuantity = (item) => {
|
||||
mallAPI.editCartQuantity(item)
|
||||
}
|
||||
|
||||
const showDel = ref(false)
|
||||
const delItems = ref([])
|
||||
const handleDeleteCart = (items) => {
|
||||
delItems.value = items
|
||||
showDel.value = true
|
||||
}
|
||||
|
||||
const handleDel = async () => {
|
||||
for (var i = 0; i < delItems.value.length; i++) {
|
||||
await mallAPI.deleteCart(delItems.value[i].id)
|
||||
}
|
||||
loadData()
|
||||
msgRef.value.show({
|
||||
title: '删除成功',
|
||||
type: 'success'
|
||||
})
|
||||
}
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (isManage.value) {
|
||||
// 删除
|
||||
delItems.value = cartList.value.filter(item => item.isCheck)
|
||||
showDel.value = true
|
||||
} else {
|
||||
// 支付
|
||||
const ids = cartList.value.map(item => item.id)
|
||||
mallAPI.createOrder({
|
||||
cart_item_ids: ids
|
||||
}).then(response => {
|
||||
if (response.success) {
|
||||
// 进入支付页面
|
||||
uni.navigateTo({
|
||||
url: '/pages/home/pay?preOrderId=' + response.data
|
||||
.preOrderId
|
||||
})
|
||||
} else {
|
||||
msgRef.value.show({
|
||||
title: '操作失败',
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const rongdou = ref(0)
|
||||
const point = ref(0)
|
||||
|
||||
const calculate = () => {
|
||||
rongdou.value = 0
|
||||
point.value = 0
|
||||
cartList.value.forEach(item => {
|
||||
if (item.isCheck) {
|
||||
rongdou.value += item.quantity * item.product.rongdou_price
|
||||
point.value += item.quantity * item.product.points_price
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const cartList = ref([])
|
||||
|
||||
const loadData = () => {
|
||||
mallAPI.getCartList().then(res => {
|
||||
cartList.value = res.data.items
|
||||
cartList.value.forEach(item => item.isCheck = false)
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadHeight()
|
||||
loadData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
<style lang="scss" scoped>
|
||||
.cart-container {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background: linear-gradient(180deg, #E3E8FF 0%, #FFFFFF 100%);
|
||||
background-blend-mode: lighten;
|
||||
|
||||
</style>
|
||||
.right-menu {
|
||||
display: flex;
|
||||
margin-right: 24rpx;
|
||||
font-family: Work Sans;
|
||||
font-weight: 500;
|
||||
font-style: Medium;
|
||||
font-size: 32rpx;
|
||||
leading-trim: NONE;
|
||||
line-height: 100%;
|
||||
letter-spacing: -2%;
|
||||
|
||||
.del-text {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.add-text {
|
||||
color: #305DEF;
|
||||
}
|
||||
}
|
||||
|
||||
.cart-list {
|
||||
.cart-item {
|
||||
display: flex;
|
||||
background: #E3ECFF;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 10rpx;
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.right {
|
||||
flex: 1;
|
||||
margin-left: 20rpx;
|
||||
|
||||
.icon {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.box-div {
|
||||
padding: 60rpx 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.box-bottom {
|
||||
width: 100%;
|
||||
padding: 20rpx 40rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
background: #F5F8FF;
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
BIN
static/icon/delete.png
Normal file
BIN
static/icon/delete.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 673 B |
@@ -208,6 +208,10 @@ const handleError = (errorInfo) => {
|
||||
})
|
||||
// uToast.warning(data.message || '您的账户尚未激活,请完成支付后再使用')
|
||||
}
|
||||
} else if (!data.success) {
|
||||
uni.redirectTo({
|
||||
url: '/pages/login/login'
|
||||
})
|
||||
} else {
|
||||
// uToast.error(data.message || '权限不足')
|
||||
uni.showToast({
|
||||
|
||||
Reference in New Issue
Block a user