# 公开页 · iframe 嵌入外观对接说明(主题 / 背景色) 本文档面向**嵌入方(宿主系统)**,说明如何在用 ` ``` --- ## 3. postMessage(嵌入后动态切换) 适用于宿主站点支持用户切主题、需要 iframe 实时跟随的场景。向 iframe 的 `contentWindow` 发消息即可,**无需等待子页面回执**(监听器在应用挂载时注册)。 ### 3.1 消息格式 ```js const frame = document.getElementById("deerflow-frame"); // 切整体明暗主题(theme 取值同 2.2) frame.contentWindow.postMessage({ type: "deerflow:set-theme", theme: "dark" }, "*"); // 改背景色 / 文字色(字段名与 URL 参数一致,bg/background、text/fg 均可) frame.contentWindow.postMessage({ type: "deerflow:set-bg", bg: "#001529", text: "#fff" }, "*"); // 兼容别名:type 也可写 "deerflow:set-background" ``` 说明: - 两类消息相互独立,可只发其一;`set-bg` 里 `bg`、`text` 也可只传其一,未传的字段保持当前值。 - 非法颜色值 / 不认识的 `theme` 取值会被忽略,不会清空已有设置。 - targetOrigin 建议按需收紧(写 DeerFlow 站点的 origin 而非 `"*"`)。 ### 3.2 宿主主题联动示例 ```js function syncDeerflowTheme(isDark) { const win = document.getElementById("deerflow-frame").contentWindow; win.postMessage({ type: "deerflow:set-theme", theme: isDark ? "dark" : "light" }, "*"); win.postMessage( { type: "deerflow:set-bg", bg: isDark ? "#001529" : "#ffffff" }, "*", ); } // iframe 首次加载用 URL 参数兜底,之后切换走 postMessage myThemeStore.subscribe((theme) => syncDeerflowTheme(theme === "dark")); ``` --- ## 4. 优先级与默认行为 同一项配置多处传入时,按以下优先级取值(高 → 低): 1. **postMessage** 动态设置的值 2. hash 路由内的 URL 参数(`#/路由?theme=...`) 3. `#` 之前的 URL 参数(`?theme=...#/路由`) 4. 都没传 → DeerFlow 默认配色(浅色主题 + 页面自带 Tailwind 配色) 其他保证: - 外部主题只影响**当前 iframe 的渲染**,不写 localStorage——不会污染用户直接访问 DeerFlow 主站时自己选择的主题。 - `bg`/`text` 是内联样式,作用在页面根容器上,优先级高于主题变量;与 `theme` 叠加时以 `bg`/`text` 为准。 --- ## 5. 常见问题排查 | 现象 | 排查 | |------|------| | `theme=dark` 不生效 | 确认路由属于第 1 节列出的公开页;确认参数拼在 hash 路由后(`/#/share/xx?theme=dark`),而不是写成了 `/#/share/xx#theme=dark` | | `bg=#fff` 不生效 | URL 里 `#` 没编码会被浏览器截断,必须写 `%23fff`;或直接省略 `#` 写 `bg=fff` | | postMessage 无反应 | 确认消息体是对象且 `type` 拼写为 `deerflow:set-theme` / `deerflow:set-bg`;确认在 iframe `load` 之后发送 | | 颜色被忽略 | 检查是否符合 2.3 白名单格式(如 `linear-gradient(...)` 等复杂值不支持) | | 主题切了但个别区域颜色没变 | 该区域可能使用了固定配色;把页面路由与截图反馈给 DeerFlow 维护方补充 `dark:` 样式 |