Files
ai-dimension/backend/wdkj-server/src/controllers/pinyin/achievementController.js
T
Yuzhiran Dev 24cd9cef53 🎉 feat: initialize 宇之然AI维度 project
- uni-app Vue3 frontend with dark glassmorphism theme
- 5 AI dimensions: Origin / Development / Current / Learning / Trend
- AI Chat system prompt updated from geometry to AI
- 23 AI knowledge articles initialized in DB
- Trend API + cron job for daily news
- Product pricing (Pro ¥19.9, VIP ¥39.9)
- Pinia stores + API utilities
- AGENTS.md documentation
2026-07-10 13:26:04 +08:00

289 lines
6.5 KiB
JavaScript
Executable File

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;
}
}