Files
----/前端源码/uni-app/components/examples/PaymentExample.vue

368 lines
9.7 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>
<view class="payment-example">
<view class="example-header">
<text class="example-title">支付功能示例</text>
</view>
<!-- 示例1: 购买报告 -->
<view class="example-section">
<text class="example-section-title">示例1: 购买命名报告</text>
<view class="example-card">
<view class="example-card-content">
<text class="example-card-name">张三命名报告</text>
<text class="example-card-desc">包含六维分析周易卦象等</text>
<text class="example-card-price">¥99</text>
</view>
<view class="example-card-btn" @click="buyReport">
<text class="example-card-btn-text">立即购买</text>
</view>
</view>
</view>
<!-- 示例2: 推广合伙人 -->
<view class="example-section">
<text class="example-section-title">示例2: 开通推广合伙人</text>
<view class="example-card">
<view class="example-card-content">
<text class="example-card-name">推广合伙人权益</text>
<text class="example-card-desc">开启睡后收入之旅</text>
<text class="example-card-price">¥99</text>
</view>
<view class="example-card-btn" @click="buyPartner">
<text class="example-card-btn-text">立即开通</text>
</view>
</view>
</view>
<!-- 示例3: 测试支付 -->
<view class="example-section">
<text class="example-section-title">示例3: 测试支付0.01</text>
<view class="example-card">
<view class="example-card-content">
<text class="example-card-name">测试商品</text>
<text class="example-card-desc">用于测试支付流程</text>
<text class="example-card-price">¥0.01</text>
</view>
<view class="example-card-btn" @click="testPay">
<text class="example-card-btn-text">测试支付</text>
</view>
</view>
</view>
<!-- 订单列表 -->
<view class="example-section">
<text class="example-section-title">最近订单</text>
<view v-if="orders.length === 0" class="example-empty">
<text class="example-empty-text">暂无订单</text>
</view>
<view v-else class="example-orders">
<view v-for="order in orders" :key="order.out_trade_no" class="example-order">
<view class="example-order-info">
<text class="example-order-name">{{ order.business_type }}</text>
<text class="example-order-time">{{ order.paid_at || '待支付' }}</text>
</view>
<view class="example-order-right">
<text class="example-order-amount">¥{{ order.total_amount }}</text>
<text class="example-order-status" :class="`status-${order.status}`">
{{ getStatusText(order.status) }}
</text>
</view>
</view>
</view>
</view>
<!-- 支付弹窗 -->
<PaymentModal :visible="showPayment" :product-name="paymentInfo.productName"
:product-desc="paymentInfo.productDesc" :product-icon="paymentInfo.productIcon" :amount="paymentInfo.amount"
:business-type="paymentInfo.businessType" :business-id="paymentInfo.businessId" @close="showPayment = false"
@success="handlePaymentSuccess" @fail="handlePaymentFail" />
</view>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue';
import PaymentModal from '../PaymentModal.vue';
import type { QueryOrderResponse } from '@/api/types';
declare const uni: any;
const showPayment = ref(false);
const orders = ref<QueryOrderResponse[]>([]);
const paymentInfo = reactive({
productName: '',
productDesc: '',
productIcon: '📦',
amount: 0,
businessType: '',
businessId: 0
});
// 购买报告
const buyReport = () => {
paymentInfo.productName = '张三命名报告';
paymentInfo.productDesc = '包含六维分析、周易卦象、开运建议等';
paymentInfo.productIcon = '📊';
paymentInfo.amount = 99;
paymentInfo.businessType = 'naming_report';
paymentInfo.businessId = 123;
showPayment.value = true;
};
// 购买推广合伙人
const buyPartner = () => {
paymentInfo.productName = '推广合伙人权益';
paymentInfo.productDesc = '开启睡后收入之旅';
paymentInfo.productIcon = '💼';
paymentInfo.amount = 99;
paymentInfo.businessType = 'partner_apply';
paymentInfo.businessId = 456;
showPayment.value = true;
};
// 测试支付
const testPay = () => {
paymentInfo.productName = '测试商品';
paymentInfo.productDesc = '用于测试支付流程';
paymentInfo.productIcon = '🧪';
paymentInfo.amount = 0.01;
paymentInfo.businessType = 'test';
paymentInfo.businessId = 999;
showPayment.value = true;
};
// 支付成功回调
const handlePaymentSuccess = (outTradeNo: string) => {
// Web环境使用alertuni-app环境使用showModal
if (typeof uni?.showModal === 'function') {
uni.showModal({
title: '支付成功',
content: `订单号:${outTradeNo}\n感谢您的购买`,
showCancel: false,
success: () => {
// 刷新订单列表
loadOrders();
}
});
} else {
// Web环境使用原生alert
alert(`支付成功\n\n订单号${outTradeNo}\n感谢您的购买`);
loadOrders();
}
};
// 支付失败回调
const handlePaymentFail = (message: string) => {
console.log('支付失败:', message);
// Web环境使用alertuni-app环境使用showModal
if (typeof uni?.showModal === 'function') {
uni.showModal({
title: '支付失败',
content: message || '支付过程中出现问题,请重试',
showCancel: false
});
} else {
// Web环境使用原生alert
alert(`支付失败\n\n${message || '支付过程中出现问题,请重试'}`);
}
};
// 加载订单列表(示例数据)
const loadOrders = () => {
// 实际应该调用API获取订单列表
orders.value = [
{
out_trade_no: 'ORDER_001',
status: 'paid',
total_amount: 99,
paid_amount: 99,
paid_at: '2026-01-15 10:30:00',
business_type: 'naming_report',
business_id: 123
},
{
out_trade_no: 'ORDER_002',
status: 'pending',
total_amount: 99,
business_type: 'partner_apply',
business_id: 456
}
];
};
// 获取状态文本
const getStatusText = (status: string) => {
const statusMap: Record<string, string> = {
pending: '待支付',
paid: '已支付',
cancelled: '已取消',
refunded: '已退款'
};
return statusMap[status] || status;
};
onMounted(() => {
loadOrders();
});
</script>
<style scoped>
.payment-example {
padding: 32rpx;
background-color: #f5f5f5;
min-height: 100vh;
}
.example-header {
margin-bottom: 32rpx;
}
.example-title {
font-size: 40rpx;
font-weight: 700;
color: #2c2c2c;
}
.example-section {
margin-bottom: 32rpx;
}
.example-section-title {
font-size: 28rpx;
font-weight: 700;
color: #2c2c2c;
margin-bottom: 16rpx;
display: block;
}
.example-card {
background-color: #fff;
border-radius: 16rpx;
padding: 24rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.example-card-content {
display: flex;
flex-direction: column;
gap: 8rpx;
margin-bottom: 16rpx;
}
.example-card-name {
font-size: 32rpx;
font-weight: 700;
color: #2c2c2c;
}
.example-card-desc {
font-size: 24rpx;
color: #999;
}
.example-card-price {
font-size: 40rpx;
font-weight: 700;
color: #8b2323;
margin-top: 8rpx;
}
.example-card-btn {
width: 100%;
padding: 20rpx 0;
background-color: #8b2323;
border-radius: 12rpx;
display: flex;
justify-content: center;
}
.example-card-btn-text {
font-size: 28rpx;
font-weight: 700;
color: #fff;
}
.example-empty {
text-align: center;
padding: 64rpx 0;
}
.example-empty-text {
font-size: 24rpx;
color: #999;
}
.example-orders {
display: flex;
flex-direction: column;
gap: 16rpx;
}
.example-order {
background-color: #fff;
border-radius: 16rpx;
padding: 24rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
.example-order-info {
display: flex;
flex-direction: column;
gap: 8rpx;
}
.example-order-name {
font-size: 28rpx;
color: #2c2c2c;
font-weight: 500;
}
.example-order-time {
font-size: 20rpx;
color: #999;
}
.example-order-right {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 8rpx;
}
.example-order-amount {
font-size: 32rpx;
font-weight: 700;
color: #2c2c2c;
}
.example-order-status {
font-size: 20rpx;
padding: 4rpx 12rpx;
border-radius: 8rpx;
}
.status-paid {
background-color: #e8f5e9;
color: #4caf50;
}
.status-pending {
background-color: #fff3e0;
color: #ff9800;
}
.status-cancelled {
background-color: #f5f5f5;
color: #999;
}
.status-refunded {
background-color: #ffebee;
color: #f44336;
}
</style>