fix: 修复路由竞态、删除确认、输入同步等交互问题

- router.js 添加竞态防护和页面清理钩子
- logs.js 切换 Tab 时清空搜索框
- models.js 删除 Provider 添加确认提示,输入框改 oninput 实时同步
- mcp.js 删除 Server 添加确认提示
- gateway.js Tailscale 地址为空时保留原配置
This commit is contained in:
晴天
2026-02-26 23:23:11 +08:00
parent ed353cb3b5
commit 91c33f78a4
5 changed files with 26 additions and 4 deletions

View File

@@ -107,7 +107,7 @@ async function saveConfig(page, state) {
state.config.gateway = {
...state.config.gateway,
port, bind, mode, authToken,
tailscale: tailscaleAddr ? { address: tailscaleAddr } : undefined,
tailscale: tailscaleAddr ? { address: tailscaleAddr } : (state.config.gateway?.tailscale || undefined),
}
try {

View File

@@ -42,6 +42,7 @@ export async function render() {
page.querySelectorAll('.tab').forEach(t => t.classList.remove('active'))
tab.classList.add('active')
currentTab = tab.dataset.tab
page.querySelector('#log-search').value = ''
loadLog(page, currentTab)
}
})

View File

@@ -76,6 +76,7 @@ function renderServers(page, state) {
const action = btn.dataset.action
if (action === 'delete') {
if (!confirm(`确定删除 MCP Server "${key}"`)) return
if (state.config.mcpServers) delete state.config.mcpServers[key]
else delete state.config[key]
renderServers(page, state)

View File

@@ -102,6 +102,7 @@ function renderProviders(page, state) {
const models = section.querySelector('.provider-models')
models.style.display = models.style.display === 'none' ? 'block' : 'none'
} else if (action === 'delete-provider') {
if (!confirm(`确定删除 Provider "${providerKey}"`)) return
delete state.config.models.providers[providerKey]
renderProviders(page, state)
toast(`已删除 ${providerKey}`, 'info')
@@ -124,9 +125,9 @@ function renderProviders(page, state) {
}
})
// 输入框变更同步到 state
// 输入框变更实时同步到 state
listEl.querySelectorAll('[data-field]').forEach(input => {
input.onchange = () => {
input.oninput = () => {
const providerKey = input.closest('[data-provider]').dataset.provider
state.config.models.providers[providerKey][input.dataset.field] = input.value
}