shop-web/src/pages/product/components/checkout.vue

252 lines
5.5 KiB
Vue
Raw Normal View History

2025-03-08 08:09:31 +08:00
<script setup lang="ts">
import { useCartStore } from "@/pinia/stores/cart"
import { storeToRefs } from "pinia"
import { showConfirmDialog } from "vant"
import { ref } from "vue"
const cartStore = useCartStore()
const { cartItems, totalPrice } = storeToRefs(cartStore)
// 支付方式选项
const paymentMethods = [
{ value: 1, label: "微信支付", icon: "wechat" },
{ value: 2, label: "支付宝", icon: "alipay" },
{ value: 3, label: "银行卡支付", icon: "credit-pay" }
]
const selectedPayment = ref<number>()
const contact = ref("")
const remark = ref("")
const submitting = ref(false)
// 提交订单
async function handleSubmit() {
if (!cartItems.value.length) {
return showConfirmDialog({
title: "提示",
message: "请先选择商品后再结算"
})
}
if (!selectedPayment.value) {
return showConfirmDialog({
title: "提示",
message: "请选择支付方式"
})
}
submitting.value = true
try {
// TODO: 调用实际的下单API
console.log("提交订单", {
items: cartItems.value,
total: totalPrice.value,
paymentMethod: selectedPayment.value,
contact: contact.value,
remark: remark.value
})
await showConfirmDialog({
title: "提交成功",
message: "订单已创建,正在跳转支付..."
})
// 清空购物车
cartStore.clearCart()
} finally {
submitting.value = false
}
}
</script>
<template>
<div class="checkout-container">
<!-- 新增固定导航栏 -->
<van-nav-bar
title="结算页面"
left-text="返回"
left-arrow
fixed
@click-left="() => $router.go(-1)"
/>
<!-- 原有内容容器 -->
<div class="content-wrapper">
<!-- 原有商品列表等代码保持不动 -->
<van-cell-group class="product-list">
<van-cell
v-for="item in cartItems"
:key="item.product.id"
class="product-item"
>
<template #icon>
<van-image
:src="item.product.image"
width="60"
height="60"
class="product-image"
/>
</template>
<div class="product-info">
<div class="product-name van-ellipsis">
{{ item.product.name }}
</div>
<div class="price-row">
<span class="product-price">
¥{{ item.product.price.toFixed(2) }}
</span>
<span class="quantity">
×{{ item.quantity }}
</span>
</div>
</div>
</van-cell>
</van-cell-group>
<!-- 联系方式与备注 -->
<van-cell-group class="contact-form">
<van-field
v-model="contact"
label="联系方式"
placeholder="请输入手机号"
:rules="[
{ required: true, message: '请填写联系方式' },
{ pattern: /^1[3-9]\d{9}$/, message: '手机号格式不正确' },
]"
/>
<van-field
v-model="remark"
label="备注"
type="textarea"
placeholder="选填,可备注特殊需求"
rows="2"
autosize
/>
</van-cell-group>
<!-- 支付方式选择 -->
<van-cell-group title="支付方式" class="payment-methods">
<van-radio-group v-model="selectedPayment">
<van-cell
v-for="method in paymentMethods"
:key="method.value"
clickable
@click="selectedPayment = method.value"
>
<template #icon>
<van-icon :name="method.icon" class="method-icon" />
</template>
<template #title>
<span class="method-label">{{ method.label }}</span>
</template>
<template #right-icon>
<van-radio :name="method.value" />
</template>
</van-cell>
</van-radio-group>
</van-cell-group>
<!-- 提交订单栏 -->
<div class="submit-bar">
<div class="total-price">
合计¥{{ totalPrice.toFixed(2) }}
</div>
<van-button
type="primary"
size="large"
:loading="submitting"
loading-text="提交中..."
@click="handleSubmit"
>
提交订单
</van-button>
</div>
</div>
</div>
</template>
<style scoped>
.van-nav-bar {
position: fixed;
top: 0;
width: 100%;
z-index: 999;
background: #fff;
border-bottom: 1px solid #ebedf0;
}
.content-wrapper {
padding-top: 46px; /* 导航栏高度 */
}
.checkout-container {
padding: 12px 16px 80px;
}
.product-list {
margin-bottom: 20px;
}
.product-item {
align-items: flex-start;
}
.product-image {
margin-right: 12px;
border-radius: 4px;
}
.product-info {
display: flex;
flex-direction: column;
justify-content: space-between;
height: 60px;
}
.price-row {
display: flex;
justify-content: space-between;
align-items: center;
}
.product-price {
color: #e95d5d;
font-weight: bold;
font-size: 14px;
}
.quantity {
color: #666;
font-size: 13px;
}
.method-icon {
font-size: 24px;
margin-right: 10px;
}
.method-label {
font-size: 15px;
}
.submit-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: #fff;
padding: 10px 16px;
display: flex;
align-items: center;
justify-content: space-between;
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.05);
}
.total-price {
font-size: 16px;
color: #e95d5d;
font-weight: bold;
}
</style>