const { PinyinAchievement, PinyinProgress } = require('../../models/pinyin'); /** * 获取成就列表 * GET /api/pinyin/achievements */ exports.getAchievements = async (req, res) => { try { const { type } = req.query; const query = { isActive: true }; if (type) query.type = type; const achievements = await PinyinAchievement.find(query) .sort({ order: 1, createdAt: 1 }) .select('-__v'); res.json({ code: 0, message: 'success', data: { list: achievements } }); } catch (error) { console.error('获取成就列表失败:', error); res.status(500).json({ code: 500, message: '获取成就列表失败', error: error.message }); } }; /** * 获取用户已获得的成就 * GET /api/pinyin/achievements/my */ exports.getMyAchievements = async (req, res) => { try { const userId = req.user._id; const progress = await PinyinProgress.findOne({ userId }); if (!progress || !progress.achievements || progress.achievements.length === 0) { return res.json({ code: 0, message: 'success', data: { total: 0, list: [] } }); } // 获取成就详情 const achievementCodes = progress.achievements.map(a => a.code); const achievements = await PinyinAchievement.find({ code: { $in: achievementCodes } }).select('-__v'); // 合并获得时间 const achievementsWithTime = achievements.map(ach => { const userAch = progress.achievements.find(a => a.code === ach.code); return { ...ach.toObject(), obtainedAt: userAch ? userAch.obtainedAt : null }; }); res.json({ code: 0, message: 'success', data: { total: achievementsWithTime.length, list: achievementsWithTime } }); } catch (error) { console.error('获取用户成就失败:', error); res.status(500).json({ code: 500, message: '获取用户成就失败', error: error.message }); } }; /** * 检查成就达成 * POST /api/pinyin/achievements/check */ exports.checkAchievements = async (req, res) => { try { const userId = req.user._id; const progress = await PinyinProgress.findOne({ userId }); if (!progress) { return res.json({ code: 0, message: 'success', data: { newAchievements: [] } }); } // 获取所有启用的成就 const achievements = await PinyinAchievement.find({ isActive: true }); const newAchievements = []; for (const achievement of achievements) { // 检查是否已获得 if (progress.achievements.some(a => a.code === achievement.code)) { continue; } // 检查条件 const isAchieved = checkCondition(progress, achievement.condition); if (isAchieved) { progress.achievements.push({ code: achievement.code, obtainedAt: new Date() }); newAchievements.push({ code: achievement.code, name: achievement.name, description: achievement.description, icon: achievement.icon, reward: achievement.reward }); } } if (newAchievements.length > 0) { await progress.save(); } res.json({ code: 0, message: 'success', data: { newAchievements } }); } catch (error) { console.error('检查成就失败:', error); res.status(500).json({ code: 500, message: '检查成就失败', error: error.message }); } }; /** * 创建成就(管理员) * POST /api/pinyin/achievements */ exports.createAchievement = async (req, res) => { try { const achievementData = req.body; // 检查code是否已存在 const existing = await PinyinAchievement.findOne({ code: achievementData.code }); if (existing) { return res.status(400).json({ code: 400, message: '该成就代码已存在' }); } const achievement = new PinyinAchievement(achievementData); await achievement.save(); res.status(201).json({ code: 0, message: '创建成功', data: achievement }); } catch (error) { console.error('创建成就失败:', error); res.status(500).json({ code: 500, message: '创建成就失败', error: error.message }); } }; /** * 更新成就(管理员) * PUT /api/pinyin/achievements/:id */ exports.updateAchievement = async (req, res) => { try { const { id } = req.params; const updateData = req.body; // 不允许修改code delete updateData.code; const achievement = await PinyinAchievement.findByIdAndUpdate( id, { $set: updateData }, { new: true, runValidators: true } ); if (!achievement) { return res.status(404).json({ code: 404, message: '成就不存在' }); } res.json({ code: 0, message: '更新成功', data: achievement }); } catch (error) { console.error('更新成就失败:', error); res.status(500).json({ code: 500, message: '更新成就失败', error: error.message }); } }; /** * 删除成就(管理员) * DELETE /api/pinyin/achievements/:id */ exports.deleteAchievement = async (req, res) => { try { const { id } = req.params; const achievement = await PinyinAchievement.findByIdAndDelete(id); if (!achievement) { return res.status(404).json({ code: 404, message: '成就不存在' }); } res.json({ code: 0, message: '删除成功' }); } catch (error) { console.error('删除成就失败:', error); res.status(500).json({ code: 500, message: '删除成就失败', error: error.message }); } }; /** * 检查成就条件 * @param {Object} progress - 用户进度 * @param {Object} condition - 条件 * @returns {Boolean} */ function checkCondition(progress, condition) { switch (condition.type) { case 'explore_count': return progress.totalExplored >= condition.value; case 'collect_count': return progress.totalStones >= condition.value; case 'streak_days': return progress.streakDays >= condition.value; case 'complete_symbol': return progress.isSymbolCompleted(condition.symbol); default: return false; } }