feat: 兑换改为扣除指定枚数并新增倒计时确认弹窗

- 后端按 collectedAt 顺序扣除最早的 threshold 枚图章,保留剩余
- 前端新增二次确认弹窗,含工作人员提示与 5 秒倒计时防误触
- 后台日志"图章数"列改为"扣除枚数"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-19 18:58:51 +08:00
parent ae63cb1d85
commit 613684384b
3 changed files with 156 additions and 14 deletions

View File

@@ -41,10 +41,19 @@ router.post("/redeem", requireAuth, async (req, res) => {
}
const redemption = await prisma.$transaction(async (tx) => {
const record = await tx.redemption.create({
data: { userId: req.userId!, ruleId: rule.id, stampCount: collectionCount },
// Deduct the oldest N collections (chronological order by collectedAt)
const toDelete = await tx.collection.findMany({
where: { userId: req.userId! },
orderBy: { collectedAt: "asc" },
take: rule.threshold,
select: { id: true },
});
await tx.collection.deleteMany({
where: { id: { in: toDelete.map((c) => c.id) } },
});
const record = await tx.redemption.create({
data: { userId: req.userId!, ruleId: rule.id, stampCount: rule.threshold },
});
await tx.collection.deleteMany({ where: { userId: req.userId! } });
return record;
});