模式 · PATTERN
安全验证外壳 VerifyShell
第三方人机验证(Cloudflare Turnstile、阿里云验证码)的外围壳:始终可见、占位固定,底下三种反馈态——通过、冷却、限流。
第三方安全验证 · 始终可见外围壳
正在进行人机验证…CLOUDFLARE
TURNSTILE
验证通过 · 可发送冷却中 · 60s请求过多 · 暂时拦截
import { VerifyShell } from './extracted/VerifyShell.jsx'
export function Shell() {
return (
<div style={{ width: 400, maxWidth: '100%' }}>
<VerifyShell />
</div>
)
}<div style="width: 400px; max-width: 100%">
<div
style="
padding: 12px;
border-radius: 12px;
background: rgba(0, 0, 0, 0.035);
border: 1px solid rgba(0, 0, 0, 0.08);
"
>
<div style="font-size: 11.5px; color: #54544f; line-height: 1.6">
第三方安全验证 · 始终可见外围壳
</div>
<div
style="
margin-top: 8px;
min-height: 54px;
padding: 9px 12px;
border-radius: 8px;
background: #ffffff;
border: 1px solid rgba(0, 0, 0, 0.12);
display: flex;
align-items: center;
gap: 10px;
"
>
<span
style="
width: 18px;
height: 18px;
border-radius: 4px;
border: 1.5px solid rgba(0, 0, 0, 0.28);
background: #fafaf8;
flex: none;
"
></span>
<span style="font-size: 12px; color: #3f3f3b">正在进行人机验证…</span>
<span style="flex: 1"></span>
<span
style="font-family:ui-monospace,'SF Mono',Menlo,monospace;font-size:8.5px;color:#A2A29C;text-align:right;white-space:pre-line"
>
CLOUDFLARE TURNSTILE
</span>
</div>
<div style="display: flex; gap: 6px; margin-top: 8px; flex-wrap: wrap">
<span
style="
display: inline-block;
font-size: 10.5px;
padding: 3px 8px;
border-radius: 999px;
background: rgba(79, 169, 106, 0.1);
color: #3b8557;
"
>
验证通过 · 可发送
</span>
<span
style="
display: inline-block;
font-size: 10.5px;
padding: 3px 8px;
border-radius: 999px;
background: #efefec;
color: #8b8b85;
"
>
冷却中 · 60s
</span>
<span
style="
display: inline-block;
font-size: 10.5px;
padding: 3px 8px;
border-radius: 999px;
background: rgba(166, 64, 47, 0.07);
color: var(--zzm-accent, #a6402f);
"
>
请求过多 · 暂时拦截
</span>
</div>
</div>
</div>/* tokens.css · 用到的令牌 */
:root {
--zzm-accent: #A6402F;
}为什么要一个外壳
第三方验证控件的 iframe 加载慢、时有时无。直接放进表单,它出现和消失会把表单顶得上下跳。外壳先占住位置(最小高 54),真实 iframe 渲染在里面(children);外壳下方用状态胶囊统一给出反馈。
| 属性 | 取值 | 默认 | 说明 |
|---|---|---|---|
| title | string | '第三方安全验证 · 始终可见外围壳' | 外壳标题 |
| provider | string | 'CLOUDFLARE\nTURNSTILE' | 右侧服务商标识(未传 children 时显示) |
| states | ('ok' · 'cooldown' · 'limited')[] | 三种都显示 | 要显示的反馈态 |
| children | ReactNode | — | 真实验证控件挂载点 |
规则
✓ 要单次 token:每次发送验证码前重新验证
✓ 要发送后 60 秒冷却,冷却中显示倒计时
✓ 要被限流时明确说「请求过多 · 暂时拦截」
✗ 不要验证失败时只让按钮变灰、不说原因