feat: features as GitHub Issues style with comments/discussion, status filter
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user