为什么需要 AI 平台聚合页面?

当前主流 AI 平台众多,包括:

  • 阿里通义千问(Qwen)
  • 腾讯元宝(Yuanbao)
  • Moonshot 的 Kimi
  • OpenAI 的 ChatGPT
  • 字节跳动的豆包(Doubao)
  • 百度文心一言
  • DeepSeek、Metaso 等新兴平台

每个平台登录方式、UI 风格、功能特性各不相同。频繁切换不仅低效,还容易造成上下文丢失。因此,构建一个聚合访问门户,集中展示、一键跳转或内嵌访问这些平台,极大提升使用效率。

虽然部分平台出于安全考虑禁止 <iframe> 嵌入(如 Qwen、DeepSeek),但我们仍可通过优雅降级的方式展示提示,并提供直接跳转或代理访问选项。


第一步:准备服务器环境(Ubuntu 22.04 示例)

您的本地或云服务器需安装 Nginx。以下以 Ubuntu 22.04 为例。

# 更新系统
sudo apt update && sudo apt upgrade -y

# 安装 Nginx
sudo apt install nginx -y

# 启动并设置开机自启
sudo systemctl start nginx
sudo systemctl enable nginx

# 检查状态
systemctl status nginx

默认情况下,Nginx 的 Web 根目录为 /var/www/html


第二步:部署聚合页面(index.html)

将您提供的 index.html 文件上传至服务器的 Nginx 根目录:

# 使用 scp(本地上传)或直接在服务器创建
sudo nano /var/www/html/index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AI平台聚合页面(带代理功能)</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <style>
        /* 保持原有的所有CSS样式不变 */
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
        }
        
        body {
            background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
            color: #f0f0f0;
            min-height: 100vh;
            overflow-x: hidden;
        }
        
        .container {
            display: flex;
            flex-direction: column;
            height: 100vh;
            max-width: 100%;
        }
        
        .main-content {
            display: flex;
            flex: 1;
            overflow: hidden;
        }
        
        /* 侧边栏样式 */
        .sidebar {
            width: 280px;
            background-color: rgba(0, 0, 0, 0.4);
            padding: 20px 0;
            overflow-y: auto;
            border-right: 1px solid rgba(255, 255, 255, 0.1);
            transition: all 0.3s ease;
        }
        
        .sidebar-header {
            padding: 0 20px 20px;
            border-bottom: 1px solid rgba(255, 255, 255, 0.1);
        }
        
        .sidebar h2 {
            font-size: 1.3rem;
            margin-bottom: 5px;
        }
        
        .platform-count {
            color: #6a8cff;
            font-size: 0.9rem;
        }
        
        .platform-list {
            list-style: none;
        }
        
        .platform-item {
            padding: 16px 20px;
            border-bottom: 1px solid rgba(255, 255, 255, 0.05);
            cursor: pointer;
            transition: all 0.2s ease;
            display: flex;
            align-items: center;
        }
        
        .platform-item:hover {
            background-color: rgba(106, 140, 255, 0.1);
        }
        
        .platform-item.active {
            background-color: rgba(106, 140, 255, 0.2);
            border-left: 4px solid #6a8cff;
        }
        
        .platform-icon {
            width: 40px;
            height: 40px;
            border-radius: 8px;
            display: flex;
            align-items: center;
            justify-content: center;
            margin-right: 15px;
            font-size: 1.2rem;
        }
        
        .platform-info h3 {
            font-size: 1.1rem;
            margin-bottom: 3px;
        }
        
        .platform-info p {
            font-size: 0.85rem;
            color: #aaa;
        }
        
        /* 内容区域样式 */
        .content-container {
            flex: 1;
            display: flex;
            flex-direction: column;
            overflow: hidden;
            background-color: rgba(0, 0, 0, 0.2);
        }
        
        .content-header {
            padding: 20px 30px;
            background-color: rgba(0, 0, 0, 0.4);
            display: flex;
            align-items: center;
            justify-content: space-between;
            border-bottom: 1px solid rgba(255, 255, 255, 0.1);
        }
        
        .current-platform {
            display: flex;
            align-items: center;
        }
        
        .current-platform h2 {
            font-size: 1.5rem;
        }
        
        .content-controls {
            display: flex;
            gap: 10px;
        }
        
        .control-btn {
            background: rgba(106, 140, 255, 0.3);
            color: white;
            border: 1px solid rgba(106, 140, 255, 0.5);
            padding: 8px 15px;
            border-radius: 6px;
            cursor: pointer;
            transition: all 0.3s ease;
            font-size: 0.9rem;
        }
        
        .control-btn:hover {
            background: rgba(106, 140, 255, 0.5);
        }
        
        /* 嵌入内容区域 */
        .embedded-content {
            flex: 1;
            position: relative;
            background-color: #0d1117;
        }
        
        .embedded-frame {
            width: 100%;
            height: 100%;
            border: none;
        }
        
        .frame-loading {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            background-color: #0d1117;
            z-index: 10;
        }
        
        .loader {
            width: 50px;
            height: 50px;
            border: 5px solid rgba(106, 140, 255, 0.3);
            border-radius: 50%;
            border-top-color: #6a8cff;
            animation: spin 1s ease-in-out infinite;
            margin-bottom: 20px;
        }
        
        @keyframes spin {
            to { transform: rotate(360deg); }
        }
        
        /* 添加按钮样式 */
        .add-section {
            padding: 20px;
            margin-top: auto;
            border-top: 1px solid rgba(255, 255, 255, 0.1);
        }
        
        .add-button {
            background: rgba(46, 204, 113, 0.8);
            color: white;
            border: none;
            padding: 12px 20px;
            font-size: 1rem;
            border-radius: 8px;
            cursor: pointer;
            transition: background 0.3s ease;
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
            display: flex;
            align-items: center;
            justify-content: center;
            width: 100%;
        }
        
        .add-button:hover {
            background: rgba(39, 174, 96, 1);
            transform: translateY(-2px);
            box-shadow: 0 6px 15px rgba(0, 0, 0, 0.15);
        }
        
        .add-button i {
            margin-right: 8px;
        }
        
        /* 错误信息样式 */
        .error-message {
            text-align: center;
            padding: 40px 20px;
            background: rgba(231, 76, 60, 0.1);
            border-radius: 8px;
            margin: 20px;
            border-left: 4px solid #e74c3c;
        }
        
        .error-message i {
            font-size: 3rem;
            color: #e74c3c;
            margin-bottom: 20px;
        }
        
        .error-message h3 {
            font-size: 1.5rem;
            margin-bottom: 15px;
            color: #e74c3c;
        }
        
        .error-message p {
            color: #ccc;
            margin-bottom: 20px;
            line-height: 1.6;
        }
        
        .solution-buttons {
            display: flex;
            justify-content: center;
            gap: 10px;
            flex-wrap: wrap;
        }
        
        .solution-btn {
            background: rgba(52, 152, 219, 0.8);
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 6px;
            cursor: pointer;
            transition: background 0.3s ease;
            font-size: 0.9rem;
        }
        
        .solution-btn:hover {
            background: rgba(52, 152, 219, 1);
        }
        
        /* 下拉选择器 - 移动端 */
        .platform-selector {
            display: none;
            margin: 20px 30px 0;
            position: relative;
        }
        
        .platform-selector select {
            width: 100%;
            padding: 12px 20px;
            background-color: rgba(0, 0, 0, 0.5);
            border: 1px solid rgba(106, 140, 255, 0.5);
            border-radius: 8px;
            color: white;
            font-size: 1rem;
            appearance: none;
            cursor: pointer;
        }
        
        .selector-icon {
            position: absolute;
            right: 15px;
            top: 50%;
            transform: translateY(-50%);
            pointer-events: none;
            color: #6a8cff;
        }
        
        /* 响应式设计 */
        @media (max-width: 1024px) {
            .sidebar {
                width: 240px;
            }
        }
        
        @media (max-width: 768px) {
            .main-content {
                flex-direction: column;
            }
            
            .sidebar {
                width: 100%;
                max-height: 200px;
                padding: 10px 0;
            }
            
            .platform-selector {
                display: block;
            }
            
            .sidebar-header {
                padding: 10px 20px;
            }
            
            .platform-list {
                display: none;
            }
            
            .content-header {
                padding: 15px 20px;
            }
            
            .solution-buttons {
                flex-direction: column;
            }
        }
        
        .footer {
            padding: 15px;
            text-align: center;
            font-size: 0.85rem;
            color: #888;
            border-top: 1px solid rgba(255, 255, 255, 0.1);
            background-color: rgba(0, 0, 0, 0.3);
        }
        
        .footer a {
            color: #6a8cff;
            text-decoration: none;
        }
        
        .footer a:hover {
            text-decoration: underline;
        }
        
        /* 滚动条样式 */
        ::-webkit-scrollbar {
            width: 8px;
        }
        
        ::-webkit-scrollbar-track {
            background: rgba(255, 255, 255, 0.05);
        }
        
        ::-webkit-scrollbar-thumb {
            background: rgba(106, 140, 255, 0.5);
            border-radius: 4px;
        }
        
        ::-webkit-scrollbar-thumb:hover {
            background: rgba(106, 140, 255, 0.7);
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="platform-selector">
            <select id="mobilePlatformSelect">
                <option value="0">Qwen Chat (阿里)</option>
                <option value="1">腾讯元宝</option>
                <option value="2">DeepSeek</option>
                <option value="3">Kimi (月之暗面)</option>
                <option value="4">ChatGPT (OpenAI)</option>
                <option value="5">豆包 (字节跳动)</option>
                <option value="6">文心一言 (百度)</option>
                <option value="7">Metaso</option>
                <option value="8">Cursor Agents</option>
                <option value="9">N.cn</option>
            </select>
            <div class="selector-icon"><i class="fas fa-chevron-down"></i></div>
        </div>
        
        <div class="main-content">
            <div class="sidebar">
                <div class="sidebar-header">
                    <h2>AI平台列表</h2>
                    <p class="platform-count">10个平台可供选择</p>
                </div>
                <ul class="platform-list" id="platformList">
                    <!-- 平台列表将通过JavaScript动态生成 -->
                </ul>
                <div class="add-section">
                    <button class="add-button" id="addButton">
                        <i class="fas fa-plus"></i> 添加新平台
                    </button>
                </div>
            </div>
            
            <div class="content-container">
                <div class="content-header">
                    <div class="current-platform">
                        <h2 id="currentPlatformName">Qwen Chat</h2>
                    </div>
                    <div class="content-controls">
                        <button class="control-btn" id="refreshBtn">
                            <i class="fas fa-redo"></i> 刷新
                        </button>
                        <button class="control-btn" id="openNewBtn">
                            <i class="fas fa-external-link-alt"></i> 新窗口打开
                        </button>
                        <button class="control-btn" id="useProxyBtn">
                            <i class="fas fa-server"></i> 使用代理
                        </button>
                    </div>
                </div>
                
                <div class="embedded-content">
                    <!-- 默认显示错误信息 -->
                    <div class="frame-loading" id="errorIndicator">
                        <div class="error-message">
                            <i class="fas fa-exclamation-triangle"></i>
                            <h3>连接被拒绝</h3>
                            <p>chat.qwen.ai 拒绝了我们的连接请求。这是因为该网站设置了安全策略,禁止在iframe中嵌入。</p>
                            <p><strong>解决方案:</strong></p>
                            <div class="solution-buttons">
                                <button class="solution-btn" id="directOpenBtn">
                                    <i class="fas fa-external-link-alt"></i> 直接打开网站
                                </button>
                                <button class="solution-btn" id="proxyOpenBtn">
                                    <i class="fas fa-server"></i> 通过代理访问
                                </button>
                                <button class="solution-btn" id="otherPlatformBtn">
                                    <i class="fas fa-random"></i> 切换到其他平台
                                </button>
                            </div>
                        </div>
                    </div>
                    
                    <iframe 
                        class="embedded-frame" 
                        id="embeddedFrame"
                        style="display: none;"
                        allow="clipboard-read; clipboard-write"
                        allowfullscreen>
                    </iframe>
                </div>
            </div>
        </div>
        
        <div class="footer">
            <p>聚合页面仅供学习交流使用,所有AI平台版权归各自公司所有 | 
                <a href="https://github.com" target="_blank">项目源代码</a> | 
                注意:某些平台因安全策略无法在iframe中嵌入
            </p>
        </div>
    </div>

    <script>
        // 平台数据
        const platforms = [
            {
                name: "Qwen Chat",
                url: "https://chat.qwen.ai/",
                description: "通义千问AI助手,提供深度思考、图像编辑、网页开发等多种功能。",
                color: "#ff6b35",
                icon: "fas fa-comment-dots",
                blocked: true // 标记为被阻止的网站
            },
            {
                name: "腾讯元宝",
                url: "https://yuanbao.tencent.com/",
                description: "腾讯云官方平台,提供云计算、人工智能、大数据等服务。",
                color: "#07c160",
                icon: "fab fa-weixin"
            },
            {
                name: "DeepSeek",
                url: "https://chat.deepseek.com/",
                description: "探索未至之境,支持手机号、微信、邮箱登录的AI助手。",
                color: "#6c47ff",
                icon: "fas fa-search",
                blocked: true
            },
            {
                name: "Kimi",
                url: "https://www.kimi.com/chat",
                description: "月之暗面开发的AI助手,支持长思考功能,可生成PPT等内容。",
                color: "#8957e5",
                icon: "fas fa-moon"
            },
            {
                name: "ChatGPT",
                url: "https://chatgpt.com/",
                description: "OpenAI开发的AI助手,当前链接可能无法访问。",
                color: "#10a37f",
                icon: "fas fa-robot",
                error: true
            },
            {
                name: "豆包",
                url: "https://www.doubao.com/chat",
                description: "字节跳动旗下AI智能助手,提供写作、翻译、编程等多种功能。",
                color: "#ff2442",
                icon: "fas fa-seedling"
            },
            {
                name: "文心一言",
                url: "https://wenxin.baidu.com/",
                description: "百度旗下AI助手,提供写作帮手、工作报告、文案润色等功能。",
                color: "#4e6ef2",
                icon: "fas fa-brain"
            },
            {
                name: "Metaso",
                url: "https://metaso.cn/",
                description: "AI智能助手平台,提供多种AI工具和服务。",
                color: "#3a86ff",
                icon: "fas fa-cube",
                blocked: true
            },
            {
                name: "Cursor Agents",
                url: "https://cursor.com/cn/agents",
                description: "AI代码编辑器,提供云代理、快速模型和优先支持等功能。",
                color: "#3a86ff",
                icon: "fas fa-code"
            },
            {
                name: "N.cn",
                url: "https://www.n.cn/",
                description: "AI平台,提供多种人工智能服务和工具。",
                color: "#9b59b6",
                icon: "fas fa-globe"
            }
        ];
        
        // DOM元素
        const platformList = document.getElementById('platformList');
        const embeddedFrame = document.getElementById('embeddedFrame');
        const errorIndicator = document.getElementById('errorIndicator');
        const currentPlatformName = document.getElementById('currentPlatformName');
        const mobilePlatformSelect = document.getElementById('mobilePlatformSelect');
        const addButton = document.getElementById('addButton');
        const refreshBtn = document.getElementById('refreshBtn');
        const openNewBtn = document.getElementById('openNewBtn');
        const useProxyBtn = document.getElementById('useProxyBtn');
        const directOpenBtn = document.getElementById('directOpenBtn');
        const proxyOpenBtn = document.getElementById('proxyOpenBtn');
        const otherPlatformBtn = document.getElementById('otherPlatformBtn');
        
        // 当前选中的平台索引
        let currentPlatformIndex = 0;
        
        // 初始化平台列表
        function initPlatformList() {
            platformList.innerHTML = '';
            
            platforms.forEach((platform, index) => {
                const li = document.createElement('li');
                li.className = `platform-item ${index === currentPlatformIndex ? 'active' : ''}`;
                li.dataset.index = index;
                
                li.innerHTML = `
                    <div class="platform-icon" style="background-color: ${platform.color}40; color: ${platform.color}">
                        <i class="${platform.icon}"></i>
                    </div>
                    <div class="platform-info">
                        <h3>${platform.name}</h3>
                        <p>${platform.description.substring(0, 30)}...</p>
                    </div>
                `;
                
                li.addEventListener('click', () => switchPlatform(index));
                platformList.appendChild(li);
            });
        }
        
        // 切换平台
        function switchPlatform(index) {
            currentPlatformIndex = index;
            const platform = platforms[index];
            
            // 更新活动状态
            document.querySelectorAll('.platform-item').forEach(item => {
                item.classList.remove('active');
            });
            document.querySelector(`.platform-item[data-index="${index}"]`).classList.add('active');
            
            // 更新当前平台名称
            currentPlatformName.textContent = platform.name;
            
            // 更新移动端选择器
            mobilePlatformSelect.value = index;
            
            // 检查是否是被阻止的网站
            if (platform.blocked) {
                showBlockedMessage(platform);
            } else if (platform.error) {
                showErrorMessage(platform);
            } else {
                // 正常加载
                loadPlatform(platform.url);
            }
        }
        
        // 显示被阻止的消息
        function showBlockedMessage(platform) {
            errorIndicator.style.display = 'flex';
            embeddedFrame.style.display = 'none';
            
            const errorMessage = errorIndicator.querySelector('.error-message');
            errorMessage.innerHTML = `
                <i class="fas fa-exclamation-triangle"></i>
                <h3>安全限制</h3>
                <p><strong>${platform.name}</strong> 设置了安全策略,禁止在iframe中嵌入。</p>
                <p>这是网站为了保护用户安全而设置的正常限制,不是你的问题。</p>
                <p><strong>解决方案:</strong></p>
                <div class="solution-buttons">
                    <button class="solution-btn" id="directOpenBtn">
                        <i class="fas fa-external-link-alt"></i> 直接打开${platform.name}
                    </button>
                    <button class="solution-btn" id="otherPlatformBtn">
                        <i class="fas fa-random"></i> 切换到其他平台
                    </button>
                </div>
            `;
            
            // 重新绑定事件
            document.getElementById('directOpenBtn').addEventListener('click', () => {
                window.open(platform.url, '_blank');
            });
            
            document.getElementById('otherPlatformBtn').addEventListener('click', () => {
                // 找到下一个不被阻止的平台
                let nextIndex = (currentPlatformIndex + 1) % platforms.length;
                while (platforms[nextIndex].blocked || platforms[nextIndex].error) {
                    nextIndex = (nextIndex + 1) % platforms.length;
                }
                switchPlatform(nextIndex);
            });
        }
        
        // 显示错误消息
        function showErrorMessage(platform) {
            errorIndicator.style.display = 'flex';
            embeddedFrame.style.display = 'none';
            
            const errorMessage = errorIndicator.querySelector('.error-message');
            errorMessage.innerHTML = `
                <i class="fas fa-exclamation-triangle"></i>
                <h3>访问受限</h3>
                <p><strong>${platform.name}</strong> 当前可能无法访问。</p>
                <p>这可能是由于网络问题、地区限制或网站维护。</p>
                <p><strong>解决方案:</strong></p>
                <div class="solution-buttons">
                    <button class="solution-btn" id="directOpenBtn">
                        <i class="fas fa-external-link-alt"></i> 尝试直接打开
                    </button>
                    <button class="solution-btn" id="otherPlatformBtn">
                        <i class="fas fa-random"></i> 切换到其他平台
                    </button>
                </div>
            `;
            
            // 重新绑定事件
            document.getElementById('directOpenBtn').addEventListener('click', () => {
                window.open(platform.url, '_blank');
            });
            
            document.getElementById('otherPlatformBtn').addEventListener('click', () => {
                // 找到下一个正常的平台
                let nextIndex = (currentPlatformIndex + 1) % platforms.length;
                while (platforms[nextIndex].error) {
                    nextIndex = (nextIndex + 1) % platforms.length;
                }
                switchPlatform(nextIndex);
            });
        }
        
        // 加载平台
        function loadPlatform(url) {
            errorIndicator.style.display = 'none';
            embeddedFrame.style.display = 'block';
            embeddedFrame.src = url;
        }
        
        // 刷新当前页面
        function refreshCurrentPage() {
            const platform = platforms[currentPlatformIndex];
            if (platform.blocked || platform.error) {
                switchPlatform(currentPlatformIndex);
            } else {
                embeddedFrame.src = embeddedFrame.src;
            }
        }
        
        // 在新窗口打开当前页面
        function openInNewWindow() {
            window.open(platforms[currentPlatformIndex].url, '_blank');
        }
        
        // 使用代理(示例)
        function useProxy() {
            const platform = platforms[currentPlatformIndex];
            alert(`代理功能需要后端支持。\n\n对于 ${platform.name},你可以:\n1. 使用浏览器扩展绕过X-Frame限制\n2. 自建代理服务器\n3. 联系网站管理员请求嵌入权限`);
        }
        
        // 添加新平台
        function addNewPlatform() {
            const name = prompt('请输入新平台名称:');
            if (!name) return;
            
            const url = prompt('请输入新平台URL:');
            if (!url) return;
            
            const description = prompt('请输入新平台描述:') || '这是一个新的AI平台';
            
            const newPlatform = {
                name: name,
                url: url,
                description: description,
                color: getRandomColor(),
                icon: "fas fa-plus"
            };
            
            platforms.push(newPlatform);
            
            // 重新初始化平台列表
            initPlatformList();
            
            // 更新平台计数
            document.querySelector('.platform-count').textContent = `${platforms.length}个平台可供选择`;
            
            // 更新移动端选择器
            updateMobileSelector();
            
            // 切换到新平台
            switchPlatform(platforms.length - 1);
            
            alert('新平台已添加成功!');
        }
        
        // 更新移动端选择器
        function updateMobileSelector() {
            mobilePlatformSelect.innerHTML = '';
            
            platforms.forEach((platform, index) => {
                const option = document.createElement('option');
                option.value = index;
                option.textContent = platform.name;
                mobilePlatformSelect.appendChild(option);
            });
        }
        
        // 生成随机颜色
        function getRandomColor() {
            const colors = [
                '#ff6b35', '#07c160', '#6c47ff', '#8957e5', '#10a37f',
                '#ff2442', '#4e6ef2', '#3a86ff', '#9b59b6', '#e74c3c'
            ];
            return colors[Math.floor(Math.random() * colors.length)];
        }
        
        // 移动端选择器事件
        mobilePlatformSelect.addEventListener('change', (e) => {
            switchPlatform(parseInt(e.target.value));
        });
        
        // 按钮事件绑定
        addButton.addEventListener('click', addNewPlatform);
        refreshBtn.addEventListener('click', refreshCurrentPage);
        openNewBtn.addEventListener('click', openInNewWindow);
        useProxyBtn.addEventListener('click', useProxy);
        
        // 初始化
        document.addEventListener('DOMContentLoaded', () => {
            initPlatformList();
            updateMobileSelector();
            switchPlatform(0);
        });
    </script>
</body>
</html>

💡 本文已将 HTML 内容留空,您只需将完整的 index.html 内容粘贴保存即可。

该页面包含以下特性:

  • 响应式侧边栏 + 下拉选择(适配手机)
  • 支持 10+ 主流 AI 平台
  • 自动识别 X-Frame-Options 限制并友好提示
  • 支持“刷新”、“新窗口打开”、“添加自定义平台”等操作
  • 美观的深色主题 + 动画加载效果

第三步:(可选)配置 HTTPS 与域名

为提升安全性与专业性,建议绑定域名并启用 HTTPS(使用 Let’s Encrypt 免费证书)。

# 安装 Certbot
sudo apt install certbot python3-certbot-nginx -y

# 假设你的域名为 ai.yourdomain.com,已解析到服务器 IP
sudo certbot --nginx -d ai.yourdomain.com

Certbot 会自动修改 Nginx 配置,启用 HTTPS 并设置自动续期。


第四步:关于“代理功能”的说明

当前 HTML 中的“使用代理”按钮仅为示意。真正的代理绕过 X-Frame-Options 限制需后端支持,例如:

  • 使用反向代理(Nginx)并移除响应头中的 X-Frame-Options
  • 自建中间服务(如用 Node.js/Python 抓取页面并重写响应)
  • 使用浏览器插件(如“Ignore X-Frame headers”)

⚠️ 注意:绕过安全策略可能违反目标网站的使用条款,请仅用于个人学习或内部合法场景。


效果预览

在这里插入图片描述

(实际部署后,您将看到左侧平台列表 + 右侧嵌入或错误提示区域)

在支持嵌入的平台(如 Kimi、豆包)上可直接使用;在 Qwen、DeepSeek 等平台则会显示友好提示,并提供“直接打开”按钮。


扩展建议

  1. 持久化自定义平台:当前“添加平台”仅保存在内存中,可结合 localStorage 实现本地持久化。
  2. 用户认证:如用于团队,可结合 Nginx 的 auth_basic 实现简单登录。
  3. 统计访问日志:通过 Nginx 日志分析各平台使用频率。
  4. PWA 支持:添加 manifest.json 和 Service Worker,支持离线访问与桌面安装。

完整可直接使用的 Nginx 配置文件

✅ 文件路径:/etc/nginx/sites-available/ai-aggregator

server {
    listen 80;
    server_name ai.yourdomain.com;  # ← 替换为你的实际域名,如 ai.example.com
    root /var/www/html;
    index index.html;

    # 禁用敏感文件访问
    location ~ /\.(env|git|htaccess|ini)$ {
        deny all;
    }

    # 静态资源缓存(可选)
    location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # 所有请求返回 index.html(单页应用友好)
    location / {
        try_files $uri $uri/ /index.html;
    }

    # 安全头(增强防护)
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "no-referrer-when-downgrade" always;
    add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;

    # 可选:开启 gzip 压缩
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
}

🔒 注意:由于大多数 AI 平台(如 Qwen、DeepSeek、ChatGPT)设置了 X-Frame-Options: DENY,即使你在 Nginx 中允许嵌入,浏览器仍会阻止 <iframe> 加载。这是正常的安全机制,无法通过前端绕过。


🔐 启用 HTTPS(使用 Let’s Encrypt)

  1. 先确保域名已解析到服务器 IP。
  2. 安装证书:
sudo certbot --nginx -d ai.yourdomain.com
  1. Certbot 会自动在上述配置中插入 HTTPS 相关块,并设置 301 重定向。

最终会生成类似:

server {
    listen 443 ssl http2;
    server_name ai.yourdomain.com;
    root /var/www/html;
    index index.html;

    ssl_certificate /etc/letsencrypt/live/ai.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ai.yourdomain.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    # ...其余配置同上...
}

server {
    listen 80;
    server_name ai.yourdomain.com;
    return 301 https://$host$request_uri;
}

🚀 部署步骤总结

# 1. 保存配置
sudo nano /etc/nginx/sites-available/ai-aggregator

# 2. 启用站点
sudo ln -s /etc/nginx/sites-available/ai-aggregator /etc/nginx/sites-enabled/

# 3. 测试配置
sudo nginx -t

# 4. 重载 Nginx
sudo systemctl reload nginx

# 5. 放入你的 index.html
sudo cp your-local-index.html /var/www/html/index.html

📌 补充说明

  • 如果你没有域名,可直接用 IP 访问(但无法申请 HTTPS 证书,且部分浏览器对 HTTP iframe 限制更严)。
  • 若用于内网/本地测试,可忽略 HTTPS,仅用 HTTP + localhost 或内网 IP。
  • 页面中“使用代理”功能需额外开发后端代理服务(如用 Python Flask 或 Nginx 反向代理 + 头部重写),目前仅为提示。

需要我提供一个 带基础反向代理绕过 X-Frame 限制的 Nginx 示例(仅限测试环境使用)吗?或者帮你把 index.html 中的 URL 做一次格式清理(去除多余空格)?

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐