| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- <template>
- <view class="container">
- <!-- 进度统计 -->
- <view class="progress-card">
- <text class="progress-title">新手任务</text>
- <view class="progress-bar-wrap">
- <view class="progress-bar">
- <view class="progress-fill" :style="{ width: progressPercent + '%' }"></view>
- </view>
- <text class="progress-text">{{ completedCount }}/6 已完成</text>
- </view>
- <text class="progress-hint">完成所有任务,领取丰厚奖励!</text>
- </view>
- <!-- 任务列表 -->
- <view class="task-list">
- <view class="task-item" v-for="item in taskList" :key="item.taskType">
- <view class="task-left">
- <view class="task-icon">{{ item.icon }}</view>
- <view class="task-info">
- <text class="task-name">{{ item.name }}</text>
- <text class="task-reward">获得 {{ item.rewardPoints }} 积分 + {{ item.rewardEnergy }} 能量</text>
- </view>
- </view>
- <view class="task-right">
- <text class="task-status" v-if="item.status === 'CLAIMED'" :class="'status-claimed'">已领取</text>
- <text class="task-status" v-else-if="item.status === 'COMPLETED'" :class="'status-completed'">已完成</text>
- <text class="task-status" v-else :class="'status-pending'">待完成</text>
- <button
- v-if="item.status === 'COMPLETED'"
- class="claim-btn"
- @click="claimReward(item)"
- :disabled="item.claiming"
- >领取</button>
- </view>
- </view>
- </view>
- <!-- 加载状态 -->
- <view class="loading-state" v-if="loading">
- <text>加载中...</text>
- </view>
- </view>
- </template>
- <script>
- import { getOnboardingProgress, claimOnboardingReward } from '../../utils/api.js'
- var TASK_META = {
- REGISTER: { icon: '📝', name: '完成注册' },
- COMPLETE_PROFILE: { icon: '👤', name: '完善个人资料' },
- ADD_CHILD: { icon: '👨\u200D👩\u200D👧\u200D👦', name: '添加家庭成员' },
- FIRST_CHECKIN: { icon: '✅', name: '完成首次健康打卡' },
- FIRST_TASK: { icon: '🎯', name: '完成首次任务' },
- BIND_REFERRAL: { icon: '🤝', name: '绑定推荐人' }
- }
- export default {
- data() {
- return {
- taskList: [],
- loading: false
- }
- },
- computed: {
- completedCount() {
- var count = 0
- for (var i = 0; i < this.taskList.length; i++) {
- if (this.taskList[i].status === 'COMPLETED' || this.taskList[i].status === 'CLAIMED') {
- count++
- }
- }
- return count
- },
- progressPercent() {
- return Math.round((this.completedCount / 6) * 100)
- }
- },
- onLoad() {
- this.loadProgress()
- },
- onShow() {
- this.loadProgress()
- },
- methods: {
- async loadProgress() {
- this.loading = true
- try {
- var res = await getOnboardingProgress()
- var records = (res.data && res.data.records) || res.data || []
- if (!Array.isArray(records)) {
- records = []
- }
- this.taskList = records.map(function(item) {
- var meta = TASK_META[item.taskType] || { icon: '📋', name: item.taskType }
- return {
- taskType: item.taskType,
- icon: meta.icon,
- name: meta.name,
- rewardPoints: item.rewardPoints || 0,
- rewardEnergy: item.rewardEnergy || 0,
- status: item.status || 'PENDING',
- claiming: false
- }
- })
- } catch (e) {
- console.error('获取新手任务进度失败', e)
- }
- this.loading = false
- },
- async claimReward(item) {
- if (item.claiming) return
- item.claiming = true
- try {
- await claimOnboardingReward(item.taskType)
- item.status = 'CLAIMED'
- uni.showToast({
- title: '获得' + item.rewardPoints + '积分+' + item.rewardEnergy + '能量',
- icon: 'none',
- duration: 2000
- })
- } catch (e) {
- uni.showToast({ title: '领取失败', icon: 'none' })
- }
- item.claiming = false
- }
- }
- }
- </script>
- <style scoped>
- .container {
- padding: 30rpx;
- min-height: 100vh;
- background: #FFF7ED;
- }
- /* ===== 进度卡片 ===== */
- .progress-card {
- background: linear-gradient(135deg, #F97316, #EA580C);
- border-radius: 20rpx;
- padding: 40rpx;
- color: #fff;
- margin-bottom: 24rpx;
- }
- .progress-title {
- font-size: 36rpx;
- font-weight: bold;
- display: block;
- margin-bottom: 24rpx;
- }
- .progress-bar-wrap {
- display: flex;
- align-items: center;
- margin-bottom: 16rpx;
- }
- .progress-bar {
- flex: 1;
- height: 16rpx;
- background: rgba(255,255,255,0.3);
- border-radius: 8rpx;
- overflow: hidden;
- }
- .progress-fill {
- height: 100%;
- background: #fff;
- border-radius: 8rpx;
- transition: width 0.3s ease;
- }
- .progress-text {
- font-size: 24rpx;
- margin-left: 16rpx;
- white-space: nowrap;
- }
- .progress-hint {
- font-size: 22rpx;
- opacity: 0.85;
- display: block;
- }
- /* ===== 任务列表 ===== */
- .task-list {
- background: #fff;
- border-radius: 20rpx;
- overflow: hidden;
- box-shadow: 0 2rpx 12rpx rgba(249,115,22,0.08);
- }
- .task-item {
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 28rpx 30rpx;
- border-bottom: 1rpx solid #FED7AA;
- }
- .task-item:last-child {
- border-bottom: none;
- }
- .task-left {
- display: flex;
- align-items: center;
- flex: 1;
- margin-right: 20rpx;
- }
- .task-icon {
- width: 72rpx;
- height: 72rpx;
- border-radius: 16rpx;
- background: #FEF3C7;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 36rpx;
- margin-right: 20rpx;
- flex-shrink: 0;
- }
- .task-info {
- flex: 1;
- }
- .task-name {
- font-size: 28rpx;
- font-weight: 600;
- color: #1E293B;
- display: block;
- margin-bottom: 6rpx;
- }
- .task-reward {
- font-size: 22rpx;
- color: #F97316;
- display: block;
- }
- .task-right {
- display: flex;
- align-items: center;
- flex-shrink: 0;
- }
- .task-status {
- font-size: 22rpx;
- padding: 6rpx 16rpx;
- border-radius: 20rpx;
- margin-right: 12rpx;
- }
- .status-pending {
- background: #F1F5F9;
- color: #94A3B8;
- }
- .status-completed {
- background: #DCFCE7;
- color: #16A34A;
- }
- .status-claimed {
- background: #FEF3C7;
- color: #D97706;
- }
- .claim-btn {
- background: #F97316;
- color: #fff;
- font-size: 24rpx;
- border-radius: 30rpx;
- height: 56rpx;
- line-height: 56rpx;
- padding: 0 28rpx;
- font-weight: 500;
- }
- .claim-btn::after {
- border: none;
- }
- .claim-btn:active {
- opacity: 0.8;
- }
- .claim-btn[disabled] {
- opacity: 0.5;
- }
- .loading-state {
- text-align: center;
- padding: 60rpx;
- color: #94A3B8;
- font-size: 28rpx;
- }
- </style>
|