feat(nav-category): support dynamic home grid categories in admin and uniapp

这个提交包含在:
xcbyy
2026-10-10 09:08:18 +08:00
父节点 f010cfb7ab
当前提交 51682fffea
共有 11 个文件被更改,包括 1077 次插入 和 6 次删除

查看文件

@@ -739,6 +739,130 @@ app.delete('/api/admin/banners/:id', async (req: Request, res: Response) => {
}
});
// 首页金刚区活动品类导航列表 (小程序端读取上架状态)
app.get('/api/nav-categories', async (_req: Request, res: Response) => {
try {
const list = await repo.getNavCategories();
res.json({ code: 20000, data: list });
} catch (err: any) {
res.status(500).json({ code: 50000, message: err.message });
}
});
// 管理后台: 获取全部品类导航列表 (含停用状态)
app.get('/api/admin/nav-categories', async (_req: Request, res: Response) => {
try {
const list = await repo.getAdminNavCategories();
res.json({ code: 20000, data: list });
} catch (err: any) {
res.status(500).json({ code: 50000, message: err.message });
}
});
// 管理后台: 新增品类导航
app.post('/api/admin/nav-categories', async (req: Request, res: Response) => {
try {
const { code, name, icon, bgClass, cat, targetUrl, badgeText, sortOrder, status } = req.body;
if (!name || !name.trim()) {
return res.status(400).json({ code: 40000, message: '品类名称不能为空' });
}
if (!icon || !icon.trim()) {
return res.status(400).json({ code: 40000, message: '品类图标不能为空' });
}
// 微信内容安全检测
const secCheck = contentSecurityService.checkText(name + ' ' + (badgeText || ''));
if (!secCheck.pass) {
return res.status(400).json({ code: secCheck.code, message: secCheck.message });
}
const item = await repo.createNavCategory({
code,
name: name.trim(),
icon: icon.trim(),
bgClass,
cat,
targetUrl,
badgeText,
sortOrder: sortOrder !== undefined ? Number(sortOrder) : 0,
status: status !== undefined ? Number(status) : 1
});
res.json({ code: 20000, data: item, message: '品类导航创建成功' });
} catch (err: any) {
res.status(400).json({ code: 40000, message: err.message });
}
});
// 管理后台: 修改品类导航
app.put('/api/admin/nav-categories/:id', async (req: Request, res: Response) => {
try {
const catId = String(req.params.id);
const { name, icon, bgClass, cat, targetUrl, badgeText, sortOrder, status } = req.body;
if (name) {
const secCheck = contentSecurityService.checkText(name + ' ' + (badgeText || ''));
if (!secCheck.pass) {
return res.status(400).json({ code: secCheck.code, message: secCheck.message });
}
}
const updated = await repo.updateNavCategory(catId, {
name,
icon,
bgClass,
cat,
targetUrl,
badgeText,
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.post('/api/admin/nav-categories/:id/status', async (req: Request, res: Response) => {
try {
const catId = String(req.params.id);
const { status } = req.body;
if (status === undefined || (status !== 0 && status !== 1)) {
return res.status(400).json({ code: 40000, message: '状态参数必须为 0 或 1' });
}
const updated = await repo.updateNavCategoryStatus(catId, Number(status));
if (!updated) {
return res.status(404).json({ code: 40400, message: '品类导航不存在' });
}
res.json({ code: 20000, data: updated, message: status === 1 ? '品类导航已上架' : '品类导航已下线隐藏' });
} catch (err: any) {
res.status(400).json({ code: 40000, message: err.message });
}
});
// 管理后台: 删除品类导航
app.delete('/api/admin/nav-categories/:id', async (req: Request, res: Response) => {
try {
const catId = String(req.params.id);
const ok = await repo.deleteNavCategory(catId);
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 {