# @shencom/request

封装 `axios` 请求，兼容了 `uni-app` 的 `uni.request` 和 `uni.uploadFile` 的适配器；并且对 `GET` 请求和 `POST` 请求进行简单改写，添加了 `upload` 文件上传方法

官网连接: https://www.axios-http.cn/docs/intro

## Install

```sh
pnpm add @shencom/request
```

### uniapp

<code style="color:yellow">**📢 注意：**</code>目前只测试使用 vite 创建的项目。

```ts
import { adapter, http, version } from '@shencom/request';
// or
import { http, version } from '@shencom/request/uniapp';
```

使用 `@shencom/request/uniapp` 会自定加载 `adapter` 适配器

使用 `@shencom/request` 需要自行配置

```ts
http.defaults.adapter = adapter;
```

### browser

<code style="color:red;">**📢 注意：**</code>在 `vue/cli` 的项目中，开发环境中会出现 `uni` 未定义的情况，打包正常会进行 `tree-shaking` 处理。

```ts
import { http, version } from '@shencom/request';
```

## Default Config

添加和修改一些配置，其他配置同 `axios`

| Name          | Description            | Default |
| ------------- | ---------------------- | ------: |
| timeout       | 请求时间               | `20000` |
| isFilterEmpty | 是否过滤空字符串的参数 |  `true` |
| errcode       | 接口业务状态码         |  `0000` |

```ts
// 接口.isFilterEmpty > defaults.isFilterEmpty
http.defaults.isFilterEmpty = false; // 默认 true
http.post('xx', {}, { isFilterEmpty: false }); // 默认 true

// 接口.errcode > defaults.errcode
http.defaults.errcode = '1111'; // 默认 '0000'
http.post('xx', {}, { errcode: '1111' }); // 默认 true
```

## Headers

| Name          | Description | Type   | Default | Optional                        |
| ------------- | ----------- | ------ | ------- | ------------------------------- |
| scid          | 租户 id     | String | -       | -                               |
| Authorization | token       | String | -       | -                               |
| miniProgram   | 平台环境    | -      | -       | `weixin` / `ali` / `h5` / `app` |

### Set Headers

具体设置参考[官网文档](https://www.axios-http.cn/docs/config_defaults)

```ts
// 配置示例，具体可自行根据业务进行配置
axios.defaults.headers.common.scid = scid;
axios.defaults.headers.common.miniProgram = miniProgram;
axios.defaults.headers.common.timeout = 20000;
```

## Method

```ts
type ScRequest = <R = Dictionary, D = Dictionary>(
  url: string,
  data?: D,
  config?: Config<D>,
) => Promise<ScResponse<R>>;
```

**get**

- 说明: GET 请求
- 类型: `ScRequest`
- 参数:
  - `url`: 请求连接
  - `data`: 请求参数
  - `config`: 自定义参数 https://www.axios-http.cn/docs/req_config
- 响应: 参考 https://www.axios-http.cn/docs/res_schema

**post**

- 说明: POST 请求
- 类型: `ScRequest`
- 参数:
  - `url`: 请求连接
  - `data`: 请求参数
  - `config`: 自定义参数 https://www.axios-http.cn/docs/req_config
- 响应: 参考 https://www.axios-http.cn/docs/res_schema

**upload**

- 说明: 文件上传
- 类型: `ScRequest`
- 参数:
  - `url`: 请求连接
  - `data`: 请求参数
  - `config`: 自定义参数 https://www.axios-http.cn/docs/req_config
  -
- 响应:
  - 参考 https://www.axios-http.cn/docs/res_schema
  - 在 oss 直传中，响应数据会全部返回

## Example

### GET and POST

> 对这个 2 个请求进行了一个响应拦截处理，`res.data?.errcode === '0000'`，
> 遇见需要改变的请求状态码,可以在 `http.defaults.errcode` 和接口参数中进行设置，
> 如果不需要 `errcode` 可以使用 `http.request` 进行自定义请求

```ts
http.post('url', { a: 1 }).then((res) => {
  console.info(res.data);
});

// 不使用 token，和修改 scid
http.post('url', { a: 1 }, { headers: { Authorization: null, scid: 'xxx' } }).then((res) => {
  console.info(res.data);
});

// 修改 errcode
http.post('url', {}, { headers: { errcode: '1111' } }).then((res) => {
  console.info(res.data);
});

// 不对参数进行空字符串过滤
http.post('url', { a: '' }, { headers: { isFilterEmpty: false } }).then((res) => {
  console.info(res.data);
});

http.post<{ val: number }>('url').then((res) => {
  console.info(res.data.val); // val:number
});

// 类型错误
http.post<{ val: number }, { code: number }>('url', {}).then((res) => {
  console.info(res.data.val); // val:number
});

// 类型错误: 不能将类型“string”分配给类型“number”。
http.post<{ val: number }, { code: number }>('url', { code: '' }).then((res) => {
  console.info(res.data.val); // val:number
});

http.post<{ val: number }, { code: number }>('url', { code: 1 }).then((res) => {
  console.info(res.data.val); // val:number
});
```

### UPLOAD

`upload API` 使用说明

一般上传使用在 `服务器` 和 `OSS` 上传的情况  
在 `OSS` 直传情况下，响应 `data` 返回的是空字符串，并且需要再 `Header` 中获取 `ETag` 数据
所以响应的数据没有做过滤  

#### 小程序

```ts
const data = { target: 0, open: 1, name: 'file', file };
http.upload('url', data);
```

#### web 和 uniapp web

```ts
const data = new FormData();
data.append('target', '0');
data.append('open', '1');
data.append('name', 'file');
data.append('file', file);

http.upload('url', data);
```

<code style="color:yellow;">**提示**</code>: 不推荐直接使用 `upload` 方法进行上传数据，推荐使用 [@shencom/api](https://www.npmjs.com/package/@shencom/api) 中的两个方法进行上传文件
`BaseFileUpload` 和 `BaseFileOssUpload` 上传文件

### Interceptors

```ts
const Token = () => {
  const Authorization = UserInfo.getToken();
  return Authorization ? `bearer ${Authorization}` : null;
};

http.interceptors.request.use(
  (res) => {
    // token 处理
    const { Authorization } = res.headers!;
    if (Authorization === null || JSON.stringify(Authorization) === '{}') {
      delete res.headers!.Authorization;
    } else {
      const token = Token();
      if (token) res.headers!.Authorization = token;
      else delete res.headers!.Authorization;
    }

    // 业务处理
    console.info('请求数据 :', res.url, '\n', res);

    return res;
  },
  (error) => {
    // 业务处理
    return Promise.reject(error);
  },
);

http.interceptors.response.use(
  (res) => {
    // 业务处理
    console.info('响应数据 :', res.config.url, '\n', res);

    return res;
  },
  (error) => {
    // 业务处理
    return Promise.reject(error);
  },
);
```
