feat(marketing): implement recharge tiers and coupon management across admin, server, and uniapp

这个提交包含在:
xcbyy
2026-10-10 09:22:46 +08:00
父节点 51682fffea
当前提交 d9c8388711
共有 12 个文件被更改,包括 1494 次插入 和 7 次删除

查看文件

@@ -863,6 +863,194 @@ app.delete('/api/admin/nav-categories/:id', async (req: Request, res: Response)
}
});
// ===================== 营销中心 API =====================
// 1. 充值阶梯接口
// 移动端:获取启用的充值阶梯
app.get('/api/marketing/recharge-tiers', async (_req: Request, res: Response) => {
try {
const list = await repo.getRechargeTiers();
res.json({ code: 20000, data: list });
} catch (err: any) {
res.status(500).json({ code: 50000, message: err.message });
}
});
// 管理后台:获取全部充值阶梯
app.get('/api/admin/recharge-tiers', async (_req: Request, res: Response) => {
try {
const list = await repo.getAdminRechargeTiers();
res.json({ code: 20000, data: list });
} catch (err: any) {
res.status(500).json({ code: 50000, message: err.message });
}
});
// 管理后台:新增充值阶梯
app.post('/api/admin/recharge-tiers', async (req: Request, res: Response) => {
try {
const { amount, bonusAmount, tag, sortOrder, status } = req.body;
if (amount === undefined || Number(amount) <= 0) {
return res.status(400).json({ code: 40000, message: '充值金额必须大于0' });
}
const tier = await repo.createRechargeTier({
amount: Number(amount),
bonusAmount: bonusAmount !== undefined ? Number(bonusAmount) : 0,
tag: tag || '',
sortOrder: sortOrder !== undefined ? Number(sortOrder) : 0,
status: status !== undefined ? Number(status) : 1
});
res.json({ code: 20000, data: tier, message: '充值阶梯创建成功' });
} catch (err: any) {
res.status(400).json({ code: 40000, message: err.message });
}
});
// 管理后台:修改充值阶梯
app.put('/api/admin/recharge-tiers/:id', async (req: Request, res: Response) => {
try {
const tierId = String(req.params.id);
const { amount, bonusAmount, tag, sortOrder, status } = req.body;
const updated = await repo.updateRechargeTier(tierId, {
amount: amount !== undefined ? Number(amount) : undefined,
bonusAmount: bonusAmount !== undefined ? Number(bonusAmount) : undefined,
tag,
sortOrder: sortOrder !== undefined ? Number(sortOrder) : undefined,
status: status !== undefined ? Number(status) : undefined
});
if (!updated) {
return res.status(404).json({ code: 40400, message: '充值阶梯不存在或已被删除' });
}
res.json({ code: 20000, data: updated, message: '充值阶梯修改成功' });
} catch (err: any) {
res.status(400).json({ code: 40000, message: err.message });
}
});
// 管理后台:删除充值阶梯
app.delete('/api/admin/recharge-tiers/:id', async (req: Request, res: Response) => {
try {
const tierId = String(req.params.id);
const ok = await repo.deleteRechargeTier(tierId);
if (!ok) {
return res.status(404).json({ code: 40400, message: '充值阶梯不存在或已被删除' });
}
res.json({ code: 20000, data: null, message: '充值阶梯已删除' });
} catch (err: any) {
res.status(400).json({ code: 40000, message: err.message });
}
});
// 2. 优惠券接口
// 移动端:领券中心或下单结算可用券列表
app.get('/api/marketing/coupons', async (req: Request, res: Response) => {
try {
const category = req.query.category ? String(req.query.category) : undefined;
const list = await repo.getCoupons(category);
res.json({ code: 20000, data: list });
} catch (err: any) {
res.status(500).json({ code: 50000, message: err.message });
}
});
// 管理后台:获取全部优惠券
app.get('/api/admin/coupons', async (_req: Request, res: Response) => {
try {
const list = await repo.getAdminCoupons();
res.json({ code: 20000, data: list });
} catch (err: any) {
res.status(500).json({ code: 50000, message: err.message });
}
});
// 管理后台:新增优惠券
app.post('/api/admin/coupons', async (req: Request, res: Response) => {
try {
const { name, discountAmount, minSpend, validDays, totalCount, categoryLimit, description, status } = req.body;
if (!name || !name.trim()) {
return res.status(400).json({ code: 40000, message: '优惠券名称不能为空' });
}
if (!discountAmount || Number(discountAmount) <= 0) {
return res.status(400).json({ code: 40000, message: '减免面额必须大于0' });
}
// 微信内容安全检测
const sec = contentSecurityService.checkText(name + ' ' + (description || ''));
if (!sec.pass) {
return res.status(400).json({ code: sec.code, message: sec.message });
}
const coupon = await repo.createCoupon({
name: name.trim(),
discountAmount: Number(discountAmount),
minSpend: minSpend !== undefined ? Number(minSpend) : 0,
validDays: validDays !== undefined ? Number(validDays) : 7,
totalCount: totalCount !== undefined ? Number(totalCount) : 1000,
categoryLimit: categoryLimit || 'ALL',
description: description || '',
status: status !== undefined ? Number(status) : 1
});
res.json({ code: 20000, data: coupon, message: '优惠券创建成功' });
} catch (err: any) {
res.status(400).json({ code: 40000, message: err.message });
}
});
// 管理后台:修改优惠券
app.put('/api/admin/coupons/:id', async (req: Request, res: Response) => {
try {
const couponId = String(req.params.id);
const { name, discountAmount, minSpend, validDays, totalCount, categoryLimit, description, status } = req.body;
if (name) {
const sec = contentSecurityService.checkText(name + ' ' + (description || ''));
if (!sec.pass) {
return res.status(400).json({ code: sec.code, message: sec.message });
}
}
const updated = await repo.updateCoupon(couponId, {
name: name ? name.trim() : undefined,
discountAmount: discountAmount !== undefined ? Number(discountAmount) : undefined,
minSpend: minSpend !== undefined ? Number(minSpend) : undefined,
validDays: validDays !== undefined ? Number(validDays) : undefined,
totalCount: totalCount !== undefined ? Number(totalCount) : undefined,
categoryLimit,
description,
status: status !== undefined ? Number(status) : undefined
});
if (!updated) {
return res.status(404).json({ code: 40400, message: '优惠券不存在或已被删除' });
}
res.json({ code: 20000, data: updated, message: '优惠券修改成功' });
} catch (err: any) {
res.status(400).json({ code: 40000, message: err.message });
}
});
// 管理后台:删除优惠券
app.delete('/api/admin/coupons/:id', async (req: Request, res: Response) => {
try {
const couponId = String(req.params.id);
const ok = await repo.deleteCoupon(couponId);
if (!ok) {
return res.status(404).json({ code: 40400, message: '优惠券不存在或已被删除' });
}
res.json({ code: 20000, data: null, message: '优惠券已删除' });
} catch (err: any) {
res.status(400).json({ code: 40000, message: err.message });
}
});
// 创建新订单 (落盘 MySQL)
app.post('/api/orders', async (req: Request, res: Response) => {
try {