[{"data":1,"prerenderedAt":1557},["ShallowReactive",2],{"article-/topics/design/website-case-study-page-conversion-architecture-guide":3,"related-design":361,"content-query-1lLxD45Ehq":1303},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"topic":5,"author":11,"tags":12,"image":17,"imageQuery":18,"pexelsPhotoId":19,"pexelsUrl":20,"featured":6,"readingTime":21,"body":22,"_type":355,"_id":356,"_source":357,"_file":358,"_stem":359,"_extension":360},"/topics/design/website-case-study-page-conversion-architecture-guide","design",false,"","案例页怎么做成转化资产：不是展示作品，而是回答客户决策问题","很多网站案例页只展示项目截图，读完后用户仍然无法判断你是否适合自己。本文给出案例页转化架构，帮助团队把案例从作品陈列升级为决策支持页面。","2026-05-27","HTMLPAGE 团队",[13,14,15,16],"网站设计","页面设计","案例页","转化优化","/images/articles/website-case-study-page-conversion-architecture-guide-featured.jpg","case study presentation business strategy laptop",3184170,"https://www.pexels.com/photo/person-in-front-of-his-laptop-3184170/",15,{"type":23,"children":24,"toc":343},"root",[25,33,38,67,74,179,184,190,195,200,206,211,216,222,227,232,238,243,263,268,274,279,284,290,313,319,338],{"type":26,"tag":27,"props":28,"children":29},"element","p",{},[30],{"type":31,"value":32},"text","很多团队很重视案例页，却常得到一个令人尴尬的反馈：页面看起来专业，但咨询并没有明显增加。原因通常不在案例数量，而在案例结构。大多数案例页在做“成果展示”，而用户在看的是“决策验证”。他关心的不是你做得多漂亮，而是你是否解决过和他相似的问题，并且这种结果能否在他的约束下复现。",{"type":26,"tag":27,"props":34,"children":35},{},[36],{"type":31,"value":37},"当案例页只放截图和一段泛化总结，它在视觉上像作品集，在决策上却没有回答核心问题。结果是用户会觉得“你们做过很多项目”，但仍不知道“你们是否适合我”。",{"type":26,"tag":27,"props":39,"children":40},{},[41,43,50,52,58,59,65],{"type":31,"value":42},"可搭配 ",{"type":26,"tag":44,"props":45,"children":47},"a",{"href":46},"/topics/practical-tips/website-trust-evidence-library-operations-guide",[48],{"type":31,"value":49},"网站信任证据库怎么建",{"type":31,"value":51},"、",{"type":26,"tag":44,"props":53,"children":55},{"href":54},"/topics/design/corporate-website-homepage-design-structure-guide",[56],{"type":31,"value":57},"企业官网首页设计怎么做",{"type":31,"value":51},{"type":26,"tag":44,"props":60,"children":62},{"href":61},"/topics/practical-tips/website-lead-quality-diagnosis-marketing-sales-alignment-guide",[63],{"type":31,"value":64},"网站线索质量下降怎么查",{"type":31,"value":66}," 一起看。",{"type":26,"tag":68,"props":69,"children":71},"h2",{"id":70},"先给结论高转化案例页要围绕决策问题组织而不是围绕项目时间线组织",[72],{"type":31,"value":73},"先给结论：高转化案例页要围绕“决策问题”组织，而不是围绕“项目时间线”组织",{"type":26,"tag":75,"props":76,"children":77},"table",{},[78,102],{"type":26,"tag":79,"props":80,"children":81},"thead",{},[82],{"type":26,"tag":83,"props":84,"children":85},"tr",{},[86,92,97],{"type":26,"tag":87,"props":88,"children":89},"th",{},[90],{"type":31,"value":91},"案例页层级",{"type":26,"tag":87,"props":93,"children":94},{},[95],{"type":31,"value":96},"应回答的问题",{"type":26,"tag":87,"props":98,"children":99},{},[100],{"type":31,"value":101},"常见缺口",{"type":26,"tag":103,"props":104,"children":105},"tbody",{},[106,125,143,161],{"type":26,"tag":83,"props":107,"children":108},{},[109,115,120],{"type":26,"tag":110,"props":111,"children":112},"td",{},[113],{"type":31,"value":114},"背景层",{"type":26,"tag":110,"props":116,"children":117},{},[118],{"type":31,"value":119},"客户原始场景与约束是什么",{"type":26,"tag":110,"props":121,"children":122},{},[123],{"type":31,"value":124},"只写行业名，不写约束条件",{"type":26,"tag":83,"props":126,"children":127},{},[128,133,138],{"type":26,"tag":110,"props":129,"children":130},{},[131],{"type":31,"value":132},"过程层",{"type":26,"tag":110,"props":134,"children":135},{},[136],{"type":31,"value":137},"关键决策如何做、为何这样做",{"type":26,"tag":110,"props":139,"children":140},{},[141],{"type":31,"value":142},"只写执行动作，不写判断逻辑",{"type":26,"tag":83,"props":144,"children":145},{},[146,151,156],{"type":26,"tag":110,"props":147,"children":148},{},[149],{"type":31,"value":150},"结果层",{"type":26,"tag":110,"props":152,"children":153},{},[154],{"type":31,"value":155},"结果怎么衡量、边界在哪里",{"type":26,"tag":110,"props":157,"children":158},{},[159],{"type":31,"value":160},"只写漂亮结果，不写适用边界",{"type":26,"tag":83,"props":162,"children":163},{},[164,169,174],{"type":26,"tag":110,"props":165,"children":166},{},[167],{"type":31,"value":168},"迁移层",{"type":26,"tag":110,"props":170,"children":171},{},[172],{"type":31,"value":173},"哪些经验可复制到新客户",{"type":26,"tag":110,"props":175,"children":176},{},[177],{"type":31,"value":178},"没有迁移规则，用户无法自我映射",{"type":26,"tag":27,"props":180,"children":181},{},[182],{"type":31,"value":183},"案例页不是讲故事比赛，而是帮助潜在客户完成风险评估。",{"type":26,"tag":68,"props":185,"children":187},{"id":186},"第一层先写约束不写约束的案例等于无效对照",[188],{"type":31,"value":189},"第一层先写约束，不写约束的案例等于无效对照",{"type":26,"tag":27,"props":191,"children":192},{},[193],{"type":31,"value":194},"很多案例页会把背景写成“某知名企业，进行了数字化升级”。这类描述看似稳妥，实际价值很低。用户需要知道的不是客户名字，而是约束：预算、周期、资源、组织复杂度。没有约束，案例结果就无法被判断是否可复制。",{"type":26,"tag":27,"props":196,"children":197},{},[198],{"type":31,"value":199},"所以案例背景至少要回答：当时面对的核心限制是什么，这个限制为什么关键。",{"type":26,"tag":68,"props":201,"children":203},{"id":202},"第二层要讲关键决策不要只列执行清单",[204],{"type":31,"value":205},"第二层要讲关键决策，不要只列执行清单",{"type":26,"tag":27,"props":207,"children":208},{},[209],{"type":31,"value":210},"案例页常见写法是“我们做了 A、B、C、D”。这种流水账对执行复盘有用，对客户决策帮助有限。客户真正要看的是：为什么选这个路径，而不是另一个路径；关键取舍是什么；当时避开了哪些高风险方案。",{"type":26,"tag":27,"props":212,"children":213},{},[214],{"type":31,"value":215},"你不需要公开全部细节，但至少要给出关键判断点。这样读者才能把你的案例和自己的问题建立映射。",{"type":26,"tag":68,"props":217,"children":219},{"id":218},"结果层要同时写成果和边界",[220],{"type":31,"value":221},"结果层要同时写“成果”和“边界”",{"type":26,"tag":27,"props":223,"children":224},{},[225],{"type":31,"value":226},"很多案例页只写结果数字，容易让人怀疑可信度。更稳的表达是结果 + 条件。例如：在什么周期内、在什么渠道结构下、在什么资源投入下达成了什么指标变化。这样虽然看起来“没那么夸张”，但信任度更高。",{"type":26,"tag":27,"props":228,"children":229},{},[230],{"type":31,"value":231},"结果层最忌讳“只报喜不写边界”。边界写清，才是专业感的来源。",{"type":26,"tag":68,"props":233,"children":235},{"id":234},"最后一层必须给迁移提示帮读者判断我是否适用",[236],{"type":31,"value":237},"最后一层必须给迁移提示，帮读者判断“我是否适用”",{"type":26,"tag":27,"props":239,"children":240},{},[241],{"type":31,"value":242},"案例页常见缺失是结尾没有迁移提示。用户读完后只能感叹“你们很厉害”，却无法判断“我能不能这样做”。建议结尾固定给出适用判断：",{"type":26,"tag":244,"props":245,"children":246},"ul",{},[247,253,258],{"type":26,"tag":248,"props":249,"children":250},"li",{},[251],{"type":31,"value":252},"什么类型客户最适用",{"type":26,"tag":248,"props":254,"children":255},{},[256],{"type":31,"value":257},"什么条件下不建议照搬",{"type":26,"tag":248,"props":259,"children":260},{},[261],{"type":31,"value":262},"如果要试，先从哪一步开始",{"type":26,"tag":27,"props":264,"children":265},{},[266],{"type":31,"value":267},"这一步会显著提升案例页的咨询质量。",{"type":26,"tag":68,"props":269,"children":271},{"id":270},"失败案例案例页访问高但咨询转化长期偏低",[272],{"type":31,"value":273},"失败案例：案例页访问高，但咨询转化长期偏低",{"type":26,"tag":27,"props":275,"children":276},{},[277],{"type":31,"value":278},"某团队案例页访问量长期稳定，页面停留时长也不错，但来自案例页的咨询率一直偏低。复盘后发现案例页内容几乎都在展示成果截图和品牌 logo，没有讲客户约束、关键决策和可迁移条件。读者看完只能确认“你们做过项目”，无法确认“你们能解决我的问题”。",{"type":26,"tag":27,"props":280,"children":281},{},[282],{"type":31,"value":283},"后来他们重构案例模板，增加约束、决策、边界和迁移提示四层结构。两个月后，案例页来源咨询的有效率明显提升。",{"type":26,"tag":68,"props":285,"children":287},{"id":286},"哪些信号说明你的案例页还停留在展示页",[288],{"type":31,"value":289},"哪些信号说明你的案例页还停留在“展示页”",{"type":26,"tag":244,"props":291,"children":292},{},[293,298,303,308],{"type":26,"tag":248,"props":294,"children":295},{},[296],{"type":31,"value":297},"案例内容大量是视觉截图和泛化赞誉",{"type":26,"tag":248,"props":299,"children":300},{},[301],{"type":31,"value":302},"几乎不出现约束条件和关键取舍",{"type":26,"tag":248,"props":304,"children":305},{},[306],{"type":31,"value":307},"结果数据没有时间窗和条件说明",{"type":26,"tag":248,"props":309,"children":310},{},[311],{"type":31,"value":312},"咨询常问“你们有没有做过类似我们这种情况”",{"type":26,"tag":68,"props":314,"children":316},{"id":315},"先做什么先重写-3-篇高价值案例的结构",[317],{"type":31,"value":318},"先做什么：先重写 3 篇高价值案例的结构",{"type":26,"tag":320,"props":321,"children":322},"ol",{},[323,328,333],{"type":26,"tag":248,"props":324,"children":325},{},[326],{"type":31,"value":327},"每篇补齐约束、决策、结果边界、迁移提示四段。",{"type":26,"tag":248,"props":329,"children":330},{},[331],{"type":31,"value":332},"把“我们做了什么”改成“客户如何判断并选择”。",{"type":26,"tag":248,"props":334,"children":335},{},[336],{"type":31,"value":337},"优先替换流量最高的案例页模板，再扩展全站。",{"type":26,"tag":27,"props":339,"children":340},{},[341],{"type":31,"value":342},"案例页真正的价值，不是展示做过多少项目，而是让潜在客户更低风险地做出联系决策。",{"title":7,"searchDepth":344,"depth":344,"links":345},3,[346,348,349,350,351,352,353,354],{"id":70,"depth":347,"text":73},2,{"id":186,"depth":347,"text":189},{"id":202,"depth":347,"text":205},{"id":218,"depth":347,"text":221},{"id":234,"depth":347,"text":237},{"id":270,"depth":347,"text":273},{"id":286,"depth":347,"text":289},{"id":315,"depth":347,"text":318},"markdown","content:topics:design:website-case-study-page-conversion-architecture-guide.md","content","topics/design/website-case-study-page-conversion-architecture-guide.md","topics/design/website-case-study-page-conversion-architecture-guide","md",[362,722,1024],{"_path":363,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":364,"description":365,"keywords":366,"image":372,"author":11,"date":373,"readingTime":374,"topic":5,"body":375,"_type":355,"_id":719,"_source":357,"_file":720,"_stem":721,"_extension":360},"/topics/design/button-component-design","按钮组件设计详解","学习按钮样式、交互状态、无障碍性和最佳实践",[367,368,369,370,371],"按钮设计","Button Component","交互状态","UI 组件","用户体验","/images/topics/button-design.jpg","2025-12-08",18,{"type":23,"children":376,"toc":701},[377,381,386,391,398,411,417,426,432,441,445,451,462,468,477,483,492,497,506,511,522,527,536,541,554,588,599,642,647],{"type":26,"tag":68,"props":378,"children":379},{"id":364},[380],{"type":31,"value":364},{"type":26,"tag":27,"props":382,"children":383},{},[384],{"type":31,"value":385},"按钮是 UI 中最重要的交互元素。优秀的按钮设计能够指导用户行为。",{"type":26,"tag":68,"props":387,"children":389},{"id":388},"按钮类型",[390],{"type":31,"value":388},{"type":26,"tag":392,"props":393,"children":395},"h3",{"id":394},"primary-button主按钮",[396],{"type":31,"value":397},"Primary Button（主按钮）",{"type":26,"tag":399,"props":400,"children":405},"pre",{"className":401,"code":403,"language":404,"meta":7},[402],"language-css",".btn-primary {\n  background-color: #0066cc;\n  color: #ffffff;\n  padding: 12px 24px;\n  border: none;\n  border-radius: 4px;\n  font-weight: 600;\n  font-size: 16px;\n  cursor: pointer;\n  transition: all 0.2s ease;\n}\n\n.btn-primary:hover {\n  background-color: #0052a3;\n  box-shadow: 0 4px 12px rgba(0, 102, 204, 0.2);\n}\n\n.btn-primary:active {\n  background-color: #003d7a;\n  transform: scale(0.98);\n}\n\n.btn-primary:disabled {\n  background-color: #cccccc;\n  cursor: not-allowed;\n  opacity: 0.6;\n}\n","css",[406],{"type":26,"tag":407,"props":408,"children":409},"code",{"__ignoreMap":7},[410],{"type":31,"value":403},{"type":26,"tag":392,"props":412,"children":414},{"id":413},"secondary-button次按钮",[415],{"type":31,"value":416},"Secondary Button（次按钮）",{"type":26,"tag":399,"props":418,"children":421},{"className":419,"code":420,"language":404,"meta":7},[402],".btn-secondary {\n  background-color: transparent;\n  color: #0066cc;\n  border: 2px solid #0066cc;\n  padding: 10px 22px;\n  border-radius: 4px;\n  font-weight: 600;\n  cursor: pointer;\n  transition: all 0.2s;\n}\n\n.btn-secondary:hover {\n  background-color: rgba(0, 102, 204, 0.1);\n}\n\n.btn-secondary:active {\n  background-color: rgba(0, 102, 204, 0.2);\n}\n",[422],{"type":26,"tag":407,"props":423,"children":424},{"__ignoreMap":7},[425],{"type":31,"value":420},{"type":26,"tag":392,"props":427,"children":429},{"id":428},"danger-button危险按钮",[430],{"type":31,"value":431},"Danger Button（危险按钮）",{"type":26,"tag":399,"props":433,"children":436},{"className":434,"code":435,"language":404,"meta":7},[402],".btn-danger {\n  background-color: #cc0000;\n  color: #ffffff;\n  padding: 12px 24px;\n  border-radius: 4px;\n  cursor: pointer;\n  font-weight: 600;\n}\n\n.btn-danger:hover {\n  background-color: #990000;\n  box-shadow: 0 4px 12px rgba(204, 0, 0, 0.2);\n}\n",[437],{"type":26,"tag":407,"props":438,"children":439},{"__ignoreMap":7},[440],{"type":31,"value":435},{"type":26,"tag":68,"props":442,"children":443},{"id":369},[444],{"type":31,"value":369},{"type":26,"tag":392,"props":446,"children":448},{"id":447},"loading-状态",[449],{"type":31,"value":450},"Loading 状态",{"type":26,"tag":399,"props":452,"children":457},{"className":453,"code":455,"language":456,"meta":7},[454],"language-jsx","import { useState } from 'react';\n\nfunction Button({ children, onClick, loading, ...props }) {\n  const [isLoading, setIsLoading] = useState(false);\n  \n  const handleClick = async () => {\n    setIsLoading(true);\n    try {\n      await onClick();\n    } finally {\n      setIsLoading(false);\n    }\n  };\n  \n  return (\n    \u003Cbutton\n      onClick={handleClick}\n      disabled={isLoading || loading}\n      aria-busy={isLoading || loading}\n      {...props}\n    >\n      {isLoading ? (\n        \u003C>\n          \u003Cspan className=\"spinner\" aria-hidden=\"true\">\u003C/span>\n          {children}\n        \u003C/>\n      ) : (\n        children\n      )}\n    \u003C/button>\n  );\n}\n","jsx",[458],{"type":26,"tag":407,"props":459,"children":460},{"__ignoreMap":7},[461],{"type":31,"value":455},{"type":26,"tag":392,"props":463,"children":465},{"id":464},"disabled-状态",[466],{"type":31,"value":467},"Disabled 状态",{"type":26,"tag":399,"props":469,"children":472},{"className":470,"code":471,"language":404,"meta":7},[402],".btn:disabled {\n  opacity: 0.5;\n  cursor: not-allowed;\n  background-color: #cccccc;\n  color: #999999;\n}\n\n/* 禁用状态下隐藏指针光标 */\n.btn:disabled:hover {\n  box-shadow: none;\n  transform: none;\n}\n",[473],{"type":26,"tag":407,"props":474,"children":475},{"__ignoreMap":7},[476],{"type":31,"value":471},{"type":26,"tag":392,"props":478,"children":480},{"id":479},"focus-状态",[481],{"type":31,"value":482},"Focus 状态",{"type":26,"tag":399,"props":484,"children":487},{"className":485,"code":486,"language":404,"meta":7},[402],".btn:focus {\n  outline: none;\n  box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.1),\n              0 0 0 5px #0066cc;\n}\n\n/* 键盘导航焦点 */\n.btn:focus-visible {\n  outline: 2px solid #0066cc;\n  outline-offset: 2px;\n}\n",[488],{"type":26,"tag":407,"props":489,"children":490},{"__ignoreMap":7},[491],{"type":31,"value":486},{"type":26,"tag":68,"props":493,"children":495},{"id":494},"按钮大小",[496],{"type":31,"value":494},{"type":26,"tag":399,"props":498,"children":501},{"className":499,"code":500,"language":404,"meta":7},[402],"/* 小按钮 */\n.btn-sm {\n  padding: 6px 12px;\n  font-size: 12px;\n  min-height: 32px;\n  min-width: 32px;\n}\n\n/* 中等按钮（默认） */\n.btn-md {\n  padding: 12px 24px;\n  font-size: 16px;\n  min-height: 44px;\n  min-width: 44px;\n}\n\n/* 大按钮 */\n.btn-lg {\n  padding: 16px 32px;\n  font-size: 18px;\n  min-height: 56px;\n  min-width: 56px;\n}\n\n/* 全宽按钮 */\n.btn-block {\n  width: 100%;\n  display: block;\n}\n",[502],{"type":26,"tag":407,"props":503,"children":504},{"__ignoreMap":7},[505],{"type":31,"value":500},{"type":26,"tag":68,"props":507,"children":509},{"id":508},"无障碍性",[510],{"type":31,"value":508},{"type":26,"tag":399,"props":512,"children":517},{"className":513,"code":515,"language":516,"meta":7},[514],"language-html","\u003C!-- 语义正确 -->\n\u003Cbutton type=\"submit\" aria-label=\"提交表单\">\n  提交\n\u003C/button>\n\n\u003C!-- 加载状态 -->\n\u003Cbutton aria-busy=\"true\" disabled>\n  \u003Cspan aria-hidden=\"true\" class=\"spinner\">\u003C/span>\n  加载中...\n\u003C/button>\n\n\u003C!-- 图标按钮 -->\n\u003Cbutton aria-label=\"关闭\">\n  \u003Csvg aria-hidden=\"true\" width=\"24\" height=\"24\">\n    \u003Cline x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n    \u003Cline x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n  \u003C/svg>\n\u003C/button>\n\n\u003C!-- 切换按钮 -->\n\u003Cbutton aria-pressed=\"false\" aria-label=\"点赞\">\n  ♥\n\u003C/button>\n","html",[518],{"type":26,"tag":407,"props":519,"children":520},{"__ignoreMap":7},[521],{"type":31,"value":515},{"type":26,"tag":68,"props":523,"children":525},{"id":524},"完整组件示例",[526],{"type":31,"value":524},{"type":26,"tag":399,"props":528,"children":531},{"className":529,"code":530,"language":456,"meta":7},[454],"const Button = React.forwardRef((\n  {\n    children,\n    variant = 'primary',\n    size = 'md',\n    loading = false,\n    disabled = false,\n    icon,\n    className,\n    ...props\n  },\n  ref\n) => {\n  return (\n    \u003Cbutton\n      ref={ref}\n      className={`btn btn-${variant} btn-${size} ${className}`}\n      disabled={disabled || loading}\n      aria-busy={loading}\n      {...props}\n    >\n      {icon && \u003Cspan className=\"btn-icon\" aria-hidden=\"true\">{icon}\u003C/span>}\n      {loading ? (\n        \u003C>\n          \u003Cspan className=\"spinner\" aria-hidden=\"true\">\u003C/span>\n          {children}\n        \u003C/>\n      ) : (\n        children\n      )}\n    \u003C/button>\n  );\n});\n\nButton.displayName = 'Button';\n",[532],{"type":26,"tag":407,"props":533,"children":534},{"__ignoreMap":7},[535],{"type":31,"value":530},{"type":26,"tag":68,"props":537,"children":539},{"id":538},"最佳实践",[540],{"type":31,"value":538},{"type":26,"tag":27,"props":542,"children":543},{},[544,546,552],{"type":31,"value":545},"✅ ",{"type":26,"tag":547,"props":548,"children":549},"strong",{},[550],{"type":31,"value":551},"应该做的事",{"type":31,"value":553},":",{"type":26,"tag":244,"props":555,"children":556},{},[557,562,567,578,583],{"type":26,"tag":248,"props":558,"children":559},{},[560],{"type":31,"value":561},"最小触摸目标 44x44px",{"type":26,"tag":248,"props":563,"children":564},{},[565],{"type":31,"value":566},"清晰的视觉反馈",{"type":26,"tag":248,"props":568,"children":569},{},[570,572],{"type":31,"value":571},"使用语义 HTML ",{"type":26,"tag":407,"props":573,"children":575},{"className":574},[],[576],{"type":31,"value":577},"\u003Cbutton>",{"type":26,"tag":248,"props":579,"children":580},{},[581],{"type":31,"value":582},"提供加载状态反馈",{"type":26,"tag":248,"props":584,"children":585},{},[586],{"type":31,"value":587},"支持键盘导航",{"type":26,"tag":27,"props":589,"children":590},{},[591,593,598],{"type":31,"value":592},"❌ ",{"type":26,"tag":547,"props":594,"children":595},{},[596],{"type":31,"value":597},"不应该做的事",{"type":31,"value":553},{"type":26,"tag":244,"props":600,"children":601},{},[602,615,620,625,630],{"type":26,"tag":248,"props":603,"children":604},{},[605,607,613],{"type":31,"value":606},"使用 ",{"type":26,"tag":407,"props":608,"children":610},{"className":609},[],[611],{"type":31,"value":612},"\u003Cdiv>",{"type":31,"value":614}," 模拟按钮",{"type":26,"tag":248,"props":616,"children":617},{},[618],{"type":31,"value":619},"隐藏焦点指示器",{"type":26,"tag":248,"props":621,"children":622},{},[623],{"type":31,"value":624},"过多的按钮样式",{"type":26,"tag":248,"props":626,"children":627},{},[628],{"type":31,"value":629},"忽视禁用状态",{"type":26,"tag":248,"props":631,"children":632},{},[633,634,640],{"type":31,"value":606},{"type":26,"tag":407,"props":635,"children":637},{"className":636},[],[638],{"type":31,"value":639},"\u003Ca>",{"type":31,"value":641}," 代替按钮",{"type":26,"tag":68,"props":643,"children":645},{"id":644},"测试清单",[646],{"type":31,"value":644},{"type":26,"tag":244,"props":648,"children":651},{"className":649},[650],"contains-task-list",[652,665,674,683,692],{"type":26,"tag":248,"props":653,"children":656},{"className":654},[655],"task-list-item",[657,663],{"type":26,"tag":658,"props":659,"children":662},"input",{"disabled":660,"type":661},true,"checkbox",[],{"type":31,"value":664}," 在各种浏览器中测试",{"type":26,"tag":248,"props":666,"children":668},{"className":667},[655],[669,672],{"type":26,"tag":658,"props":670,"children":671},{"disabled":660,"type":661},[],{"type":31,"value":673}," 验证键盘导航",{"type":26,"tag":248,"props":675,"children":677},{"className":676},[655],[678,681],{"type":26,"tag":658,"props":679,"children":680},{"disabled":660,"type":661},[],{"type":31,"value":682}," 检查色彩对比度",{"type":26,"tag":248,"props":684,"children":686},{"className":685},[655],[687,690],{"type":26,"tag":658,"props":688,"children":689},{"disabled":660,"type":661},[],{"type":31,"value":691}," 测试触摸设备",{"type":26,"tag":248,"props":693,"children":695},{"className":694},[655],[696,699],{"type":26,"tag":658,"props":697,"children":698},{"disabled":660,"type":661},[],{"type":31,"value":700}," 屏幕阅读器兼容性",{"title":7,"searchDepth":344,"depth":344,"links":702},[703,704,709,714,715,716,717,718],{"id":364,"depth":347,"text":364},{"id":388,"depth":347,"text":388,"children":705},[706,707,708],{"id":394,"depth":344,"text":397},{"id":413,"depth":344,"text":416},{"id":428,"depth":344,"text":431},{"id":369,"depth":347,"text":369,"children":710},[711,712,713],{"id":447,"depth":344,"text":450},{"id":464,"depth":344,"text":467},{"id":479,"depth":344,"text":482},{"id":494,"depth":347,"text":494},{"id":508,"depth":347,"text":508},{"id":524,"depth":347,"text":524},{"id":538,"depth":347,"text":538},{"id":644,"depth":347,"text":644},"content:topics:design:button-component-design.md","topics/design/button-component-design.md","topics/design/button-component-design",{"_path":723,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":724,"description":725,"keywords":726,"image":731,"author":11,"date":373,"readingTime":732,"topic":5,"body":733,"_type":355,"_id":1021,"_source":357,"_file":1022,"_stem":1023,"_extension":360},"/topics/design/dark-mode-design","暗黑模式设计完整方案","学习暗黑模式实现、色彩方案、对比度管理和最佳实践",[727,728,729,730,371],"暗黑模式","Dark Mode","色彩系统","CSS 变量","/images/topics/dark-mode-design.jpg",20,{"type":23,"children":734,"toc":1004},[735,739,744,749,755,764,770,779,784,790,799,805,816,822,831,836,845,850,859,864,873,877,886,914,923,951,955],{"type":26,"tag":68,"props":736,"children":737},{"id":724},[738],{"type":31,"value":724},{"type":26,"tag":27,"props":740,"children":741},{},[742],{"type":31,"value":743},"暗黑模式已成为现代应用的标准功能。它能够减少眼睛疲劳、节省电池、改善用户体验。",{"type":26,"tag":68,"props":745,"children":747},{"id":746},"核心色彩系统",[748],{"type":31,"value":746},{"type":26,"tag":392,"props":750,"children":752},{"id":751},"light-mode-配色",[753],{"type":31,"value":754},"Light Mode 配色",{"type":26,"tag":399,"props":756,"children":759},{"className":757,"code":758,"language":404,"meta":7},[402],":root {\n  /* Light Mode */\n  --bg-primary: #ffffff;\n  --bg-secondary: #f5f5f5;\n  --bg-tertiary: #efefef;\n  \n  --text-primary: #1a1a1a;\n  --text-secondary: #666666;\n  --text-tertiary: #999999;\n  \n  --border-color: #e0e0e0;\n  --divider-color: #f0f0f0;\n}\n",[760],{"type":26,"tag":407,"props":761,"children":762},{"__ignoreMap":7},[763],{"type":31,"value":758},{"type":26,"tag":392,"props":765,"children":767},{"id":766},"dark-mode-配色",[768],{"type":31,"value":769},"Dark Mode 配色",{"type":26,"tag":399,"props":771,"children":774},{"className":772,"code":773,"language":404,"meta":7},[402],"@media (prefers-color-scheme: dark) {\n  :root {\n    /* Dark Mode */\n    --bg-primary: #1a1a1a;\n    --bg-secondary: #2d2d2d;\n    --bg-tertiary: #3a3a3a;\n    \n    --text-primary: #ffffff;\n    --text-secondary: #e0e0e0;\n    --text-tertiary: #a0a0a0;\n    \n    --border-color: #404040;\n    --divider-color: #2a2a2a;\n  }\n}\n",[775],{"type":26,"tag":407,"props":776,"children":777},{"__ignoreMap":7},[778],{"type":31,"value":773},{"type":26,"tag":68,"props":780,"children":782},{"id":781},"实现方案",[783],{"type":31,"value":781},{"type":26,"tag":392,"props":785,"children":787},{"id":786},"方案-1prefers-color-scheme",[788],{"type":31,"value":789},"方案 1：prefers-color-scheme",{"type":26,"tag":399,"props":791,"children":794},{"className":792,"code":793,"language":404,"meta":7},[402],"/* 自动跟随系统设置 */\n@media (prefers-color-scheme: light) {\n  :root {\n    --bg: #fff;\n    --text: #000;\n  }\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n    --bg: #1a1a1a;\n    --text: #fff;\n  }\n}\n\nbody {\n  background: var(--bg);\n  color: var(--text);\n}\n",[795],{"type":26,"tag":407,"props":796,"children":797},{"__ignoreMap":7},[798],{"type":31,"value":793},{"type":26,"tag":392,"props":800,"children":802},{"id":801},"方案-2javascript-切换",[803],{"type":31,"value":804},"方案 2：JavaScript 切换",{"type":26,"tag":399,"props":806,"children":811},{"className":807,"code":809,"language":810,"meta":7},[808],"language-javascript","// 检测和切换暗黑模式\nfunction initDarkMode() {\n  const isDark = localStorage.getItem('darkMode') === 'true' ||\n                 window.matchMedia('(prefers-color-scheme: dark)').matches;\n  \n  if (isDark) {\n    document.documentElement.setAttribute('data-theme', 'dark');\n  }\n}\n\nfunction toggleDarkMode() {\n  const isDark = document.documentElement.getAttribute('data-theme') === 'dark';\n  const newTheme = isDark ? 'light' : 'dark';\n  \n  document.documentElement.setAttribute('data-theme', newTheme);\n  localStorage.setItem('darkMode', newTheme === 'dark');\n}\n\n// CSS 应用\nhtml[data-theme='light'] {\n  color-scheme: light;\n}\n\nhtml[data-theme='dark'] {\n  color-scheme: dark;\n}\n","javascript",[812],{"type":26,"tag":407,"props":813,"children":814},{"__ignoreMap":7},[815],{"type":31,"value":809},{"type":26,"tag":392,"props":817,"children":819},{"id":818},"方案-3css-variables-javascript",[820],{"type":31,"value":821},"方案 3：CSS Variables + JavaScript",{"type":26,"tag":399,"props":823,"children":826},{"className":824,"code":825,"language":810,"meta":7},[808],"const themes = {\n  light: {\n    '--bg-primary': '#ffffff',\n    '--text-primary': '#000000',\n    '--accent': '#0066cc',\n    '--border': '#e0e0e0',\n  },\n  dark: {\n    '--bg-primary': '#1a1a1a',\n    '--text-primary': '#ffffff',\n    '--accent': '#4da3ff',\n    '--border': '#404040',\n  },\n};\n\nfunction applyTheme(themeName) {\n  const theme = themes[themeName];\n  Object.entries(theme).forEach(([key, value]) => {\n    document.documentElement.style.setProperty(key, value);\n  });\n  localStorage.setItem('theme', themeName);\n}\n",[827],{"type":26,"tag":407,"props":828,"children":829},{"__ignoreMap":7},[830],{"type":31,"value":825},{"type":26,"tag":68,"props":832,"children":834},{"id":833},"对比度管理",[835],{"type":31,"value":833},{"type":26,"tag":399,"props":837,"children":840},{"className":838,"code":839,"language":404,"meta":7},[402],"/* Light Mode 对比度 */\n:root {\n  --contrast-high: #000000;     /* 21:1 */\n  --contrast-medium: #333333;   /* 12.6:1 */\n  --contrast-low: #666666;      /* 5.1:1 */\n}\n\n/* Dark Mode 对比度 */\n@media (prefers-color-scheme: dark) {\n  :root {\n    --contrast-high: #ffffff;    /* 21:1 */\n    --contrast-medium: #e0e0e0;  /* 11.6:1 */\n    --contrast-low: #a0a0a0;     /* 4.5:1 */\n  }\n}\n\n/* 应用对比度 */\n.text-primary { color: var(--contrast-high); }\n.text-secondary { color: var(--contrast-medium); }\n.text-tertiary { color: var(--contrast-low); }\n",[841],{"type":26,"tag":407,"props":842,"children":843},{"__ignoreMap":7},[844],{"type":31,"value":839},{"type":26,"tag":68,"props":846,"children":848},{"id":847},"图片和图表处理",[849],{"type":31,"value":847},{"type":26,"tag":399,"props":851,"children":854},{"className":852,"code":853,"language":516,"meta":7},[514],"\u003C!-- 针对不同主题的图片 -->\n\u003Cpicture>\n  \u003Csource \n    media=\"(prefers-color-scheme: dark)\" \n    srcset=\"chart-dark.svg\"\n  />\n  \u003Cimg src=\"chart-light.svg\" alt=\"图表\" />\n\u003C/picture>\n\n\u003C!-- SVG 颜色适配 -->\n\u003Csvg class=\"icon\">\n  \u003Ccircle cx=\"50\" cy=\"50\" r=\"40\" fill=\"currentColor\" />\n\u003C/svg>\n\n\u003Cstyle>\n  .icon {\n    color: var(--text-primary);\n  }\n\u003C/style>\n",[855],{"type":26,"tag":407,"props":856,"children":857},{"__ignoreMap":7},[858],{"type":31,"value":853},{"type":26,"tag":68,"props":860,"children":862},{"id":861},"完整示例",[863],{"type":31,"value":861},{"type":26,"tag":399,"props":865,"children":868},{"className":866,"code":867,"language":456,"meta":7},[454],"import { useState, useEffect } from 'react';\n\nfunction ThemeProvider({ children }) {\n  const [theme, setTheme] = useState('light');\n  const [mounted, setMounted] = useState(false);\n  \n  useEffect(() => {\n    setMounted(true);\n    \n    // 获取保存的主题或系统偏好\n    const savedTheme = localStorage.getItem('theme');\n    const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches \n      ? 'dark' \n      : 'light';\n    \n    const initialTheme = savedTheme || systemTheme;\n    setTheme(initialTheme);\n    document.documentElement.setAttribute('data-theme', initialTheme);\n  }, []);\n  \n  const toggleTheme = () => {\n    const newTheme = theme === 'light' ? 'dark' : 'light';\n    setTheme(newTheme);\n    localStorage.setItem('theme', newTheme);\n    document.documentElement.setAttribute('data-theme', newTheme);\n  };\n  \n  // 防止闪烁\n  if (!mounted) {\n    return null;\n  }\n  \n  return (\n    \u003CThemeContext.Provider value={{ theme, toggleTheme }}>\n      {children}\n      \u003CThemeToggle theme={theme} onChange={toggleTheme} />\n    \u003C/ThemeContext.Provider>\n  );\n}\n\nfunction ThemeToggle({ theme, onChange }) {\n  return (\n    \u003Cbutton \n      onClick={onChange}\n      aria-label={`切换到${theme === 'light' ? '暗黑' : '亮色'}模式`}\n    >\n      {theme === 'light' ? '🌙' : '☀️'}\n    \u003C/button>\n  );\n}\n",[869],{"type":26,"tag":407,"props":870,"children":871},{"__ignoreMap":7},[872],{"type":31,"value":867},{"type":26,"tag":68,"props":874,"children":875},{"id":538},[876],{"type":31,"value":538},{"type":26,"tag":27,"props":878,"children":879},{},[880,881,885],{"type":31,"value":545},{"type":26,"tag":547,"props":882,"children":883},{},[884],{"type":31,"value":551},{"type":31,"value":553},{"type":26,"tag":244,"props":887,"children":888},{},[889,894,899,904,909],{"type":26,"tag":248,"props":890,"children":891},{},[892],{"type":31,"value":893},"支持系统偏好",{"type":26,"tag":248,"props":895,"children":896},{},[897],{"type":31,"value":898},"提供手动切换选项",{"type":26,"tag":248,"props":900,"children":901},{},[902],{"type":31,"value":903},"确保足够的对比度",{"type":26,"tag":248,"props":905,"children":906},{},[907],{"type":31,"value":908},"优化图片和图表",{"type":26,"tag":248,"props":910,"children":911},{},[912],{"type":31,"value":913},"防止加载闪烁",{"type":26,"tag":27,"props":915,"children":916},{},[917,918,922],{"type":31,"value":592},{"type":26,"tag":547,"props":919,"children":920},{},[921],{"type":31,"value":597},{"type":31,"value":553},{"type":26,"tag":244,"props":924,"children":925},{},[926,931,936,941,946],{"type":26,"tag":248,"props":927,"children":928},{},[929],{"type":31,"value":930},"强制单一模式",{"type":26,"tag":248,"props":932,"children":933},{},[934],{"type":31,"value":935},"忽视性能影响",{"type":26,"tag":248,"props":937,"children":938},{},[939],{"type":31,"value":940},"使用相同的颜色",{"type":26,"tag":248,"props":942,"children":943},{},[944],{"type":31,"value":945},"忘记保存用户偏好",{"type":26,"tag":248,"props":947,"children":948},{},[949],{"type":31,"value":950},"过度使用深色背景",{"type":26,"tag":68,"props":952,"children":953},{"id":644},[954],{"type":31,"value":644},{"type":26,"tag":244,"props":956,"children":958},{"className":957},[650],[959,968,977,986,995],{"type":26,"tag":248,"props":960,"children":962},{"className":961},[655],[963,966],{"type":26,"tag":658,"props":964,"children":965},{"disabled":660,"type":661},[],{"type":31,"value":967}," 在浅色和深色模式下测试所有页面",{"type":26,"tag":248,"props":969,"children":971},{"className":970},[655],[972,975],{"type":26,"tag":658,"props":973,"children":974},{"disabled":660,"type":661},[],{"type":31,"value":976}," 检查颜色对比度符合 WCAG 标准",{"type":26,"tag":248,"props":978,"children":980},{"className":979},[655],[981,984],{"type":26,"tag":658,"props":982,"children":983},{"disabled":660,"type":661},[],{"type":31,"value":985}," 验证图片和图表在两种模式下清晰",{"type":26,"tag":248,"props":987,"children":989},{"className":988},[655],[990,993],{"type":26,"tag":658,"props":991,"children":992},{"disabled":660,"type":661},[],{"type":31,"value":994}," 测试主题切换的平滑性",{"type":26,"tag":248,"props":996,"children":998},{"className":997},[655],[999,1002],{"type":26,"tag":658,"props":1000,"children":1001},{"disabled":660,"type":661},[],{"type":31,"value":1003}," 检查用户偏好是否被保存",{"title":7,"searchDepth":344,"depth":344,"links":1005},[1006,1007,1011,1016,1017,1018,1019,1020],{"id":724,"depth":347,"text":724},{"id":746,"depth":347,"text":746,"children":1008},[1009,1010],{"id":751,"depth":344,"text":754},{"id":766,"depth":344,"text":769},{"id":781,"depth":347,"text":781,"children":1012},[1013,1014,1015],{"id":786,"depth":344,"text":789},{"id":801,"depth":344,"text":804},{"id":818,"depth":344,"text":821},{"id":833,"depth":347,"text":833},{"id":847,"depth":347,"text":847},{"id":861,"depth":347,"text":861},{"id":538,"depth":347,"text":538},{"id":644,"depth":347,"text":644},"content:topics:design:dark-mode-design.md","topics/design/dark-mode-design.md","topics/design/dark-mode-design",{"_path":1025,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":1026,"description":1027,"keywords":1028,"image":1033,"author":1034,"date":373,"readingTime":732,"topic":5,"body":1035,"_type":355,"_id":1300,"_source":357,"_file":1301,"_stem":1302,"_extension":360},"/topics/design/form-controls-design","表单控件设计规范","学习输入框、选择框、复选框等表单控件的设计和实现",[1029,1030,1031,1032,371],"表单设计","Form Controls","输入框","验证反馈","/images/topics/form-controls-design.jpg","AI Content Team",{"type":23,"children":1036,"toc":1286},[1037,1041,1046,1051,1056,1065,1070,1079,1083,1092,1097,1106,1111,1120,1125,1134,1139,1148,1152,1161,1187,1196,1224,1228],{"type":26,"tag":68,"props":1038,"children":1039},{"id":1026},[1040],{"type":31,"value":1026},{"type":26,"tag":27,"props":1042,"children":1043},{},[1044],{"type":31,"value":1045},"优秀的表单设计能够提高用户完成率和满意度。",{"type":26,"tag":68,"props":1047,"children":1049},{"id":1048},"输入框设计",[1050],{"type":31,"value":1048},{"type":26,"tag":392,"props":1052,"children":1054},{"id":1053},"基础文本输入",[1055],{"type":31,"value":1053},{"type":26,"tag":399,"props":1057,"children":1060},{"className":1058,"code":1059,"language":404,"meta":7},[402],".input {\n  width: 100%;\n  padding: 12px 16px;\n  font-size: 16px;\n  border: 2px solid #e0e0e0;\n  border-radius: 4px;\n  font-family: inherit;\n  transition: border-color 0.2s;\n}\n\n.input:hover {\n  border-color: #bdbdbd;\n}\n\n.input:focus {\n  outline: none;\n  border-color: #0066cc;\n  box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.1);\n}\n\n.input:disabled {\n  background-color: #f5f5f5;\n  color: #999999;\n  cursor: not-allowed;\n}\n\n.input.error {\n  border-color: #cc0000;\n}\n\n.input.success {\n  border-color: #00cc00;\n}\n",[1061],{"type":26,"tag":407,"props":1062,"children":1063},{"__ignoreMap":7},[1064],{"type":31,"value":1059},{"type":26,"tag":392,"props":1066,"children":1068},{"id":1067},"标签和提示",[1069],{"type":31,"value":1067},{"type":26,"tag":399,"props":1071,"children":1074},{"className":1072,"code":1073,"language":516,"meta":7},[514],"\u003Cdiv class=\"form-group\">\n  \u003Clabel for=\"email\" class=\"form-label\">\n    邮箱地址 \u003Cspan class=\"required\">*\u003C/span>\n  \u003C/label>\n  \u003Cinput\n    id=\"email\"\n    type=\"email\"\n    placeholder=\"user@example.com\"\n    class=\"input\"\n    aria-describedby=\"email-hint\"\n  />\n  \u003Cp id=\"email-hint\" class=\"form-hint\">\n    我们永远不会分享你的邮箱\n  \u003C/p>\n\u003C/div>\n",[1075],{"type":26,"tag":407,"props":1076,"children":1077},{"__ignoreMap":7},[1078],{"type":31,"value":1073},{"type":26,"tag":68,"props":1080,"children":1081},{"id":1032},[1082],{"type":31,"value":1032},{"type":26,"tag":399,"props":1084,"children":1087},{"className":1085,"code":1086,"language":456,"meta":7},[454],"function FormInput({ label, error, success, helperText, value, onChange, ...props }) {\n  return (\n    \u003Cdiv className=\"form-group\">\n      \u003Clabel className=\"form-label\">{label}\u003C/label>\n      \u003Cinput\n        className={`input ${\n          error ? 'error' : success ? 'success' : ''\n        }`}\n        value={value}\n        onChange={onChange}\n        {...props}\n      />\n      {error && (\n        \u003Cp className=\"form-error\" role=\"alert\">\n          {error}\n        \u003C/p>\n      )}\n      {success && (\n        \u003Cp className=\"form-success\">\n          ✓ {success}\n        \u003C/p>\n      )}\n      {helperText && (\n        \u003Cp className=\"form-hint\">{helperText}\u003C/p>\n      )}\n    \u003C/div>\n  );\n}\n",[1088],{"type":26,"tag":407,"props":1089,"children":1090},{"__ignoreMap":7},[1091],{"type":31,"value":1086},{"type":26,"tag":68,"props":1093,"children":1095},{"id":1094},"选择框设计",[1096],{"type":31,"value":1094},{"type":26,"tag":399,"props":1098,"children":1101},{"className":1099,"code":1100,"language":404,"meta":7},[402],".select {\n  appearance: none;\n  width: 100%;\n  padding: 12px 16px;\n  border: 2px solid #e0e0e0;\n  border-radius: 4px;\n  background-image: url('data:image/svg+xml;...');\n  background-repeat: no-repeat;\n  background-position: right 12px center;\n  padding-right: 40px;\n  font-size: 16px;\n  cursor: pointer;\n}\n\n.select:hover {\n  border-color: #bdbdbd;\n}\n\n.select:focus {\n  outline: none;\n  border-color: #0066cc;\n  box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.1);\n}\n",[1102],{"type":26,"tag":407,"props":1103,"children":1104},{"__ignoreMap":7},[1105],{"type":31,"value":1100},{"type":26,"tag":68,"props":1107,"children":1109},{"id":1108},"复选框和单选按钮",[1110],{"type":31,"value":1108},{"type":26,"tag":399,"props":1112,"children":1115},{"className":1113,"code":1114,"language":404,"meta":7},[402],".checkbox-group {\n  display: flex;\n  gap: 12px;\n  align-items: center;\n}\n\n.checkbox-input {\n  width: 20px;\n  height: 20px;\n  cursor: pointer;\n  accent-color: #0066cc;\n}\n\n.checkbox-label {\n  cursor: pointer;\n  user-select: none;\n}\n\n/* 自定义复选框 */\n.custom-checkbox {\n  appearance: none;\n  width: 20px;\n  height: 20px;\n  border: 2px solid #e0e0e0;\n  border-radius: 4px;\n  cursor: pointer;\n  background-color: white;\n  transition: all 0.2s;\n}\n\n.custom-checkbox:checked {\n  background-color: #0066cc;\n  border-color: #0066cc;\n  background-image: url('data:image/svg+xml;...');\n}\n\n.custom-checkbox:focus {\n  box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.1);\n}\n",[1116],{"type":26,"tag":407,"props":1117,"children":1118},{"__ignoreMap":7},[1119],{"type":31,"value":1114},{"type":26,"tag":68,"props":1121,"children":1123},{"id":1122},"文本区域",[1124],{"type":31,"value":1122},{"type":26,"tag":399,"props":1126,"children":1129},{"className":1127,"code":1128,"language":404,"meta":7},[402],".textarea {\n  width: 100%;\n  min-height: 120px;\n  padding: 12px 16px;\n  border: 2px solid #e0e0e0;\n  border-radius: 4px;\n  font-family: inherit;\n  font-size: 16px;\n  resize: vertical;\n  transition: border-color 0.2s;\n}\n\n.textarea:focus {\n  outline: none;\n  border-color: #0066cc;\n  box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.1);\n}\n",[1130],{"type":26,"tag":407,"props":1131,"children":1132},{"__ignoreMap":7},[1133],{"type":31,"value":1128},{"type":26,"tag":68,"props":1135,"children":1137},{"id":1136},"完整表单示例",[1138],{"type":31,"value":1136},{"type":26,"tag":399,"props":1140,"children":1143},{"className":1141,"code":1142,"language":456,"meta":7},[454],"function SignupForm() {\n  const [formData, setFormData] = useState({\n    name: '',\n    email: '',\n    password: '',\n    confirmPassword: '',\n    subscribe: false,\n    terms: false,\n  });\n  \n  const [errors, setErrors] = useState({});\n  const [touched, setTouched] = useState({});\n  const [submitted, setSubmitted] = useState(false);\n  \n  const handleChange = (e) => {\n    const { name, value, type, checked } = e.target;\n    setFormData(prev => ({\n      ...prev,\n      [name]: type === 'checkbox' ? checked : value,\n    }));\n    \n    // 实时验证\n    if (touched[name]) {\n      validateField(name, type === 'checkbox' ? checked : value);\n    }\n  };\n  \n  const handleBlur = (e) => {\n    const { name } = e.target;\n    setTouched(prev => ({ ...prev, [name]: true }));\n    validateField(name, formData[name]);\n  };\n  \n  const validateField = (name, value) => {\n    const newErrors = { ...errors };\n    \n    switch (name) {\n      case 'name':\n        if (!value) newErrors.name = '名字不能为空';\n        else delete newErrors.name;\n        break;\n      case 'email':\n        if (!value) newErrors.email = '邮箱不能为空';\n        else if (!/^[^\\\\s@]+@[^\\\\s@]+\\\\.[^\\\\s@]+$/.test(value)) {\n          newErrors.email = '请输入有效的邮箱';\n        } else {\n          delete newErrors.email;\n        }\n        break;\n      case 'password':\n        if (!value) newErrors.password = '密码不能为空';\n        else if (value.length \u003C 8) newErrors.password = '密码至少 8 位';\n        else delete newErrors.password;\n        break;\n      case 'confirmPassword':\n        if (value !== formData.password) {\n          newErrors.confirmPassword = '两次密码输入不一致';\n        } else {\n          delete newErrors.confirmPassword;\n        }\n        break;\n      case 'terms':\n        if (!value) newErrors.terms = '必须同意服务条款';\n        else delete newErrors.terms;\n        break;\n      default:\n        break;\n    }\n    \n    setErrors(newErrors);\n  };\n  \n  const validate = () => {\n    const newErrors = {};\n    \n    if (!formData.name) newErrors.name = '名字不能为空';\n    if (!formData.email) newErrors.email = '邮箱不能为空';\n    if (formData.password.length \u003C 8) newErrors.password = '密码至少 8 位';\n    if (formData.password !== formData.confirmPassword) {\n      newErrors.confirmPassword = '两次密码输入不一致';\n    }\n    if (!formData.terms) newErrors.terms = '必须同意服务条款';\n    \n    return newErrors;\n  };\n  \n  const handleSubmit = async (e) => {\n    e.preventDefault();\n    \n    // 标记所有字段已触碰\n    setTouched({\n      name: true,\n      email: true,\n      password: true,\n      confirmPassword: true,\n      terms: true,\n    });\n    \n    const newErrors = validate();\n    \n    if (Object.keys(newErrors).length === 0) {\n      setSubmitted(true);\n      // 提交表单\n      console.log('Form submitted:', formData);\n      // 重置表单\n      setFormData({\n        name: '',\n        email: '',\n        password: '',\n        confirmPassword: '',\n        subscribe: false,\n        terms: false,\n      });\n    } else {\n      setErrors(newErrors);\n    }\n  };\n  \n  return (\n    \u003Cform onSubmit={handleSubmit} noValidate>\n      {submitted && (\n        \u003Cdiv className=\"form-success-message\" role=\"alert\">\n          注册成功！\n        \u003C/div>\n      )}\n      \n      \u003CFormInput\n        label=\"姓名\"\n        name=\"name\"\n        value={formData.name}\n        onChange={handleChange}\n        onBlur={handleBlur}\n        error={touched.name && errors.name}\n        helperText=\"请输入你的全名\"\n      />\n      \n      \u003CFormInput\n        label=\"邮箱\"\n        name=\"email\"\n        type=\"email\"\n        value={formData.email}\n        onChange={handleChange}\n        onBlur={handleBlur}\n        error={touched.email && errors.email}\n      />\n      \n      \u003CFormInput\n        label=\"密码\"\n        name=\"password\"\n        type=\"password\"\n        value={formData.password}\n        onChange={handleChange}\n        onBlur={handleBlur}\n        error={touched.password && errors.password}\n        helperText=\"至少 8 个字符\"\n      />\n      \n      \u003CFormInput\n        label=\"确认密码\"\n        name=\"confirmPassword\"\n        type=\"password\"\n        value={formData.confirmPassword}\n        onChange={handleChange}\n        onBlur={handleBlur}\n        error={touched.confirmPassword && errors.confirmPassword}\n      />\n      \n      \u003Cdiv className=\"form-group\">\n        \u003Clabel className=\"checkbox-label\">\n          \u003Cinput\n            type=\"checkbox\"\n            name=\"subscribe\"\n            checked={formData.subscribe}\n            onChange={handleChange}\n            className=\"checkbox-input\"\n          />\n          订阅我们的新闻通讯\n        \u003C/label>\n      \u003C/div>\n      \n      \u003Cdiv className=\"form-group\">\n        \u003Clabel className=\"checkbox-label\">\n          \u003Cinput\n            type=\"checkbox\"\n            name=\"terms\"\n            checked={formData.terms}\n            onChange={handleChange}\n            onBlur={handleBlur}\n            className=\"checkbox-input\"\n          />\n          我同意\n          \u003Ca href=\"/terms\" target=\"_blank\" rel=\"noopener noreferrer\">\n            服务条款\n          \u003C/a>\n          和\n          \u003Ca href=\"/privacy\" target=\"_blank\" rel=\"noopener noreferrer\">\n            隐私政策\n          \u003C/a>\n        \u003C/label>\n        {touched.terms && errors.terms && (\n          \u003Cp className=\"form-error\">{errors.terms}\u003C/p>\n        )}\n      \u003C/div>\n      \n      \u003Cbutton type=\"submit\" className=\"btn btn-primary btn-block\">\n        注册\n      \u003C/button>\n    \u003C/form>\n  );\n}\n",[1144],{"type":26,"tag":407,"props":1145,"children":1146},{"__ignoreMap":7},[1147],{"type":31,"value":1142},{"type":26,"tag":68,"props":1149,"children":1150},{"id":538},[1151],{"type":31,"value":538},{"type":26,"tag":27,"props":1153,"children":1154},{},[1155,1156,1160],{"type":31,"value":545},{"type":26,"tag":547,"props":1157,"children":1158},{},[1159],{"type":31,"value":551},{"type":31,"value":553},{"type":26,"tag":244,"props":1162,"children":1163},{},[1164,1169,1174,1179,1183],{"type":26,"tag":248,"props":1165,"children":1166},{},[1167],{"type":31,"value":1168},"使用正确的输入类型",{"type":26,"tag":248,"props":1170,"children":1171},{},[1172],{"type":31,"value":1173},"提供实时验证反馈",{"type":26,"tag":248,"props":1175,"children":1176},{},[1177],{"type":31,"value":1178},"清晰的标签和提示",{"type":26,"tag":248,"props":1180,"children":1181},{},[1182],{"type":31,"value":561},{"type":26,"tag":248,"props":1184,"children":1185},{},[1186],{"type":31,"value":587},{"type":26,"tag":27,"props":1188,"children":1189},{},[1190,1191,1195],{"type":31,"value":592},{"type":26,"tag":547,"props":1192,"children":1193},{},[1194],{"type":31,"value":597},{"type":31,"value":553},{"type":26,"tag":244,"props":1197,"children":1198},{},[1199,1204,1209,1214,1219],{"type":26,"tag":248,"props":1200,"children":1201},{},[1202],{"type":31,"value":1203},"隐藏标签",{"type":26,"tag":248,"props":1205,"children":1206},{},[1207],{"type":31,"value":1208},"过度使用占位符",{"type":26,"tag":248,"props":1210,"children":1211},{},[1212],{"type":31,"value":1213},"验证后立即提交",{"type":26,"tag":248,"props":1215,"children":1216},{},[1217],{"type":31,"value":1218},"忽视无障碍性",{"type":26,"tag":248,"props":1220,"children":1221},{},[1222],{"type":31,"value":1223},"复杂的验证规则",{"type":26,"tag":68,"props":1225,"children":1226},{"id":644},[1227],{"type":31,"value":644},{"type":26,"tag":244,"props":1229,"children":1231},{"className":1230},[650],[1232,1241,1250,1259,1268,1277],{"type":26,"tag":248,"props":1233,"children":1235},{"className":1234},[655],[1236,1239],{"type":26,"tag":658,"props":1237,"children":1238},{"disabled":660,"type":661},[],{"type":31,"value":1240}," 所有控件都可用键盘导航",{"type":26,"tag":248,"props":1242,"children":1244},{"className":1243},[655],[1245,1248],{"type":26,"tag":658,"props":1246,"children":1247},{"disabled":660,"type":661},[],{"type":31,"value":1249}," 标签与输入框关联",{"type":26,"tag":248,"props":1251,"children":1253},{"className":1252},[655],[1254,1257],{"type":26,"tag":658,"props":1255,"children":1256},{"disabled":660,"type":661},[],{"type":31,"value":1258}," 验证消息清晰",{"type":26,"tag":248,"props":1260,"children":1262},{"className":1261},[655],[1263,1266],{"type":26,"tag":658,"props":1264,"children":1265},{"disabled":660,"type":661},[],{"type":31,"value":1267}," 色彩对比度足够",{"type":26,"tag":248,"props":1269,"children":1271},{"className":1270},[655],[1272,1275],{"type":26,"tag":658,"props":1273,"children":1274},{"disabled":660,"type":661},[],{"type":31,"value":1276}," 屏幕阅读器兼容",{"type":26,"tag":248,"props":1278,"children":1280},{"className":1279},[655],[1281,1284],{"type":26,"tag":658,"props":1282,"children":1283},{"disabled":660,"type":661},[],{"type":31,"value":1285}," 移动设备测试",{"title":7,"searchDepth":344,"depth":344,"links":1287},[1288,1289,1293,1294,1295,1296,1297,1298,1299],{"id":1026,"depth":347,"text":1026},{"id":1048,"depth":347,"text":1048,"children":1290},[1291,1292],{"id":1053,"depth":344,"text":1053},{"id":1067,"depth":344,"text":1067},{"id":1032,"depth":347,"text":1032},{"id":1094,"depth":347,"text":1094},{"id":1108,"depth":347,"text":1108},{"id":1122,"depth":347,"text":1122},{"id":1136,"depth":347,"text":1136},{"id":538,"depth":347,"text":538},{"id":644,"depth":347,"text":644},"content:topics:design:form-controls-design.md","topics/design/form-controls-design.md","topics/design/form-controls-design",{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"topic":5,"author":11,"tags":1304,"image":17,"imageQuery":18,"pexelsPhotoId":19,"pexelsUrl":20,"featured":6,"readingTime":21,"body":1305,"_type":355,"_id":356,"_source":357,"_file":358,"_stem":359,"_extension":360},[13,14,15,16],{"type":23,"children":1306,"toc":1547},[1307,1311,1315,1334,1338,1422,1426,1430,1434,1438,1442,1446,1450,1454,1458,1462,1466,1470,1485,1489,1493,1497,1501,1505,1524,1528,1543],{"type":26,"tag":27,"props":1308,"children":1309},{},[1310],{"type":31,"value":32},{"type":26,"tag":27,"props":1312,"children":1313},{},[1314],{"type":31,"value":37},{"type":26,"tag":27,"props":1316,"children":1317},{},[1318,1319,1323,1324,1328,1329,1333],{"type":31,"value":42},{"type":26,"tag":44,"props":1320,"children":1321},{"href":46},[1322],{"type":31,"value":49},{"type":31,"value":51},{"type":26,"tag":44,"props":1325,"children":1326},{"href":54},[1327],{"type":31,"value":57},{"type":31,"value":51},{"type":26,"tag":44,"props":1330,"children":1331},{"href":61},[1332],{"type":31,"value":64},{"type":31,"value":66},{"type":26,"tag":68,"props":1335,"children":1336},{"id":70},[1337],{"type":31,"value":73},{"type":26,"tag":75,"props":1339,"children":1340},{},[1341,1359],{"type":26,"tag":79,"props":1342,"children":1343},{},[1344],{"type":26,"tag":83,"props":1345,"children":1346},{},[1347,1351,1355],{"type":26,"tag":87,"props":1348,"children":1349},{},[1350],{"type":31,"value":91},{"type":26,"tag":87,"props":1352,"children":1353},{},[1354],{"type":31,"value":96},{"type":26,"tag":87,"props":1356,"children":1357},{},[1358],{"type":31,"value":101},{"type":26,"tag":103,"props":1360,"children":1361},{},[1362,1377,1392,1407],{"type":26,"tag":83,"props":1363,"children":1364},{},[1365,1369,1373],{"type":26,"tag":110,"props":1366,"children":1367},{},[1368],{"type":31,"value":114},{"type":26,"tag":110,"props":1370,"children":1371},{},[1372],{"type":31,"value":119},{"type":26,"tag":110,"props":1374,"children":1375},{},[1376],{"type":31,"value":124},{"type":26,"tag":83,"props":1378,"children":1379},{},[1380,1384,1388],{"type":26,"tag":110,"props":1381,"children":1382},{},[1383],{"type":31,"value":132},{"type":26,"tag":110,"props":1385,"children":1386},{},[1387],{"type":31,"value":137},{"type":26,"tag":110,"props":1389,"children":1390},{},[1391],{"type":31,"value":142},{"type":26,"tag":83,"props":1393,"children":1394},{},[1395,1399,1403],{"type":26,"tag":110,"props":1396,"children":1397},{},[1398],{"type":31,"value":150},{"type":26,"tag":110,"props":1400,"children":1401},{},[1402],{"type":31,"value":155},{"type":26,"tag":110,"props":1404,"children":1405},{},[1406],{"type":31,"value":160},{"type":26,"tag":83,"props":1408,"children":1409},{},[1410,1414,1418],{"type":26,"tag":110,"props":1411,"children":1412},{},[1413],{"type":31,"value":168},{"type":26,"tag":110,"props":1415,"children":1416},{},[1417],{"type":31,"value":173},{"type":26,"tag":110,"props":1419,"children":1420},{},[1421],{"type":31,"value":178},{"type":26,"tag":27,"props":1423,"children":1424},{},[1425],{"type":31,"value":183},{"type":26,"tag":68,"props":1427,"children":1428},{"id":186},[1429],{"type":31,"value":189},{"type":26,"tag":27,"props":1431,"children":1432},{},[1433],{"type":31,"value":194},{"type":26,"tag":27,"props":1435,"children":1436},{},[1437],{"type":31,"value":199},{"type":26,"tag":68,"props":1439,"children":1440},{"id":202},[1441],{"type":31,"value":205},{"type":26,"tag":27,"props":1443,"children":1444},{},[1445],{"type":31,"value":210},{"type":26,"tag":27,"props":1447,"children":1448},{},[1449],{"type":31,"value":215},{"type":26,"tag":68,"props":1451,"children":1452},{"id":218},[1453],{"type":31,"value":221},{"type":26,"tag":27,"props":1455,"children":1456},{},[1457],{"type":31,"value":226},{"type":26,"tag":27,"props":1459,"children":1460},{},[1461],{"type":31,"value":231},{"type":26,"tag":68,"props":1463,"children":1464},{"id":234},[1465],{"type":31,"value":237},{"type":26,"tag":27,"props":1467,"children":1468},{},[1469],{"type":31,"value":242},{"type":26,"tag":244,"props":1471,"children":1472},{},[1473,1477,1481],{"type":26,"tag":248,"props":1474,"children":1475},{},[1476],{"type":31,"value":252},{"type":26,"tag":248,"props":1478,"children":1479},{},[1480],{"type":31,"value":257},{"type":26,"tag":248,"props":1482,"children":1483},{},[1484],{"type":31,"value":262},{"type":26,"tag":27,"props":1486,"children":1487},{},[1488],{"type":31,"value":267},{"type":26,"tag":68,"props":1490,"children":1491},{"id":270},[1492],{"type":31,"value":273},{"type":26,"tag":27,"props":1494,"children":1495},{},[1496],{"type":31,"value":278},{"type":26,"tag":27,"props":1498,"children":1499},{},[1500],{"type":31,"value":283},{"type":26,"tag":68,"props":1502,"children":1503},{"id":286},[1504],{"type":31,"value":289},{"type":26,"tag":244,"props":1506,"children":1507},{},[1508,1512,1516,1520],{"type":26,"tag":248,"props":1509,"children":1510},{},[1511],{"type":31,"value":297},{"type":26,"tag":248,"props":1513,"children":1514},{},[1515],{"type":31,"value":302},{"type":26,"tag":248,"props":1517,"children":1518},{},[1519],{"type":31,"value":307},{"type":26,"tag":248,"props":1521,"children":1522},{},[1523],{"type":31,"value":312},{"type":26,"tag":68,"props":1525,"children":1526},{"id":315},[1527],{"type":31,"value":318},{"type":26,"tag":320,"props":1529,"children":1530},{},[1531,1535,1539],{"type":26,"tag":248,"props":1532,"children":1533},{},[1534],{"type":31,"value":327},{"type":26,"tag":248,"props":1536,"children":1537},{},[1538],{"type":31,"value":332},{"type":26,"tag":248,"props":1540,"children":1541},{},[1542],{"type":31,"value":337},{"type":26,"tag":27,"props":1544,"children":1545},{},[1546],{"type":31,"value":342},{"title":7,"searchDepth":344,"depth":344,"links":1548},[1549,1550,1551,1552,1553,1554,1555,1556],{"id":70,"depth":347,"text":73},{"id":186,"depth":347,"text":189},{"id":202,"depth":347,"text":205},{"id":218,"depth":347,"text":221},{"id":234,"depth":347,"text":237},{"id":270,"depth":347,"text":273},{"id":286,"depth":347,"text":289},{"id":315,"depth":347,"text":318},1779842376127]