diff --git a/xuan-deduct-uniapp/src/pages/mine/coins.vue b/xuan-deduct-uniapp/src/pages/mine/coins.vue
index d79bd9f..24f730f 100644
--- a/xuan-deduct-uniapp/src/pages/mine/coins.vue
+++ b/xuan-deduct-uniapp/src/pages/mine/coins.vue
@@ -8,24 +8,37 @@
{{ coins }}
-
- 每日任务
+
+
-
-
-
- 📅
+
+
+
+ {{ index + 1 }}
-
- 每日签到
- +5金币
-
-
-
- {{ signedToday ? '已签到' : '签到' }}
+ {{ day.label }}
+ +{{ getDayReward(index) }}
+
+ 连续签到奖励递增,第7天可获得{{ getDayReward(6) }}金币
+
+
+
+
+ {{ signedToday ? '今日已签到' : '立即签到' }}
+
+ 签到可获得 +{{ todayReward }} 金币
+
+
+
+
+ 其他任务
+
@@ -62,7 +75,11 @@
金币说明
- 1. 每日签到可获得5金币\n2. 邀请好友注册可获得10金币\n3. 每次测算消耗1金币\n4. 会员用户无需消耗金币
+ 1. 连续签到奖励递增:第1天5金币,第2天6金币...第7天15金币
+2. 断签后重新从第1天开始计算
+3. 邀请好友注册可获得10金币
+4. 每次测算消耗1金币
+5. 会员用户无需消耗金币
@@ -73,14 +90,20 @@ export default {
return {
coins: 10,
signedToday: false,
- records: [
- { name: '新用户奖励', amount: 10, time: '2024-01-01 12:00' }
- ]
+ streakDays: 0,
+ weekDays: [],
+ records: []
+ }
+ },
+ computed: {
+ todayReward() {
+ return this.getDayReward(this.streakDays % 7)
}
},
onShow() {
this.loadCoins()
- this.checkSignIn()
+ this.initWeekProgress()
+ this.loadRecords()
},
onShareAppMessage() {
return {
@@ -90,16 +113,53 @@ export default {
}
},
methods: {
+ getDayReward(dayIndex) {
+ const rewards = [5, 6, 7, 8, 10, 12, 15]
+ return rewards[dayIndex % 7]
+ },
loadCoins() {
const coins = uni.getStorageSync('userCoins')
if (coins) {
this.coins = parseInt(coins)
}
},
- checkSignIn() {
- const lastSignIn = uni.getStorageSync('lastSignInDate')
- const today = new Date().toDateString()
- this.signedToday = lastSignIn === today
+ loadRecords() {
+ const records = uni.getStorageSync('coinRecords')
+ if (records) {
+ this.records = JSON.parse(records)
+ }
+ },
+ saveRecords() {
+ uni.setStorageSync('coinRecords', JSON.stringify(this.records))
+ },
+ initWeekProgress() {
+ const today = new Date()
+ const dayOfWeek = today.getDay()
+ const weekLabels = ['日', '一', '二', '三', '四', '五', '六']
+
+ const lastSignInStr = uni.getStorageSync('lastSignInDate')
+ const streakStr = uni.getStorageSync('streakDays')
+ this.streakDays = streakStr ? parseInt(streakStr) : 0
+
+ const todayStr = this.formatDate(today)
+ this.signedToday = lastSignInStr === todayStr
+
+ const signInHistory = uni.getStorageSync('signInHistory') || '{}'
+ const history = JSON.parse(signInHistory)
+
+ this.weekDays = []
+ for (let i = 0; i < 7; i++) {
+ const date = new Date(today)
+ date.setDate(today.getDate() - dayOfWeek + i)
+ const dateStr = this.formatDate(date)
+
+ this.weekDays.push({
+ label: weekLabels[i],
+ signed: history[dateStr] === true,
+ isToday: i === dayOfWeek,
+ date: dateStr
+ })
+ }
},
signIn() {
if (this.signedToday) {
@@ -107,20 +167,43 @@ export default {
return
}
- this.coins += 5
- uni.setStorageSync('userCoins', this.coins)
+ const today = new Date()
+ const todayStr = this.formatDate(today)
+ const lastSignInStr = uni.getStorageSync('lastSignInDate')
- const today = new Date().toDateString()
- uni.setStorageSync('lastSignInDate', today)
+ const yesterday = new Date(today)
+ yesterday.setDate(today.getDate() - 1)
+ const yesterdayStr = this.formatDate(yesterday)
+
+ if (lastSignInStr === yesterdayStr) {
+ this.streakDays++
+ } else {
+ this.streakDays = 1
+ }
+
+ const reward = this.getDayReward((this.streakDays - 1) % 7)
+ this.coins += reward
+
+ uni.setStorageSync('userCoins', this.coins)
+ uni.setStorageSync('lastSignInDate', todayStr)
+ uni.setStorageSync('streakDays', this.streakDays)
+
+ const signInHistory = uni.getStorageSync('signInHistory') || '{}'
+ const history = JSON.parse(signInHistory)
+ history[todayStr] = true
+ uni.setStorageSync('signInHistory', JSON.stringify(history))
this.records.unshift({
- name: '每日签到',
- amount: 5,
+ name: `每日签到(连续${this.streakDays}天)`,
+ amount: reward,
time: this.formatTime(new Date())
})
+ this.saveRecords()
this.signedToday = true
- uni.showToast({ title: '签到成功 +5金币', icon: 'success' })
+ this.initWeekProgress()
+
+ uni.showToast({ title: `签到成功 +${reward}金币`, icon: 'success' })
},
inviteFriend() {
uni.showShareMenu({
@@ -128,6 +211,12 @@ export default {
menus: ['shareAppMessage']
})
},
+ formatDate(date) {
+ const y = date.getFullYear()
+ const m = String(date.getMonth() + 1).padStart(2, '0')
+ const d = String(date.getDate()).padStart(2, '0')
+ return `${y}-${m}-${d}`
+ },
formatTime(date) {
const y = date.getFullYear()
const m = String(date.getMonth() + 1).padStart(2, '0')
@@ -188,6 +277,125 @@ page {
color: #78350F;
}
+.sign-card {
+ background: rgba(255, 255, 255, 0.95);
+ border-radius: 24rpx;
+ padding: 32rpx;
+ margin-bottom: 24rpx;
+ box-shadow: 0 8rpx 32rpx rgba(16, 185, 129, 0.1);
+ border: 2rpx solid rgba(16, 185, 129, 0.1);
+}
+
+.sign-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 24rpx;
+}
+
+.sign-title {
+ font-size: 30rpx;
+ font-weight: 600;
+ color: #065F46;
+}
+
+.sign-streak {
+ font-size: 24rpx;
+ color: #F59E0B;
+ font-weight: 500;
+}
+
+.week-progress {
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: 24rpx;
+}
+
+.day-item {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ flex: 1;
+}
+
+.day-circle {
+ width: 56rpx;
+ height: 56rpx;
+ border-radius: 50%;
+ background: #E5E7EB;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-bottom: 8rpx;
+}
+
+.day-circle.signed {
+ background: linear-gradient(135deg, #10B981 0%, #059669 100%);
+}
+
+.day-circle.today {
+ border: 3rpx solid #F59E0B;
+}
+
+.day-num {
+ font-size: 24rpx;
+ color: #6B7280;
+ font-weight: 500;
+}
+
+.day-circle.signed .day-num {
+ color: #ffffff;
+}
+
+.day-label {
+ font-size: 20rpx;
+ color: #9CA3AF;
+ margin-bottom: 4rpx;
+}
+
+.day-reward {
+ font-size: 18rpx;
+ color: #F59E0B;
+}
+
+.sign-info {
+ text-align: center;
+ margin-bottom: 24rpx;
+}
+
+.sign-tip {
+ font-size: 24rpx;
+ color: #6B7280;
+}
+
+.sign-btn-wrapper {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.sign-btn {
+ background: linear-gradient(135deg, #10B981 0%, #059669 100%);
+ padding: 20rpx 80rpx;
+ border-radius: 40rpx;
+ margin-bottom: 12rpx;
+}
+
+.sign-btn.done {
+ background: #D1D5DB;
+}
+
+.sign-btn-text {
+ font-size: 30rpx;
+ color: #ffffff;
+ font-weight: 600;
+}
+
+.sign-reward-tip {
+ font-size: 22rpx;
+ color: #F59E0B;
+}
+
.task-card {
background: rgba(255, 255, 255, 0.95);
border-radius: 24rpx;
@@ -259,10 +467,6 @@ page {
border-radius: 32rpx;
}
-.task-btn.done {
- background: #D1D5DB;
-}
-
.task-btn-text {
font-size: 26rpx;
color: #ffffff;
@@ -356,7 +560,7 @@ page {
}
.tips-content {
- font-size: 26rpx;
+ font-size: 24rpx;
color: #374151;
line-height: 1.8;
}