fix(chat): preserve settings context
This commit is contained in:
+12
-2
@@ -763,7 +763,11 @@ function renderEffortControl(name: string) {
|
|||||||
|
|
||||||
function renderModelOption(choice: ModelChoice) {
|
function renderModelOption(choice: ModelChoice) {
|
||||||
const active = choice.provider.id === state.providerId && choice.model.id === state.model;
|
const active = choice.provider.id === state.providerId && choice.model.id === state.model;
|
||||||
return `<button class="model-option${active ? " active" : ""}" type="button" data-action="choose-model" data-provider="${escapeHtml(choice.provider.id)}" data-model="${escapeHtml(choice.model.id)}"><span><strong>${escapeHtml(compactModelName(choice.model.name || choice.model.id))}</strong><small>${escapeHtml(choice.provider.name)}</small></span><small>${choice.provider.connection.type === "frontend" ? "Frontend" : "Backend"}</small></button>`;
|
const displayName = compactModelName(choice.model.name || choice.model.id);
|
||||||
|
const detail = displayName === choice.model.id
|
||||||
|
? choice.provider.name
|
||||||
|
: `${choice.model.id} · ${choice.provider.name}`;
|
||||||
|
return `<button class="model-option${active ? " active" : ""}" type="button" data-action="choose-model" data-provider="${escapeHtml(choice.provider.id)}" data-model="${escapeHtml(choice.model.id)}"><span><strong>${escapeHtml(displayName)}</strong><small title="${escapeHtml(choice.model.id)}">${escapeHtml(detail)}</small></span><small>${choice.provider.connection.type === "frontend" ? "Frontend" : "Backend"}</small></button>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function quickModelChoices(choices: ModelChoice[]) {
|
function quickModelChoices(choices: ModelChoice[]) {
|
||||||
@@ -811,7 +815,12 @@ function renderSettingsPage() {
|
|||||||
const providerSettings = renderProviderSettings();
|
const providerSettings = renderProviderSettings();
|
||||||
const accountHref = state.authenticated ? "https://xiteng.site/account" : appUrl("/api/login");
|
const accountHref = state.authenticated ? "https://xiteng.site/account" : appUrl("/api/login");
|
||||||
const accountLabel = state.authenticated ? "管理 Backend Provider 与凭据" : "登录并配置 Backend Provider";
|
const accountLabel = state.authenticated ? "管理 Backend Provider 与凭据" : "登录并配置 Backend Provider";
|
||||||
return `<section class="settings-page" role="dialog" aria-modal="true" aria-label="设置"><header class="settings-page-header"><button type="button" data-action="close-settings" aria-label="关闭设置">${icons.close}</button><span><strong>设置</strong><small>更改会自动保存</small></span></header><div class="settings-layout"><nav class="settings-nav" aria-label="设置分类"><a href="#settings-models">模型</a><a href="#settings-generation">生成</a><a href="#settings-providers">Provider</a><a href="#settings-interface">界面</a></nav><main class="settings-content"><section class="settings-card" id="settings-models"><header><h2>模型</h2><p>选择当前会话使用的模型。</p></header><label class="settings-model-search">${icons.search}<input value="${escapeHtml(state.modelQuery)}" data-action="model-search" placeholder="搜索 Provider 或模型"></label><div class="settings-model-groups">${groups || '<p class="settings-empty">没有匹配的模型</p>'}</div></section><section class="settings-card" id="settings-generation"><header><h2>生成</h2><p>这些参数随当前会话保存。</p></header>${renderGenerationSettings()}</section><section class="settings-card" id="settings-providers"><header><h2>Provider</h2><p>管理浏览器直连端点;Backend 凭据由账户安全保存。</p></header>${providerSettings || '<p class="settings-empty">当前没有可配置的浏览器 Provider。</p>'}<a class="settings-account-link" href="${accountHref}">${icons.settings}<span>${accountLabel}</span></a></section><section class="settings-card" id="settings-interface"><header><h2>界面</h2><p>这些选项仅保存在当前浏览器。</p></header><div class="settings-interface-options"><label class="settings-check"><input type="checkbox" data-action="advanced-actions"${state.advancedActions ? " checked" : ""}><span><strong>显示高级对话操作</strong><small>显示“需要回答”和编辑助手回答</small></span></label><label class="settings-check"><input type="checkbox" data-action="history-tree-setting"${state.historyTree ? " checked" : ""}><span><strong>树状显示聊天历史</strong><small>按会话名称中的路径组织侧栏</small></span></label></div></section></main></div></section>`;
|
return `<section class="settings-page" role="dialog" aria-modal="true" aria-label="设置"><header class="settings-page-header"><button type="button" data-action="close-settings" aria-label="关闭设置">${icons.close}</button><span><strong>设置</strong><small>更改会自动保存</small></span></header><div class="settings-layout"><nav class="settings-nav" aria-label="设置分类"><button type="button" data-action="scroll-settings-section" data-id="settings-models">模型</button><button type="button" data-action="scroll-settings-section" data-id="settings-generation">生成</button><button type="button" data-action="scroll-settings-section" data-id="settings-providers">Provider</button><button type="button" data-action="scroll-settings-section" data-id="settings-interface">界面</button></nav><main class="settings-content"><section class="settings-card" id="settings-models"><header><h2>模型</h2><p>选择当前会话使用的模型。</p></header><label class="settings-model-search">${icons.search}<input value="${escapeHtml(state.modelQuery)}" data-action="model-search" placeholder="搜索 Provider 或模型"></label><div class="settings-model-groups">${groups || '<p class="settings-empty">没有匹配的模型</p>'}</div></section><section class="settings-card" id="settings-generation"><header><h2>生成</h2><p>这些参数随当前会话保存。</p></header>${renderGenerationSettings()}</section><section class="settings-card" id="settings-providers"><header><h2>Provider</h2><p>管理浏览器直连端点;Backend 凭据由账户安全保存。</p></header>${providerSettings || '<p class="settings-empty">当前没有可配置的浏览器 Provider。</p>'}<a class="settings-account-link" href="${accountHref}">${icons.settings}<span>${accountLabel}</span></a></section><section class="settings-card" id="settings-interface"><header><h2>界面</h2><p>这些选项仅保存在当前浏览器。</p></header><div class="settings-interface-options"><label class="settings-check"><input type="checkbox" data-action="advanced-actions"${state.advancedActions ? " checked" : ""}><span><strong>显示高级对话操作</strong><small>显示“需要回答”和编辑助手回答</small></span></label><label class="settings-check"><input type="checkbox" data-action="history-tree-setting"${state.historyTree ? " checked" : ""}><span><strong>树状显示聊天历史</strong><small>按会话名称中的路径组织侧栏</small></span></label></div></section></main></div></section>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrollSettingsSection(id: string) {
|
||||||
|
const section = root.querySelector<HTMLElement>(`#${CSS.escape(id)}`);
|
||||||
|
section?.scrollIntoView({behavior: "smooth", block: "start"});
|
||||||
}
|
}
|
||||||
|
|
||||||
function historyItem(item: ConversationSummary, label = item.name, depth = 0) {
|
function historyItem(item: ConversationSummary, label = item.name, depth = 0) {
|
||||||
@@ -2503,6 +2512,7 @@ root.addEventListener("click", (event) => {
|
|||||||
const action = button.dataset.action;
|
const action = button.dataset.action;
|
||||||
if (action === "open-settings") { state.settingsOpen = true; state.modelQuery = ""; renderApp(); }
|
if (action === "open-settings") { state.settingsOpen = true; state.modelQuery = ""; renderApp(); }
|
||||||
if (action === "close-settings") { state.settingsOpen = false; state.modelQuery = ""; renderApp(); }
|
if (action === "close-settings") { state.settingsOpen = false; state.modelQuery = ""; renderApp(); }
|
||||||
|
if (action === "scroll-settings-section" && button.dataset.id) scrollSettingsSection(button.dataset.id);
|
||||||
if (action === "toggle-history") { state.historyOpen = !state.historyOpen; renderApp(); }
|
if (action === "toggle-history") { state.historyOpen = !state.historyOpen; renderApp(); }
|
||||||
if (action === "close-history") { state.historyOpen = false; renderApp(); }
|
if (action === "close-history") { state.historyOpen = false; renderApp(); }
|
||||||
if (action === "toggle-history-tree") {
|
if (action === "toggle-history-tree") {
|
||||||
|
|||||||
+3
-3
@@ -102,8 +102,8 @@ button, a { -webkit-tap-highlight-color: transparent; }
|
|||||||
.settings-page-header > span small { margin-top: 2px; color: var(--muted); font-size: 9px; }
|
.settings-page-header > span small { margin-top: 2px; color: var(--muted); font-size: 9px; }
|
||||||
.settings-layout { display: grid; min-height: 0; flex: 1; grid-template-columns: 176px minmax(0, 760px); justify-content: center; gap: 28px; overflow: hidden; padding: 28px 24px; }
|
.settings-layout { display: grid; min-height: 0; flex: 1; grid-template-columns: 176px minmax(0, 760px); justify-content: center; gap: 28px; overflow: hidden; padding: 28px 24px; }
|
||||||
.settings-nav { display: grid; align-content: start; gap: 3px; }
|
.settings-nav { display: grid; align-content: start; gap: 3px; }
|
||||||
.settings-nav a { border-radius: 9px; padding: 9px 11px; color: var(--muted); font-size: 11px; font-weight: 650; text-decoration: none; }
|
.settings-nav button { border: 0; border-radius: 9px; padding: 9px 11px; background: transparent; color: var(--muted); font-size: 11px; font-weight: 650; text-align: left; cursor: pointer; }
|
||||||
.settings-nav a:hover { background: var(--soft); color: var(--text); }
|
.settings-nav button:hover { background: var(--soft); color: var(--text); }
|
||||||
.settings-content { display: grid; min-width: 0; align-content: start; overflow-y: auto; gap: 16px; padding: 0 8px 40px 0; scroll-behavior: smooth; }
|
.settings-content { display: grid; min-width: 0; align-content: start; overflow-y: auto; gap: 16px; padding: 0 8px 40px 0; scroll-behavior: smooth; }
|
||||||
.settings-card { border: 1px solid var(--line); border-radius: 16px; padding: 18px; background: var(--panel); scroll-margin-top: 12px; }
|
.settings-card { border: 1px solid var(--line); border-radius: 16px; padding: 18px; background: var(--panel); scroll-margin-top: 12px; }
|
||||||
.settings-card > header { margin-bottom: 16px; }
|
.settings-card > header { margin-bottom: 16px; }
|
||||||
@@ -376,7 +376,7 @@ button, a { -webkit-tap-highlight-color: transparent; }
|
|||||||
.settings-page-header { height: 58px; padding: 0 12px; }
|
.settings-page-header { height: 58px; padding: 0 12px; }
|
||||||
.settings-layout { display: flex; flex-direction: column; gap: 12px; padding: 12px 0 0; }
|
.settings-layout { display: flex; flex-direction: column; gap: 12px; padding: 12px 0 0; }
|
||||||
.settings-nav { display: flex; flex: 0 0 auto; gap: 2px; overflow-x: auto; padding: 0 12px; }
|
.settings-nav { display: flex; flex: 0 0 auto; gap: 2px; overflow-x: auto; padding: 0 12px; }
|
||||||
.settings-nav a { flex: 0 0 auto; padding: 8px 10px; }
|
.settings-nav button { flex: 0 0 auto; padding: 8px 10px; }
|
||||||
.settings-content { gap: 12px; padding: 0 12px max(28px, env(safe-area-inset-bottom)); }
|
.settings-content { gap: 12px; padding: 0 12px max(28px, env(safe-area-inset-bottom)); }
|
||||||
.settings-card { border-radius: 13px; padding: 14px; }
|
.settings-card { border-radius: 13px; padding: 14px; }
|
||||||
.settings-model-group > div { grid-template-columns: 1fr; }
|
.settings-model-group > div { grid-template-columns: 1fr; }
|
||||||
|
|||||||
Reference in New Issue
Block a user