/**
* React 组件集成示例
* 如何在 React 项目中集成 GLM-4 语音聊天
*/
// ============ 方式 1: 直接使用 iframe ============
// 最简单的方式,推荐用于快速集成
import React from 'react';
export function VoiceWidgetSimple() {
return (
);
}
// ============ 方式 2: 包装成可控的组件 ============
// 支持配置和事件处理
interface VoiceWidgetProps {
position?: 'fixed' | 'absolute';
bottom?: number;
right?: number;
top?: number;
left?: number;
width?: number;
height?: number;
theme?: 'light' | 'dark';
onLoad?: () => void;
onError?: (error: Error) => void;
}
export function VoiceWidget({
position = 'fixed',
bottom = 20,
right = 20,
width = 450,
height = 600,
onLoad,
onError
}: VoiceWidgetProps) {
const iframeRef = React.useRef(null);
React.useEffect(() => {
const iframe = iframeRef.current;
if (!iframe) return;
// 监听 iframe 加载
const handleLoad = () => {
console.log('Voice widget loaded');
onLoad?.();
};
iframe.addEventListener('load', handleLoad);
return () => iframe.removeEventListener('load', handleLoad);
}, [onLoad]);
return (
);
}
// ============ 方式 3: 侧边栏布局 ============
// 将语音助手放在侧边栏
export function LayoutWithVoiceWidget({ children }: { children: React.ReactNode }) {
return (
);
}
// ============ 方式 4: 模态对话框 ============
// 按钮触发显示/隐藏
export function VoiceWidgetModal() {
const [isOpen, setIsOpen] = React.useState(true);
return (
<>
{isOpen && (
)}
>
);
}
// ============ 方式 5: 自定义 Hook ============
// 更高级的用法
interface UseVoiceWidgetOptions {
autoOpen?: boolean;
position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
}
export function useVoiceWidget(options?: UseVoiceWidgetOptions) {
const [isOpen, setIsOpen] = React.useState(options?.autoOpen ?? true);
const iframeRef = React.useRef(null);
const getPositionStyle = () => {
const base = { zIndex: 999, width: 450, height: 600 };
switch (options?.position) {
case 'bottom-left':
return { ...base, bottom: 20, left: 20 };
case 'top-right':
return { ...base, top: 20, right: 20 };
case 'top-left':
return { ...base, top: 20, left: 20 };
default: // bottom-right
return { ...base, bottom: 20, right: 20 };
}
};
const VoiceComponent = () => (
);
return {
VoiceComponent,
isOpen,
setIsOpen,
iframeRef
};
}
// ============ 方式 6: 完整页面应用 ============
// 使用 iframe 但支持更多交互
export default function App() {
const [apiKey, setApiKey] = React.useState('');
const [isConfigured, setIsConfigured] = React.useState(false);
const handleConfigApiKey = () => {
const key = prompt('请输入你的 GLM-4 API 密钥:');
if (key) {
setApiKey(key);
localStorage.setItem('glm_api_key', key);
setIsConfigured(true);
}
};
return (
{/* 主内容区 */}
欢迎使用 GLM-4 语音聊天
你可以与右侧的 AI 助手进行语音对话。
{!isConfigured && (
⚠️ 首次使用需要配置 API 密钥
)}
{/* 你的网站内容 */}
功能介绍
- 💬 智能对话:支持自然语言理解和生成
- 🎙️ 语音输入:长按按钮说话
- 🔊 语音输出:AI 自动回复语音
- 💾 对话记录:自动保存在浏览器本地
- 🔐 隐私保护:完全在浏览器端处理
{/* 语音助手侧边栏 */}
);
}
// ============ 使用示例 ============
// 最简单的用法
//
// 配置选项
//
// 带侧边栏的布局
//
//
//
// 模态对话框
//
// 使用 Hook
// const { VoiceComponent, isOpen, setIsOpen } = useVoiceWidget({ position: 'bottom-right' });
// return ;
// ============ 常见问题 ============
/**
* Q1: 如何传递 API 密钥给 iframe?
* A: API 密钥保存在 localStorage 中,iframe 会自动读取。
* 也可以在打开网页后点击 ⚙️ 手动输入。
*
* Q2: 如何与 iframe 通信?
* A: 使用 window.postMessage() 和 iframe.contentWindow.postMessage()
*
* Q3: 如何自定义样式?
* A: 修改源文件 /voice/index.html 中的