- Объединены ресурсы в 5 логических групп: Контент сайта, Бронирования, Отзывы и рейтинги, Персонал и гиды, Администрирование - Удалены дублирующие настройки navigation для чистой группировки - Добавлены CSS стили для визуального отображения иерархии с отступами - Добавлены эмодзи-иконки для каждого типа ресурсов через CSS - Улучшена навигация с правильной вложенностью элементов
176 lines
5.9 KiB
JavaScript
176 lines
5.9 KiB
JavaScript
import express from 'express';
|
|
import SiteSettingsHelper from '../helpers/site-settings.js';
|
|
import fs from 'fs/promises';
|
|
import path from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
import { dirname } from 'path';
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = dirname(__filename);
|
|
|
|
const router = express.Router();
|
|
|
|
const STYLES_CONFIG_PATH = path.join(__dirname, '../../config/styles.json');
|
|
const CUSTOM_CSS_PATH = path.join(__dirname, '../../public/css/custom-styles.css');
|
|
|
|
/**
|
|
* Динамический CSS на основе настроек сайта
|
|
*/
|
|
router.get('/dynamic-styles.css', async (req, res) => {
|
|
try {
|
|
const css = await SiteSettingsHelper.generateCSSVariables();
|
|
|
|
res.setHeader('Content-Type', 'text/css');
|
|
res.setHeader('Cache-Control', 'public, max-age=300'); // Кеш на 5 минут
|
|
res.send(css);
|
|
} catch (error) {
|
|
console.error('Error generating dynamic CSS:', error);
|
|
res.status(500).send('/* Error generating dynamic CSS */');
|
|
}
|
|
});
|
|
|
|
// Загрузка настроек стилей для продвинутого редактора
|
|
router.get('/api/settings/styles', async (req, res) => {
|
|
try {
|
|
let styles = {};
|
|
|
|
try {
|
|
const data = await fs.readFile(STYLES_CONFIG_PATH, 'utf8');
|
|
styles = JSON.parse(data);
|
|
} catch (error) {
|
|
// Файл не существует, создаем дефолтные настройки
|
|
styles = {
|
|
'primary-color': '#ff6b6b',
|
|
'secondary-color': '#38C172',
|
|
'background-color': '#f8f9fa',
|
|
'text-color': '#333333',
|
|
'primary-font': "'Inter', sans-serif",
|
|
'base-font-size': '16px',
|
|
'line-height': '1.6',
|
|
'max-width': '1200px',
|
|
'section-padding': '60px',
|
|
'border-radius': '8px',
|
|
'transition-speed': '0.3s',
|
|
'hover-effect': 'lift'
|
|
};
|
|
}
|
|
|
|
res.json({ success: true, styles });
|
|
} catch (error) {
|
|
console.error('Ошибка загрузки стилей:', error);
|
|
res.status(500).json({ success: false, error: 'Ошибка загрузки стилей' });
|
|
}
|
|
});
|
|
|
|
// Сохранение настроек стилей
|
|
router.post('/api/settings/styles', async (req, res) => {
|
|
try {
|
|
const { styles, css } = req.body;
|
|
|
|
if (!styles || !css) {
|
|
return res.status(400).json({ success: false, error: 'Отсутствуют данные стилей' });
|
|
}
|
|
|
|
// Создаем директории если не существуют
|
|
await fs.mkdir(path.dirname(STYLES_CONFIG_PATH), { recursive: true });
|
|
await fs.mkdir(path.dirname(CUSTOM_CSS_PATH), { recursive: true });
|
|
|
|
// Сохраняем конфигурацию стилей
|
|
await fs.writeFile(STYLES_CONFIG_PATH, JSON.stringify(styles, null, 2));
|
|
|
|
// Сохраняем CSS файл
|
|
const cssContent = `/* Автоматически сгенерированные стили - ${new Date().toISOString()} */\n\n${css}`;
|
|
await fs.writeFile(CUSTOM_CSS_PATH, cssContent);
|
|
|
|
res.json({ success: true, message: 'Стили успешно сохранены' });
|
|
} catch (error) {
|
|
console.error('Ошибка сохранения стилей:', error);
|
|
res.status(500).json({ success: false, error: 'Ошибка сохранения стилей' });
|
|
}
|
|
});
|
|
|
|
// Получение текущего CSS
|
|
router.get('/api/settings/styles/css', async (req, res) => {
|
|
try {
|
|
let css = '';
|
|
|
|
try {
|
|
css = await fs.readFile(CUSTOM_CSS_PATH, 'utf8');
|
|
} catch (error) {
|
|
// Файл не существует, возвращаем пустой CSS
|
|
css = '/* Пользовательские стили не найдены */';
|
|
}
|
|
|
|
res.setHeader('Content-Type', 'text/css');
|
|
res.send(css);
|
|
} catch (error) {
|
|
console.error('Ошибка загрузки CSS:', error);
|
|
res.status(500).send('/* Ошибка загрузки стилей */');
|
|
}
|
|
});
|
|
|
|
/**
|
|
* API для получения настроек сайта
|
|
*/
|
|
router.get('/api/site-settings', async (req, res) => {
|
|
try {
|
|
const settings = await SiteSettingsHelper.getAllSettings();
|
|
res.json(settings);
|
|
} catch (error) {
|
|
console.error('Error loading site settings:', error);
|
|
res.status(500).json({ error: 'Failed to load site settings' });
|
|
}
|
|
});
|
|
|
|
/**
|
|
* API для получения настроек по категории
|
|
*/
|
|
router.get('/api/site-settings/:category', async (req, res) => {
|
|
try {
|
|
const { category } = req.params;
|
|
const settings = await SiteSettingsHelper.getSettingsByCategory(category);
|
|
res.json(settings);
|
|
} catch (error) {
|
|
console.error('Error loading site settings by category:', error);
|
|
res.status(500).json({ error: 'Failed to load site settings' });
|
|
}
|
|
});
|
|
|
|
/**
|
|
* API для обновления настройки
|
|
*/
|
|
router.post('/api/site-settings', async (req, res) => {
|
|
try {
|
|
const { key, value, type, description, category } = req.body;
|
|
|
|
if (!key || value === undefined) {
|
|
return res.status(400).json({ error: 'Key and value are required' });
|
|
}
|
|
|
|
const success = await SiteSettingsHelper.setSetting(key, value, type, description, category);
|
|
|
|
if (success) {
|
|
res.json({ success: true, message: 'Setting updated successfully' });
|
|
} else {
|
|
res.status(500).json({ error: 'Failed to update setting' });
|
|
}
|
|
} catch (error) {
|
|
console.error('Error updating site setting:', error);
|
|
res.status(500).json({ error: 'Failed to update setting' });
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Очистка кеша настроек (для админов)
|
|
*/
|
|
router.post('/api/site-settings/clear-cache', async (req, res) => {
|
|
try {
|
|
SiteSettingsHelper.clearCache();
|
|
res.json({ success: true, message: 'Cache cleared successfully' });
|
|
} catch (error) {
|
|
console.error('Error clearing cache:', error);
|
|
res.status(500).json({ error: 'Failed to clear cache' });
|
|
}
|
|
});
|
|
|
|
export default router; |