feat: 添加作品/草稿/AI配额等后端API
This commit is contained in:
@@ -128,6 +128,95 @@ const UserModel = {
|
|||||||
|
|
||||||
const [rows] = await pool.query(sql, params);
|
const [rows] = await pool.query(sql, params);
|
||||||
return rows;
|
return rows;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取我的作品
|
||||||
|
async getMyWorks(userId) {
|
||||||
|
try {
|
||||||
|
const [rows] = await pool.query(
|
||||||
|
`SELECT id, title, description, category, cover_url, play_count, like_count,
|
||||||
|
comment_count, status, created_at, updated_at,
|
||||||
|
COALESCE(earnings, 0) as earnings
|
||||||
|
FROM stories
|
||||||
|
WHERE author_id = ?
|
||||||
|
ORDER BY created_at DESC`,
|
||||||
|
[userId]
|
||||||
|
);
|
||||||
|
return rows;
|
||||||
|
} catch (e) {
|
||||||
|
// 表可能还没有author_id字段,返回空数组
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取草稿箱
|
||||||
|
async getDrafts(userId) {
|
||||||
|
try {
|
||||||
|
const [rows] = await pool.query(
|
||||||
|
`SELECT id, title, category, node_count, source, created_at, updated_at
|
||||||
|
FROM story_drafts
|
||||||
|
WHERE user_id = ?
|
||||||
|
ORDER BY updated_at DESC`,
|
||||||
|
[userId]
|
||||||
|
);
|
||||||
|
return rows;
|
||||||
|
} catch (e) {
|
||||||
|
// 表可能不存在,返回空数组
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取最近游玩
|
||||||
|
async getRecentPlayed(userId, limit = 10) {
|
||||||
|
const [rows] = await pool.query(
|
||||||
|
`SELECT s.id, s.title, s.category, s.description, s.cover_url,
|
||||||
|
up.current_node_key, up.is_completed,
|
||||||
|
CASE WHEN up.is_completed THEN '已完成' ELSE '进行中' END as progress
|
||||||
|
FROM user_progress up
|
||||||
|
JOIN stories s ON up.story_id = s.id
|
||||||
|
WHERE up.user_id = ?
|
||||||
|
ORDER BY up.updated_at DESC
|
||||||
|
LIMIT ?`,
|
||||||
|
[userId, limit]
|
||||||
|
);
|
||||||
|
return rows;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取AI创作历史
|
||||||
|
async getAIHistory(userId, limit = 20) {
|
||||||
|
try {
|
||||||
|
const [rows] = await pool.query(
|
||||||
|
`SELECT id, gen_type, input_prompt, output_content, status, created_at
|
||||||
|
FROM ai_generations
|
||||||
|
WHERE user_id = ?
|
||||||
|
ORDER BY created_at DESC
|
||||||
|
LIMIT ?`,
|
||||||
|
[userId, limit]
|
||||||
|
);
|
||||||
|
return rows;
|
||||||
|
} catch (e) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取AI配额
|
||||||
|
async getAIQuota(userId) {
|
||||||
|
try {
|
||||||
|
const [rows] = await pool.query(
|
||||||
|
`SELECT daily_free_total as daily, daily_free_used as used,
|
||||||
|
purchased_quota as purchased, gift_quota as gift
|
||||||
|
FROM user_ai_quota
|
||||||
|
WHERE user_id = ?`,
|
||||||
|
[userId]
|
||||||
|
);
|
||||||
|
if (rows.length > 0) {
|
||||||
|
return rows[0];
|
||||||
|
}
|
||||||
|
// 没有记录则返回默认值
|
||||||
|
return { daily: 3, used: 0, purchased: 0, gift: 0 };
|
||||||
|
} catch (e) {
|
||||||
|
return { daily: 3, used: 0, purchased: 0, gift: 0 };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -121,4 +121,64 @@ router.get('/endings', async (req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 获取我的作品
|
||||||
|
router.get('/my-works', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { userId } = req.query;
|
||||||
|
const works = await UserModel.getMyWorks(parseInt(userId));
|
||||||
|
res.json({ code: 0, data: works });
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取作品失败:', err);
|
||||||
|
res.status(500).json({ code: 500, message: '获取作品失败' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取草稿箱
|
||||||
|
router.get('/drafts', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { userId } = req.query;
|
||||||
|
const drafts = await UserModel.getDrafts(parseInt(userId));
|
||||||
|
res.json({ code: 0, data: drafts });
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取草稿失败:', err);
|
||||||
|
res.status(500).json({ code: 500, message: '获取草稿失败' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取最近游玩
|
||||||
|
router.get('/recent-played', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { userId, limit } = req.query;
|
||||||
|
const recent = await UserModel.getRecentPlayed(parseInt(userId), parseInt(limit) || 10);
|
||||||
|
res.json({ code: 0, data: recent });
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取最近游玩失败:', err);
|
||||||
|
res.status(500).json({ code: 500, message: '获取最近游玩失败' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取AI创作历史
|
||||||
|
router.get('/ai-history', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { userId, limit } = req.query;
|
||||||
|
const history = await UserModel.getAIHistory(parseInt(userId), parseInt(limit) || 20);
|
||||||
|
res.json({ code: 0, data: history });
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取AI历史失败:', err);
|
||||||
|
res.status(500).json({ code: 500, message: '获取AI历史失败' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取AI配额
|
||||||
|
router.get('/ai-quota', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { userId } = req.query;
|
||||||
|
const quota = await UserModel.getAIQuota(parseInt(userId));
|
||||||
|
res.json({ code: 0, data: quota });
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取AI配额失败:', err);
|
||||||
|
res.status(500).json({ code: 500, message: '获取AI配额失败' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|||||||
Reference in New Issue
Block a user