feat(web): settings with 9 sidebar sections and Agent upstream management
- /console/settings#<section>[/<anchor>]; legacy ?tab= redirected in clientLoader - SETTINGS_SECTIONS in contracts with field-ownership test - Agent section: upstream list, create wizard (provider -> credentials/model -> login/test/default), edit drawer with OAuth browser/device login, test, set default, delete - sites section with site registration, snapshot/rate-limit drawer and account credentials - path mappings moved into downloader / media-server drawers; metadata and account sections Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
459991421e
commit
c67f6a9682
25 files changed
+3842
-942
No files matched your search
@@ -0,0 +1,45 @@
|
||||
import type { ReactNode } from "react";
|
||||
import { StatusBadge } from "~/components/console/status-badge.tsx";
|
||||
import { cn } from "~/lib/utils.ts";
|
||||
|
||||
/** 分区内锚点 id:`<分区>-<节>`,URL hash 写作 `#<分区>/<节>` */
|
||||
export const anchorId = (section: string, anchor: string) => `settings-${section}-${anchor}`;
|
||||
|
||||
/** 设置分区里的一节:标题 + 一句说明 + 未保存提示 + 内容;带锚点 */
|
||||
export function SettingsBlock({
|
||||
section,
|
||||
anchor,
|
||||
title,
|
||||
description,
|
||||
dirty,
|
||||
actions,
|
||||
plain,
|
||||
children,
|
||||
}: {
|
||||
section: string;
|
||||
anchor: string;
|
||||
title: string;
|
||||
description?: ReactNode;
|
||||
dirty?: boolean;
|
||||
actions?: ReactNode;
|
||||
/** 不包卡片(内容自带 DataTable 卡片时用) */
|
||||
plain?: boolean;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
const id = anchorId(section, anchor);
|
||||
return (
|
||||
<section id={id} aria-labelledby={`${id}-title`} className="scroll-mt-24">
|
||||
<div className="mb-3 flex flex-wrap items-end justify-between gap-3">
|
||||
<div className="min-w-0">
|
||||
<h2 id={`${id}-title`} className="flex items-center gap-2 text-body font-semibold text-foreground">
|
||||
{title}
|
||||
{dirty ? <StatusBadge tone="warning">未保存</StatusBadge> : null}
|
||||
</h2>
|
||||
{description ? <p className="mt-0.5 max-w-2xl text-caption text-muted-foreground">{description}</p> : null}
|
||||
</div>
|
||||
{actions ? <div className="flex shrink-0 items-center gap-2">{actions}</div> : null}
|
||||
</div>
|
||||
<div className={cn(!plain && "pg-slab min-w-0 rounded-xl p-5")}>{children}</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user