deerflow-code/frontend-web/docs/embed-public-pages-theme.md
2026-09-07 18:24:55 +08:00

6.4 KiB
Raw Blame History

公开页 · iframe 嵌入外观对接说明(主题 / 背景色)

本文档面向嵌入方(宿主系统),说明如何在用 <iframe> 嵌入 DeerFlow 公开页时,从外部控制页面的整体明暗主题(light/dark)与背景色 / 文字色,使其与宿主站点的视觉风格保持一致。

前端实现见:src/core/embed/background.ts(参数解析与 postMessage 监听)、src/App.tsx(主题接入 forcedTheme)。


0. 速读

想做什么 怎么做
嵌入时指定深色主题 iframe src 加 ?theme=dark
嵌入时指定背景/文字色 iframe src 加 ?bg=%23001529&text=%23ffffff(# 需编码为 %23)
宿主切主题时同步切换 postMessage({ type: "deerflow:set-theme", theme: "dark" }, "*")
宿主动态改背景色 postMessage({ type: "deerflow:set-bg", bg: "#001529", text: "#fff" }, "*")
什么都不传 页面使用 DeerFlow 自带默认配色,互不影响

1. 适用页面

以下公开页(免登录、只读)均支持本文档的全部参数:

页面 路由
会话分享页 /#/share/{shareCode}
圆桌分享页 /#/roundtable-share/{shareCode}、/#/roundtable-share/{shareCode}/report
用户排行榜 /#/public/leaderboard
定时任务公开页 /#/public/scheduled-tasks/{taskId}(含 /runs/{runId}/fullscreen 全屏页)

注意:站点使用 hash 路由,路径在 # 之后。 嵌入聊天页(/#/embed/chats/*、/#/embed/roundtable)有自己的主题约定,见 embed-iframe-chat.md,不在本文范围内。


2. URL 查询参数(嵌入时一次性指定)

2.1 参数列表

参数 别名 作用 合法值
theme — 切整体明暗主题 见 2.2 取值映射表
bg background 页面根容器背景色 见 2.3 颜色格式
text fg 页面根容器文字色 见 2.3 颜色格式

三个参数相互独立,可任意组合;不传或传非法值时该项忽略、沿用默认。

2.2 theme 取值映射

传入值(不区分大小写) 实际主题
dark、dark-blue、深蓝、深色 深色
light、red、红白、浅色 浅色
其他 / 不传 忽略,沿用站内默认(浅色)

2.3 颜色格式(bg / text)

颜色值经过白名单校验,仅接受以下写法,其余一律丢弃(防注入):

  • hex:#fff、#ffffffcc 等 3/4/6/8 位(# 可省略;URL 里 # 必须编码为 %23)
  • 函数式:rgb() / rgba() / hsl() / hsla(),括号内仅允许数字、逗号、百分号、空格、/
  • 命名色:纯英文字母,如 white、transparent

2.4 参数位置

参数放在 hash 路由之后(推荐)或 # 之前都能识别;两处都传时hash 路由内的优先:

https://<host>/#/public/leaderboard?theme=dark          ← 推荐
https://<host>/?theme=dark#/public/leaderboard          ← 也支持

2.5 示例

<!-- 深色主题 -->
<iframe src="https://<host>/#/public/leaderboard?theme=dark"></iframe>

<!-- 浅色主题 + 自定义背景与文字色(# 编码为 %23) -->
<iframe src="https://<host>/#/share/Ab3xYz?theme=light&bg=%23f5f7fa&text=%23333333"></iframe>

<!-- 主题与背景叠加:整页走深色变量,根背景用宿主品牌色 -->
<iframe src="https://<host>/#/roundtable-share/Ab3xYz?theme=dark&bg=%23001529"></iframe>

3. postMessage(嵌入后动态切换)

适用于宿主站点支持用户切主题、需要 iframe 实时跟随的场景。向 iframe 的 contentWindow 发消息即可,无需等待子页面回执(监听器在应用挂载时注册)。

3.1 消息格式

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 宿主主题联动示例

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: 样式