|
@@ -1,37 +1,88 @@
|
|
|
<template>
|
|
<template>
|
|
|
- <div class="container">
|
|
|
|
|
|
|
+ <div class="store-page order-detail-page">
|
|
|
<Breadcrumb />
|
|
<Breadcrumb />
|
|
|
- <a-space direction="vertical" :size="16" fill>
|
|
|
|
|
- <a-card class="general-card" title="订单状态">
|
|
|
|
|
- <div class="step">
|
|
|
|
|
- <a-steps :current="current" :status="status">
|
|
|
|
|
- <a-step :description="oneDes">{{ oneText }}</a-step>
|
|
|
|
|
- <a-step :description="twoDes">{{ twoText }}</a-step>
|
|
|
|
|
- <a-step :description="threeDes">{{ threeText }}</a-step>
|
|
|
|
|
|
|
+
|
|
|
|
|
+ <a-spin :loading="loading" class="store-spin">
|
|
|
|
|
+ <div class="detail-stack">
|
|
|
|
|
+ <!-- 待支付横幅 -->
|
|
|
|
|
+ <div v-if="data?.state === 0 && hasPay" class="pay-banner">
|
|
|
|
|
+ <div class="pay-banner__info">
|
|
|
|
|
+ <icon-clock-circle class="pay-banner__icon" />
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <div class="pay-banner__title">等待支付</div>
|
|
|
|
|
+ <div class="pay-banner__desc">{{ paymentCountdownText }}</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <a-button type="primary" size="large" class="pay-banner__btn" @click="pay">
|
|
|
|
|
+ 立即支付 ¥{{ data?.price }}
|
|
|
|
|
+ </a-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <a-card :bordered="false" class="status-card">
|
|
|
|
|
+ <a-steps :current="stepCurrent" :status="stepStatus" label-placement="vertical" class="steps">
|
|
|
|
|
+ <a-step :description="stepDescriptions[0]">{{ stepLabels[0] }}</a-step>
|
|
|
|
|
+ <a-step :description="stepDescriptions[1]">{{ stepLabels[1] }}</a-step>
|
|
|
|
|
+ <a-step :description="stepDescriptions[2]">{{ stepLabels[2] }}</a-step>
|
|
|
</a-steps>
|
|
</a-steps>
|
|
|
|
|
+ <div class="status-badge-wrap">
|
|
|
|
|
+ <OrderStateTag :state="data?.state ?? 0" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </a-card>
|
|
|
|
|
+
|
|
|
|
|
+ <a-card :bordered="false" class="info-card" title="订单信息">
|
|
|
|
|
+ <a-descriptions :column="1" bordered size="medium">
|
|
|
|
|
+ <a-descriptions-item label="商品名称">{{ data?.name || '-' }}</a-descriptions-item>
|
|
|
|
|
+ <a-descriptions-item v-if="data?.original_price && data?.discount_amount > 0" label="商品原价">
|
|
|
|
|
+ ¥{{ data.original_price }}
|
|
|
|
|
+ </a-descriptions-item>
|
|
|
|
|
+ <a-descriptions-item v-if="data?.coupon_code" label="优惠码">
|
|
|
|
|
+ {{ data.coupon_code }}
|
|
|
|
|
+ <span v-if="data?.discount_amount > 0" class="discount-tag">-¥{{ data.discount_amount }}</span>
|
|
|
|
|
+ </a-descriptions-item>
|
|
|
|
|
+ <a-descriptions-item label="支付金额">
|
|
|
|
|
+ <span class="price-text">¥{{ data?.price }}</span>
|
|
|
|
|
+ </a-descriptions-item>
|
|
|
|
|
+ <a-descriptions-item label="支付方式">
|
|
|
|
|
+ <span class="pay-row">
|
|
|
|
|
+ <icon-wechatpay v-if="data?.pay_type === 'wxpay'" />
|
|
|
|
|
+ <icon-alipay-circle v-else-if="data?.pay_type === 'alipay'" />
|
|
|
|
|
+ {{ getPayTypeLabel(data?.pay_type) }}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </a-descriptions-item>
|
|
|
|
|
+ <a-descriptions-item label="订单号">{{ data?.orderId }}</a-descriptions-item>
|
|
|
|
|
+ <a-descriptions-item v-if="data?.pay_id" label="支付平台单号">{{ data.pay_id }}</a-descriptions-item>
|
|
|
|
|
+ <a-descriptions-item label="下单时间">{{ formatStoreTimeFull(data?.create_time) }}</a-descriptions-item>
|
|
|
|
|
+ <a-descriptions-item v-if="data?.pay_time" label="支付时间">
|
|
|
|
|
+ {{ formatStoreTimeFull(data.pay_time) }}
|
|
|
|
|
+ </a-descriptions-item>
|
|
|
|
|
+ </a-descriptions>
|
|
|
|
|
+ </a-card>
|
|
|
|
|
+
|
|
|
|
|
+ <a-card v-if="content" :bordered="false" class="info-card" title="商品说明">
|
|
|
|
|
+ <div class="rich-content" v-html="content" />
|
|
|
|
|
+ </a-card>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="detail-actions">
|
|
|
|
|
+ <a-button @click="$router.push('/store/myOrder')">返回订单列表</a-button>
|
|
|
|
|
+ <a-button type="outline" @click="$router.push('/store/goodsList')">继续购物</a-button>
|
|
|
</div>
|
|
</div>
|
|
|
- <a-button type="primary" size="large" class="paybutton" @click="pay"
|
|
|
|
|
- v-if="data?.state === 0 && payData != {}">立即支付</a-button>
|
|
|
|
|
-
|
|
|
|
|
- </a-card>
|
|
|
|
|
- <a-card class="general-card" title="订单详情">
|
|
|
|
|
- <a-descriptions :data="orderData" size="large" :column="1" />
|
|
|
|
|
- </a-card>
|
|
|
|
|
- <a-card class="general-card" title="商品详情">
|
|
|
|
|
- <div v-html="content"></div>
|
|
|
|
|
- </a-card>
|
|
|
|
|
-
|
|
|
|
|
- </a-space>
|
|
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </a-spin>
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
|
-import { ref, onUnmounted, onMounted, h } from 'vue'
|
|
|
|
|
|
|
+import { ref, computed, onUnmounted, onMounted } from 'vue'
|
|
|
import { orderDeatil } from '@/api/order'
|
|
import { orderDeatil } from '@/api/order'
|
|
|
import { useRoute } from 'vue-router'
|
|
import { useRoute } from 'vue-router'
|
|
|
-import { Notification } from '@arco-design/web-vue'
|
|
|
|
|
-import { Message } from '@arco-design/web-vue'
|
|
|
|
|
-import { IconQq, IconWechatpay, IconAlipayCircle } from '@arco-design/web-vue/es/icon'
|
|
|
|
|
|
|
+import { Notification, Message } from '@arco-design/web-vue'
|
|
|
|
|
+import OrderStateTag from '@/components/store/OrderStateTag.vue'
|
|
|
|
|
+import {
|
|
|
|
|
+ formatStoreTimeFull,
|
|
|
|
|
+ getPayTypeLabel,
|
|
|
|
|
+ decodeGoodsContent,
|
|
|
|
|
+ hasPayData
|
|
|
|
|
+} from '@/utils/storeFormat'
|
|
|
|
|
|
|
|
const route = useRoute()
|
|
const route = useRoute()
|
|
|
const { id } = route.params
|
|
const { id } = route.params
|
|
@@ -39,88 +90,105 @@ const { id } = route.params
|
|
|
const loading = ref(true)
|
|
const loading = ref(true)
|
|
|
const data = ref({})
|
|
const data = ref({})
|
|
|
const payData = ref({})
|
|
const payData = ref({})
|
|
|
|
|
+const content = ref('')
|
|
|
|
|
+const paymentCountdownText = ref('')
|
|
|
|
|
|
|
|
-const current = ref(1)
|
|
|
|
|
-const status = ref('process')
|
|
|
|
|
-const oneText = ref('待支付')
|
|
|
|
|
-const twoText = ref('待处理')
|
|
|
|
|
-const threeText = ref('已完成')
|
|
|
|
|
-const oneDes = ref('')
|
|
|
|
|
-const twoDes = ref('')
|
|
|
|
|
-const threeDes = ref('')
|
|
|
|
|
|
|
+const hasPay = computed(() => hasPayData(payData.value))
|
|
|
|
|
|
|
|
-const orderData = ref([])
|
|
|
|
|
-const content = ref('')
|
|
|
|
|
|
|
+const stepCurrent = ref(1)
|
|
|
|
|
+const stepStatus = ref('process')
|
|
|
|
|
+const stepLabels = ref(['待支付', '待处理', '已完成'])
|
|
|
|
|
+const stepDescriptions = ref(['', '', ''])
|
|
|
|
|
|
|
|
-const stramptoTime = (time) => {
|
|
|
|
|
- return new Date(time).toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' })
|
|
|
|
|
|
|
+const PAY_TIMEOUT_SEC = 300
|
|
|
|
|
+let timer = null
|
|
|
|
|
+
|
|
|
|
|
+const updateStepState = () => {
|
|
|
|
|
+ const state = data.value?.state
|
|
|
|
|
+ stepDescriptions.value = ['', '', '']
|
|
|
|
|
+
|
|
|
|
|
+ switch (state) {
|
|
|
|
|
+ case 0:
|
|
|
|
|
+ stepCurrent.value = 1
|
|
|
|
|
+ stepStatus.value = 'process'
|
|
|
|
|
+ stepLabels.value = ['待支付', '待处理', '已完成']
|
|
|
|
|
+ updatePaymentCountdown()
|
|
|
|
|
+ break
|
|
|
|
|
+ case 1:
|
|
|
|
|
+ stepCurrent.value = 2
|
|
|
|
|
+ stepStatus.value = 'process'
|
|
|
|
|
+ stepDescriptions.value[1] = '支付成功,等待系统处理'
|
|
|
|
|
+ stopPolling()
|
|
|
|
|
+ break
|
|
|
|
|
+ case 2:
|
|
|
|
|
+ stepCurrent.value = 3
|
|
|
|
|
+ stepStatus.value = 'finish'
|
|
|
|
|
+ stepDescriptions.value[2] = '权益已发放至账户'
|
|
|
|
|
+ stopPolling()
|
|
|
|
|
+ break
|
|
|
|
|
+ case 3:
|
|
|
|
|
+ stepCurrent.value = 1
|
|
|
|
|
+ stepStatus.value = 'error'
|
|
|
|
|
+ stepLabels.value = ['已关闭', '待处理', '已完成']
|
|
|
|
|
+ stepDescriptions.value[0] = '订单超时或已取消'
|
|
|
|
|
+ stopPolling()
|
|
|
|
|
+ break
|
|
|
|
|
+ default:
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-function getPayType(type) {
|
|
|
|
|
- switch (type) {
|
|
|
|
|
- case 'alipay':
|
|
|
|
|
- return [h(IconAlipayCircle), ' 支付宝']
|
|
|
|
|
- case 'qqpay':
|
|
|
|
|
- return [h(IconQq), ' QQ支付']
|
|
|
|
|
- case 'wxpay':
|
|
|
|
|
- return [h(IconWechatpay), ' 微信支付']
|
|
|
|
|
|
|
+const updatePaymentCountdown = () => {
|
|
|
|
|
+ const ts = data.value?.create_time
|
|
|
|
|
+ if (!ts) {
|
|
|
|
|
+ paymentCountdownText.value = '请在规定时间内完成支付'
|
|
|
|
|
+ return
|
|
|
}
|
|
}
|
|
|
|
|
+ const diffSec = Math.floor((Date.now() - ts) / 1000)
|
|
|
|
|
+ if (diffSec > PAY_TIMEOUT_SEC) {
|
|
|
|
|
+ paymentCountdownText.value = '支付已超时,订单可能已关闭'
|
|
|
|
|
+ stepDescriptions.value[0] = '支付超时'
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ const remaining = PAY_TIMEOUT_SEC - diffSec
|
|
|
|
|
+ const m = Math.floor(remaining / 60)
|
|
|
|
|
+ const s = String(remaining % 60).padStart(2, '0')
|
|
|
|
|
+ paymentCountdownText.value = `请在 ${m} 分 ${s} 秒内完成支付`
|
|
|
|
|
+ stepDescriptions.value[0] = paymentCountdownText.value
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-const getOrderDeatil = async () => {
|
|
|
|
|
|
|
+const getOrderDetail = async () => {
|
|
|
try {
|
|
try {
|
|
|
const res = await orderDeatil({ orderId: id })
|
|
const res = await orderDeatil({ orderId: id })
|
|
|
- if (!res || res.code !== 0)
|
|
|
|
|
|
|
+ if (!res || res.code !== 0) {
|
|
|
return Notification.error({
|
|
return Notification.error({
|
|
|
- title: '获取订单详情失败!',
|
|
|
|
|
|
|
+ title: '获取订单详情失败',
|
|
|
content: res?.msg ?? '请稍后再试'
|
|
content: res?.msg ?? '请稍后再试'
|
|
|
})
|
|
})
|
|
|
- data.value = res.data
|
|
|
|
|
- content.value = decodeURI(atob(res.data.content || ''))
|
|
|
|
|
-
|
|
|
|
|
- let detail = []
|
|
|
|
|
- if (res.data.name)
|
|
|
|
|
- detail.push({ label: '商品名称', value: res.data.name })
|
|
|
|
|
- if (res.data.price)
|
|
|
|
|
- detail.push({ label: '支付价格', value: '¥' + res.data.price })
|
|
|
|
|
- if (res.data.pay_type)
|
|
|
|
|
- detail.push({ label: '支付方式', value: getPayType(res.data.pay_type) })
|
|
|
|
|
- if (res.data.orderId)
|
|
|
|
|
- detail.push({ label: '平台订单号', value: res.data.orderId })
|
|
|
|
|
- if (res.data.pay_id)
|
|
|
|
|
- detail.push({ label: '支付平台订单号', value: res.data.pay_id })
|
|
|
|
|
- if (res.data.create_time)
|
|
|
|
|
- detail.push({ label: '下单时间', value: stramptoTime(res.data.create_time) })
|
|
|
|
|
- if (res.data.pay_time)
|
|
|
|
|
- detail.push({ label: '支付时间', value: stramptoTime(res.data.pay_time) })
|
|
|
|
|
-
|
|
|
|
|
- orderData.value = detail
|
|
|
|
|
-
|
|
|
|
|
- if (res.payData)
|
|
|
|
|
- payData.value = res.payData
|
|
|
|
|
- else
|
|
|
|
|
- payData.value = {}
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ data.value = res.data ?? {}
|
|
|
|
|
+ content.value = decodeGoodsContent(res.data?.content)
|
|
|
|
|
+ payData.value = res.payData && hasPayData(res.payData) ? res.payData : {}
|
|
|
|
|
+ updateStepState()
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
Notification.error({
|
|
Notification.error({
|
|
|
- title: '获取订单详情失败!',
|
|
|
|
|
|
|
+ title: '获取订单详情失败',
|
|
|
content: error.message || '请稍后再试'
|
|
content: error.message || '请稍后再试'
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-let timer = null
|
|
|
|
|
-
|
|
|
|
|
-// 轮询
|
|
|
|
|
const startPolling = () => {
|
|
const startPolling = () => {
|
|
|
- if (!timer) {
|
|
|
|
|
- timer = setInterval(async () => {
|
|
|
|
|
- await getOrderDeatil()
|
|
|
|
|
- getOrderState()
|
|
|
|
|
- }, 1000)
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (timer) return
|
|
|
|
|
+ timer = setInterval(async () => {
|
|
|
|
|
+ if (data.value?.state !== 0) {
|
|
|
|
|
+ stopPolling()
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ await getOrderDetail()
|
|
|
|
|
+ }, 3000)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// 停止轮询
|
|
|
|
|
const stopPolling = () => {
|
|
const stopPolling = () => {
|
|
|
if (timer) {
|
|
if (timer) {
|
|
|
clearInterval(timer)
|
|
clearInterval(timer)
|
|
@@ -130,119 +198,140 @@ const stopPolling = () => {
|
|
|
|
|
|
|
|
onMounted(async () => {
|
|
onMounted(async () => {
|
|
|
loading.value = true
|
|
loading.value = true
|
|
|
- await getOrderDeatil()
|
|
|
|
|
|
|
+ await getOrderDetail()
|
|
|
loading.value = false
|
|
loading.value = false
|
|
|
- startPolling()
|
|
|
|
|
|
|
+ if (data.value?.state === 0) startPolling()
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
-// 组件销毁时停止轮询
|
|
|
|
|
-onUnmounted(() => {
|
|
|
|
|
- stopPolling()
|
|
|
|
|
-})
|
|
|
|
|
|
|
+onUnmounted(stopPolling)
|
|
|
|
|
|
|
|
-function getOrderState() {
|
|
|
|
|
- if (data.value) {
|
|
|
|
|
-
|
|
|
|
|
- switch (data.value.state) {
|
|
|
|
|
- case 0:
|
|
|
|
|
- current.value = 1
|
|
|
|
|
- getPaymentStatus(data.value.create_time)
|
|
|
|
|
- break
|
|
|
|
|
-
|
|
|
|
|
- case 1:
|
|
|
|
|
- current.value = 2
|
|
|
|
|
- twoDes.value = '支付完成,等待系统处理'
|
|
|
|
|
- oneDes.value = ''
|
|
|
|
|
- break
|
|
|
|
|
-
|
|
|
|
|
- case 2:
|
|
|
|
|
- current.value = 3
|
|
|
|
|
- threeDes.value = '订单处理完毕'
|
|
|
|
|
- status.value = 'finish'
|
|
|
|
|
- oneDes.value = ''
|
|
|
|
|
- twoDes.value = ''
|
|
|
|
|
- stopPolling()
|
|
|
|
|
- break
|
|
|
|
|
-
|
|
|
|
|
- case 3:
|
|
|
|
|
- current.value = 1
|
|
|
|
|
- status.value = 'error'
|
|
|
|
|
- oneText.value = '支付超时'
|
|
|
|
|
- oneDes.value = '订单已关闭'
|
|
|
|
|
- stopPolling()
|
|
|
|
|
- break
|
|
|
|
|
|
|
+const pay = () => {
|
|
|
|
|
+ if (!hasPay.value) {
|
|
|
|
|
+ Message.warning('暂无支付信息,请刷新页面重试')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ Message.success('正在跳转支付页面,请在新页面完成支付')
|
|
|
|
|
+ openPaymentWindow(payData.value.payUrl, payData.value.payData)
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
|
|
+function openPaymentWindow(payUrl, formData) {
|
|
|
|
|
+ const form = document.createElement('form')
|
|
|
|
|
+ form.method = 'POST'
|
|
|
|
|
+ form.action = payUrl
|
|
|
|
|
+ form.style.display = 'none'
|
|
|
|
|
+ for (const key in formData) {
|
|
|
|
|
+ if (Object.prototype.hasOwnProperty.call(formData, key)) {
|
|
|
|
|
+ const input = document.createElement('input')
|
|
|
|
|
+ input.type = 'hidden'
|
|
|
|
|
+ input.name = key
|
|
|
|
|
+ input.value = formData[key]
|
|
|
|
|
+ form.appendChild(input)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ document.body.appendChild(form)
|
|
|
|
|
+ form.submit()
|
|
|
|
|
+ document.body.removeChild(form)
|
|
|
|
|
+}
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style lang="less" scoped>
|
|
|
|
|
+@import '@/styles/store-theme.less';
|
|
|
|
|
+
|
|
|
|
|
+.detail-stack {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ gap: 16px;
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ max-width: 900px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-function getPaymentStatus(timestamp) {
|
|
|
|
|
- const now = Date.now();
|
|
|
|
|
- const diffMs = now - timestamp; // 毫秒差值
|
|
|
|
|
- const diffSeconds = Math.floor(diffMs / 1000); // 秒差值
|
|
|
|
|
|
|
+.pay-banner {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ gap: 16px;
|
|
|
|
|
+ padding: 20px 24px;
|
|
|
|
|
+ background: linear-gradient(135deg, #fff7e6 0%, #ffe7ba 100%);
|
|
|
|
|
+ border: 1px solid #ffd591;
|
|
|
|
|
+ border-radius: @store-radius;
|
|
|
|
|
+
|
|
|
|
|
+ &__info {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 12px;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- const timeout = 300;
|
|
|
|
|
|
|
+ &__icon {
|
|
|
|
|
+ font-size: 32px;
|
|
|
|
|
+ color: rgb(var(--orange-6));
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- if (diffSeconds > timeout) {
|
|
|
|
|
- oneDes.value = "支付超时";
|
|
|
|
|
- } else {
|
|
|
|
|
- const remaining = timeout - diffSeconds;
|
|
|
|
|
- const minutes = Math.floor(remaining / 60);
|
|
|
|
|
- const seconds = remaining % 60;
|
|
|
|
|
- oneDes.value = `请在${minutes}分${seconds.toString().padStart(2, '0')}秒内完成支付`;
|
|
|
|
|
|
|
+ &__title {
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ font-size: 1.1rem;
|
|
|
|
|
+ color: @store-primary;
|
|
|
}
|
|
}
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
-const pay = () => {
|
|
|
|
|
- Message.success('正在跳转支付页面...请在新页面内完成支付')
|
|
|
|
|
- if (payData.value != {}) {
|
|
|
|
|
- openPaymentWindow(payData.value.payUrl, payData.value.payData)
|
|
|
|
|
|
|
+ &__desc {
|
|
|
|
|
+ font-size: 0.85rem;
|
|
|
|
|
+ color: @store-text-muted;
|
|
|
|
|
+ margin-top: 4px;
|
|
|
}
|
|
}
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
-function openPaymentWindow(payUrl, payData) {
|
|
|
|
|
- const form = document.createElement('form');
|
|
|
|
|
- form.method = 'POST';
|
|
|
|
|
- form.action = payUrl;
|
|
|
|
|
- // form.target = '_blank'
|
|
|
|
|
- form.style.display = 'none';
|
|
|
|
|
-
|
|
|
|
|
- // 遍历 payData,将每一项添加为隐藏的 input
|
|
|
|
|
- for (const key in payData) {
|
|
|
|
|
- if (payData.hasOwnProperty(key)) {
|
|
|
|
|
- const input = document.createElement('input');
|
|
|
|
|
- input.type = 'hidden';
|
|
|
|
|
- input.name = key;
|
|
|
|
|
- input.value = payData[key];
|
|
|
|
|
- form.appendChild(input);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ &__btn {
|
|
|
|
|
+ border-radius: 999px;
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
}
|
|
}
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- document.body.appendChild(form);
|
|
|
|
|
- form.submit();
|
|
|
|
|
- document.body.removeChild(form);
|
|
|
|
|
|
|
+.status-card,
|
|
|
|
|
+.info-card {
|
|
|
|
|
+ border-radius: @store-radius;
|
|
|
|
|
+ border: 1px solid @store-card-border;
|
|
|
|
|
+ box-shadow: @store-shadow;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-</script>
|
|
|
|
|
|
|
+.steps {
|
|
|
|
|
+ max-width: 100%;
|
|
|
|
|
+ margin: 8px 0 16px;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
-<style lang="less" scoped>
|
|
|
|
|
-.container {
|
|
|
|
|
- padding: 0 20px 20px 20px;
|
|
|
|
|
|
|
+.status-badge-wrap {
|
|
|
|
|
+ text-align: center;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-.general-card {
|
|
|
|
|
- border-radius: 5px;
|
|
|
|
|
|
|
+.price-text {
|
|
|
|
|
+ font-size: 1.15rem;
|
|
|
|
|
+ font-weight: 700;
|
|
|
|
|
+ color: @store-price;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- .step {
|
|
|
|
|
- width: 900px;
|
|
|
|
|
- margin: 30px auto;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+.discount-tag {
|
|
|
|
|
+ margin-left: 8px;
|
|
|
|
|
+ color: rgb(var(--green-6));
|
|
|
|
|
+ font-size: 0.9rem;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- .paybutton {
|
|
|
|
|
- position: relative;
|
|
|
|
|
- left: 50%;
|
|
|
|
|
- translate: (-50%);
|
|
|
|
|
- margin-top: 10px;
|
|
|
|
|
|
|
+.pay-row {
|
|
|
|
|
+ display: inline-flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 6px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.rich-content {
|
|
|
|
|
+ line-height: 1.75;
|
|
|
|
|
+ color: @store-text-muted;
|
|
|
|
|
+
|
|
|
|
|
+ :deep(img) {
|
|
|
|
|
+ max-width: 100%;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-</style>
|
|
|
|
|
|
|
+
|
|
|
|
|
+.detail-actions {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ gap: 12px;
|
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
|
+ margin-top: 8px;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|