1. App.vue 启动时立即预加载 uiConfig,杜绝首屏网络延时导致瞬间闪现付费会员入口 2. 会员中心 (member/index.vue):在提审防审模式下直接展示纯净【便民服务指南】卡片,杜绝任何 VIP 皇冠、会员标价、折扣与充值入口 3. 个人中心 (mine/index.vue):提审防审模式下彻底隐藏会员卡片与我的余额,紧凑上移卡片布局 4. 订单明细、充值页与消息中心增加防审合规兼容,避免误触发任何虚拟支付诱导
1016 行
29 KiB
Vue
1016 行
29 KiB
Vue
<template>
|
||
<view class="order-detail fc-page" :class="{ 'order-detail--has-footer': showFooter }">
|
||
<!-- 规范化顶部导航(左上角返回上级/订单列表) -->
|
||
<fc-navbar title="订单详情" theme="gradient" :show-back="true" @back="handleNavBack" />
|
||
|
||
<!-- 加载中 -->
|
||
<view v-if="loading" class="order-detail__loading">
|
||
<text class="order-detail__loading-text">正在加载订单信息…</text>
|
||
</view>
|
||
|
||
<!-- 订单不存在 -->
|
||
<fc-empty v-else-if="!order" icon="receipt" text="订单不存在或已被删除" />
|
||
|
||
<view v-else class="order-detail__body">
|
||
<!-- 顶部 Hero 状态区 -->
|
||
<view class="order-detail__hero" :class="`order-detail__hero--${order.status}`">
|
||
<view class="order-detail__hero-content">
|
||
<view class="order-detail__hero-left">
|
||
<text class="order-detail__hero-title">{{ statusTitle }}</text>
|
||
<text class="order-detail__hero-desc">{{ statusDesc }}</text>
|
||
</view>
|
||
<!-- 待支付倒计时 -->
|
||
<view v-if="order.status === 'pending' && remainingSeconds > 0" class="order-detail__countdown">
|
||
<text class="order-detail__countdown-label">支付剩余</text>
|
||
<text class="order-detail__countdown-time">{{ countdownText }}</text>
|
||
</view>
|
||
<!-- 已支付状态徽章 -->
|
||
<view v-else-if="order.status === 'paid'" class="order-detail__status-badge">
|
||
<text class="order-detail__status-badge-text">交易成功</text>
|
||
</view>
|
||
<!-- 已关闭状态徽章 -->
|
||
<view v-else-if="order.status === 'closed'" class="order-detail__status-badge order-detail__status-badge--closed">
|
||
<text class="order-detail__status-badge-text">已取消</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 订单生命周期流转节点 -->
|
||
<view class="order-detail__steps">
|
||
<view class="order-detail__step" :class="{ 'order-detail__step--active': true }">
|
||
<view class="order-detail__step-dot" />
|
||
<text class="order-detail__step-text">提交订单</text>
|
||
</view>
|
||
<view class="order-detail__step-line" :class="{ 'order-detail__step-line--active': order.status === 'paid' }" />
|
||
<view class="order-detail__step" :class="{ 'order-detail__step--active': order.status === 'paid' }">
|
||
<view class="order-detail__step-dot" />
|
||
<text class="order-detail__step-text">{{ order.status === 'closed' ? '订单关闭' : '支付完成' }}</text>
|
||
</view>
|
||
<view class="order-detail__step-line" :class="{ 'order-detail__step-line--active': order.status === 'paid' }" />
|
||
<view class="order-detail__step" :class="{ 'order-detail__step--active': order.status === 'paid' }">
|
||
<view class="order-detail__step-dot" />
|
||
<text class="order-detail__step-text">权益履约</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 商品与服务权益卡片 -->
|
||
<view class="fc-card order-detail__card">
|
||
<view class="order-detail__card-header">
|
||
<text class="order-detail__card-title">商品与服务</text>
|
||
<text class="order-detail__type-pill">{{ order.typeText }}</text>
|
||
</view>
|
||
|
||
<view class="order-detail__goods">
|
||
<view class="order-detail__goods-icon">
|
||
<image class="fc-icon fc-icon--lg" :src="iconUrl(orderIconKey(order.type))" mode="aspectFit" />
|
||
</view>
|
||
<view class="order-detail__goods-info">
|
||
<text class="order-detail__goods-name">{{ order.title }}</text>
|
||
<text class="order-detail__goods-desc">{{ goodsSubTitle }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 规格与权益扩展清单 -->
|
||
<view class="order-detail__meta-list">
|
||
<!-- 会员订单权益明细 -->
|
||
<template v-if="order.type === 'member' && order.relatedInfo">
|
||
<view class="order-detail__meta-item">
|
||
<text class="order-detail__meta-label">有效周期</text>
|
||
<text class="order-detail__meta-val">{{ order.relatedInfo.days }} 天(支付后即刻生效)</text>
|
||
</view>
|
||
<view v-if="order.relatedInfo.postQuota > 0" class="order-detail__meta-item">
|
||
<text class="order-detail__meta-label">赠送特权</text>
|
||
<text class="order-detail__meta-val order-detail__meta-val--highlight">赠送免费发布 {{ order.relatedInfo.postQuota }} 条信息额度</text>
|
||
</view>
|
||
<view class="order-detail__meta-item">
|
||
<text class="order-detail__meta-label">会员权益</text>
|
||
<view class="order-detail__tags-wrap">
|
||
<text class="order-detail__tag-item">专属尊贵皇冠标识</text>
|
||
<text class="order-detail__tag-item">信息优先展示</text>
|
||
<text class="order-detail__tag-item">置顶专属折扣</text>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<!-- 发布订单明细 -->
|
||
<template v-else-if="order.type === 'post' && order.relatedInfo">
|
||
<view v-if="order.relatedInfo.categoryName" class="order-detail__meta-item">
|
||
<text class="order-detail__meta-label">所属分类</text>
|
||
<text class="order-detail__meta-val">{{ order.relatedInfo.categoryName }}</text>
|
||
</view>
|
||
<view class="order-detail__meta-item">
|
||
<text class="order-detail__meta-label">服务内容</text>
|
||
<text class="order-detail__meta-val">同城全域展示推广、智能附近推荐、基础展示 30 天</text>
|
||
</view>
|
||
<view class="order-detail__meta-item">
|
||
<text class="order-detail__meta-label">审核状态</text>
|
||
<text class="order-detail__meta-val order-detail__meta-val--highlight">{{ postAuditStatusText }}</text>
|
||
</view>
|
||
</template>
|
||
|
||
<!-- 充值订单明细 -->
|
||
<template v-else-if="order.type === 'recharge'">
|
||
<view class="order-detail__meta-item">
|
||
<text class="order-detail__meta-label">充值账户</text>
|
||
<text class="order-detail__meta-val">{{ order.userAccount || '当前登录用户' }}</text>
|
||
</view>
|
||
<view class="order-detail__meta-item">
|
||
<text class="order-detail__meta-label">到账账户</text>
|
||
<text class="order-detail__meta-val">平台个人中心 · 钱包余额</text>
|
||
</view>
|
||
<view class="order-detail__meta-item">
|
||
<text class="order-detail__meta-label">资金用途</text>
|
||
<text class="order-detail__meta-val">可用于发布付费、刷新置顶及开通会员等增值消费</text>
|
||
</view>
|
||
</template>
|
||
|
||
<!-- 付费查看明细 -->
|
||
<template v-else-if="order.type === 'payview' && order.relatedInfo">
|
||
<view class="order-detail__meta-item">
|
||
<text class="order-detail__meta-label">解锁信息</text>
|
||
<text class="order-detail__meta-val">{{ order.relatedInfo.title }}</text>
|
||
</view>
|
||
<view class="order-detail__meta-item">
|
||
<text class="order-detail__meta-label">查看权限</text>
|
||
<text class="order-detail__meta-val order-detail__meta-val--highlight">已获得该条信息的电话与微信号永久查看权限</text>
|
||
</view>
|
||
</template>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 费用账单明细卡片 -->
|
||
<view class="fc-card order-detail__card">
|
||
<view class="order-detail__card-header">
|
||
<text class="order-detail__card-title">费用账单</text>
|
||
</view>
|
||
|
||
<view class="order-detail__bill">
|
||
<view class="order-detail__bill-row">
|
||
<text class="order-detail__bill-label">服务总额</text>
|
||
<text class="order-detail__bill-val">¥{{ formatMoney(hasDiscount ? order.originAmount : order.amount) }}</text>
|
||
</view>
|
||
<view v-if="hasDiscount" class="order-detail__bill-row order-detail__bill-row--discount">
|
||
<text class="order-detail__bill-label">优惠券抵扣<text v-if="order.couponName">({{ order.couponName }})</text></text>
|
||
<text class="order-detail__bill-val">-¥{{ formatMoney(order.couponAmount) }}</text>
|
||
</view>
|
||
<view class="order-detail__bill-divider" />
|
||
<view class="order-detail__bill-row order-detail__bill-row--total">
|
||
<text class="order-detail__bill-total-label">实付款</text>
|
||
<view class="fc-price">
|
||
<text class="fc-price__symbol">¥</text>
|
||
<text class="order-detail__bill-total-val">{{ formatMoney(order.amount) }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 订单交易溯源信息卡片 -->
|
||
<view class="fc-card order-detail__card">
|
||
<view class="order-detail__card-header">
|
||
<text class="order-detail__card-title">交易信息</text>
|
||
</view>
|
||
|
||
<view class="order-detail__info-list">
|
||
<view class="order-detail__info-item">
|
||
<text class="order-detail__info-label">订单编号</text>
|
||
<view class="order-detail__info-val-box">
|
||
<text class="order-detail__info-val">{{ order.orderNo }}</text>
|
||
<view class="order-detail__copy-pill" @click="copyOrderNo">
|
||
<text>复制</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="order-detail__info-item">
|
||
<text class="order-detail__info-label">创建时间</text>
|
||
<text class="order-detail__info-val">{{ formatTime(order.createdAt) }}</text>
|
||
</view>
|
||
<view class="order-detail__info-item">
|
||
<text class="order-detail__info-label">支付方式</text>
|
||
<text class="order-detail__info-val">{{ order.payTypeText }}</text>
|
||
</view>
|
||
<view v-if="order.payTime" class="order-detail__info-item">
|
||
<text class="order-detail__info-label">支付时间</text>
|
||
<text class="order-detail__info-val">{{ formatTime(order.payTime) }}</text>
|
||
</view>
|
||
<view v-if="order.closeTime" class="order-detail__info-item">
|
||
<text class="order-detail__info-label">关闭时间</text>
|
||
<text class="order-detail__info-val">{{ formatTime(order.closeTime) }}</text>
|
||
</view>
|
||
<view v-if="order.status === 'closed' && order.refundReason" class="order-detail__info-item">
|
||
<text class="order-detail__info-label">关闭原因</text>
|
||
<text class="order-detail__info-val order-detail__info-val--warn">{{ order.refundReason }}</text>
|
||
</view>
|
||
<view class="order-detail__info-item">
|
||
<text class="order-detail__info-label">电子凭据</text>
|
||
<text class="order-detail__info-val order-detail__info-val--safe">已通过系统安全校验并存档</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 平台服务保障卡片 -->
|
||
<view class="fc-card order-detail__card order-detail__card--guarantee">
|
||
<view class="order-detail__card-header">
|
||
<text class="order-detail__card-title">平台便民服务保障</text>
|
||
</view>
|
||
<view class="order-detail__guarantee-grid">
|
||
<view class="order-detail__guarantee-col">
|
||
<text class="order-detail__guarantee-icon">🔒</text>
|
||
<text class="order-detail__guarantee-name">资金安全</text>
|
||
<text class="order-detail__guarantee-sub">官方商户支付</text>
|
||
</view>
|
||
<view class="order-detail__guarantee-col">
|
||
<text class="order-detail__guarantee-icon">⚡</text>
|
||
<text class="order-detail__guarantee-name">权益即达</text>
|
||
<text class="order-detail__guarantee-sub">系统秒级到账</text>
|
||
</view>
|
||
<view class="order-detail__guarantee-col">
|
||
<text class="order-detail__guarantee-icon">🛡️</text>
|
||
<text class="order-detail__guarantee-name">同城守护</text>
|
||
<text class="order-detail__guarantee-sub">本地便民服务</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 底部固定操作栏:仅在待支付或已支付时展示核心操作,无多余返回按钮 -->
|
||
<view v-if="showFooter" class="order-detail__footer">
|
||
<view class="order-detail__footer-safe">
|
||
<!-- 右侧操作区:严格统一右对齐,间距规则一致 -->
|
||
<view class="order-detail__footer-actions">
|
||
<!-- 待支付状态:取消订单 + 立即支付 -->
|
||
<template v-if="order.status === 'pending'">
|
||
<view class="order-detail__btn order-detail__btn--cancel" :class="{ 'order-detail__btn--disabled': canceling }" @click="onCancelOrder">
|
||
<text>{{ canceling ? '正在取消…' : '取消订单' }}</text>
|
||
</view>
|
||
<view class="order-detail__btn order-detail__btn--pay" :class="{ 'order-detail__btn--disabled': paying }" @click="onPayOrder">
|
||
<text>{{ paying ? '调起中…' : `立即支付 ¥${formatMoney(order.amount)}` }}</text>
|
||
</view>
|
||
</template>
|
||
|
||
<!-- 已支付状态:核心业务直达 -->
|
||
<template v-else-if="order.status === 'paid'">
|
||
<view class="order-detail__btn order-detail__btn--primary" @click="handleRelatedAction">
|
||
<text>{{ relatedActionText }}</text>
|
||
</view>
|
||
</template>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import FcNavbar from '@/components/fc-navbar/fc-navbar.vue'
|
||
import FcEmpty from '@/components/fc-empty/fc-empty.vue'
|
||
import orderApi from '@/common/api/order.js'
|
||
import { ORDER_TEXT, ORDER_ICON_KEY } from '@/common/constants/ui.js'
|
||
import { formatTime } from '@/common/utils/format.js'
|
||
import { iconUrl, loadUiConfig, uiState } from '@/common/store/ui.js'
|
||
import { pay } from '@/common/utils/pay.js'
|
||
|
||
export default {
|
||
components: { FcNavbar, FcEmpty },
|
||
data() {
|
||
return {
|
||
orderNo: '',
|
||
orderId: 0,
|
||
loading: true,
|
||
order: null,
|
||
remainingSeconds: 0,
|
||
timer: null,
|
||
canceling: false,
|
||
paying: false,
|
||
}
|
||
},
|
||
computed: {
|
||
/** 是否展示底部操作栏(待支付与已支付展示操作,已关闭无冗余按钮) */
|
||
showFooter() {
|
||
if (!this.order) return false
|
||
return ['pending', 'paid'].includes(this.order.status)
|
||
},
|
||
/** 是否存在有效优惠抵扣 */
|
||
hasDiscount() {
|
||
if (!this.order) return false
|
||
const couponAmount = Number(this.order.couponAmount) || 0
|
||
const originAmount = Number(this.order.originAmount) || 0
|
||
const amount = Number(this.order.amount) || 0
|
||
return couponAmount > 0 && originAmount > amount
|
||
},
|
||
/** 状态主标题 */
|
||
statusTitle() {
|
||
if (!this.order) return ''
|
||
const map = {
|
||
pending: '等待付款',
|
||
paid: '支付成功',
|
||
refunding: '退款审核中',
|
||
refunded: '已退款',
|
||
closed: '订单已关闭',
|
||
}
|
||
return map[this.order.status] || this.order.statusText || '订单处理中'
|
||
},
|
||
/** 状态说明文字 */
|
||
statusDesc() {
|
||
if (!this.order) return ''
|
||
if (this.order.status === 'pending') {
|
||
return '订单已创建,请在限定时间内完成付款以锁定权益'
|
||
}
|
||
if (this.order.status === 'paid') {
|
||
return '款项已结算到账,相关特权与服务已即刻为您发放生效'
|
||
}
|
||
if (this.order.status === 'closed') {
|
||
return this.order.refundReason ? `关闭说明:${this.order.refundReason}` : '订单已超时关闭或已由买家主动取消'
|
||
}
|
||
if (this.order.status === 'refunding') {
|
||
return '退款申请正在处理中,资金将原路返回'
|
||
}
|
||
if (this.order.status === 'refunded') {
|
||
return '退款已成功完成'
|
||
}
|
||
return ''
|
||
},
|
||
/** 倒计时格式化文本(分:秒) */
|
||
countdownText() {
|
||
const s = Math.max(0, this.remainingSeconds)
|
||
const m = Math.floor(s / 60)
|
||
const sec = s % 60
|
||
return `${m}分${sec < 10 ? '0' : ''}${sec}秒`
|
||
},
|
||
/** 商品卡片简要副标题 */
|
||
goodsSubTitle() {
|
||
if (!this.order) return ''
|
||
if (this.order.type === 'member') {
|
||
return '同城生态尊享会员套餐'
|
||
}
|
||
if (this.order.type === 'post') {
|
||
return '分类信息发布与展示服务'
|
||
}
|
||
if (this.order.type === 'recharge') {
|
||
return '平台个人账户余额充值'
|
||
}
|
||
if (this.order.type === 'payview') {
|
||
return '便民真实联系人信息查看'
|
||
}
|
||
return '平台便民增值服务'
|
||
},
|
||
/** 帖子审核状态文案 */
|
||
postAuditStatusText() {
|
||
if (!this.order || !this.order.relatedInfo) return '待审核'
|
||
const s = this.order.relatedInfo.auditStatus
|
||
if (s === 1) return '已审核通过(展示中)'
|
||
if (s === 2) return '未通过审核'
|
||
return '系统排队审核中'
|
||
},
|
||
/** 提审防审模式开关 */
|
||
isAudit() {
|
||
// #ifdef MP-WEIXIN
|
||
return uiState.virtualPayAudit !== false
|
||
// #endif
|
||
return false
|
||
},
|
||
/** 已支付状态业务动作按钮文字 */
|
||
relatedActionText() {
|
||
if (!this.order) return '查看业务'
|
||
if (this.isAudit) {
|
||
return this.order.type === 'post' ? '查看我的发布' : '返回同城首页'
|
||
}
|
||
if (this.order.type === 'member') return '前往会员中心'
|
||
if (this.order.type === 'post') return '查看我的发布'
|
||
if (this.order.type === 'recharge') return '前往钱包充值'
|
||
return '查看内容'
|
||
},
|
||
},
|
||
onLoad(options) {
|
||
loadUiConfig()
|
||
if (options.orderNo) {
|
||
this.orderNo = options.orderNo
|
||
}
|
||
if (options.id) {
|
||
this.orderId = Number(options.id) || 0
|
||
}
|
||
this.fetchDetail()
|
||
},
|
||
onUnload() {
|
||
this.clearCountdown()
|
||
},
|
||
methods: {
|
||
iconUrl,
|
||
formatTime,
|
||
/** 金额格式化 */
|
||
formatMoney(val) {
|
||
const n = Number(val) || 0
|
||
return n.toFixed(2)
|
||
},
|
||
/** 订单类型图标 */
|
||
orderIconKey(type) {
|
||
return ORDER_ICON_KEY[type] || 'order-other'
|
||
},
|
||
/** 获取订单详情 */
|
||
async fetchDetail() {
|
||
const token = uni.getStorageSync('token') || uni.getStorageSync('fc_token') || ''
|
||
if (!token) {
|
||
this.loading = false
|
||
this.order = null
|
||
return
|
||
}
|
||
this.loading = true
|
||
try {
|
||
const res = await orderApi.detail({
|
||
orderNo: this.orderNo,
|
||
id: this.orderId,
|
||
})
|
||
this.order = res
|
||
this.orderNo = res && res.orderNo
|
||
this.orderId = res && res.id
|
||
|
||
// 如果是待支付状态且有倒计时
|
||
if (this.order && this.order.status === 'pending') {
|
||
this.remainingSeconds = Number(res.expireSeconds) || 0
|
||
this.startCountdown()
|
||
} else {
|
||
this.clearCountdown()
|
||
}
|
||
} catch (e) {
|
||
// 静默置空,杜绝未登录或接口偶发报错弹出 toast
|
||
this.order = null
|
||
} finally {
|
||
this.loading = false
|
||
}
|
||
},
|
||
/** 启动倒计时定时器 */
|
||
startCountdown() {
|
||
this.clearCountdown()
|
||
if (this.remainingSeconds <= 0) {
|
||
return
|
||
}
|
||
this.timer = setInterval(() => {
|
||
this.remainingSeconds--
|
||
if (this.remainingSeconds <= 0) {
|
||
this.clearCountdown()
|
||
uni.showToast({ title: '订单已超时自动关闭', icon: 'none' })
|
||
this.fetchDetail()
|
||
}
|
||
}, 1000)
|
||
},
|
||
/** 清除倒计时 */
|
||
clearCountdown() {
|
||
if (this.timer) {
|
||
clearInterval(this.timer)
|
||
this.timer = null
|
||
}
|
||
},
|
||
/** 复制订单编号 */
|
||
copyOrderNo() {
|
||
if (!this.order || !this.order.orderNo) return
|
||
uni.setClipboardData({
|
||
data: this.order.orderNo,
|
||
success: () => {
|
||
uni.showToast({ title: '已复制订单号', icon: 'success' })
|
||
},
|
||
})
|
||
},
|
||
/** 主动取消订单 */
|
||
onCancelOrder() {
|
||
if (!this.order || this.canceling) return
|
||
uni.showModal({
|
||
title: '确认取消',
|
||
content: '取消后订单将关闭,锁定的优惠券将自动退还至您的账户,是否确认取消?',
|
||
confirmColor: '#00E070',
|
||
cancelColor: '#666666',
|
||
success: async (res) => {
|
||
if (res.confirm) {
|
||
this.canceling = true
|
||
try {
|
||
await orderApi.cancel({ orderNo: this.order.orderNo })
|
||
uni.showToast({ title: '订单已成功取消', icon: 'success' })
|
||
this.clearCountdown()
|
||
await this.fetchDetail()
|
||
} catch (e) {
|
||
uni.showToast({ title: e.message || '取消失败', icon: 'none' })
|
||
} finally {
|
||
this.canceling = false
|
||
}
|
||
}
|
||
},
|
||
})
|
||
},
|
||
/** 立即支付待支付订单 */
|
||
async onPayOrder() {
|
||
if (!this.order || this.paying) return
|
||
this.paying = true
|
||
try {
|
||
uni.showLoading({ title: '正在调起微信支付…' })
|
||
await pay({
|
||
orderNo: this.order.orderNo,
|
||
payType: this.order.payType || 'wxpay',
|
||
})
|
||
uni.hideLoading()
|
||
uni.showToast({ title: '支付成功', icon: 'success' })
|
||
this.clearCountdown()
|
||
await this.fetchDetail()
|
||
} catch (e) {
|
||
uni.hideLoading()
|
||
uni.showToast({ title: e.message || '支付未完成', icon: 'none' })
|
||
} finally {
|
||
this.paying = false
|
||
}
|
||
},
|
||
/** 业务直达跳转 */
|
||
handleRelatedAction() {
|
||
if (!this.order) return
|
||
const type = this.order.type
|
||
const relatedId = this.order.relatedId
|
||
if (type === 'post') {
|
||
if (relatedId > 0) {
|
||
uni.navigateTo({ url: `/pages/detail/detail?id=${relatedId}` })
|
||
} else {
|
||
uni.navigateTo({ url: '/pages/post/mine' })
|
||
}
|
||
} else if (type === 'member') {
|
||
uni.navigateTo({ url: '/pages/member/index' })
|
||
} else if (type === 'recharge') {
|
||
uni.navigateTo({ url: '/pages/member/recharge' })
|
||
}
|
||
},
|
||
/**
|
||
* 点击左上角返回按钮
|
||
* 优先 navigateBack,若无历史页面或返回失败则重定向至我的订单,绝不卡死失效
|
||
*/
|
||
handleNavBack() {
|
||
const pages = (typeof getCurrentPages === 'function') ? getCurrentPages() : []
|
||
if (pages && pages.length > 1) {
|
||
uni.navigateBack({
|
||
delta: 1,
|
||
fail: () => {
|
||
uni.redirectTo({
|
||
url: '/pages/member/orders',
|
||
fail: () => {
|
||
uni.reLaunch({ url: '/pages/index/index' })
|
||
},
|
||
})
|
||
},
|
||
})
|
||
} else {
|
||
uni.redirectTo({
|
||
url: '/pages/member/orders',
|
||
fail: () => {
|
||
uni.reLaunch({ url: '/pages/index/index' })
|
||
},
|
||
})
|
||
}
|
||
},
|
||
},
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.order-detail {
|
||
min-height: 100vh;
|
||
background: #F2FEF7;
|
||
padding-bottom: 60rpx;
|
||
|
||
&--has-footer {
|
||
padding-bottom: 200rpx;
|
||
}
|
||
}
|
||
|
||
.order-detail__loading {
|
||
padding: 120rpx 0;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
}
|
||
.order-detail__loading-text {
|
||
font-size: $fc-font-sm;
|
||
color: $fc-text-placeholder;
|
||
}
|
||
|
||
/* 顶部 Hero 状态区 */
|
||
.order-detail__hero {
|
||
padding: 36rpx 32rpx 30rpx;
|
||
background: linear-gradient(135deg, #00D26A 0%, #00A854 100%);
|
||
color: #ffffff;
|
||
margin-bottom: 24rpx;
|
||
|
||
&--paid {
|
||
background: linear-gradient(135deg, #00D26A 0%, #00B359 100%);
|
||
}
|
||
&--closed {
|
||
background: linear-gradient(150deg, #4A5B53, #2B3A33);
|
||
}
|
||
&--refunding,
|
||
&--refunded {
|
||
background: linear-gradient(150deg, #6B3434, #3B1B1B);
|
||
}
|
||
}
|
||
.order-detail__hero-content {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: flex-start;
|
||
}
|
||
.order-detail__hero-left {
|
||
flex: 1;
|
||
}
|
||
.order-detail__hero-title {
|
||
display: block;
|
||
font-size: 40rpx;
|
||
font-weight: 700;
|
||
color: #ffffff;
|
||
letter-spacing: 1rpx;
|
||
}
|
||
.order-detail__hero-desc {
|
||
display: block;
|
||
margin-top: 10rpx;
|
||
font-size: $fc-font-xs;
|
||
color: rgba(255, 255, 255, 0.85);
|
||
line-height: 1.5;
|
||
}
|
||
|
||
/* 状态徽章与倒计时 */
|
||
.order-detail__countdown {
|
||
text-align: right;
|
||
background: rgba(0, 0, 0, 0.25);
|
||
padding: 10rpx 20rpx;
|
||
border-radius: $fc-radius;
|
||
border: 1rpx solid rgba(255, 255, 255, 0.2);
|
||
}
|
||
.order-detail__countdown-label {
|
||
display: block;
|
||
font-size: 20rpx;
|
||
color: rgba(255, 255, 255, 0.7);
|
||
}
|
||
.order-detail__countdown-time {
|
||
display: block;
|
||
margin-top: 4rpx;
|
||
font-size: 28rpx;
|
||
font-weight: 700;
|
||
color: #F5A623;
|
||
}
|
||
.order-detail__status-badge {
|
||
padding: 8rpx 20rpx;
|
||
border-radius: $fc-radius-pill;
|
||
background: rgba(0, 224, 112, 0.25);
|
||
border: 1rpx solid #00E070;
|
||
|
||
&--closed {
|
||
background: rgba(255, 255, 255, 0.15);
|
||
border-color: rgba(255, 255, 255, 0.3);
|
||
}
|
||
}
|
||
.order-detail__status-badge-text {
|
||
font-size: 22rpx;
|
||
color: #ffffff;
|
||
font-weight: 600;
|
||
}
|
||
|
||
/* 步骤条 */
|
||
.order-detail__steps {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
margin-top: 32rpx;
|
||
padding-top: 24rpx;
|
||
border-top: 1rpx solid rgba(255, 255, 255, 0.15);
|
||
}
|
||
.order-detail__step {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
.order-detail__step-dot {
|
||
width: 14rpx;
|
||
height: 14rpx;
|
||
border-radius: 50%;
|
||
background: rgba(255, 255, 255, 0.4);
|
||
margin-right: 10rpx;
|
||
}
|
||
.order-detail__step-text {
|
||
font-size: 22rpx;
|
||
color: rgba(255, 255, 255, 0.55);
|
||
}
|
||
.order-detail__step--active {
|
||
.order-detail__step-dot {
|
||
background: #00E070;
|
||
box-shadow: 0 0 8rpx #00E070;
|
||
}
|
||
.order-detail__step-text {
|
||
color: #ffffff;
|
||
font-weight: 600;
|
||
}
|
||
}
|
||
.order-detail__step-line {
|
||
flex: 1;
|
||
height: 2rpx;
|
||
background: rgba(255, 255, 255, 0.2);
|
||
margin: 0 16rpx;
|
||
|
||
&--active {
|
||
background: #00E070;
|
||
}
|
||
}
|
||
|
||
/* 主体容器 */
|
||
.order-detail__body {
|
||
padding: 0 24rpx;
|
||
}
|
||
|
||
/* 卡片容器 */
|
||
.order-detail__card {
|
||
background: #ffffff;
|
||
border-radius: $fc-radius-lg;
|
||
padding: 28rpx;
|
||
margin-bottom: 24rpx;
|
||
box-shadow: 0 4rpx 16rpx rgba(4, 48, 30, 0.04);
|
||
}
|
||
|
||
.order-detail__card-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding-bottom: 18rpx;
|
||
border-bottom: 2rpx solid #F2F6F4;
|
||
}
|
||
.order-detail__card-title {
|
||
font-size: 30rpx;
|
||
font-weight: 700;
|
||
color: #04301E;
|
||
}
|
||
.order-detail__type-pill {
|
||
font-size: 22rpx;
|
||
padding: 4rpx 16rpx;
|
||
background: #E8F8F0;
|
||
color: #04874A;
|
||
border-radius: $fc-radius-pill;
|
||
font-weight: 600;
|
||
}
|
||
|
||
/* 商品卡片主部 */
|
||
.order-detail__goods {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 24rpx 0 20rpx;
|
||
}
|
||
.order-detail__goods-icon {
|
||
width: 104rpx;
|
||
height: 104rpx;
|
||
flex: 0 0 104rpx;
|
||
border-radius: 20rpx;
|
||
background: #EDFAF2;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
.order-detail__goods-info {
|
||
flex: 1;
|
||
margin-left: 20rpx;
|
||
}
|
||
.order-detail__goods-name {
|
||
display: block;
|
||
font-size: 32rpx;
|
||
font-weight: 700;
|
||
color: $fc-text;
|
||
line-height: 1.4;
|
||
}
|
||
.order-detail__goods-desc {
|
||
display: block;
|
||
margin-top: 8rpx;
|
||
font-size: $fc-font-xs;
|
||
color: $fc-text-placeholder;
|
||
}
|
||
|
||
/* 规格与权益扩展清单 */
|
||
.order-detail__meta-list {
|
||
padding: 16rpx 20rpx;
|
||
background: #F9FCFA;
|
||
border-radius: $fc-radius;
|
||
margin-top: 10rpx;
|
||
}
|
||
.order-detail__meta-item {
|
||
display: flex;
|
||
margin-bottom: 12rpx;
|
||
font-size: 24rpx;
|
||
line-height: 1.5;
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
}
|
||
.order-detail__meta-label {
|
||
color: $fc-text-secondary;
|
||
flex: 0 0 140rpx;
|
||
}
|
||
.order-detail__meta-val {
|
||
color: #04301E;
|
||
flex: 1;
|
||
font-weight: 500;
|
||
|
||
&--highlight {
|
||
color: #04874A;
|
||
font-weight: 600;
|
||
}
|
||
}
|
||
.order-detail__tags-wrap {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 10rpx;
|
||
flex: 1;
|
||
}
|
||
.order-detail__tag-item {
|
||
font-size: 20rpx;
|
||
padding: 4rpx 14rpx;
|
||
background: #EAF9F1;
|
||
color: #04874A;
|
||
border-radius: 6rpx;
|
||
font-weight: 500;
|
||
}
|
||
|
||
/* 费用账单明细 */
|
||
.order-detail__bill {
|
||
padding-top: 16rpx;
|
||
}
|
||
.order-detail__bill-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 14rpx;
|
||
font-size: $fc-font-sm;
|
||
color: $fc-text-secondary;
|
||
|
||
&--discount {
|
||
color: #04874A;
|
||
}
|
||
&--total {
|
||
margin-top: 16rpx;
|
||
margin-bottom: 0;
|
||
}
|
||
}
|
||
.order-detail__bill-label {
|
||
font-size: $fc-font-sm;
|
||
}
|
||
.order-detail__bill-val {
|
||
font-size: $fc-font-sm;
|
||
font-weight: 500;
|
||
}
|
||
.order-detail__bill-divider {
|
||
height: 1rpx;
|
||
background: #F0F4F2;
|
||
margin: 16rpx 0;
|
||
}
|
||
.order-detail__bill-total-label {
|
||
font-size: 30rpx;
|
||
font-weight: 700;
|
||
color: #04301E;
|
||
}
|
||
.order-detail__bill-total-val {
|
||
font-size: 40rpx;
|
||
font-weight: 800;
|
||
color: #F5A623;
|
||
}
|
||
|
||
/* 交易溯源信息 */
|
||
.order-detail__info-list {
|
||
padding-top: 14rpx;
|
||
}
|
||
.order-detail__info-item {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 12rpx 0;
|
||
font-size: $fc-font-sm;
|
||
}
|
||
.order-detail__info-label {
|
||
color: $fc-text-placeholder;
|
||
flex: 0 0 160rpx;
|
||
}
|
||
.order-detail__info-val-box {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
.order-detail__info-val {
|
||
color: #04301E;
|
||
font-weight: 500;
|
||
word-break: break-all;
|
||
|
||
&--warn {
|
||
color: $fc-danger;
|
||
}
|
||
&--safe {
|
||
color: #04874A;
|
||
font-size: 22rpx;
|
||
}
|
||
}
|
||
.order-detail__copy-pill {
|
||
margin-left: 16rpx;
|
||
padding: 4rpx 16rpx;
|
||
background: #F2FEF7;
|
||
border: 1rpx solid #00E070;
|
||
border-radius: $fc-radius-pill;
|
||
font-size: 22rpx;
|
||
color: #04301E;
|
||
font-weight: 600;
|
||
}
|
||
|
||
/* 平台保障卡片 */
|
||
.order-detail__card--guarantee {
|
||
background: linear-gradient(145deg, #F9FFFC, #FFFFFF);
|
||
border: 1rpx solid #E1F4E9;
|
||
}
|
||
.order-detail__guarantee-grid {
|
||
display: flex;
|
||
justify-content: space-around;
|
||
padding-top: 20rpx;
|
||
text-align: center;
|
||
}
|
||
.order-detail__guarantee-col {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
}
|
||
.order-detail__guarantee-icon {
|
||
font-size: 36rpx;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
.order-detail__guarantee-name {
|
||
font-size: 24rpx;
|
||
font-weight: 700;
|
||
color: #04301E;
|
||
}
|
||
.order-detail__guarantee-sub {
|
||
font-size: 20rpx;
|
||
color: $fc-text-placeholder;
|
||
margin-top: 4rpx;
|
||
}
|
||
|
||
/* 底部固定操作栏 */
|
||
.order-detail__footer {
|
||
position: fixed;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
background: #ffffff;
|
||
border-top: 1rpx solid #EAEFEA;
|
||
box-shadow: 0 -4rpx 16rpx rgba(4, 48, 30, 0.05);
|
||
z-index: 99;
|
||
}
|
||
.order-detail__footer-safe {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
padding: 16rpx 28rpx;
|
||
padding-bottom: calc(16rpx + constant(safe-area-inset-bottom));
|
||
padding-bottom: calc(16rpx + env(safe-area-inset-bottom));
|
||
}
|
||
|
||
.order-detail__footer-actions {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
}
|
||
|
||
/* 按钮通用规范 */
|
||
.order-detail__btn {
|
||
height: 72rpx;
|
||
line-height: 72rpx;
|
||
padding: 0 32rpx;
|
||
border-radius: $fc-radius-pill;
|
||
font-size: 26rpx;
|
||
font-weight: 600;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-left: 16rpx;
|
||
box-sizing: border-box;
|
||
|
||
&:active {
|
||
opacity: 0.85;
|
||
transform: scale(0.98);
|
||
}
|
||
|
||
&--disabled {
|
||
opacity: 0.6;
|
||
pointer-events: none;
|
||
}
|
||
|
||
/* 次级线框按钮(取消订单) */
|
||
&--cancel {
|
||
background: #FFFFFF;
|
||
border: 1rpx solid #D5E0DA;
|
||
color: #666666;
|
||
}
|
||
|
||
/* 核心主按钮(立即支付) */
|
||
&--pay {
|
||
background: #00E070;
|
||
color: #04301E;
|
||
font-weight: 700;
|
||
box-shadow: 0 4rpx 14rpx rgba(0, 224, 112, 0.35);
|
||
}
|
||
|
||
/* 业务主按钮(前往会员中心等) */
|
||
&--primary {
|
||
background: #00E070;
|
||
color: #04301E;
|
||
font-weight: 700;
|
||
box-shadow: 0 4rpx 14rpx rgba(0, 224, 112, 0.3);
|
||
}
|
||
}
|
||
</style>
|