🎨 Добавлен полный редактор стилей и поле image_url для туров

 Новые функции:
- Поле image_url в модели туров для изменения изображений через админ-панель
- Расширенная модель настроек сайта с категориями: colors, typography, images, effects, layout
- Динамический CSS генератор на основе настроек (/dynamic-styles.css)
- API для управления настройками сайта (/api/site-settings)

🎯 Редактор стилей:
- Управление цветами (основные, акцентные, текст, фон)
- Настройка типографики (шрифты, размеры, межстрочный интервал)
- Управление изображениями (фоны, логотипы, фавикон)
- Эффекты (прозрачность, тени, размытие, скругления)
- Макет (высота секций, размеры контейнеров)
- Пользовательский CSS код

🛠️ Техническая реализация:
- SiteSettingsHelper с кешированием для производительности
- CSS переменные для динамического изменения стилей
- Автоматическая миграция базы данных
- Интеграция с AdminJS для удобного управления
- Загрузка настроек в шаблоны для доступности

📊 База данных:
- Расширена таблица site_settings (добавлено поле category)
- Новые типы настроек: color, file
- 27 предустановленных настроек для полного контроля над дизайном
- Автоматическое применение миграций при старте приложения
This commit is contained in:
2025-11-29 22:03:00 +09:00
parent a461fea9d9
commit ed871fc4d1
8 changed files with 528 additions and 28 deletions

View File

@@ -1,16 +1,23 @@
/* Korea Tourism Agency - Main Styles */
/* CSS Variables */
/* CSS Variables - могут быть переопределены через настройки сайта */
:root {
/* Основные цвета */
--primary-color: #2563eb;
--primary-light: #3b82f6;
--primary-dark: #1d4ed8;
--secondary-color: #dc2626;
--accent-color: #059669;
--success-color: #059669;
--warning-color: #d97706;
--info-color: #0891b2;
--light-color: #f8fafc;
--dark-color: #0f172a;
--text-color: #334155;
--background-color: #ffffff;
--card-background: #f8fafc;
/* Серые тона */
--gray-100: #f1f5f9;
--gray-200: #e2e8f0;
--gray-300: #cbd5e1;
@@ -20,31 +27,56 @@
--gray-700: #334155;
--gray-800: #1e293b;
--gray-900: #0f172a;
/* Корейские цвета */
--korean-red: #c41e3a;
--korean-blue: #003478;
--font-korean: 'Noto Sans KR', 'Malgun Gothic', '맑은 고딕', sans-serif;
--font-display: 'Playfair Display', serif;
/* Типографика */
--font-family-primary: 'Noto Sans KR', 'Malgun Gothic', '맑은 고딕', sans-serif;
--font-family-display: 'Playfair Display', serif;
--font-size-base: 16px;
--line-height-base: 1.7;
/* Эффекты */
--hero-overlay-opacity: 0.8;
--hero-overlay-color: #2563eb;
--card-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
--border-radius: 8px;
--blur-effect: 10px;
--animation-duration: 0.3s;
/* Тени */
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
--shadow: var(--card-shadow);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
/* Макет */
--hero-height-desktop: 70vh;
--hero-height-mobile: 50vh;
--compact-hero-height: 25vh;
--container-max-width: 1200px;
--navbar-height: 76px;
}
/* Base Styles */
body {
font-family: var(--font-korean);
line-height: 1.7;
color: var(--gray-700);
padding-top: 76px; /* Account for fixed navbar */
font-family: var(--font-family-primary);
font-size: var(--font-size-base);
line-height: var(--line-height-base);
color: var(--text-color);
background-color: var(--background-color);
padding-top: var(--navbar-height);
}
.font-korean {
font-family: var(--font-korean);
font-family: var(--font-family-primary);
}
.font-display {
font-family: var(--font-display);
font-family: var(--font-family-display);
}
/* Custom Bootstrap Overrides */
@@ -52,7 +84,7 @@ body {
background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-light) 100%);
border: none;
box-shadow: var(--shadow-md);
transition: all 0.3s ease;
transition: all var(--animation-duration) ease;
}
.btn-primary:hover {
@@ -63,8 +95,8 @@ body {
.text-gradient {
background: linear-gradient(135deg, var(--korean-red) 0%, var(--korean-blue) 100%);
background-clip: text;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
@@ -74,14 +106,15 @@ body {
/* Navigation Styles */
.navbar {
background: rgba(37, 99, 235, 0.95) !important;
backdrop-filter: blur(10px);
background: rgba(37, 99, 235, var(--hero-overlay-opacity)) !important;
-webkit-backdrop-filter: blur(var(--blur-effect));
backdrop-filter: blur(var(--blur-effect));
box-shadow: var(--shadow-md);
transition: all 0.3s ease;
transition: all var(--animation-duration) ease;
}
.navbar-brand {
font-family: var(--font-display);
font-family: var(--font-family-display);
font-weight: 700;
font-size: 1.5rem;
}
@@ -89,7 +122,7 @@ body {
.nav-link {
font-weight: 500;
position: relative;
transition: all 0.3s ease;
transition: all var(--animation-duration) ease;
}
.nav-link:hover {
@@ -111,21 +144,21 @@ body {
/* Hero Section */
.hero-section {
background: linear-gradient(135deg, var(--primary-color) 0%, var(--korean-blue) 100%);
min-height: 70vh;
min-height: var(--hero-height-desktop);
position: relative;
overflow: hidden;
}
/* Compact Hero Section for other pages */
.hero-section.compact {
min-height: 25vh;
min-height: var(--compact-hero-height);
padding: 3rem 0;
}
/* Mobile optimization for hero sections */
@media (max-width: 768px) {
.hero-section {
min-height: 50vh;
min-height: var(--hero-height-mobile);
padding: 2rem 0;
}
@@ -154,9 +187,9 @@ body {
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg, rgba(37, 99, 235, 0.8) 0%, rgba(0, 52, 120, 0.9) 100%);
background: linear-gradient(135deg, rgba(37, 99, 235, var(--hero-overlay-opacity)) 0%, rgba(0, 52, 120, 0.9) 100%);
z-index: 2;
pointer-events: none; /* Позволяет кликам проходить через overlay */
pointer-events: none;
}
.hero-section .container {