# Download

下载按钮组件，通过 iframe 方式触发文件下载，支持下载前拦截和下载状态提示。

## 适用场景

- 点击按钮触发文件下载（GET/POST 请求）
- 需要在下载前进行权限检查或异步操作
- 需要展示下载开始提示

## Props

### DownloadButton Props

| 名称 | 类型 | 默认值 | 必填 | 说明 |
|------|------|--------|------|------|
| className | `string` | `""` | 否 | 自定义 class |
| beforeDownload | `(e) => boolean \| void \| Promise<unknown>` | `-` | 否 | 下载前回调；返回 false 阻止下载，Promise resolve 后执行下载，true/void 立即下载 |
| url | `string` | `-` | 否 | 下载地址 |
| method | `DownloadIframeMethod` | `-` | 否 | 请求方法 |
| params | `Record<string, unknown>` | `-` | 否 | 请求参数 `{ [key]: string \| number }` |
| onResponse | `(respJson: Json, respText: string) => void` | `-` | 否 | 请求成功的回调 |
| isResponseSuccess | `(respJson: Json, respText: string) => boolean` | `-` | 否 | 判断请求是否成功的函数 |
| startMessageDelay | `number` | `-` | 否 | 开始下载消息的延迟出现时间（ms），<=0 不延迟 |
| startMessageDuration | `number` | `-` | 否 | 开始下载消息的持续时间 |
| size | `"md" \| "sm" \| "xs" \| "lg" \| "xl"` | `-` | 否 | 尺寸，默认读取 ConfigContext `baseSize` |
| disabled | `boolean` | `-` | 否 | 是否禁用 |
| type | `"normal" \| "intensive" \| "important" \| "plain" \| "ghost"` | `-` | 否 | 按钮类型 |
| color | `"normal" \| "brand" \| "success" \| "danger" \| "warning" \| "primary"` | `-` | 否 | 按钮颜色（`primary` 将废弃，改用 `brand`） |
| icon | `FC<{}>` | `-` | 否 | 按钮图标 |
| loading | `boolean` | `-` | 否 | 是否处于 loading 状态 |
| loadingIcon | `SvgFC` | `-` | 否 | 自定义 loading 图标 |
| loadingType | `"normal" \| "icon-only"` | `-` | 否 | loading 类型 |
| loadingDelay | `number` | `-` | 否 | loading 图标延迟响应时间（ms），0 为立即显示 |
| href | `string` | `-` | 否 | 作为 `<a>` 链接时的跳转地址 |
| target | `string` | `-` | 否 | `<a>` 的 target |
| download | `string` | `-` | 否 | `<a>` 的 download 属性，指示浏览器下载而非跳转 |
| onClick | `(e) => void \| Promise<unknown>` | `-` | 否 | 点击回调，返回 Promise 会触发 loading 状态 |
| refHTMLElement | `Ref<HTMLButtonElement> \| Ref<HTMLAnchorElement>` | `-` | 否 | ref html element |

### DownloadIframe Props

| 名称 | 类型 | 默认值 | 必填 | 说明 |
|------|------|--------|------|------|
| className | `string` | `""` | 否 | 自定义 class |
| url | `string` | `-` | 否 | 下载地址 |
| method | `DownloadIframeMethod` | `"get"` | 否 | 请求方法 |
| params | `Record<string, unknown>` | `-` | 否 | 请求参数 |
| onResponse | `(respJson: Json, respText: string) => void` | `-` | 否 | 请求成功的回调 |
| isResponseSuccess | `(respJson: Json, respText: string) => boolean` | `-` | 否 | 判断请求是否成功的函数 |
| startMessageDelay | `number` | `300` | 否 | 开始下载消息延迟出现时间（ms） |
| startMessageDuration | `number` | `-` | 否 | 开始下载消息持续时间 |

## 典型用法

### 基础下载按钮

```tsx
import { Download } from '@befe/brick-comp-down_load'

const downloadUrl = 'https://example.com/file?id=xxx'

<Download url={downloadUrl}>导出</Download>
```

### 下载前拦截（beforeDownload）

```tsx
import { useState } from 'react'
import { Download } from '@befe/brick-comp-down_load'

function Demo() {
    const [canDownload, setCanDownload] = useState(false)

    const beforeDownload = () => {
        if (!canDownload) {
            return false  // 阻止下载
        }
        return undefined  // 继续下载
        // 也可以返回 Promise.resolve() 异步确认后下载
    }

    return (
        <Download
            beforeDownload={beforeDownload}
            url={downloadUrl}
        >
            导出
        </Download>
    )
}
```

## 注意事项

- `Download` 导出自 `@befe/brick-comp-down_load`（注意包名含下划线）
- 破坏性变更（2021）：`startMessageDelayInMS` 已改名为 `startMessageDelay`，`startMessageDurationInMS` 改名为 `startMessageDuration`，`loadingDelayInMS` 改名为 `loadingDelay`
- 若需要 ajax 方式下载，请参考 sack 工具库的 download 方法，不属于本组件范畴
- `beforeDownload` 返回 `false` 会阻止下载，返回 Promise 会等待 resolve 后再执行下载
