动态磁贴 RSS订阅 嵌入式代码

HTML/CSS/Javascript 在线代码运行工具:https://www.runoob.com/runcode

动态磁贴 RSS订阅 嵌入式代码 1

<div id="rss-tile-widget-container" class="wp-embed-container my-4">
    <!-- 引入 Tailwind CSS CDN -->
    <script src="https://cdn.tailwindcss.com"></script>
    <style>
        /* 确保中文字体优先 */
        @import url('https://fonts.googleapis.com/css2?family=Inter:[email protected]&display=swap');
        
        /* 定义磁贴的基本样式和交互效果,仅对容器内的元素生效 */
        #rss-tile-widget-container .tile {
            /* Updated for frosted glass effect (磨砂玻璃效果) */
            background-color: rgba(255, 255, 255, 0.6); /* 半透明白色背景 */
            backdrop-filter: blur(10px); 
            -webkit-backdrop-filter: blur(10px); 
            border: 1px solid rgba(255, 255, 255, 0.2); /* 细微边框,增加质感 */
            
            border-radius: 8px;
            box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
            transition: transform 0.2s, box-shadow 0.2s;
            cursor: pointer;
            overflow: hidden; /* 确保内容不溢出 */
            display: flex;
            flex-direction: column;
            font-family: 'Inter', 'Noto Sans SC', sans-serif; /* 确保字体在嵌入环境中生效 */
        }
        #rss-tile-widget-container .tile:hover {
            transform: translateY(-2px);
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
        }
        /* 强制图片占满空间并保持纵横比 */
        #rss-tile-widget-container .tile-img {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }

        /* Specific styles for colored tiles to maintain theme but allow glass effect */
        #rss-tile-widget-container .tile-blue-glass {
            background-color: rgba(0, 120, 212, 0.7); /* msn-blue with opacity */
        }
        #rss-tile-widget-container .tile-red-glass {
            background-color: rgba(216, 59, 1, 0.7); /* msn-red with opacity */
        }
        #rss-tile-widget-container .tile-dark-glass {
            background-color: rgba(55, 65, 81, 0.7); /* gray-700 with opacity */
        }
    </style>
    <script>
        // 重新配置 Tailwind 颜色,以便在嵌入环境中生效
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        'msn-blue': '#0078D4', /* 典型的 Microsoft 蓝 */
                        'msn-green': '#107C10',
                        'msn-red': '#D83B01',
                    }
                }
            }
        }
    </script>

    <!-- 磁贴主布局 -->
    <main class="max-w-7xl mx-auto p-4">
        <!-- 
            使用 CSS Grid 创建磁贴布局
            添加 grid-flow-row-dense (grid-auto-flow: dense) 确保磁贴紧凑排列,不留空隙。
        -->
        <div id="grid-container" class="grid grid-cols-2 md:grid-cols-4 gap-4 auto-rows-[120px] md:auto-rows-[160px] grid-flow-row-dense">
            <!-- 初始加载状态 -->
            <div class="col-span-4 p-8 text-center text-gray-500">
                <p>正在加载少数派和爱范儿资讯...</p>
                <div class="mt-4 w-6 h-6 border-4 border-msn-blue border-t-transparent rounded-full animate-spin mx-auto"></div>
            </div>
        </div>
    </main>

    <script>
        // RSS Feed URL 1 (少数派)
        const SSPAI_FEED_URL = "https://sspai.com/feed";
        const SSPAI_PROXY_URL = `https://api.rss2json.com/v1/api.json?rss_url=${encodeURIComponent(SSPAI_FEED_URL)}`;

        // RSS Feed URL 2 (爱范儿)
        const IFANR_FEED_URL = "https://www.ifanr.com/feed";
        const IFANR_PROXY_URL = `https://api.rss2json.com/v1/api.json?rss_url=${encodeURIComponent(IFANR_FEED_URL)}`;
        
        // 随机图片 API URL
        const RANDOM_IMAGE_URL = 'https://www.dmoe.cc/random.php';
        
        // 预定义的磁贴大小和样式 (共 20 个配置)
        const TILE_CONFIGS = [
            { class: "col-span-2 row-span-2 tile-blue-glass text-white", hasImage: true }, // 1. 2x2 (Primary)
            { class: "col-span-2 row-span-1", hasImage: true }, // 2. 2x1 (Wide)
            { class: "col-span-1 row-span-1 tile-red-glass text-white", hasImage: false }, // 3. 1x1 (Small)
            { class: "col-span-1 row-span-1", hasImage: false }, // 4. 1x1 (Small)
            { class: "col-span-1 row-span-2", hasImage: true }, // 5. 1x2 (Tall)
            { class: "col-span-1 row-span-1", hasImage: false }, // 6. 1x1 (Small)
            { class: "col-span-1 row-span-1", hasImage: false }, // 7. 1x1 (Small)
            { class: "col-span-1 row-span-1", hasImage: false }, // 8. 1x1 (Small)
            { class: "col-span-1 row-span-1", hasImage: true }, // 9. 1x1 (Small)
            { class: "col-span-2 row-span-1 tile-dark-glass text-white", hasImage: true }, // 10. 2x1 (Wide - Dark)
            
            { class: "col-span-2 row-span-1", hasImage: true }, // 11. 2x1
            { class: "col-span-1 row-span-2", hasImage: true }, // 12. 1x2
            { class: "col-span-1 row-span-1 tile-red-glass text-white", hasImage: true }, // 13. 1x1
            { class: "col-span-1 row-span-1", hasImage: false }, // 14. 1x1
            { class: "col-span-1 row-span-1 tile-blue-glass text-white", hasImage: false }, // 15. 1x1
            { class: "col-span-2 row-span-2", hasImage: true }, // 16. 2x2
            { class: "col-span-1 row-span-1", hasImage: false }, // 17. 1x1
            { class: "col-span-1 row-span-1", hasImage: false }, // 18. 1x1
            { class: "col-span-2 row-span-1 tile-dark-glass text-white", hasImage: true }, // 19. 2x1
            { class: "col-span-1 row-span-1", hasImage: false }, // 20. 1x1
        ];

        /**
         * 随机打乱数组顺序
         * @param {Array<any>} array 
         */
        function shuffleArray(array) {
            for (let i = array.length - 1; i > 0; i--) {
                const j = Math.floor(Math.random() * (i + 1));
                [array[i], array[j]] = [array[j], array[i]];
            }
            return array;
        }


        /**
         * 解析 RSS JSON 响应为文章对象数组
         * @param {object} jsonResponse - API 返回的 JSON 对象
         * @param {string} sourceName - 资讯来源名称 (e.g., '少数派', '爱范儿')
         * @returns {Array<{title: string, link: string, summary: string, source: string}>}
         */
        function parseFeed(jsonResponse, sourceName) {
            const items = jsonResponse.items || [];
            const articles = [];

            items.forEach((item) => {
                const title = item.title || '无标题';
                const link = item.link || '#';
                
                // 使用 description 或 content 字段
                const description = item.description || item.content || '无描述';
                
                // 提取纯文本并截断
                const tempDiv = document.createElement('div');
                tempDiv.innerHTML = description; 
                const plainText = tempDiv.textContent.replace(/[\n\r\t]/g, ' ').trim();
                const summary = plainText.substring(0, 150) + (plainText.length > 150 ? '...' : '');

                articles.push({ title, link, summary, source: sourceName });
            });
            return articles;
        }

        /**
         * 动态生成并渲染磁贴
         * @param {Array<{title: string, link: string, summary: string, source: string}>} articles 
         */
        function renderTiles(articles) {
            // 注意:这里我们使用容器ID来确保只查找我们这个嵌入块内的 grid-container
            const container = document.getElementById('rss-tile-widget-container').querySelector('#grid-container');
            if (!container) return;

            // 清空加载状态
            container.innerHTML = ''; 

            articles.forEach((article, index) => {
                const config = TILE_CONFIGS[index];
                
                // 针对不同尺寸的磁贴定制内容结构
                let contentHTML = '';
                const tileContentClasses = (config.class.includes('text-white') ? 'text-white' : 'text-gray-800');
                // 移除 alt 属性中的随机图片占位符,仅使用图片 URL
                const imageTag = config.hasImage ? `<img src="${RANDOM_IMAGE_URL}?v=${Math.random()}" class="tile-img" alt="资讯图片" />` : '';

                // 根据来源设置分类标签和颜色
                let categoryName;
                let categoryClass;
                let primaryTag;

                if (article.source === '少数派') {
                    categoryName = '效率工具';
                    categoryClass = 'text-msn-green';
                    primaryTag = '少数派精选';
                } else {
                    categoryName = '科技快讯';
                    // 使用紫色的 Tailwind 类来区分爱范儿
                    categoryClass = 'text-purple-500'; 
                    primaryTag = '爱范儿速递';
                }

                if (config.class.includes('col-span-2 row-span-2')) {
                    // 2x2 大磁贴 (主标题)
                    contentHTML = `
                        <a href="${article.link}" target="_blank" class="block w-full h-full relative p-4 flex flex-col justify-end">
                            <div class="w-full h-full absolute inset-0">
                                ${imageTag.replace('tile-img', 'tile-img opacity-50')} 
                            </div>
                            <div class="relative z-10">
                                <p class="text-sm font-light mb-1 opacity-80">${primaryTag}</p>
                                <h2 class="text-3xl font-extrabold leading-tight line-clamp-3">${article.title}</h2>
                                <p class="text-sm mt-2 opacity-80 hidden md:block line-clamp-2">${article.summary}</p>
                            </div>
                        </a>
                    `;
                } else if (config.class.includes('row-span-2') && config.hasImage) {
                    // 1x2 窄高磁贴 (图片在上,文字在下)
                    contentHTML = `
                        <a href="${article.link}" target="_blank" class="block w-full h-full flex flex-col">
                            <div class="h-1/2 w-full">
                                ${imageTag}
                            </div>
                            <div class="p-3 flex flex-col justify-start h-1/2 ${tileContentClasses}">
                                <p class="text-sm ${categoryClass} font-semibold mb-1">${categoryName}</p>
                                <h3 class="text-lg font-bold leading-tight line-clamp-3">${article.title}</h3>
                            </div>
                        </a>
                    `;
                } else if (config.class.includes('col-span-2') && config.hasImage) {
                    // 2x1 宽磁贴 (标题和摘要,左侧图片)
                    contentHTML = `
                        <a href="${article.link}" target="_blank" class="block w-full h-full p-4 flex items-center ${tileContentClasses}">
                            <div class="flex-shrink-0 w-24 h-full hidden sm:block mr-4 rounded overflow-hidden">
                                ${imageTag}
                            </div>
                            <div class="flex-grow">
                                <p class="text-sm ${categoryClass} font-semibold mb-1">${categoryName}</p>
                                <h3 class="text-xl font-bold truncate">${article.title}</h3>
                                <p class="text-sm opacity-80 mt-1 hidden sm:block line-clamp-1">${article.summary}</p>
                            </div>
                        </a>
                    `;
                } else {
                    // 1x1 或无图磁贴 (只有标题/摘要)
                    contentHTML = `
                        <a href="${article.link}" target="_blank" class="block w-full h-full p-3 ${tileContentClasses}">
                            <p class="text-xs ${categoryClass} font-semibold mb-1">${article.source}专栏</p>
                            <h3 class="font-semibold line-clamp-3">${article.title}</h3>
                            ${config.class.includes('row-span-2') ? `<p class="text-sm opacity-80 mt-2 line-clamp-4">${article.summary}</p>` : ''}
                        </a>
                    `;
                }

                const tileDiv = document.createElement('div');
                tileDiv.className = `tile ${config.class}`;
                tileDiv.innerHTML = contentHTML;
                
                container.appendChild(tileDiv);
            });
        }

        /**
         * 启动函数:获取 RSS Feed 并渲染
         */
        async function fetchFeed() {
            const widgetContainer = document.getElementById('rss-tile-widget-container');
            const container = widgetContainer ? widgetContainer.querySelector('#grid-container') : null;
            if (container) {
                container.innerHTML = '<div class="col-span-4 p-8 text-center text-gray-500"><p>正在加载少数派和爱范儿资讯...</p><div class="mt-4 w-6 h-6 border-4 border-msn-blue border-t-transparent rounded-full animate-spin mx-auto"></div></div>';
            } else {
                return; // 如果容器不存在,则停止执行
            }

            try {
                // 1. 同时获取两个 RSS Feed
                const [sspaiResponse, ifanrResponse] = await Promise.all([
                    fetch(SSPAI_PROXY_URL),
                    fetch(IFANR_PROXY_URL),
                ]);

                // 2. 检查响应状态 (使用 console.warn 避免在嵌入环境中显示红色错误)
                if (!sspaiResponse.ok) {
                    console.warn(`[WARNING] SSPAI fetch failed with status ${sspaiResponse.status}. Using fallback.`);
                }
                if (!ifanrResponse.ok) {
                    console.warn(`[WARNING] IFANR fetch failed with status ${ifanrResponse.status}. Using fallback.`);
                }
                
                // 3. 解析 JSON
                const sspaiJson = sspaiResponse.ok ? await sspaiResponse.json() : { status: 'error' };
                const ifanrJson = ifanrResponse.ok ? await ifanrResponse.json() : { status: 'error' };
                
                // 4. 解析文章
                const sspaiArticles = sspaiJson.status === 'ok' ? parseFeed(sspaiJson, '少数派') : [];
                const ifanrArticles = ifanrJson.status === 'ok' ? parseFeed(ifanrJson, '爱范儿') : [];

                // 5. 合并、打乱并限制数量
                let allArticles = shuffleArray([...sspaiArticles, ...ifanrArticles]);
                
                if (allArticles.length === 0) {
                     throw new Error('两个 RSS Feed 内容均为空或无法解析。');
                }
                
                // 限制文章数量以匹配磁贴配置
                allArticles = allArticles.slice(0, TILE_CONFIGS.length); 

                // 6. 渲染
                renderTiles(allArticles);
            } catch (error) {
                console.error("Failed to fetch or parse RSS feed:", error);
                
                if (container) {
                    container.innerHTML = 
                        '<div class="col-span-4 p-8 text-center text-red-600 bg-red-100 rounded-lg">' +
                        '<p class="font-bold mb-2">资讯加载失败</p>' +
                        `错误信息: ${error.message}` +
                        '<p class="mt-2 text-sm">请检查 RSS 源是否可用,或代理服务是否正常工作。</p>' +
                        '</div>';
                }
            }
        }

        // 确保在整个嵌入容器加载完成后运行
        document.addEventListener('DOMContentLoaded', fetchFeed);
    </script>
</div>

动态磁贴 RSS订阅 嵌入式代码 2

<div id="rss-tile-widget-container" class="wp-embed-container my-4">
    <!-- 引入 Tailwind CSS CDN -->
    <script src="https://cdn.tailwindcss.com"></script>
    <style>
        /* 确保中文字体优先 */
        @import url('https://fonts.googleapis.com/css2?family=Inter:[email protected]&display=swap');
        
        /* ----------------------------------------------------------- */
        /* 关键:防止样式泄露的隔离和重置,使用 !important 提高优先级 */
        /* ----------------------------------------------------------- */
        /* 强制重置所有子元素的 box-sizing, margin, padding,防止被 WordPress 主题继承 */
        #rss-tile-widget-container * {
            box-sizing: border-box !important;
            margin: 0 !important; 
            padding: 0 !important; 
            line-height: normal !important; 
            text-decoration: none !important; /* 清除链接下划线 */
        }
        /* 确保内部 <main> 元素能够正确居中和间距 */
        #rss-tile-widget-container main {
            padding: 1rem !important; 
            margin-left: auto !important; 
            margin-right: auto !important; 
            max-width: 80rem !important; /* 匹配 max-w-7xl */
        }

        /* ----------------------------------------------------------- */
        /* 定义磁贴的基本样式和交互效果,仅对容器内的元素生效 */
        /* ----------------------------------------------------------- */
        #rss-tile-widget-container .tile {
            /* 默认深色磨砂玻璃背景 (Apple Dark Mode 风格) */
            background-color: rgba(30, 30, 30, 0.8) !important; /* 提高不透明度 */
            backdrop-filter: blur(12px) !important; 
            -webkit-backdrop-filter: blur(12px) !important; 
            border: 1px solid rgba(255, 255, 255, 0.15) !important; /* 增强边框可见性 */
            color: #f3f4f6 !important; /* 默认浅色字体 (text-gray-100) */
            
            border-radius: 10px !important; /* 略微更圆润的边缘 */
            /* 增强阴影,增加深度感 */
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4) !important; 
            transition: transform 0.2s, box-shadow 0.2s !important;
            cursor: pointer !important;
            overflow: hidden !important; 
            display: flex !important;
            flex-direction: column !important;
            font-family: 'Inter', 'Noto Sans SC', sans-serif !important; 
            text-decoration: none !important; 
        }
        #rss-tile-widget-container .tile:hover {
            transform: translateY(-4px) !important; /* 更明显的悬停提升 */
            box-shadow: 0 8px 20px rgba(0, 0, 0, 0.5) !important; /* 更深的悬停阴影 */
        }
        /* 强制图片占满空间并保持纵横比 */
        #rss-tile-widget-container .tile-img {
            width: 100% !important;
            height: 100% !important;
            object-fit: cover !important;
        }

        /* Specific styles for colored tiles to maintain theme but allow glass effect */
        #rss-tile-widget-container .tile-blue-glass {
            background-color: rgba(0, 120, 212, 0.75) !important; 
        }
        #rss-tile-widget-container .tile-red-glass {
            background-color: rgba(216, 59, 1, 0.75) !important; 
        }
        #rss-tile-widget-container .tile-dark-glass {
            background-color: rgba(55, 65, 81, 0.75) !important; 
        }
        /* 确保内部链接的颜色是继承的白色,并且没有下划线 */
        #rss-tile-widget-container a {
            color: inherit !important;
            text-decoration: none !important;
        }
    </style>
    <script>
        // 重新配置 Tailwind 颜色,以便在嵌入环境中生效
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        'msn-blue': '#0078D4', /* 典型的 Microsoft 蓝 */
                        'msn-green': '#107C10',
                        'msn-red': '#D83B01',
                    }
                }
            }
        }
    </script>

    <!-- 磁贴主布局 -->
    <main class="max-w-7xl mx-auto p-4">
        <!-- 
            使用 CSS Grid 创建磁贴布局
            添加 grid-flow-row-dense (grid-auto-flow: dense) 确保磁贴紧凑排列,不留空隙。
        -->
        <div id="grid-container" class="grid grid-cols-2 md:grid-cols-4 gap-4 auto-rows-[120px] md:auto-rows-[160px] grid-flow-row-dense">
            <!-- 初始加载状态 -->
            <div class="col-span-4 p-8 text-center text-gray-400">
                <p>正在加载少数派和爱范儿资讯...</p>
                <div class="mt-4 w-6 h-6 border-4 border-msn-blue border-t-transparent rounded-full animate-spin mx-auto"></div>
            </div>
        </div>
    </main>

    <script>
        // RSS Feed URL 1 (少数派)
        const SSPAI_FEED_URL = "https://sspai.com/feed";
        const SSPAI_PROXY_URL = `https://api.rss2json.com/v1/api.json?rss_url=${encodeURIComponent(SSPAI_FEED_URL)}`;

        // RSS Feed URL 2 (爱范儿)
        const IFANR_FEED_URL = "https://www.ifanr.com/feed";
        const IFANR_PROXY_URL = `https://api.rss2json.com/v1/api.json?rss_url=${encodeURIComponent(IFANR_FEED_URL)}`;
        
        // 随机图片 API URL
        const RANDOM_IMAGE_URL = 'https://www.dmoe.cc/random.php';
        
        // 预定义的磁贴大小和样式 (共 20 个配置)
        const TILE_CONFIGS = [
            { class: "col-span-2 row-span-2 tile-blue-glass", hasImage: true }, // 1. 2x2 (Primary)
            { class: "col-span-2 row-span-1", hasImage: true }, // 2. 2x1 (Wide)
            { class: "col-span-1 row-span-1 tile-red-glass", hasImage: false }, // 3. 1x1 (Small)
            { class: "col-span-1 row-span-1", hasImage: false }, // 4. 1x1 (Small)
            { class: "col-span-1 row-span-2", hasImage: true }, // 5. 1x2 (Tall)
            { class: "col-span-1 row-span-1", hasImage: false }, // 6. 1x1 (Small)
            { class: "col-span-1 row-span-1", hasImage: false }, // 7. 1x1 (Small)
            { class: "col-span-1 row-span-1", hasImage: false }, // 8. 1x1 (Small)
            { class: "col-span-1 row-span-1", hasImage: true }, // 9. 1x1 (Small)
            { class: "col-span-2 row-span-1 tile-dark-glass", hasImage: true }, // 10. 2x1 (Wide - Dark)
            
            { class: "col-span-2 row-span-1", hasImage: true }, // 11. 2x1
            { class: "col-span-1 row-span-2", hasImage: true }, // 12. 1x2
            { class: "col-span-1 row-span-1 tile-red-glass", hasImage: true }, // 13. 1x1
            { class: "col-span-1 row-span-1", hasImage: false }, // 14. 1x1
            { class: "col-span-1 row-span-1 tile-blue-glass", hasImage: false }, // 15. 1x1
            { class: "col-span-2 row-span-2", hasImage: true }, // 16. 2x2
            { class: "col-span-1 row-span-1", hasImage: false }, // 17. 1x1
            { class: "col-span-1 row-span-1", hasImage: false }, // 18. 1x1
            { class: "col-span-2 row-span-1 tile-dark-glass", hasImage: true }, // 19. 2x1
            { class: "col-span-1 row-span-1", hasImage: false }, // 20. 1x1
        ];

        /**
         * 随机打乱数组顺序
         * @param {Array<any>} array 
         */
        function shuffleArray(array) {
            for (let i = array.length - 1; i > 0; i--) {
                const j = Math.floor(Math.random() * (i + 1));
                [array[i], array[j]] = [array[j], array[i]];
            }
            return array;
        }


        /**
         * 解析 RSS JSON 响应为文章对象数组
         * @param {object} jsonResponse - API 返回的 JSON 对象
         * @param {string} sourceName - 资讯来源名称 (e.g., '少数派', '爱范儿')
         * @returns {Array<{title: string, link: string, summary: string, source: string}>}
         */
        function parseFeed(jsonResponse, sourceName) {
            const items = jsonResponse.items || [];
            const articles = [];

            items.forEach((item) => {
                const title = item.title || '无标题';
                const link = item.link || '#';
                
                // 使用 description 或 content 字段
                const description = item.description || item.content || '无描述';
                
                // 提取纯文本并截断
                const tempDiv = document.createElement('div');
                tempDiv.innerHTML = description; 
                const plainText = tempDiv.textContent.replace(/[\n\r\t]/g, ' ').trim();
                const summary = plainText.substring(0, 150) + (plainText.length > 150 ? '...' : '');

                articles.push({ title, link, summary, source: sourceName });
            });
            return articles;
        }

        /**
         * 动态生成并渲染磁贴
         * @param {Array<{title: string, link: string, summary: string, source: string}>} articles 
         */
        function renderTiles(articles) {
            // 注意:这里我们使用容器ID来确保只查找我们这个嵌入块内的 grid-container
            const container = document.getElementById('rss-tile-widget-container').querySelector('#grid-container');
            if (!container) return;

            // 清空加载状态
            container.innerHTML = ''; 

            articles.forEach((article, index) => {
                const config = TILE_CONFIGS[index];
                
                // 针对不同尺寸的磁贴定制内容结构
                let contentHTML = '';
                const imageTag = config.hasImage ? `<img src="${RANDOM_IMAGE_URL}?v=${Math.random()}" class="tile-img" alt="资讯图片" />` : '';

                // 根据来源设置分类标签和颜色
                let categoryName;
                let categoryClass;
                let primaryTag;

                if (article.source === '少数派') {
                    categoryName = '效率工具';
                    categoryClass = 'text-msn-green';
                    primaryTag = '少数派精选';
                } else {
                    categoryName = '科技快讯';
                    // 使用紫色的 Tailwind 类来区分爱范儿
                    categoryClass = 'text-purple-400'; 
                    primaryTag = '爱范儿速递';
                }

                // 所有磁贴现在默认继承浅色字体
                const defaultTextColor = 'text-gray-100'; 

                if (config.class.includes('col-span-2 row-span-2')) {
                    // 2x2 大磁贴 (主标题)
                    // 调整字体大小为 4xl, 摘要为 base
                    contentHTML = `
                        <a href="${article.link}" target="_blank" class="block w-full h-full relative p-4 flex flex-col justify-end ${defaultTextColor}">
                            <div class="w-full h-full absolute inset-0">
                                ${imageTag.replace('tile-img', 'tile-img opacity-50')} 
                            </div>
                            <div class="relative z-10">
                                <p class="text-sm font-light mb-1 opacity-80">
                                    <span class="${categoryClass}">${primaryTag}</span>
                                </p>
                                <h2 class="text-4xl font-extrabold leading-tight line-clamp-3">${article.title}</h2>
                                <p class="text-base mt-2 opacity-80 hidden md:block line-clamp-2">${article.summary}</p>
                            </div>
                        </a>
                    `;
                } else if (config.class.includes('row-span-2') && config.hasImage) {
                    // 1x2 窄高磁贴 (图片在上,文字在下)
                    // 调整字体大小为 xl
                    contentHTML = `
                        <a href="${article.link}" target="_blank" class="block w-full h-full flex flex-col ${defaultTextColor}">
                            <div class="h-1/2 w-full">
                                ${imageTag}
                            </div>
                            <div class="p-3 flex flex-col justify-start h-1/2">
                                <p class="text-sm ${categoryClass} font-semibold mb-1">${categoryName}</p>
                                <h3 class="text-xl font-bold leading-tight line-clamp-3">${article.title}</h3>
                            </div>
                        </a>
                    `;
                } else if (config.class.includes('col-span-2') && config.hasImage) {
                    // 2x1 宽磁贴 (标题和摘要,左侧图片)
                    // 调整字体大小为 2xl, 摘要为 base
                    contentHTML = `
                        <a href="${article.link}" target="_blank" class="block w-full h-full p-4 flex items-center ${defaultTextColor}">
                            <div class="flex-shrink-0 w-24 h-full hidden sm:block mr-4 rounded overflow-hidden">
                                ${imageTag}
                            </div>
                            <div class="flex-grow">
                                <p class="text-sm ${categoryClass} font-semibold mb-1">${categoryName}</p>
                                <h3 class="text-2xl font-bold truncate">${article.title}</h3>
                                <p class="text-base opacity-80 mt-1 hidden sm:block line-clamp-1">${article.summary}</p>
                            </div>
                        </a>
                    `;
                } else {
                    // 1x1 或无图磁贴 (只有标题/摘要)
                    // 调整字体大小为 sm/base
                    contentHTML = `
                        <a href="${article.link}" target="_blank" class="block w-full h-full p-3 ${defaultTextColor}">
                            <p class="text-sm ${categoryClass} font-semibold mb-1">${article.source}专栏</p>
                            <h3 class="font-bold line-clamp-3">${article.title}</h3>
                            ${config.class.includes('row-span-2') ? `<p class="text-base opacity-80 mt-2 line-clamp-4">${article.summary}</p>` : ''}
                        </a>
                    `;
                }

                const tileDiv = document.createElement('div');
                tileDiv.className = `tile ${config.class}`;
                tileDiv.innerHTML = contentHTML;
                
                container.appendChild(tileDiv);
            });
        }

        /**
         * 启动函数:获取 RSS Feed 并渲染
         */
        async function fetchFeed() {
            const widgetContainer = document.getElementById('rss-tile-widget-container');
            const container = widgetContainer ? widgetContainer.querySelector('#grid-container') : null;
            if (container) {
                // 确保加载文字和旋转图标在新的深色背景下可见
                container.innerHTML = '<div class="col-span-4 p-8 text-center text-gray-400"><p>正在加载少数派和爱范儿资讯...</p><div class="mt-4 w-6 h-6 border-4 border-msn-blue border-t-transparent rounded-full animate-spin mx-auto"></div></div>';
            } else {
                return; // 如果容器不存在,则停止执行
            }

            try {
                // 1. 同时获取两个 RSS Feed
                const [sspaiResponse, ifanrResponse] = await Promise.all([
                    fetch(SSPAI_PROXY_URL),
                    fetch(IFANR_PROXY_URL),
                ]);

                // 2. 检查响应状态 (使用 console.warn 避免在嵌入环境中显示红色错误)
                if (!sspaiResponse.ok) {
                    console.warn(`[WARNING] SSPAI fetch failed with status ${sspaiResponse.status}. Using fallback.`);
                }
                if (!ifanrResponse.ok) {
                    console.warn(`[WARNING] IFANR fetch failed with status ${ifanrResponse.status}. Using fallback.`);
                }
                
                // 3. 解析 JSON
                const sspaiJson = sspaiResponse.ok ? await sspaiResponse.json() : { status: 'error' };
                const ifanrJson = ifanrResponse.ok ? await ifanrResponse.json() : { status: 'error' };
                
                // 4. 解析文章
                const sspaiArticles = sspaiJson.status === 'ok' ? parseFeed(sspaiJson, '少数派') : [];
                const ifanrArticles = ifanrJson.status === 'ok' ? parseFeed(ifanrJson, '爱范儿') : [];

                // 5. 合并、打乱并限制数量
                let allArticles = shuffleArray([...sspaiArticles, ...ifanrArticles]);
                
                if (allArticles.length === 0) {
                     throw new Error('两个 RSS Feed 内容均为空或无法解析。');
                }
                
                // 限制文章数量以匹配磁贴配置
                allArticles = allArticles.slice(0, TILE_CONFIGS.length); 

                // 6. 渲染
                renderTiles(allArticles);
            } catch (error) {
                console.error("Failed to fetch or parse RSS feed:", error);
                
                if (container) {
                    container.innerHTML = 
                        '<div class="col-span-4 p-8 text-center text-red-400 bg-red-900/50 rounded-lg">' +
                        '<p class="font-bold mb-2">资讯加载失败</p>' +
                        `错误信息: ${error.message}` +
                        '<p class="mt-2 text-sm">请检查 RSS 源是否可用,或代理服务是否正常工作。</p>' +
                        '</div>';
                }
            }
        }

        // 确保在整个嵌入容器加载完成后运行
        document.addEventListener('DOMContentLoaded', fetchFeed);
    </script>
</div>

留下评论

您的邮箱地址不会被公开。 必填项已用 * 标注