去提问»
提问背景 Question:
哎,内容都是空白了,估计标签没有填对。

零外部依赖的原生详情页重构方案

发布时间:2026-08-18 23:09 👁️ 阅读:0

为了彻底解决由于外部 CDN 被拦截(ERR_BLOCKED_BY_CLIENT)、样式加载失败、以及折叠按钮不明显、收起时滚动跳动等痛点,我们对详情页进行了完整重构。

本方案采用纯原生 HTML、CSS(自定义变量与现代 Flexbox/Grid 布局)和 JavaScript 编写,不引入任何外部 CSS/JS 库,保证加载速度与本地离线可用性,同时完美匹配您主页的高端极简视觉风格。

完整重构代码

您可以直接复制并保存为 .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>
    <style>
        /* 基础重置 & 自定义变量 */
        :root {
            --primary: #4f46e5;
            --primary-hover: #4338ca;
            --primary-light: #e0e7ff;
            --slate-50: #f8fafc;
            --slate-100: #f1f5f9;
            --slate-200: #e2e8f0;
            --slate-600: #475569;
            --slate-700: #334155;
            --slate-900: #0f172a;
        }

        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }

        body {
            background-color: var(--slate-50);
            color: var(--slate-900);
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
            line-height: 1.6;
            -webkit-font-smoothing: antialiased;
            padding-bottom: 3rem;
        }

        /* 毛玻璃顶部导航栏 */
        .header {
            position: sticky;
            top: 0;
            z-index: 50;
            background: rgba(255, 255, 255, 0.8);
            backdrop-filter: blur(12px);
            -webkit-backdrop-filter: blur(12px);
            border-bottom: 1px solid rgba(226, 232, 240, 0.8);
        }

        .header-container {
            max-width: 1000px;
            margin: 0 auto;
            padding: 0 1rem;
            height: 4rem;
            display: flex;
            align-items: center;
            justify-content: space-between;
        }

        .logo {
            display: flex;
            align-items: center;
            gap: 0.5rem;
            text-decoration: none;
        }

        .logo-icon {
            font-size: 1.5rem;
        }

        .logo-text {
            font-weight: 800;
            font-size: 1.125rem;
            background: linear-gradient(to right, #4f46e5, #7c3aed);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }

        /* 主体布局 */
        .main-container {
            max-width: 1000px;
            margin: 1.5rem auto 0;
            padding: 0 1rem;
        }

        /* 提问背景卡片 */
        .question-card {
            background: #ffffff;
            border: 1px solid var(--slate-200);
            border-radius: 1rem;
            padding: 1.5rem;
            box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
            position: relative;
            margin-bottom: 1.5rem;
        }

        .question-header {
            display: flex;
            align-items: center;
            gap: 0.5rem;
            font-size: 0.75rem;
            font-weight: 700;
            color: var(--primary);
            text-transform: uppercase;
            letter-spacing: 0.05em;
            margin-bottom: 0.75rem;
        }

        /* 折叠核心区域 */
        .msg-wrapper {
            position: relative;
            overflow: hidden;
        }

        .msg-content {
            font-size: 0.95rem;
            color: var(--slate-700);
            white-space: pre-wrap;
            word-break: break-all;
            max-height: none; /* 由 JS 动态控制 */
            transition: max-height 0.4s cubic-bezier(0.4, 0, 0.2, 1);
        }

        /* 未展开时的底部半透明遮罩 */
        .msg-wrapper.collapsed::after {
            content: "";
            position: absolute;
            bottom: 0;
            left: 0;
            right: 0;
            height: 60px;
            background: linear-gradient(to top, rgba(255,255,255,1), rgba(255,255,255,0));
            pointer-events: none;
        }

        /* 按钮容器:居中定位 */
        .btn-container {
            display: flex;
            justify-content: center;
            margin-top: 1rem;
        }

        /* 折叠/收起按钮优雅设计 */
        .toggle-btn {
            display: none; /* 默认隐藏,由 JS 根据内容高度判断是否显示 */
            align-items: center;
            gap: 0.35rem;
            padding: 0.5rem 1.25rem;
            font-size: 0.85rem;
            font-weight: 600;
            color: var(--primary);
            background-color: var(--primary-light);
            border: none;
            border-radius: 9999px;
            cursor: pointer;
            transition: all 0.2s ease;
        }

        .toggle-btn:hover {
            background-color: #d2d9ff;
            transform: translateY(-1px);
        }

        .toggle-btn svg {
            width: 16px;
            height: 16px;
            transition: transform 0.3s ease;
        }

        .toggle-btn.active svg {
            transform: rotate(180deg); /* 展开状态下图标翻转 */
        }
    </style>
</head>
<body>

    <!-- 导航栏 -->
    <header class="header">
        <div class="header-container">
            <a href="#" class="logo">
                <span class="logo-icon">🧠</span>
                <span class="logo-text">AI 智库百科</span>
            </a>
        </div>
    </header>

    <!-- 主体区域 -->
    <main class="main-container">
        
        <!-- 锚点:定位在提问区域顶部,并加少量偏移避免被吸顶导航遮挡 -->
        <div id="question-top" style="scroll-margin-top: 5rem;"></div>

        <!-- 提问卡片 -->
        <div class="question-card">
            <div class="question-header">
                <span>❓ 提问背景 Question:</span>
            </div>

            <!-- 折叠包裹层 -->
            <div id="msg-wrapper" class="msg-wrapper">
                <div id="content-body" class="msg-content">
                    <!-- 这里是您动态绑定的内容 -->
                    【案例演示长文本】
                    大语言模型(LLM)的兴起带来了全新的软件开发范式,即基于 Prompt 的声明式编程。传统的软件模块间通过确定的 API 交互,而 AI Agent 的引入将模块边界推进到了具备“理解、推理、规划、行动”能力的主动智能体级别。这种变革要求我们在底层技术栈设计上做出如下调整:
                    
                    1. 状态管理:从单会话短记忆(Session Memory)升级到基于多模态语义检索的多级长期记忆网络;
                    2. 执行引擎:从传统的顺序指令流,进化为引入 ReAct、Plan-and-Solve 等思想的自适应决策环;
                    3. 工具调用(Function Calling):需要通过高鲁棒性的 Schema 校验、错误自动重试(Self-Reflection)来约束大模型不稳定的输出格式。
                    
                    通过本页面优雅的原生结构,我们将实现最健壮的内容折叠逻辑,保证在大段复杂技术背景下依然能提供极佳的移动端和PC端多端兼容阅读体验。
                </div>
            </div>

            <!-- 居中按钮 -->
            <div class="btn-container">
                <button id="toggle-btn" class="toggle-btn" onclick="toggleContent()">
                    <span>展开全文</span>
                    <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M19 9l-7 7-7-7" />
                    </svg>
                </button>
            </div>
        </div>

    </main>

    <script>
        const LIMIT_HEIGHT = 160; // 设定的折叠高度阈值 (px)
        
        document.addEventListener("DOMContentLoaded", function () {
            const wrapper = document.getElementById("msg-wrapper");
            const body = document.getElementById("content-body");
            const btn = document.getElementById("toggle-btn");

            // 1. 判断实际高度是否超出预设阈值
            if (body.scrollHeight > LIMIT_HEIGHT) {
                // 开启折叠状态
                wrapper.classList.add("collapsed");
                body.style.maxHeight = LIMIT_HEIGHT + "px";
                btn.style.display = "inline-flex"; // 显示按钮
            } else {
                // 高度不足,直接显示全部,隐藏按钮
                wrapper.classList.remove("collapsed");
                body.style.maxHeight = "none";
                btn.style.display = "none";
            }
        });

        function toggleContent() {
            const wrapper = document.getElementById("msg-wrapper");
            const body = document.getElementById("content-body");
            const btn = document.getElementById("toggle-btn");
            const btnText = btn.querySelector("span");
            const anchor = document.getElementById("question-top");

            if (wrapper.classList.contains("collapsed")) {
                // 【执行展开】
                wrapper.classList.remove("collapsed");
                body.style.maxHeight = body.scrollHeight + "px"; // 平滑过渡到实际撑开的高度
                btnText.textContent = "收起全文";
                btn.classList.add("active");
            } else {
                // 【执行收起】
                wrapper.classList.add("collapsed");
                body.style.maxHeight = LIMIT_HEIGHT + "px";
                btnText.textContent = "展开全文";
                btn.classList.remove("active");

                // 核心修复:收起后,平滑回滚至该区域顶部 (通过 id 对应的锚点)
                anchor.scrollIntoView({ behavior: "smooth", block: "start" });
            }
        }
    </script>
</body>
</html>

关键改动解析

  1. 移除对 tailwindcss CDN 的依赖:采用原生自定义变量和标准 CSS 设计,确保页面不产生 net::ERR_BLOCKED_BY_CLIENT 拦截报错,秒级加载。
  2. 智能折叠逻辑:JS 自动在页面加载时(DOMContentLoaded)读取内容的实际高度 body.scrollHeight。如果文本内容低于 160px(几行内的小问题),则自动隐藏展开按钮,防止不必要的交互动作干扰阅读。
  3. 精准且平滑的回弹定位:收起时,通过原生 JavaScript 核心 API:
    anchor.scrollIntoView({ behavior: "smooth", block: "start" });
    
    平滑回滚到顶部。通过在 CSS 中设置 scroll-margin-top: 5rem;,精准避开了吸顶导航栏的遮挡,让“提问背景”标题完美停靠在屏幕最上方,用户体验极佳。