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

# CDN / 脚本标签

> 无需打包工具，即可将 ThunderPhone 语音小部件添加到任何网站

CDN 构建在内部捆绑了 React，因此您可以在静态网站、WordPress、Webflow，或任何可以添加 HTML 的页面上使用该小组件。无需 npm、打包工具或框架。

## CDN URL

<CodeGroup>
  ```html Latest (recommended) theme={null}
  <link rel="stylesheet" href="https://cdn.thunderphone.com/widget/latest/style.css" />
  <script src="https://cdn.thunderphone.com/widget/latest/widget.js"></script>
  ```

  ```html Pinned version theme={null}
  <!-- Each stable release also publishes an immutable /widget/vX.Y.Z/ path
       matching the @thunderphone/widget npm version (v1.1.2 at the time of
       writing). If you pin, you own updating the URL for new releases. -->
  <link rel="stylesheet" href="https://cdn.thunderphone.com/widget/v1.1.2/style.css" />
  <script src="https://cdn.thunderphone.com/widget/v1.1.2/widget.js"></script>
  ```
</CodeGroup>

<Tip>
  `latest` URL 是控制台嵌入代码生成器生成的 URL。它们会缓存 5 分钟，并自动采用新的稳定版本。固定的 `/widget/vX.Y.Z/` 路径不可变且长期缓存——如果您固定版本，请使其与您开发所使用的 `@thunderphone/widget` npm 发布版本保持一致。
</Tip>

***

## 基本用法

```html theme={null}
<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="https://cdn.thunderphone.com/widget/latest/style.css" />
</head>
<body>

  <div id="thunderphone"></div>

  <script src="https://cdn.thunderphone.com/widget/latest/widget.js"></script>
  <script>
    ThunderPhone.mount({
      element: '#thunderphone',
      publishableKey: 'pk_live_your_publishable_key',
    })
  </script>

</body>
</html>
```

该小组件会挂载到目标元素中，并渲染为**视口角落中的固定定位栏**（默认值为 `bottom-right`，由 `position` 选项控制）。挂载元素仅作为 React 根节点——它在页面中的位置不会影响小组件的显示位置。

***

## 挂载选项

`ThunderPhone.mount()` 接受与 React 组件相同的选项，另加 `element` 属性：

| 选项               | 类型                                                             | 必填 | 默认值                                 | 说明                                                              |
| ---------------- | -------------------------------------------------------------- | -- | ----------------------------------- | --------------------------------------------------------------- |
| `element`        | `string \| HTMLElement`                                        | 是  | --                                  | CSS 选择器（例如 `'#thunderphone'`）或 DOM 元素引用。                        |
| `publishableKey` | `string`                                                       | 是  | --                                  | 可发布 API 密钥（`pk_live_...`）。系统会根据该密钥的小组件配置自动解析智能体。                |
| `theme`          | `'light' \| 'dark'`                                            | 否  | `'light'`                           | 配色方案。                                                           |
| `primaryColor`   | `string`                                                       | 否  | `'#000000'`（浅色）/ `'#ffffff'`（深色）    | 用作强调色的 CSS 颜色字符串。                                               |
| `title`          | `string`                                                       | 否  | `'Voice assistant'`                 | 显示在小组件栏中的文本。                                                    |
| `position`       | `'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left'` | 否  | `'bottom-right'`                    | 视口固定位置。                                                         |
| `apiBase`        | `string`                                                       | 否  | `'https://api.thunderphone.com/v1'` | 覆盖 API 基础 URL。                                                  |
| `language`       | `string`                                                       | 否  | --                                  | 每个会话的语言覆盖设置——语言代码或区域设置，例如 `en`、`es` 或 `fr-FR`。未设置时，将应用智能体配置的语言。 |
| `voice`          | `string`                                                       | 否  | --                                  | 每个会话的语音覆盖设置——语音名称，例如 `maria`。未设置时，将应用智能体配置的语音。                  |
| `context`        | `string`                                                       | 否  | --                                  | 传递给智能体的每个会话的事实性页面或网站上下文。服务器端会截断至 12,000 个字符。                    |
| `onConnect`      | `() => void`                                                   | 否  | --                                  | 语音会话连接时调用。                                                      |
| `onDisconnect`   | `() => void`                                                   | 否  | --                                  | 会话结束时调用。                                                        |
| `onError`        | `(error) => void`                                              | 否  | --                                  | 发生错误时调用。错误对象包含 `error`（代码）和 `message` 字段。                       |
| `ringtone`       | `boolean \| string`                                            | 否  | `false`                             | 连接期间播放铃声。`true` 表示使用默认铃声，或使用 URL 字符串指定自定义音频。                    |

***

## 清理

`ThunderPhone.mount()` 会返回一个包含清理方法的小组件实例：

```html theme={null}
<script>
  var widget = ThunderPhone.mount({
    element: '#thunderphone',
    publishableKey: 'pk_live_your_publishable_key',
  })

  // Later, when you want to remove the widget:
  widget.unmount()

  // Or equivalently:
  widget.destroy()
</script>
```

`unmount()` 和 `destroy()` 的作用相同——它们会断开所有活跃的语音会话，并从 DOM 中移除小组件。请根据代码可读性选择使用其中任意一种。

<Note>
  在单页应用中离开当前页面时，或包含元素被移除时，始终清理小组件。这可确保活跃的语音会话被正确断开。
</Note>

***

## 示例

### 使用自定义颜色的深色主题

```html theme={null}
<div id="thunderphone"></div>

<link rel="stylesheet" href="https://cdn.thunderphone.com/widget/latest/style.css" />
<script src="https://cdn.thunderphone.com/widget/latest/widget.js"></script>
<script>
  ThunderPhone.mount({
    element: '#thunderphone',
    publishableKey: 'pk_live_your_publishable_key',
    theme: 'dark',
    primaryColor: '#8b5cf6',
    title: 'Talk to our AI',
  })
</script>
```

### 自定义位置

```html theme={null}
<div id="thunderphone"></div>

<script src="https://cdn.thunderphone.com/widget/latest/widget.js"></script>
<script>
  ThunderPhone.mount({
    element: '#thunderphone',
    publishableKey: 'pk_live_your_publishable_key',
    position: 'bottom-left',
  })
</script>
```

### 使用事件回调

```html theme={null}
<div id="thunderphone"></div>

<link rel="stylesheet" href="https://cdn.thunderphone.com/widget/latest/style.css" />
<script src="https://cdn.thunderphone.com/widget/latest/widget.js"></script>
<script>
  ThunderPhone.mount({
    element: '#thunderphone',
    publishableKey: 'pk_live_your_publishable_key',
    onConnect: function () {
      console.log('Call started')
    },
    onDisconnect: function () {
      console.log('Call ended')
    },
    onError: function (error) {
      console.error('Widget error:', error.error, error.message)
    },
  })
</script>
```

### 使用铃声

```html theme={null}
<div id="thunderphone"></div>

<link rel="stylesheet" href="https://cdn.thunderphone.com/widget/latest/style.css" />
<script src="https://cdn.thunderphone.com/widget/latest/widget.js"></script>
<script>
  ThunderPhone.mount({
    element: '#thunderphone',
    publishableKey: 'pk_live_your_publishable_key',
    ringtone: true, // or a custom URL: 'https://example.com/ringtone.mp3'
  })
</script>
```

### 使用 DOM 元素引用

```html theme={null}
<div id="thunderphone"></div>

<script src="https://cdn.thunderphone.com/widget/latest/widget.js"></script>
<script>
  var container = document.getElementById('thunderphone')

  ThunderPhone.mount({
    element: container,
    publishableKey: 'pk_live_your_publishable_key',
  })
</script>
```

### WordPress / CMS 集成

将以下内容添加到自定义 HTML 区块或主题的页脚中：

```html theme={null}
<link rel="stylesheet" href="https://cdn.thunderphone.com/widget/latest/style.css" />
<script src="https://cdn.thunderphone.com/widget/latest/widget.js"></script>

<div id="thunderphone-widget"></div>
<script>
  ThunderPhone.mount({
    element: '#thunderphone-widget',
    publishableKey: 'pk_live_your_publishable_key',
  })
</script>
```

<Tip>
  `<div>` 可以放在任何位置——它仅作为挂载点。小组件本身会以固定覆盖层的形式呈现在视口角落（由 `position` 选项设置），不会随周围内容流动。
</Tip>

***

## 故障排除

<AccordionGroup>
  <Accordion title="小组件未显示">
    请确保 CSS 和 JS 文件均已加载。检查浏览器控制台中是否存在网络错误。请确认在调用 `ThunderPhone.mount()` 前，目标元素已存在于 DOM 中。
  </Accordion>

  <Accordion title="ThunderPhone 未定义">
    脚本尚未加载。请确保 `widget.js` 的 `<script>` 标签位于挂载调用之前，或者将挂载调用包装在 `DOMContentLoaded` 监听器中。
  </Accordion>

  <Accordion title="不允许的域名错误">
    在 [app.thunderphone.com](https://app.thunderphone.com) 的 **开发者** 设置中，将您的域名添加到允许的域名列表。请注意，始终允许使用 `localhost`。
  </Accordion>
</AccordionGroup>

***

## 后续步骤

<CardGroup cols={2}>
  <Card title="样式" icon="palette" href="/zh/widget/styling">
    使用 CSS 自定义属性自定义小组件外观。
  </Card>

  <Card title="React 组件" icon="react" href="/zh/widget/react">
    使用 React？组件集成更加简单。
  </Card>
</CardGroup>
