[{"data":1,"prerenderedAt":1566},["ShallowReactive",2],{"article-/topics/design/conversion-proof-modules-trust-evidence-page-design":3,"related-design":366,"content-query-j6DoUzLezF":1308},{"_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":360,"_id":361,"_source":362,"_file":363,"_stem":364,"_extension":365},"/topics/design/conversion-proof-modules-trust-evidence-page-design","design",false,"","高转化页面的证据模块怎么设计：别只讲卖点，要让用户看到可验证的依据","很多页面转化低，不是卖点不够多，而是缺少可验证证据。本文从页面设计角度拆解案例、数据、对比和风险说明四类证据模块，帮助团队把“看起来不错”变成“值得信任”。","2026-05-25","HTMLPAGE 团队",[13,14,15,16],"网页设计","转化优化","信任设计","页面结构","/images/articles/conversion-proof-modules-trust-evidence-page-design-featured.jpg","website analytics conversion evidence dashboard laptop",3183145,"https://www.pexels.com/photo/photo-of-person-using-laptop-3183145/",14,{"type":23,"children":24,"toc":348},"root",[25,33,38,67,74,179,185,190,195,201,206,211,217,222,227,247,252,258,263,268,274,279,284,290,313,318,324,343],{"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/design/web-design-layout-visual-hierarchy-practical-guide",[48],{"type":31,"value":49},"网页设计布局与视觉层级实战",{"type":31,"value":51},"、",{"type":26,"tag":44,"props":53,"children":55},{"href":54},"/topics/practical-tips/website-design-acceptance-visual-responsive-seo-guide",[56],{"type":31,"value":57},"网站设计验收怎么做",{"type":31,"value":51},{"type":26,"tag":44,"props":60,"children":62},{"href":61},"/topics/practical-tips/website-post-launch-7-day-data-review",[63],{"type":31,"value":64},"网页上线后 7 天数据观察",{"type":31,"value":66}," 一起使用。",{"type":26,"tag":68,"props":69,"children":71},"h2",{"id":70},"先给结论高价值页面至少要有-4-类证据",[72],{"type":31,"value":73},"先给结论：高价值页面至少要有 4 类证据",{"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},"只放 logo，不给具体场景",{"type":26,"tag":68,"props":180,"children":182},{"id":181},"结果证据先讲在什么条件下达到什么结果",[183],{"type":31,"value":184},"结果证据：先讲“在什么条件下达到什么结果”",{"type":26,"tag":27,"props":186,"children":187},{},[188],{"type":31,"value":189},"很多页面会写“转化提升 300%”“效率提升 10 倍”。这种数字很吸引人，但也最容易被怀疑。因为用户知道结果受场景影响，不会盲信绝对值。",{"type":26,"tag":27,"props":191,"children":192},{},[193],{"type":31,"value":194},"更可信的写法是同时给出条件：行业类型、时间周期、基线状态、改动范围。你不需要透露敏感数据，但要让用户理解结果发生的上下文。",{"type":26,"tag":68,"props":196,"children":198},{"id":197},"过程证据把黑盒承诺拆成可理解步骤",[199],{"type":31,"value":200},"过程证据：把黑盒承诺拆成可理解步骤",{"type":26,"tag":27,"props":202,"children":203},{},[204],{"type":31,"value":205},"“我们有一套成熟方法”这类话通常没有说服力。页面应至少给出最小过程框架，让用户知道合作后会经历什么。比如：诊断、方案、执行、验证四段流程，每段输出什么。",{"type":26,"tag":27,"props":207,"children":208},{},[209],{"type":31,"value":210},"过程证据的价值是降低不确定性。用户不一定现在就买，但他会判断“这个团队做事是否可控”。",{"type":26,"tag":68,"props":212,"children":214},{"id":213},"风险证据主动写边界反而更能建立信任",[215],{"type":31,"value":216},"风险证据：主动写边界，反而更能建立信任",{"type":26,"tag":27,"props":218,"children":219},{},[220],{"type":31,"value":221},"很多团队怕写风险会影响转化，结果把页面写成无条件承诺。高意向用户反而会因此降低信任，因为现实项目没有零风险。",{"type":26,"tag":27,"props":223,"children":224},{},[225],{"type":31,"value":226},"更成熟的做法是写清三类边界：",{"type":26,"tag":228,"props":229,"children":230},"ul",{},[231,237,242],{"type":26,"tag":232,"props":233,"children":234},"li",{},[235],{"type":31,"value":236},"不适用场景",{"type":26,"tag":232,"props":238,"children":239},{},[240],{"type":31,"value":241},"可能失败的前置条件",{"type":26,"tag":232,"props":243,"children":244},{},[245],{"type":31,"value":246},"失败后的应对动作",{"type":26,"tag":27,"props":248,"children":249},{},[250],{"type":31,"value":251},"当你愿意公开边界，用户会更容易相信你的成功案例不是筛选出来的幸存者偏差。",{"type":26,"tag":68,"props":253,"children":255},{"id":254},"社会证据logo-墙不是证据链场景才是",[256],{"type":31,"value":257},"社会证据：Logo 墙不是证据链，场景才是",{"type":26,"tag":27,"props":259,"children":260},{},[261],{"type":31,"value":262},"很多页面喜欢堆 logo 墙，但没有任何上下文。用户看到 logo 只能知道“你合作过”，却不知道“你解决了什么”。",{"type":26,"tag":27,"props":264,"children":265},{},[266],{"type":31,"value":267},"更有用的社会证据是“小场景证明”：客户初始问题、采用方案、结果变化。即使每个案例只写 80 到 120 字，也比纯 logo 有价值。",{"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},"某团队做产品着陆页时，首屏和功能区写得非常饱满：高效、稳定、专业、可扩展。设计也很精致，但咨询率长期在低位。后续复盘发现页面几乎没有证据模块，只有一段泛化客户评价和几个大词。用户看完知道“你很厉害”，却不知道“你在我的场景里是否靠谱”。",{"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":228,"props":291,"children":292},{},[293,298,303,308],{"type":26,"tag":232,"props":294,"children":295},{},[296],{"type":31,"value":297},"页面停留时间不低，但 CTA 点击率低",{"type":26,"tag":232,"props":299,"children":300},{},[301],{"type":31,"value":302},"用户常问“你们有做过类似项目吗”",{"type":26,"tag":232,"props":304,"children":305},{},[306],{"type":31,"value":307},"销售沟通中重复解释同一类风险问题",{"type":26,"tag":232,"props":309,"children":310},{},[311],{"type":31,"value":312},"A/B 测试里换标题无明显提升",{"type":26,"tag":27,"props":314,"children":315},{},[316],{"type":31,"value":317},"这些信号说明，问题不在“看不看得见”，而在“信不信得过”。",{"type":26,"tag":68,"props":319,"children":321},{"id":320},"下一步动作先做一版最小证据链",[322],{"type":31,"value":323},"下一步动作：先做一版最小证据链",{"type":26,"tag":325,"props":326,"children":327},"ol",{},[328,333,338],{"type":26,"tag":232,"props":329,"children":330},{},[331],{"type":31,"value":332},"为当前页面补一个结果证据和一个过程证据。",{"type":26,"tag":232,"props":334,"children":335},{},[336],{"type":31,"value":337},"增加一段风险边界说明，减少过度承诺。",{"type":26,"tag":232,"props":339,"children":340},{},[341],{"type":31,"value":342},"把 logo 墙升级为 2 到 3 个场景化案例卡片。",{"type":26,"tag":27,"props":344,"children":345},{},[346],{"type":31,"value":347},"转化页面的关键不是说服所有人，而是帮助真正有需求的人更快完成信任判断。证据模块设计好，页面才会从“好看”走向“可信”。",{"title":7,"searchDepth":349,"depth":349,"links":350},3,[351,353,354,355,356,357,358,359],{"id":70,"depth":352,"text":73},2,{"id":181,"depth":352,"text":184},{"id":197,"depth":352,"text":200},{"id":213,"depth":352,"text":216},{"id":254,"depth":352,"text":257},{"id":270,"depth":352,"text":273},{"id":286,"depth":352,"text":289},{"id":320,"depth":352,"text":323},"markdown","content:topics:design:conversion-proof-modules-trust-evidence-page-design.md","content","topics/design/conversion-proof-modules-trust-evidence-page-design.md","topics/design/conversion-proof-modules-trust-evidence-page-design","md",[367,727,1029],{"_path":368,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":369,"description":370,"keywords":371,"image":377,"author":11,"date":378,"readingTime":379,"topic":5,"body":380,"_type":360,"_id":724,"_source":362,"_file":725,"_stem":726,"_extension":365},"/topics/design/button-component-design","按钮组件设计详解","学习按钮样式、交互状态、无障碍性和最佳实践",[372,373,374,375,376],"按钮设计","Button Component","交互状态","UI 组件","用户体验","/images/topics/button-design.jpg","2025-12-08",18,{"type":23,"children":381,"toc":706},[382,386,391,396,403,416,422,431,437,446,450,456,467,473,482,488,497,502,511,516,527,532,541,546,559,593,604,647,652],{"type":26,"tag":68,"props":383,"children":384},{"id":369},[385],{"type":31,"value":369},{"type":26,"tag":27,"props":387,"children":388},{},[389],{"type":31,"value":390},"按钮是 UI 中最重要的交互元素。优秀的按钮设计能够指导用户行为。",{"type":26,"tag":68,"props":392,"children":394},{"id":393},"按钮类型",[395],{"type":31,"value":393},{"type":26,"tag":397,"props":398,"children":400},"h3",{"id":399},"primary-button主按钮",[401],{"type":31,"value":402},"Primary Button（主按钮）",{"type":26,"tag":404,"props":405,"children":410},"pre",{"className":406,"code":408,"language":409,"meta":7},[407],"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",[411],{"type":26,"tag":412,"props":413,"children":414},"code",{"__ignoreMap":7},[415],{"type":31,"value":408},{"type":26,"tag":397,"props":417,"children":419},{"id":418},"secondary-button次按钮",[420],{"type":31,"value":421},"Secondary Button（次按钮）",{"type":26,"tag":404,"props":423,"children":426},{"className":424,"code":425,"language":409,"meta":7},[407],".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",[427],{"type":26,"tag":412,"props":428,"children":429},{"__ignoreMap":7},[430],{"type":31,"value":425},{"type":26,"tag":397,"props":432,"children":434},{"id":433},"danger-button危险按钮",[435],{"type":31,"value":436},"Danger Button（危险按钮）",{"type":26,"tag":404,"props":438,"children":441},{"className":439,"code":440,"language":409,"meta":7},[407],".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",[442],{"type":26,"tag":412,"props":443,"children":444},{"__ignoreMap":7},[445],{"type":31,"value":440},{"type":26,"tag":68,"props":447,"children":448},{"id":374},[449],{"type":31,"value":374},{"type":26,"tag":397,"props":451,"children":453},{"id":452},"loading-状态",[454],{"type":31,"value":455},"Loading 状态",{"type":26,"tag":404,"props":457,"children":462},{"className":458,"code":460,"language":461,"meta":7},[459],"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",[463],{"type":26,"tag":412,"props":464,"children":465},{"__ignoreMap":7},[466],{"type":31,"value":460},{"type":26,"tag":397,"props":468,"children":470},{"id":469},"disabled-状态",[471],{"type":31,"value":472},"Disabled 状态",{"type":26,"tag":404,"props":474,"children":477},{"className":475,"code":476,"language":409,"meta":7},[407],".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",[478],{"type":26,"tag":412,"props":479,"children":480},{"__ignoreMap":7},[481],{"type":31,"value":476},{"type":26,"tag":397,"props":483,"children":485},{"id":484},"focus-状态",[486],{"type":31,"value":487},"Focus 状态",{"type":26,"tag":404,"props":489,"children":492},{"className":490,"code":491,"language":409,"meta":7},[407],".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",[493],{"type":26,"tag":412,"props":494,"children":495},{"__ignoreMap":7},[496],{"type":31,"value":491},{"type":26,"tag":68,"props":498,"children":500},{"id":499},"按钮大小",[501],{"type":31,"value":499},{"type":26,"tag":404,"props":503,"children":506},{"className":504,"code":505,"language":409,"meta":7},[407],"/* 小按钮 */\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",[507],{"type":26,"tag":412,"props":508,"children":509},{"__ignoreMap":7},[510],{"type":31,"value":505},{"type":26,"tag":68,"props":512,"children":514},{"id":513},"无障碍性",[515],{"type":31,"value":513},{"type":26,"tag":404,"props":517,"children":522},{"className":518,"code":520,"language":521,"meta":7},[519],"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",[523],{"type":26,"tag":412,"props":524,"children":525},{"__ignoreMap":7},[526],{"type":31,"value":520},{"type":26,"tag":68,"props":528,"children":530},{"id":529},"完整组件示例",[531],{"type":31,"value":529},{"type":26,"tag":404,"props":533,"children":536},{"className":534,"code":535,"language":461,"meta":7},[459],"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",[537],{"type":26,"tag":412,"props":538,"children":539},{"__ignoreMap":7},[540],{"type":31,"value":535},{"type":26,"tag":68,"props":542,"children":544},{"id":543},"最佳实践",[545],{"type":31,"value":543},{"type":26,"tag":27,"props":547,"children":548},{},[549,551,557],{"type":31,"value":550},"✅ ",{"type":26,"tag":552,"props":553,"children":554},"strong",{},[555],{"type":31,"value":556},"应该做的事",{"type":31,"value":558},":",{"type":26,"tag":228,"props":560,"children":561},{},[562,567,572,583,588],{"type":26,"tag":232,"props":563,"children":564},{},[565],{"type":31,"value":566},"最小触摸目标 44x44px",{"type":26,"tag":232,"props":568,"children":569},{},[570],{"type":31,"value":571},"清晰的视觉反馈",{"type":26,"tag":232,"props":573,"children":574},{},[575,577],{"type":31,"value":576},"使用语义 HTML ",{"type":26,"tag":412,"props":578,"children":580},{"className":579},[],[581],{"type":31,"value":582},"\u003Cbutton>",{"type":26,"tag":232,"props":584,"children":585},{},[586],{"type":31,"value":587},"提供加载状态反馈",{"type":26,"tag":232,"props":589,"children":590},{},[591],{"type":31,"value":592},"支持键盘导航",{"type":26,"tag":27,"props":594,"children":595},{},[596,598,603],{"type":31,"value":597},"❌ ",{"type":26,"tag":552,"props":599,"children":600},{},[601],{"type":31,"value":602},"不应该做的事",{"type":31,"value":558},{"type":26,"tag":228,"props":605,"children":606},{},[607,620,625,630,635],{"type":26,"tag":232,"props":608,"children":609},{},[610,612,618],{"type":31,"value":611},"使用 ",{"type":26,"tag":412,"props":613,"children":615},{"className":614},[],[616],{"type":31,"value":617},"\u003Cdiv>",{"type":31,"value":619}," 模拟按钮",{"type":26,"tag":232,"props":621,"children":622},{},[623],{"type":31,"value":624},"隐藏焦点指示器",{"type":26,"tag":232,"props":626,"children":627},{},[628],{"type":31,"value":629},"过多的按钮样式",{"type":26,"tag":232,"props":631,"children":632},{},[633],{"type":31,"value":634},"忽视禁用状态",{"type":26,"tag":232,"props":636,"children":637},{},[638,639,645],{"type":31,"value":611},{"type":26,"tag":412,"props":640,"children":642},{"className":641},[],[643],{"type":31,"value":644},"\u003Ca>",{"type":31,"value":646}," 代替按钮",{"type":26,"tag":68,"props":648,"children":650},{"id":649},"测试清单",[651],{"type":31,"value":649},{"type":26,"tag":228,"props":653,"children":656},{"className":654},[655],"contains-task-list",[657,670,679,688,697],{"type":26,"tag":232,"props":658,"children":661},{"className":659},[660],"task-list-item",[662,668],{"type":26,"tag":663,"props":664,"children":667},"input",{"disabled":665,"type":666},true,"checkbox",[],{"type":31,"value":669}," 在各种浏览器中测试",{"type":26,"tag":232,"props":671,"children":673},{"className":672},[660],[674,677],{"type":26,"tag":663,"props":675,"children":676},{"disabled":665,"type":666},[],{"type":31,"value":678}," 验证键盘导航",{"type":26,"tag":232,"props":680,"children":682},{"className":681},[660],[683,686],{"type":26,"tag":663,"props":684,"children":685},{"disabled":665,"type":666},[],{"type":31,"value":687}," 检查色彩对比度",{"type":26,"tag":232,"props":689,"children":691},{"className":690},[660],[692,695],{"type":26,"tag":663,"props":693,"children":694},{"disabled":665,"type":666},[],{"type":31,"value":696}," 测试触摸设备",{"type":26,"tag":232,"props":698,"children":700},{"className":699},[660],[701,704],{"type":26,"tag":663,"props":702,"children":703},{"disabled":665,"type":666},[],{"type":31,"value":705}," 屏幕阅读器兼容性",{"title":7,"searchDepth":349,"depth":349,"links":707},[708,709,714,719,720,721,722,723],{"id":369,"depth":352,"text":369},{"id":393,"depth":352,"text":393,"children":710},[711,712,713],{"id":399,"depth":349,"text":402},{"id":418,"depth":349,"text":421},{"id":433,"depth":349,"text":436},{"id":374,"depth":352,"text":374,"children":715},[716,717,718],{"id":452,"depth":349,"text":455},{"id":469,"depth":349,"text":472},{"id":484,"depth":349,"text":487},{"id":499,"depth":352,"text":499},{"id":513,"depth":352,"text":513},{"id":529,"depth":352,"text":529},{"id":543,"depth":352,"text":543},{"id":649,"depth":352,"text":649},"content:topics:design:button-component-design.md","topics/design/button-component-design.md","topics/design/button-component-design",{"_path":728,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":729,"description":730,"keywords":731,"image":736,"author":11,"date":378,"readingTime":737,"topic":5,"body":738,"_type":360,"_id":1026,"_source":362,"_file":1027,"_stem":1028,"_extension":365},"/topics/design/dark-mode-design","暗黑模式设计完整方案","学习暗黑模式实现、色彩方案、对比度管理和最佳实践",[732,733,734,735,376],"暗黑模式","Dark Mode","色彩系统","CSS 变量","/images/topics/dark-mode-design.jpg",20,{"type":23,"children":739,"toc":1009},[740,744,749,754,760,769,775,784,789,795,804,810,821,827,836,841,850,855,864,869,878,882,891,919,928,956,960],{"type":26,"tag":68,"props":741,"children":742},{"id":729},[743],{"type":31,"value":729},{"type":26,"tag":27,"props":745,"children":746},{},[747],{"type":31,"value":748},"暗黑模式已成为现代应用的标准功能。它能够减少眼睛疲劳、节省电池、改善用户体验。",{"type":26,"tag":68,"props":750,"children":752},{"id":751},"核心色彩系统",[753],{"type":31,"value":751},{"type":26,"tag":397,"props":755,"children":757},{"id":756},"light-mode-配色",[758],{"type":31,"value":759},"Light Mode 配色",{"type":26,"tag":404,"props":761,"children":764},{"className":762,"code":763,"language":409,"meta":7},[407],":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",[765],{"type":26,"tag":412,"props":766,"children":767},{"__ignoreMap":7},[768],{"type":31,"value":763},{"type":26,"tag":397,"props":770,"children":772},{"id":771},"dark-mode-配色",[773],{"type":31,"value":774},"Dark Mode 配色",{"type":26,"tag":404,"props":776,"children":779},{"className":777,"code":778,"language":409,"meta":7},[407],"@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",[780],{"type":26,"tag":412,"props":781,"children":782},{"__ignoreMap":7},[783],{"type":31,"value":778},{"type":26,"tag":68,"props":785,"children":787},{"id":786},"实现方案",[788],{"type":31,"value":786},{"type":26,"tag":397,"props":790,"children":792},{"id":791},"方案-1prefers-color-scheme",[793],{"type":31,"value":794},"方案 1：prefers-color-scheme",{"type":26,"tag":404,"props":796,"children":799},{"className":797,"code":798,"language":409,"meta":7},[407],"/* 自动跟随系统设置 */\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",[800],{"type":26,"tag":412,"props":801,"children":802},{"__ignoreMap":7},[803],{"type":31,"value":798},{"type":26,"tag":397,"props":805,"children":807},{"id":806},"方案-2javascript-切换",[808],{"type":31,"value":809},"方案 2：JavaScript 切换",{"type":26,"tag":404,"props":811,"children":816},{"className":812,"code":814,"language":815,"meta":7},[813],"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",[817],{"type":26,"tag":412,"props":818,"children":819},{"__ignoreMap":7},[820],{"type":31,"value":814},{"type":26,"tag":397,"props":822,"children":824},{"id":823},"方案-3css-variables-javascript",[825],{"type":31,"value":826},"方案 3：CSS Variables + JavaScript",{"type":26,"tag":404,"props":828,"children":831},{"className":829,"code":830,"language":815,"meta":7},[813],"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",[832],{"type":26,"tag":412,"props":833,"children":834},{"__ignoreMap":7},[835],{"type":31,"value":830},{"type":26,"tag":68,"props":837,"children":839},{"id":838},"对比度管理",[840],{"type":31,"value":838},{"type":26,"tag":404,"props":842,"children":845},{"className":843,"code":844,"language":409,"meta":7},[407],"/* 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",[846],{"type":26,"tag":412,"props":847,"children":848},{"__ignoreMap":7},[849],{"type":31,"value":844},{"type":26,"tag":68,"props":851,"children":853},{"id":852},"图片和图表处理",[854],{"type":31,"value":852},{"type":26,"tag":404,"props":856,"children":859},{"className":857,"code":858,"language":521,"meta":7},[519],"\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",[860],{"type":26,"tag":412,"props":861,"children":862},{"__ignoreMap":7},[863],{"type":31,"value":858},{"type":26,"tag":68,"props":865,"children":867},{"id":866},"完整示例",[868],{"type":31,"value":866},{"type":26,"tag":404,"props":870,"children":873},{"className":871,"code":872,"language":461,"meta":7},[459],"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",[874],{"type":26,"tag":412,"props":875,"children":876},{"__ignoreMap":7},[877],{"type":31,"value":872},{"type":26,"tag":68,"props":879,"children":880},{"id":543},[881],{"type":31,"value":543},{"type":26,"tag":27,"props":883,"children":884},{},[885,886,890],{"type":31,"value":550},{"type":26,"tag":552,"props":887,"children":888},{},[889],{"type":31,"value":556},{"type":31,"value":558},{"type":26,"tag":228,"props":892,"children":893},{},[894,899,904,909,914],{"type":26,"tag":232,"props":895,"children":896},{},[897],{"type":31,"value":898},"支持系统偏好",{"type":26,"tag":232,"props":900,"children":901},{},[902],{"type":31,"value":903},"提供手动切换选项",{"type":26,"tag":232,"props":905,"children":906},{},[907],{"type":31,"value":908},"确保足够的对比度",{"type":26,"tag":232,"props":910,"children":911},{},[912],{"type":31,"value":913},"优化图片和图表",{"type":26,"tag":232,"props":915,"children":916},{},[917],{"type":31,"value":918},"防止加载闪烁",{"type":26,"tag":27,"props":920,"children":921},{},[922,923,927],{"type":31,"value":597},{"type":26,"tag":552,"props":924,"children":925},{},[926],{"type":31,"value":602},{"type":31,"value":558},{"type":26,"tag":228,"props":929,"children":930},{},[931,936,941,946,951],{"type":26,"tag":232,"props":932,"children":933},{},[934],{"type":31,"value":935},"强制单一模式",{"type":26,"tag":232,"props":937,"children":938},{},[939],{"type":31,"value":940},"忽视性能影响",{"type":26,"tag":232,"props":942,"children":943},{},[944],{"type":31,"value":945},"使用相同的颜色",{"type":26,"tag":232,"props":947,"children":948},{},[949],{"type":31,"value":950},"忘记保存用户偏好",{"type":26,"tag":232,"props":952,"children":953},{},[954],{"type":31,"value":955},"过度使用深色背景",{"type":26,"tag":68,"props":957,"children":958},{"id":649},[959],{"type":31,"value":649},{"type":26,"tag":228,"props":961,"children":963},{"className":962},[655],[964,973,982,991,1000],{"type":26,"tag":232,"props":965,"children":967},{"className":966},[660],[968,971],{"type":26,"tag":663,"props":969,"children":970},{"disabled":665,"type":666},[],{"type":31,"value":972}," 在浅色和深色模式下测试所有页面",{"type":26,"tag":232,"props":974,"children":976},{"className":975},[660],[977,980],{"type":26,"tag":663,"props":978,"children":979},{"disabled":665,"type":666},[],{"type":31,"value":981}," 检查颜色对比度符合 WCAG 标准",{"type":26,"tag":232,"props":983,"children":985},{"className":984},[660],[986,989],{"type":26,"tag":663,"props":987,"children":988},{"disabled":665,"type":666},[],{"type":31,"value":990}," 验证图片和图表在两种模式下清晰",{"type":26,"tag":232,"props":992,"children":994},{"className":993},[660],[995,998],{"type":26,"tag":663,"props":996,"children":997},{"disabled":665,"type":666},[],{"type":31,"value":999}," 测试主题切换的平滑性",{"type":26,"tag":232,"props":1001,"children":1003},{"className":1002},[660],[1004,1007],{"type":26,"tag":663,"props":1005,"children":1006},{"disabled":665,"type":666},[],{"type":31,"value":1008}," 检查用户偏好是否被保存",{"title":7,"searchDepth":349,"depth":349,"links":1010},[1011,1012,1016,1021,1022,1023,1024,1025],{"id":729,"depth":352,"text":729},{"id":751,"depth":352,"text":751,"children":1013},[1014,1015],{"id":756,"depth":349,"text":759},{"id":771,"depth":349,"text":774},{"id":786,"depth":352,"text":786,"children":1017},[1018,1019,1020],{"id":791,"depth":349,"text":794},{"id":806,"depth":349,"text":809},{"id":823,"depth":349,"text":826},{"id":838,"depth":352,"text":838},{"id":852,"depth":352,"text":852},{"id":866,"depth":352,"text":866},{"id":543,"depth":352,"text":543},{"id":649,"depth":352,"text":649},"content:topics:design:dark-mode-design.md","topics/design/dark-mode-design.md","topics/design/dark-mode-design",{"_path":1030,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":1031,"description":1032,"keywords":1033,"image":1038,"author":1039,"date":378,"readingTime":737,"topic":5,"body":1040,"_type":360,"_id":1305,"_source":362,"_file":1306,"_stem":1307,"_extension":365},"/topics/design/form-controls-design","表单控件设计规范","学习输入框、选择框、复选框等表单控件的设计和实现",[1034,1035,1036,1037,376],"表单设计","Form Controls","输入框","验证反馈","/images/topics/form-controls-design.jpg","AI Content Team",{"type":23,"children":1041,"toc":1291},[1042,1046,1051,1056,1061,1070,1075,1084,1088,1097,1102,1111,1116,1125,1130,1139,1144,1153,1157,1166,1192,1201,1229,1233],{"type":26,"tag":68,"props":1043,"children":1044},{"id":1031},[1045],{"type":31,"value":1031},{"type":26,"tag":27,"props":1047,"children":1048},{},[1049],{"type":31,"value":1050},"优秀的表单设计能够提高用户完成率和满意度。",{"type":26,"tag":68,"props":1052,"children":1054},{"id":1053},"输入框设计",[1055],{"type":31,"value":1053},{"type":26,"tag":397,"props":1057,"children":1059},{"id":1058},"基础文本输入",[1060],{"type":31,"value":1058},{"type":26,"tag":404,"props":1062,"children":1065},{"className":1063,"code":1064,"language":409,"meta":7},[407],".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",[1066],{"type":26,"tag":412,"props":1067,"children":1068},{"__ignoreMap":7},[1069],{"type":31,"value":1064},{"type":26,"tag":397,"props":1071,"children":1073},{"id":1072},"标签和提示",[1074],{"type":31,"value":1072},{"type":26,"tag":404,"props":1076,"children":1079},{"className":1077,"code":1078,"language":521,"meta":7},[519],"\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",[1080],{"type":26,"tag":412,"props":1081,"children":1082},{"__ignoreMap":7},[1083],{"type":31,"value":1078},{"type":26,"tag":68,"props":1085,"children":1086},{"id":1037},[1087],{"type":31,"value":1037},{"type":26,"tag":404,"props":1089,"children":1092},{"className":1090,"code":1091,"language":461,"meta":7},[459],"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",[1093],{"type":26,"tag":412,"props":1094,"children":1095},{"__ignoreMap":7},[1096],{"type":31,"value":1091},{"type":26,"tag":68,"props":1098,"children":1100},{"id":1099},"选择框设计",[1101],{"type":31,"value":1099},{"type":26,"tag":404,"props":1103,"children":1106},{"className":1104,"code":1105,"language":409,"meta":7},[407],".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",[1107],{"type":26,"tag":412,"props":1108,"children":1109},{"__ignoreMap":7},[1110],{"type":31,"value":1105},{"type":26,"tag":68,"props":1112,"children":1114},{"id":1113},"复选框和单选按钮",[1115],{"type":31,"value":1113},{"type":26,"tag":404,"props":1117,"children":1120},{"className":1118,"code":1119,"language":409,"meta":7},[407],".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",[1121],{"type":26,"tag":412,"props":1122,"children":1123},{"__ignoreMap":7},[1124],{"type":31,"value":1119},{"type":26,"tag":68,"props":1126,"children":1128},{"id":1127},"文本区域",[1129],{"type":31,"value":1127},{"type":26,"tag":404,"props":1131,"children":1134},{"className":1132,"code":1133,"language":409,"meta":7},[407],".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",[1135],{"type":26,"tag":412,"props":1136,"children":1137},{"__ignoreMap":7},[1138],{"type":31,"value":1133},{"type":26,"tag":68,"props":1140,"children":1142},{"id":1141},"完整表单示例",[1143],{"type":31,"value":1141},{"type":26,"tag":404,"props":1145,"children":1148},{"className":1146,"code":1147,"language":461,"meta":7},[459],"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",[1149],{"type":26,"tag":412,"props":1150,"children":1151},{"__ignoreMap":7},[1152],{"type":31,"value":1147},{"type":26,"tag":68,"props":1154,"children":1155},{"id":543},[1156],{"type":31,"value":543},{"type":26,"tag":27,"props":1158,"children":1159},{},[1160,1161,1165],{"type":31,"value":550},{"type":26,"tag":552,"props":1162,"children":1163},{},[1164],{"type":31,"value":556},{"type":31,"value":558},{"type":26,"tag":228,"props":1167,"children":1168},{},[1169,1174,1179,1184,1188],{"type":26,"tag":232,"props":1170,"children":1171},{},[1172],{"type":31,"value":1173},"使用正确的输入类型",{"type":26,"tag":232,"props":1175,"children":1176},{},[1177],{"type":31,"value":1178},"提供实时验证反馈",{"type":26,"tag":232,"props":1180,"children":1181},{},[1182],{"type":31,"value":1183},"清晰的标签和提示",{"type":26,"tag":232,"props":1185,"children":1186},{},[1187],{"type":31,"value":566},{"type":26,"tag":232,"props":1189,"children":1190},{},[1191],{"type":31,"value":592},{"type":26,"tag":27,"props":1193,"children":1194},{},[1195,1196,1200],{"type":31,"value":597},{"type":26,"tag":552,"props":1197,"children":1198},{},[1199],{"type":31,"value":602},{"type":31,"value":558},{"type":26,"tag":228,"props":1202,"children":1203},{},[1204,1209,1214,1219,1224],{"type":26,"tag":232,"props":1205,"children":1206},{},[1207],{"type":31,"value":1208},"隐藏标签",{"type":26,"tag":232,"props":1210,"children":1211},{},[1212],{"type":31,"value":1213},"过度使用占位符",{"type":26,"tag":232,"props":1215,"children":1216},{},[1217],{"type":31,"value":1218},"验证后立即提交",{"type":26,"tag":232,"props":1220,"children":1221},{},[1222],{"type":31,"value":1223},"忽视无障碍性",{"type":26,"tag":232,"props":1225,"children":1226},{},[1227],{"type":31,"value":1228},"复杂的验证规则",{"type":26,"tag":68,"props":1230,"children":1231},{"id":649},[1232],{"type":31,"value":649},{"type":26,"tag":228,"props":1234,"children":1236},{"className":1235},[655],[1237,1246,1255,1264,1273,1282],{"type":26,"tag":232,"props":1238,"children":1240},{"className":1239},[660],[1241,1244],{"type":26,"tag":663,"props":1242,"children":1243},{"disabled":665,"type":666},[],{"type":31,"value":1245}," 所有控件都可用键盘导航",{"type":26,"tag":232,"props":1247,"children":1249},{"className":1248},[660],[1250,1253],{"type":26,"tag":663,"props":1251,"children":1252},{"disabled":665,"type":666},[],{"type":31,"value":1254}," 标签与输入框关联",{"type":26,"tag":232,"props":1256,"children":1258},{"className":1257},[660],[1259,1262],{"type":26,"tag":663,"props":1260,"children":1261},{"disabled":665,"type":666},[],{"type":31,"value":1263}," 验证消息清晰",{"type":26,"tag":232,"props":1265,"children":1267},{"className":1266},[660],[1268,1271],{"type":26,"tag":663,"props":1269,"children":1270},{"disabled":665,"type":666},[],{"type":31,"value":1272}," 色彩对比度足够",{"type":26,"tag":232,"props":1274,"children":1276},{"className":1275},[660],[1277,1280],{"type":26,"tag":663,"props":1278,"children":1279},{"disabled":665,"type":666},[],{"type":31,"value":1281}," 屏幕阅读器兼容",{"type":26,"tag":232,"props":1283,"children":1285},{"className":1284},[660],[1286,1289],{"type":26,"tag":663,"props":1287,"children":1288},{"disabled":665,"type":666},[],{"type":31,"value":1290}," 移动设备测试",{"title":7,"searchDepth":349,"depth":349,"links":1292},[1293,1294,1298,1299,1300,1301,1302,1303,1304],{"id":1031,"depth":352,"text":1031},{"id":1053,"depth":352,"text":1053,"children":1295},[1296,1297],{"id":1058,"depth":349,"text":1058},{"id":1072,"depth":349,"text":1072},{"id":1037,"depth":352,"text":1037},{"id":1099,"depth":352,"text":1099},{"id":1113,"depth":352,"text":1113},{"id":1127,"depth":352,"text":1127},{"id":1141,"depth":352,"text":1141},{"id":543,"depth":352,"text":543},{"id":649,"depth":352,"text":649},"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":1309,"image":17,"imageQuery":18,"pexelsPhotoId":19,"pexelsUrl":20,"featured":6,"readingTime":21,"body":1310,"_type":360,"_id":361,"_source":362,"_file":363,"_stem":364,"_extension":365},[13,14,15,16],{"type":23,"children":1311,"toc":1556},[1312,1316,1320,1339,1343,1427,1431,1435,1439,1443,1447,1451,1455,1459,1463,1478,1482,1486,1490,1494,1498,1502,1506,1510,1529,1533,1537,1552],{"type":26,"tag":27,"props":1313,"children":1314},{},[1315],{"type":31,"value":32},{"type":26,"tag":27,"props":1317,"children":1318},{},[1319],{"type":31,"value":37},{"type":26,"tag":27,"props":1321,"children":1322},{},[1323,1324,1328,1329,1333,1334,1338],{"type":31,"value":42},{"type":26,"tag":44,"props":1325,"children":1326},{"href":46},[1327],{"type":31,"value":49},{"type":31,"value":51},{"type":26,"tag":44,"props":1330,"children":1331},{"href":54},[1332],{"type":31,"value":57},{"type":31,"value":51},{"type":26,"tag":44,"props":1335,"children":1336},{"href":61},[1337],{"type":31,"value":64},{"type":31,"value":66},{"type":26,"tag":68,"props":1340,"children":1341},{"id":70},[1342],{"type":31,"value":73},{"type":26,"tag":75,"props":1344,"children":1345},{},[1346,1364],{"type":26,"tag":79,"props":1347,"children":1348},{},[1349],{"type":26,"tag":83,"props":1350,"children":1351},{},[1352,1356,1360],{"type":26,"tag":87,"props":1353,"children":1354},{},[1355],{"type":31,"value":91},{"type":26,"tag":87,"props":1357,"children":1358},{},[1359],{"type":31,"value":96},{"type":26,"tag":87,"props":1361,"children":1362},{},[1363],{"type":31,"value":101},{"type":26,"tag":103,"props":1365,"children":1366},{},[1367,1382,1397,1412],{"type":26,"tag":83,"props":1368,"children":1369},{},[1370,1374,1378],{"type":26,"tag":110,"props":1371,"children":1372},{},[1373],{"type":31,"value":114},{"type":26,"tag":110,"props":1375,"children":1376},{},[1377],{"type":31,"value":119},{"type":26,"tag":110,"props":1379,"children":1380},{},[1381],{"type":31,"value":124},{"type":26,"tag":83,"props":1383,"children":1384},{},[1385,1389,1393],{"type":26,"tag":110,"props":1386,"children":1387},{},[1388],{"type":31,"value":132},{"type":26,"tag":110,"props":1390,"children":1391},{},[1392],{"type":31,"value":137},{"type":26,"tag":110,"props":1394,"children":1395},{},[1396],{"type":31,"value":142},{"type":26,"tag":83,"props":1398,"children":1399},{},[1400,1404,1408],{"type":26,"tag":110,"props":1401,"children":1402},{},[1403],{"type":31,"value":150},{"type":26,"tag":110,"props":1405,"children":1406},{},[1407],{"type":31,"value":155},{"type":26,"tag":110,"props":1409,"children":1410},{},[1411],{"type":31,"value":160},{"type":26,"tag":83,"props":1413,"children":1414},{},[1415,1419,1423],{"type":26,"tag":110,"props":1416,"children":1417},{},[1418],{"type":31,"value":168},{"type":26,"tag":110,"props":1420,"children":1421},{},[1422],{"type":31,"value":173},{"type":26,"tag":110,"props":1424,"children":1425},{},[1426],{"type":31,"value":178},{"type":26,"tag":68,"props":1428,"children":1429},{"id":181},[1430],{"type":31,"value":184},{"type":26,"tag":27,"props":1432,"children":1433},{},[1434],{"type":31,"value":189},{"type":26,"tag":27,"props":1436,"children":1437},{},[1438],{"type":31,"value":194},{"type":26,"tag":68,"props":1440,"children":1441},{"id":197},[1442],{"type":31,"value":200},{"type":26,"tag":27,"props":1444,"children":1445},{},[1446],{"type":31,"value":205},{"type":26,"tag":27,"props":1448,"children":1449},{},[1450],{"type":31,"value":210},{"type":26,"tag":68,"props":1452,"children":1453},{"id":213},[1454],{"type":31,"value":216},{"type":26,"tag":27,"props":1456,"children":1457},{},[1458],{"type":31,"value":221},{"type":26,"tag":27,"props":1460,"children":1461},{},[1462],{"type":31,"value":226},{"type":26,"tag":228,"props":1464,"children":1465},{},[1466,1470,1474],{"type":26,"tag":232,"props":1467,"children":1468},{},[1469],{"type":31,"value":236},{"type":26,"tag":232,"props":1471,"children":1472},{},[1473],{"type":31,"value":241},{"type":26,"tag":232,"props":1475,"children":1476},{},[1477],{"type":31,"value":246},{"type":26,"tag":27,"props":1479,"children":1480},{},[1481],{"type":31,"value":251},{"type":26,"tag":68,"props":1483,"children":1484},{"id":254},[1485],{"type":31,"value":257},{"type":26,"tag":27,"props":1487,"children":1488},{},[1489],{"type":31,"value":262},{"type":26,"tag":27,"props":1491,"children":1492},{},[1493],{"type":31,"value":267},{"type":26,"tag":68,"props":1495,"children":1496},{"id":270},[1497],{"type":31,"value":273},{"type":26,"tag":27,"props":1499,"children":1500},{},[1501],{"type":31,"value":278},{"type":26,"tag":27,"props":1503,"children":1504},{},[1505],{"type":31,"value":283},{"type":26,"tag":68,"props":1507,"children":1508},{"id":286},[1509],{"type":31,"value":289},{"type":26,"tag":228,"props":1511,"children":1512},{},[1513,1517,1521,1525],{"type":26,"tag":232,"props":1514,"children":1515},{},[1516],{"type":31,"value":297},{"type":26,"tag":232,"props":1518,"children":1519},{},[1520],{"type":31,"value":302},{"type":26,"tag":232,"props":1522,"children":1523},{},[1524],{"type":31,"value":307},{"type":26,"tag":232,"props":1526,"children":1527},{},[1528],{"type":31,"value":312},{"type":26,"tag":27,"props":1530,"children":1531},{},[1532],{"type":31,"value":317},{"type":26,"tag":68,"props":1534,"children":1535},{"id":320},[1536],{"type":31,"value":323},{"type":26,"tag":325,"props":1538,"children":1539},{},[1540,1544,1548],{"type":26,"tag":232,"props":1541,"children":1542},{},[1543],{"type":31,"value":332},{"type":26,"tag":232,"props":1545,"children":1546},{},[1547],{"type":31,"value":337},{"type":26,"tag":232,"props":1549,"children":1550},{},[1551],{"type":31,"value":342},{"type":26,"tag":27,"props":1553,"children":1554},{},[1555],{"type":31,"value":347},{"title":7,"searchDepth":349,"depth":349,"links":1557},[1558,1559,1560,1561,1562,1563,1564,1565],{"id":70,"depth":352,"text":73},{"id":181,"depth":352,"text":184},{"id":197,"depth":352,"text":200},{"id":213,"depth":352,"text":216},{"id":254,"depth":352,"text":257},{"id":270,"depth":352,"text":273},{"id":286,"depth":352,"text":289},{"id":320,"depth":352,"text":323},1780533130133]