Files
shoot-miniprograms/src/pages/be-vip.vue
2025-07-15 15:15:47 +08:00

228 lines
7.4 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.

<script setup>
import { ref } from "vue";
import Container from "@/components/Container.vue";
import Avatar from "@/components/Avatar.vue";
import SButton from "@/components/SButton.vue";
import SModal from "@/components/SModal.vue";
import Signin from "@/components/Signin.vue";
import UserHeader from "@/components/UserHeader.vue";
import { createOrderAPI, getHomeData } from "@/apis";
import { formatTimestamp } from "@/util";
import useStore from "@/store";
import { storeToRefs } from "pinia";
const store = useStore();
const { user, config } = storeToRefs(store);
const { updateUser } = store;
const selectedVIP = ref(0);
const showModal = ref(false);
const onPay = async () => {
if (!user.value.id) {
showModal.value = true;
} else if (config.value.vipMenus[selectedVIP.value]) {
if (config.value.vipMenus[selectedVIP.value].id) {
const result = await createOrderAPI(
config.value.vipMenus[selectedVIP.value].id
);
if (!result.pay) return;
const params = result.pay.order.jsApi.params;
if (params) {
wx.requestPayment({
timeStamp: params.timeStamp, // 时间戳
nonceStr: params.nonceStr, // 随机字符串
package: params.package, // 统一下单接口返回的 prepay_id 参数值格式prepay_id=***
paySign: params.paySign, // 签名
signType: "RSA", // 签名类型默认为RSA
async success(res) {
const result = await getHomeData();
if (result.user) updateUser(result.user);
uni.showToast({
title: "支付成功",
icon: "none",
});
},
fail(res) {
console.log("pay error", res);
},
});
}
}
}
};
const toOrderPage = () => {
uni.navigateTo({
url: "/pages/orders",
});
};
</script>
<template>
<Container title="会员说明">
<view :style="{ width: '100%', height: '100%' }">
<view v-if="user.id" class="header">
<view>
<Avatar :src="user.avatar" :size="35" />
<text class="truncate">{{ user.nickName }}</text>
</view>
<text v-if="user.expiredAt">
{{ formatTimestamp(user.expiredAt) }}到期
</text>
</view>
<view
class="container"
:style="{ height: !user.id ? '100%' : 'calc(100% - 62px)' }"
>
<view class="content vip-content">
<view class="title-bar">
<view />
<text>VIP 介绍</text>
</view>
<view>
<text
>射灵的的VIP服务是为了正式对战打造的专属特权让您在激烈的射击运动中充分享受与同级别想着对战的乐趣</text
>
<text
>VIP的收取形式灵活多样充分考虑到了不同用户的需求我们提供按月收取的方式每月仅需10元即可轻松成为VIP会员享受一个月的尊贵特权这种方式适合那些希望先体验VIP服务再决定是否长期投入的用户您可以先购买一个月的VIP亲身感受VIP带来的种种好处如果觉得满意再继续选择适合自己的购买方案而对于那些已经确定会长期参与对战希望持续享受VIP特权的用户我们则推出了更为优惠的一年VIP套餐一次性购买一年的VIP仅需100元平均每月不到9元您就能全年畅享VIP的所有权益这不仅为您节省了时间和精力还为您带来了实实在在的经济优惠
一年的时间足够您在对战的世界中尽情驰骋不断挑战自我创造属于自己的辉煌战绩</text
>
<text
>VIP会员还将获得专属的客服支持当您在游戏中遇到任何问题无论是技术故障规则疑问还是其他需要帮助的情况都可以随时联系我们的VIP专属客服团队他们将为您提供24小时不间断的优质服务以最快的速度为您解决问题确保您的对战体验不受任何影响</text
>
<text
>除了这些直接与对战相关的特权VIP会员还将享受到一系列的福利我们不定期为VIP会员举办专属的活动如邀请知名对战选手进行线上交流举办VIP会员专属的锦标赛等在这些活动中您不仅有机会与偶像近距离接触还能与其他VIP会员交流心得共同进步同时VIP会员在购买游戏内的道具装备时还将享受专属的折扣优惠这些道具和装备能够帮助您在对战中更好地发挥自己的实力提升您的对战体验</text
>
</view>
</view>
<view class="content">
<view class="title-bar">
<view />
<text>成为射灵会员</text>
</view>
<view class="vip-items">
<view
v-for="(item, index) in config.vipMenus || []"
:key="index"
:style="{
color: selectedVIP === index ? '#fff' : '#333333',
borderColor: selectedVIP === index ? '#FF7D57' : '#eee',
background:
selectedVIP === index
? '#FF7D57'
: 'linear-gradient(180deg, #fbfbfb 0%, #f5f5f5 100%)',
}"
@click="() => (selectedVIP = index)"
>
{{ item.name }}
</view>
</view>
</view>
<SButton :onClick="onPay">支付</SButton>
<SModal :show="showModal" :onClose="() => (showModal = false)">
<Signin :onClose="() => (showModal = false)" />
</SModal>
<view class="my-orders" v-if="user.id">
<view @click="toOrderPage">
<text>我的订单</text>
<image src="../static/enter-arrow-blue.png" mode="widthFix" />
</view>
</view>
</view>
</view>
</Container>
</template>
<style scoped>
.header {
width: calc(100% - 30px);
display: flex;
align-items: center;
justify-content: space-between;
color: #fff;
padding: 15px;
padding-top: 0;
font-size: 14px;
}
.header > view {
display: flex;
align-items: center;
}
.header > view > text:last-child {
margin-left: 10px;
width: 120px;
text-align: left;
}
.header > text:nth-child(2) {
color: #fed847;
}
.container {
width: 100%;
background-color: #f5f5f5;
padding-top: 10px;
}
.content {
display: flex;
flex-direction: column;
align-items: center;
background-color: #fff;
padding: 15px;
margin-bottom: 10px;
}
.title-bar {
width: 100%;
display: flex;
align-items: center;
}
.title-bar > view:first-child {
width: 5px;
height: 15px;
border-radius: 10px;
background-color: #fed847;
margin-right: 10px;
}
.content > view:nth-child(2) {
font-size: 14px;
color: #333;
}
.content > view:nth-child(2) > text {
display: block;
margin-top: 10px;
color: #333;
}
.vip-items {
width: 100%;
display: grid;
grid-template-columns: repeat(4, 23.5%);
padding: 10px;
row-gap: 5%;
column-gap: 2%;
}
.vip-items > view {
border: 1px solid #eee;
padding: 12px 0;
border-radius: 10px;
text-align: center;
}
.vip-content {
height: 62%;
}
.vip-content > view:nth-child(2) {
overflow: auto;
}
.my-orders {
display: flex;
justify-content: center;
color: #39a8ff;
margin-top: 10px;
font-size: 13px;
}
.my-orders > view {
display: flex;
align-items: center;
}
.my-orders > view > image {
width: 15px;
}
</style>