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' }) } } })