From 3161470a7dff742e7f2e3f30892fca645beba5a3 Mon Sep 17 00:00:00 2001 From: jze9 Date: Wed, 17 Jun 2026 18:47:19 +0500 Subject: [PATCH] =?UTF-8?q?feat:=20=D0=BC=D1=83=D0=BB=D1=8C=D1=82=D0=B8?= =?UTF-8?q?=D0=B2=D1=8B=D0=B1=D0=BE=D1=80=20=D0=BA=D0=BE=D0=BB=D0=BB=D0=B5?= =?UTF-8?q?=D0=B4=D0=B6=D0=B5=D0=B9=20=D0=B2=20=D1=84=D0=B8=D0=BB=D1=8C?= =?UTF-8?q?=D1=82=D1=80=D0=B5=20=D0=BF=D1=83=D0=B1=D0=BB=D0=B8=D1=87=D0=BD?= =?UTF-8?q?=D0=BE=D0=B9=20=D0=BB=D0=B5=D0=BD=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Параметр category в /news принимает несколько slug'ов через запятую (category_id IN ...), обратно совместим с одиночным slug. FilterBar: чипы колледжей стали переключателями (можно отметить несколько), filters.category теперь массив. Co-Authored-By: Claude Opus 4.8 --- api/route/public.py | 10 +++++++--- web-react/src/components/FilterBar.jsx | 19 ++++++++++++++----- web-react/src/pages/NewsFeed.jsx | 4 ++-- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/api/route/public.py b/api/route/public.py index 69990a0..6cd54bf 100644 --- a/api/route/public.py +++ b/api/route/public.py @@ -62,9 +62,13 @@ async def list_news( ) if category: - cat = (await db.execute(select(Category).where(Category.slug == category))).scalar_one_or_none() - if cat: - base = base.where(Article.category_id == cat.id) + # Поддержка нескольких колледжей: category="slug1,slug2,..." + slugs = [s for s in (part.strip() for part in category.split(",")) if s] + cat_ids = ( + await db.execute(select(Category.id).where(Category.slug.in_(slugs))) + ).scalars().all() + if cat_ids: + base = base.where(Article.category_id.in_(cat_ids)) else: return {"total": 0, "offset": offset, "limit": limit, "has_more": False, "items": []} diff --git a/web-react/src/components/FilterBar.jsx b/web-react/src/components/FilterBar.jsx index 87c077b..e4567fe 100644 --- a/web-react/src/components/FilterBar.jsx +++ b/web-react/src/components/FilterBar.jsx @@ -11,19 +11,28 @@ const DATE_PRESETS = [ export default function FilterBar({ categories, tags, filters, onChange }) { const set = key => val => onChange({ ...filters, [key]: val }) + // Мультивыбор колледжей: filters.category — массив slug'ов + const selected = filters.category ?? [] + const toggleCategory = slug => { + const next = selected.includes(slug) + ? selected.filter(s => s !== slug) + : [...selected, slug] + set('category')(next) + } + return (
- {/* Категории */} + {/* Категории (можно выбрать несколько) */}
{categories.map(c => ( ))}
diff --git a/web-react/src/pages/NewsFeed.jsx b/web-react/src/pages/NewsFeed.jsx index 45e51ce..57ffdc0 100644 --- a/web-react/src/pages/NewsFeed.jsx +++ b/web-react/src/pages/NewsFeed.jsx @@ -26,7 +26,7 @@ export default function NewsFeed() { const [loading, setLoading] = useState(true) const [loadingMore, setLoadingMore] = useState(false) const [hasMore, setHasMore] = useState(false) - const [filters, setFilters] = useState({ category: null, tag: null, datePreset: '' }) + const [filters, setFilters] = useState({ category: [], tag: null, datePreset: '' }) const offsetRef = useRef(0) const busyRef = useRef(false) @@ -60,7 +60,7 @@ export default function NewsFeed() { const buildParams = useCallback((offset) => { const params = { limit: PAGE_SIZE, offset } - if (filters.category) params.category = filters.category + if (filters.category?.length) params.category = filters.category.join(',') if (filters.tag) params.tag = filters.tag const df = presetToDateFrom(filters.datePreset) if (df) params.date_from = df