Files
jurong_circle_frontdesk/src/views/PayLoading.vue
2025-09-02 17:05:49 +08:00

591 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="pay-failed-page">
<!-- 导航栏 -->
<nav class="navbar">
<div class="nav-left">
<el-button
type="text"
@click="$router.push({ name: 'Shop' })"
class="back-btn"
>
<el-icon><ArrowLeft /></el-icon>
</el-button>
</div>
<div class="nav-center">
<h1 class="nav-title">订单详情</h1>
</div>
<div class="nav-right">
<!-- 占位元素保持标题居中 -->
</div>
</nav>
<div v-loading="loading" class="page-content">
<!-- 订单信息 -->
<div class="order-info-section">
<h3 class="section-title">订单信息</h3>
<div class="info-item">
<span class="label">订单号</span>
<span class="value">{{ orderData.orderNumber || '-' }}</span>
</div>
<div class="info-item">
<span class="label">创建时间</span>
<span class="value">{{ formatDateTime(orderData.createTime) || '-' }}</span>
</div>
</div>
<!-- 收货地址 -->
<div class="address-section">
<h3 class="section-title">收货地址</h3>
<div class="address-card">
<div class="address-header">
<span class="recipient">{{ orderData.address?.recipient || '-' }}</span>
<span class="phone">{{ orderData.address?.phone || '-' }}</span>
</div>
<div class="address-detail">
{{ formatAddress(orderData.address) || '暂无地址信息' }}
</div>
</div>
</div>
<!-- 商品清单 -->
<div class="products-section">
<h3 class="section-title">商品清单</h3>
<div class="product-list">
<div
v-for="item in orderData.cartItems"
:key="item.id"
class="product-item"
>
<img :src="item.image" :alt="item.name" class="product-image" />
<div class="product-info">
<div class="product-name">{{ item.name }}</div>
<div class="product-spec">{{ item.specification || '默认规格' }}</div>
<div class="product-price">
<div class="item-price-container">
<div class="item-main-price">
<img :src="getImageUrl('/imgs/profile/融豆.png')" alt="融豆" class="item-rongdou-icon" />
<span class="item-rongdou-price">{{ item.rongdou_price }}</span>
</div>
<div class="item-sub-price">
<el-icon class="item-points-icon"><Coin /></el-icon>
<span class="item-points-price">{{ item.points_price }}</span>
</div>
</div>
<span class="quantity-label">× {{ item.quantity }}</span>
</div>
</div>
<div class="product-total">
<div class="total-price-container">
<div class="total-main-price">
<img :src="getImageUrl('/imgs/profile/融豆.png')" alt="融豆" class="total-rongdou-icon" />
<span class="total-rongdou-price">{{ (item.rongdou_price * item.quantity) }}</span>
</div>
<div class="total-sub-price">
<el-icon class="total-points-icon"><Coin /></el-icon>
<span class="total-points-price">{{ (item.points_price * item.quantity) }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 费用明细 -->
<div class="cost-section">
<h3 class="section-title">费用明细</h3>
<div class="cost-item">
<span class="label">商品总价</span>
<span class="value">
<img :src="getImageUrl('/imgs/profile/融豆.png')" alt="融豆" class="cost-rongdou-icon" />
{{ orderData.totalAmount || 0 }}
</span>
</div>
<div class="cost-item">
<span class="label">运费</span>
<span class="value">
<img :src="getImageUrl('/imgs/profile/融豆.png')" alt="融豆" class="cost-rongdou-icon" />
{{ orderData.shippingFee || 0 }}
</span>
</div>
<div class="cost-item total">
<span class="label">总计</span>
<span class="value">
<img :src="getImageUrl('/imgs/profile/融豆.png')" alt="融豆" class="cost-rongdou-icon" />
{{ orderData.totalAmount || 0 }}
</span>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
ArrowLeft,
Warning,
Coin
} from '@element-plus/icons-vue'
import api from '@/utils/api'
import { getImageUrl } from '@/config'
const route = useRoute()
const router = useRouter()
// 响应式数据
const loading = ref(false)
const orderData = ref({
orderNumber: '', // 订单编号
createTime: '', // 订单创建时间
totalAmount: 0, // 订单总金额
subtotal: 0, // 商品小计金额(不含运费)
shippingFee: 0, // 运费
address: { // 收货地址信息
recipient: '', // 收件人姓名
phone: '', // 收件人电话
province: '', // 省份
city: '', // 城市
district: '', // 区/县
detail: '' // 详细地址
},
cartItems: [] // 购物车商品列表
})
// 方法
const formatDateTime = (dateTime) => {
if (!dateTime) return ''
const date = new Date(dateTime)
return date.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit'
})
}
const formatAddress = (address) => {
if (!address) return ''
const { province, city, district, detail } = address
return `${province || ''}${city || ''}${district || ''}${detail || ''}`
}
const fetchOrderData = async () => {
try {
loading.value = true
const orderId = route.query.orderId
console.log('orderId:', orderId)
// 检查orderId是否有效
if (!orderId || orderId === 'undefined' || orderId === 'null') {
console.warn('orderId无效使用默认订单数据')
throw new Error('无效的订单ID')
}
// 从后端获取待支付订单信息
const response = await api.get(`/orders/${orderId}`)
console.log('API响应:', response)
if (response.data.success) {
const data = response.data.data
const order = data.order || data
orderData.value = {
orderNumber: order.order_no || 'ORD' + Date.now(),
createTime: order.created_at || new Date().toISOString(),
totalAmount: order.total_amount || 0,
subtotal: order.total_amount || 0,
shippingFee: 0,
address: {
recipient: data.address?.receiver_name || order.username || '收件人',
phone: data.address?.receiver_phone || order.phone || '手机号',
province: data.address?.province_name || '',
city: data.address?.city_name || '',
district: data.address?.district_name || '',
detail: data.address?.detailed_address || '暂无地址信息'
},
cartItems: (data.items || order.items || []).map(item => ({
id: item.id,
name: item.product_name,
image: item.image_url || '/imgs/loading.png',
specification: item.spec_info || '默认规格',
price: item.price || 0,
points_price: item.points_price || 0,
rongdou_price: item.rongdou_price || 0,
quantity: item.quantity || 1
}))
}
} else {
throw new Error(response.data.message || '获取订单信息失败')
}
} catch (error) {
ElMessage.error(error.message || '获取订单信息失败')
// 如果获取失败,使用默认数据
orderData.value = {
orderNumber: 'ORD' + Date.now(),
createTime: new Date().toISOString(),
totalAmount: 0,
subtotal: 0,
shippingFee: 0,
address: {
recipient: '张三',
phone: '13888888888',
province: '浙江省',
city: '宁波市',
district: '鄞州区',
detail: '宁波外经合作大厦'
},
cartItems: [
{
id: 1,
name: '示例商品1',
image: '/imgs/loading.png',
specification: '默认规格',
price: 199.00,
quantity: 1
},
{
id: 2,
name: '示例商品2',
image: '/imgs/loading.png',
specification: '标准版',
price: 90.00,
quantity: 1
}
]
}
} finally {
loading.value = false
}
}
// 生命周期
onMounted(() => {
fetchOrderData()
})
</script>
<style scoped>
.pay-failed-page {
min-height: 100vh;
background: #f5f5f5;
display: flex;
flex-direction: column;
}
.navbar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 16px;
background: white;
border-bottom: 1px solid #eee;
position: relative;
}
.nav-left,
.nav-right {
width: 48px;
display: flex;
justify-content: center;
}
.nav-center {
position: absolute;
left: 50%;
transform: translateX(-50%);
}
.nav-title {
font-size: 18px;
font-weight: 500;
margin: 0;
}
.back-btn {
color: #333;
padding: 0;
}
.page-content {
flex: 1;
padding: 0;
}
.order-info-section,
.address-section,
.products-section,
.cost-section {
background: white;
padding: 16px;
margin-bottom: 8px;
}
.section-title {
font-size: 16px;
font-weight: 500;
margin: 0 0 12px 0;
color: #333;
}
.info-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 0;
border-bottom: 1px solid #f5f5f5;
}
.info-item:last-child {
border-bottom: none;
}
.label {
font-size: 14px;
color: #666;
}
.value {
font-size: 14px;
color: #333;
font-weight: 500;
}
.address-card {
background: #f8f9fa;
padding: 12px;
border-radius: 8px;
}
.address-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.recipient {
font-size: 14px;
font-weight: 500;
color: #333;
}
.phone {
font-size: 14px;
color: #666;
}
.address-detail {
font-size: 14px;
color: #666;
line-height: 1.4;
}
.product-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.product-item {
display: flex;
align-items: center;
gap: 12px;
padding: 12px;
background: #f8f9fa;
border-radius: 8px;
}
.product-image {
width: 60px;
height: 60px;
object-fit: cover;
border-radius: 6px;
}
.product-info {
flex: 1;
}
.product-name {
font-size: 14px;
font-weight: 500;
color: #333;
margin-bottom: 4px;
}
.product-spec {
font-size: 12px;
color: #999;
margin-bottom: 4px;
}
.product-price {
font-size: 12px;
color: #666;
display: flex;
align-items: center;
gap: 2px;
}
.product-price .el-icon {
color: #ffae00;
font-size: 12px;
}
.product-total {
font-size: 14px;
font-weight: 500;
color: #ff4757;
display: flex;
align-items: center;
gap: 2px;
}
.product-total .el-icon {
color: #ffae00;
font-size: 14px;
}
.cost-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 0;
}
.cost-item.total {
border-top: 1px solid #eee;
margin-top: 8px;
padding-top: 12px;
font-weight: 500;
}
.cost-item.total .value {
color: #ff4757;
font-size: 16px;
display: flex;
align-items: center;
gap: 4px;
}
.cost-item .value {
display: flex;
align-items: center;
gap: 2px;
}
.cost-item .value .el-icon {
color: #ffae00;
font-size: 14px;
}
.cost-item.total .value .el-icon {
color: #ffae00;
font-size: 16px;
}
/* 商品价格显示样式 */
.item-price-container {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 2px;
margin-bottom: 4px;
}
.item-main-price {
display: flex;
align-items: center;
gap: 2px;
}
.item-rongdou-icon {
width: 12px;
height: 12px;
}
.item-rongdou-price {
font-size: 12px;
font-weight: 500;
color: #333;
}
.item-sub-price {
display: flex;
align-items: center;
gap: 2px;
}
.item-points-icon {
font-size: 10px;
color: #ffae00;
}
.item-points-price {
font-size: 10px;
color: #666;
}
.quantity-label {
font-size: 12px;
color: #666;
margin-top: 2px;
}
/* 商品总价显示样式 */
.total-price-container {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 2px;
}
.total-main-price {
display: flex;
align-items: center;
gap: 2px;
}
.total-rongdou-icon {
width: 14px;
height: 14px;
}
.total-rongdou-price {
font-size: 14px;
font-weight: 500;
color: #ff4757;
}
.total-sub-price {
display: flex;
align-items: center;
gap: 2px;
}
.total-points-icon {
font-size: 12px;
color: #ffae00;
}
.total-points-price {
font-size: 12px;
color: #666;
}
/* 费用明细融豆图标样式 */
.cost-rongdou-icon {
width: 14px;
height: 14px;
margin-right: 2px;
}
</style>