feat: 优化每日签到功能
- 显示一周签到进度,已签到显示绿色圆圈 - 今日显示橙色边框高亮 - 连续签到奖励递增:第1天5金币到第7天15金币 - 断签后重新从第1天开始计算 - 保存签到历史记录
This commit is contained in:
1 parent
058bf0c2bd
commit
e34586e3f0
1 file changed
+238
-34
@@ -8,24 +8,37 @@
|
||||
<text class="coins-value">{{ coins }}</text>
|
||||
</view>
|
||||
|
||||
<view class="task-card">
|
||||
<text class="task-title">每日任务</text>
|
||||
<view class="sign-card">
|
||||
<view class="sign-header">
|
||||
<text class="sign-title">每日签到</text>
|
||||
<text class="sign-streak">已连签 {{ streakDays }} 天</text>
|
||||
</view>
|
||||
|
||||
<view class="task-item">
|
||||
<view class="task-left">
|
||||
<view class="task-icon">
|
||||
<text class="task-icon-text">📅</text>
|
||||
<view class="week-progress">
|
||||
<view class="day-item" v-for="(day, index) in weekDays" :key="index">
|
||||
<view class="day-circle" :class="{ signed: day.signed, today: day.isToday }">
|
||||
<text class="day-num">{{ index + 1 }}</text>
|
||||
</view>
|
||||
<view class="task-info">
|
||||
<text class="task-name">每日签到</text>
|
||||
<text class="task-reward">+5金币</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="task-btn" :class="{ done: signedToday }" @click="signIn">
|
||||
<text class="task-btn-text">{{ signedToday ? '已签到' : '签到' }}</text>
|
||||
<text class="day-label">{{ day.label }}</text>
|
||||
<text class="day-reward">+{{ getDayReward(index) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="sign-info">
|
||||
<text class="sign-tip">连续签到奖励递增,第7天可获得{{ getDayReward(6) }}金币</text>
|
||||
</view>
|
||||
|
||||
<view class="sign-btn-wrapper">
|
||||
<view class="sign-btn" :class="{ done: signedToday }" @click="signIn">
|
||||
<text class="sign-btn-text">{{ signedToday ? '今日已签到' : '立即签到' }}</text>
|
||||
</view>
|
||||
<text class="sign-reward-tip" v-if="!signedToday">签到可获得 +{{ todayReward }} 金币</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="task-card">
|
||||
<text class="task-title">其他任务</text>
|
||||
|
||||
<view class="task-item">
|
||||
<view class="task-left">
|
||||
<view class="task-icon">
|
||||
@@ -62,7 +75,11 @@
|
||||
|
||||
<view class="tips-card">
|
||||
<text class="tips-title">金币说明</text>
|
||||
<text class="tips-content">1. 每日签到可获得5金币\n2. 邀请好友注册可获得10金币\n3. 每次测算消耗1金币\n4. 会员用户无需消耗金币</text>
|
||||
<text class="tips-content">1. 连续签到奖励递增:第1天5金币,第2天6金币...第7天15金币
|
||||
2. 断签后重新从第1天开始计算
|
||||
3. 邀请好友注册可获得10金币
|
||||
4. 每次测算消耗1金币
|
||||
5. 会员用户无需消耗金币</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user