|
|
|
|
@ -8,17 +8,32 @@
|
|
|
|
|
<!-- 用户信息卡片 -->
|
|
|
|
|
<view class="user-card">
|
|
|
|
|
<view class="user-info">
|
|
|
|
|
<image class="avatar" src="/static/imgs/avatar.png" mode="aspectFill"></image>
|
|
|
|
|
<image
|
|
|
|
|
class="avatar"
|
|
|
|
|
src="/static/imgs/avatar.png"
|
|
|
|
|
mode="aspectFill"
|
|
|
|
|
></image>
|
|
|
|
|
<view class="user-details">
|
|
|
|
|
<view class="username">
|
|
|
|
|
{{ userStore.userInfo.username }}
|
|
|
|
|
<u-icon name="checkmark-circle-fill" color="#ffa500" size="16"></u-icon>
|
|
|
|
|
<u-icon
|
|
|
|
|
name="checkmark-circle-fill"
|
|
|
|
|
color="#ffa500"
|
|
|
|
|
size="16"
|
|
|
|
|
></u-icon>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="user-id">用户ID: {{ userStore.userInfo.id }}</view>
|
|
|
|
|
<view class="membership">
|
|
|
|
|
会员等级: <span v-if="memberInfo.is_vip">{{memberInfo.plan?.name}} (有效期至:
|
|
|
|
|
{{memberInfo.end_at ? dayjs(memberInfo.end_at * 1000).format('YYYY-MM-DD') : ''}})</span><span
|
|
|
|
|
v-else>无</span>
|
|
|
|
|
会员等级:
|
|
|
|
|
<span v-if="memberInfo.is_vip">
|
|
|
|
|
{{ memberInfo.plan?.name }} (有效期至:
|
|
|
|
|
{{
|
|
|
|
|
memberInfo.end_at
|
|
|
|
|
? dayjs(memberInfo.end_at * 1000).format("YYYY-MM-DD")
|
|
|
|
|
: ""
|
|
|
|
|
}})
|
|
|
|
|
</span>
|
|
|
|
|
<span v-else>无</span>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
@ -33,9 +48,17 @@
|
|
|
|
|
<view class="balance-header">
|
|
|
|
|
<view class="balance-label">账户余额</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="balance-amount">¥{{memberInfo.wallet_balance || 0}}</view>
|
|
|
|
|
<view class="balance-amount">
|
|
|
|
|
¥{{ memberInfo.wallet_balance || 0 }}
|
|
|
|
|
</view>
|
|
|
|
|
</div>
|
|
|
|
|
<uv-button type="primary" color="#fff" customStyle="color:#000;width:90px" shape="circle" @click="recharge">
|
|
|
|
|
<uv-button
|
|
|
|
|
type="primary"
|
|
|
|
|
color="#fff"
|
|
|
|
|
customStyle="color:#000;width:90px"
|
|
|
|
|
shape="circle"
|
|
|
|
|
@click="recharge"
|
|
|
|
|
>
|
|
|
|
|
充值
|
|
|
|
|
</uv-button>
|
|
|
|
|
</view>
|
|
|
|
|
@ -43,8 +66,13 @@
|
|
|
|
|
<!-- 会员套餐 -->
|
|
|
|
|
<view class="membership-section">
|
|
|
|
|
<view class="membership-grid">
|
|
|
|
|
<view class="membership-item" :class="{ active: selectedPlan === item.id }" v-for="item in planList"
|
|
|
|
|
:key="item.id" @click="selectPlan(item)">
|
|
|
|
|
<view
|
|
|
|
|
class="membership-item"
|
|
|
|
|
:class="{ active: selectedPlan === item.id }"
|
|
|
|
|
v-for="item in planList"
|
|
|
|
|
:key="item.id"
|
|
|
|
|
@click="selectPlan(item)"
|
|
|
|
|
>
|
|
|
|
|
<view class="tag" v-if="item.tags">{{ item.tags }}</view>
|
|
|
|
|
<view class="plan-name">{{ item.name }}</view>
|
|
|
|
|
<view class="plan-price">¥{{ item.price }}</view>
|
|
|
|
|
@ -72,74 +100,73 @@
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- 支付方式 -->
|
|
|
|
|
<view class="payment-section">
|
|
|
|
|
<!-- 微信支付 -->
|
|
|
|
|
<view class="payment-item" :class="{ active: selectedPayment === 'wallet' }"
|
|
|
|
|
@click="selectPayment('wallet')">
|
|
|
|
|
<view class="payment-info">
|
|
|
|
|
<uv-icon name="empty-coupon" color="#07c160" size="24"></uv-icon>
|
|
|
|
|
<text class="payment-name">钱包支付</text>
|
|
|
|
|
<!-- 底部按钮 -->
|
|
|
|
|
<view class="bottom-section">
|
|
|
|
|
<uv-button type="primary" @click="goToPayment">前往支付</uv-button>
|
|
|
|
|
<!-- <view class="agreement">
|
|
|
|
|
购买前请仔细阅读
|
|
|
|
|
<text class="link" @click="showAgreement">《会员服务协议》</text>
|
|
|
|
|
</view> -->
|
|
|
|
|
</view>
|
|
|
|
|
<uv-icon name="checkmark-circle-fill" :color="selectedPayment === 'wallet' ? '#ff3333' : '#ccc'"
|
|
|
|
|
size="20"></uv-icon>
|
|
|
|
|
|
|
|
|
|
<view class="app-section">
|
|
|
|
|
<!-- 缓存 -->
|
|
|
|
|
<!-- <view class="profile-item" @click="clearCache">
|
|
|
|
|
<view class="item-label">缓存</view>
|
|
|
|
|
<view class="item-content">
|
|
|
|
|
<text class="item-value">{{ cacheSize }}</text>
|
|
|
|
|
<uv-icon name="arrow-right" size="16" color="#ccc"></uv-icon>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="payment-item" :class="{ active: selectedPayment === 'wxpay' }" @click="selectPayment('wxpay')">
|
|
|
|
|
<view class="payment-info">
|
|
|
|
|
<uv-icon name="weixin-fill" color="#07c160" size="24"></uv-icon>
|
|
|
|
|
<text class="payment-name">微信支付</text>
|
|
|
|
|
</view> -->
|
|
|
|
|
|
|
|
|
|
<!-- 用户协议 -->
|
|
|
|
|
<view class="profile-item" @click="viewUserAgreement">
|
|
|
|
|
<view class="item-label">用户协议</view>
|
|
|
|
|
<view class="item-content">
|
|
|
|
|
<uv-icon name="arrow-right" size="16" color="#ccc"></uv-icon>
|
|
|
|
|
</view>
|
|
|
|
|
<uv-icon name="checkmark-circle-fill" :color="selectedPayment === 'wxpay' ? '#ff3333' : '#ccc'"
|
|
|
|
|
size="20"></uv-icon>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- 支付宝支付 - 仅在H5环境显示 -->
|
|
|
|
|
<view v-if="showAlipay" class="payment-item" :class="{ active: selectedPayment === 'alipay' }"
|
|
|
|
|
@click="selectPayment('alipay')">
|
|
|
|
|
<view class="payment-info">
|
|
|
|
|
<uv-icon name="/static/imgs/alipay.png" color="#1677ff" size="24"></uv-icon>
|
|
|
|
|
<text class="payment-name">支付宝</text>
|
|
|
|
|
<!-- 关于我们 -->
|
|
|
|
|
<view class="profile-item" @click="viewAbout">
|
|
|
|
|
<view class="item-label">关于我们</view>
|
|
|
|
|
<view class="item-content">
|
|
|
|
|
<uv-icon name="arrow-right" size="16" color="#ccc"></uv-icon>
|
|
|
|
|
</view>
|
|
|
|
|
<uv-icon name="checkmark-circle-fill" :color="selectedPayment === 'alipay' ? '#ff3333' : '#ccc'"
|
|
|
|
|
size="20"></uv-icon>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="profile-item" @click="logout">
|
|
|
|
|
<view class="item-label">退出登录</view>
|
|
|
|
|
<view class="item-content">
|
|
|
|
|
<uv-icon name="arrow-right" size="16" color="#ccc"></uv-icon>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- 底部按钮 -->
|
|
|
|
|
<view class="bottom-section">
|
|
|
|
|
<uv-button type="primary" size="large" @click="confirmPayment" :loading="paying">
|
|
|
|
|
确认支付
|
|
|
|
|
</uv-button>
|
|
|
|
|
<view class="agreement">
|
|
|
|
|
购买前请仔细阅读
|
|
|
|
|
<text class="link" @click="showAgreement">《会员服务协议》</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- <view class="logout-section">
|
|
|
|
|
<uv-button
|
|
|
|
|
type="error"
|
|
|
|
|
@click="logout"
|
|
|
|
|
:loading="logoutLoading"
|
|
|
|
|
>
|
|
|
|
|
退出登录
|
|
|
|
|
</uv-button>
|
|
|
|
|
</view> -->
|
|
|
|
|
</view>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
import {
|
|
|
|
|
ref,
|
|
|
|
|
onMounted
|
|
|
|
|
} from "vue";
|
|
|
|
|
import {
|
|
|
|
|
onShow,
|
|
|
|
|
onPullDownRefresh
|
|
|
|
|
} from "@dcloudio/uni-app";
|
|
|
|
|
import { ref, onMounted } from "vue";
|
|
|
|
|
import { onShow, onPullDownRefresh } from "@dcloudio/uni-app";
|
|
|
|
|
import HeaderCustom from "/components/HeaderCustom/HeaderCustom.vue";
|
|
|
|
|
import {
|
|
|
|
|
useAuthStore,
|
|
|
|
|
useUserStore
|
|
|
|
|
} from "@/store";
|
|
|
|
|
import { useAuthStore, useUserStore } from "@/store";
|
|
|
|
|
import RPC from "@/utils/request";
|
|
|
|
|
import dayjs from 'dayjs'
|
|
|
|
|
import dayjs from "dayjs";
|
|
|
|
|
|
|
|
|
|
const modal = ref(null);
|
|
|
|
|
const authStore = useAuthStore();
|
|
|
|
|
const userStore = useUserStore();
|
|
|
|
|
|
|
|
|
|
const balance = ref(null)
|
|
|
|
|
const balance = ref(null);
|
|
|
|
|
// const getBalance = () => {
|
|
|
|
|
// RPC.post('/wallet/balance', {
|
|
|
|
|
// user_id: userStore.userInfo.id
|
|
|
|
|
@ -147,46 +174,42 @@
|
|
|
|
|
// balance.value = res.balance_cents || 0
|
|
|
|
|
// })
|
|
|
|
|
// }
|
|
|
|
|
const memberInfo = ref({})
|
|
|
|
|
const memberInfo = ref({});
|
|
|
|
|
const getMemberInfo = () => {
|
|
|
|
|
uni.showLoading();
|
|
|
|
|
RPC.post('/membership/user/info', {
|
|
|
|
|
user_id: userStore.userInfo.id
|
|
|
|
|
}).then(res => {
|
|
|
|
|
memberInfo.value = res || {}
|
|
|
|
|
}).finally(() => {
|
|
|
|
|
uni.hideLoading();
|
|
|
|
|
RPC.post("/membership/user/info", {
|
|
|
|
|
user_id: userStore.userInfo.id,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
.then((res) => {
|
|
|
|
|
memberInfo.value = res || {};
|
|
|
|
|
})
|
|
|
|
|
.finally(() => {
|
|
|
|
|
uni.hideLoading();
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 响应式数据
|
|
|
|
|
const selectedPlan = ref("");
|
|
|
|
|
const selectedPayment = ref("wxpay"); // 默认选中微信支付
|
|
|
|
|
const paying = ref(false);
|
|
|
|
|
const showAlipay = ref(true); // 控制是否显示支付宝选项
|
|
|
|
|
const planList = ref([])
|
|
|
|
|
const planList = ref([]);
|
|
|
|
|
const getPlanList = () => {
|
|
|
|
|
RPC.post('/membership_plan/list', {
|
|
|
|
|
RPC.post("/membership_plan/list", {
|
|
|
|
|
page: 1,
|
|
|
|
|
limit: -1,
|
|
|
|
|
orderby: [{
|
|
|
|
|
sort: 'asc'
|
|
|
|
|
}]
|
|
|
|
|
}).then(res => {
|
|
|
|
|
planList.value = (res.rows || []).filter(item => item.enabled)
|
|
|
|
|
selectedPlan.value = planList.value[0] ? planList.value[0].id : ''
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
orderby: [
|
|
|
|
|
{
|
|
|
|
|
sort: "asc",
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
}).then((res) => {
|
|
|
|
|
planList.value = (res.rows || []).filter((item) => item.enabled);
|
|
|
|
|
selectedPlan.value = planList.value[0] ? planList.value[0].id : "";
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
// 选择会员套餐
|
|
|
|
|
const selectPlan = (plan) => {
|
|
|
|
|
selectedPlan.value = plan.id;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 选择支付方式
|
|
|
|
|
const selectPayment = (payment) => {
|
|
|
|
|
selectedPayment.value = payment;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 编辑资料
|
|
|
|
|
const editProfile = () => {
|
|
|
|
|
uni.navigateTo({
|
|
|
|
|
@ -201,77 +224,8 @@
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 微信支付
|
|
|
|
|
const wechatPay = async (orderInfo) => {
|
|
|
|
|
// #ifdef MP-WEIXIN
|
|
|
|
|
// 微信小程序支付
|
|
|
|
|
try {
|
|
|
|
|
const paymentResult = await uni.requestPayment({
|
|
|
|
|
provider: "wxpay",
|
|
|
|
|
timeStamp: orderInfo.timeStamp,
|
|
|
|
|
nonceStr: orderInfo.nonceStr,
|
|
|
|
|
package: orderInfo.package,
|
|
|
|
|
signType: orderInfo.signType,
|
|
|
|
|
paySign: orderInfo.paySign,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
console.log("微信支付成功:", paymentResult);
|
|
|
|
|
return {
|
|
|
|
|
success: true,
|
|
|
|
|
data: paymentResult
|
|
|
|
|
};
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("微信支付失败:", error);
|
|
|
|
|
if (error.errMsg === "requestPayment:fail cancel") {
|
|
|
|
|
throw new Error("用户取消支付");
|
|
|
|
|
}
|
|
|
|
|
throw new Error("微信支付失败");
|
|
|
|
|
}
|
|
|
|
|
// #endif
|
|
|
|
|
|
|
|
|
|
// #ifdef H5
|
|
|
|
|
// H5微信支付
|
|
|
|
|
// 不在微信环境,跳转到支付页面
|
|
|
|
|
const payUrl = orderInfo.mwebUrl; // 后端返回的H5支付链接
|
|
|
|
|
window.location.href = payUrl;
|
|
|
|
|
return {
|
|
|
|
|
success: true,
|
|
|
|
|
redirect: true
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// #endif
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function showModalAsync(options) {
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
uni.showModal({
|
|
|
|
|
...options,
|
|
|
|
|
success: (res) => {
|
|
|
|
|
resolve(res); // 将用户操作结果传递给 await
|
|
|
|
|
},
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
reject(err); // 处理失败情况
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 支付宝支付(仅H5环境)
|
|
|
|
|
const alipayPay = async (orderInfo) => {
|
|
|
|
|
// #ifdef H5
|
|
|
|
|
// H5支付宝支付
|
|
|
|
|
const payUrl = orderInfo.pay_url; // 后端返回的支付宝H5支付链接
|
|
|
|
|
window.location.href = payUrl;
|
|
|
|
|
return {
|
|
|
|
|
success: true,
|
|
|
|
|
redirect: true
|
|
|
|
|
};
|
|
|
|
|
// #endif
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 确认支付
|
|
|
|
|
const confirmPayment = async () => {
|
|
|
|
|
// 跳转到支付页面
|
|
|
|
|
const goToPayment = () => {
|
|
|
|
|
if (!selectedPlan.value) {
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: "请选择会员套餐",
|
|
|
|
|
@ -280,163 +234,19 @@
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!selectedPayment.value) {
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: "请选择支付方式",
|
|
|
|
|
icon: "none",
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// 获取选中的套餐信息
|
|
|
|
|
const selectedPlanInfo = planList.value.find(
|
|
|
|
|
(plan) => plan.id === selectedPlan.value
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
paying.value = true;
|
|
|
|
|
try {
|
|
|
|
|
// 1. 创建订单参数
|
|
|
|
|
const orderParams = {
|
|
|
|
|
user_id: userStore.userInfo?.id,
|
|
|
|
|
plan_id: selectedPlan.value,
|
|
|
|
|
pay_channel: selectedPayment.value
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
uni.showLoading({
|
|
|
|
|
title: "正在创建订单...",
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 2. 创建订单
|
|
|
|
|
const orderNum = await RPC.post('/membership/order/create', orderParams);
|
|
|
|
|
|
|
|
|
|
// 模拟创建订单返回的数据
|
|
|
|
|
// const orderResult = {
|
|
|
|
|
// orderId: "ORDER_" + Date.now(),
|
|
|
|
|
// amount: orderParams.amount,
|
|
|
|
|
// // 微信支付参数(实际应该由后端返回)
|
|
|
|
|
// wechatPayInfo: {
|
|
|
|
|
// appId: "wx1234567890",
|
|
|
|
|
// timeStamp: String(Date.now()),
|
|
|
|
|
// nonceStr: "random_string_" + Date.now(),
|
|
|
|
|
// package: "prepay_id=wx_prepay_id_123456",
|
|
|
|
|
// signType: "RSA",
|
|
|
|
|
// paySign: "mock_pay_sign_123456",
|
|
|
|
|
// // H5支付链接
|
|
|
|
|
// mwebUrl: "https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx_prepay_id_123456",
|
|
|
|
|
// },
|
|
|
|
|
// // 支付宝支付参数(实际应该由后端返回)
|
|
|
|
|
// alipayInfo: {
|
|
|
|
|
// orderString: "mock_alipay_order_string_123456",
|
|
|
|
|
// payUrl: "https://openapi.alipay.com/gateway.do?mock_pay_url",
|
|
|
|
|
// },
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
uni.hideLoading();
|
|
|
|
|
let orderResult = {}
|
|
|
|
|
// 3. 根据支付方式调用对应的支付方法
|
|
|
|
|
let paymentResult;
|
|
|
|
|
if (selectedPayment.value === "wxpay") {
|
|
|
|
|
// #ifdef MP-WEIXIN
|
|
|
|
|
const res = await uni.login({
|
|
|
|
|
provider: 'weixin'
|
|
|
|
|
})
|
|
|
|
|
orderResult = await RPC.post('/membership/order/pay_by_wechat_mini', {
|
|
|
|
|
code: res.code,
|
|
|
|
|
"order_no": orderNum.order_no
|
|
|
|
|
})
|
|
|
|
|
// #endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// #ifdef H5
|
|
|
|
|
orderResult = await RPC.post('/membership/order/pay_by_wechat_h5', {
|
|
|
|
|
"order_no": orderNum.order_no
|
|
|
|
|
})
|
|
|
|
|
// #endif
|
|
|
|
|
uni.showLoading({
|
|
|
|
|
title: "正在跳转微信支付...",
|
|
|
|
|
});
|
|
|
|
|
console.log('orderResult', orderResult)
|
|
|
|
|
if(1==1) return
|
|
|
|
|
paymentResult = await wechatPay(orderResult);
|
|
|
|
|
} else if (selectedPayment.value === "alipay") {
|
|
|
|
|
orderResult = await RPC.post('/membership/order/pay_by_alipay', {
|
|
|
|
|
"order_no": orderNum.order_no
|
|
|
|
|
})
|
|
|
|
|
uni.showLoading({
|
|
|
|
|
title: "正在跳转支付宝...",
|
|
|
|
|
});
|
|
|
|
|
console.log('orderResult', orderResult)
|
|
|
|
|
paymentResult = await alipayPay(orderResult);
|
|
|
|
|
} else if (selectedPayment.value === 'wallet') {
|
|
|
|
|
const res = await showModalAsync({
|
|
|
|
|
title: '确认支付',
|
|
|
|
|
content: '确认使用钱包余额支付?'
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 同步判断逻辑
|
|
|
|
|
if (res.confirm) {
|
|
|
|
|
paymentResult = await RPC.post('/membership/order/pay_by_wallet', {
|
|
|
|
|
order_no: orderNum.order_no
|
|
|
|
|
})
|
|
|
|
|
console.log('paymentResult', paymentResult)
|
|
|
|
|
} else if (res.cancel) {
|
|
|
|
|
console.log('用户点击了取消');
|
|
|
|
|
paymentResult={success:false}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uni.hideLoading();
|
|
|
|
|
console.log('paymentResult111',paymentResult)
|
|
|
|
|
// 4. 处理支付结果
|
|
|
|
|
if (paymentResult?.success) {
|
|
|
|
|
if (paymentResult.redirect) {
|
|
|
|
|
// H5跳转支付,不需要额外处理
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: "正在跳转支付页面...",
|
|
|
|
|
icon: "loading",
|
|
|
|
|
duration: 2000,
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
// 支付成功
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: "支付成功",
|
|
|
|
|
icon: "success",
|
|
|
|
|
});
|
|
|
|
|
setTimeout(()=>{
|
|
|
|
|
getMemberInfo()
|
|
|
|
|
},500)
|
|
|
|
|
}, 1000)
|
|
|
|
|
// getMemberInfo()
|
|
|
|
|
|
|
|
|
|
// 延迟跳转到订单页面或刷新用户信息
|
|
|
|
|
// setTimeout(() => {
|
|
|
|
|
// 可以跳转到订单详情页面
|
|
|
|
|
// uni.navigateTo({
|
|
|
|
|
// url: `/pages/order-detail/order-detail?orderId=${orderResult.orderId}`,
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
// 或者刷新当前页面的用户信息
|
|
|
|
|
// loadUserInfo();
|
|
|
|
|
// }, 1500);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
uni.hideLoading();
|
|
|
|
|
console.error("支付失败:", error);
|
|
|
|
|
console.log('error', error)
|
|
|
|
|
let errorMessage = "支付失败,请重试";
|
|
|
|
|
if (error.message === "用户取消支付") {
|
|
|
|
|
errorMessage = "支付已取消";
|
|
|
|
|
} else if (error.message) {
|
|
|
|
|
errorMessage = error.message;
|
|
|
|
|
|
|
|
|
|
} else if (error) {
|
|
|
|
|
errorMessage = error
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: errorMessage,
|
|
|
|
|
icon: "none",
|
|
|
|
|
// 跳转到支付页面,传递套餐信息
|
|
|
|
|
uni.navigateTo({
|
|
|
|
|
url: `/pagesA/payment/payment?planId=${
|
|
|
|
|
selectedPlan.value
|
|
|
|
|
}&planName=${encodeURIComponent(selectedPlanInfo?.name || "")}&planPrice=${
|
|
|
|
|
selectedPlanInfo?.price || 0
|
|
|
|
|
}`,
|
|
|
|
|
});
|
|
|
|
|
} finally {
|
|
|
|
|
paying.value = false;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 显示协议
|
|
|
|
|
@ -446,118 +256,66 @@
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 检查支付结果(用于H5支付回调)
|
|
|
|
|
const checkPaymentResult = async (orderId) => {
|
|
|
|
|
try {
|
|
|
|
|
// 调用后端接口检查支付结果
|
|
|
|
|
// const result = await RPC.get(`/api/order/check-payment/${orderId}`);
|
|
|
|
|
|
|
|
|
|
// 模拟检查结果
|
|
|
|
|
const result = {
|
|
|
|
|
success: true,
|
|
|
|
|
status: "paid", // paid, pending, failed
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (result.status === "paid") {
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: "支付成功",
|
|
|
|
|
icon: "success",
|
|
|
|
|
// 页面挂载时获取套餐列表
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
// getPlanList();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 更新用户信息或跳转到成功页面
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
uni.navigateTo({
|
|
|
|
|
url: `/pages/order-detail/order-detail?orderId=${orderId}`,
|
|
|
|
|
});
|
|
|
|
|
}, 1500);
|
|
|
|
|
} else if (result.status === "failed") {
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: "支付失败",
|
|
|
|
|
icon: "none",
|
|
|
|
|
// 页面显示时获取会员信息
|
|
|
|
|
onShow(() => {
|
|
|
|
|
getPlanList();
|
|
|
|
|
getMemberInfo();
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: "支付处理中,请稍后查看订单状态",
|
|
|
|
|
icon: "none",
|
|
|
|
|
onPullDownRefresh(() => {
|
|
|
|
|
getPlanList();
|
|
|
|
|
// getBalance()
|
|
|
|
|
getMemberInfo();
|
|
|
|
|
uni.stopPullDownRefresh();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("检查支付结果失败:", error);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 页面显示时检查是否有支付回调参数
|
|
|
|
|
const handlePaymentCallback = () => {
|
|
|
|
|
// #ifdef H5
|
|
|
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
|
|
|
const orderId = urlParams.get("orderId");
|
|
|
|
|
const payResult = urlParams.get("payResult");
|
|
|
|
|
|
|
|
|
|
if (orderId && payResult) {
|
|
|
|
|
// 清理URL参数
|
|
|
|
|
const url = new URL(window.location);
|
|
|
|
|
url.searchParams.delete("orderId");
|
|
|
|
|
url.searchParams.delete("payResult");
|
|
|
|
|
window.history.replaceState({}, document.title, url.pathname + url.search);
|
|
|
|
|
|
|
|
|
|
// 检查支付结果
|
|
|
|
|
if (payResult === "success") {
|
|
|
|
|
checkPaymentResult(orderId);
|
|
|
|
|
} else {
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: "支付失败或取消",
|
|
|
|
|
icon: "none",
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// #endif
|
|
|
|
|
};
|
|
|
|
|
const logoutLoading = ref(false)
|
|
|
|
|
|
|
|
|
|
// 检查当前环境并设置支付选项
|
|
|
|
|
const checkEnvironment = () => {
|
|
|
|
|
// #ifdef MP-WEIXIN
|
|
|
|
|
// 微信小程序环境,隐藏支付宝选项,默认选择微信支付
|
|
|
|
|
showAlipay.value = false;
|
|
|
|
|
// #endif
|
|
|
|
|
|
|
|
|
|
// #ifdef H5
|
|
|
|
|
// H5环境,显示所有支付选项
|
|
|
|
|
showAlipay.value = true;
|
|
|
|
|
// 如果在微信浏览器内,默认选择微信支付
|
|
|
|
|
const ua = navigator.userAgent.toLowerCase();
|
|
|
|
|
const isWechat = ua.indexOf("micromessenger") !== -1;
|
|
|
|
|
// #endif
|
|
|
|
|
};
|
|
|
|
|
const logout = () => {
|
|
|
|
|
uni.showModal({
|
|
|
|
|
title: "退出登录",
|
|
|
|
|
content: "确定要退出登录吗?",
|
|
|
|
|
success: (res) => {
|
|
|
|
|
if (res.confirm) {
|
|
|
|
|
logoutLoading.value = true;
|
|
|
|
|
|
|
|
|
|
// 页面挂载时处理支付回调和环境检查
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
checkEnvironment();
|
|
|
|
|
getPlanList()
|
|
|
|
|
// handlePaymentCallback();
|
|
|
|
|
// 模拟退出登录
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
authStore.signOut();
|
|
|
|
|
logoutLoading.value = false;
|
|
|
|
|
|
|
|
|
|
// 清除用户信息和token
|
|
|
|
|
// authStore.logout()
|
|
|
|
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: "已退出登录",
|
|
|
|
|
icon: "success",
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 页面显示时也检查支付回调(从其他页面返回时)
|
|
|
|
|
onShow(() => {
|
|
|
|
|
handlePaymentCallback();
|
|
|
|
|
// getBalance()
|
|
|
|
|
getMemberInfo()
|
|
|
|
|
// 跳转到登录页
|
|
|
|
|
uni.reLaunch({
|
|
|
|
|
url: "/pages/login/login",
|
|
|
|
|
});
|
|
|
|
|
onPullDownRefresh(() => {
|
|
|
|
|
getPlanList()
|
|
|
|
|
// getBalance()
|
|
|
|
|
getMemberInfo()
|
|
|
|
|
uni.stopPullDownRefresh();
|
|
|
|
|
}, 1000);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
.container {
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
background: linear-gradient(180deg, #7b9cdb 0%, #f8f8f8 40%);
|
|
|
|
|
padding-bottom: 120px;
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
// padding-bottom: 120px;
|
|
|
|
|
|
|
|
|
|
/* #ifdef H5 */
|
|
|
|
|
padding-bottom: 170px;
|
|
|
|
|
// padding-bottom: 170px;
|
|
|
|
|
/* H5环境下需要更多空间 (底部按钮高度 + tabBar高度 + 间距) */
|
|
|
|
|
/* #endif */
|
|
|
|
|
}
|
|
|
|
|
@ -719,43 +477,76 @@
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.payment-section {
|
|
|
|
|
margin: 0 16px 24px;
|
|
|
|
|
.bottom-section {
|
|
|
|
|
// position: fixed;
|
|
|
|
|
// bottom: 0;
|
|
|
|
|
// left: 0;
|
|
|
|
|
// right: 0;
|
|
|
|
|
background: white;
|
|
|
|
|
// padding: 16px;
|
|
|
|
|
margin: 16px;
|
|
|
|
|
border-top: 1px solid #e5e5e5;
|
|
|
|
|
|
|
|
|
|
/* #ifdef H5 */
|
|
|
|
|
bottom: 50px;
|
|
|
|
|
/* H5环境下给tabBar留出空间 */
|
|
|
|
|
/* #endif */
|
|
|
|
|
|
|
|
|
|
.agreement {
|
|
|
|
|
text-align: center;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
color: #999;
|
|
|
|
|
margin-top: 12px;
|
|
|
|
|
|
|
|
|
|
.link {
|
|
|
|
|
color: #4285f4;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.app-section {
|
|
|
|
|
background: white;
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
margin: 16px;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
|
|
|
|
.payment-item {
|
|
|
|
|
.profile-item {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
background: white;
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
padding: 16px;
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
border: 1px solid #e5e5e5;
|
|
|
|
|
transition: all 0.3s;
|
|
|
|
|
border-bottom: 1px solid #f0f0f0;
|
|
|
|
|
|
|
|
|
|
&.active {
|
|
|
|
|
border-color: #4285f4;
|
|
|
|
|
background-color: #f0f7ff;
|
|
|
|
|
&:last-child {
|
|
|
|
|
border-bottom: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&:last-child {
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
.item-label {
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
color: #333;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.payment-info {
|
|
|
|
|
.item-content {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 12px;
|
|
|
|
|
gap: 8px;
|
|
|
|
|
|
|
|
|
|
.avatar {
|
|
|
|
|
width: 40px;
|
|
|
|
|
height: 40px;
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.payment-name {
|
|
|
|
|
.item-value {
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
color: #333;
|
|
|
|
|
color: #666;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.bottom-section {
|
|
|
|
|
.logout-section {
|
|
|
|
|
position: fixed;
|
|
|
|
|
bottom: 0;
|
|
|
|
|
left: 0;
|
|
|
|
|
@ -768,16 +559,5 @@
|
|
|
|
|
bottom: 50px;
|
|
|
|
|
/* H5环境下给tabBar留出空间 */
|
|
|
|
|
/* #endif */
|
|
|
|
|
|
|
|
|
|
.agreement {
|
|
|
|
|
text-align: center;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
color: #999;
|
|
|
|
|
margin-top: 12px;
|
|
|
|
|
|
|
|
|
|
.link {
|
|
|
|
|
color: #4285f4;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|