feat: Paper plugin + external API POST endpoint

This commit is contained in:
2026-07-13 01:28:33 +08:00
parent ea3cd67e02
commit de5a46f392
9 changed files with 403 additions and 0 deletions

View File

@@ -19,6 +19,41 @@ function externalAuth(req, res, next) {
router.use(externalAuth);
router.post('/tickets', async (req, res) => {
const { type, title, reporter_game_name, reporter_game_uid,
target_game_name, target_game_uid, reason, description } = req.body;
if (!type || !['report','suggestion','appeal'].includes(type)) return res.status(400).json({ error: '类型不正确' });
if (!title) return res.status(400).json({ error: '标题不能为空' });
if (!reporter_game_name || !reporter_game_uid) return res.status(400).json({ error: '请填写游戏名称和UID' });
if (type === 'report') {
if (!reason) return res.status(400).json({ error: '请填写举报原因' });
}
if (type === 'suggestion' && !description) return res.status(400).json({ error: '建议内容不能为空' });
if (type === 'appeal') {
if (!reason) return res.status(400).json({ error: '请填写申诉理由' });
if (!description) return res.status(400).json({ error: '请填写详细申诉内容' });
}
const countRow = await getRow("SELECT COUNT(*) as c FROM tickets WHERE (reporter_game_name = ? OR reporter_game_uid = ?) AND status IN ('pending','processing','awaiting_info','appealing')", [reporter_game_name, reporter_game_uid]);
if (countRow.c >= 5) return res.status(400).json({ error: '待处理工单已达上限' });
const trackingToken = require('uuid').v4();
const [r] = await query(`INSERT INTO tickets(type,title,reporter_game_name,reporter_game_uid,
target_game_name,target_game_uid,reason,description,tracking_token) VALUES (?,?,?,?,?,?,?,?,?)`,
[type, title, reporter_game_name, reporter_game_uid,
(type==='report')?(target_game_name||''):null,
(type==='report')?(target_game_uid||''):null,
(type==='report'||type==='appeal')?reason:null,
(type==='suggestion'||type==='appeal')?description:'',
trackingToken]);
await query("INSERT INTO responses(ticket_id, content, is_staff) VALUES (?,?,0)", [r.insertId, `游戏内${type==='report'?'举报':type==='appeal'?'申诉':'建议'}\n提交人: ${reporter_game_name} (UID: ${reporter_game_uid})\n${reason||description||''}`]);
res.status(201).json({ id: r.insertId, tracking_token: trackingToken });
});
router.get('/tickets', async (req, res) => {
const { type, status, page, limit } = req.query;
let q = `SELECT t.id, t.type, t.title, t.status, t.priority,