423 lines
11 KiB
TypeScript
423 lines
11 KiB
TypeScript
import { defineStore } from 'pinia';
|
||
|
||
// 获取当前用户
|
||
const getCurrentUser = () => {
|
||
return localStorage.getItem('currentUser') || 'default';
|
||
};
|
||
|
||
// 从 localStorage 加载数据
|
||
const loadFromLocalStorage = () => {
|
||
try {
|
||
const user = getCurrentUser();
|
||
const saved = localStorage.getItem(`starEnergyData_${user}`);
|
||
return saved ? JSON.parse(saved) : null;
|
||
} catch (error) {
|
||
console.error('加载数据失败:', error);
|
||
return null;
|
||
}
|
||
};
|
||
|
||
// 保存到 localStorage
|
||
const saveToLocalStorage = (data: any) => {
|
||
try {
|
||
const user = getCurrentUser();
|
||
localStorage.setItem(`starEnergyData_${user}`, JSON.stringify(data));
|
||
} catch (error) {
|
||
console.error('保存数据失败:', error);
|
||
}
|
||
};
|
||
|
||
// 星星能量存储
|
||
export const useStarEnergyStore = defineStore('starEnergy', {
|
||
state: () => {
|
||
// 尝试从 localStorage 加载保存的数据
|
||
const savedData = loadFromLocalStorage();
|
||
|
||
// 获取当前日期
|
||
const today = new Date().toDateString();
|
||
|
||
// 检查是否需要重置怪兽状态和已兑换奖励
|
||
let monsters = savedData?.monsters;
|
||
let lastResetDate = savedData?.lastResetDate;
|
||
let claimedRewards = savedData?.claimedRewards;
|
||
let givenRewards = savedData?.givenRewards;
|
||
let bossDefeats = savedData?.bossDefeats;
|
||
|
||
// 防御性检查
|
||
if (!Array.isArray(claimedRewards)) {
|
||
claimedRewards = [];
|
||
}
|
||
if (!Array.isArray(givenRewards)) {
|
||
givenRewards = [];
|
||
}
|
||
if (typeof bossDefeats !== 'number') {
|
||
bossDefeats = 0;
|
||
}
|
||
|
||
// 如果是新的一天,重置怪兽状态和已兑换奖励
|
||
if (!lastResetDate || lastResetDate !== today) {
|
||
monsters = {
|
||
boss: {
|
||
name: '坏习惯大魔王',
|
||
health: 500,
|
||
defeated: false,
|
||
habits: ['brushTeeth', 'noBedLate', 'noPickyEating', 'washHands', 'homeworkFast', 'earlySleep', 'cleanRoom']
|
||
}
|
||
};
|
||
claimedRewards = []; // 重置已兑换奖励
|
||
givenRewards = []; // 重置已给孩子的奖励
|
||
lastResetDate = today;
|
||
}
|
||
|
||
return {
|
||
// 星星能量总数
|
||
total: typeof savedData?.total === 'number' ? savedData.total : 20,
|
||
// 各区域的星星能量
|
||
areas: savedData?.areas || {
|
||
knowledge: 0,
|
||
craft: 0,
|
||
logic: 0,
|
||
habit: 0,
|
||
parent: 0
|
||
},
|
||
// 习惯打卡记录
|
||
habits: {
|
||
brushTeeth: {
|
||
name: '刷牙',
|
||
count: 0,
|
||
streak: 0,
|
||
lastChecked: null as string | null,
|
||
...savedData?.habits?.brushTeeth
|
||
},
|
||
noBedLate: {
|
||
name: '不赖床',
|
||
count: 0,
|
||
streak: 0,
|
||
lastChecked: null as string | null,
|
||
...savedData?.habits?.noBedLate
|
||
},
|
||
noPickyEating: {
|
||
name: '不挑食',
|
||
count: 0,
|
||
streak: 0,
|
||
lastChecked: null as string | null,
|
||
...savedData?.habits?.noPickyEating
|
||
},
|
||
washHands: {
|
||
name: '勤洗手',
|
||
count: 0,
|
||
streak: 0,
|
||
lastChecked: null as string | null,
|
||
...savedData?.habits?.washHands
|
||
},
|
||
homeworkFast: {
|
||
name: '写作业快',
|
||
count: 0,
|
||
streak: 0,
|
||
lastChecked: null as string | null,
|
||
...savedData?.habits?.homeworkFast
|
||
},
|
||
earlySleep: {
|
||
name: '早睡',
|
||
count: 0,
|
||
streak: 0,
|
||
lastChecked: null as string | null,
|
||
...savedData?.habits?.earlySleep
|
||
},
|
||
cleanRoom: {
|
||
name: '打扫卫生',
|
||
count: 0,
|
||
streak: 0,
|
||
lastChecked: null as string | null,
|
||
...savedData?.habits?.cleanRoom
|
||
}
|
||
},
|
||
// 怪兽状态
|
||
monsters: monsters || {
|
||
boss: {
|
||
name: '坏习惯大魔王',
|
||
health: 500,
|
||
defeated: false,
|
||
habits: ['brushTeeth', 'noBedLate', 'noPickyEating', 'washHands', 'homeworkFast', 'earlySleep', 'cleanRoom']
|
||
}
|
||
},
|
||
// 勋章
|
||
badges: Array.isArray(savedData?.badges) ? savedData.badges : [] as string[],
|
||
// 已兑换奖励
|
||
claimedRewards: claimedRewards,
|
||
// 已给孩子的奖励
|
||
givenRewards: givenRewards,
|
||
// 击败BOSS次数
|
||
bossDefeats: bossDefeats,
|
||
// 上次重置日期
|
||
lastResetDate: lastResetDate || today
|
||
};
|
||
},
|
||
|
||
getters: {
|
||
// 获取总星星能量
|
||
getTotalEnergy: (state) => state.total,
|
||
|
||
// 获取各区域能量
|
||
getAreaEnergy: (state) => (area: keyof typeof state.areas) => state.areas[area],
|
||
|
||
// 获取习惯打卡情况
|
||
getHabitStatus: (state) => (habit: keyof typeof state.habits) => state.habits[habit],
|
||
|
||
// 获取怪兽状态
|
||
getMonsterStatus: (state) => (monster: keyof typeof state.monsters) => state.monsters[monster],
|
||
|
||
// 获取所有勋章
|
||
getAllBadges: (state) => state.badges,
|
||
|
||
// 获取已兑换奖励
|
||
getClaimedRewards: (state) => state.claimedRewards,
|
||
|
||
// 获取已给孩子的奖励
|
||
getGivenRewards: (state) => state.givenRewards,
|
||
|
||
// 获取击败BOSS次数
|
||
getBossDefeats: (state) => state.bossDefeats
|
||
},
|
||
|
||
actions: {
|
||
// 保存状态到 localStorage
|
||
$persist() {
|
||
const data = {
|
||
total: this.total,
|
||
areas: this.areas,
|
||
habits: this.habits,
|
||
monsters: this.monsters,
|
||
badges: this.badges,
|
||
claimedRewards: this.claimedRewards,
|
||
givenRewards: this.givenRewards,
|
||
bossDefeats: this.bossDefeats,
|
||
lastResetDate: this.lastResetDate
|
||
};
|
||
saveToLocalStorage(data);
|
||
},
|
||
|
||
// 增加星星能量
|
||
addEnergy(amount: number, area: keyof typeof this.areas) {
|
||
this.total += amount;
|
||
this.areas[area] += amount;
|
||
this.$persist();
|
||
},
|
||
|
||
// 减少星星能量
|
||
removeEnergy(amount: number) {
|
||
if (this.total >= amount) {
|
||
this.total -= amount;
|
||
this.$persist();
|
||
return true;
|
||
}
|
||
return false;
|
||
},
|
||
|
||
// 打卡习惯
|
||
checkHabit(habit: keyof typeof this.habits) {
|
||
const today = new Date().toISOString().split('T')[0];
|
||
const habitData = this.habits[habit];
|
||
|
||
// 检查习惯数据是否存在
|
||
if (!habitData) {
|
||
return;
|
||
}
|
||
|
||
// 防止重复打卡
|
||
if (habitData.lastChecked === today) {
|
||
return;
|
||
}
|
||
|
||
// 保存原来的lastChecked值用于连续打卡计算
|
||
const originalLastChecked = habitData.lastChecked;
|
||
|
||
// 更新打卡记录
|
||
habitData.count++;
|
||
habitData.lastChecked = today;
|
||
|
||
// 更新连续打卡天数
|
||
const yesterday = new Date();
|
||
yesterday.setDate(yesterday.getDate() - 1);
|
||
const yesterdayStr = yesterday.toISOString().split('T')[0];
|
||
|
||
if (originalLastChecked === yesterdayStr) {
|
||
habitData.streak++;
|
||
} else {
|
||
habitData.streak = 1;
|
||
}
|
||
|
||
// 奖励星星能量
|
||
this.addEnergy(10, 'habit');
|
||
|
||
// 连续3天打卡额外奖励
|
||
if (habitData.streak % 3 === 0) {
|
||
this.addEnergy(5, 'habit');
|
||
}
|
||
|
||
// 保存数据
|
||
this.$persist();
|
||
},
|
||
|
||
// 攻击怪兽
|
||
attackMonster(monster: keyof typeof this.monsters, energy: number) {
|
||
const monsterData = this.monsters[monster];
|
||
if (monsterData.defeated) return;
|
||
|
||
// 每次攻击消耗10颗星星,固定掉10滴血
|
||
if (this.total >= 10) {
|
||
monsterData.health = Math.max(0, monsterData.health - 10);
|
||
|
||
// 扣除星星能量
|
||
this.total -= 10;
|
||
|
||
// 检查是否击败
|
||
if (monsterData.health === 0) {
|
||
monsterData.defeated = true;
|
||
// 奖励星星能量
|
||
this.addEnergy(200, 'habit');
|
||
|
||
// 增加击败BOSS次数
|
||
this.bossDefeats++;
|
||
|
||
// 解锁勋章
|
||
const badge = '习惯守护者';
|
||
if (!this.badges.includes(badge)) {
|
||
this.badges.push(badge);
|
||
}
|
||
}
|
||
this.$persist();
|
||
}
|
||
},
|
||
|
||
// 亲子合力攻击
|
||
parentAttack(monster: keyof typeof this.monsters) {
|
||
const monsterData = this.monsters[monster];
|
||
if (monsterData.defeated) return;
|
||
|
||
// 亲子攻击固定掉10滴血
|
||
monsterData.health = Math.max(0, monsterData.health - 10);
|
||
|
||
// 检查是否击败
|
||
if (monsterData.health === 0) {
|
||
monsterData.defeated = true;
|
||
// 奖励星星能量
|
||
this.addEnergy(200, 'habit');
|
||
|
||
// 增加击败BOSS次数
|
||
this.bossDefeats++;
|
||
|
||
// 解锁勋章
|
||
const badge = '习惯守护者';
|
||
if (!this.badges.includes(badge)) {
|
||
this.badges.push(badge);
|
||
}
|
||
}
|
||
this.$persist();
|
||
},
|
||
|
||
// 兑换奖励
|
||
redeemReward(rewardId: string, cost: number) {
|
||
if (this.total < cost) {
|
||
return false;
|
||
}
|
||
this.total -= cost;
|
||
if (!this.claimedRewards.includes(rewardId)) {
|
||
this.claimedRewards.push(rewardId);
|
||
}
|
||
this.$persist();
|
||
return true;
|
||
},
|
||
|
||
// 标记奖励为已给孩子
|
||
markRewardAsGiven(rewardId: string) {
|
||
if (!this.givenRewards.includes(rewardId)) {
|
||
this.givenRewards.push(rewardId);
|
||
this.$persist();
|
||
return true;
|
||
}
|
||
return false;
|
||
},
|
||
|
||
// 取消标记奖励为已给孩子
|
||
unmarkRewardAsGiven(rewardId: string) {
|
||
const index = this.givenRewards.indexOf(rewardId);
|
||
if (index > -1) {
|
||
this.givenRewards.splice(index, 1);
|
||
this.$persist();
|
||
return true;
|
||
}
|
||
return false;
|
||
},
|
||
|
||
// 重置所有数据(清除游戏进度)
|
||
resetAll() {
|
||
this.total = 0;
|
||
this.areas = {
|
||
knowledge: 0,
|
||
craft: 0,
|
||
logic: 0,
|
||
habit: 0,
|
||
parent: 0
|
||
};
|
||
this.habits = {
|
||
brushTeeth: {
|
||
name: '刷牙',
|
||
count: 0,
|
||
streak: 0,
|
||
lastChecked: null
|
||
},
|
||
noBedLate: {
|
||
name: '不赖床',
|
||
count: 0,
|
||
streak: 0,
|
||
lastChecked: null
|
||
},
|
||
noPickyEating: {
|
||
name: '不挑食',
|
||
count: 0,
|
||
streak: 0,
|
||
lastChecked: null
|
||
},
|
||
washHands: {
|
||
name: '勤洗手',
|
||
count: 0,
|
||
streak: 0,
|
||
lastChecked: null
|
||
},
|
||
homeworkFast: {
|
||
name: '写作业快',
|
||
count: 0,
|
||
streak: 0,
|
||
lastChecked: null
|
||
},
|
||
earlySleep: {
|
||
name: '早睡',
|
||
count: 0,
|
||
streak: 0,
|
||
lastChecked: null
|
||
},
|
||
cleanRoom: {
|
||
name: '打扫卫生',
|
||
count: 0,
|
||
streak: 0,
|
||
lastChecked: null
|
||
}
|
||
};
|
||
this.monsters = {
|
||
boss: {
|
||
name: '坏习惯大魔王',
|
||
health: 500,
|
||
defeated: false,
|
||
habits: ['brushTeeth', 'noBedLate', 'noPickyEating', 'washHands', 'homeworkFast', 'earlySleep', 'cleanRoom']
|
||
}
|
||
};
|
||
this.badges = [];
|
||
this.claimedRewards = [];
|
||
this.givenRewards = [];
|
||
this.bossDefeats = 0;
|
||
const user = getCurrentUser();
|
||
localStorage.removeItem(`starEnergyData_${user}`);
|
||
}
|
||
}
|
||
}); |