> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flashduty.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 嵌入组件（Widget）

> 将状态页的实时状态以状态徽标或事件横幅嵌入你的网站，或通过公开 JSON 接口自行集成

Flashduty 状态页提供**嵌入组件（Widget）**：一段可以直接粘贴到任意网站 HTML 中的代码，把状态页的实时状态展示在你的官网、帮助中心或内部系统里。Widget 以 Web Component 形式运行（`<flashduty-status-widget>`），样式与宿主页面隔离，不会相互影响。

<Warning>
  嵌入组件仅适用于**公开状态页**。内部状态页的「嵌入组件」设置页不可用。
</Warning>

## 两种形态

| 形态               | 说明                            | 适用场景                    |
| ---------------- | ----------------------------- | ----------------------- |
| **状态徽标**（Badge）  | 始终显示当前整体状态，点击跳转到你的状态页         | 页脚、帮助中心等需要常显服务状态的位置     |
| **事件横幅**（Banner） | 仅在发生故障或维护时显示，固定在页面顶部或底部，访客可关闭 | 官网、控制台等需要在故障期间主动告知访客的位置 |

两种形态都支持主题（自动 / 亮色 / 暗色）与语言（中文 / English）配置，徽标额外支持尺寸选择，横幅额外支持位置选择。

***

## 在控制台生成嵌入代码

<Steps>
  <Step title="打开嵌入组件设置">
    进入状态页详情页，选择 **设置 → 嵌入组件**。页面包含 **状态徽标**、**事件横幅**、**API** 三个页签。
  </Step>

  <Step title="配置外观">
    在对应页签下调整主题、语言、尺寸（徽标）或位置（横幅），右侧**实时预览**会同步更新。预览仅用于查看效果，不会修改真实状态页；横幅还可以切换「运行正常 / 服务故障 / 已计划的维护」三种预览场景。
  </Step>

  <Step title="复制嵌入代码">
    点击 **复制代码**，将嵌入代码粘贴到你网站的 HTML 中即可。嵌入代码中的脚本版本与你的状态页部署实际提供的版本保持一致，无需手工维护。
  </Step>
</Steps>

### 嵌入代码示例

<CodeGroup>
  ```html 状态徽标 theme={null}
  <script async src="https://status.example.com/status-page-widget/1.0.1/widget.js" integrity="sha384-UPNiiTsMdVbjrBGP/eTAW+OBpaWrL5bFa4L0IJkxrGelurQ+sELET6of/tdLcrOn" crossorigin="anonymous"></script>

  <flashduty-status-widget
    page="https://status.example.com"
    type="badge"
    theme="auto"
    locale="zh"
    size="medium"
  ></flashduty-status-widget>
  ```

  ```html 事件横幅 theme={null}
  <script async src="https://status.example.com/status-page-widget/1.0.1/widget.js" integrity="sha384-UPNiiTsMdVbjrBGP/eTAW+OBpaWrL5bFa4L0IJkxrGelurQ+sELET6of/tdLcrOn" crossorigin="anonymous"></script>

  <flashduty-status-widget
    page="https://status.example.com"
    type="banner"
    theme="auto"
    locale="zh"
    position="top"
  ></flashduty-status-widget>
  ```
</CodeGroup>

<Note>
  脚本标签带有 `integrity`（SRI 校验）与 `crossorigin="anonymous"` 属性，请整段复制，不要只拷贝 `<flashduty-status-widget>` 标签。示例中的 `https://status.example.com` 请替换为你状态页的实际地址（控制台生成的代码中已是真实地址）。
</Note>

### 属性参考

`<flashduty-status-widget>` 支持以下属性：

| 属性                          | 取值                           | 默认值       | 适用形态 | 说明                                                     |
| --------------------------- | ---------------------------- | --------- | ---- | ------------------------------------------------------ |
| `page`                      | 状态页完整 URL（http/https）        | 无（**必填**） | 两者   | Widget 据此请求 `<page>/api/widget/v1/summary.json` 获取状态数据 |
| `type`                      | `badge` / `banner`           | `badge`   | 两者   | 徽标或横幅形态                                                |
| `theme`                     | `auto` / `light` / `dark`    | `auto`    | 两者   | `auto` 跟随访客系统的深色模式设置                                   |
| `locale`                    | `zh` / `en`                  | 跟随浏览器语言   | 两者   | Widget 文案语言                                            |
| `size`                      | `small` / `medium` / `large` | `medium`  | 仅徽标  | 徽标尺寸                                                   |
| `position`                  | `top` / `bottom`             | `top`     | 仅横幅  | 横幅固定在页面顶部或底部                                           |
| `show-upcoming-maintenance` | `true` / `false`             | `true`    | 仅横幅  | 计划维护是否在开始前 24 小时自动显示                                   |

***

## 行为说明

### 数据刷新

* Widget 默认每 **30 秒**轮询一次状态接口（间隔由接口的 `poll_after_seconds` 字段下发），并带有随机抖动，避免大量访客同时请求
* 请求携带 `If-None-Match`（ETag）条件头；数据未变化时服务端返回 `304`，不重复传输内容
* 页面隐藏（切到后台标签页）时**暂停轮询**，回到前台立即刷新一次
* 请求失败时按指数退避重试（5 秒起步，最长 5 分钟）

### 数据过期（Stale）

接口通过 `max_stale_seconds`（默认 **120 秒**）声明数据保鲜期。超过该时间未能成功校验数据时：

* **徽标**进入「未知状态」，并显示最近一次确认数据的时间
* **横幅**在无有效数据时不显示

### 横幅的显示与关闭

* 横幅按优先级选取展示内容：**进行中的故障** > **进行中的维护** > **24 小时内开始的计划维护**；存在多条事件时，横幅会显示「另有 N 条」
* 访客可点击 × 关闭横幅。关闭状态记忆在**当前浏览器会话**中，按「事件 ID + 最近更新时间」记录——当事件有新进展（状态更新或新增时间线）时，横幅会重新出现
* 设置 `show-upcoming-maintenance="false"` 可关闭计划维护的提前显示

### 状态枚举与颜色

| 状态               | 含义   | 颜色    |
| ---------------- | ---- | ----- |
| `operational`    | 运行正常 | 🟢 绿色 |
| `degraded`       | 性能下降 | 🟡 黄色 |
| `partial_outage` | 部分中断 | 🟠 橙色 |
| `full_outage`    | 完全中断 | 🔴 红色 |
| `maintenance`    | 维护中  | 🔵 蓝色 |

<Note>
  状态页中被设置为**隐藏**的组件不会出现在 Widget 数据中——快照只包含对外可见组件的故障与维护事件。
</Note>

***

## 公开接口 summary.json

如果你不想使用现成的 Web Component，可以直接调用每个公开状态页自带的 JSON 快照接口，自行渲染或集成到你的监控体系中。控制台「嵌入组件 → API」页签展示了该地址。

```
GET {状态页地址}/api/widget/v1/summary.json
```

* **公开访问**：无需鉴权、无需 API Key
* **跨域**：响应携带 `Access-Control-Allow-Origin: *`，浏览器可直接调用；支持 `GET`、`HEAD` 与 `OPTIONS`（预检）
* **缓存**：响应头 `Cache-Control: public, max-age=30, s-maxage=30, stale-while-revalidate=120, stale-if-error=3600`，并返回 `ETag`——携带 `If-None-Match` 且数据未变化时返回 `304`
* **时效**：响应头 `X-Status-Validated-At` 表示快照最近一次从后端成功校验的时间，可据此判断数据是否过期

<Warning>
  该接口面向浏览器端低频轮询设计。**高流量场景下请通过你的服务端代理并缓存响应**，不要让大量客户端直连该地址。
</Warning>

### 响应字段

响应为单个 JSON 对象，`schema_version` 当前固定为 `"1.0"`：

| 字段                         | 类型     | 说明                                                                                               |
| -------------------------- | ------ | ------------------------------------------------------------------------------------------------ |
| `schema_version`           | string | 数据结构版本，当前为 `"1.0"`                                                                               |
| `generated_at`             | string | 快照的数据版本时间（ISO 8601），数据有变化才会更新                                                                    |
| `poll_after_seconds`       | number | 建议的轮询间隔（秒），当前为 `30`                                                                              |
| `max_stale_seconds`        | number | 数据保鲜期（秒），超过未校验成功应视为过期，当前为 `120`                                                                  |
| `page`                     | object | 状态页信息：`name`（名称）、`url`（地址）                                                                       |
| `overall`                  | object | 整体状态：`status` 取 `operational` / `degraded` / `partial_outage` / `full_outage` / `maintenance` 之一 |
| `ongoing_incidents`        | array  | 进行中的故障列表（见下表）                                                                                    |
| `in_progress_maintenances` | array  | 进行中的维护列表（见下表）                                                                                    |
| `scheduled_maintenances`   | array  | 72 小时内开始的计划维护，最多返回 3 条                                                                           |

`ongoing_incidents` 数组元素：

| 字段                    | 类型             | 说明                                                   |
| --------------------- | -------------- | ---------------------------------------------------- |
| `id`                  | string         | 事件 ID                                                |
| `title`               | string         | 事件标题                                                 |
| `phase`               | string         | 生命周期状态：`investigating` / `identified` / `monitoring` |
| `impact`              | string         | 影响程度，取值同状态枚举                                         |
| `started_at`          | string         | 开始时间（ISO 8601）                                       |
| `updated_at`          | string         | 最近更新时间（ISO 8601）                                     |
| `url`                 | string         | 事件在状态页上的详情链接                                         |
| `last_update`         | object \| null | 最近一条时间线更新：`at`（时间）、`message`（内容）                     |
| `affected_components` | array          | 受影响组件：`id`、`name`、`group_name`（可选）、`status`（取状态枚举之一） |

`in_progress_maintenances` 与 `scheduled_maintenances` 数组元素：

| 字段                    | 类型             | 说明                                |
| --------------------- | -------------- | --------------------------------- |
| `id`                  | string         | 事件 ID                             |
| `title`               | string         | 事件标题                              |
| `phase`               | string         | 生命周期状态：`scheduled` / `ongoing`    |
| `starts_at`           | string         | 计划开始时间（ISO 8601）                  |
| `ends_at`             | string \| null | 计划结束时间；手动推进的维护可能没有结束时间，此时为 `null` |
| `updated_at`          | string         | 最近更新时间（ISO 8601）                  |
| `overdue`             | boolean        | 是否已超过计划结束时间仍未完成                   |
| `url`                 | string         | 事件在状态页上的详情链接                      |
| `last_update`         | object \| null | 最近一条时间线更新：`at`、`message`          |
| `affected_components` | array          | 受影响组件，结构同故障                       |

### 响应示例

```json theme={null}
{
  "schema_version": "1.0",
  "generated_at": "2026-08-11T08:00:00Z",
  "poll_after_seconds": 30,
  "max_stale_seconds": 120,
  "page": {
    "name": "Example Status",
    "url": "https://status.example.com"
  },
  "overall": {
    "status": "partial_outage"
  },
  "ongoing_incidents": [
    {
      "id": "1024",
      "title": "API 错误率上升",
      "phase": "investigating",
      "impact": "partial_outage",
      "started_at": "2026-08-11T07:40:00Z",
      "updated_at": "2026-08-11T07:55:00Z",
      "url": "https://status.example.com/incidents/1024",
      "last_update": {
        "at": "2026-08-11T07:55:00Z",
        "message": "我们正在排查错误率上升的问题。"
      },
      "affected_components": [
        {
          "id": "cmp-1",
          "name": "公共 API",
          "group_name": "核心服务",
          "status": "partial_outage"
        }
      ]
    }
  ],
  "in_progress_maintenances": [],
  "scheduled_maintenances": []
}
```

### 错误响应

| 状态码   | 响应体                                       | 说明                           |
| ----- | ----------------------------------------- | ---------------------------- |
| `404` | `{"error": "status_page_not_found"}`      | 状态页不存在、非公开，或部署侧关闭了 Widget 功能 |
| `503` | `{"error": "widget_summary_unavailable"}` | 状态数据暂时不可用，请稍后重试              |

<Tip>
  Widget 功能默认开启，你无需任何配置即可使用。私有化部署环境中，部署管理员可通过 `deploy.widgetEnabled` 开关整体关闭该功能（关闭后接口返回 404）。
</Tip>
