- 新增 TechInfo 折叠组件(默认收起,标题「技术信息」);设置新增「界面」分区, 「默认展开技术信息」开关存本机浏览器 - 原因码表 @umt/contracts reasons.ts(identity_unknown、blocked:target_exists、below_min_size… → 一句人话 + 下一步),服务端整理记录 message 与冲突事项标题/摘要改用它 - 整理记录列表/详情、下载详情与时间线:原码、ID、hash、用时、变更序号进技术信息; 下载完成但入库失败时单独提示;时间线只列有记录的阶段,标题改「经过」 - 待处理:没识别出作品类事项主按钮「指定作品」(搜媒体库 + TMDB,走已有 resolve; 整理类事项打开重新整理),忽略为次要;去掉正常态徽章与「实时」指示;原始证据改「详细信息」进技术信息 - 整理成功后同时关闭该下载的「没识别出作品」事项 Co-Authored-By: Claude Opus 5.5 <[email protected]>
52 lines
2.3 KiB
TypeScript
52 lines
2.3 KiB
TypeScript
import { SETTINGS_SECTIONS, type SettingsSectionDef, type SettingsSectionId } from "@umt/contracts";
|
|
import {
|
|
Bot,
|
|
FolderTree,
|
|
KeyRound,
|
|
type LucideIcon,
|
|
Monitor,
|
|
Server,
|
|
Shield,
|
|
Tags,
|
|
Tv,
|
|
UserCog,
|
|
Zap,
|
|
} from "lucide-react";
|
|
import type { ReactNode } from "react";
|
|
import { AccountSection } from "./account.tsx";
|
|
import { AgentSection } from "./agent.tsx";
|
|
import { ApiKeysSection } from "./api-keys.tsx";
|
|
import { AutomationSection } from "./automation.tsx";
|
|
import { DownloadersSection, MediaServersSection } from "./instances.tsx";
|
|
import { InterfaceSection } from "./interface.tsx";
|
|
import { LibrarySection } from "./library.tsx";
|
|
import { MetadataSection } from "./metadata.tsx";
|
|
import { SitesSection } from "./sites.tsx";
|
|
|
|
// 设置分区:文案与字段归属在 contracts 的 SETTINGS_SECTIONS,这里只挂图标与渲染
|
|
|
|
const UI: Record<SettingsSectionId, { icon: LucideIcon; render: () => ReactNode }> = {
|
|
automation: { icon: Zap, render: () => <AutomationSection /> },
|
|
sites: { icon: UserCog, render: () => <SitesSection /> },
|
|
downloaders: { icon: Server, render: () => <DownloadersSection /> },
|
|
library: { icon: FolderTree, render: () => <LibrarySection /> },
|
|
"media-servers": { icon: Tv, render: () => <MediaServersSection /> },
|
|
metadata: { icon: Tags, render: () => <MetadataSection /> },
|
|
agent: { icon: Bot, render: () => <AgentSection /> },
|
|
"api-keys": { icon: KeyRound, render: () => <ApiKeysSection /> },
|
|
interface: { icon: Monitor, render: () => <InterfaceSection /> },
|
|
account: { icon: Shield, render: () => <AccountSection /> },
|
|
};
|
|
|
|
export type SectionView = SettingsSectionDef & { icon: LucideIcon; render: () => ReactNode };
|
|
export const SECTIONS: SectionView[] = SETTINGS_SECTIONS.map((s) => ({ ...s, ...UI[s.id] }));
|
|
|
|
/** URL hash:`#<分区>` 或 `#<分区>/<节>`;不认识的落到默认分区 */
|
|
export function parseSettingsHash(hash: string): { section: SectionView; anchor: string | null } {
|
|
const [id, anchor] = decodeURIComponent(hash.replace(/^#/, "")).split("/");
|
|
const section = SECTIONS.find((s) => s.id === id) ?? (SECTIONS[0] as SectionView);
|
|
return { section, anchor: section.id === id && anchor ? anchor : null };
|
|
}
|
|
|
|
export const settingsHash = (section: string, anchor?: string | null) => `#${section}${anchor ? `/${anchor}` : ""}`;
|