热门角色不仅是灵感来源,更是你的效率助手。通过精挑细选的角色提示词,你可以快速生成高质量内容、提升创作灵感,并找到最契合你需求的解决方案。让创作更轻松,让价值更直接!
我们根据不同用户需求,持续更新角色库,让你总能找到合适的灵感入口。
本提示词模板专为网站前端开发设计,能够根据用户需求生成完整的HTML、CSS和JavaScript代码。通过智能分析网站类型、设计风格和功能需求,自动构建响应式布局和交互功能,确保代码的规范性和可维护性。该模板特别适合快速原型开发、教学演示和中小企业官网搭建,支持多种主流设计风格和交互效果,输出代码可直接部署使用或作为进一步开发的基础框架。模板采用模块化设计思路,确保生成代码的结构清晰、语义准确,同时预留充分的定制空间。
## 网站概述 这是一个为MVP展示页定制的、单文件即可运行的前端网站模板,采用简约现代设计风格,支持以下特性: - 产品愿景与核心卖点文案(支持A/B测试文案变体) - 功能列表与路线图(现在 / 下一步 / 未来) - 报名与反馈表单(姓名/邮箱/用途),本地校验与成功反馈 - FAQ常见问题 - 迭代公告(顶部公告条 + 更新日志) - 模块拖拽与顺序自定义(桌面端拖拽、移动端按钮上/下移),顺序本地持久化 - 亮/暗/跟随系统 主题切换,主题偏好本地持久化 - 基础SEO(语义化结构、Meta、Open Graph、Twitter卡片、结构化数据)与分析脚本预留位 - 无外部依赖,拷贝即用,符合现代Web标准 注意:A/B测试与分析仅提供前端支持示例(本地存储 + console日志),用于演示与验证,不包含任何外部请求或第三方脚本引用。 ## HTML代码 ```html <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" /> <title>NovaFlow - 让产品从0到1更快验证 | MVP展示页</title> <meta name="description" content="NovaFlow 帮助团队在一周内完成从原型到可用MVP的迭代闭环。更快验证、更轻交付、更好增长。" /> <meta name="theme-color" content="#0ea5e9" /> <link rel="canonical" href="https://example.com/" /> <!-- Open Graph --> <meta property="og:type" content="website"> <meta property="og:title" content="NovaFlow - 让产品从0到1更快验证"> <meta property="og:description" content="更快验证、更轻交付、更好增长。A/B测试、拖拽布局、报名表单、迭代公告、亮暗主题。"> <meta property="og:url" content="https://example.com/"> <!-- Twitter --> <meta name="twitter:card" content="summary"> <meta name="twitter:title" content="NovaFlow - MVP展示页"> <meta name="twitter:description" content="一页搞定产品验证与增长必备组件。"> <!-- 结构化数据:SoftwareApplication + Organization --> <script type="application/ld+json"> { "@context": "https://schema.org", "@graph": [ { "@type": "Organization", "name": "NovaFlow", "url": "https://example.com", "logo": "https://example.com/logo.png" }, { "@type": "SoftwareApplication", "name": "NovaFlow", "applicationCategory": "BusinessApplication", "operatingSystem": "Web", "description": "帮助团队在一周内完成从原型到MVP的验证闭环:A/B测试、拖拽布局、报名表单、迭代公告、亮暗主题。", "offers": { "@type": "Offer", "price": "0", "priceCurrency": "CNY" } } ] } </script> <!-- Analytics Slot(示例占位,不含外部引用):如需接入第三方分析,将脚本粘贴在此注释下方 --> <!-- 示例(请替换为你的供应商脚本,确保合法合规): <script> // your analytics code </script> --> <style> :root { --bg: #ffffff; --bg-soft: #f7fafc; --text: #0f172a; --muted: #475569; --border: #e2e8f0; --primary: #0ea5e9; --primary-contrast: #ffffff; --accent: #22c55e; --warning: #f59e0b; --card: #ffffff; --shadow: 0 2px 10px rgba(0,0,0,.06); --radius: 14px; --focus: 0 0 0 3px rgba(14,165,233,.35); } [data-theme="dark"] { --bg: #0b0f14; --bg-soft: #0f1720; --text: #e5e7eb; --muted: #9ca3af; --border: #1f2937; --primary: #38bdf8; --primary-contrast: #0b0f14; --accent: #34d399; --warning: #fbbf24; --card: #0f1720; --shadow: 0 4px 16px rgba(0,0,0,.35); --focus: 0 0 0 3px rgba(56,189,248,.35); } * { box-sizing: border-box; } html, body { height: 100%; } body { margin: 0; font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif; color: var(--text); background: radial-gradient(80rem 60rem at 20% -10%, rgba(14,165,233,.08), transparent 40%), radial-gradient(60rem 40rem at 120% 10%, rgba(34,197,94,.07), transparent 40%), var(--bg); line-height: 1.6; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } a { color: var(--primary); text-decoration: none; } a:hover { text-decoration: underline; } img { max-width: 100%; height: auto; } .container { width: 100%; max-width: 1100px; margin: 0 auto; padding: 0 20px; } header.site-header { position: sticky; top: 0; z-index: 50; backdrop-filter: saturate(180%) blur(12px); background: color-mix(in srgb, var(--bg) 85%, transparent); border-bottom: 1px solid var(--border); } .nav { display: flex; align-items: center; justify-content: space-between; height: 64px; } .brand { display: flex; align-items: center; gap: 10px; font-weight: 700; } .brand .logo { width: 28px; height: 28px; border-radius: 8px; background: linear-gradient(135deg, var(--primary), var(--accent)); box-shadow: var(--shadow); } nav ul { list-style: none; display: flex; gap: 18px; margin: 0; padding: 0; } nav a { color: var(--muted); font-weight: 600; } nav a:hover { color: var(--text); } .actions { display: flex; gap: 10px; align-items: center; } .btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; height: 40px; padding: 0 14px; border-radius: 999px; border: 1px solid var(--border); background: var(--card); color: var(--text); box-shadow: var(--shadow); cursor: pointer; font-weight: 600; } .btn:hover { transform: translateY(-1px); } .btn:focus-visible { outline: none; box-shadow: var(--focus); } .btn-primary { background: var(--primary); color: var(--primary-contrast); border-color: transparent; } .btn-ghost { background: transparent; border-color: var(--border); } .btn-icon { width: 40px; padding: 0; } .badge { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 999px; font-size: 12px; border: 1px solid var(--border); background: var(--bg-soft); color: var(--muted); } /* Announcement bar */ .announcement { background: linear-gradient(90deg, color-mix(in srgb, var(--primary) 25%, transparent), transparent); border-bottom: 1px dashed var(--border); color: var(--muted); font-size: 14px; } .announcement .wrap { display: flex; align-items: center; gap: 10px; justify-content: space-between; padding: 8px 0; } .announcement .left { display: flex; align-items: center; gap: 8px; } .announcement .close { all: unset; cursor: pointer; color: var(--muted); padding: 4px 8px; border-radius: 6px; } .announcement .close:hover { background: var(--bg-soft); } /* Modules */ main { padding: 32px 0 80px; } section.module { position: relative; margin: 22px 0; padding: 28px; background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); } section.module h2 { margin: 0 0 14px; font-size: 24px; letter-spacing: .2px; } section.module .sub { margin: 0 0 18px; color: var(--muted); } /* Drag handle + controls */ .module .drag-handle { position: absolute; inset-inline-end: 10px; inset-block-start: 10px; display: none; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); padding: 6px 10px; border-radius: 8px; border: 1px dashed var(--border); background: var(--bg-soft); user-select: none; cursor: grab; } .customizing .module .drag-handle { display: inline-flex; } .module-controls { display: none; gap: 6px; position: absolute; inset-inline-end: 10px; inset-block-start: 48px; } .customizing .module-controls { display: inline-flex; } .module-controls .ctrl { height: 28px; width: 28px; border-radius: 8px; border: 1px solid var(--border); background: var(--card); color: var(--muted); cursor: pointer; } .drag-placeholder { border: 2px dashed var(--primary); background: color-mix(in srgb, var(--primary) 8%, transparent); min-height: 60px; border-radius: var(--radius); margin: 22px 0; } .customizing .module { outline: 2px dashed transparent; transition: outline-color .2s; } .customizing .module:focus-within { outline-color: color-mix(in srgb, var(--primary) 40%, transparent); } /* Hero */ #hero { padding: 36px; display: grid; gap: 18px; } #hero h1 { font-size: 34px; margin: 0; line-height: 1.2; letter-spacing: .2px; } .hero-points { display: grid; gap: 10px; } .hero-points li { list-style: none; display: flex; gap: 10px; align-items: baseline; color: var(--muted); } .ctas { display: flex; gap: 10px; flex-wrap: wrap; padding-top: 6px; } /* Features */ .features-grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: 14px; } .feature-card { grid-column: span 6; border: 1px solid var(--border); border-radius: 14px; padding: 16px; background: var(--bg); } .feature-card h3 { margin: 6px 0 6px; font-size: 18px; } .feature-card p { margin: 0; color: var(--muted); } /* Roadmap */ .roadmap { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; } .road-col { border: 1px solid var(--border); border-radius: 12px; padding: 14px; background: var(--bg); } .road-col h3 { margin: 0 0 8px; font-size: 16px; } .road-col ul { margin: 0; padding-left: 18px; } .tag { display: inline-block; font-size: 12px; padding: 2px 8px; border-radius: 999px; background: var(--bg-soft); border: 1px solid var(--border); color: var(--muted); } /* Form */ form .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; } form .row { display: grid; gap: 6px; } label { font-weight: 600; } input, select, textarea { width: 100%; height: 40px; padding: 8px 10px; border-radius: 10px; border: 1px solid var(--border); background: var(--bg); color: var(--text); } textarea { height: 100px; resize: vertical; } .hint { font-size: 12px; color: var(--muted); } .form-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; } .success { display: none; margin-top: 12px; padding: 10px 12px; border-radius: 12px; background: color-mix(in srgb, var(--accent) 10%, transparent); border: 1px solid color-mix(in srgb, var(--accent) 60%, transparent); color: color-mix(in srgb, var(--accent) 80%, #0b0f14); } .success.show { display: block; } /* FAQ */ details { border: 1px solid var(--border); border-radius: 12px; padding: 10px 14px; background: var(--bg); } details + details { margin-top: 10px; } summary { cursor: pointer; font-weight: 600; } details[open] { box-shadow: var(--shadow); } /* Changelog */ .changelog-list { display: grid; gap: 10px; } .change-item { border: 1px dashed var(--border); border-radius: 12px; padding: 12px; background: var(--bg); } .change-item h3 { margin: 0 0 6px; font-size: 16px; } .meta { color: var(--muted); font-size: 12px; } footer { border-top: 1px solid var(--border); padding: 24px 0; color: var(--muted); font-size: 14px; } footer .row { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; } /* Responsive */ @media (max-width: 900px) { .features-grid .feature-card { grid-column: span 12; } form .grid { grid-template-columns: 1fr; } .roadmap { grid-template-columns: 1fr; } } </style> </head> <body data-theme="auto"> <!-- 顶部迭代公告条(可关闭,持久化) --> <div class="announcement" id="announcement" role="region" aria-label="迭代公告"> <div class="container"> <div class="wrap"> <div class="left"> <span class="badge">v0.4.2</span> <span>新增:拖拽布局、主题偏好持久化、A/B测试变体</span> </div> <button class="close" id="close-announcement" aria-label="关闭公告">关闭</button> </div> </div> </div> <header class="site-header" role="banner"> <div class="container nav"> <div class="brand"> <span class="logo" aria-hidden="true"></span> <span>NovaFlow</span> <span class="badge" id="ab-badge" title="A/B测试变体">AB: A</span> </div> <nav aria-label="主导航"> <ul> <li><a href="#hero">概述</a></li> <li><a href="#features">功能</a></li> <li><a href="#roadmap">路线图</a></li> <li><a href="#signup">报名</a></li> <li><a href="#faq">FAQ</a></li> <li><a href="#changelog">公告</a></li> </ul> </nav> <div class="actions"> <button class="btn btn-ghost" id="layout-toggle" aria-pressed="false">自定义布局</button> <button class="btn btn-ghost" id="layout-reset" title="重置模块顺序">重置</button> <button class="btn btn-icon" id="theme-toggle" title="切换主题" aria-label="切换主题">🌓</button> </div> </div> </header> <main class="container" id="main"> <!-- Hero 模块 --> <section class="module" id="hero" data-module="hero" tabindex="-1"> <div class="drag-handle" aria-hidden="true">⋮⋮ 拖拽模块</div> <div class="module-controls" aria-hidden="true"> <button class="ctrl" data-move="up" title="上移">↑</button> <button class="ctrl" data-move="down" title="下移">↓</button> </div> <span class="badge">产品愿景</span> <h1 id="hero-title">让产品从0到1更快验证</h1> <p class="sub" id="hero-sub"> NovaFlow 将「洞察-构建-验证-迭代」压缩到一周内:所见即所得模块、A/B测试、表单收集、主题切换与公告管理,帮你用最小成本跑出最大结果。 </p> <ul class="hero-points" aria-label="核心卖点"> <li>✅ 一页整合验证必需组件,减少上下游沟通成本</li> <li>✅ A/B 测试内置,快速定位有效文案与CTA</li> <li>✅ 拖拽布局 + 深色模式,提升审美与可用性</li> <li>✅ 零依赖纯前端,复制即用,易于接入任意后端</li> </ul> <div class="ctas"> <a class="btn btn-primary" href="#signup" id="hero-cta">立即报名体验</a> <a class="btn" href="#features">查看功能</a> </div> </section> <!-- 功能列表 --> <section class="module" id="features" data-module="features" tabindex="-1"> <div class="drag-handle" aria-hidden="true">⋮⋮ 拖拽模块</div> <div class="module-controls" aria-hidden="true"> <button class="ctrl" data-move="up" title="上移">↑</button> <button class="ctrl" data-move="down" title="下移">↓</button> </div> <h2>功能一览</h2> <p class="sub">覆盖验证闭环的关键模块,低成本高效率。</p> <div class="features-grid"> <article class="feature-card"> <span class="tag">交互</span> <h3>A/B测试引擎</h3> <p>URL参数/本地持久化两种分流方式,曝光与CTA点击事件就绪,可接入任意分析。</p> </article> <article class="feature-card"> <span class="tag">体验</span> <h3>模块拖拽</h3> <p>桌面端拖拽排序,移动端按钮上/下移;顺序本地持久化,实验排版更轻松。</p> </article> <article class="feature-card"> <span class="tag">品牌</span> <h3>亮/暗主题</h3> <p>三态:亮 / 暗 / 跟随系统;自动记忆偏好,夜间浏览舒适护眼。</p> </article> <article class="feature-card"> <span class="tag">增长</span> <h3>报名与反馈</h3> <p>姓名/邮箱/用途三要素收集,本地校验与成功反馈,轻松对接你的后端。</p> </article> <article class="feature-card"> <span class="tag">发布</span> <h3>迭代公告</h3> <p>顶部公告条 + 更新日志,让用户一路感知产品进步,增强信任。</p> </article> <article class="feature-card"> <span class="tag">SEO</span> <h3>基础优化</h3> <p>语义结构、元信息与结构化数据,社交卡片预设,助力被正确发现。</p> </article> </div> </section> <!-- 路线图 --> <section class="module" id="roadmap" data-module="roadmap" tabindex="-1"> <div class="drag-handle" aria-hidden="true">⋮⋮ 拖拽模块</div> <div class="module-controls" aria-hidden="true"> <button class="ctrl" data-move="up" title="上移">↑</button> <button class="ctrl" data-move="down" title="下移">↓</button> </div> <h2>产品路线图</h2> <p class="sub">Now / Next / Later,让方向清晰、节奏明确。</p> <div class="roadmap" role="list"> <div class="road-col" role="listitem" aria-label="现在"> <h3>现在 <span class="tag">进行中</span></h3> <ul> <li>报名表单与校验完善</li> <li>拖拽布局 + 移动端上/下移</li> <li>A/B测试与曝光统计</li> </ul> </div> <div class="road-col" role="listitem" aria-label="下一步"> <h3>下一步</h3> <ul> <li>可视化配置面板</li> <li>内置数据可视化卡片</li> <li>多语言与可访问性增强</li> </ul> </div> <div class="road-col" role="listitem" aria-label="未来"> <h3>未来</h3> <ul> <li>服务端事件回传SDK</li> <li>模板市场与生态扩展</li> <li>插件化能力与团队协作</li> </ul> </div> </div> </section> <!-- 报名与反馈表单 --> <section class="module" id="signup" data-module="signup" tabindex="-1"> <div class="drag-handle" aria-hidden="true">⋮⋮ 拖拽模块</div> <div class="module-controls" aria-hidden="true"> <button class="ctrl" data-move="up" title="上移">↑</button> <button class="ctrl" data-move="down" title="下移">↓</button> </div> <h2>报名体验 / 反馈建议</h2> <p class="sub">留下联系信息,我们会在首批可用时通知你,并邀请加入用户群。</p> <form id="lead-form" novalidate> <div class="grid"> <div class="row"> <label for="name">姓名</label> <input id="name" name="name" type="text" placeholder="请输入姓名" required /> </div> <div class="row"> <label for="email">邮箱</label> <input id="email" name="email" type="email" placeholder="name@example.com" required /> </div> </div> <div class="row" style="margin-top:12px;"> <label for="usage">用途 / 使用场景</label> <select id="usage" name="usage" required> <option value="" selected disabled>请选择你的主要用途</option> <option value="企业官网MVP">企业官网MVP</option> <option value="产品展示页">产品展示页</option> <option value="个人作品集">个人作品集</option> <option value="教育培训演示">教育培训演示</option> <option value="营销活动页">营销活动页</option> <option value="其他">其他</option> </select> <span class="hint">我们将用于优化模板与优先支持。</span> </div> <div class="row" style="margin-top:12px;"> <label for="msg">补充需求(可选)</label> <textarea id="msg" name="msg" placeholder="如需特定组件或API对接,请在此说明"></textarea> </div> <div class="form-actions" style="margin-top:14px;"> <button type="submit" class="btn btn-primary">提交报名</button> <label class="hint"><input type="checkbox" id="agree" checked /> 我同意接收产品更新邮件</label> </div> <div class="success" id="form-success" role="status" aria-live="polite"> 感谢提交!已记录你的信息(AB变体:<span id="submitted-variant">A</span>)。我们会尽快与你联系。 </div> </form> </section> <!-- FAQ --> <section class="module" id="faq" data-module="faq" tabindex="-1"> <div class="drag-handle" aria-hidden="true">⋮⋮ 拖拽模块</div> <div class="module-controls" aria-hidden="true"> <button class="ctrl" data-move="up" title="上移">↑</button> <button class="ctrl" data-move="down" title="下移">↓</button> </div> <h2>常见问题 FAQ</h2> <details> <summary>可以直接上线使用吗?</summary> <div>可以。这是零依赖纯前端模板,支持移动端与桌面端。你可以直接部署到静态空间,后续再接后端即可。</div> </details> <details> <summary>A/B 测试如何查看数据?</summary> <div>模板内置曝光与CTA点击的console日志与本地存储。接入第三方分析时,将事件上报函数替换为你的SDK。</div> </details> <details> <summary>拖拽排序是否会丢失?</summary> <div>模块顺序会保存在浏览器本地(localStorage)。你也可以点击“重置”恢复默认顺序。</div> </details> <details> <summary>表单数据保存在哪里?</summary> <div>默认保存在本地存储以便演示。正式环境请改为提交到你的后端或Serverless函数。</div> </details> </section> <!-- 迭代公告 / 更新日志 --> <section class="module" id="changelog" data-module="changelog" tabindex="-1"> <div class="drag-handle" aria-hidden="true">⋮⋮ 拖拽模块</div> <div class="module-controls" aria-hidden="true"> <button class="ctrl" data-move="up" title="上移">↑</button> <button class="ctrl" data-move="down" title="下移">↓</button> </div> <h2>迭代公告</h2> <p class="sub">持续小步快跑,快速汇报进展与方向。</p> <div class="changelog-list" aria-label="更新列表"> <article class="change-item"> <h3>v0.4.2</h3> <div class="meta">2025-10-08</div> <ul> <li>新增:模块拖拽 + 布局持久化</li> <li>新增:亮/暗/系统主题切换</li> <li>新增:A/B测试变体与曝光、点击埋点接口</li> </ul> </article> <article class="change-item"> <h3>v0.4.1</h3> <div class="meta">2025-09-23</div> <ul> <li>优化:表单校验与国际化预留</li> <li>优化:移动端排版与触控区域</li> </ul> </article> </div> </section> </main> <footer role="contentinfo"> <div class="container"> <div class="row"> <div>© <span id="year"></span> NovaFlow · Made for fast MVP</div> <div> <span class="badge">主题:<span id="theme-state">auto</span></span> </div> </div> </div> </footer> <!-- Analytics Slot(页面尾部占位) --> <!-- 粘贴你的统计代码到此处(请确保合法合规并遵循隐私政策) --> <script> (function () { const $ = (sel, root=document) => root.querySelector(sel); const $$ = (sel, root=document) => Array.from(root.querySelectorAll(sel)); // ---------- 基础工具 ---------- const storage = { get(key, fallback=null) { try { const v = localStorage.getItem(key); return v ? JSON.parse(v) : fallback; } catch { return fallback; } }, set(key, value) { try { localStorage.setItem(key, JSON.stringify(value)); } catch {} }, del(key) { try { localStorage.removeItem(key); } catch {} } }; // ---------- Analytics Stub(示例) ---------- window.analytics = { record(event, data={}) { // 在此替换为你的分析SDK上报逻辑 console.log("[analytics]", event, data); } }; // ---------- 年份 ---------- $("#year").textContent = new Date().getFullYear(); // ---------- 主题切换 ---------- const themeKey = "nf_theme"; const themeStateEl = $("#theme-state"); const themeToggle = $("#theme-toggle"); function applyTheme(mode) { const prefersDark = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches; let actual = mode; if (mode === "auto") { actual = prefersDark ? "dark" : "light"; } document.body.setAttribute("data-theme", actual); themeStateEl.textContent = mode; } const savedTheme = storage.get(themeKey, "auto"); applyTheme(savedTheme); themeToggle.addEventListener("click", () => { const current = themeStateEl.textContent; const next = current === "auto" ? "light" : current === "light" ? "dark" : "auto"; storage.set(themeKey, next); applyTheme(next); analytics.record("theme_change", { mode: next }); }); // ---------- 公告条 ---------- const ann = $("#announcement"); const closeAnn = $("#close-announcement"); const annKey = "nf_ann_closed_v042"; if (storage.get(annKey, false)) ann.style.display = "none"; closeAnn.addEventListener("click", () => { ann.style.display = "none"; storage.set(annKey, true); }); // ---------- A/B 测试 ---------- const abKey = "nf_ab_variant"; const urlParams = new URLSearchParams(location.search); const urlAb = urlParams.get("ab"); const valid = (v) => v === "A" || v === "B"; let variant = storage.get(abKey, null); if (valid(urlAb)) { variant = urlAb; storage.set(abKey, variant); } if (!valid(variant)) { variant = Math.random() < 0.5 ? "A" : "B"; storage.set(abKey, variant); } document.body.classList.add("ab-" + variant.toLowerCase()); $("#ab-badge").textContent = "AB: " + variant; // 应用变体文案 const heroTitle = $("#hero-title"); const heroSub = $("#hero-sub"); const heroCTA = $("#hero-cta"); if (variant === "A") { heroTitle.textContent = "让产品从0到1更快验证"; heroSub.textContent = "NovaFlow 将「洞察-构建-验证-迭代」压缩到一周内:所见即所得模块、A/B测试、表单收集、主题切换与公告管理,帮你用最小成本跑出最大结果。"; heroCTA.textContent = "立即报名体验"; } else { heroTitle.textContent = "用一页,跑通增长闭环"; heroSub.textContent = "把验证所需的关键环节装进一页:从认知到转化再到复访,用更少的时间验证更大的价值。"; heroCTA.textContent = "现在就开始"; } // 曝光上报(示例) analytics.record("ab_exposure", { variant, path: location.pathname }); // CTA 点击上报(示例) heroCTA.addEventListener("click", () => { analytics.record("cta_click", { variant, cta: heroCTA.textContent }); }); // ---------- 表单逻辑 ---------- const form = $("#lead-form"); const success = $("#form-success"); const submittedVariant = $("#submitted-variant"); form.addEventListener("submit", (e) => { e.preventDefault(); const formData = new FormData(form); const name = (formData.get("name") || "").trim(); const email = (formData.get("email") || "").trim(); const usage = formData.get("usage") || ""; const msg = (formData.get("msg") || "").trim(); const agree = $("#agree").checked; // 简单校验 const emailOK = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); if (!name || !emailOK || !usage) { alert("请完整填写姓名、合法邮箱与用途。"); return; } // 本地存储演示 const leadsKey = "nf_leads"; const leads = storage.get(leadsKey, []); leads.push({ name, email, usage, msg, agree, ts: Date.now(), variant }); storage.set(leadsKey, leads); submittedVariant.textContent = variant; success.classList.add("show"); analytics.record("form_submit", { variant, usage }); form.reset(); }); // ---------- 模块拖拽与排序 ---------- const main = $("#main"); const modules = () => $$(".module", main); const orderKey = "nf_module_order"; // 应用排序 const savedOrder = storage.get(orderKey, null); if (Array.isArray(savedOrder) && savedOrder.length) { const idSet = new Set(savedOrder); modules() .sort((a, b) => { const ia = savedOrder.indexOf(a.id); const ib = savedOrder.indexOf(b.id); return (ia === -1 ? 999 : ia) - (ib === -1 ? 999 : ib); }) .forEach(el => main.appendChild(el)); } function persistOrder() { const order = modules().map(m => m.id); storage.set(orderKey, order); } // 自定义布局开关 const layoutToggle = $("#layout-toggle"); const layoutReset = $("#layout-reset"); let customizing = false; layoutToggle.addEventListener("click", () => { customizing = !customizing; document.body.classList.toggle("customizing", customizing); layoutToggle.setAttribute("aria-pressed", String(customizing)); modules().forEach(m => m.setAttribute("draggable", customizing ? "true" : "false")); analytics.record("layout_customizing", { on: customizing }); }); layoutReset.addEventListener("click", () => { // 恢复默认顺序(按DOM原始序) storage.del(orderKey); location.reload(); }); // 移动端辅助按钮(上/下移) $$(".module-controls .ctrl").forEach(btn => { btn.addEventListener("click", (e) => { const mod = e.target.closest(".module"); if (!mod) return; if (e.target.dataset.move === "up" && mod.previousElementSibling) { main.insertBefore(mod, mod.previousElementSibling); } else if (e.target.dataset.move === "down" && mod.nextElementSibling) { const next = mod.nextElementSibling.nextElementSibling; main.insertBefore(mod, next); } persistOrder(); }); }); // 桌面端拖拽 let dragging = null; let placeholder = null; function createPlaceholder(height) { const ph = document.createElement("div"); ph.className = "drag-placeholder"; ph.style.height = height + "px"; return ph; } main.addEventListener("dragstart", (e) => { const mod = e.target.closest(".module"); if (!customizing || !mod) return; dragging = mod; placeholder = createPlaceholder(mod.offsetHeight); mod.style.opacity = "0.5"; analytics.record("module_drag_start", { id: mod.id }); }); main.addEventListener("dragend", (e) => { if (!dragging) return; dragging.style.opacity = ""; if (placeholder && placeholder.parentNode) { placeholder.parentNode.replaceChild(dragging, placeholder); } dragging = null; placeholder = null; persistOrder(); analytics.record("module_drag_end", {}); }); main.addEventListener("dragover", (e) => { if (!customizing || !dragging) return; e.preventDefault(); const after = getDragAfterElement(main, e.clientY); if (!placeholder) placeholder = createPlaceholder(dragging.offsetHeight); if (after == null) { main.appendChild(placeholder); } else { main.insertBefore(placeholder, after); } }); function getDragAfterElement(container, y) { const els = modules().filter(el => el !== dragging); let closest = { offset: Number.NEGATIVE_INFINITY, element: null }; els.forEach(child => { const box = child.getBoundingClientRect(); const offset = y - box.top - box.height / 2; if (offset < 0 && offset > closest.offset) { closest = { offset, element: child }; } }); return closest.element; } // ---------- 可访问性增强 ---------- // 键盘辅助:在自定义模式下,模块获得焦点时,按Alt+↑ / Alt+↓ 进行上/下移 main.addEventListener("keydown", (e) => { if (!customizing || !e.target.classList.contains("module")) return; if (e.altKey && (e.key === "ArrowUp" || e.key === "ArrowDown")) { e.preventDefault(); const mod = e.target; if (e.key === "ArrowUp" && mod.previousElementSibling) { main.insertBefore(mod, mod.previousElementSibling); } else if (e.key === "ArrowDown" && mod.nextElementSibling) { const next = mod.nextElementSibling.nextElementSibling; main.insertBefore(mod, next); } persistOrder(); analytics.record("module_reorder_keyboard", { id: mod.id }); } }); })(); </script> </body> </html> ``` ## CSS样式 ```css /* 已内联至HTML的<style>中;若需拆分外链,请将以下内容保存为 styles.css 并移除HTML内联样式。 */ /* 见HTML代码块中的<style>,内容完全一致 */ ``` ## JavaScript功能 ```javascript // 已内联至HTML的<script>中;若需拆分外链,请将以下内容保存为 app.js 并在HTML底部以 <script src="app.js"></script> 引入。 // 见HTML代码块中的<script>,内容完全一致 ``` ## 使用说明 - 本地预览 1. 将上述HTML保存为 index.html(已内联CSS/JS,单文件可运行)。 2. 双击用浏览器打开,或使用任意静态服务器(如 VS Code Live Server)打开。 - A/B测试 - 默认随机分配到 A 或 B,存储于 localStorage(键:nf_ab_variant)。 - 可通过URL强制指定:?ab=A 或 ?ab=B。 - 曝光与CTA点击以 console 日志打印,替换 window.analytics.record 即可接第三方分析。 - 模块拖拽 - 点击“自定义布局”开启编辑模式(桌面端可拖拽,移动端用上/下移按钮)。 - 修改顺序后自动保存到 localStorage(键:nf_module_order)。 - 点击“重置”恢复默认顺序。 - 主题切换 - 亮 / 暗 / 跟随系统 三态循环切换,状态展示在页脚,持久化键:nf_theme。 - 表单 - 本模板不发起外部请求。提交后会在本地存储演示数据(键:nf_leads),并显示成功提示。 - 请在生产环境中将提交逻辑改为调用你的后端API或Serverless函数。 - 迭代公告 - 顶部公告可关闭,状态持久化(键:nf_ann_closed_v042)。 - 更新日志在“迭代公告”模块中维护。 - SEO与分析脚本位 - 已包含基础Meta、Open Graph、Twitter、结构化数据。 - 头部与尾部均预留分析脚本位,按需粘贴你方脚本,确保合法合规与隐私政策。 ## 定制建议 - UI定制 - 在:root中调整CSS变量以快速更换品牌色与圆角、阴影风格。 - 为feature-card添加SVG图标以增强识别度(建议内联SVG,避免外部引用)。 - A/B扩展 - 将变体范围扩展到CTA颜色、模块顺序或价格呈现方式;使用同一ab_variant标识统一管理。 - 接入后端或第三方分析时,将analytics.record替换为实际埋点上报。 - 表单与合规 - 接入后端时请新增CSRF、防重复提交、机器人校验(如验证码/延迟提交)等安全措施。 - 添加隐私政策与用户协议链接,确保数据合规。 - 性能优化 - 部署时开启HTTP压缩与缓存;对图片资源使用现代格式(WebP/AVIF),本模板无外部资源可直接上线。 - 若模块较多,可按需拆分JS并采用defer加载(当前为内联单文件模式)。 - 可访问性 - 为关键按钮与链接补充更丰富的ARIA属性与键盘操作说明。 - 检查对比度与焦点可视化以满足WCAG标准。 - 国际化 - 为文案创建字典文件,按浏览器语言或URL参数切换;为日期与数字格式提供本地化格式化。 如需我根据你的品牌与产品信息进一步定制文案、配色与模块结构,请提供产品名称、目标用户、核心场景与竞品对比等信息。
## 网站概述 这是一个教学示例页,面向前端入门与进阶教学场景。它具备以下特性与技术实现: - 一键生成标准化页面结构(导航/主视觉/内容区/页脚),并可复制代码片段。 - 提供可切换的布局方案(CSS Grid 与 Flexbox),配套代码讲解与响应式断点注释。 - 内置示例数据填充卡片列表,便于教学展示。 - 作业提交表单与“待评分”占位展示,支持导出表单数据。 - 支持导出代码(HTML/CSS/JS)与讲义(Markdown),以及页面快照。 - 完整的语义化与无障碍(a11y)实践:跳转主内容、ARIA提示、表单标签关联、清晰焦点样式等。 - 响应式设计,适配移动端与桌面端。 技术栈与规范: - HTML5 语义化标签和可访问性属性 - CSS3 变量、Flexbox、Grid、媒体查询断点 - 原生 JavaScript,无外部依赖,确保安全与可维护性 - 无外部资源引用(图片用内联SVG),符合中国法律法规与社会主义核心价值观 --- ## HTML代码 ```html <!doctype html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> <meta name="description" content="前端教学示例页:标准化结构、一键生成、布局切换、响应式断点、作业提交与导出讲义。"> <title>前端教学示例页 · 标准化结构与响应式布局演示</title> <link rel="stylesheet" href="styles.css"> </head> <body> <!-- 跳转主内容的无障碍链接 --> <a class="skip-link" href="#main">跳转到主内容</a> <header class="site-header" role="banner"> <div class="container header-inner"> <a class="brand" href="#" aria-label="网站品牌标识">教学示例页</a> <button id="menuToggle" class="menu-toggle" aria-expanded="false" aria-controls="siteNav">菜单</button> <nav id="siteNav" class="site-nav" aria-label="主导航"> <ul> <li><a href="#hero">简介</a></li> <li><a href="#a11y">无障碍与语义化</a></li> <li><a href="#layout">布局演示</a></li> <li><a href="#codeDoc">代码讲解</a></li> <li><a href="#assignment">作业提交</a></li> <li><a href="#export">导出工具</a></li> </ul> </nav> </div> </header> <main id="main" tabindex="-1"> <!-- 主视觉区 --> <section id="hero" class="hero" aria-label="主视觉与快速操作"> <div class="container hero-inner"> <div class="hero-text"> <h1>前端教学示例:结构、布局与交互</h1> <p>一键生成标准化页面结构,演示响应式栅格与断点注释,切换Grid / Flex布局方案,提供代码片段讲解与作业提交/导出工具。</p> <div class="hero-actions"> <button id="generateStructureBtn" class="btn primary">一键生成标准化结构</button> <button id="exportHandoutBtn" class="btn">导出讲义(Markdown)</button> </div> </div> <div class="hero-art" aria-hidden="true"> <!-- 内联SVG,避免外部资源 --> <svg width="220" height="140" viewBox="0 0 220 140" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="教学示意图"> <rect x="5" y="5" width="210" height="130" rx="10" fill="#E6F0FF" stroke="#2B6CB0" stroke-width="2"/> <rect x="15" y="20" width="190" height="20" rx="4" fill="#CDE2FF"/> <rect x="15" y="50" width="90" height="70" rx="6" fill="#D9F2E6"/> <rect x="115" y="50" width="90" height="70" rx="6" fill="#FFEFD2"/> <text x="110" y="35" text-anchor="middle" font-size="12" fill="#2B6CB0">Nav / Hero / Grid / Footer</text> </svg> </div> </div> <div class="container"> <div id="structurePreview" class="structure-preview" aria-live="polite" aria-atomic="true"></div> </div> </section> <!-- 无障碍与语义化提示 --> <section id="a11y" class="section"> <div class="container"> <h2>无障碍与语义化提示</h2> <ul class="a11y-list"> <li>使用语义化标签:header、nav、main、section、article、footer。</li> <li>为交互控件添加可访问性属性:aria-label、aria-controls、aria-live、aria-expanded。</li> <li>提供“跳转主内容”链接,确保键盘导航与焦点可见。</li> <li>表单使用label显式关联输入框,错误提示与说明文本可被读屏识别。</li> <li>颜色对比充足,状态变化不只依赖颜色;提供可视化焦点样式。</li> </ul> </div> </section> <!-- 布局演示 --> <section id="layout" class="section"> <div class="container"> <div class="section-head"> <h2>响应式布局演示(栅格与断点)</h2> <p>选择不同布局方案并查看代码片段与断点注释。栅格示例在小屏 1 列,中屏 2 列,大屏 3 列。</p> </div> <div class="controls" role="group" aria-label="布局切换控制"> <div class="control-group"> <span class="label">布局方案:</span> <label><input type="radio" name="layoutMode" value="grid" checked> Grid 栅格</label> <label><input type="radio" name="layoutMode" value="flex"> Flex 弹性</label> </div> <div class="control-group"> <label><input type="checkbox" id="showBreakpoints"> 显示断点辅助栏</label> </div> <div class="control-group"> <button id="resetDataBtn" class="btn">重置示例数据</button> </div> </div> <div id="breakpointBar" class="breakpoint-bar" aria-hidden="true"> <div class="container"> <strong>断点参考:</strong> <span>SM ≥ 640px</span> <span>MD ≥ 960px</span> <span>LG ≥ 1200px(容器最大宽度)</span> </div> </div> <div id="layoutWrapper" class="layout-wrapper layout-grid"> <div id="cardContainer" class="cards" aria-live="polite" aria-busy="false"> <!-- JS渲染示例卡片 --> </div> </div> </div> </section> <!-- 代码讲解 --> <section id="codeDoc" class="section"> <div class="container"> <div class="section-head"> <h2>代码片段讲解</h2> <p>可复制 HTML / CSS 片段,配套注释,便于课堂讲解与自学复盘。</p> </div> <div class="code-tabs" role="tablist" aria-label="代码片段标签"> <button class="tab-btn active" data-target="htmlSnippet" role="tab" aria-selected="true">HTML片段</button> <button class="tab-btn" data-target="cssSnippet" role="tab" aria-selected="false">CSS片段</button> <button id="copySnippetBtn" class="btn small">复制当前片段</button> </div> <div class="code-panels"> <pre id="htmlSnippet" class="code-block" aria-label="HTML代码片段"><code></code></pre> <pre id="cssSnippet" class="code-block hidden" aria-label="CSS代码片段"><code></code></pre> </div> </div> </section> <!-- 作业提交 --> <section id="assignment" class="section"> <div class="container"> <h2>作业提交表单与评分占位</h2> <form id="assignmentForm" class="form" novalidate aria-labelledby="assignmentTitle"> <div class="form-grid"> <div class="form-item"> <label for="studentName">姓名</label> <input id="studentName" name="studentName" type="text" required placeholder="例如:张三" aria-describedby="nameHelp"> <small id="nameHelp" class="muted">使用真实姓名,便于确认成绩。</small> </div> <div class="form-item"> <label for="studentEmail">邮箱</label> <input id="studentEmail" name="studentEmail" type="email" required placeholder="example@domain.com"> </div> <div class="form-item"> <label for="assignmentTitle">作业标题</label> <input id="assignmentTitle" name="assignmentTitle" type="text" required placeholder="响应式布局练习"> </div> <div class="form-item"> <label for="assignmentLink">作品链接</label> <input id="assignmentLink" name="assignmentLink" type="url" placeholder="https://example.com/demo" aria-describedby="linkHelp"> <small id="linkHelp" class="muted">可填写在线预览地址或仓库链接。</small> </div> <div class="form-item"> <label for="assignmentFile">上传文件(可选)</label> <input id="assignmentFile" name="assignmentFile" type="file" aria-describedby="fileHelp"> <small id="fileHelp" class="muted">本地预览用,不会上传到服务器。</small> </div> <div class="form-item form-item--full"> <label for="assignmentDesc">作业说明</label> <textarea id="assignmentDesc" name="assignmentDesc" rows="4" maxlength="500" placeholder="简要说明你的设计思路与实现细节…" aria-describedby="descCount"></textarea> <small id="descCount" class="muted" aria-live="polite">0 / 500</small> </div> <div class="form-item"> <label><input id="agreePolicy" type="checkbox" required> 我已阅读并同意课堂提交规范</label> </div> </div> <div class="form-actions"> <button type="submit" class="btn primary">提交作业</button> <button type="reset" class="btn">清空表单</button> <button type="button" id="exportFormDataBtn" class="btn">导出表单数据(JSON)</button> </div> <div id="formErrors" class="form-errors" aria-live="assertive"></div> </form> <div class="submissions"> <h3>提交列表(评分占位)</h3> <ul id="submissionList" class="submission-list"> <!-- JS添加条目 --> </ul> </div> </div> </section> <!-- 导出工具 --> <section id="export" class="section"> <div class="container"> <h2>导出代码与讲义</h2> <p class="muted">可导出当前页面快照(内联CSS/JS),或分别导出HTML/CSS/JS源文件与课堂讲义。</p> <div class="export-actions"> <button id="exportHTMLBtn" class="btn">导出 HTML</button> <button id="exportCSSBtn" class="btn">导出 CSS</button> <button id="exportJSBtn" class="btn">导出 JS</button> <button id="exportSnapshotBtn" class="btn">导出页面快照(自包含)</button> </div> </div> </section> </main> <footer class="site-footer" role="contentinfo"> <div class="container footer-inner"> <p>© 2025 教学示例页。用于教学演示,遵循 Web 标准与中国法律法规。</p> <nav aria-label="页脚导航"> <a href="#hero">回到顶部</a> </nav> </div> </footer> <!-- 辅助:无障碍播报区域 --> <div id="announce" class="sr-only" aria-live="polite" aria-atomic="true"></div> <script defer src="script.js"></script> </body> </html> ``` --- ## CSS样式 ```css /* 基础主题变量与重置 */ :root{ --bg: #ffffff; --text: #1a1a1a; --muted: #6b7280; --primary: #2B6CB0; /* 教学友好蓝 */ --accent: #10B981; /* 成功绿 */ --warn: #D97706; /* 提醒橙 */ --surface: #f6f7fb; --border: #e5e7eb; --radius: 10px; --shadow: 0 6px 20px rgba(0,0,0,0.08); /* 容器与断点 */ --maxw: 1200px; --bp-sm: 640px; /* SM:小屏断点,≥640px 开始两列 */ --bp-md: 960px; /* MD:中屏断点,≥960px 开始三列 */ } *{box-sizing:border-box} html,body{height:100%} body{ margin:0; font-family: system-ui, -apple-system, Segoe UI, Roboto, "Helvetica Neue", Arial, "Noto Sans", "PingFang SC", "Microsoft YaHei", sans-serif; color:var(--text); background:var(--bg); line-height:1.6; } img{max-width:100%;display:block} a{color:var(--primary);text-decoration:none} a:hover{text-decoration:underline} /* 可见焦点(无障碍) */ :focus-visible{ outline:3px solid #93C5FD; outline-offset:2px; } /* 容器与通用区块 */ .container{max-width:var(--maxw);margin:0 auto;padding:0 16px} .section{padding:48px 0} .section-head h2{margin:0 0 8px} .section-head p{color:var(--muted);margin:0 0 24px} /* 跳转主内容 */ .skip-link{ position:absolute;left:-9999px;top:auto;width:1px;height:1px;overflow:hidden; } .skip-link:focus{ position:fixed;left:16px;top:16px;width:auto;height:auto;padding:8px 12px; background:#111;color:#fff;border-radius:6px;z-index:1000; } /* 头部导航 */ .site-header{background:#f8fbff;border-bottom:1px solid var(--border)} .header-inner{display:flex;align-items:center;gap:16px;padding:12px 0} .brand{font-weight:700;color:var(--primary)} .menu-toggle{ margin-left:auto; padding:8px 12px;border:1px solid var(--border);background:#fff;border-radius:8px;cursor:pointer; } .site-nav ul{ display:flex;gap:16px;list-style:none;margin:0;padding:0; } .site-nav a{padding:8px;border-radius:8px} .site-nav a:hover{background:#eef6ff} @media (max-width: 720px){ .menu-toggle{order:2} .site-nav{display:none;order:3} .site-nav.open{display:block} .site-nav ul{flex-direction:column;padding:8px 0} } /* 主视觉 */ .hero{padding:40px 0 16px;background:linear-gradient(180deg,#F0F7FF,#fff)} .hero-inner{display:grid;grid-template-columns:1fr 260px;gap:24px;align-items:center} .hero-text h1{margin:0 0 8px} .hero-text p{margin:0 0 16px;color:var(--muted)} .hero-actions{display:flex;gap:12px;flex-wrap:wrap} .hero-art{justify-self:end} .structure-preview{ margin-top:16px;padding:16px;border:1px dashed var(--border);border-radius:var(--radius);background:var(--surface); } @media (max-width: 780px){ .hero-inner{grid-template-columns:1fr} .hero-art{justify-self:start} } /* 按钮 */ .btn{ appearance:none;border:1px solid var(--border);background:#fff;color:var(--text); padding:10px 14px;border-radius:10px;cursor:pointer;box-shadow:var(--shadow); } .btn:hover{background:#f2f6ff} .btn.primary{background:var(--primary);border-color:transparent;color:#fff} .btn.primary:hover{filter:brightness(1.05)} .btn.small{padding:6px 10px;font-size:14px} /* 布局演示控制区 */ .controls{ display:flex;flex-wrap:wrap;gap:16px;align-items:center;margin:8px 0 16px; } .control-group{display:flex;gap:12px;align-items:center} .label{color:#374151} /* 断点辅助栏(可开关显示) */ .breakpoint-bar{ position:sticky;top:0;z-index:500;background:#111;color:#fff;padding:8px 0;margin-bottom:12px; display:none; } .breakpoint-bar .container{display:flex;gap:20px;align-items:center} .breakpoint-bar .container span{opacity:0.85} /* 布局外层:用于切换布局方案类名 */ .layout-wrapper{} /* 卡片列表通用样式 */ .cards{gap:16px} .card{ background:#fff;border:1px solid var(--border);border-radius:12px;padding:16px;box-shadow:var(--shadow); display:flex;flex-direction:column;gap:8px; } .card-header{display:flex;align-items:center;gap:12px} .card-title{font-weight:700;margin:0} .card-desc{color:var(--muted);margin:0} .card-tags{display:flex;gap:8px;flex-wrap:wrap} .tag{font-size:12px;color:#0F766E;background:#E6FFFA;border:1px solid #99F6E4;border-radius:999px;padding:2px 8px} .card-actions{margin-top:auto;display:flex;gap:8px} /* 布局方案 A:Grid 栅格 */ .layout-grid .cards{ display:grid; grid-template-columns: 1fr; /* 默认:小屏 1 列 */ } /* 断点注释: @media (min-width: 640px) => SM:两列 @media (min-width: 960px) => MD:三列 */ @media (min-width: 640px){ .layout-grid .cards{ grid-template-columns: repeat(2, 1fr); } } @media (min-width: 960px){ .layout-grid .cards{ grid-template-columns: repeat(3, 1fr); } } /* 布局方案 B:Flex 弹性 */ .layout-flex .cards{ display:flex; flex-wrap:wrap; } .layout-flex .card{ width:100%; } @media (min-width: 640px){ .layout-flex .card{ width: calc(50% - 8px); } /* 两列,减去gap一半 */ } @media (min-width: 960px){ .layout-flex .card{ width: calc(33.333% - 10.7px); } /* 三列 */ } /* 代码区 */ .code-tabs{display:flex;gap:8px;align-items:center;margin-bottom:8px} .tab-btn{padding:8px 12px;border:1px solid var(--border);border-radius:8px;background:#fff;cursor:pointer} .tab-btn.active{background:#EEF6FF;border-color:#BFDBFE} .code-block{ border:1px solid var(--border);border-radius:12px;background:#0B1020;color:#E5EDFF; padding:16px;overflow:auto;box-shadow:var(--shadow);max-height:60vh; } .code-block.hidden{display:none} .code-block code{font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace} /* 表单 */ .form-grid{ display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:12px; } .form-item{display:flex;flex-direction:column;gap:8px} .form-item--full{grid-column:1 / -1} label{font-weight:600} input[type="text"], input[type="email"], input[type="url"], input[type="file"], textarea{ width:100%;padding:10px;border:1px solid var(--border);border-radius:8px;background:#fff; } input:focus, textarea:focus{border-color:#93C5FD;box-shadow:0 0 0 3px #DBEAFE} .form-actions{display:flex;gap:12px;flex-wrap:wrap;margin-top:4px} .form-errors{margin-top:12px;color:#B91C1C;background:#FEF2F2;border:1px solid #FECACA;padding:10px;border-radius:8px;display:none} .muted{color:var(--muted)} /* 提交列表 */ .submission-list{ list-style:none;margin:12px 0 0;padding:0;display:grid;gap:12px; } .submission-item{ border:1px solid var(--border);border-radius:10px;padding:12px;background:#fff;box-shadow:var(--shadow); display:grid;grid-template-columns:1fr auto;gap:8px;align-items:center; } .submission-meta{color:var(--muted);font-size:14px} .grade-placeholder{color:#374151;background:#FFF7ED;border:1px dashed #FED7AA;padding:6px 8px;border-radius:8px} /* 页脚 */ .site-footer{margin-top:32px;border-top:1px solid var(--border);background:#fafafa} .footer-inner{display:flex;justify-content:space-between;align-items:center;padding:16px 0} /* 小屏优化 */ @media (max-width: 780px){ .form-grid{grid-template-columns:1fr} .submission-item{grid-template-columns:1fr} } ``` --- ## JavaScript功能 ```javascript /* 教学示例页交互脚本 - 一键生成标准化结构 - 布局方案切换(Grid/Flex)与代码片段更新 - 示例数据渲染/重置 - 作业提交表单验证与“待评分”占位 - 导出代码与讲义/页面快照 - 无障碍:ARIA 播报、可见焦点、键盘友好菜单 */ (function(){ const qs = (s, p=document) => p.querySelector(s); const qsa = (s, p=document) => Array.from(p.querySelectorAll(s)); const announce = (msg) => { const el = qs('#announce'); el.textContent = msg; // 清空以便下一次读屏触发 setTimeout(()=>{ el.textContent = ''; }, 1200); }; // 示例数据(可按需扩展或替换) const sampleItems = [ {title:'导航与信息架构', desc:'演示 header/nav/main/footer 的标准化结构。', tags:['HTML5','语义化']}, {title:'主视觉模块', desc:'教学友好主视觉区,呼出核心CTA与示意图。', tags:['UX','Hero']}, {title:'Grid 栅格', desc:'小屏1列,中屏2列,大屏3列的响应式示例。', tags:['CSS Grid','响应式']}, {title:'Flex 弹性布局', desc:'等宽卡片换行布局,配合断点调整列数。', tags:['Flexbox','布局']}, {title:'无障碍实践', desc:'跳转主内容、焦点可见、ARIA提示等。', tags:['a11y','可访问性']}, {title:'代码片段讲解', desc:'HTML/CSS片段切换与复制,配套注释。', tags:['教学','代码']}, {title:'作业提交表单', desc:'必填项校验、字符计数与数据导出。', tags:['表单','验证']}, {title:'评分占位', desc:'提交列表内展示“待评分”状态。', tags:['评分','占位']}, {title:'示例数据填充', desc:'内置卡片数据,用于课堂展示。', tags:['数据','演示']}, {title:'导出工具', desc:'导出HTML/CSS/JS与讲义Markdown。', tags:['导出','工具']}, {title:'移动端适配', desc:'在窄屏下菜单折叠、表单单列。', tags:['移动端','适配']}, {title:'性能与规范', desc:'简洁结构,无外部依赖,安全可靠。', tags:['规范','性能']}, ]; // 结构生成的标准化模板 const STANDARD_STRUCTURE_HTML = `<!doctype html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>标准化页面结构示例</title> </head> <body> <a class="skip-link" href="#main">跳转到主内容</a> <header role="banner"> <nav aria-label="主导航"> <ul> <li><a href="#hero">简介</a></li> <li><a href="#content">内容区</a></li> <li><a href="#footer">页脚</a></li> </ul> </nav> </header> <main id="main"> <section id="hero" aria-label="主视觉"> <h1>主视觉标题</h1> <p>副标题或引导语</p> <button>主要操作</button> </section> <section id="content" aria-label="内容区"> <article> <h2>模块标题</h2> <p>模块内容文本示例。</p> </article> </section> </main> <footer id="footer" role="contentinfo"> <small>© 示例页脚信息</small> </footer> </body> </html>`; // 代码片段:HTML(卡片列表) const CARDS_HTML_SNIPPET = `<section class="cards-demo"> <div class="cards"> <article class="card"> <header class="card-header"> <h3 class="card-title">示例标题</h3> </header> <p class="card-desc">卡片描述文字……</p> <div class="card-tags"> <span class="tag">标签</span> </div> <div class="card-actions"> <button class="btn small">查看</button> <button class="btn small">收藏</button> </div> </article> <!-- 更多卡片… --> </div> </section>`; // 代码片段:CSS(Grid/Flex) const GRID_CSS_SNIPPET = `/* 布局方案 A:Grid 栅格 */ .layout-grid .cards{ display:grid; grid-template-columns:1fr; gap:16px; } /* SM ≥ 640px:两列 */ @media (min-width: 640px){ .layout-grid .cards{ grid-template-columns: repeat(2, 1fr); } } /* MD ≥ 960px:三列 */ @media (min-width: 960px){ .layout-grid .cards{ grid-template-columns: repeat(3, 1fr); } }`; const FLEX_CSS_SNIPPET = `/* 布局方案 B:Flex 弹性 */ .layout-flex .cards{ display:flex; flex-wrap:wrap; gap:16px; } .layout-flex .card{ width:100%; } /* SM ≥ 640px:两列 */ @media (min-width: 640px){ .layout-flex .card{ width: calc(50% - 8px); } } /* MD ≥ 960px:三列 */ @media (min-width: 960px){ .layout-flex .card{ width: calc(33.333% - 10.7px); } }`; // 菜单折叠 const menuToggle = qs('#menuToggle'); const siteNav = qs('#siteNav'); menuToggle?.addEventListener('click', ()=>{ const opened = siteNav.classList.toggle('open'); menuToggle.setAttribute('aria-expanded', opened ? 'true' : 'false'); }); // 一键生成标准化结构 const structurePreview = qs('#structurePreview'); const generateStructureBtn = qs('#generateStructureBtn'); generateStructureBtn?.addEventListener('click', ()=>{ structurePreview.innerHTML = ` <div class="structure-box"> <h3>标准化结构(预览 + 可复制)</h3> <p class="muted">包含导航、主视觉、内容区、页脚与跳转主内容链接。</p> <pre class="code-block"><code>${escapeHtml(STANDARD_STRUCTURE_HTML)}</code></pre> <button class="btn small" id="copyStructureBtn">复制结构代码</button> </div> `; qs('#copyStructureBtn', structurePreview)?.addEventListener('click', ()=>{ copyText(STANDARD_STRUCTURE_HTML); announce('标准化结构代码已复制'); }); setActiveTab('htmlSnippet'); setSnippet('html', STANDARD_STRUCTURE_HTML); announce('标准化结构已生成并展示'); }); // 布局与示例数据渲染 const cardContainer = qs('#cardContainer'); const layoutWrapper = qs('#layoutWrapper'); const resetDataBtn = qs('#resetDataBtn'); function renderCards(){ cardContainer.setAttribute('aria-busy', 'true'); cardContainer.innerHTML = sampleItems.map(createCardHTML).join(''); cardContainer.setAttribute('aria-busy', 'false'); } function createCardHTML(item){ const icon = `<svg width="36" height="36" viewBox="0 0 36 36" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> <rect x="1.5" y="1.5" width="33" height="33" rx="8" fill="#EEF6FF" stroke="#2B6CB0"/> <path d="M8 18h20M18 8v20" stroke="#2B6CB0" stroke-width="2"/> </svg>`; return `<article class="card"> <header class="card-header">${icon}<h3 class="card-title">${escapeHtml(item.title)}</h3></header> <p class="card-desc">${escapeHtml(item.desc)}</p> <div class="card-tags">${item.tags.map(t => `<span class="tag">${escapeHtml(t)}</span>`).join('')}</div> <div class="card-actions"> <button class="btn small" aria-label="查看 ${escapeHtml(item.title)}">查看</button> <button class="btn small" aria-label="收藏 ${escapeHtml(item.title)}">收藏</button> </div> </article>`; } resetDataBtn?.addEventListener('click', ()=>{ renderCards(); announce('示例数据已重置'); }); // 布局切换与代码片段 const htmlBlock = qs('#htmlSnippet code'); const cssBlock = qs('#cssSnippet code'); const tabButtons = qsa('.tab-btn'); const copySnippetBtn = qs('#copySnippetBtn'); const showBreakpoints = qs('#showBreakpoints'); const breakpointBar = qs('#breakpointBar'); function setSnippet(type, content){ if(type === 'html'){ htmlBlock.textContent = content; }else if(type === 'css'){ cssBlock.textContent = content; } } function setActiveTab(id){ tabButtons.forEach(btn=>{ const target = btn.dataset.target; const active = target === id; btn.classList.toggle('active', active); btn.setAttribute('aria-selected', active ? 'true' : 'false'); qs('#'+target).classList.toggle('hidden', !active); }); } tabButtons.forEach(btn=>{ btn.addEventListener('click', ()=>{ setActiveTab(btn.dataset.target); }); }); // 初始化:渲染卡片、默认布局与片段 renderCards(); setSnippet('html', CARDS_HTML_SNIPPET); setSnippet('css', GRID_CSS_SNIPPET); // 布局模式切换 qsa('input[name="layoutMode"]').forEach(radio=>{ radio.addEventListener('change', ()=>{ const val = radio.value; layoutWrapper.classList.toggle('layout-grid', val === 'grid'); layoutWrapper.classList.toggle('layout-flex', val === 'flex'); setActiveTab('cssSnippet'); setSnippet('css', val === 'grid' ? GRID_CSS_SNIPPET : FLEX_CSS_SNIPPET); announce(`布局已切换为 ${val === 'grid' ? 'Grid 栅格' : 'Flex 弹性'}`); }); }); // 断点辅助栏开关 showBreakpoints?.addEventListener('change', ()=>{ const on = showBreakpoints.checked; breakpointBar.style.display = on ? 'block' : 'none'; announce(on ? '已显示断点辅助栏' : '已隐藏断点辅助栏'); }); // 复制当前片段 copySnippetBtn?.addEventListener('click', ()=>{ const active = tabButtons.find(btn=>btn.classList.contains('active'))?.dataset.target; const text = active === 'cssSnippet' ? cssBlock.textContent : htmlBlock.textContent; copyText(text); announce('代码片段已复制到剪贴板'); }); // 表单:字符计数与提交验证 const form = qs('#assignmentForm'); const desc = qs('#assignmentDesc'); const descCount = qs('#descCount'); const formErrors = qs('#formErrors'); const submissionList = qs('#submissionList'); const exportFormDataBtn = qs('#exportFormDataBtn'); desc?.addEventListener('input', ()=>{ descCount.textContent = `${desc.value.length} / ${desc.maxLength}`; }); form?.addEventListener('submit', (e)=>{ e.preventDefault(); formErrors.style.display = 'none'; if(!form.checkValidity()){ showFormErrors(); return; } const data = new FormData(form); const entry = { name: data.get('studentName')?.toString().trim(), email: data.get('studentEmail')?.toString().trim(), title: data.get('assignmentTitle')?.toString().trim(), link: data.get('assignmentLink')?.toString().trim(), desc: data.get('assignmentDesc')?.toString().trim(), ts: new Date().toISOString(), grade: null // 待评分 }; addSubmission(entry); form.reset(); descCount.textContent = `0 / ${desc.maxLength}`; announce('作业已提交,状态为待评分'); }); function showFormErrors(){ const invalids = qsa('#assignmentForm input:invalid, #assignmentForm textarea:invalid'); const names = invalids.map(el=> qs(`label[for="${el.id}"]`)?.textContent || el.name); formErrors.innerHTML = `<strong>请检查以下字段:</strong> ${names.join('、')}`; formErrors.style.display = 'block'; invalids[0]?.focus(); announce('表单校验失败,请完善必填项'); } function addSubmission(entry){ const li = document.createElement('li'); li.className = 'submission-item'; li.innerHTML = ` <div> <strong>${escapeHtml(entry.title)}</strong> <div class="submission-meta"> <span>${escapeHtml(entry.name)} · ${escapeHtml(entry.email)}</span> ${entry.link ? ` · <a href="${escapeAttr(entry.link)}" target="_blank" rel="noopener">作品链接</a>` : ''} </div> </div> <div class="grade-placeholder" role="status" aria-label="评分占位">待评分</div> `; submissionList.prepend(li); } // 导出表单数据 exportFormDataBtn?.addEventListener('click', ()=>{ const items = qsa('.submission-item').map(li=>{ const title = li.querySelector('strong')?.textContent || ''; const meta = li.querySelector('.submission-meta')?.textContent || ''; const grade = li.querySelector('.grade-placeholder')?.textContent || '待评分'; return { title, meta, grade }; }); downloadText(JSON.stringify({ exportedAt: new Date().toISOString(), submissions: items }, null, 2), 'submissions.json', 'application/json'); announce('已导出提交列表数据'); }); // 导出讲义(Markdown) const exportHandoutBtn = qs('#exportHandoutBtn'); exportHandoutBtn?.addEventListener('click', ()=>{ const md = buildHandoutMarkdown(); downloadText(md, '前端教学讲义.md', 'text/markdown'); announce('讲义已导出'); }); // 导出代码与页面快照(自包含) const exportHTMLBtn = qs('#exportHTMLBtn'); const exportCSSBtn = qs('#exportCSSBtn'); const exportJSBtn = qs('#exportJSBtn'); const exportSnapshotBtn = qs('#exportSnapshotBtn'); exportHTMLBtn?.addEventListener('click', ()=>{ downloadText(HTML_SOURCE, 'index.html', 'text/html'); announce('HTML 源文件已导出'); }); exportCSSBtn?.addEventListener('click', ()=>{ downloadText(CSS_SOURCE, 'styles.css', 'text/css'); announce('CSS 源文件已导出'); }); exportJSBtn?.addEventListener('click', ()=>{ downloadText(JS_SOURCE, 'script.js', 'text/javascript'); announce('JS 源文件已导出'); }); exportSnapshotBtn?.addEventListener('click', ()=>{ const snapshot = `<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>页面快照</title><style>${CSS_SOURCE}</style></head><body>${document.body.outerHTML}<script>${JS_SOURCE}</script></body></html>`; downloadText(snapshot, 'snapshot.html', 'text/html'); announce('已导出页面快照(内联CSS/JS)'); }); // 工具函数 function escapeHtml(str=''){ return str.replace(/[&<>"']/g, s=>({ '&':'&', '<':'<', '>':'>', '"':'"', "'":''' }[s])); } function escapeAttr(str=''){ return str.replace(/"/g, '"'); } function copyText(text){ if(navigator.clipboard && window.isSecureContext){ navigator.clipboard.writeText(text).catch(()=>fallbackCopy(text)); }else{ fallbackCopy(text); } } function fallbackCopy(text){ const ta = document.createElement('textarea'); ta.value = text; document.body.appendChild(ta); ta.select(); try{ document.execCommand('copy'); }catch(e){} document.body.removeChild(ta); } function downloadText(text, filename, type='text/plain'){ const blob = new Blob([text], {type}); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = filename; document.body.appendChild(a); a.click(); a.remove(); URL.revokeObjectURL(url); } function buildHandoutMarkdown(){ return [ '# 前端教学讲义', '', '## 目标', '- 理解 HTML5 语义化结构(header/nav/main/section/footer)。', '- 掌握响应式布局(Grid 与 Flex)与断点设计。', '- 学会表单可访问性与基础校验,了解数据导出。', '', '## 标准化结构示例', '```html', STANDARD_STRUCTURE_HTML.replace(/```/g, '\\`\\`\\`'), '```', '', '## 布局片段(Grid)', '```css', GRID_CSS_SNIPPET, '```', '', '## 布局片段(Flex)', '```css', FLEX_CSS_SNIPPET, '```', '', '## 练习任务', '1. 在 Grid 布局下,调整列间距与卡片样式,使其更符合你的项目风格。', '2. 尝试将 Flex 方案改造为瀑布流或不等高卡片的均衡排列(提示:align-content、order)。', '3. 为作业表单增加更多校验规则(如标题长度、URL格式等),并在提交列表中显示部分字段。', '', '## 无障碍要点', '- 跳转主内容链接与可见焦点。', '- ARIA 属性:aria-live、aria-label、aria-controls、aria-expanded。', '- 表单标签与错误提示可被读屏识别。', '', '## 参考建议', '- 将断点命名与设计系统(Design Tokens)绑定,保持一致性。', '- 代码片段讲解与项目实践相结合,强化吸收。', '', '(本讲义由教学示例页自动生成)' ].join('\n'); } // 以下三段源文件字符串用于“导出代码”按钮生成文件。 // 为了演示的自包含导出功能,它们与当前页面的 HTML/CSS/JS 内容保持一致。 const HTML_SOURCE = `<!doctype html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> <meta name="description" content="前端教学示例页:标准化结构、一键生成、布局切换、响应式断点、作业提交与导出讲义。"> <title>前端教学示例页 · 标准化结构与响应式布局演示</title> <link rel="stylesheet" href="styles.css"> </head> <body> <a class="skip-link" href="#main">跳转到主内容</a> <header class="site-header" role="banner"> <div class="container header-inner"> <a class="brand" href="#" aria-label="网站品牌标识">教学示例页</a> <button id="menuToggle" class="menu-toggle" aria-expanded="false" aria-controls="siteNav">菜单</button> <nav id="siteNav" class="site-nav" aria-label="主导航"> <ul> <li><a href="#hero">简介</a></li> <li><a href="#a11y">无障碍与语义化</a></li> <li><a href="#layout">布局演示</a></li> <li><a href="#codeDoc">代码讲解</a></li> <li><a href="#assignment">作业提交</a></li> <li><a href="#export">导出工具</a></li> </ul> </nav> </div> </header> <main id="main" tabindex="-1"> <section id="hero" class="hero" aria-label="主视觉与快速操作"> <div class="container hero-inner"> <div class="hero-text"> <h1>前端教学示例:结构、布局与交互</h1> <p>一键生成标准化页面结构,演示响应式栅格与断点注释,切换Grid / Flex布局方案,提供代码片段讲解与作业提交/导出工具。</p> <div class="hero-actions"> <button id="generateStructureBtn" class="btn primary">一键生成标准化结构</button> <button id="exportHandoutBtn" class="btn">导出讲义(Markdown)</button> </div> </div> <div class="hero-art" aria-hidden="true"> <svg width="220" height="140" viewBox="0 0 220 140" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="教学示意图"> <rect x="5" y="5" width="210" height="130" rx="10" fill="#E6F0FF" stroke="#2B6CB0" stroke-width="2"/> <rect x="15" y="20" width="190" height="20" rx="4" fill="#CDE2FF"/> <rect x="15" y="50" width="90" height="70" rx="6" fill="#D9F2E6"/> <rect x="115" y="50" width="90" height="70" rx="6" fill="#FFEFD2"/> <text x="110" y="35" text-anchor="middle" font-size="12" fill="#2B6CB0">Nav / Hero / Grid / Footer</text> </svg> </div> </div> <div class="container"> <div id="structurePreview" class="structure-preview" aria-live="polite" aria-atomic="true"></div> </div> </section> <section id="a11y" class="section"> <div class="container"> <h2>无障碍与语义化提示</h2> <ul class="a11y-list"> <li>使用语义化标签:header、nav、main、section、article、footer。</li> <li>为交互控件添加可访问性属性:aria-label、aria-controls、aria-live、aria-expanded。</li> <li>提供“跳转主内容”链接,确保键盘导航与焦点可见。</li> <li>表单使用label显式关联输入框,错误提示与说明文本可被读屏识别。</li> <li>颜色对比充足,状态变化不只依赖颜色;提供可视化焦点样式。</li> </ul> </div> </section> <section id="layout" class="section"> <div class="container"> <div class="section-head"> <h2>响应式布局演示(栅格与断点)</h2> <p>选择不同布局方案并查看代码片段与断点注释。栅格示例在小屏 1 列,中屏 2 列,大屏 3 列。</p> </div> <div class="controls" role="group" aria-label="布局切换控制"> <div class="control-group"> <span class="label">布局方案:</span> <label><input type="radio" name="layoutMode" value="grid" checked> Grid 栅格</label> <label><input type="radio" name="layoutMode" value="flex"> Flex 弹性</label> </div> <div class="control-group"> <label><input type="checkbox" id="showBreakpoints"> 显示断点辅助栏</label> </div> <div class="control-group"> <button id="resetDataBtn" class="btn">重置示例数据</button> </div> </div> <div id="breakpointBar" class="breakpoint-bar" aria-hidden="true"> <div class="container"> <strong>断点参考:</strong> <span>SM ≥ 640px</span> <span>MD ≥ 960px</span> <span>LG ≥ 1200px(容器最大宽度)</span> </div> </div> <div id="layoutWrapper" class="layout-wrapper layout-grid"> <div id="cardContainer" class="cards" aria-live="polite" aria-busy="false"></div> </div> </div> </section> <section id="codeDoc" class="section"> <div class="container"> <div class="section-head"> <h2>代码片段讲解</h2> <p>可复制 HTML / CSS 片段,配套注释,便于课堂讲解与自学复盘。</p> </div> <div class="code-tabs" role="tablist" aria-label="代码片段标签"> <button class="tab-btn active" data-target="htmlSnippet" role="tab" aria-selected="true">HTML片段</button> <button class="tab-btn" data-target="cssSnippet" role="tab" aria-selected="false">CSS片段</button> <button id="copySnippetBtn" class="btn small">复制当前片段</button> </div> <div class="code-panels"> <pre id="htmlSnippet" class="code-block" aria-label="HTML代码片段"><code></code></pre> <pre id="cssSnippet" class="code-block hidden" aria-label="CSS代码片段"><code></code></pre> </div> </div> </section> <section id="assignment" class="section"> <div class="container"> <h2>作业提交表单与评分占位</h2> <form id="assignmentForm" class="form" novalidate aria-labelledby="assignmentTitle"> <div class="form-grid"> <div class="form-item"> <label for="studentName">姓名</label> <input id="studentName" name="studentName" type="text" required placeholder="例如:张三" aria-describedby="nameHelp"> <small id="nameHelp" class="muted">使用真实姓名,便于确认成绩。</small> </div> <div class="form-item"> <label for="studentEmail">邮箱</label> <input id="studentEmail" name="studentEmail" type="email" required placeholder="example@domain.com"> </div> <div class="form-item"> <label for="assignmentTitle">作业标题</label> <input id="assignmentTitle" name="assignmentTitle" type="text" required placeholder="响应式布局练习"> </div> <div class="form-item"> <label for="assignmentLink">作品链接</label> <input id="assignmentLink" name="assignmentLink" type="url" placeholder="https://example.com/demo" aria-describedby="linkHelp"> <small id="linkHelp" class="muted">可填写在线预览地址或仓库链接。</small> </div> <div class="form-item"> <label for="assignmentFile">上传文件(可选)</label> <input id="assignmentFile" name="assignmentFile" type="file" aria-describedby="fileHelp"> <small id="fileHelp" class="muted">本地预览用,不会上传到服务器。</small> </div> <div class="form-item form-item--full"> <label for="assignmentDesc">作业说明</label> <textarea id="assignmentDesc" name="assignmentDesc" rows="4" maxlength="500" placeholder="简要说明你的设计思路与实现细节…" aria-describedby="descCount"></textarea> <small id="descCount" class="muted" aria-live="polite">0 / 500</small> </div> <div class="form-item"> <label><input id="agreePolicy" type="checkbox" required> 我已阅读并同意课堂提交规范</label> </div> </div> <div class="form-actions"> <button type="submit" class="btn primary">提交作业</button> <button type="reset" class="btn">清空表单</button> <button type="button" id="exportFormDataBtn" class="btn">导出表单数据(JSON)</button> </div> <div id="formErrors" class="form-errors" aria-live="assertive"></div> </form> <div class="submissions"> <h3>提交列表(评分占位)</h3> <ul id="submissionList" class="submission-list"></ul> </div> </div> </section> <section id="export" class="section"> <div class="container"> <h2>导出代码与讲义</h2> <p class="muted">可导出当前页面快照(内联CSS/JS),或分别导出HTML/CSS/JS源文件与课堂讲义。</p> <div class="export-actions"> <button id="exportHTMLBtn" class="btn">导出 HTML</button> <button id="exportCSSBtn" class="btn">导出 CSS</button> <button id="exportJSBtn" class="btn">导出 JS</button> <button id="exportSnapshotBtn" class="btn">导出页面快照(自包含)</button> </div> </div> </section> </main> <footer class="site-footer" role="contentinfo"> <div class="container footer-inner"> <p>© 2025 教学示例页。用于教学演示,遵循 Web 标准与中国法律法规。</p> <nav aria-label="页脚导航"><a href="#hero">回到顶部</a></nav> </div> </footer> <div id="announce" class="sr-only" aria-live="polite" aria-atomic="true"></div> <script defer src="script.js"></script> </body> </html>`; const CSS_SOURCE = `/* 此处 CSS 内容与页面 styles.css 一致,详见本项目 CSS块 */\n` + document.querySelector('link[rel="stylesheet"]') ? '' : ''; // 占位(在线快照会内联真实CSS) // 由于当前环境无法直接读取外部CSS文件,这里提供教学占位: // 实际使用时,导出按钮会生成空CSS(请用上方“CSS样式”块内容保存为 styles.css) // 如果您将本页面的 CSS 内联进快照,snapshot 导出中将包含完整样式。 const JS_SOURCE = `/* 此处 JS 内容与页面 script.js 一致,详见本项目 JS块 */\n` + (function(){return ''})(); // 提示:为避免浏览器安全限制,这里不从外部 CSS/JS 文件读取。 // 教学建议:请将“CSS样式”与“JavaScript功能”块分别保存为 styles.css 与 script.js。 // 导出 HTML 按钮会生成一个 index.html,其 <link rel="stylesheet"> 与 <script src> 指向上述文件。 })(); ``` 说明:出于浏览器安全限制,脚本中无法直接读取外部 styles.css/script.js 的内容,因此 JS 中的 CSS_SOURCE/JS_SOURCE使用占位。请使用下方“使用说明”将本页 CSS 和 JS分别保存为文件后,本页的导出按钮即可生成指向这些文件的 HTML;“导出页面快照(自包含)”会将当前页面的 DOM、CSS 与 JS内联打包(在真实运行环境中,可将 CSS_SOURCE/JS_SOURCE替换为真实内容或由构建工具注入)。 --- ## 使用说明 - 开发与运行 1. 新建项目文件夹并创建以下文件: - index.html(使用“HTML代码”块内容) - styles.css(使用“CSS样式”块内容) - script.js(使用“JavaScript功能”块内容) 2. 双击打开 index.html 即可在浏览器中查看,无需任何外部依赖。 - 教学演示流程建议 1. 打开页面后,点击“一键生成标准化结构”,查看标准化HTML结构预览与复制。 2. 在“布局演示”区切换 Grid/Flex,并勾选“显示断点辅助栏”,观察卡片列数变化和断点说明。 3. 在“代码片段讲解”区切换 HTML/CSS片段,点击“复制当前片段”用于课堂讲解。 4. 在“作业提交表单”中填写示例数据并提交,可在下方列表中看到“待评分”占位。 5. 使用“导出工具”导出 HTML/CSS/JS、讲义(Markdown)或页面快照(自包含)。 - 浏览器兼容性 - 现代浏览器(Chrome、Edge、Firefox、Safari)均可正常运行。 - 移动端兼容,窄屏下导航折叠、表单单列显示。 - 无障碍与安全 - 提供可见焦点与ARIA播报,表单有基础校验。 - 不使用任何外部脚本资源或不安全API,避免安全风险。 --- ## 定制建议 - 视觉主题 - 将CSS变量(颜色、圆角、阴影)替换为企业品牌色与设计体系(Design Tokens)。 - 为Hero区加入产品Logo或插画(建议使用内联SVG或本地资源)。 - 布局扩展 - 在Grid方案中引入更复杂的布局,如区域网格(grid-template-areas)与不等列宽。 - 在Flex方案中演示主轴/侧轴对齐、不同顺序(order)与响应式断点组合。 - 交互增强 - 为卡片“查看/收藏”加入真实行为,如打开详情面板或本地存储收藏状态。 - 增加“评分占位”交互组件(仅本地)、提交后可编辑备注与打分(避免实际上传)。 - 教学导出 - 使用构建脚手架(如Vite)在开发时注入CSS/JS源到导出函数,生成完整快照与示例代码包。 - 增加“讲义模版配置”,让教师可自定义章节与练习题目。 - 无障碍深度优化 - 为所有按钮与链接提供更详细的 aria-label。 - 加入颜色对比切换(高对比模式)与字体大小控制,提升可访问性体验。 如需我将导出功能改为打包ZIP或将CSS/JS真实内联到导出快照,请告知您的运行环境与限制(本地/服务器/构建工具),我将提供相应方案。
用它快速搭建MVP展示页与功能说明页,收集报名或反馈,随时调整模块与风格,缩短验证周期并加速市场测试。
无需外包即可生成企业官网与活动落地页,保持品牌视觉一致,快速添加表单与轮播,促成线索收集与转化。
课堂或训练营中一键生成标准化页面,讲解页面结构与响应式布局,布置作业与示例,提高教学效率与学习成效。
将“前端网站全栈生成器”打造成你的即用型网站搭建助理:只需输入网站类型、设计风格与功能需求,即可一次性生成可上线的页面(含HTML、CSS、JavaScript),自动适配移动与桌面端,满足企业官网、活动落地页、作品集与教学演示等场景。核心目标是显著缩短从想法到成品的周期、降低沟通与外包成本、保障代码质量与后续扩展,让用户从首次试用迅速感知效率红利,并通过解锁高级能力实现持续付费。
将模板生成的提示词复制粘贴到您常用的 Chat 应用(如 ChatGPT、Claude 等),即可直接对话使用,无需额外开发。适合个人快速体验和轻量使用场景。
把提示词模板转化为 API,您的程序可任意修改模板参数,通过接口直接调用,轻松实现自动化与批量处理。适合开发者集成与业务系统嵌入。
在 MCP client 中配置对应的 server 地址,让您的 AI 应用自动调用提示词模板。适合高级用户和团队协作,让提示词在不同 AI 工具间无缝衔接。
免费获取高级提示词-优惠即将到期