- 左栏三组分区 + 当前分区的节;窄屏为搜索框、分组下拉和节的横排胶囊 - 搜索框按分区、节、节别名和字段名定位,选中字段时滚到该字段并聚焦 - 旧 hash(#automation/cache、#api-keys、#library/scrape 等)replace 到新位置 - 下载器分区放下载盘水位与保种缺省值,名字与实例抽屉统一(暂停线 / 恢复线 / 保种天数) - 新增获取、整理与刮削、系统、缓存分区;API Key 并入账户与安全,快捷键移到界面 - 补上缺的入口:最小视频体积、子会话并发与层数、搜索站点;日志保留天数(已废弃)不再显示 - 缓存分区按区列出条数、占用、最近写入,单区清空二次确认;TMDB 与图片缓存并入 - 保存提示统一为「已保存「节名」」;按入库口径把相关文案改成「整理」 Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
74 lines
2.8 KiB
TypeScript
74 lines
2.8 KiB
TypeScript
import {
|
|
resolveSettingsHash,
|
|
SETTINGS_GROUPS,
|
|
SETTINGS_SECTIONS,
|
|
type SettingsSectionDef,
|
|
type SettingsSectionId,
|
|
} from "@umt/contracts";
|
|
import {
|
|
Bot,
|
|
Database,
|
|
Download,
|
|
FolderTree,
|
|
Globe,
|
|
type LucideIcon,
|
|
Monitor,
|
|
Search,
|
|
Settings2,
|
|
Shield,
|
|
Tags,
|
|
Tv,
|
|
Wand2,
|
|
} from "lucide-react";
|
|
import type { ReactNode } from "react";
|
|
import { AccountSection } from "./account.tsx";
|
|
import { AcquireSection } from "./acquire.tsx";
|
|
import { AgentSection } from "./agent.tsx";
|
|
import { CacheSection } from "./cache.tsx";
|
|
import { DownloadersSection } from "./downloaders.tsx";
|
|
import { MediaServersSection } from "./instances.tsx";
|
|
import { InterfaceSection } from "./interface.tsx";
|
|
import { LibrarySection } from "./library.tsx";
|
|
import { MetadataSection } from "./metadata.tsx";
|
|
import { OrganizeSection } from "./organize.tsx";
|
|
import { SitesSection } from "./sites.tsx";
|
|
import { SystemSection } from "./system.tsx";
|
|
|
|
// 设置分区:文案、分组与字段归属在 contracts 的 SETTINGS_SECTIONS,这里只挂图标与渲染
|
|
|
|
const UI: Record<SettingsSectionId, { icon: LucideIcon; render: () => ReactNode }> = {
|
|
downloaders: { icon: Download, render: () => <DownloadersSection /> },
|
|
"media-servers": { icon: Tv, render: () => <MediaServersSection /> },
|
|
sites: { icon: Globe, render: () => <SitesSection /> },
|
|
metadata: { icon: Tags, render: () => <MetadataSection /> },
|
|
acquire: { icon: Search, render: () => <AcquireSection /> },
|
|
library: { icon: FolderTree, render: () => <LibrarySection /> },
|
|
organize: { icon: Wand2, render: () => <OrganizeSection /> },
|
|
agent: { icon: Bot, render: () => <AgentSection /> },
|
|
system: { icon: Settings2, render: () => <SystemSection /> },
|
|
cache: { icon: Database, render: () => <CacheSection /> },
|
|
account: { icon: Shield, render: () => <AccountSection /> },
|
|
interface: { icon: Monitor, render: () => <InterfaceSection /> },
|
|
};
|
|
|
|
export type SectionView = SettingsSectionDef & { icon: LucideIcon; render: () => ReactNode };
|
|
export const SECTIONS: SectionView[] = SETTINGS_SECTIONS.map((s) => ({ ...s, ...UI[s.id] }));
|
|
|
|
/** 左栏分组:接入 / 流程 / 系统 */
|
|
export const SECTION_GROUPS = SETTINGS_GROUPS.map((g) => ({
|
|
...g,
|
|
sections: SECTIONS.filter((s) => s.group === g.id),
|
|
}));
|
|
|
|
/**
|
|
* URL hash:`#<分区>` 或 `#<分区>/<节>`;旧 hash 换成新位置(moved = true 时页面用 replace 改地址栏),
|
|
* 不认识的落到第一个分区
|
|
*/
|
|
export function parseSettingsHash(hash: string): { section: SectionView; anchor: string | null; moved: boolean } {
|
|
const r = resolveSettingsHash(hash);
|
|
const section = SECTIONS.find((s) => s.id === r.section) ?? (SECTIONS[0] as SectionView);
|
|
return { section, anchor: r.section ? r.anchor : null, moved: r.moved };
|
|
}
|
|
|
|
export const settingsHash = (section: string, anchor?: string | null) => `#${section}${anchor ? `/${anchor}` : ""}`;
|