思路
- 任何需要嵌入的页面,就是加载一个js
js
复制代码
const ai = document.createElement('script')
ai.src = process.env.VUE_APP_AI_EMBED_JS_URL + '/embed.js?sid=' + sid + '&token=' + token
ai.async = true
ai.defer = true
ai.id = 'chat-script'
document.body.appendChild(ai);
js
复制代码
<script
async
defer
src="http://11.27.1.241/api/application/embed?protocol=http&host=11.27.1.241&token=f5c93503fc6c292e">
</script>
- embed.js的大体功能:读取url参数->创建浮动按钮->创建iframe容器->iframe.src=vue的聊天页面
js
复制代码
(function () {
if (window.chatWindowEmbedded) return;
window.chatWindowEmbedded = true;
// 解析参数
const script = document.currentScript;
const params = new URLSearchParams(script.src.split('?')[1]);
const sid = params.get('sid') || '';
const token = params.get('token') || '';
// 创建浮动按钮
const floatBtn = document.createElement('div');
floatBtn.innerHTML = '💬 AI';
floatBtn.style.cssText = `
position: fixed;
bottom: 20px;
right: 20px;
background: #4285f4;
color: white;
padding: 12px 20px;
border-radius: 30px;
cursor: pointer;
box-shadow: 0 2px 10px rgba(0,0,0,0.2);
z-index: 9998;
font-family: sans-serif;
font-size: 14px;
`;
floatBtn.id = 'chat-button';
// 创建 iframe 容器
const iframeContainer = document.createElement('div');
iframeContainer.id = 'chat-window-container';
iframeContainer.style.cssText = `
position: fixed;
bottom: 80px;
right: 20px;
width: 400px;
height: 600px;
z-index: 9999;
display: none;
box-shadow: 0 0 20px rgba(0,0,0,0.1);
border-radius: 12px;
overflow: hidden;
background: white;
`;
// 创建 iframe
const iframe = document.createElement('iframe');
iframe.id = 'chat-window-iframe';
iframe.style.cssText = `
width: 100%;
height: 100%;
border: none;
`;
iframeContainer.appendChild(iframe);
// 添加关闭按钮
const closeBtn = document.createElement('div');
closeBtn.innerHTML = '×';
closeBtn.style.cssText = `
position: absolute;
top: 10px;
right: 10px;
width: 24px;
height: 24px;
line-height: 24px;
text-align: center;
cursor: pointer;
font-size: 20px;
color: #888;
z-index: 10000;
background: rgba(255,255,255,0.8);
border-radius: 50%;
`;
iframeContainer.appendChild(closeBtn);
// 添加全屏按钮
const fullscreenBtn = document.createElement('div');
fullscreenBtn.innerHTML = '🔍';
fullscreenBtn.style.cssText = `
position: absolute;
top: 10px;
left: 10px;
width: 24px;
height: 24px;
line-height: 24px;
text-align: center;
cursor: pointer;
font-size: 20px;
color: #888;
z-index: 10000;
background: rgba(255,255,255,0.8);
border-radius: 50%;
`;
iframeContainer.appendChild(fullscreenBtn);
document.body.appendChild(floatBtn);
document.body.appendChild(iframeContainer);
// 获取基础 URL
const baseUrl = script.src.split('/').slice(0, -1).join('/');
// 设置 iframe 的源 URL
iframe.src = `${baseUrl}?sid=${sid}&token=${token}`;
// 添加事件监听器
let isOpen = false;
floatBtn.addEventListener('click', () => {
isOpen = !isOpen;
iframeContainer.style.display = isOpen ? 'block' : 'none';
if (isOpen) {
iframe.contentWindow.postMessage('openChatWindow', '*')
}
});
closeBtn.addEventListener('click', () => {
isOpen = false;
iframeContainer.style.display = 'none';
});
fullscreenBtn.addEventListener('click', () => {
if (iframeContainer.style.width === '50vw' && iframeContainer.style.height === '100vh') {
// 如果已经是全屏状态,恢复原始大小
iframeContainer.style.width = '400px';
iframeContainer.style.height = '600px';
iframeContainer.style.bottom = '80px';
iframeContainer.style.right = '20px';
fullscreenBtn.innerHTML = '🔍'; // 改回放大镜图标
} else {
// 如果不是全屏状态,放大到屏幕的一半
iframeContainer.style.width = '50vw';
iframeContainer.style.height = '100vh';
iframeContainer.style.bottom = '0';
iframeContainer.style.right = '0';
fullscreenBtn.innerHTML = '🔍'; // 改成缩小图标
}
});
// 点击外部关闭
document.addEventListener('click', (e) => {
if (isOpen && !iframeContainer.contains(e.target) && e.target !== floatBtn && !e.target.closest('#chat-window-iframe')) {
isOpen = false;
iframeContainer.style.display = 'none';
}
});
// 添加键盘快捷键(ESC关闭)
document.addEventListener('keydown', (e) => {
if (isOpen && e.key === 'Escape') {
isOpen = false;
iframeContainer.style.display = 'none';
}
});
// 监听来自 iframe 的消息(用于关闭等操作)
window.addEventListener('message', (event) => {
// 确保消息来自可信源
if (event.origin !== new URL(baseUrl).origin) return;
if (event.data === 'closeChatWindow') {
isOpen = false;
iframeContainer.style.display = 'none';
}
});
})();
- 点击悬浮按钮打开聊天页面事件
js
复制代码
let isOpen = false;
floatBtn.addEventListener('click', () => {
isOpen = !isOpen;
iframeContainer.style.display = isOpen ? 'block' : 'none';
if (isOpen) {
iframe.contentWindow.postMessage('openChatWindow', '*')
}
});
- vue聊天项目main.js,单独加载vue文件
js
复制代码
const isEmbedded = window.chatWindowEmbedded && !window.location.hostname.includes('localhost');
if (!isEmbedded) {
createApp(App).use(store).use(router).mount('#app')
} else {
console.log('Running in embedded mode');
import('@/components/ChatWindow.vue').then(module => {
window.ChatWindow = module.default;
});
}
- 相应的vue文件,设置消息监听
js
复制代码
onMounted(() => {
messages.push({
role: 'ai',
content: '您好,我是您的专属AI助手,我可以帮您分析客户相关数据并进行总结,比如"综合报告","征信简报","流水简报"等。',
displayContent: '您好,我是您的专属AI助手,我可以帮您分析客户相关数据并进行总结,比如"综合报告","征信简报","流水简报"等。',
isStreaming: false,
timestamp: new Date()
});
scrollToBottom();
window.addEventListener('message', handleParentMessage);
});