| | |
| | | const items = computed(() => detail.value?.items || []) |
| | | const payments = computed(() => detail.value?.payments || []) |
| | | const refunds = computed(() => detail.value?.refunds || []) |
| | | const discountAmount = computed(() => Math.max(0, Number(detail.value?.orderAmount || 0) - Number(detail.value?.subsidyAmount || 0) - Number(detail.value?.payAmount || 0))) |
| | | const previewVisible = ref(false) |
| | | const previewUrl = ref('') |
| | | const talentDiscountAmount = computed(() => Math.max(0, Number(detail.value?.orderAmount || 0) - Number(detail.value?.basePayAmount ?? detail.value?.orderAmount ?? 0))) |
| | | const couponAmount = computed(() => Math.max(0, Number(detail.value?.couponAmount || 0))) |
| | | const talentDiscountRate = computed(() => { |
| | | const original = Number(detail.value?.orderAmount || 0) |
| | | const base = Number(detail.value?.basePayAmount ?? original) |
| | | if (!original || !base) return '-' |
| | | return `${(base / original * 10).toFixed(1).replace(/\.0$/, '')}折` |
| | | }) |
| | | |
| | | function money(value: unknown) { |
| | | if (value === null || value === undefined || value === '') return '-' |
| | |
| | | |
| | | function paymentStatus(value: string) { |
| | | return ({ pending: '待支付', processing: '支付中', paid: '支付成功', failed: '支付失败', closed: '已关闭' } as Record<string, string>)[value] || value || '-' |
| | | } |
| | | |
| | | function previewImage(url: string) { |
| | | if (!url) return |
| | | previewUrl.value = url |
| | | previewVisible.value = true |
| | | } |
| | | |
| | | function paymentTime(payment: Detail) { |
| | | if (detail.value?.orderStatus === 0 || payment.status === 'pending') return '-' |
| | | return dateTime(payment.paidAt) |
| | | } |
| | | |
| | | function refundStatus(value: number) { |
| | |
| | | <el-table-column prop="name" label="商品名称" min-width="220" show-overflow-tooltip /> |
| | | <el-table-column label="封面图" width="130" align="center"> |
| | | <template #default="{ row }"> |
| | | <el-image v-if="row.coverUrl" :src="row.coverUrl" fit="cover" class="product-cover" preview-teleported /> |
| | | <el-image v-if="row.coverUrl" :src="row.coverUrl" fit="cover" class="product-cover" :preview-src-list="[row.coverUrl]" preview-teleported /> |
| | | <span v-else class="empty-cover">-</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="商品金额" min-width="130" align="right"> |
| | | <template #default="{ row }">{{ money(row.amount) }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" width="100" align="center"> |
| | | <template #default="{ row }"> |
| | | <el-button link type="primary" :disabled="!row.coverUrl" @click="previewImage(row.coverUrl)">查看</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </section> |
| | |
| | | <div><span>商品金额</span><strong>{{ money(detail.orderAmount) }}</strong></div> |
| | | <div><span>商品数量</span><strong>{{ items.length }}</strong></div> |
| | | <div><span>小计</span><strong>{{ money(detail.orderAmount) }}</strong></div> |
| | | <div><span>优惠信息</span><strong>{{ discountAmount ? `优惠 ¥${(discountAmount / 100).toFixed(2)}` : '-' }}</strong></div> |
| | | <div><span>优惠金额</span><strong>{{ discountAmount ? `-¥${(discountAmount / 100).toFixed(2)}` : '-' }}</strong></div> |
| | | <div><span>政府补贴</span><strong>{{ money(detail.subsidyAmount) }}</strong></div> |
| | | <div class="discount-summary-row"> |
| | | <span>优惠信息</span> |
| | | <div class="discount-summary-content"> |
| | | <div><span>人才折扣</span><strong>{{ talentDiscountRate }}</strong><span>折扣金额</span><strong class="discount-value">{{ talentDiscountAmount ? `-¥${(talentDiscountAmount / 100).toFixed(2)}` : '-' }}</strong></div> |
| | | <div v-if="detail.couponName || couponAmount"><span>商品优惠</span><strong>{{ detail.couponName || '-' }}</strong><span>优惠金额</span><strong class="discount-value">{{ couponAmount ? `-¥${(couponAmount / 100).toFixed(2)}` : '-' }}</strong></div> |
| | | <div><span>补贴金额</span><strong>{{ money(detail.subsidyAmount) }}</strong></div> |
| | | </div> |
| | | </div> |
| | | <div><span>实际应付</span><strong class="amount-strong">{{ money(detail.payAmount) }}</strong></div> |
| | | <div><span>下单时间</span><strong>{{ dateTime(detail.createdAt) }}</strong></div> |
| | | <div><span>核销时间</span><strong>{{ dateTime(detail.verifyTime) }}</strong></div> |
| | |
| | | <h3>支付信息</h3> |
| | | <div v-if="payments.length" class="records-stack"> |
| | | <div v-for="payment in payments" :key="payment.paymentNo" class="info-card info-grid payment-grid"> |
| | | <div><span>支付时间</span><strong>{{ dateTime(payment.paidAt || payment.createdAt) }}</strong></div> |
| | | <div><span>支付时间</span><strong>{{ paymentTime(payment) }}</strong></div> |
| | | <div><span>支付方式</span><strong>{{ payment.provider === 'HUIFU' ? '微信支付' : payment.provider || '-' }}</strong></div> |
| | | <div><span>支付流水号</span><strong>{{ payment.providerTransactionNo || payment.paymentNo || '-' }}</strong></div> |
| | | <div><span>支付金额</span><strong class="amount-strong">{{ money(payment.amount) }}</strong></div> |
| | |
| | | <el-button v-if="canRefund()" type="danger" plain @click="refund">退款</el-button> |
| | | </div> |
| | | </template> |
| | | <el-dialog v-model="previewVisible" title="封面图预览" width="640px" destroy-on-close> |
| | | <el-image v-if="previewUrl" :src="previewUrl" fit="contain" class="order-preview-image" /> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | .detail-items { margin-top: 10px; } |
| | | .detail-items :deep(th.el-table__cell) { color: #1d2129; font-weight: 600; background: #f3f4f6; } |
| | | .product-cover { width: 48px; height: 38px; vertical-align: middle; } |
| | | .order-preview-image { display: block; width: 100%; max-height: 520px; } |
| | | .empty-cover { color: #86909c; } |
| | | .order-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } |
| | | .order-grid div:nth-child(5), .order-grid div:nth-child(9) { grid-column: span 2; } |
| | | .discount-summary-row { grid-column: 1 / -1; display: flex; align-items: flex-start !important; gap: 14px !important; } |
| | | .discount-summary-content { display: grid; flex: 1; gap: 10px; } |
| | | .discount-summary-content > div { display: grid; grid-template-columns: 72px minmax(110px, 1fr) 72px minmax(100px, 1fr); align-items: baseline; gap: 10px; } |
| | | .discount-summary-content span { color: #4e5969; font-size: 13px; } |
| | | .discount-summary-content strong { color: #1d2129; font-size: 13px; font-weight: 500; } |
| | | .discount-summary-content .discount-value { color: #d99000; } |
| | | .payment-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } |
| | | .refund-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } |
| | | .amount-strong { color: #1d2129; font-weight: 600 !important; } |