---
title: 安全验证外壳 VerifyShell
url: https://ui.zhaozimin.cn/patterns/verify-shell/
markdown: https://ui.zhaozimin.cn/patterns/verify-shell.md
group: 模式
origin: 提炼层组件（src/extracted），本仓库是唯一源头
source:
  - src/extracted/VerifyShell.jsx  # https://ui.zhaozimin.cn/src/extracted/VerifyShell.jsx
  - src/extracted/Tag.jsx  # https://ui.zhaozimin.cn/src/extracted/Tag.jsx
version: v0.2.0  # 设计系统版本，发布于 2026-09-23
scope: .zzm-v4   # 根节点必须带这个类，否则样式不生效
css: https://ui.zhaozimin.cn/v/0.2.0/zzm.css   # 锁版本地址，本仓库再改也不影响你
---

# 安全验证外壳 VerifyShell

> 第三方人机验证（Cloudflare Turnstile、阿里云验证码）的外围壳：始终可见、占位固定，底下三种反馈态——通过、冷却、限流。

### 样张 · 外壳 + 三种反馈

React：

```jsx
import { VerifyShell } from './extracted/VerifyShell.jsx'

export function Shell() {
  return (
    <div style={{ width: 400, maxWidth: '100%' }}>
      <VerifyShell />
    </div>
  )
}
```

HTML（构建时由上面的 React 渲染得到，可直接粘贴）：

```html
<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,&#x27;SF Mono&#x27;,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>
```

## 为什么要一个外壳

第三方验证控件的 iframe 加载慢、时有时无。直接放进表单，它出现和消失会把表单顶得上下跳。外壳先占住位置（最小高 54），真实 iframe 渲染在里面（`children`）；外壳下方用状态胶囊统一给出反馈。

| 属性 | 取值 | 默认 | 说明 |
|---|---|---|---|
| `title` | string | '第三方安全验证 · 始终可见外围壳' | 外壳标题 |
| `provider` | string | 'CLOUDFLARE\nTURNSTILE' | 右侧服务商标识（未传 children 时显示） |
| `states` | ('ok' · 'cooldown' · 'limited')[] | 三种都显示 | 要显示的反馈态 |
| `children` | ReactNode | — | 真实验证控件挂载点 |

## 规则

- ✓ 要：单次 token：每次发送验证码前重新验证
- ✓ 要：发送后 60 秒冷却，冷却中显示倒计时
- ✓ 要：被限流时明确说「请求过多 · 暂时拦截」
- ✗ 不要：验证失败时只让按钮变灰、不说原因

---

上一页：[数据表格](https://ui.zhaozimin.cn/patterns/data-table.md) · 下一页：[笔记标注块](https://ui.zhaozimin.cn/patterns/callouts.md) · 全站目录：https://ui.zhaozimin.cn/llms.txt
