Vue项目中使用coze的聊天窗(二)
·
背景:
通过js连接引入的方式,不适用于使用coze开源框架搭建的自有平台。需要使用coze-chat-sdk,但该组件是面向react的。
实现
- 引入sdk
- 把sdk作为一个vue组件。创建一个文件vue文件
<template>
<div>
<div ref="chatContainer" class="coze-chat" style="width: 800px; height: 600px"></div>
<div v-if="error" class="error-message">
{{ error }}
</div>
<div v-if="loading" class="loading-message">
正在初始化聊天组件...
</div>
</div>
</template>
<script setup lang="ts">
import "@coze/chat-sdk/webCss";
import { onMounted, ref, onBeforeUnmount, watch, computed, nextTick } from 'vue';
import ChatSdk from '@coze/chat-sdk/webJs';
const chatContainer = ref<HTMLDivElement | null>(null);
interface UserInfo {
id?: string;
name?: string;
avatar?: string;
}
const props = withDefaults(defineProps<{
botId: string;
token?: string;
authType?: 'token' | 'none';
onRefreshToken?: () => Promise<string> | string;
userInfo?: UserInfo;
mount?: 'inline' | 'float';
width?: number | string;
height?: number | string;
title?: string;
uploadable?: boolean;
layout?: 'pc' | 'h5';
lang?: string;
zIndex?: number;
}>(), {
authType: 'token',
mount: 'inline',
title: 'AI 助手',
uploadable: true,
layout: 'pc',
lang: 'zh-CN',
zIndex: 100,
width: 800,
height: 600,
userInfo: {
id: '123',
name: '张三',
avatar: 'https://example.com/avatar.png'
}
});
const emit = defineEmits<{
(e: 'ready'): void;
(e: 'show'): void;
(e: 'hide'): void;
(e: 'error', err: unknown): void;
}>();
const error = ref<string>('');
const loading = ref<boolean>(false);
let root: any = null;
async function createClient() {
if (typeof window === 'undefined') return;
try {
error.value = '';
loading.value = true;
console.log('开始加载 Coze SDK...');
// 导入 CSS 样式
await import('@coze/chat-sdk/webCss');
// 动态导入 SDK
// const ChatSdk = await import('@coze/chat-sdk/webJs');
const {ChatFramework} = ChatSdk;
console.log('SDK 加载完成,ChatFramework:', ChatFramework);
if (!ChatFramework) {
throw new Error('未找到 ChatFramework 组件');
}
// 创建 React 根节点
const React = (window as any).React;
const ReactDOM = (window as any).ReactDOM;
if (!React || !ReactDOM) {
throw new Error('React 运行时未正确加载');
}
// 创建配置
const config = {
chat: {
type: 'bot',
appId: props.botId,
isIframe: false,
},
auth: {
token: props.token,
onRefreshToken: props.onRefreshToken
},
setting: {
apiBaseUrl: 'https://api.coze.cn',
language: props.lang
},
ui: {
layout: props.layout,
header: {
isNeed: true,
title: props.title
},
input: {
isNeed: true,
placeholder: '请输入您的问题...'
}
},
userInfo: props.userInfo
};
console.log('使用配置:', config);
// 创建 React 根节点并渲染
root = ReactDOM.createRoot(chatContainer.value!);
root.render(React.createElement(ChatFramework, config));
console.log('Chat Framework 渲染完成');
emit('ready');
} catch (err: any) {
const errorMsg = err?.message || '初始化失败';
error.value = errorMsg;
emit('error', err);
console.error('Coze Chat 初始化失败:', err);
} finally {
loading.value = false;
}
}
function destroyClient() {
try {
if (root) {
root.unmount();
root = null;
console.log('客户端已销毁');
}
} catch (e) {
console.warn('销毁客户端时出错:', e);
}
}
onMounted(async () => {
await nextTick();
await createClient();
});
onBeforeUnmount(() => {
destroyClient();
});
// 监听关键参数变化
watch(
() => [props.botId, props.mount, props.layout, props.lang] as const,
async () => {
destroyClient();
await nextTick();
await createClient();
}
);
// 监听 token 变化
watch(
() => props.token,
async (nv, ov) => {
if (nv === ov) return;
console.log('Token 更新,重建客户端');
destroyClient();
await createClient();
}
);
// 暴露方法
defineExpose({
show: () => {},
hide: () => {},
destroy: () => destroyClient(),
});
</script>
<style scoped>
.error-message {
color: #f56c6c;
padding: 10px;
border: 1px solid #f56c6c;
border-radius: 4px;
background-color: #fef0f0;
margin: 10px 0;
}
.loading-message {
color: #409eff;
padding: 10px;
text-align: center;
background-color: #f0f9ff;
border-radius: 4px;
margin: 10px 0;
}
</style>
- 环境配置:
4. 为了避免crypto.hash is not a function以及react与sdk版本不兼容的问题,请参考package.json配置{ "name": "coze-chat", "private": true, "version": "0.0.0", "type": "module", "scripts": { "dev": "vite", "build": "vue-tsc -b && vite build", "preview": "vite preview" }, "dependencies": { "@coze/chat-sdk": "^0.1.11-beta.19", "react": "^18.2.0", "react-dom": "^18.2.0", "vue": "^3.5.18" }, "devDependencies": { "@vitejs/plugin-vue": "^6.0.1", "@vue/tsconfig": "^0.7.0", "typescript": "~5.8.3", "vite": "^6.0.0", "vue-tsc": "^3.0.5" } }- 在
main.ts文件中配置sdk运行的react环境
import React from 'react'; import ReactDOM from 'react-dom/client'; // 设置全局 React 变量 (window as any).React = React; (window as any).ReactDOM = ReactDOM; - 在
- 组件使用
<!--扣子聊天窗 -->
<el-dialog
v-model="showKefu"
:width="900"
>
<CozeChat
bot-id="bot_id"
token="bot_token"
title="AI 助手"
:width="900"
:height="640"
layout="pc"
lang="zh-CN"
@ready="onReady"
@show="onShow"
@hide="onHide"
@error="onError"
/>
</el-dialog>
更多推荐
所有评论(0)