474 lines
12 KiB
Vue
474 lines
12 KiB
Vue
<template>
|
||
<view class="container safe-area-inset-bottom">
|
||
<MessageNotification />
|
||
<!-- 头部区域:显示数量和清空按钮 -->
|
||
<view class="head">
|
||
<view class="num">
|
||
购物车(共{{ totalCount }}件商品)
|
||
</view>
|
||
<view class="clear" @click='clearCart'>
|
||
<text class="iconfont icon-qingchu"></text>
|
||
清空购物车
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 商品列表卡片 -->
|
||
<view class="card">
|
||
<!-- 门店名称 -->
|
||
<view class="store">
|
||
<text class="iconfont icon-mendian"></text>
|
||
{{ cartLists.store_name }}
|
||
</view>
|
||
|
||
<!-- 购物车列表循环 -->
|
||
<u-checkbox-group>
|
||
<view class="list" v-for="item in cartLists.data" :key="item.id">
|
||
|
||
<!-- 复选框 -->
|
||
<u-checkbox shape="circle" @change="checkboxChange(item)" v-model="item.checked">
|
||
</u-checkbox>
|
||
|
||
<!-- 商品图片:点击跳转详情 (使用 .stop 阻止冒泡,避免触发选中) -->
|
||
<view class="img" @click.stop="goProductDetail(item)">
|
||
<image :src="item.drug.image" mode="aspectFill"></image>
|
||
</view>
|
||
|
||
<!-- 商品信息区域:点击空白处切换选中状态 -->
|
||
<view class="it" @click="checkboxChange(item)">
|
||
<!-- 商品名称:点击跳转详情 (使用 .stop 阻止冒泡) -->
|
||
<view class="it_name" @click.stop="goProductDetail(item)">{{ item.drug.drug_name }}</view>
|
||
|
||
<!-- 规格/用法信息 -->
|
||
<view class="it_info">{{ item.drug.usage }}</view>
|
||
|
||
<!-- 价格与数量控制器 -->
|
||
<view class="it_price">
|
||
<!-- 显示价格 -->
|
||
<text>¥{{ item.drug.drug_store_relations ? item.drug.drug_store_relations.price : '0.00' }}</text>
|
||
|
||
<!-- 步进器:点击阻止冒泡,防止触发选中 -->
|
||
<view class="it_num" @click.stop>
|
||
<uni-number-box :min="1" @change="changeNum($event,item)" :value="item.qty">
|
||
</uni-number-box>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</u-checkbox-group>
|
||
</view>
|
||
|
||
<!-- 底部结算栏 -->
|
||
<view class="footer">
|
||
<view class="allselect-left" @click="checkedAll">
|
||
<u-checkbox-group>
|
||
<u-checkbox v-model="checked" shape="circle">全选</u-checkbox>
|
||
</u-checkbox-group>
|
||
</view>
|
||
|
||
<view class="total">
|
||
合计:
|
||
<text class="price">¥{{ totalPrice }}</text>
|
||
</view>
|
||
|
||
<view class="to_btn" @click="toPay">去结算</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
// 引入API接口
|
||
import {
|
||
CartList,
|
||
addCart,
|
||
clearAll
|
||
} from '../../request/api/api'
|
||
import {getCartListApi, saveCartApi} from "@/request/api/cart";
|
||
import {genOrderByCartApi} from "@/request/api/order";
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
checked: false, // 全选状态
|
||
allcheck: false,
|
||
value: 1,
|
||
numberValue: 0,
|
||
vModelValue: 3,
|
||
list: [{
|
||
checked: false,
|
||
disabled: false
|
||
}],
|
||
selectList: [], // 选中的数据
|
||
cartLists: { // 购物车列表数据源
|
||
data: []
|
||
},
|
||
drug_ids: [], // 药品id集合
|
||
cart_ids: [], // 购物车id集合
|
||
qty: '',
|
||
change_qty: '',
|
||
true_qty: ''
|
||
}
|
||
},
|
||
onShow() {
|
||
this.getCartList()
|
||
},
|
||
|
||
computed: {
|
||
// 计算选中商品的总价格
|
||
totalPrice: function() {
|
||
// 空值检查,防止报错
|
||
if (!this.cartLists || !this.cartLists.data || this.cartLists.data.length === 0) {
|
||
return '0.00';
|
||
}
|
||
|
||
let totalPrice = 0;
|
||
// 过滤出已选中的商品
|
||
const checkedItems = this.cartLists.data.filter(item => item.checked);
|
||
|
||
checkedItems.forEach(item => {
|
||
let price = 0;
|
||
if (item.drug && item.drug.drug_store_relations && item.drug.drug_store_relations.price) {
|
||
price = item.drug.drug_store_relations.price;
|
||
}
|
||
|
||
const qty = item.qty || 0;
|
||
totalPrice += price * qty;
|
||
});
|
||
|
||
return totalPrice.toFixed(2);
|
||
},
|
||
|
||
// 计算购物车总件数
|
||
totalCount: function () {
|
||
if (!this.cartLists || !this.cartLists.data) return 0;
|
||
var totalCount = 0;
|
||
for (var i = 0; i < this.cartLists.data.length; i++) {
|
||
totalCount += this.cartLists.data[i].qty;
|
||
}
|
||
return totalCount;
|
||
},
|
||
},
|
||
|
||
methods: {
|
||
// 跳转商品详情页
|
||
goProductDetail(item) {
|
||
if (!item || !item.drug) return;
|
||
|
||
// 获取显示价格,逻辑与模板保持一致
|
||
let price = '0';
|
||
if (item.drug.drug_store_relations && item.drug.drug_store_relations.price) {
|
||
price = item.drug.drug_store_relations.price;
|
||
}
|
||
|
||
// 构建参数并跳转
|
||
uni.navigateTo({
|
||
url: `/subPackages/product/symptoms?id=${item.drug.id}&drug_name=${item.drug.drug_name}&is_otc=${item.drug.is_otc}&image=${item.drug.image}&price=${price}`
|
||
});
|
||
},
|
||
|
||
// 清空购物车
|
||
clearCart() {
|
||
this.clearAll()
|
||
},
|
||
|
||
// 步进器数量变化
|
||
changeNum(e, current) {
|
||
console.log(e, current);
|
||
this.cartLists.data.forEach(item => {
|
||
if (item.id == current.id) {
|
||
item.qty = e;
|
||
this.true_qty = e
|
||
this.drug_id = current.drug_id
|
||
this.addToCart()
|
||
}
|
||
})
|
||
},
|
||
|
||
// 单个商品复选框状态改变
|
||
checkboxChange(item) {
|
||
console.log(item);
|
||
item.checked = !item.checked
|
||
// 如果存在未选中的项,则取消全选状态
|
||
if (this.cartLists.data.filter(e => !e.checked).length) {
|
||
this.checked = false
|
||
} else {
|
||
this.checked = true
|
||
}
|
||
},
|
||
|
||
// 全选/反选
|
||
checkedAll() {
|
||
// 如果当前已经是全部选中状态,则全部取消
|
||
if (this.cartLists.data.filter(item => item.checked).length === this.cartLists.data.length) {
|
||
this.cartLists = {
|
||
...this.cartLists,
|
||
data: this.cartLists.data.map(item => {
|
||
return {
|
||
...item,
|
||
checked: false
|
||
}
|
||
})
|
||
}
|
||
} else {
|
||
// 否则全部选中
|
||
this.cartLists = {
|
||
...this.cartLists,
|
||
data: this.cartLists.data.map(item => {
|
||
return {
|
||
...item,
|
||
checked: true
|
||
}
|
||
})
|
||
}
|
||
}
|
||
},
|
||
|
||
// 去结算
|
||
toPay() {
|
||
const list = this.cartLists.data.filter(item => item.checked).map(item => {
|
||
return {
|
||
drug_id: item.drug_id,
|
||
id: item.id,
|
||
numbers: item.qty
|
||
}
|
||
})
|
||
|
||
if(list.length === 0) {
|
||
uni.showToast({
|
||
title: '请先选择商品',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
let cart_ids = list.map(item => item.id);
|
||
genOrderByCartApi({
|
||
store_id: uni.getStorageSync('store_id') || '11001',
|
||
cart_ids: cart_ids
|
||
}).then((resOrder) => {
|
||
if (resOrder.data.code === 0) {
|
||
uni.navigateTo({
|
||
url: `/subPackages/my/my-drug/drug-info?id=${resOrder.data.result.id}&order_type=${resOrder.data.result.order_type}`
|
||
})
|
||
}
|
||
})
|
||
},
|
||
|
||
// 调用API清空购物车
|
||
clearAll() {
|
||
clearAll({
|
||
method: "post",
|
||
data: {
|
||
store_id: uni.getStorageSync('store_id') || '11001',
|
||
}
|
||
}).then((res) => {
|
||
if (res.data.code == 0) {
|
||
uni.showToast({
|
||
title: '清空成功',
|
||
icon: 'success',
|
||
})
|
||
this.getCartList()
|
||
}
|
||
})
|
||
},
|
||
|
||
// 更新购物车数量到服务器
|
||
addToCart() {
|
||
saveCartApi({
|
||
store_id: uni.getStorageSync('store_id') || '11001',
|
||
drug_id: this.drug_id,
|
||
quantity: this.true_qty
|
||
}).then((res) => {
|
||
if (res.data.code == 0) {
|
||
console.log('数量更新成功');
|
||
}
|
||
})
|
||
},
|
||
|
||
// 获取购物车列表数据
|
||
getCartList() {
|
||
getCartListApi({
|
||
store_id: uni.getStorageSync('store_id') || '11001',
|
||
}).then((res) => {
|
||
console.log(res, 'list');
|
||
if (res.data.code == 0) {
|
||
this.cartLists = {
|
||
...res.data.result,
|
||
data: res.data.result.data.map((item) => {
|
||
return {
|
||
...item,
|
||
checked: false // 默认不选中
|
||
};
|
||
})
|
||
};
|
||
}
|
||
})
|
||
},
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.container {
|
||
width: 750rpx;
|
||
max-height: 100%;
|
||
min-height: 100vh;
|
||
padding-bottom: env(safe-area-inset-bottom);
|
||
background: #F5F5F5;
|
||
|
||
.head {
|
||
width: 750rpx;
|
||
height: 88rpx;
|
||
margin: 0 auto;
|
||
padding: 0rpx 40rpx 0;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
|
||
.num {
|
||
font-size: 28rpx;
|
||
font-family: PingFang SC-Regular, PingFang SC;
|
||
font-weight: 400;
|
||
color: #232323;
|
||
}
|
||
|
||
.clear {
|
||
font-size: 24rpx;
|
||
font-family: PingFang SC-Regular, PingFang SC;
|
||
font-weight: 400;
|
||
color: #232323;
|
||
|
||
.iconfont {
|
||
font-size: 32rpx;
|
||
margin-left: 6rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.card {
|
||
width: 750rpx;
|
||
margin: 0 auto;
|
||
padding: 20rpx 12rpx 200rpx 20rpx;
|
||
background: #FFFFFF;
|
||
|
||
.store {
|
||
font-size: 28rpx;
|
||
font-family: PingFang SC-Regular, PingFang SC;
|
||
font-weight: 500;
|
||
color: #232323;
|
||
margin-left: 20rpx;
|
||
|
||
.iconfont {
|
||
font-size: 39rpx;
|
||
color: #666666;
|
||
vertical-align: middle;
|
||
margin-right: 10rpx;
|
||
}
|
||
}
|
||
|
||
.list {
|
||
display: flex;
|
||
justify-content: space-around;
|
||
width: 100%;
|
||
height: 254rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.checkbox {
|
||
width: 44rpx;
|
||
height: 44rpx;
|
||
background: #1777FF;
|
||
border-radius: 50%;
|
||
}
|
||
|
||
.img {
|
||
width: 200rpx;
|
||
height: 200rpx;
|
||
margin-right: 10rpx;
|
||
|
||
image {
|
||
width: 200rpx;
|
||
height: 200rpx;
|
||
border-radius: 8rpx;
|
||
}
|
||
}
|
||
|
||
.it {
|
||
flex: 1;
|
||
padding: 16rpx 10rpx;
|
||
font-family: PingFang SC-Bold, PingFang SC;
|
||
|
||
.it_name {
|
||
font-size: 28rpx;
|
||
font-weight: bold;
|
||
color: #232323;
|
||
}
|
||
|
||
.it_info {
|
||
font-size: 24rpx;
|
||
font-weight: 400;
|
||
color: #666666;
|
||
margin: 20rpx 0 48rpx 10rpx;
|
||
display: -webkit-box;
|
||
-webkit-line-clamp: 1;
|
||
-webkit-box-orient: vertical;
|
||
text-overflow: ellipsis;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.it_price {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
|
||
text {
|
||
font-size: 36rpx;
|
||
font-weight: bold;
|
||
color: #F93030;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.footer {
|
||
width: 750rpx;
|
||
height: 104rpx;
|
||
background: #fff;
|
||
position: fixed;
|
||
left: 0;
|
||
bottom: env(safe-area-inset-bottom);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 0 44rpx;
|
||
|
||
.total {
|
||
font-size: 28rpx;
|
||
font-family: PingFang SC-Regular, PingFang SC;
|
||
font-weight: 400;
|
||
color: #232323;
|
||
|
||
.price {
|
||
font-size: 36rpx;
|
||
font-family: PingFang SC-Bold, PingFang SC;
|
||
font-weight: bold;
|
||
color: #4175EE;
|
||
}
|
||
}
|
||
|
||
.to_btn {
|
||
width: 196rpx;
|
||
height: 64rpx;
|
||
border-radius: 64rpx;
|
||
text-align: center;
|
||
line-height: 62rpx;
|
||
background: #4175EE;
|
||
font-size: 28rpx;
|
||
font-family: PingFang SC-Regular, PingFang SC;
|
||
font-weight: 400;
|
||
color: #FFFFFF;
|
||
}
|
||
}
|
||
}
|
||
</style>
|