feat: добавлена навигация по неделям с возможностью отключения через админ-панель

feat: добавлена навигация по неделям с возможностью отключения через админ-панель

Реализована навигация по неделям в расписании с парсингом ссылок из HTML страницы
оригинального сайта. Добавлена возможность управления навигацией через админ-панель
с сохранением настроек в файл.

Основные изменения:

- Парсинг навигации по неделям:
  * Добавлены типы WeekInfo и ParseResult в парсер
  * Реализована функция parseWeekNavigation для извлечения ссылок с параметром wk
  * Парсер ищет ссылки в href, onclick, формах и других атрибутах
  * Автоматическое определение номеров недель из текста ссылок и контекста
  * Вычисление соседних недель на основе найденных данных

- API и функции:
  * Обновлена функция getSchedule для поддержки параметра wk в URL
  * Обновлен getServerSideProps для чтения параметра wk из query string
  * Кэширование расписания с учетом недели (ключ включает group + wk)

- Компоненты:
  * Создан компонент WeekNavigation с кнопками навигации
  * Интегрирована навигация в компонент Schedule
  * Навигация работает через изменение URL параметра wk

- Система настроек:
  * Создан settings-loader для загрузки/сохранения настроек в JSON
  * Добавлен API endpoint /api/admin/settings для управления настройками
  * Добавлен переключатель в админ-панели для включения/выключения навигации
  * Настройки сохраняются в src/shared/data/settings.json и переживают перезапуски

- Файлы:
  * src/app/parser/schedule.ts - парсинг навигации по неделям
  * src/app/agregator/schedule.ts - поддержка параметра wk
  * src/pages/[group].tsx - чтение wk из query и передача настроек
  * src/widgets/schedule/week-navigation.tsx - компонент навигации
  * src/widgets/schedule/index.tsx - интеграция навигации
  * src/pages/admin.tsx - управление настройками
  * src/shared/data/settings-loader.ts - загрузка/сохранение настроек
  * src/pages/api/admin/settings.ts - API для настроек
  * src/shared/data/settings.json - файл с настройками
This commit is contained in:
kilyabin
2025-11-23 02:24:27 +04:00
parent cf0137a8d6
commit 2893a9fd18
10 changed files with 681 additions and 27 deletions

View File

@@ -0,0 +1,106 @@
import fs from 'fs'
import path from 'path'
export type AppSettings = {
weekNavigationEnabled: boolean
}
let cachedSettings: AppSettings | null = null
const defaultSettings: AppSettings = {
weekNavigationEnabled: true
}
/**
* Загружает настройки из JSON файла
* Использует кеш для оптимизации в production
*/
export function loadSettings(): AppSettings {
if (cachedSettings) {
return cachedSettings
}
// В production Next.js может использовать другую структуру директорий
// Пробуем несколько путей
const possiblePaths = [
path.join(process.cwd(), 'src/shared/data/settings.json'),
path.join(process.cwd(), '.next/standalone/src/shared/data/settings.json'),
path.join(process.cwd(), 'settings.json'),
]
for (const filePath of possiblePaths) {
try {
if (fs.existsSync(filePath)) {
const fileContents = fs.readFileSync(filePath, 'utf8')
const settings = JSON.parse(fileContents) as AppSettings
// Убеждаемся, что все обязательные поля присутствуют
const mergedSettings: AppSettings = {
...defaultSettings,
...settings
}
cachedSettings = mergedSettings
return mergedSettings
}
} catch (error) {
// Пробуем следующий путь
continue
}
}
// Если файл не найден, создаем его с настройками по умолчанию
const mainPath = path.join(process.cwd(), 'src/shared/data/settings.json')
try {
// Создаем директорию, если её нет
const dir = path.dirname(mainPath)
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true })
}
fs.writeFileSync(mainPath, JSON.stringify(defaultSettings, null, 2), 'utf8')
cachedSettings = defaultSettings
return defaultSettings
} catch (error) {
console.error('Error creating settings.json:', error)
// Возвращаем настройки по умолчанию
return defaultSettings
}
}
/**
* Сохраняет настройки в JSON файл
*/
export function saveSettings(settings: AppSettings): void {
// Всегда сохраняем в основной путь
const filePath = path.join(process.cwd(), 'src/shared/data/settings.json')
try {
// Создаем директорию, если её нет
const dir = path.dirname(filePath)
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true })
}
// Объединяем с настройками по умолчанию для сохранения всех полей
const mergedSettings: AppSettings = {
...defaultSettings,
...settings
}
fs.writeFileSync(filePath, JSON.stringify(mergedSettings, null, 2), 'utf8')
// Сбрасываем кеш
cachedSettings = null
} catch (error) {
console.error('Error saving settings.json:', error)
throw new Error('Failed to save settings')
}
}
/**
* Сбрасывает кеш настроек (полезно после обновления файла)
*/
export function clearSettingsCache(): void {
cachedSettings = null
}