前端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);
});
相关推荐
Flittly25 分钟前
【SpringAIAlibaba新手村系列】(11)Embedding 向量化与向量数据库
java·笔记·spring·ai·springboot
ZPC821026 分钟前
如何创建一个单例类 (Singleton)
开发语言·前端·人工智能
紫_龙1 小时前
最新版vue3+TypeScript开发入门到实战教程之重要详解readonly/shallowReadOnly
前端·javascript·typescript
roamingcode2 小时前
前端 AI Agent 多智能体协作架构:从对抗式排查到工作流解耦
前端·人工智能·架构·agent·team
GEO索引未来3 小时前
一文说清2026年GPT 卖货两种方式
人工智能·gpt·ai·chatgpt
蓝莓味的口香糖3 小时前
【vue】初始化 Vue 项目
前端·javascript·vue.js
光影少年4 小时前
数组去重方法
开发语言·前端·javascript
我命由我123454 小时前
浏览器的 JS 模块化支持观察记录
开发语言·前端·javascript·css·html·ecmascript·html5
小哈里4 小时前
【Agent】MCP协议介绍、MCP Server服务端开发与 Skills技能编写
ai·agent·mcp·mcp server·skills
菩提小狗4 小时前
每日极客日报 · 2026年04月03日 · 2026-04-03
ai·开源·极客日报·it热点·技术资讯