refactor: 清理遗留设置模型与无用代码

- 删除 settings 的 sections 与 sidebar 六个旧排序/显隐字段,前后端类型与校验同步
- 删除旧分类模型 types、旧 /api/catalog 客户端、旧路由解析与 settings CRUD
- 删除未使用的 AppProject::initial
- 删除 27 条已无组件的 CSS 规则(159 行)
- 保持现有首页/接口页渲染,cargo test 52 passed
This commit is contained in:
2026-11-03 19:49:04 +08:00
parent ffa123d2cd
commit 6dabeabaf2
9 changed files with 16 additions and 804 deletions
+1 -63
View File
@@ -1,5 +1,3 @@
import type { Category } from './data/types'
export type Project = {
name: string
route_path: string
@@ -26,7 +24,7 @@ export async function fetchProjects(signal?: AbortSignal): Promise<Project[]> {
return Array.isArray(payload.projects) ? payload.projects : []
}
export type ProjectEventsHandlers = {
type ProjectEventsHandlers = {
onProjects: (projects: Project[]) => void
/** SSE 连接建立 / 断开时回调,浏览器的 EventSource 会自行重连。 */
onConnectionChange?: (connected: boolean) => void
@@ -68,63 +66,3 @@ export function subscribeProjects(handlers: ProjectEventsHandlers): () => void {
source.close()
}
}
// ---------------------------------------------------------------------------
// 内容目录:数据来自后端的 SQLite 内容库(data/stash.db),不再是前端静态数组
// ---------------------------------------------------------------------------
const CATALOG_ENDPOINT = '/api/catalog'
const CATALOG_EVENTS_ENDPOINT = '/api/catalog/events'
type CatalogPayload = {
categories?: Category[]
}
/** 内容目录的完整返回;侧栏由这份分类树派生 */
export type Catalog = {
categories: Category[]
}
/**
* 拉取完整内容目录。
*
* 数据量只有几十 KB,一次全量取回即可;搜索仍然在前端按关键字过滤。
*/
export async function fetchCatalog(signal?: AbortSignal): Promise<Catalog> {
const response = await fetch(CATALOG_ENDPOINT, {
signal,
headers: { Accept: 'application/json' },
})
if (!response.ok) {
throw new Error(`请求 ${CATALOG_ENDPOINT} 失败:HTTP ${response.status}`)
}
const payload = (await response.json()) as CatalogPayload
return {
categories: Array.isArray(payload.categories) ? payload.categories : [],
}
}
/**
* 订阅内容库变更。
*
* 服务端用 SQLite 的 data_version 检测「外部工具改了库」,事件里不带数据,
* 只表示「该重新拉一次了」,避免两套数据结构需要保持同步。
*/
export function subscribeCatalog(onChange: () => void): () => void {
if (typeof EventSource === 'undefined') {
return () => {}
}
const source = new EventSource(CATALOG_EVENTS_ENDPOINT)
const handleChange = () => onChange()
source.addEventListener('catalog', handleChange)
return () => {
source.removeEventListener('catalog', handleChange)
source.close()
}
}