/
miilsvkk
/
BookRecSystem
Обзор
Документация
Войти
/
miilsvkk
/
BookRecSystem
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
main.py
402 строки
15 KB
miilsvkk
Финальная версия
17 дек 2025, 09:31
17 дек 2025, 09:31
88fff3d
Код
Авторство
О чём код?
import flet as ft from colors import COLORS import database from books import books_data from rec_system import recomend def main(page: ft.Page): page.title = "Read and Vibe" page.padding = 20 page.bgcolor = COLORS["BG_MAIN"] # Инициализация базы данных database.init_database() # Получаем лайкнутые книги при запуске user_id = "user_123" liked_books = database.get_liked_books(user_id) # Словарь для хранения избранных книг like_buttons = {} # Все доступные жанры и настроения all_genres = list(set(book["genre"] for book in books_data)) all_moods = list(set(book["mood"] for book in books_data)) header = ft.Container( content=ft.Column([ ft.Text( "Read and Vibe", size=36, weight=ft.FontWeight.BOLD, color=COLORS["TEXT_WHITE"] ) ], horizontal_alignment=ft.CrossAxisAlignment.CENTER, spacing=5), bgcolor=COLORS["PRIMARY"], padding=30, border_radius=15, alignment=ft.alignment.center, margin=ft.margin.only(bottom=20), shadow=ft.BoxShadow( spread_radius=1, blur_radius=15, color=COLORS["PRIMARY"], ) ) # Текст фильтра filter_text = ft.Text("Все книги", size=18, weight=ft.FontWeight.BOLD, color=COLORS["PRIMARY_DARK"]) # Кнопка "Избранное" favorites_btn = ft.FilledButton( "❤️ Избранное", on_click=lambda e: show_favorites(), style=ft.ButtonStyle( color=COLORS["TEXT_WHITE"], bgcolor=COLORS["ACCENT_RED"], padding=ft.padding.symmetric(horizontal=20, vertical=12), ) ) # Кнопка "Рекомендации" recommendations_btn = ft.FilledButton( "💡 Рекомендации", on_click=lambda e: show_recommendations(), style=ft.ButtonStyle( color=COLORS["TEXT_WHITE"], bgcolor=COLORS["ACCENT_GREEN"], # Добавьте этот цвет в colors.py или используйте другой padding=ft.padding.symmetric(horizontal=20, vertical=12), ) ) # Контейнер для карточек книг books_row = ft.Row([], scroll=ft.ScrollMode.AUTO, wrap=False) # Функция для обработки лайка def handle_like(book_title, like_button): # Текущее состояние is_liked = like_button.icon_color == COLORS["ACCENT_RED"] # Инвертируем состояние new_liked_state = 0 if is_liked else 1 # Сохраняем в БД success = database.toggle_like(user_id, book_title, new_liked_state) if success: # Обновляем внешний вид кнопки if new_liked_state == 1: like_button.icon_color = COLORS["ACCENT_RED"] like_button.tooltip = "Удалить из избранного" # Показываем snackbar с подтверждением page.snack_bar = ft.SnackBar( ft.Text(f"Добавлено в избранное: {book_title}"), bgcolor=COLORS["SUCCESS"] ) page.snack_bar.open = True else: like_button.icon_color = COLORS["TEXT_SECONDARY"] like_button.tooltip = "Добавить в избранное" # Обновляем список лайкнутых книг nonlocal liked_books liked_books = database.get_liked_books(user_id) page.update() else: # Показываем ошибку page.snack_bar = ft.SnackBar( ft.Text("Ошибка при сохранении. Попробуйте снова."), bgcolor=COLORS["ERROR"] ) page.snack_bar.open = True page.update() # Функция для создания карточки книги с кнопкой лайка def create_book_card(book): # Проверяем, лайкнута ли книга is_liked = book["title"] in liked_books # Создаем кнопку лайка like_button = ft.IconButton( icon=ft.Icons.FAVORITE, icon_color=COLORS["ACCENT_RED"] if is_liked else COLORS["TEXT_SECONDARY"], icon_size=20, tooltip="Добавить в избранное" if not is_liked else "Удалить из избранного", ) # Назначаем обработчик с передачей book_title и like_button like_button.on_click = lambda e, title=book["title"], btn=like_button: handle_like(title, btn) # Сохраняем ссылку на кнопку like_buttons[book["title"]] = like_button return ft.Card( content=ft.Container( content=ft.Column([ ft.Row([ ft.Icon(ft.Icons.BOOK, size=24, color=COLORS["PRIMARY"]), ft.Container(width=5), like_button ], alignment=ft.MainAxisAlignment.SPACE_BETWEEN), ft.Text( book["title"], size=12, weight=ft.FontWeight.BOLD, text_align=ft.TextAlign.CENTER, color=COLORS["TEXT_MAIN"] ), ft.Text( book["author"], size=10, text_align=ft.TextAlign.CENTER, color=COLORS["TEXT_SECONDARY"] ), ft.Row([ ft.Container( content=ft.Text( book["genre"], size=9, color=COLORS["TEXT_WHITE"] ), bgcolor=COLORS["PRIMARY_LIGHT"], padding=ft.padding.symmetric(horizontal=6, vertical=2), border_radius=5 ), ft.Container( content=ft.Text( f"{book['pages']} стр.", size=9, color=COLORS["PRIMARY"] ), padding=ft.padding.symmetric(horizontal=6, vertical=2), border_radius=5, border=ft.border.all(1, COLORS["BORDER"]) ) ], alignment=ft.MainAxisAlignment.CENTER, spacing=5), # Показать количество лайков ft.Text( f"❤️ {database.get_book_likes(book['title'])}", size=9, color=COLORS["TEXT_SECONDARY"] ) ], horizontal_alignment=ft.CrossAxisAlignment.CENTER, spacing=5), width=140, height=170, padding=10, bgcolor=COLORS["BG_CARD"], border_radius=10 ), elevation=3, color=COLORS["SHADOW"] ) # Функция показа всех книг def show_all_books(): filter_text.value = "Все книги" books_row.controls.clear() for book in books_data: card = create_book_card(book) books_row.controls.append(card) page.update() # Функция показа избранного def show_favorites(): filter_text.value = "Избранное" books_row.controls.clear() for book in books_data: if book["title"] in liked_books: card = create_book_card(book) books_row.controls.append(card) page.update() # Функция показа рекомендаций def show_recommendations(): try: # Получаем рекомендации из системы recommended_books = recomend(user_id) # Функция из rec_system.py filter_text.value = "Рекомендации для вас" books_row.controls.clear() if recommended_books: # Создаем словарь для быстрого поиска книг по названию books_dict = {book["title"]: book for book in books_data} # Отображаем рекомендуемые книги for book_title in recommended_books: if book_title in books_dict: card = create_book_card(books_dict[book_title]) books_row.controls.append(card) if not books_row.controls: # Если не нашли книги, показываем сообщение books_row.controls.append( ft.Container( content=ft.Text( "Рекомендуемые книги не найдены", color=COLORS["TEXT_SECONDARY"], size=14 ), padding=20 ) ) else: # Если рекомендаций нет books_row.controls.append( ft.Container( content=ft.Column([ ft.Icon(ft.Icons.LIGHTBULB_OUTLINE, size=40, color=COLORS["PRIMARY"]), ft.Text( "Лайкайте книги, чтобы получать рекомендации!", color=COLORS["TEXT_SECONDARY"], size=14, text_align=ft.TextAlign.CENTER ) ], horizontal_alignment=ft.CrossAxisAlignment.CENTER, spacing=10), padding=40 ) ) except Exception as e: # Обработка ошибок print(f"Ошибка при получении рекомендаций: {e}") page.snack_bar = ft.SnackBar( ft.Text(f"Ошибка при загрузке рекомендаций: {str(e)}"), bgcolor=COLORS["ERROR"] ) page.snack_bar.open = True books_row.controls.clear() books_row.controls.append( ft.Container( content=ft.Text( "Ошибка при загрузке рекомендаций", color=COLORS["ERROR"], size=14 ), padding=20 ) ) page.update() # Функция фильтра по жанру def filter_by_genre(genre): filter_text.value = f"Жанр: {genre}" books_row.controls.clear() for book in books_data: if book["genre"] == genre: card = create_book_card(book) books_row.controls.append(card) page.update() # Функция фильтра по настроению def filter_by_mood(mood): filter_text.value = f"Настроение: {mood}" books_row.controls.clear() for book in books_data: if book["mood"] == mood: card = create_book_card(book) books_row.controls.append(card) page.update() # Создаем кнопки жанров genre_buttons = ft.Row([], scroll=ft.ScrollMode.AUTO) for genre in all_genres: btn = ft.FilledButton( genre, on_click=lambda e, g=genre: filter_by_genre(g), style=ft.ButtonStyle( color=COLORS["TEXT_WHITE"], bgcolor=COLORS["PRIMARY"], padding=ft.padding.symmetric(horizontal=20, vertical=12), overlay_color=COLORS["PRIMARY_DARK"], elevation=2 ) ) genre_buttons.controls.append(btn) # Создаем кнопки настроений mood_buttons = ft.Row([], scroll=ft.ScrollMode.AUTO) for mood in all_moods: btn = ft.OutlinedButton( mood, on_click=lambda e, m=mood: filter_by_mood(m), style=ft.ButtonStyle( color=COLORS["PRIMARY_DARK"], side=ft.BorderSide(2, COLORS["BORDER"]), padding=ft.padding.symmetric(horizontal=20, vertical=12), overlay_color=COLORS["BG_HOVER"], ) ) mood_buttons.controls.append(btn) # Кнопка "Показать все" show_all_btn = ft.FilledButton( "Показать все", on_click=lambda e: show_all_books(), style=ft.ButtonStyle( color=COLORS["TEXT_WHITE"], bgcolor=COLORS["ACCENT"], padding=ft.padding.symmetric(horizontal=20, vertical=12), ) ) # Показываем все книги при запуске show_all_books() # Собираем интерфейс page.add( header, ft.Container( content=ft.Column([ ft.Row([ ft.Text("Фильтры", size=20, weight=ft.FontWeight.BOLD, color=COLORS["PRIMARY_DARK"]), ft.Row([favorites_btn, recommendations_btn], spacing=10) # Добавляем обе кнопки в ряд ], alignment=ft.MainAxisAlignment.SPACE_BETWEEN), ft.Text("Жанры", size=16, weight=ft.FontWeight.BOLD, color=COLORS["PRIMARY_DARK"]), genre_buttons, ft.Container(height=10), ft.Text("Настроение", size=16, weight=ft.FontWeight.BOLD, color=COLORS["PRIMARY_DARK"]), mood_buttons, ft.Container(height=15), ft.Row([ filter_text, show_all_btn ], alignment=ft.MainAxisAlignment.SPACE_BETWEEN), ]), bgcolor=COLORS["TEXT_WHITE"], padding=20, border_radius=10, shadow=ft.BoxShadow( spread_radius=1, blur_radius=10, color=COLORS["SHADOW"], ) ), ft.Container(height=20), books_row ) ft.app(target=main, view=ft.WEB_BROWSER)