AI-News/backend/app/db/repositories/home_featured.py
2025-12-04 10:04:21 +08:00

83 lines
2.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# app/db/repositories/home_featured.py
from typing import List, Sequence
from asyncpg import Connection
from app.db.repositories.base import BaseRepository
class HomeFeaturedRepository(BaseRepository):
"""
维护首页推送文章的排序列表(最多 10 条)。
仅存 slug + sort_order真正返回文章数据时再通过 ArticlesRepository 拉取。
"""
def __init__(self, conn: Connection) -> None:
super().__init__(conn)
async def _ensure_table(self) -> None:
await self.connection.execute(
"""
CREATE TABLE IF NOT EXISTS home_featured_articles (
slug TEXT PRIMARY KEY,
sort_order INT NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
""",
)
async def list_slugs(self, *, limit: int = 10) -> List[str]:
await self._ensure_table()
rows = await self.connection.fetch(
"""
SELECT slug
FROM home_featured_articles
ORDER BY sort_order ASC, updated_at DESC, created_at DESC
LIMIT $1;
""",
limit,
)
return [row["slug"] for row in rows]
async def save_slugs(self, *, slugs: Sequence[str], limit: int = 10) -> List[str]:
"""
保存首页推送顺序,自动去重并截断到 limit。
返回最终生效的 slug 顺序。
"""
await self._ensure_table()
clean_slugs: List[str] = []
for slug in slugs:
normalized = str(slug).strip()
if not normalized:
continue
if normalized not in clean_slugs:
clean_slugs.append(normalized)
clean_slugs = clean_slugs[:limit]
async with self.connection.transaction():
if clean_slugs:
await self.connection.execute(
"""
DELETE FROM home_featured_articles
WHERE slug <> ALL($1::text[]);
""",
clean_slugs,
)
for idx, slug in enumerate(clean_slugs):
await self.connection.execute(
"""
INSERT INTO home_featured_articles (slug, sort_order)
VALUES ($1, $2)
ON CONFLICT (slug) DO UPDATE
SET sort_order = EXCLUDED.sort_order,
updated_at = NOW();
""",
slug,
idx,
)
else:
await self.connection.execute("DELETE FROM home_featured_articles;")
return clean_slugs