| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- <template>
- <view class="page">
- <view class="nav-bar">
- <view class="nav-back" @tap="goBack">
- <text class="back-text">‹ 返回</text>
- </view>
- <text class="nav-title">健康启航计划</text>
- </view>
- <scroll-view class="content" scroll-y>
- <!-- 头部横幅 -->
- <view class="hero">
- <text class="hero-title">健康启航计划</text>
- <text class="hero-desc">199元解锁全年健康管理</text>
- <view class="hero-price">
- <text class="price-original">¥199</text>
- <text class="price-note">7天全功能体验</text>
- </view>
- </view>
- <!-- 权益对比 -->
- <view class="card">
- <view class="card-header">
- <text class="card-title">您的权益</text>
- </view>
- <view class="benefit-list">
- <view class="benefit-item" v-for="(item, idx) in benefits" :key="idx">
- <text class="benefit-icon">{{ item.icon }}</text>
- <text class="benefit-text">{{ item.text }}</text>
- <text class="benefit-status" :class="item.active ? 'active' : 'inactive'">{{ item.active ? '✓ 已包含' : '✗ 需升级' }}</text>
- </view>
- </view>
- </view>
- <!-- CF奖励计算器 -->
- <view class="card">
- <view class="card-header">
- <text class="card-title">打卡返CF值</text>
- <text class="card-subtitle">完成任务最高可得19,900 CF = 199元</text>
- </view>
- <view class="cf-calculator">
- <view class="cf-row">
- <text class="cf-label">基础奖励</text>
- <text class="cf-value">300 CF</text>
- </view>
- <view class="cf-row">
- <text class="cf-label">连续打卡加成</text>
- <text class="cf-value">+420 CF</text>
- </view>
- <view class="cf-row">
- <text class="cf-label">个性化任务</text>
- <text class="cf-value">+180 CF</text>
- </view>
- <view class="cf-divider"></view>
- <view class="cf-total">
- <text class="cf-total-label">累计可得</text>
- <text class="cf-total-value">19,900 CF</text>
- </view>
- <text class="cf-equivalent">= ¥199 全额返还</text>
- </view>
- </view>
- <!-- 闯关任务预览 -->
- <view class="card">
- <view class="card-header">
- <text class="card-title">3周闯关挑战</text>
- </view>
- <view class="challenge-preview">
- <view class="week-item" v-for="(week, idx) in weeks" :key="idx">
- <view class="week-header">
- <text class="week-num">第{{ idx + 1 }}周</text>
- <text class="week-reward">{{ week.reward }} CF</text>
- </view>
- <view class="week-tasks">
- <text class="task-tag" v-for="(task, tidx) in week.tasks" :key="tidx">{{ task }}</text>
- </view>
- </view>
- </view>
- </view>
- <!-- 购买按钮 -->
- <view class="purchase-wrap">
- <view class="purchase-btn" :class="{ 'loading': submitting }" @tap="handlePurchase">
- <text class="btn-text">{{ submitting ? '处理中...' : '立即开启体验' }}</text>
- </view>
- <text class="purchase-tip">7天内可随时取消,首周打卡可获199元CF返还</text>
- </view>
- </scroll-view>
- </view>
- </template>
- <script>
- import { checkPurchase, createPurchaseOrder, getPurchasePayParams } from '../../utils/api.js'
- import { requestVirtualPayment } from '../../utils/api.js'
- export default {
- data() {
- return {
- submitting: false,
- benefits: [
- { icon: '📋', text: '无限报告上传', active: true },
- { icon: '🤖', text: 'AI报告解析', active: true },
- { icon: '📝', text: '每日方案生成', active: true },
- { icon: '🏆', text: '3周闯关挑战', active: true },
- { icon: '💰', text: 'CF值奖励', active: true },
- { icon: '👨👩👧', text: '家庭会员权益', active: false }
- ],
- weeks: [
- { reward: '300 CF', tasks: ['首次报告上传', '连续3天打卡', '上传1份报告'] },
- { reward: '300 CF', tasks: ['上传3份报告', '连续7天打卡', '累计3份报告'] },
- { reward: '300 CF', tasks: ['完成3个挑战', '连续21天打卡', '上传5份报告'] }
- ]
- }
- },
- onLoad() {
- this.checkStatus()
- },
- methods: {
- goBack() { uni.navigateBack() },
- async checkStatus() {
- try {
- var res = await checkPurchase()
- if (res.data && res.data.hasPurchased && res.data.isActive) {
- // 从方案制定页来购买:返回方案页,由 onShow 自动继续生成
- if (uni.getStorageSync('PLAN_RESUME_AFTER_PURCHASE') === '1') {
- uni.navigateBack()
- return
- }
- // 已有有效购买,跳转闯关进度
- uni.redirectTo({ url: '/pages/growth/challenge-progress' })
- }
- } catch (e) {
- console.log('检查购买状态失败', e)
- }
- },
- handlePurchase() {
- var self = this
- self.submitting = true
- createPurchaseOrder().then(function(res) {
- if (res.data && res.data.success && res.data.orderNo) {
- var orderNo = res.data.orderNo
- // 获取虚拟支付参数并拉起支付
- getPurchasePayParams(orderNo).then(function(payRes) {
- var dto = payRes.data || {}
- if (dto.orderInfo && dto.sign) {
- requestVirtualPayment(dto, {
- success: function() {
- self.submitting = false
- uni.showToast({ title: '支付成功,开通中…', icon: 'none' })
- setTimeout(function() {
- if (uni.getStorageSync('PLAN_RESUME_AFTER_PURCHASE') === '1') {
- // 从方案制定页来购买:返回方案页,由 onShow 自动继续生成
- uni.navigateBack()
- } else {
- uni.redirectTo({ url: '/pages/growth/challenge-progress' })
- }
- }, 800)
- },
- fail: function(err) {
- self.submitting = false
- var errCode = err && err.errCode
- var msg = '支付取消'
- if (errCode === -15007 || errCode === -15005) msg = '登录态已过期,请重新登录'
- else if (err && err.errMsg) msg = err.errMsg
- uni.showToast({ title: msg, icon: 'none' })
- }
- })
- } else {
- self.submitting = false
- uni.showToast({ title: payRes.message || '支付参数获取失败', icon: 'none' })
- }
- }).catch(function(err) {
- self.submitting = false
- if (err && err.code === 46001) {
- uni.showToast({ title: '该商品暂未开放购买', icon: 'none' })
- } else {
- uni.showToast({ title: (err && err.message) || '支付参数获取失败', icon: 'none' })
- }
- })
- } else {
- self.submitting = false
- uni.showToast({ title: (res.data && res.data.message) || '创建订单失败', icon: 'none' })
- }
- }).catch(function(err) {
- self.submitting = false
- uni.showToast({ title: '创建订单失败', icon: 'none' })
- })
- }
- }
- }
- </script>
- <style scoped>
- .page { min-height: 100vh; background: #FFF7ED; }
- .nav-bar { display: flex; align-items: center; height: 88rpx; padding-top: env(safe-area-inset-top); background: #fff; border-bottom: 1rpx solid #f0f0f0; position: relative; }
- .nav-back { position: absolute; left: 24rpx; top: 0; bottom: 0; display: flex; align-items: center; }
- .back-text { font-size: 28rpx; color: #F97316; }
- .nav-title { flex: 1; text-align: center; font-size: 32rpx; font-weight: bold; color: #333; }
- .content { height: calc(100vh - 88rpx); }
- .hero { background: linear-gradient(135deg, #FF8C42, #F97316); padding: 40rpx 32rpx; text-align: center; }
- .hero-title { font-size: 40rpx; font-weight: bold; color: #fff; display: block; }
- .hero-desc { font-size: 26rpx; color: rgba(255,255,255,0.9); margin-top: 8rpx; display: block; }
- .hero-price { margin-top: 24rpx; }
- .price-original { font-size: 56rpx; font-weight: bold; color: #fff; }
- .price-note { font-size: 22rpx; color: rgba(255,255,255,0.8); margin-left: 12rpx; }
- .card { margin: 16rpx 24rpx; background: #fff; border-radius: 20rpx; overflow: hidden; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
- .card-header { padding: 24rpx 24rpx 16rpx; border-bottom: 1rpx solid #f5f5f5; }
- .card-title { font-size: 28rpx; font-weight: bold; color: #333; }
- .card-subtitle { font-size: 22rpx; color: #999; margin-left: 12rpx; }
- .benefit-list { padding: 16rpx 24rpx; }
- .benefit-item { display: flex; align-items: center; gap: 16rpx; padding: 16rpx 0; border-bottom: 1rpx solid #f5f5f5; }
- .benefit-item:last-child { border-bottom: none; }
- .benefit-icon { font-size: 36rpx; }
- .benefit-text { flex: 1; font-size: 26rpx; color: #333; }
- .benefit-status { font-size: 22rpx; padding: 4rpx 12rpx; border-radius: 12rpx; }
- .benefit-status.active { background: #E8F5E9; color: #4CAF50; }
- .benefit-status.inactive { background: #F5F5F5; color: #999; }
- .cf-calculator { padding: 16rpx 24rpx; }
- .cf-row { display: flex; justify-content: space-between; padding: 8rpx 0; }
- .cf-label { font-size: 24rpx; color: #666; }
- .cf-value { font-size: 24rpx; color: #F97316; font-weight: bold; }
- .cf-divider { height: 1rpx; background: #e0e0e0; margin: 12rpx 0; }
- .cf-total { display: flex; justify-content: space-between; padding: 8rpx 0; }
- .cf-total-label { font-size: 26rpx; color: #333; font-weight: bold; }
- .cf-total-value { font-size: 32rpx; color: #F97316; font-weight: bold; }
- .cf-equivalent { font-size: 22rpx; color: #999; text-align: center; margin-top: 8rpx; display: block; }
- .challenge-preview { padding: 16rpx 24rpx; }
- .week-item { margin-bottom: 20rpx; }
- .week-item:last-child { margin-bottom: 0; }
- .week-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12rpx; }
- .week-num { font-size: 26rpx; font-weight: bold; color: #333; }
- .week-reward { font-size: 22rpx; color: #F97316; }
- .week-tasks { display: flex; flex-wrap: wrap; gap: 8rpx; }
- .task-tag { font-size: 22rpx; color: #666; background: #FFF3E0; padding: 6rpx 12rpx; border-radius: 12rpx; }
- .purchase-wrap { padding: 32rpx 24rpx 40rpx; text-align: center; }
- .purchase-btn { background: linear-gradient(135deg, #FF8C42, #F97316); color: #fff; text-align: center; padding: 28rpx 0; border-radius: 16rpx; font-size: 32rpx; font-weight: bold; }
- .purchase-btn.loading { opacity: 0.6; }
- .purchase-tip { font-size: 22rpx; color: #999; margin-top: 16rpx; display: block; }
- </style>
|