fix(external-systems): 支持已有连接直接重连

This commit is contained in:
caoqianming 2026-08-11 10:48:50 +08:00
parent ca4998265e
commit 729c4caafb
4 changed files with 34 additions and 10 deletions

View File

@ -5,6 +5,10 @@
> 所以不是每个版本号都有条目。条目格式 `## <版本> — <日期>`,新条目加在最上面。 > 所以不是每个版本号都有条目。条目格式 `## <版本> — <日期>`,新条目加在最上面。
> 工程口径的完整记录见 `PROGRESS.md` / git log。 > 工程口径的完整记录见 `PROGRESS.md` / git log。
## 0.63.7 — 2026-08-11
- 已连接的外部系统现在可直接在凭据表单中重新连接并验证,不再被“该外部系统已连接”的重复创建提示拦住。
## 0.63.6 — 2026-08-11 ## 0.63.6 — 2026-08-11
- 修复外部系统配置弹框未按 OpenAPI、MCP 和认证方式切换配置项的问题;弹框滚动时不再带动后台页面。 - 修复外部系统配置弹框未按 OpenAPI、MCP 和认证方式切换配置项的问题;弹框滚动时不再带动后台页面。

View File

@ -2,7 +2,7 @@
> 配合 `DESIGN.md`。本文件只记 phase 状态、决策偏差、文件量、下一步。每条 1-2 句:做了啥 + 关键判断;细节查 `git log` / `git diff` / `DESIGN §7.9` > 配合 `DESIGN.md`。本文件只记 phase 状态、决策偏差、文件量、下一步。每条 1-2 句:做了啥 + 关键判断;细节查 `git log` / `git diff` / `DESIGN §7.9`
最后更新:2026-08-11(外部系统弹框动态字段与滚动隔离修复,bump 0.63.6) 最后更新:2026-08-11(外部系统已有连接直接重连修复,bump 0.63.7)
--- ---
@ -23,6 +23,8 @@
### 2026-08-11 ### 2026-08-11
- **08-11 / 0.63.7 / 外部系统已有连接直接重连**:用户凭据表单按所选 definition 识别已有连接,自动切换为“重新连接并验证”并调用现有凭据更新接口,验证成功后保存新凭据和 active 状态不再先按新连接提交后收到重复连接提示卡片上的显式“更新凭据”入口保持不变。Web 无 DB 路由与静态资源共 35 项 unittest、JavaScript 语法及 diff 检查通过;无 schema、migration、HTTP API、依赖或运行方式变化未连接生产 DB。
- **08-11 / 0.63.6 / 外部系统弹框动态字段 + 滚动隔离修复**:修复表单 label 样式覆盖 HTML `hidden` 语义OpenAPI/MCP connector、认证方式和接口执行模式切换后只显示适用配置项弹框改为独立可收缩滚动区并在打开期间锁定根页面滚动滚动到边界不再带动后台页面。Node 前端 19 项、Web 公共逻辑 unittest 3 项、JavaScript 语法及 diff 检查通过;无 schema、migration、HTTP API、依赖或运行方式变化未连接生产 DB。 - **08-11 / 0.63.6 / 外部系统弹框动态字段 + 滚动隔离修复**:修复表单 label 样式覆盖 HTML `hidden` 语义OpenAPI/MCP connector、认证方式和接口执行模式切换后只显示适用配置项弹框改为独立可收缩滚动区并在打开期间锁定根页面滚动滚动到边界不再带动后台页面。Node 前端 19 项、Web 公共逻辑 unittest 3 项、JavaScript 语法及 diff 检查通过;无 schema、migration、HTTP API、依赖或运行方式变化未连接生产 DB。
- **08-11 / 0.63.5 / 外部系统配置弹框 + 动态字段**:管理后台外部系统定义由页面平铺表单改为新增/编辑弹框,按 OpenAPI/MCP connector 和认证方式只展示、提交当前适用字段MCP URL 自动提供认证同源基址,新建时不再重复要求 Base URL编辑存量定义继续保留既有基址列表能力模式对 MCP 改为动态 `tools/list`。Web 无 DB 路由 23 项、JavaScript 语法、动态 DOM 引用及 diff 检查通过;当前运行时未发现可连接浏览器,真实点击冒烟待浏览器配置恢复后补验。无 schema、migration、HTTP API、依赖或运行方式变化未连接生产 DB。 - **08-11 / 0.63.5 / 外部系统配置弹框 + 动态字段**:管理后台外部系统定义由页面平铺表单改为新增/编辑弹框,按 OpenAPI/MCP connector 和认证方式只展示、提交当前适用字段MCP URL 自动提供认证同源基址,新建时不再重复要求 Base URL编辑存量定义继续保留既有基址列表能力模式对 MCP 改为动态 `tools/list`。Web 无 DB 路由 23 项、JavaScript 语法、动态 DOM 引用及 diff 检查通过;当前运行时未发现可连接浏览器,真实点击冒烟待浏览器配置恢复后补验。无 schema、migration、HTTP API、依赖或运行方式变化未连接生产 DB。

View File

@ -1,3 +1,3 @@
# zcbot 版本号单一事实源:web/app.py 的 FastAPI version、/healthz 返回、前端展示都引这里。 # zcbot 版本号单一事实源:web/app.py 的 FastAPI version、/healthz 返回、前端展示都引这里。
# 改版本只动这一行。 # 改版本只动这一行。
__version__ = "0.63.6" __version__ = "0.63.7"

View File

@ -22,6 +22,16 @@ function renderCredentialFields(fields = []) {
`).join(""); `).join("");
} }
function connectionForDefinition(definitionId) {
return Array.from(systemsById.values())
.find(item => item.definition_id === definitionId);
}
function submitButtonLabel() {
if (!editingId) return "连接并验证";
return $("ext-definition").disabled ? "验证并更新" : "重新连接并验证";
}
function resetForm() { function resetForm() {
editingId = ""; editingId = "";
$("ext-form-title").textContent = "连接外部系统"; $("ext-form-title").textContent = "连接外部系统";
@ -31,8 +41,18 @@ function resetForm() {
$("ext-save").textContent = "连接并验证"; $("ext-save").textContent = "连接并验证";
$("ext-form-cancel").hidden = true; $("ext-form-cancel").hidden = true;
const selected = selectedDefinition() || definitions[0]; const selected = selectedDefinition() || definitions[0];
const connection = selected && connectionForDefinition(selected.definition_id);
if (connection) {
editingId = connection.external_system_id;
$("ext-form-title").textContent = `重新连接${connection.system_name || "外部系统"}`;
$("ext-name").value = connection.name;
$("ext-name").disabled = true;
$("ext-save").textContent = "重新连接并验证";
renderCredentialFields(connection.credential_fields || []);
} else {
$("ext-name").value = selected ? selected.name : ""; $("ext-name").value = selected ? selected.name : "";
renderCredentialFields((selected || {}).credential_fields || []); renderCredentialFields((selected || {}).credential_fields || []);
}
} }
export function closeExternalSystemsModal() { export function closeExternalSystemsModal() {
@ -106,10 +126,8 @@ $("external-modal").addEventListener("click", event => {
}); });
$("ext-form-cancel").onclick = resetForm; $("ext-form-cancel").onclick = resetForm;
$("ext-definition").onchange = () => { $("ext-definition").onchange = () => {
if (editingId) return; if ($("ext-definition").disabled) return;
const selected = selectedDefinition(); resetForm();
if (selected) $("ext-name").value = selected.name;
renderCredentialFields((selected || {}).credential_fields || []);
}; };
$("ext-form").addEventListener("submit", async event => { $("ext-form").addEventListener("submit", async event => {
@ -132,7 +150,7 @@ $("ext-form").addEventListener("submit", async event => {
try { try {
if (editingId) { if (editingId) {
await api("PUT", `/v1/external-systems/${editingId}/credentials`, { credentials }); await api("PUT", `/v1/external-systems/${editingId}/credentials`, { credentials });
message("外部系统凭据已更新", "success"); message("外部系统已重新连接,凭据已更新", "success");
} else { } else {
await api("POST", "/v1/external-systems", { definition_id: definitionId, name, credentials }); await api("POST", "/v1/external-systems", { definition_id: definitionId, name, credentials });
message("外部系统已连接;下一轮对话即可使用", "success"); message("外部系统已连接;下一轮对话即可使用", "success");
@ -143,7 +161,7 @@ $("ext-form").addEventListener("submit", async event => {
$("ext-err").textContent = error.message; $("ext-err").textContent = error.message;
} finally { } finally {
button.disabled = !providerReady; button.disabled = !providerReady;
button.textContent = editingId ? "验证并更新" : "连接并验证"; button.textContent = submitButtonLabel();
} }
}); });