diff --git a/apps/web/index.html b/apps/web/index.html
index 8d9b2cbf..e9d21245 100644
--- a/apps/web/index.html
+++ b/apps/web/index.html
@@ -61,7 +61,7 @@
-
+
diff --git a/apps/web/public/version.json b/apps/web/public/version.json
index 2e1791f6..61098e74 100644
--- a/apps/web/public/version.json
+++ b/apps/web/public/version.json
@@ -1,6 +1,6 @@
{
"version": "0.5.37",
- "buildTime": "2026-01-21T08:48:22.382Z",
+ "buildTime": "2026-01-21T08:48:23.142Z",
"gitCommit": "unknown",
"changelog": []
}
\ No newline at end of file
diff --git a/packages/drawnix/src/components/tool-element/tool.generator.ts b/packages/drawnix/src/components/tool-element/tool.generator.ts
index 96879a95..905b5591 100644
--- a/packages/drawnix/src/components/tool-element/tool.generator.ts
+++ b/packages/drawnix/src/components/tool-element/tool.generator.ts
@@ -15,6 +15,8 @@ import { ToolProviderWrapper } from '../toolbox-drawer/ToolProviderWrapper';
import { ToolTransforms } from '../../plugins/with-tool';
import { toolWindowService } from '../../services/tool-window-service';
import { BUILT_IN_TOOLS } from '../../constants/built-in-tools';
+import { processToolUrl, hasTemplateVariables } from '../../utils/url-template';
+import { geminiSettings } from '../../utils/settings-manager';
/**
* 工具元素渲染生成器
@@ -26,6 +28,7 @@ export class ToolGenerator {
private loadStates = new Map();
private loadTimeouts = new Map();
private canvasClickHandler: ((e: MouseEvent) => void) | null = null;
+ private settingsChangeHandler: (() => void) | null = null;
// 加载超时时间(毫秒)
private static readonly LOAD_TIMEOUT = 10000; // 10 秒
@@ -35,6 +38,40 @@ export class ToolGenerator {
// 监听画布点击事件,恢复所有 iframe 蒙层
this.setupCanvasClickHandler();
+
+ // 监听设置变化,刷新包含模板变量的 iframe
+ this.setupSettingsChangeHandler();
+ }
+
+ /**
+ * 设置设置变化监听器
+ * 当 apiKey 等配置变化时,刷新包含模板变量的 iframe
+ */
+ private setupSettingsChangeHandler(): void {
+ this.settingsChangeHandler = () => {
+ this.refreshTemplateIframes();
+ };
+
+ // 监听设置变化事件
+ window.addEventListener('gemini-settings-changed', this.settingsChangeHandler);
+ }
+
+ /**
+ * 刷新所有包含模板变量的 iframe
+ */
+ private refreshTemplateIframes(): void {
+ this.iframeCache.forEach((iframe, elementId) => {
+ const templateUrl = (iframe as any).__templateUrl;
+ if (templateUrl && hasTemplateVariables(templateUrl)) {
+ // 重新处理模板变量
+ const { url: processedUrl } = processToolUrl(templateUrl);
+ const url = new URL(processedUrl, window.location.origin);
+ url.searchParams.set('toolId', elementId);
+
+ // 更新 iframe src
+ iframe.src = url.toString();
+ }
+ });
}
/**
@@ -526,10 +563,20 @@ export class ToolGenerator {
// 设置超时检测
this.setupLoadTimeout(element.id);
+ // 处理模板变量(如 ${apiKey}),在渲染时动态替换
+ const { url: processedUrl, missingVariables } = processToolUrl(element.url);
+
+ if (missingVariables.length > 0) {
+ console.warn(`[ToolGenerator] URL contains missing variables: ${missingVariables.join(', ')}`);
+ }
+
// 设置 iframe URL,添加 toolId 参数用于通信
- const url = new URL(element.url, window.location.origin);
+ const url = new URL(processedUrl, window.location.origin);
url.searchParams.set('toolId', element.id);
iframe.src = url.toString();
+
+ // 保存原始模板 URL,用于设置变化时重新替换
+ (iframe as any).__templateUrl = element.url;
// 关键修改:默认启用 iframe 的鼠标事件,因为拖动只在标题栏上
// 这样 iframe 内的页面可以正常点击和滚动
@@ -822,6 +869,12 @@ export class ToolGenerator {
document.removeEventListener('click', this.canvasClickHandler);
this.canvasClickHandler = null;
}
+
+ // 移除设置变化监听器
+ if (this.settingsChangeHandler) {
+ window.removeEventListener('gemini-settings-changed', this.settingsChangeHandler);
+ this.settingsChangeHandler = null;
+ }
// 清理所有超时定时器
this.loadTimeouts.forEach((timeoutId) => {
diff --git a/packages/drawnix/src/components/toolbox-drawer/ToolWinBoxManager.tsx b/packages/drawnix/src/components/toolbox-drawer/ToolWinBoxManager.tsx
index b7897de7..0883b7f8 100644
--- a/packages/drawnix/src/components/toolbox-drawer/ToolWinBoxManager.tsx
+++ b/packages/drawnix/src/components/toolbox-drawer/ToolWinBoxManager.tsx
@@ -14,6 +14,7 @@ import { InternalToolComponents } from './InternalToolComponents';
import { useDrawnix } from '../../hooks/use-drawnix';
import { ToolTransforms } from '../../plugins/with-tool';
import { DEFAULT_TOOL_CONFIG } from '../../constants/built-in-tools';
+import { processToolUrl } from '../../utils/url-template';
/**
* 工具弹窗管理器组件
@@ -123,7 +124,7 @@ export const ToolWinBoxManager: React.FC = () => {
) : tool.url ? (