152 lines
4.2 KiB
JavaScript
152 lines
4.2 KiB
JavaScript
const { request } = require('../../utils_new/request');
|
|
const { payProduct } = require('../../utils_new/payment');
|
|
const api = require('../../utils/api');
|
|
|
|
Page({
|
|
data: {
|
|
statusBarHeight: 20,
|
|
navBarHeight: 44,
|
|
totalNavHeight: 64,
|
|
products: [],
|
|
vipPackages: [],
|
|
modal: {
|
|
visible: false,
|
|
type: 'product',
|
|
id: 0,
|
|
orderType: '',
|
|
title: '',
|
|
price: 0,
|
|
benefits: []
|
|
}
|
|
},
|
|
|
|
onLoad() {
|
|
const systemInfo = wx.getSystemInfoSync()
|
|
const statusBarHeight = systemInfo.statusBarHeight || 20
|
|
const menuButton = wx.getMenuButtonBoundingClientRect()
|
|
const navBarHeight = menuButton.height + (menuButton.top - statusBarHeight) * 2
|
|
|
|
this.setData({
|
|
statusBarHeight,
|
|
navBarHeight,
|
|
totalNavHeight: statusBarHeight + navBarHeight
|
|
})
|
|
},
|
|
|
|
onShow() {
|
|
this.loadProducts()
|
|
},
|
|
|
|
async loadProducts() {
|
|
try {
|
|
const res = await api.payment.getPackages()
|
|
const body = res.data || {}
|
|
const list = Array.isArray(body) ? body : body?.data || []
|
|
|
|
if (!list.length) return
|
|
|
|
const raw = list.map((p) => {
|
|
const attrs = p.attributes || {}
|
|
|
|
const gradientStart = p.gradientStart || attrs.gradient_start || '#60A5FA'
|
|
const gradientEnd = p.gradientEnd || attrs.gradient_end || '#2563EB'
|
|
const tagColor = p.tagColor || attrs.tag_color || '#1E3A8A'
|
|
const tagText = p.tagText || attrs.tag_text || ''
|
|
const benefits = p.benefits || attrs.benefits || []
|
|
|
|
const iconMap = {
|
|
first: 'gift',
|
|
month: 'gift',
|
|
yearly: 'gift',
|
|
year: 'crown',
|
|
svip: 'diamond',
|
|
soulmate: 'heart-filled',
|
|
guardian: 'diamond',
|
|
companion: 'crown',
|
|
listener: 'gift'
|
|
}
|
|
|
|
let vipType = attrs.type || p.vipType || ''
|
|
if (vipType === 'monthly') vipType = 'month'
|
|
if (vipType === 'yearly') vipType = 'year'
|
|
if (vipType === 'lifetime') vipType = 'svip'
|
|
|
|
return {
|
|
id: Number(p.id),
|
|
orderType: 'vip',
|
|
vipType,
|
|
price: Number(p.price) || 0,
|
|
originalPrice: Number(p.originalPrice) || 0,
|
|
title: p.title,
|
|
subtitle: p.subtitle || attrs.subtitle || (benefits[0] || ''),
|
|
tagText: tagText,
|
|
gradient: `background: linear-gradient(180deg, ${gradientStart}, ${gradientEnd});`,
|
|
tagStyle: `color: ${tagColor}; background: rgba(255,255,255,0.25);`,
|
|
icon: iconMap[vipType] || 'crown',
|
|
iconGradient: `background: linear-gradient(180deg, ${gradientStart}, ${gradientEnd});`,
|
|
priceColor: `color: ${gradientEnd};`,
|
|
checkColor: tagColor || gradientEnd,
|
|
borderStyle: `border-color: rgba(0,0,0,0.06); background: rgba(255,255,255,0.9);`,
|
|
btnGradient: `background: linear-gradient(90deg, ${gradientStart}, ${gradientEnd});`,
|
|
benefits,
|
|
isRecommend: p.isRecommend || attrs.is_recommended || false
|
|
}
|
|
})
|
|
|
|
this.setData({
|
|
products: raw,
|
|
vipPackages: raw
|
|
})
|
|
} catch (err) {
|
|
console.error('Failed to load products:', err)
|
|
}
|
|
},
|
|
|
|
onBack() {
|
|
wx.navigateBack({ delta: 1 })
|
|
},
|
|
|
|
openProductPay(e) {
|
|
const id = Number(e.currentTarget.dataset.id)
|
|
const product = this.data.products.find(x => Number(x.id) === id)
|
|
if (!product) return
|
|
|
|
const pkg = this.data.vipPackages.find(x => Number(x.id) === id)
|
|
const benefits = pkg?.benefits || []
|
|
|
|
this.setData({
|
|
modal: {
|
|
visible: true,
|
|
type: 'product',
|
|
id: Number(product.id),
|
|
orderType: product.orderType,
|
|
title: product.title,
|
|
price: product.price,
|
|
benefits
|
|
}
|
|
})
|
|
},
|
|
|
|
closeModal() {
|
|
this.setData({ 'modal.visible': false })
|
|
},
|
|
|
|
async confirmAction() {
|
|
const modal = this.data.modal
|
|
|
|
wx.showLoading({ title: '发起支付...' })
|
|
try {
|
|
await payProduct({
|
|
productId: modal.id,
|
|
orderType: modal.orderType
|
|
})
|
|
wx.hideLoading()
|
|
wx.showToast({ title: '购买成功', icon: 'success' })
|
|
this.closeModal()
|
|
} catch (err) {
|
|
wx.hideLoading()
|
|
wx.showToast({ title: err.message || '支付失败', icon: 'none' })
|
|
}
|
|
}
|
|
})
|