Files
sts-avto-v2/modules/equipment/index.js
kalugin66 11fb813a09
All checks were successful
Deploy sts / deploy-sber (push) Successful in 42s
модификация
2026-07-20 00:27:48 +05:00

117 lines
5.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const { createCrudRoutes } = require('../database/crud');
const multer = require('multer');
const path = require('path');
const fs = require('fs');
const sharp = require('sharp');
let db;
function init(database) { db = database; }
function setupRoutes(app, auth) {
const uploadDir = path.join(__dirname, '..', '..', 'data', 'equipment_images');
if (!fs.existsSync(uploadDir)) fs.mkdirSync(uploadDir, { recursive: true });
const storage = multer.diskStorage({
destination: uploadDir,
filename: (req, file, cb) => {
const ext = path.extname(file.originalname);
cb(null, 'equip_' + Date.now() + '_' + Math.round(Math.random() * 1000) + ext);
}
});
const upload = multer({
storage,
limits: { fileSize: 5 * 1024 * 1024 },
fileFilter: (req, file, cb) => {
const allowed = ['.jpg', '.jpeg', '.png', '.webp', '.gif'];
const ext = path.extname(file.originalname).toLowerCase();
cb(null, allowed.includes(ext));
}
});
async function convertToWebp(filePath, fname) {
const ext = path.extname(fname).toLowerCase();
if (ext === '.webp') return fname;
try {
const webpName = path.basename(fname, ext) + '.webp';
await sharp(filePath).webp({ quality: 85 }).toFile(path.join(uploadDir, webpName));
fs.unlinkSync(filePath);
return webpName;
} catch (e) { return fname; }
}
app.post('/api/admin/equipment/upload', auth.authenticateToken, auth.requireAdmin, upload.single('image'), async (req, res) => {
if (!req.file) return res.status(400).json({ error: 'Файл не загружен' });
const fname = await convertToWebp(req.file.path, req.file.filename);
res.json({ path: fname, url: `/data/equipment_images/${fname}` });
});
app.post('/api/admin/equipment/gallery/upload', auth.authenticateToken, auth.requireAdmin, upload.array('images', 10), async (req, res) => {
if (!req.files || req.files.length === 0) return res.status(400).json({ error: 'Файлы не загружены' });
const results = [];
for (const file of req.files) {
const fname = await convertToWebp(file.path, file.filename);
results.push({ path: fname, url: `/data/equipment_images/${fname}` });
}
res.json(results);
});
app.get('/api/admin/equipment/:id/gallery', auth.authenticateToken, auth.requireAdmin, (req, res) => {
const id = parseInt(req.params.id);
if (isNaN(id)) return res.status(400).json({ error: 'Неверный ID' });
db.all(`SELECT * FROM equipment_gallery WHERE equipment_id = ? ORDER BY sort_order`, [id], (err, rows) => {
if (err) return res.status(500).json({ error: 'Ошибка БД' });
res.json(rows);
});
});
app.post('/api/admin/equipment/:id/gallery', auth.authenticateToken, auth.requireAdmin, (req, res) => {
const id = parseInt(req.params.id);
if (isNaN(id)) return res.status(400).json({ error: 'Неверный ID' });
const { image_path, sort_order } = req.body;
if (!image_path) return res.status(400).json({ error: 'Не указан путь к изображению' });
const stmt = db.prepare(`INSERT INTO equipment_gallery (equipment_id, image_path, sort_order) VALUES (?, ?, ?)`);
stmt.run(id, image_path, sort_order || 0, function(err) {
if (err) return res.status(500).json({ error: 'Ошибка создания' });
db.get(`SELECT * FROM equipment_gallery WHERE id = ?`, [this.lastID], (e2, row) => {
if (e2) return res.status(500).json({});
res.status(201).json(row);
});
});
stmt.finalize();
});
app.put('/api/admin/equipment/gallery/:imageId', auth.authenticateToken, auth.requireAdmin, (req, res) => {
const imageId = parseInt(req.params.imageId);
if (isNaN(imageId)) return res.status(400).json({ error: 'Неверный ID' });
const { image_path, sort_order } = req.body;
const stmt = db.prepare(`UPDATE equipment_gallery SET image_path = COALESCE(?, image_path), sort_order = COALESCE(?, sort_order) WHERE id = ?`);
stmt.run(image_path || null, sort_order != null ? sort_order : null, imageId, function(err) {
if (err) return res.status(500).json({ error: 'Ошибка обновления' });
if (this.changes === 0) return res.status(404).json({ error: 'Не найдено' });
db.get(`SELECT * FROM equipment_gallery WHERE id = ?`, [imageId], (e2, row) => {
res.json(row);
});
});
stmt.finalize();
});
app.delete('/api/admin/equipment/gallery/:imageId', auth.authenticateToken, auth.requireAdmin, (req, res) => {
const imageId = parseInt(req.params.imageId);
if (isNaN(imageId)) return res.status(400).json({ error: 'Неверный ID' });
const stmt = db.prepare(`DELETE FROM equipment_gallery WHERE id = ?`);
stmt.run(imageId, function(err) {
if (err) return res.status(500).json({ error: 'Ошибка удаления' });
if (this.changes === 0) return res.status(404).json({ error: 'Не найдено' });
res.json({ message: 'Удалено' });
});
stmt.finalize();
});
createCrudRoutes(app, auth, 'equipment', {
fields: ['name', 'brand', 'image_path', 'qty', 'specs', 'age_badge', 'sort_order', 'is_active']
});
}
module.exports = { init, setupRoutes };