feat: 添加管理员管理和场地图片功能
This commit is contained in:
+56
-10
@@ -1,6 +1,6 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const { Activity, Photo, Sponsor, Expense, Registration, Prize } = require('../models');
|
||||
const { Activity, Photo, Sponsor, Expense, Registration, Prize, VenueImage } = require('../models');
|
||||
const { upload, getFileUrls } = require('../middleware/upload');
|
||||
|
||||
// 获取活动列表
|
||||
@@ -8,7 +8,11 @@ router.get('/activities', async (req, res) => {
|
||||
try {
|
||||
const { status } = req.query;
|
||||
const where = status ? { status } : {};
|
||||
const activities = await Activity.findAll({ where, order: [['startTime', 'DESC']] });
|
||||
const activities = await Activity.findAll({
|
||||
where,
|
||||
order: [['startTime', 'DESC']],
|
||||
raw: true
|
||||
});
|
||||
res.json(activities);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
@@ -18,22 +22,42 @@ router.get('/activities', async (req, res) => {
|
||||
// 获取活动详情
|
||||
router.get('/activities/:id', async (req, res) => {
|
||||
try {
|
||||
const activity = await Activity.findByPk(req.params.id);
|
||||
const activity = await Activity.findByPk(req.params.id, { raw: true });
|
||||
if (!activity) {
|
||||
return res.status(404).json({ error: '活动不存在' });
|
||||
}
|
||||
|
||||
// 只返回已审核通过的照片
|
||||
const photos = await Photo.findAll({
|
||||
where: { activityId: req.params.id, status: 'approved' }
|
||||
where: { activityId: req.params.id, status: 'approved' },
|
||||
raw: true
|
||||
});
|
||||
const sponsors = await Sponsor.findAll({
|
||||
where: { activityId: req.params.id },
|
||||
order: [['sortOrder', 'ASC'], ['id', 'ASC']]
|
||||
order: [['sortOrder', 'ASC'], ['id', 'ASC']],
|
||||
raw: true
|
||||
});
|
||||
const expenses = await Expense.findAll({ where: { activityId: req.params.id } });
|
||||
const expenses = await Expense.findAll({
|
||||
where: { activityId: req.params.id },
|
||||
raw: true
|
||||
});
|
||||
// 手动解析JSON字段
|
||||
const parsedExpenses = expenses.map(expense => ({
|
||||
...expense,
|
||||
media: typeof expense.media === 'string' ? JSON.parse(expense.media || '[]') : (expense.media || [])
|
||||
}));
|
||||
const prizes = await Prize.findAll({
|
||||
where: { activityId: req.params.id },
|
||||
order: [['sortOrder', 'ASC'], ['id', 'ASC']]
|
||||
order: [['sortOrder', 'ASC'], ['id', 'ASC']],
|
||||
raw: true
|
||||
});
|
||||
const venueImages = await VenueImage.findAll({
|
||||
where: { activityId: req.params.id },
|
||||
order: [['sortOrder', 'ASC'], ['id', 'ASC']],
|
||||
raw: true
|
||||
});
|
||||
|
||||
res.json({ activity, photos, sponsors, expenses, prizes });
|
||||
res.json({ activity, photos, sponsors, expenses: parsedExpenses, prizes, venueImages: venueImages.map(img => img.image).filter(Boolean) });
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
@@ -42,8 +66,30 @@ router.get('/activities/:id', async (req, res) => {
|
||||
// 获取活动经费(公开接口)
|
||||
router.get('/activities/:id/expenses', async (req, res) => {
|
||||
try {
|
||||
const expenses = await Expense.findAll({ where: { activityId: req.params.id } });
|
||||
res.json(expenses);
|
||||
const expenses = await Expense.findAll({
|
||||
where: { activityId: req.params.id },
|
||||
raw: true
|
||||
});
|
||||
// 手动解析JSON字段
|
||||
const parsedExpenses = expenses.map(expense => ({
|
||||
...expense,
|
||||
media: typeof expense.media === 'string' ? JSON.parse(expense.media || '[]') : (expense.media || [])
|
||||
}));
|
||||
res.json(parsedExpenses);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// 获取场地图片列表
|
||||
router.get('/activities/:id/venue-images', async (req, res) => {
|
||||
try {
|
||||
const images = await VenueImage.findAll({
|
||||
where: { activityId: req.params.id },
|
||||
order: [['sortOrder', 'ASC'], ['id', 'ASC']],
|
||||
raw: true
|
||||
});
|
||||
res.json(images.map(img => img.image).filter(Boolean));
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
|
||||
+44
-3
@@ -32,6 +32,20 @@ router.post('/login', async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Token续期
|
||||
router.post('/refresh-token', auth, async (req, res) => {
|
||||
try {
|
||||
const admin = await Admin.findByPk(req.adminId);
|
||||
if (!admin) {
|
||||
return res.status(401).json({ error: '用户不存在' });
|
||||
}
|
||||
const token = jwt.sign({ id: admin.id }, process.env.JWT_SECRET, { expiresIn: '7d' });
|
||||
res.json({ token });
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// ========== 管理员管理API(仅超级管理员) ==========
|
||||
|
||||
// 获取管理员列表
|
||||
@@ -173,10 +187,12 @@ router.put('/activities/:id', auth, async (req, res) => {
|
||||
// 审核报名
|
||||
router.put('/registrations/:id', auth, async (req, res) => {
|
||||
try {
|
||||
const { status, peopleCount } = req.body;
|
||||
const { status, peopleCount, carNumber, groupStatus } = req.body;
|
||||
const updateData = {};
|
||||
if (status) updateData.status = status;
|
||||
if (peopleCount !== undefined) updateData.peopleCount = peopleCount;
|
||||
if (carNumber !== undefined) updateData.carNumber = carNumber;
|
||||
if (groupStatus !== undefined) updateData.groupStatus = groupStatus;
|
||||
|
||||
await Registration.update(updateData, { where: { id: req.params.id } });
|
||||
const registration = await Registration.findByPk(req.params.id);
|
||||
@@ -207,6 +223,26 @@ router.put('/registrations/:id/checkin', auth, async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// 进群/取消进群
|
||||
router.put('/registrations/:id/group', auth, async (req, res) => {
|
||||
try {
|
||||
const registration = await Registration.findByPk(req.params.id);
|
||||
if (!registration) {
|
||||
return res.status(404).json({ error: '报名信息不存在' });
|
||||
}
|
||||
|
||||
const newStatus = !registration.groupStatus;
|
||||
await Registration.update({
|
||||
groupStatus: newStatus
|
||||
}, { where: { id: req.params.id } });
|
||||
|
||||
const updated = await Registration.findByPk(req.params.id);
|
||||
res.json(updated);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// 获取所有报名(含待审核)
|
||||
router.get('/registrations', auth, async (req, res) => {
|
||||
try {
|
||||
@@ -264,8 +300,13 @@ router.get('/expenses', auth, async (req, res) => {
|
||||
try {
|
||||
const { activityId } = req.query;
|
||||
const where = activityId ? { activityId } : {};
|
||||
const expenses = await Expense.findAll({ where });
|
||||
res.json(expenses);
|
||||
const expenses = await Expense.findAll({ where, raw: true });
|
||||
// 手动解析JSON字段
|
||||
const parsedExpenses = expenses.map(expense => ({
|
||||
...expense,
|
||||
media: typeof expense.media === 'string' ? JSON.parse(expense.media || '[]') : (expense.media || [])
|
||||
}));
|
||||
res.json(parsedExpenses);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ router.post('/registrations', async (req, res) => {
|
||||
activityId, name, phone, carModel, carNumber, note
|
||||
});
|
||||
|
||||
res.json(registration);
|
||||
res.json(registration.toJSON());
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
@@ -25,7 +25,7 @@ router.post('/registrations', async (req, res) => {
|
||||
// 查询报名状态
|
||||
router.get('/registrations/:id', async (req, res) => {
|
||||
try {
|
||||
const registration = await Registration.findByPk(req.params.id);
|
||||
const registration = await Registration.findByPk(req.params.id, { raw: true });
|
||||
res.json(registration);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
@@ -36,7 +36,8 @@ router.get('/registrations/:id', async (req, res) => {
|
||||
router.get('/activities/:id/registrations', async (req, res) => {
|
||||
try {
|
||||
const registrations = await Registration.findAll({
|
||||
where: { activityId: req.params.id, status: 'approved' }
|
||||
where: { activityId: req.params.id, status: 'approved' },
|
||||
raw: true
|
||||
});
|
||||
res.json(registrations);
|
||||
} catch (error) {
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const auth = require('../middleware/auth');
|
||||
const { upload, getFileUrls } = require('../middleware/upload');
|
||||
const { VenueImage } = require('../models');
|
||||
|
||||
// 获取场地图片列表
|
||||
router.get('/venue-images', auth, async (req, res) => {
|
||||
try {
|
||||
const { activityId } = req.query;
|
||||
const images = await VenueImage.findAll({
|
||||
where: { activityId },
|
||||
order: [['sortOrder', 'ASC'], ['id', 'ASC']],
|
||||
raw: true
|
||||
});
|
||||
res.json(images);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// 上传场地图片
|
||||
router.post('/venue-images', auth, upload.single('image'), async (req, res) => {
|
||||
try {
|
||||
const { activityId, sortOrder } = req.body;
|
||||
|
||||
if (!req.file) {
|
||||
return res.status(400).json({ error: '请选择图片' });
|
||||
}
|
||||
|
||||
const [uploaded] = getFileUrls([req.file]);
|
||||
const image = await VenueImage.create({
|
||||
activityId,
|
||||
image: uploaded.url,
|
||||
sortOrder: sortOrder || 0
|
||||
});
|
||||
|
||||
res.json(image);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// 更新场地图片排序
|
||||
router.put('/venue-images/:id', auth, async (req, res) => {
|
||||
try {
|
||||
const { sortOrder } = req.body;
|
||||
await VenueImage.update({ sortOrder }, { where: { id: req.params.id } });
|
||||
const image = await VenueImage.findByPk(req.params.id);
|
||||
res.json(image);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// 删除场地图片
|
||||
router.delete('/venue-images/:id', auth, async (req, res) => {
|
||||
try {
|
||||
await VenueImage.destroy({ where: { id: req.params.id } });
|
||||
res.json({ message: '删除成功' });
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
Reference in New Issue
Block a user