feat(settings): add advanced settings navigation tabs

This commit is contained in:
lzt404 committed 2026-07-30 14:40:16 +08:00
1 parent c121e46056
commit 97b6f82e76
5 files changed
+83 -8

No files matched your search

+4 -1
View File
@@ -11,7 +11,7 @@ export const jaOverrides = {
'app.nav.home': 'ホーム',
'app.nav.versions': 'バージョン管理',
'app.nav.kernel': 'コア',
'app.nav.config': '設定',
'app.nav.config': '詳細設定',
'app.nav.thinkingAliases': 'モデルエイリアス',
'app.nav.oauth': 'OAuth',
'app.nav.api': 'API 接続',
@@ -241,6 +241,9 @@ export const jaOverrides = {
'aliases.delete': '{alias} を削除',
'config.routing.roundRobin': 'ラウンドロビン',
'config.routing.fillFirst': '優先充填',
'config.tabs.label': '詳細設定ページ',
'config.tabs.general': '基本設定',
'config.tabs.network': 'ネットワークとルーティング',
'config.error.emptyKey': '認証キーを入力してください',
'config.error.invalidKey': '空白を含まない表示可能な ASCII 文字のみ使用できます',
'config.error.duplicateKey': '同じ認証キーがすでに存在します',
+8 -2
View File
@@ -14,7 +14,7 @@ export const zhCN = {
'app.nav.home': '首页',
'app.nav.versions': '版本管理',
'app.nav.kernel': '内核',
'app.nav.config': '配置',
'app.nav.config': '高级设置',
'app.nav.thinkingAliases': '模型别名',
'app.nav.oauth': 'OAuth',
'app.nav.api': 'API 接入',
@@ -244,6 +244,9 @@ export const zhCN = {
'aliases.delete': '删除 {alias}',
'config.routing.roundRobin': '轮询',
'config.routing.fillFirst': '优先填充',
'config.tabs.label': '高级设置子页面',
'config.tabs.general': '基础设置',
'config.tabs.network': '网络与路由',
'config.error.emptyKey': '鉴权密钥不能为空',
'config.error.invalidKey': '只能使用 ASCII 可见字符,且不能包含空格',
'config.error.duplicateKey': '该鉴权密钥已经存在',
@@ -861,7 +864,7 @@ export const en: Record<MessageKey, string> = {
'app.nav.home': 'Home',
'app.nav.versions': 'Version Management',
'app.nav.kernel': 'Core',
'app.nav.config': 'Settings',
'app.nav.config': 'Advanced Settings',
'app.nav.thinkingAliases': 'Model Aliases',
'app.nav.oauth': 'OAuth',
'app.nav.api': 'API Access',
@@ -1091,6 +1094,9 @@ export const en: Record<MessageKey, string> = {
'aliases.delete': 'Delete {alias}',
'config.routing.roundRobin': 'Round Robin',
'config.routing.fillFirst': 'Fill First',
'config.tabs.label': 'Advanced settings sections',
'config.tabs.general': 'General Settings',
'config.tabs.network': 'Network & Routing',
'config.error.emptyKey': 'The authentication key cannot be empty',
'config.error.invalidKey': 'Use visible ASCII characters only, without spaces',
'config.error.duplicateKey': 'This authentication key already exists',
+1
View File
@@ -1,4 +1,5 @@
const phraseReplacements: ReadonlyArray<readonly [string, string]> = [
['高级设置', '進階設定'],
['繁体中文', '繁體中文'],
['简体中文', '簡體中文'],
['智能体', '智慧代理'],
+50 -5
View File
@@ -48,6 +48,7 @@ type ConfigAction =
| 'network'
| null;
type NoticeTone = 'success' | 'error';
type ConfigSubpage = 'general' | 'network';
const ROUTING_OPTIONS = [
{ value: 'round-robin', labelKey: 'config.routing.roundRobin' },
@@ -70,6 +71,7 @@ export function ConfigPanelPage() {
const [formError, setFormError] = useState('');
const [copiedIndex, setCopiedIndex] = useState<number | null>(null);
const [notice, setNotice] = useState<{ message: string; tone: NoticeTone } | null>(null);
const [activeSubpage, setActiveSubpage] = useState<ConfigSubpage>('general');
const [portDraft, setPortDraft] = useState('8317');
const [allowLanDraft, setAllowLanDraft] = useState(false);
const [proxyUrlDraft, setProxyUrlDraft] = useState('');
@@ -351,7 +353,41 @@ export function ConfigPanelPage() {
return (
<section className="page config-page">
<div className="config-workspace-grid">
<div className="agent-subpage-tabs config-subpage-tabs" role="tablist" aria-label={t('config.tabs.label')}>
<button
type="button"
id="config-subpage-tab-general"
role="tab"
className={activeSubpage === 'general' ? 'active' : ''}
aria-selected={activeSubpage === 'general'}
aria-controls="config-subpage-panel-general"
tabIndex={activeSubpage === 'general' ? 0 : -1}
onClick={() => setActiveSubpage('general')}
>
{t('config.tabs.general')}
</button>
<button
type="button"
id="config-subpage-tab-network"
role="tab"
className={activeSubpage === 'network' ? 'active' : ''}
aria-selected={activeSubpage === 'network'}
aria-controls="config-subpage-panel-network"
tabIndex={activeSubpage === 'network' ? 0 : -1}
onClick={() => setActiveSubpage('network')}
>
{t('config.tabs.network')}
</button>
</div>
{activeSubpage === 'general' ? (
<div
className="config-subpage-panel"
id="config-subpage-panel-general"
role="tabpanel"
aria-labelledby="config-subpage-tab-general"
>
<div className="config-workspace-grid">
<section className="panel config-keys-panel">
<div className="config-panel-heading">
<div className="config-heading-title">
@@ -454,7 +490,7 @@ export function ConfigPanelPage() {
</div>
</section>
<div className="config-side-stack">
<div className="config-side-stack single">
<section className="panel config-setting-panel">
<div className="config-panel-heading">
<div className="config-heading-title">
@@ -485,7 +521,16 @@ export function ConfigPanelPage() {
</label>
</div>
</section>
</div>
</div>
</div>
) : (
<div
className="config-subpage-panel config-network-subpage"
id="config-subpage-panel-network"
role="tabpanel"
aria-labelledby="config-subpage-tab-network"
>
<section className="panel config-setting-panel">
<div className="config-panel-heading">
<div className="config-heading-title">
@@ -516,8 +561,6 @@ export function ConfigPanelPage() {
))}
</div>
</section>
</div>
</div>
<section className="panel config-network-panel">
<div className="config-panel-heading">
@@ -658,6 +701,8 @@ export function ConfigPanelPage() {
</label>
</div>
</section>
</div>
)}
{addDialogOpen ? (
<div className="config-dialog-backdrop" onMouseDown={(event) => {
+20
View File
@@ -861,6 +861,16 @@ input:focus-visible {
height: 350px;
}
.config-subpage-panel {
display: grid;
min-width: 0;
gap: 18px;
}
.config-network-subpage > .config-setting-panel {
width: min(420px, 100%);
}
.control-panel {
grid-column: auto;
}
@@ -1503,6 +1513,12 @@ input:focus-visible {
height: 350px;
}
.config-side-stack.single {
grid-template-rows: 166px;
align-content: start;
height: 166px;
}
.config-setting-panel {
grid-template-rows: 42px minmax(0, 1fr);
gap: 16px;
@@ -6725,6 +6741,10 @@ input:focus-visible {
height: 166px;
}
.config-side-stack.single {
grid-template-columns: 1fr;
}
.control-panel,
.version-panel {
grid-column: auto;