feat: 增加支付宝在线支付、套餐订购弹窗、会员权益、支持模型展示等

This commit is contained in:
Gsh
2025-08-14 00:26:39 +08:00
parent 48d8c528f6
commit ee6b4827fa
11 changed files with 1564 additions and 38 deletions

View File

@@ -0,0 +1,201 @@
<script setup lang="ts">
import { ElButton, ElDivider } from 'element-plus';
import { onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
import { getUserInfo } from '@/api';
import {
SSO_CLIENT_LOGIN_AGAIN,
SSO_SEVER_URL,
} from '@/config/sso.ts';
import { useUserStore } from '@/stores';
import { useSessionStore } from '@/stores/modules/session.ts';
const userStore = useUserStore();
const router = useRouter();
const sessionStore = useSessionStore();
interface PayResult {
out_trade_no: string;
trade_no: string;
total_amount: string;
[key: string]: string;
}
const payResult = ref<PayResult>({
out_trade_no: '',
trade_no: '',
total_amount: '',
});
function parseUrlParams() {
const params = new URLSearchParams(window.location.search);
const result: PayResult = {
out_trade_no: params.get('out_trade_no') || '',
trade_no: params.get('trade_no') || '',
total_amount: params.get('total_amount') || '',
};
params.forEach((value, key) => {
if (!(key in result))
result[key] = value;
});
payResult.value = result;
}
onMounted(() => {
parseUrlParams();
});
function handleThirdPartyLogin(type: any) {
const redirectUri = encodeURIComponent(`${window.location.origin}/chat`);
console.log('cccc', type);
const popup = window.open(
`${SSO_SEVER_URL}/login?client_id=${type}&redirect_uri=${redirectUri}`,
'SSOLogin',
'width=1000,height=800',
);
// 使用标志位防止重复执行
let isHandled = false;
const messageHandler = async (event: any) => {
if (event.origin === new URL(SSO_SEVER_URL).origin
&& event.data.type === 'SSO_LOGIN_SUCCESS'
&& !isHandled) {
isHandled = true;
try {
// 清理监听
window.removeEventListener('message', messageHandler);
const { token, refreshToken } = event.data;
userStore.setToken(token, refreshToken);
const resUserInfo = await getUserInfo();
userStore.setUserInfo(resUserInfo.data);
// 关闭弹窗
if (popup && !popup.closed) {
popup.close();
}
// 后续逻辑
ElMessage.success('登录成功');
userStore.closeLoginDialog();
await sessionStore.requestSessionList(1, true);
await router.replace('/');
}
catch (error) {
console.error('登录处理失败:', error);
ElMessage.error('登录失败');
}
}
};
// 先移除旧监听,再添加新监听
window.removeEventListener('message', messageHandler);
window.addEventListener('message', messageHandler);
// 超时自动清理
// setTimeout(() => {
// if (!isHandled) {
// window.removeEventListener('message', messageHandler);
// if (popup && !popup.closed)
// popup.close();
// ElMessage.warning('登录超时');
// }
// }, 60 * 1000); // 60分钟超时关闭
}
function toHome() {
router.replace('/');
}
</script>
<template>
<div class="pay-result-container flex flex-col items-center justify-center p-6 min-h-screen bg-gray-50">
<div class="card bg-white rounded-xl shadow-lg p-8 max-w-md w-full text-center">
<!-- 成功提示 -->
<h1 class="text-4xl font-extrabold mb-4 text-orange-500">
🎉 恭喜
</h1>
<p class="text-xl font-semibold mb-6">
您已成为尊贵的 <span class="text-orange-500">YixinAI VIP</span>
</p>
<!-- 订单信息卡片 -->
<div class="order-info bg-gray-100 p-4 rounded-lg mb-4 text-left">
<p class="mb-2">
<strong>商户订单号</strong>{{ payResult.out_trade_no }}
</p>
<p class="mb-2">
<strong>支付交易号</strong>{{ payResult.trade_no }}
</p>
<p class="mb-0">
<strong>支付金额</strong><span class="text-red-500 font-bold">¥{{ payResult.total_amount }}</span>
</p>
</div>
<!-- 更多信息提示 -->
<div class="mb-6 text-gray-600 text-sm">
更多订单信息和会员详情<br>请前往 <strong>用户中心 充值记录</strong> 查看<br>
用户中心在首页右上角个人头像点击下拉菜单
</div>
<!-- 重新登录提示 -->
<div class="mb-4 text-gray-600">
开通 VIP 需要重新登录意社区生效
</div>
<ElDivider content-position="center">
<span class="text-gray-400 text-sm">操作</span>
</ElDivider>
<!-- 按钮区域 -->
<div class="flex flex-col gap-3 mt-4">
<ElButton
class="w-full py-3 text-lg font-medium"
type="primary"
size="large"
@click="handleThirdPartyLogin(SSO_CLIENT_LOGIN_AGAIN)"
>
意社区重新登录
</ElButton>
<ElButton
class="w-full py-3 text-lg font-medium"
type="default"
size="large"
@click="toHome()"
>
返回首页
</ElButton>
</div>
</div>
</div>
</template>
<style scoped lang="scss">
.pay-result-container {
.card {
transition: transform 0.2s;
&:hover {
transform: translateY(-5px);
}
}
.order-info p {
font-size: 1rem;
}
.el-button {
border-radius: 8px;
}
@media (max-width: 768px) {
.card {
padding: 6vw;
}
.order-info p {
font-size: 0.95rem;
}
.el-button {
font-size: 1rem;
}
}
}
</style>