feat(db): 内容库迁入 SQLite,分类与侧栏导航改为数据库驱动

This commit is contained in:
2026-10-23 20:22:23 +08:00
parent 386c0f77c7
commit 41fed5e64d
23 changed files with 2867 additions and 319 deletions
+24 -2
View File
@@ -7,7 +7,7 @@ import { ItemDetailView } from './components/content/ItemDetailView'
import { SiteHeader } from './components/header/SiteHeader'
import { SearchBar } from './components/search/SearchBar'
import { Sidebar } from './components/sidebar/Sidebar'
import { buildCategories } from './data/catalog'
import { withLocalCategory } from './data/local'
import {
appDetailModel,
posterDetailModel,
@@ -24,6 +24,7 @@ import {
relatedPosterItems,
} from './data/types'
import { useProjects } from './useProjects'
import { useCatalog } from './useCatalog'
import './App.css'
/**
@@ -39,13 +40,18 @@ type View =
export default function App() {
const { status, projects, error, live, refreshing, refresh } = useProjects()
// 内容目录来自后端 SQLite 内容库;本地服务分类仍由托管项目动态生成
const catalog = useCatalog()
const [keyword, setKeyword] = useState('')
const [view, setView] = useState<View>({ type: 'home' })
const [scrolled, setScrolled] = useState(false)
const searchRef = useRef<HTMLInputElement>(null)
const scrollRef = useRef<HTMLDivElement>(null)
const categories = useMemo(() => buildCategories(projects), [projects])
const categories = useMemo(
() => withLocalCategory(projects, catalog.categories),
[projects, catalog.categories],
)
const visibleCategories = useMemo(
() => filterCategories(categories, keyword),
[categories, keyword],
@@ -184,6 +190,7 @@ export default function App() {
<div className="layout">
<Sidebar
projects={projects}
nav={catalog.nav}
live={live}
refreshing={refreshing}
onRefresh={refresh}
@@ -217,8 +224,23 @@ export default function App() {
</div>
)}
{/* 内容库读取失败通常是用户改坏了 data 列里的 JSON,错误信息会带条目 id */}
{catalog.status === 'error' && (
<div className="notice notice-error" role="alert">
<strong>内容库读取失败</strong>
<p>{catalog.error}</p>
<button type="button" className="notice-action" onClick={catalog.reload}>
重试
</button>
</div>
)}
{detailView === undefined && itemView === undefined && (
<>
{catalog.status === 'loading' && (
<p className="section-empty">正在读取内容库…</p>
)}
<HomeView
categories={visibleCategories}
onOpenDetail={openDetail}