前端JS嵌入AI聊天

思路

  1. 任何需要嵌入的页面,就是加载一个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>
  1. 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';
        }
    });
})();
  1. 点击悬浮按钮打开聊天页面事件
js 复制代码
    let isOpen = false;
    floatBtn.addEventListener('click', () => {
        isOpen = !isOpen;
        iframeContainer.style.display = isOpen ? 'block' : 'none';

        if (isOpen) {
            iframe.contentWindow.postMessage('openChatWindow', '*')
        }
    });
  1. 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;
    });
}
  1. 相应的vue文件,设置消息监听
js 复制代码
onMounted(() => {
  messages.push({
    role: 'ai',
    content: '您好,我是您的专属AI助手,我可以帮您分析客户相关数据并进行总结,比如"综合报告","征信简报","流水简报"等。',
    displayContent: '您好,我是您的专属AI助手,我可以帮您分析客户相关数据并进行总结,比如"综合报告","征信简报","流水简报"等。',
    isStreaming: false,
    timestamp: new Date()
  });
  scrollToBottom();

  window.addEventListener('message', handleParentMessage);
});
相关推荐
qq_406176144 小时前
JS 事件循环(Event Loop)
开发语言·前端·javascript
Codebee4 小时前
ooder A2UI ES6版本正式发布:现代化模块架构,MIT开源许可
前端
Devin_chen4 小时前
4.前端使用Node + MongoDB + Langchain消息管理与聊天历史存储
前端·langchain
前端er小芳4 小时前
前端文件 / 图片核心 API 全解析:File、FileReader、Blob、Base64、URL
前端
twl4 小时前
探索Agent RAG: 一文讲清楚从理论到具体落地
前端
FinClip4 小时前
赢千元好礼!FinClip Chatkit “1小时AI集成挑战赛”,邀你来战!
前端
实习生小黄4 小时前
vue3静态文件打包404解决方案
前端·vue.js·vite
啃火龙果的兔子4 小时前
Capacitor移动框架简介及使用场景
前端
yuanyxh4 小时前
程序设计模版
前端
小满zs4 小时前
Next.js第二十章(MDX)
前端·next.js