|
|
@@ -7,18 +7,18 @@
|
|
|
<div class="success-body">
|
|
|
<el-card class="success-card" shadow="hover">
|
|
|
<!-- 顶部成功图标与标题 -->
|
|
|
- <div class="success-header">
|
|
|
+ <div class="success-header" :class="`status-${statusLevel}`">
|
|
|
<div class="success-icon-wrapper">
|
|
|
<div class="success-icon">
|
|
|
<el-icon class="success-icon-inner">
|
|
|
- <SuccessFilled />
|
|
|
+ <component :is="statusIcon" />
|
|
|
</el-icon>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="success-text">
|
|
|
- <h2 class="success-title">下单成功</h2>
|
|
|
+ <h2 class="success-title">{{ statusTitle }}</h2>
|
|
|
<p class="success-subtitle">
|
|
|
- 您的订单已经创建成功,请尽快完成支付或前往订单中心查看详情。
|
|
|
+ {{ statusSubtitle }}
|
|
|
</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -38,6 +38,20 @@
|
|
|
<div class="info-value">{{ orderInfo.orderId }}</div>
|
|
|
</div>
|
|
|
|
|
|
+ <div class="info-row">
|
|
|
+ <div class="info-label">订单状态</div>
|
|
|
+ <div class="info-value">
|
|
|
+ <el-tag
|
|
|
+ v-if="orderInfo.payStatusText || orderInfo.orderStatusText"
|
|
|
+ :type="statusTagType"
|
|
|
+ size="small"
|
|
|
+ >
|
|
|
+ {{ orderInfo.payStatusText || orderInfo.orderStatusText }}
|
|
|
+ </el-tag>
|
|
|
+ <span v-else>--</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
<div class="info-row">
|
|
|
<div class="info-label">商品名称</div>
|
|
|
<div class="info-value">{{ orderInfo.goodsName }}</div>
|
|
|
@@ -52,14 +66,6 @@
|
|
|
<div class="info-label">下单时间</div>
|
|
|
<div class="info-value">{{ orderInfo.createdAt }}</div>
|
|
|
</div>
|
|
|
-
|
|
|
- <div
|
|
|
- v-if="orderInfo.contact"
|
|
|
- class="info-row"
|
|
|
- >
|
|
|
- <div class="info-label">接收邮箱</div>
|
|
|
- <div class="info-value">{{ orderInfo.contact }}</div>
|
|
|
- </div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 操作按钮 -->
|
|
|
@@ -96,10 +102,18 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { computed, onMounted, reactive } from 'vue'
|
|
|
+import { computed, onMounted, reactive, ref } from 'vue'
|
|
|
import { useRoute, useRouter } from 'vue-router'
|
|
|
-import { SuccessFilled } from '@element-plus/icons-vue'
|
|
|
+import {
|
|
|
+ SuccessFilled,
|
|
|
+ WarningFilled,
|
|
|
+ CircleCloseFilled,
|
|
|
+ InfoFilled
|
|
|
+} from '@element-plus/icons-vue'
|
|
|
import Header from './header.vue'
|
|
|
+import { checkOrderStatus } from '/@/api/frontend/order'
|
|
|
+
|
|
|
+
|
|
|
|
|
|
defineOptions({ name: 'ClientOrderSuccess' })
|
|
|
|
|
|
@@ -108,11 +122,15 @@ const router = useRouter()
|
|
|
|
|
|
const orderInfo = reactive({
|
|
|
orderId: '',
|
|
|
+ orderNo: '',
|
|
|
goodsName: '',
|
|
|
amount: 0,
|
|
|
payMethod: '',
|
|
|
contact: '',
|
|
|
- createdAt: ''
|
|
|
+ createdAt: '',
|
|
|
+ payStatus: '', // 1已支付 0待支付 2失败 3取消
|
|
|
+ payStatusText: '',
|
|
|
+ orderStatusText: ''
|
|
|
})
|
|
|
|
|
|
const displayAmount = computed(() => {
|
|
|
@@ -129,32 +147,108 @@ const displayPayMethod = computed(() => {
|
|
|
return map[orderInfo.payMethod] || orderInfo.payMethod
|
|
|
})
|
|
|
|
|
|
-const initFromRoute = () => {
|
|
|
+// 订单状态级别:success / warning / danger / info
|
|
|
+const statusLevel = computed(() => {
|
|
|
+ const status = String(orderInfo.payStatus || '')
|
|
|
+ if (status === '1') return 'success'
|
|
|
+ if (status === '0' || status === '') return 'pending'
|
|
|
+ if (status === '2' || status === '3') return 'failed'
|
|
|
+ return 'info'
|
|
|
+})
|
|
|
+
|
|
|
+// 不同状态使用不同图标
|
|
|
+const statusIcon = computed(() => {
|
|
|
+ if (statusLevel.value === 'success') return SuccessFilled
|
|
|
+ if (statusLevel.value === 'failed') return CircleCloseFilled
|
|
|
+ if (statusLevel.value === 'pending') return WarningFilled
|
|
|
+ return InfoFilled
|
|
|
+})
|
|
|
+
|
|
|
+const statusTitle = computed(() => {
|
|
|
+ if (statusLevel.value === 'success') return '支付成功'
|
|
|
+ if (statusLevel.value === 'failed') return '订单未完成'
|
|
|
+ if (statusLevel.value === 'pending') return '订单待支付'
|
|
|
+ return '订单状态'
|
|
|
+})
|
|
|
+
|
|
|
+const statusSubtitle = computed(() => {
|
|
|
+ if (statusLevel.value === 'success') {
|
|
|
+ return orderInfo.orderStatusText || '您的订单已支付成功,可前往订单中心查看详情。'
|
|
|
+ }
|
|
|
+ if (statusLevel.value === 'failed') {
|
|
|
+ return orderInfo.payStatusText || '订单已取消或支付失败,如有疑问可联系商家处理。'
|
|
|
+ }
|
|
|
+ if (statusLevel.value === 'pending') {
|
|
|
+ return '订单已创建但尚未完成支付,您可以前往订单中心继续支付或查看详情。'
|
|
|
+ }
|
|
|
+ return '您可以在订单中心查看当前订单的详细状态。'
|
|
|
+})
|
|
|
+
|
|
|
+const statusTagType = computed(() => {
|
|
|
+ if (statusLevel.value === 'success') return 'success'
|
|
|
+ if (statusLevel.value === 'failed') return 'danger'
|
|
|
+ if (statusLevel.value === 'pending') return 'warning'
|
|
|
+ return 'info'
|
|
|
+})
|
|
|
+
|
|
|
+const loading = ref(false)
|
|
|
+
|
|
|
+// 从后台查询订单详情
|
|
|
+const fetchOrderDetail = async () => {
|
|
|
const query = route?.query || {}
|
|
|
- const now = new Date()
|
|
|
- const defaultDate = `${now.getFullYear()}-${(now.getMonth() + 1)
|
|
|
- .toString()
|
|
|
- .padStart(2, '0')}-${now
|
|
|
- .getDate()
|
|
|
- .toString()
|
|
|
- .padStart(2, '0')} ${now
|
|
|
- .getHours()
|
|
|
- .toString()
|
|
|
- .padStart(2, '0')}:${now
|
|
|
- .getMinutes()
|
|
|
- .toString()
|
|
|
- .padStart(2, '0')}`
|
|
|
-
|
|
|
- orderInfo.orderId = query.orderId || query.out_trade_no || '示例订单号 202312030001'
|
|
|
- orderInfo.goodsName = query.goodsName || query.subject || '惊鸿·日卡'
|
|
|
- orderInfo.amount = query.amount || query.totalAmount || query.total_fee || 25
|
|
|
- orderInfo.payMethod = query.payMethod || query.pay_method || 'alipay'
|
|
|
- orderInfo.contact = query.email || query.contact || ''
|
|
|
- orderInfo.createdAt = query.createdAt || defaultDate
|
|
|
+ const orderId = query.order_id
|
|
|
+ const orderNo = query.order_no
|
|
|
+
|
|
|
+ // 如果没有携带必要参数,直接返回(可以根据需要做兜底处理)
|
|
|
+ if (!orderId && !orderNo) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ loading.value = true
|
|
|
+ try {
|
|
|
+ const params = {}
|
|
|
+ if (orderId) params.order_id = orderId
|
|
|
+ if (orderNo) params.order_no = orderNo
|
|
|
+
|
|
|
+ const res = await checkOrderStatus(params)
|
|
|
+ const order = res?.data?.order || res?.data
|
|
|
+ if (!order) return
|
|
|
+
|
|
|
+ // 将接口返回的数据映射到页面展示所需字段
|
|
|
+ orderInfo.orderId = order.order_no || order.id || ''
|
|
|
+ orderInfo.orderNo = order.order_no || ''
|
|
|
+ orderInfo.goodsName =
|
|
|
+ order.remark ||
|
|
|
+ order.package_name ||
|
|
|
+ order.product_name ||
|
|
|
+ order.title ||
|
|
|
+ ''
|
|
|
+ orderInfo.amount = order.pay_amount || order.total_amount || 0
|
|
|
+ orderInfo.payMethod = order.pay_method || ''
|
|
|
+ orderInfo.createdAt =
|
|
|
+ order.order_time_formatted ||
|
|
|
+ order.order_time ||
|
|
|
+ order.create_time_formatted ||
|
|
|
+ order.create_time ||
|
|
|
+ ''
|
|
|
+
|
|
|
+ // 状态相关
|
|
|
+ const rawPayStatus = order.pay_status
|
|
|
+ orderInfo.payStatus = rawPayStatus != null ? String(rawPayStatus) : ''
|
|
|
+ orderInfo.payStatusText = order.pay_status_text || ''
|
|
|
+ orderInfo.orderStatusText = order.order_status_text || ''
|
|
|
+ } catch (e) {
|
|
|
+ console.error('加载订单详情失败', e)
|
|
|
+ } finally {
|
|
|
+ loading.value = false
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
const goToOrders = () => {
|
|
|
- router.push('/user/orders')
|
|
|
+ router.push({
|
|
|
+ path: '/user/me',
|
|
|
+ query: { tab: 'purchase-history' }
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
const goHome = () => {
|
|
|
@@ -162,7 +256,7 @@ const goHome = () => {
|
|
|
}
|
|
|
|
|
|
onMounted(() => {
|
|
|
- initFromRoute()
|
|
|
+ fetchOrderDetail()
|
|
|
})
|
|
|
</script>
|
|
|
|
|
|
@@ -236,6 +330,36 @@ onMounted(() => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+.success-header.status-success .success-icon {
|
|
|
+ background: #f0f9eb;
|
|
|
+ color: #67c23a;
|
|
|
+ box-shadow: 0 0 0 6px rgba(103, 194, 58, 0.12);
|
|
|
+}
|
|
|
+
|
|
|
+.success-header.status-pending .success-icon {
|
|
|
+ background: #fdf6ec;
|
|
|
+ color: #e6a23c;
|
|
|
+ box-shadow: 0 0 0 6px rgba(230, 162, 60, 0.16);
|
|
|
+}
|
|
|
+
|
|
|
+.success-header.status-failed .success-icon {
|
|
|
+ background: #fef0f0;
|
|
|
+ color: #f56c6c;
|
|
|
+ box-shadow: 0 0 0 6px rgba(245, 108, 108, 0.16);
|
|
|
+}
|
|
|
+
|
|
|
+.success-header.status-success .success-title {
|
|
|
+ color: #303133;
|
|
|
+}
|
|
|
+
|
|
|
+.success-header.status-pending .success-title {
|
|
|
+ color: #e6a23c;
|
|
|
+}
|
|
|
+
|
|
|
+.success-header.status-failed .success-title {
|
|
|
+ color: #f56c6c;
|
|
|
+}
|
|
|
+
|
|
|
.success-text {
|
|
|
flex: 1;
|
|
|
min-width: 0;
|