This commit is contained in:
2026-07-10 16:14:31 +08:00
commit 637b0bd144
158 changed files with 33269 additions and 0 deletions
@@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}
@@ -0,0 +1,169 @@
import { updatesessionkey, userInfo, vips, vipVirtualPayment } from "../../utils/request"
interface VipPlan {
id: number
name: string
price: number
desc: string
recommend?: boolean
selected: boolean
}
Component({
properties: {
visible: {
type: Boolean,
value: false,
},
},
data: {
benefits: [
{ title: '更低生成成本', desc: '享受更多优惠', iconClass: 'cost-icon' },
{ title: '专属会员标识', desc: '尊享身份标识', iconClass: 'badge-icon' },
{ title: '优先体验新功能', desc: '抢先体验特权', iconClass: 'flash-icon' },
],
plans: [
{ id: 1, name: '月卡会员', price: 25, desc: '¥25/月', selected: false },
{ id: 2, name: '半年卡会员', price: 98, desc: '¥16.3/月', selected: false },
{ id: 3, name: '年卡会员', price: 168, desc: '¥14/月', recommend: true, selected: true },
{ id: 4, name: '终身会员', price: 298, desc: '一次付费\n永久使用', selected: false },
] as VipPlan[],
selectedPackage: null as VipPlan | null
},
lifetimes: {
attached() {
vips().then((res: any) => {
if (!res.code) {
let array = [];
for (let q = 0; q < res.data.length; q++) {
let item = res.data[q];
item.price = (+item.price).toFixed(0);
array.push(item);
}
this.setData({ plans: array });
}
})
},
detached() {
}
},
attached() {
vips().then((res: any) => {
if (!res.code) {
let array = [];
for (let q = 0; q < res.data.length; q++) {
let item = res.data[q];
item.price = (+item.price).toFixed(0);
array.push(item);
}
this.setData({ plans: array });
}
})
},
detached() {
},
pageLifetimes: {
},
methods: {
noop() { },
handleOverlayTap() {
this.handleClose()
},
handleClose() {
this.triggerEvent('close')
},
handlePlanTap(e: WechatMiniprogram.TouchEvent) {
const id = e.currentTarget.dataset.id
this.data.plans.forEach((value, i) => {
if (id == value.id) {
console.log(value);
this.setData({
selectedPackage: value,
})
}
})
},
handleConfirm() {
this.handleBuy()
},
handleBuy() {
const that = this;
if (that.data.selectedPackage == null) {
return;
}
wx.showLoading({ title: '处理中...', mask: true });
wx.checkSession({
success() {
that.payment();
},
fail() {
wx.login({
success(login) {
updatesessionkey(login.code).then((res: any) => {
if (!res.code) {
that.payment();
} else {
wx.showModal({
title: '温馨提示',
content: res.message,
showCancel: false
})
}
})
}
})
wx.hideLoading();
}
})
},
payment() {
let that = this;
vipVirtualPayment((that.data.selectedPackage || { id: 0 }).id).then((res: any) => {
wx.requestVirtualPayment({
signData: JSON.stringify(res.param.signData),
paySig: res.param.paySig,
signature: res.param.signature,
mode: res.param.mode,
success(result: any) {
wx.hideLoading();
console.log(result)
userInfo().then((res: any) => {
if (!res.code) {
wx.setStorageSync('userInfo', res.data);
that.setData({ userInfo: res.data });
}
})
},
fail(error: any) {
wx.hideLoading();
console.log(error);
wx.showModal({
title: '温馨提示',
content: '支付失败',
showCancel: false
})
}
});
}).catch(() => {
wx.hideLoading();
wx.showModal({
title: '温馨提示',
content: '系统繁忙, 请稍后再试',
showCancel: false
})
})
}
},
})
@@ -0,0 +1,64 @@
<view wx:if="{{visible}}" class="vip-overlay" catchtap="handleOverlayTap">
<view class="vip-popup" catchtap="noop">
<image class="vip-bg" src="/static/images/my/vip_bg.png" mode="widthFix"></image>
<view class="close-hotspot" bindtap="handleClose"></view>
<view class="vip-content">
<view class="gift-list">
<view class="gift-copy">
<text>立即赠送</text>
<text class="highlight">300</text>
<text>金币</text>
</view>
<view class="gift-copy daily-copy">
<text>平台每天赠送</text>
<text class="highlight">30</text>
<text>金币</text>
<text class="orange-note">(仅当天有效)</text>
</view>
</view>
<view class="plan-section">
<scroll-view class="plan-scroll" scroll-x enhanced show-scrollbar="false">
<view class="plan-track">
<view
wx:for="{{plans}}"
wx:key="id"
class="plan-card {{(selectedPackage && item.id == selectedPackage.id) || (!selectedPackage && item.selected) ? 'selected' : ''}}"
data-id="{{item.id}}"
bindtap="handlePlanTap"
>
<image wx:if="{{(selectedPackage && item.id == selectedPackage.id) || (!selectedPackage && item.selected)}}" class="plan-selected-bg" src="/static/images/my/vip_selected.png" mode="scaleToFill"></image>
<view wx:if="{{item.recommend}}" class="recommend-ribbon">推荐</view>
<text class="plan-name">{{item.title}}</text>
<view class="price-row">
<text class="currency">¥</text>
<text class="price">{{item.price}}</text>
</view>
<text class="plan-desc">{{item.price}}/月</text>
</view>
</view>
</scroll-view>
<view class="dots">
<text
wx:for="{{plans}}"
wx:key="id"
class="dot {{(selectedPackage && item.id == selectedPackage.id) || (!selectedPackage && item.selected) ? 'active' : ''}}"
></text>
</view>
</view>
<view class="action-section">
<image class="vip-btn" src="/static/images/my/vip_btn.png" mode="widthFix" bindtap="handleConfirm"></image>
<view class="skip-btn" bindtap="handleClose">暂不需要</view>
</view>
</view>
</view>
</view>
@@ -0,0 +1,228 @@
.vip-overlay {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 999;
display: flex;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.58);
box-sizing: border-box;
}
.vip-popup {
position: relative;
width: 706rpx;
height: 1130rpx;
max-height: 92vh;
overflow: visible;
background: transparent;
box-sizing: border-box;
}
.vip-bg {
position: absolute;
top: 0;
left: 0;
z-index: 0;
width: 706rpx;
height: auto;
display: block;
}
.close-hotspot {
position: absolute;
top: 112rpx;
right: 24rpx;
z-index: 5;
width: 72rpx;
height: 72rpx;
}
.vip-content {
position: relative;
z-index: 2;
height: 100%;
display: flex;
flex-direction: column;
box-sizing: border-box;
padding-top: 284rpx;
}
.gift-list {
display: flex;
flex-direction: column;
gap: 68rpx;
padding-left: 208rpx;
box-sizing: border-box;
}
.gift-copy {
display: flex;
align-items: baseline;
gap: 9rpx;
height: 58rpx;
color: #321708;
font-size: 27rpx;
font-weight: 900;
white-space: nowrap;
}
.highlight {
color: #f18a0a;
font-size: 42rpx;
font-style: italic;
}
.orange-note {
color: #f18400;
font-size: 24rpx;
}
.plan-section {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 220rpx;
}
.plan-scroll {
width: 706rpx;
height: 218rpx;
white-space: nowrap;
}
.plan-track {
height: 218rpx;
padding: 0 52rpx;
display: flex;
gap: 14rpx;
box-sizing: border-box;
}
.plan-card {
position: relative;
width: 142rpx;
height: 214rpx;
border-radius: 14rpx;
display: inline-flex;
flex-direction: column;
align-items: center;
justify-content: center;
flex-shrink: 0;
overflow: hidden;
border: 1rpx solid #e7dcf2;
background: linear-gradient(180deg, #fffefe, #fbf9ff);
box-sizing: border-box;
}
.plan-card.selected {
border: 0;
background: transparent;
}
.plan-selected-bg {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 0;
width: 100%;
height: 100%;
display: block;
}
.recommend-ribbon {
display: none;
}
.plan-name,
.price-row,
.plan-desc {
position: relative;
z-index: 1;
}
.plan-name {
color: #25170d;
font-size: 23rpx;
font-weight: 900;
}
.price-row {
margin-top: 20rpx;
display: flex;
align-items: baseline;
color: #7047ee;
}
.selected .price-row {
color: #f08d09;
}
.currency {
font-size: 24rpx;
font-weight: 900;
}
.price {
font-size: 48rpx;
line-height: 1;
font-weight: 900;
}
.plan-desc {
margin-top: 18rpx;
color: #7f7f86;
font-size: 20rpx;
line-height: 1.25;
text-align: center;
white-space: pre-line;
}
.dots {
display: flex;
align-items: center;
justify-content: center;
gap: 14rpx;
margin-top: 22rpx;
}
.dot {
width: 12rpx;
height: 12rpx;
border-radius: 999rpx;
background: #dedee2;
}
.dot.active {
width: 36rpx;
background: #764ef7;
}
.action-section {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 24rpx;
}
.vip-btn {
width: 590rpx;
height: auto;
display: block;
}
.skip-btn {
margin-top: 20rpx;
color: #8e8e94;
font-size: 24rpx;
font-weight: 800;
text-align: center;
}