前端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);
});
相关推荐
ZC跨境爬虫34 分钟前
跟着 MDN 学 HTML day_52:(深入 XPathExpression 接口)
开发语言·前端·javascript·ui·html·音视频
UXbot1 小时前
AI 原型工具零设计基础操作指南与功能解析(2026)
前端·ui·产品经理·原型模式·web app
Jurio.1 小时前
当 AI 不再只是对话:Codex app 的自动化功能
运维·人工智能·ai·自动化·codex
yuzhiboyouye1 小时前
VO一般java后端怎么转换成前端想要的数据
java·前端·状态模式
小脑斧1232 小时前
从范式重构到工程落地:OpenTiny NEXT 引领前端智能化新范式
前端·hermesagent·opentiny next
小江的记录本2 小时前
【AI大模型选型指南】《2026年5月(最新版)国内外主流AI大模型选型指南》(企业版)
前端·人工智能·后端·ai作画·aigc·ai编程·ai写作
幽络源小助理2 小时前
最新轻量美化表白墙系统源码v2.0_带后台版_附搭建教程
前端·开源·源码·php源码
金智维科技官方2 小时前
金智维入选中国信通院《高质量数字化转型技术解决方案集(2025年)》
人工智能·ai·自动化·数字化·智能体
qq_381338502 小时前
前端状态管理新范式:Zustand、Jotai 与 Preact Signals 深度对比
前端·arcgis