version 2

This commit is contained in:
2026-03-02 07:02:25 +08:00
parent 0c220d3fe2
commit 6e3f63185d
3 changed files with 242 additions and 31 deletions

View File

@@ -158,7 +158,8 @@ const habits = {
noPickyEating: { name: '不挑食', icon: '🥦' },
washHands: { name: '勤洗手', icon: '🧼' },
homeworkFast: { name: '写作业快', icon: '📝' },
earlySleep: { name: '早睡', icon: '🌙' }
earlySleep: { name: '早睡', icon: '🌙' },
cleanRoom: { name: '打扫卫生', icon: '🧹' }
};
// 坏习惯数据
@@ -174,7 +175,7 @@ const monsters = {
boss: {
name: '坏习惯大魔王',
health: 500,
habits: ['brushTeeth', 'noBedLate', 'noPickyEating', 'washHands', 'homeworkFast', 'earlySleep']
habits: ['brushTeeth', 'noBedLate', 'noPickyEating', 'washHands', 'homeworkFast', 'earlySleep', 'cleanRoom']
}
};
@@ -190,7 +191,7 @@ const badges = computed(() => starEnergyStore.badges);
// 检查习惯是否已打卡
const isChecked = (habit: keyof typeof habitData.value) => {
const today = new Date().toISOString().split('T')[0];
return habitData.value[habit].lastChecked === today;
return habitData.value[habit]?.lastChecked === today;
};
// 打卡习惯

View File

@@ -65,13 +65,38 @@
<!-- 已兑换奖励 -->
<div class="claimed-rewards" v-if="claimedRewards.length > 0">
<h3 class="claimed-title">🎉 已兑换的奖励</h3>
<div class="reward-stats">
<div class="stat-item">
<span class="stat-label">已兑换:</span>
<span class="stat-value">{{ claimedRewards.length }} </span>
</div>
<div class="stat-item">
<span class="stat-label">已给孩子:</span>
<span class="stat-value">{{ givenRewards.length }} </span>
</div>
<div class="stat-item">
<span class="stat-label">待领取:</span>
<span class="stat-value">{{ claimedRewards.length - givenRewards.length }} </span>
</div>
</div>
<div class="claimed-grid">
<div
v-for="id in claimedRewards"
:key="id"
class="claimed-card"
:class="{ given: givenRewards.includes(id) }"
>
{{ getRewardById(id)?.emoji }} {{ getRewardById(id)?.name }}
<div class="claimed-content">
{{ getRewardById(id)?.emoji }} {{ getRewardById(id)?.name }}
</div>
<button
v-if="!givenRewards.includes(id)"
class="give-btn"
@click="markRewardAsGiven(id)"
>
已给孩子
</button>
<div v-else class="given-badge">已给孩子 </div>
</div>
</div>
</div>
@@ -110,6 +135,9 @@ const currentCategory = ref('all');
// 已兑换奖励ID列表
const claimedRewards = computed(() => starEnergyStore.claimedRewards);
// 已给孩子的奖励ID列表
const givenRewards = computed(() => starEnergyStore.getGivenRewards || []);
// 弹窗状态
const showSuccessModal = ref(false);
const showInsufficientModal = ref(false);
@@ -166,7 +194,7 @@ const rewards = [
id: 'park_50',
name: '去公园玩',
description: '可以和爸爸妈妈去公园玩!',
cost: 50,
cost: 100,
emoji: '🎡',
category: 'activity'
},
@@ -191,7 +219,7 @@ const rewards = [
id: 'zoo_100',
name: '去动物园',
description: '可以去动物园看小动物!',
cost: 100,
cost: 500,
emoji: '🦁',
category: 'activity'
},
@@ -200,7 +228,7 @@ const rewards = [
id: 'lego_200',
name: '乐高积木套装',
description: '可以获得一套乐高积木!',
cost: 200,
cost: 400,
emoji: '🧱',
category: 'toy'
},
@@ -224,7 +252,7 @@ const rewards = [
id: 'amusement_200',
name: '游乐园一日游',
description: '可以和爸爸妈妈去游乐园玩一整天!',
cost: 200,
cost: 500,
emoji: '🎢',
category: 'activity'
},
@@ -232,7 +260,7 @@ const rewards = [
id: 'bike_200',
name: '自行车一辆',
description: '可以获得一辆全新的自行车!',
cost: 200,
cost: 1000,
emoji: '🚲',
category: 'toy'
},
@@ -250,7 +278,7 @@ const rewards = [
id: 'family_trip_500',
name: '家庭旅行',
description: '可以和家人一起去旅行!',
cost: 500,
cost: 1000,
emoji: '✈️',
category: 'activity'
},
@@ -258,7 +286,7 @@ const rewards = [
id: 'game_console_500',
name: '游戏机',
description: '可以获得一台游戏机!',
cost: 500,
cost: 2000,
emoji: '🎮',
category: 'toy'
},
@@ -372,7 +400,12 @@ const redeemReward = (reward: any) => {
// 根据ID获取奖励
const getRewardById = (id: string) => {
return rewards.find(reward => reward.id === id);
return rewards.find(reward => reward.id === id) || { emoji: '🎁', name: '未知奖励' };
};
// 标记奖励为已给孩子
const markRewardAsGiven = (rewardId: string) => {
starEnergyStore.markRewardAsGiven(rewardId);
};
// 关闭弹窗
@@ -661,9 +694,41 @@ const closeModal = () => {
animation: bounce 2s ease-in-out infinite;
}
/* 奖励统计 */
.reward-stats {
display: flex;
justify-content: space-around;
margin-bottom: 20px;
padding: 15px;
background: linear-gradient(135deg, #98FB98, #90EE90);
border-radius: 20px;
border: 3px solid #32CD32;
}
.stat-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 5px;
}
.stat-label {
font-size: 14px;
color: #006400;
font-weight: bold;
font-family: var(--cartoon-font);
}
.stat-value {
font-size: 18px;
color: #006400;
font-weight: bold;
font-family: var(--cartoon-font);
}
.claimed-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
gap: 15px;
}
@@ -677,6 +742,53 @@ const closeModal = () => {
color: white;
box-shadow: 0 4px 10px rgba(255, 215, 0, 0.4);
animation: bounce 2s ease-in-out infinite;
display: flex;
flex-direction: column;
gap: 10px;
min-height: 100px;
}
.claimed-card.given {
background: linear-gradient(135deg, #98FB98, #32CD32);
border: 3px solid #228B22;
}
.claimed-content {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
}
.give-btn {
background: rgba(255, 255, 255, 0.9);
color: #8B4513;
border: none;
padding: 8px 16px;
border-radius: 12px;
font-size: 12px;
font-weight: bold;
cursor: pointer;
transition: all 0.3s ease;
font-family: var(--cartoon-font);
}
.give-btn:hover {
background: white;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.given-badge {
background: rgba(255, 255, 255, 0.3);
color: white;
padding: 6px 12px;
border-radius: 10px;
font-size: 12px;
font-weight: bold;
font-family: var(--cartoon-font);
border: 2px solid rgba(255, 255, 255, 0.5);
}
/* 弹窗 */