20260929
This commit is contained in:
@@ -0,0 +1,339 @@
|
||||
<template>
|
||||
<view class="cart-page">
|
||||
<view class="page-hero">
|
||||
<AppNavbar class="page-navbar" title="购物车"/>
|
||||
<view class="intro-card">
|
||||
<view class="card-title">
|
||||
<view class="title-bar"></view>
|
||||
<text>购物车</text>
|
||||
</view>
|
||||
<text class="intro-text">按商家分单结算,蓝色主色适配竖版,支持多件商品数量调整与勾选。</text>
|
||||
<view class="hero-tags">
|
||||
<view class="chip">分商家结算</view>
|
||||
<view class="chip">蓝白风格</view>
|
||||
<view class="chip">竖版适配</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="card vendor-card" v-for="(vendor, vIdx) in cartVendors" :key="vendor.name">
|
||||
<view class="vendor-head">
|
||||
<label class="check">
|
||||
<checkbox :checked="vendor.selected" color="#2563eb" @tap.stop="toggleVendor(vIdx)" />
|
||||
<text class="vendor-name">{{ vendor.name }}</text>
|
||||
</label>
|
||||
<view class="freight">运费:¥{{ vendor.freight }}</view>
|
||||
</view>
|
||||
|
||||
<view class="item" v-for="(item, idx) in vendor.items" :key="item.id">
|
||||
<label class="check">
|
||||
<checkbox :checked="item.selected" color="#2563eb" @tap.stop="toggleItem(vIdx, idx)" />
|
||||
</label>
|
||||
<view class="item-info">
|
||||
<view class="item-name">{{ item.name }}</view>
|
||||
<view class="item-meta">规格 {{ item.specs }}</view>
|
||||
<view class="price-row">
|
||||
<view class="price">¥{{ item.price }}</view>
|
||||
<view class="origin">¥{{ item.origin }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="qty">
|
||||
<view class="btn" @tap="changeQty(vIdx, idx, -1)">-</view>
|
||||
<view class="num">{{ item.qty }}</view>
|
||||
<view class="btn" @tap="changeQty(vIdx, idx, 1)">+</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="summary card">
|
||||
<view class="summary-left">
|
||||
<view class="section-title">结算信息</view>
|
||||
<view class="sum-line">已选 {{ selectedCount }} 件,商品金额 ¥{{ goodsTotal }}</view>
|
||||
<view class="sum-line">预估运费 ¥{{ freightTotal }},合计 ¥{{ totalPrice }}</view>
|
||||
</view>
|
||||
<view class="primary-btn go-checkout" @tap="goCheckout">去结算</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AppNavbar from "@/components/AppNavbar.vue";
|
||||
|
||||
export default {
|
||||
components: {AppNavbar},
|
||||
data() {
|
||||
return {
|
||||
cartVendors: [{
|
||||
name: '华润三九',
|
||||
freight: 8,
|
||||
selected: true,
|
||||
items: [{
|
||||
id: 1,
|
||||
name: '三九感冒灵颗粒',
|
||||
specs: '10袋/盒',
|
||||
price: 29.9,
|
||||
origin: 39.9,
|
||||
qty: 1,
|
||||
selected: true
|
||||
}, {
|
||||
id: 2,
|
||||
name: '感冒软胶囊',
|
||||
specs: '24粒/盒',
|
||||
price: 32,
|
||||
origin: 45,
|
||||
qty: 2,
|
||||
selected: true
|
||||
}]
|
||||
}, {
|
||||
name: '华润江中',
|
||||
freight: 6,
|
||||
selected: true,
|
||||
items: [{
|
||||
id: 3,
|
||||
name: '健胃消食片',
|
||||
specs: '48片/盒',
|
||||
price: 36.8,
|
||||
origin: 46,
|
||||
qty: 2,
|
||||
selected: true
|
||||
}]
|
||||
}]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
selectedCount() {
|
||||
return this.cartVendors.reduce((sum, v) => {
|
||||
v.items.forEach(i => {
|
||||
if (i.selected) sum += i.qty
|
||||
})
|
||||
return sum
|
||||
}, 0)
|
||||
},
|
||||
goodsTotal() {
|
||||
return this.cartVendors.reduce((sum, v) => {
|
||||
v.items.forEach(i => {
|
||||
if (i.selected) sum += i.qty * i.price
|
||||
})
|
||||
return sum
|
||||
}, 0).toFixed(2)
|
||||
},
|
||||
freightTotal() {
|
||||
return this.cartVendors.reduce((sum, v) => {
|
||||
const hasSelected = v.items.some(i => i.selected)
|
||||
return sum + (hasSelected ? v.freight : 0)
|
||||
}, 0).toFixed(2)
|
||||
},
|
||||
totalPrice() {
|
||||
return (parseFloat(this.goodsTotal) + parseFloat(this.freightTotal)).toFixed(2)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changeQty(vIdx, idx, delta) {
|
||||
const item = this.cartVendors[vIdx].items[idx]
|
||||
const next = item.qty + delta
|
||||
if (next < 1) return
|
||||
this.cartVendors[vIdx].items[idx].qty = next
|
||||
this.cartVendors = [...this.cartVendors]
|
||||
},
|
||||
toggleItem(vIdx, idx) {
|
||||
const item = this.cartVendors[vIdx].items[idx]
|
||||
item.selected = !item.selected
|
||||
this.syncVendorSelect(vIdx)
|
||||
this.cartVendors = [...this.cartVendors]
|
||||
},
|
||||
toggleVendor(vIdx) {
|
||||
const vendor = this.cartVendors[vIdx]
|
||||
const next = !vendor.selected
|
||||
vendor.selected = next
|
||||
vendor.items.forEach(i => {
|
||||
i.selected = next
|
||||
})
|
||||
this.cartVendors = [...this.cartVendors]
|
||||
},
|
||||
syncVendorSelect(vIdx) {
|
||||
const vendor = this.cartVendors[vIdx]
|
||||
vendor.selected = vendor.items.every(i => i.selected)
|
||||
},
|
||||
goCheckout() {
|
||||
uni.navigateTo({
|
||||
url: `/pages/order/checkout?total=${this.totalPrice}`
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.cart-page {
|
||||
min-height: 100vh;
|
||||
padding: 0 20rpx 40rpx;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.page-hero {
|
||||
padding: 30rpx 6rpx 18rpx;
|
||||
background: url('https://yaodongxiao.oss-cn-guangzhou.aliyuncs.com/20260126/462bfa04cf0eff8698884c38b9d17519.png') no-repeat
|
||||
top center / 100% auto;
|
||||
}
|
||||
|
||||
.page-navbar {
|
||||
padding: 0 6rpx;
|
||||
}
|
||||
|
||||
.intro-card {
|
||||
margin-top: 18rpx;
|
||||
padding: 20rpx 18rpx;
|
||||
border-radius: 20rpx;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
box-shadow: 0 10rpx 20rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.card-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.title-bar {
|
||||
width: 6rpx;
|
||||
height: 30rpx;
|
||||
border-radius: 999rpx;
|
||||
background: #2fc6a7;
|
||||
}
|
||||
|
||||
.intro-text {
|
||||
margin-top: 12rpx;
|
||||
font-size: 26rpx;
|
||||
color: #6b7280;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.hero-tags {
|
||||
display: flex;
|
||||
gap: 12rpx;
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
|
||||
.vendor-card {
|
||||
margin-top: 18rpx;
|
||||
}
|
||||
|
||||
.vendor-head {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.check {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.vendor-name {
|
||||
font-weight: 700;
|
||||
color: var(--text-main);
|
||||
}
|
||||
|
||||
.freight {
|
||||
color: var(--text-sub);
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
gap: 12rpx;
|
||||
align-items: center;
|
||||
padding: 12rpx 0;
|
||||
border-bottom: 1rpx solid #edf1f7;
|
||||
}
|
||||
|
||||
.item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.item-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.item-name {
|
||||
font-weight: 700;
|
||||
color: var(--text-main);
|
||||
}
|
||||
|
||||
.item-meta {
|
||||
color: var(--text-sub);
|
||||
font-size: 24rpx;
|
||||
margin: 4rpx 0;
|
||||
}
|
||||
|
||||
.price-row {
|
||||
display: flex;
|
||||
gap: 10rpx;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.price {
|
||||
color: #ff3b30;
|
||||
font-weight: 800;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.origin {
|
||||
text-decoration: line-through;
|
||||
color: #a1aabc;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.qty {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
background: #f4f7fb;
|
||||
border-radius: 12rpx;
|
||||
padding: 6rpx 10rpx;
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
border-radius: 12rpx;
|
||||
background: #e9f1ff;
|
||||
color: var(--brand-primary);
|
||||
text-align: center;
|
||||
line-height: 40rpx;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.num {
|
||||
min-width: 34rpx;
|
||||
text-align: center;
|
||||
color: var(--text-main);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.summary {
|
||||
margin-top: 18rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.summary-left {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.sum-line {
|
||||
color: var(--text-sub);
|
||||
margin-top: 6rpx;
|
||||
}
|
||||
|
||||
.go-checkout {
|
||||
padding: 14rpx 24rpx;
|
||||
margin-left: 12rpx;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user