feat: features as GitHub Issues style with comments/discussion, status filter

This commit is contained in:
2026-07-14 03:25:50 +08:00
parent f277711082
commit 4d8bc848e1
3 changed files with 101 additions and 22 deletions

View File

@@ -224,6 +224,15 @@ async function initSchema(connection) {
INDEX idx_item (item_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4`);
await createIfNotExists('feature_comments', `CREATE TABLE feature_comments (
id INT AUTO_INCREMENT PRIMARY KEY,
item_id INT NOT NULL,
user_id INT NOT NULL,
content TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
INDEX idx_item (item_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4`);
await createIfNotExists('server_groups', `CREATE TABLE server_groups (
id INT AUTO_INCREMENT PRIMARY KEY,
group_name VARCHAR(100) NOT NULL,

View File

@@ -5,19 +5,31 @@ const { authenticate, requireRole } = require('../middleware/auth');
const router = express.Router();
router.get('/', authenticate, async (req, res) => {
const { group_name, server_name, sort } = req.query;
const { group_name, server_name, sort, status } = req.query;
let orderClause = 'ORDER BY fi.created_at DESC';
if (sort === 'votes') orderClause = 'ORDER BY votes_count DESC, fi.created_at DESC';
const items = await query(`SELECT fi.*,
(SELECT COUNT(*) FROM feature_votes WHERE item_id = fi.id) as votes_count,
(SELECT COUNT(*) FROM feature_votes WHERE item_id = fi.id AND user_id = ?) as my_vote
(SELECT COUNT(*) FROM feature_votes WHERE item_id = fi.id AND user_id = ?) as my_vote,
(SELECT COUNT(*) FROM feature_comments WHERE item_id = fi.id) as comments_count
FROM feature_items fi
WHERE (fi.group_name = ? OR ? = '') AND (fi.server_name = ? OR ? = '')
${orderClause}`, [req.user.id, group_name||'', group_name||'', server_name||'', server_name||'']);
AND (fi.status = ? OR ? = '' OR ? = 'all')
${orderClause}`, [req.user.id, group_name||'', group_name||'', server_name||'', server_name||'', status||'', status||'', status||'']);
res.json(items);
});
router.get('/:id', authenticate, async (req, res) => {
const item = await getRow(`SELECT fi.*,
(SELECT COUNT(*) FROM feature_votes WHERE item_id = fi.id) as votes_count,
(SELECT COUNT(*) FROM feature_votes WHERE item_id = fi.id AND user_id = ?) as my_vote
FROM feature_items fi WHERE fi.id = ?`, [req.user.id, req.params.id]);
if (!item) return res.status(404).json({ error: '不存在' });
item.comments = await query(`SELECT fc.*, u.username, u.role FROM feature_comments fc LEFT JOIN users u ON fc.user_id = u.id WHERE fc.item_id = ? ORDER BY fc.created_at ASC`, [req.params.id]);
res.json(item);
});
router.post('/', authenticate, requireRole('owner'), async (req, res) => {
const { title, description, group_name, server_name } = req.body;
if (!title) return res.status(400).json({ error: '标题为必填' });
@@ -39,6 +51,7 @@ router.put('/:id', authenticate, requireRole('owner'), async (req, res) => {
});
router.delete('/:id', authenticate, requireRole('owner'), async (req, res) => {
await query('DELETE FROM feature_comments WHERE item_id = ?', [req.params.id]);
await query('DELETE FROM feature_votes WHERE item_id = ?', [req.params.id]);
await query('DELETE FROM feature_items WHERE id = ?', [req.params.id]);
res.json({ message: '已删除' });
@@ -56,4 +69,13 @@ router.post('/:id/vote', authenticate, async (req, res) => {
res.json({ message: '投票成功' });
});
router.post('/:id/comment', authenticate, async (req, res) => {
const { content } = req.body;
if (!content) return res.status(400).json({ error: '内容不能为空' });
const item = await getRow('SELECT id FROM feature_items WHERE id = ?', [req.params.id]);
if (!item) return res.status(404).json({ error: '不存在' });
await query('INSERT INTO feature_comments(item_id, user_id, content) VALUES (?,?,?)', [req.params.id, req.user.id, content]);
res.status(201).json({ message: '评论成功' });
});
module.exports = router;