| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- <template>
- <view class="gates-page">
- <view class="page-section" v-if="mainGates.length > 0">
- <text class="section-title">主线关卡</text>
- <view class="gate-list">
- <view class="gate-card" v-for="(g, i) in mainGates" :key="i"
- :class="'gate-card--' + (g.status === 'UNLOCKED' ? 'done' : (g.status === 'CURRENT' ? 'current' : 'locked'))">
- <view class="gate-status-icon">
- <text v-if="g.status === 'UNLOCKED'">✅</text>
- <text v-else-if="g.status === 'CURRENT'">🔓</text>
- <text v-else>🔒</text>
- </view>
- <view class="gate-info">
- <text class="gate-name">{{ g.name }}</text>
- <text class="gate-desc">{{ g.description }}</text>
- <view class="gate-reward" v-if="g.rewardPoints > 0 || g.rewardEnergy > 0">
- <text class="reward-label">奖励:</text>
- <text class="reward-points" v-if="g.rewardPoints > 0">+{{ g.rewardPoints }}积分</text>
- <text class="reward-energy" v-if="g.rewardEnergy > 0">+{{ g.rewardEnergy }}能量</text>
- </view>
- </view>
- <view class="gate-action">
- <text v-if="g.status === 'CURRENT'" class="action-btn" @click="goGateAction(g)">去完成</text>
- <text v-else-if="g.status === 'LOCKED'" class="action-disabled">未解锁</text>
- <text v-else class="action-done">已解锁</text>
- </view>
- </view>
- </view>
- </view>
- <view class="page-section" v-if="softGates.length > 0">
- <text class="section-title">推荐挑战</text>
- <view class="gate-list">
- <view class="gate-card" :class="'gate-card--' + (g.status === 'UNLOCKED' ? 'done' : 'current')"
- v-for="(g, i) in softGates" :key="i">
- <view class="gate-status-icon">
- <text v-if="g.status === 'UNLOCKED'">✅</text>
- <text v-else>🎯</text>
- </view>
- <view class="gate-info">
- <text class="gate-name">{{ g.name }}</text>
- <text class="gate-desc">{{ g.description }}</text>
- <view class="gate-reward" v-if="g.rewardPoints > 0 || g.rewardEnergy > 0">
- <text class="reward-label">奖励:</text>
- <text class="reward-points" v-if="g.rewardPoints > 0">+{{ g.rewardPoints }}积分</text>
- <text class="reward-energy" v-if="g.rewardEnergy > 0">+{{ g.rewardEnergy }}能量</text>
- </view>
- </view>
- <view class="gate-action">
- <text v-if="g.status !== 'UNLOCKED'" class="action-btn" @click="goGateAction(g)">去挑战</text>
- <text v-else class="action-done">已完成</text>
- </view>
- </view>
- </view>
- </view>
- <view class="page-section" v-if="valueGates.length > 0">
- <text class="section-title">增值关卡</text>
- <view class="gate-list">
- <view class="gate-card gate-card--value" v-for="(g, i) in valueGates" :key="i">
- <view class="gate-status-icon">
- <text v-if="g.status === 'UNLOCKED'">✅</text>
- <text v-else>💎</text>
- </view>
- <view class="gate-info">
- <text class="gate-name">{{ g.name }}</text>
- <text class="gate-desc">{{ g.description }}</text>
- <view class="gate-reward" v-if="g.rewardPoints > 0 || g.rewardEnergy > 0">
- <text class="reward-label">奖励:</text>
- <text class="reward-points" v-if="g.rewardPoints > 0">+{{ g.rewardPoints }}积分</text>
- <text class="reward-energy" v-if="g.rewardEnergy > 0">+{{ g.rewardEnergy }}能量</text>
- </view>
- </view>
- <view class="gate-action">
- <text v-if="g.status !== 'UNLOCKED'" class="action-btn" @click="goGateAction(g)">前往</text>
- <text v-else class="action-done">已解锁</text>
- </view>
- </view>
- </view>
- </view>
- <view class="empty-state" v-if="loading">
- <text>加载中...</text>
- </view>
- </view>
- </template>
- <script>
- import { getUnlockStatus } from '../../utils/api'
- export default {
- data: function() {
- return {
- loading: true,
- gates: []
- }
- },
- computed: {
- mainGates: function() {
- return this.gates.filter(function(g) { return g.isRequired === 1 && g.isSoft === 0 })
- },
- softGates: function() {
- return this.gates.filter(function(g) { return g.isRequired === 1 && g.isSoft === 1 })
- },
- valueGates: function() {
- return this.gates.filter(function(g) { return g.isRequired === 0 })
- }
- },
- onShow: function() {
- this.loadData()
- },
- methods: {
- loadData: function() {
- var self = this
- self.loading = true
- getUnlockStatus().then(function(res) {
- if (res && res.data) {
- self.gates = res.data.gates || []
- }
- self.loading = false
- }).catch(function() {
- self.loading = false
- })
- },
- goGateAction: function(g) {
- var type = g.gateType
- var url = ''
- switch (type) {
- case 'SELF_CHECK':
- url = '/pages/family/self-check'
- break
- case 'INVITE_FAMILY':
- url = '/pages/family/address-edit'
- break
- case 'CREATE_FAMILY_MEMBER':
- url = '/pages/profile-extra/family-members'
- break
- case 'PURCHASE':
- url = '/pages/shop/index/index'
- break
- case 'MEMBERSHIP':
- url = '/pages/membership/index'
- break
- case 'REPORT_UPLOAD':
- url = '/pages/health/report-upload'
- break
- case 'MICRO_ACTION':
- url = '/pages/home-pages/parent-index'
- break
- case 'STREAK_DAYS':
- url = '/pages/health/daily-checkin'
- break
- }
- if (url) {
- uni.navigateTo({ url: url })
- }
- }
- }
- }
- </script>
- <style scoped>
- .gates-page {
- padding: 20rpx 0;
- min-height: 100vh;
- background: #f5f5f5;
- }
- .page-section {
- margin-bottom: 24rpx;
- }
- .section-title {
- font-size: 28rpx;
- font-weight: bold;
- color: #333;
- padding: 0 30rpx;
- margin-bottom: 16rpx;
- display: block;
- }
- .gate-list {
- padding: 0 24rpx;
- }
- .gate-card {
- display: flex;
- align-items: center;
- background: #fff;
- border-radius: 16rpx;
- padding: 24rpx;
- margin-bottom: 16rpx;
- box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.04);
- }
- .gate-card--done {
- opacity: 0.7;
- }
- .gate-card--current {
- border: 2rpx solid #5B9BD5;
- }
- .gate-status-icon {
- width: 60rpx;
- font-size: 36rpx;
- text-align: center;
- flex-shrink: 0;
- }
- .gate-info {
- flex: 1;
- margin: 0 16rpx;
- }
- .gate-name {
- font-size: 28rpx;
- font-weight: bold;
- color: #333;
- display: block;
- }
- .gate-desc {
- font-size: 22rpx;
- color: #999;
- margin-top: 4rpx;
- display: block;
- }
- .gate-reward {
- display: flex;
- align-items: center;
- gap: 8rpx;
- margin-top: 8rpx;
- flex-wrap: wrap;
- }
- .reward-label {
- font-size: 20rpx;
- color: #999;
- }
- .reward-points, .reward-energy {
- font-size: 20rpx;
- padding: 2rpx 10rpx;
- border-radius: 12rpx;
- }
- .reward-points { color: #B8860B; background: rgba(255,215,0,0.15); }
- .reward-energy { color: #3A7CC2; background: rgba(66,165,245,0.15); }
- .gate-action {
- flex-shrink: 0;
- }
- .action-btn {
- font-size: 24rpx;
- color: #fff;
- background: #5B9BD5;
- padding: 8rpx 20rpx;
- border-radius: 20rpx;
- }
- .action-btn:active {
- opacity: 0.8;
- }
- .action-disabled {
- font-size: 22rpx;
- color: #ccc;
- }
- .action-done {
- font-size: 22rpx;
- color: #5B9BD5;
- }
- .empty-state {
- text-align: center;
- padding: 60rpx;
- color: #999;
- }
- </style>
|