xk/backend/routes/partners.js
2026-02-02 20:51:52 +08:00

260 lines
6.4 KiB
JavaScript

const express = require('express');
const router = express.Router();
const multer = require('multer');
const path = require('path');
const fs = require('fs').promises;
const db = require('../config/database');
const { requireAuth } = require('../middleware/auth');
// Configure multer for file upload
const storage = multer.diskStorage({
destination: async (req, file, cb) => {
const uploadDir = path.join(__dirname, '../../img/logo');
try {
await fs.mkdir(uploadDir, { recursive: true });
cb(null, uploadDir);
} catch (error) {
cb(error);
}
},
filename: (req, file, cb) => {
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
cb(null, uniqueSuffix + path.extname(file.originalname));
}
});
const upload = multer({
storage: storage,
limits: {
fileSize: 5 * 1024 * 1024 // 5MB
},
fileFilter: (req, file, cb) => {
const allowedTypes = /jpeg|jpg|png|gif|svg/;
const extname = allowedTypes.test(path.extname(file.originalname).toLowerCase());
const mimetype = allowedTypes.test(file.mimetype);
if (mimetype && extname) {
return cb(null, true);
} else {
cb(new Error('Only image files are allowed (jpg, jpeg, png, gif, svg)'));
}
}
});
// Public endpoint: Get active partners (for frontend display)
router.get('/public', async (req, res) => {
try {
const [partners] = await db.query(
'SELECT name, logo, url FROM partners WHERE status = 1 ORDER BY sort_order ASC, id DESC'
);
res.json({
success: true,
data: partners
});
} catch (error) {
console.error('Get public partners error:', error);
res.status(500).json({
success: false,
message: 'Failed to fetch partners'
});
}
});
// Get all partners
router.get('/', requireAuth, async (req, res) => {
try {
const [partners] = await db.query(
'SELECT * FROM partners ORDER BY sort_order ASC, id DESC'
);
res.json({
success: true,
data: partners
});
} catch (error) {
console.error('Get partners error:', error);
res.status(500).json({
success: false,
message: 'Failed to fetch partners'
});
}
});
// Get single partner
router.get('/:id', requireAuth, async (req, res) => {
try {
const [partners] = await db.query(
'SELECT * FROM partners WHERE id = ?',
[req.params.id]
);
if (partners.length === 0) {
return res.status(404).json({
success: false,
message: 'Partner not found'
});
}
res.json({
success: true,
data: partners[0]
});
} catch (error) {
console.error('Get partner error:', error);
res.status(500).json({
success: false,
message: 'Failed to fetch partner'
});
}
});
// Create partner
router.post('/', requireAuth, upload.single('logo'), async (req, res) => {
try {
const { name, url, status } = req.body;
if (!name) {
return res.status(400).json({
success: false,
message: 'Partner name is required'
});
}
if (!req.file) {
return res.status(400).json({
success: false,
message: 'Logo image is required'
});
}
const logoPath = 'img/logo/' + req.file.filename;
// Get max sort order
const [maxOrder] = await db.query(
'SELECT MAX(sort_order) as max_order FROM partners'
);
const sortOrder = (maxOrder[0].max_order || 0) + 1;
const [result] = await db.query(
'INSERT INTO partners (name, logo, url, sort_order, status) VALUES (?, ?, ?, ?, ?)',
[name, logoPath, url || '', sortOrder, status || 1]
);
res.json({
success: true,
message: 'Partner created successfully',
data: {
id: result.insertId,
name,
logo: logoPath,
url: url || '',
sort_order: sortOrder,
status: status || 1
}
});
} catch (error) {
console.error('Create partner error:', error);
res.status(500).json({
success: false,
message: 'Failed to create partner'
});
}
});
// Update partner
router.put('/:id', requireAuth, upload.single('logo'), async (req, res) => {
try {
const { name, url, status, sort_order } = req.body;
const partnerId = req.params.id;
// Check if partner exists
const [existingPartner] = await db.query(
'SELECT * FROM partners WHERE id = ?',
[partnerId]
);
if (existingPartner.length === 0) {
return res.status(404).json({
success: false,
message: 'Partner not found'
});
}
let logoPath = existingPartner[0].logo;
// If new logo uploaded, delete old one and use new one
if (req.file) {
// Delete old logo file
const oldLogoPath = path.join(__dirname, '../..', existingPartner[0].logo);
try {
await fs.unlink(oldLogoPath);
} catch (err) {
console.log('Old logo file not found or cannot be deleted');
}
logoPath = 'img/logo/' + req.file.filename;
}
await db.query(
'UPDATE partners SET name = ?, logo = ?, url = ?, status = ?, sort_order = ? WHERE id = ?',
[name, logoPath, url || '', status || 1, sort_order || existingPartner[0].sort_order, partnerId]
);
res.json({
success: true,
message: 'Partner updated successfully'
});
} catch (error) {
console.error('Update partner error:', error);
res.status(500).json({
success: false,
message: 'Failed to update partner'
});
}
});
// Delete partner
router.delete('/:id', requireAuth, async (req, res) => {
try {
const partnerId = req.params.id;
// Get partner info
const [partner] = await db.query(
'SELECT * FROM partners WHERE id = ?',
[partnerId]
);
if (partner.length === 0) {
return res.status(404).json({
success: false,
message: 'Partner not found'
});
}
// Delete logo file
const logoPath = path.join(__dirname, '../..', partner[0].logo);
try {
await fs.unlink(logoPath);
} catch (err) {
console.log('Logo file not found or cannot be deleted');
}
// Delete from database
await db.query('DELETE FROM partners WHERE id = ?', [partnerId]);
res.json({
success: true,
message: 'Partner deleted successfully'
});
} catch (error) {
console.error('Delete partner error:', error);
res.status(500).json({
success: false,
message: 'Failed to delete partner'
});
}
});
module.exports = router;