import { Button } from '@chakra-ui/react';
import { ArgsTable, Meta, Story, Canvas } from '@storybook/addon-docs';
import { OrderDirection } from './interfaces';
import NewBadge from '../new-badge';
import { ApolloTable } from './index';
import { useState } from 'react';

<Meta title="数据展示/GraphQL表格 ApolloTable" component={ApolloTable} />

# 表格 ApolloTable

基于游标分页的 ApolloTable

## 导入

```typescript
import { ApolloTable } from '@ahri-ui/core';
```

<Canvas>
  <Story name="基本使用">
    <ApolloTable
      dataSource={[
        {
          apiUsername: 'qq.dd.com',
          balance: '2857.00',
          createdAt: '2021-07-16T06:08:07.512Z',
          domain: 'qq.maybelddiever.com',
          email: 'qq@dd.com',
          ID: 'fd',
          isAvailable: true,
          isEnable: true,
          isSandbox: true,
          limit: '2857.00',
          name: '网关3-2',
          receiverEmail: 'qq@dd.com',
          receiverId: 'fdUHS2M2VRN64',
          updatedAt: '2021-07-23T08:51:20.615Z',
          description: null,
          tags: ['可收款', '单数::50'],
          proxyHost: '3.219.220.131',
          proxyPort: 4445,
          proxyUsername: 'u61310',
          __typename: 'Gateway',
        },
      ]}
      columns={[
        {
          copyable: true,
          dataIndex: 'ID',
          title: 'ID',
          search: {
            phrase: true,
          },
        },
        {
          dataIndex: 'name',
          title: '名称',
          hidden: true,
        },
        {
          dataIndex: 'isEnable',
          title: '开关',
          search: {
            shortcut: true,
            searchParamType: Boolean,
          },
          filterType: 'checkbox',
          valueEnum: [
            { label: '开启', value: true },
            { label: '关闭', value: false },
          ],
          render: text => {
            return text ? <NewBadge>开启</NewBadge> : <NewBadge>关闭</NewBadge>;
          },
        },
        {
          dataIndex: 'isAvailable',
          title: '可用性',
          search: {
            shortcut: true,
            searchParamType: Boolean,
          },
          filterType: 'radio',
          valueEnum: [
            { label: '有效', value: true },
            { label: '无效', value: false },
          ],
          render: text => {
            return text ? <NewBadge>有效</NewBadge> : <NewBadge>无效</NewBadge>;
          },
        },
        {
          dataIndex: 'isSandbox',
          title: '环境',
          search: {
            shortcut: true,
            searchParamType: Boolean,
          },
          filterType: 'radio',
          valueEnum: [
            { label: '沙盒', value: true },
            { label: '线上', value: false },
          ],
          render: text => {
            return text ? <NewBadge>沙盒</NewBadge> : <NewBadge>线上</NewBadge>;
          },
        },
        {
          dataIndex: 'tags',
          title: '标签',
          search: { shortcut: true },
          filterType: 'input',
          valueType: 'tag',
        },
        {
          dataIndex: 'limit',
          title: '总额度',
          valueType: {
            type: 'money',
            currency: 'USD',
          },
        },
        {
          dataIndex: 'balance',
          title: '剩余额度',
          valueType: {
            type: 'money',
            currency: 'USD',
          },
        },
        {
          copyable: true,
          dataIndex: 'domain',
          title: '域名',
        },
        {
          copyable: true,
          dataIndex: 'email',
        },
        {
          dataIndex: 'createdAt',
          title: '创建时间',
          valueType: 'dateTime',
        },
      ]}
      scroll={{ x: 'max-content' }}
      id="id"
      rowKey="ID"
      request={(params, id) => {
        console.log(params, id);
      }}
    />
  </Story>
</Canvas>

## 批量操作

<Canvas>
  <Story name="批量操作">
    <ApolloTable
      dataSource={[
        {
          apiUsername: 'qq.dd.com',
          balance: '2857.00',
          createdAt: '2021-07-16T06:08:07.512Z',
          domain: 'qq.maybelddiever.com',
          email: 'qq@dd.com',
          ID: 'fd',
          isAvailable: true,
          isEnable: true,
          isSandbox: true,
          limit: '2857.00',
          name: '网关3-2',
          receiverEmail: 'qq@dd.com',
          receiverId: 'fdUHS2M2VRN64',
          updatedAt: '2021-07-23T08:51:20.615Z',
          description: null,
          tags: ['可收款', '单数::50'],
          proxyHost: '3.219.220.131',
          proxyPort: 4445,
          proxyUsername: 'u61310',
          __typename: 'Gateway',
        },
      ]}
      rowSelection={{}}
      tableAlertRender={() => ({
        promotedBulkActions: [
          {
            content: '删除',
            onClick: () => {
              console.log('删除');
            },
          },
          {
            content: '编辑',
            onClick: () => {
              console.log('删除');
            },
          },
        ],
        bulkActions: [
          {
            content: '操作1',
            onClick: () => {
              console.log('操作1');
            },
          },
          {
            content: '操作2',
            onClick: () => {
              console.log('操作2');
            },
          },
        ],
      })}
      columns={[
        {
          copyable: true,
          dataIndex: 'ID',
          title: 'ID',
          filterType: 'input',
          search: {
            phrase: true,
          },
        },
        {
          dataIndex: 'name',
          title: '名称',
          filterType: 'input',
        },
        {
          dataIndex: 'isEnable',
          title: '开关',
          search: {
            shortcut: true,
            searchParamType: Boolean,
          },
          filterType: 'checkbox',
          valueEnum: [
            { label: '开启', value: true },
            { label: '关闭', value: false },
          ],
          render: text => {
            return text ? <NewBadge>开启</NewBadge> : <NewBadge>关闭</NewBadge>;
          },
        },
        {
          dataIndex: 'isAvailable',
          title: '可用性',
          search: {
            shortcut: true,
            searchParamType: Boolean,
          },
          filterType: 'radio',
          valueEnum: [
            { label: '有效', value: true },
            { label: '无效', value: false },
          ],
          render: text => {
            return text ? <NewBadge>有效</NewBadge> : <NewBadge>无效</NewBadge>;
          },
        },
        {
          dataIndex: 'isSandbox',
          title: '环境',
          search: {
            shortcut: true,
            searchParamType: Boolean,
          },
          filterType: 'radio',
          valueEnum: [
            { label: '沙盒', value: true },
            { label: '线上', value: false },
          ],
          render: text => {
            return text ? <NewBadge>沙盒</NewBadge> : <NewBadge>线上</NewBadge>;
          },
        },
        {
          dataIndex: 'tags',
          title: '标签',
          search: { shortcut: true },
          filterType: 'input',
          valueType: 'tag',
        },
        {
          dataIndex: 'limit',
          title: '总额度',
          valueType: {
            type: 'money',
            currency: 'USD',
          },
        },
        {
          dataIndex: 'balance',
          title: '剩余额度',
          valueType: {
            type: 'money',
            currency: 'USD',
          },
        },
        {
          copyable: true,
          dataIndex: 'domain',
          title: '域名',
          filterType: 'input',
        },
        {
          copyable: true,
          dataIndex: 'email',
          title: '邮箱',
          filterType: 'input',
        },
        {
          dataIndex: 'createdAt',
          title: '创建时间',
          align: 'left',
          filterType: 'dateTimeRange',
          valueType: 'dateTime',
        },
      ]}
      scroll={{ x: 'max-content' }}
      id="id"
      rowKey="ID"
      request={(params, id) => {
        console.log(params, id);
      }}
    />
  </Story>
</Canvas>

## 视图

<Canvas>
  <Story name="视图">
    <ApolloTable
      dataSource={[
        {
          apiUsername: 'qq.dd.com',
          balance: '2857.00',
          createdAt: '2021-07-16T06:08:07.512Z',
          domain: 'qq.maybelddiever.com',
          email: 'qq@dd.com',
          ID: 'fd',
          isAvailable: true,
          isEnable: true,
          isSandbox: true,
          limit: '2857.00',
          name: '网关3-2',
          receiverEmail: 'qq@dd.com',
          receiverId: 'fdUHS2M2VRN64',
          updatedAt: '2021-07-23T08:51:20.615Z',
          description: null,
          tags: ['可收款', '单数::50'],
          proxyHost: '3.219.220.131',
          proxyPort: 4445,
          proxyUsername: 'u61310',
          __typename: 'Gateway',
        },
      ]}
      search={{
        queryProps: {
          placeholder: '筛选网关',
        },
        defaultSortValue: {
          field: 'createdAt',
          direction: 'DESC',
        },
        sortOptions: [
          {
            label: '创建时间（升序）',
            field: 'createdAt',
            direction: 'ASC',
          },
          {
            label: '创建时间（降序）',
            field: 'createdAt',
            direction: 'DESC',
          },
        ],
        selectedViews: {
          config: [
            {
              name: '沙盒',
              id: 'gatewaySandbox-true',
              filters: {
                isSandbox: true,
              },
              orderBy: { field: 'createdAt', direction: 'DESC' },
            },
            {
              name: '线上',
              id: 'gatewaySandbox-false',
              filters: {
                isSandbox: false,
              },
              orderBy: { field: 'createdAt', direction: 'DESC' },
            },
          ],
        },
      }}
      columns={[
        {
          copyable: true,
          dataIndex: 'ID',
          title: 'ID',
          filterType: 'input',
          search: {
            phrase: true,
          },
        },
        {
          dataIndex: 'name',
          title: '名称',
          filterType: 'input',
        },
        {
          dataIndex: 'isEnable',
          title: '开关',
          search: {
            shortcut: true,
            searchParamType: Boolean,
          },
          filterType: 'checkbox',
          valueEnum: [
            { label: '开启', value: true },
            { label: '关闭', value: false },
          ],
          render: text => {
            return text ? <NewBadge>开启</NewBadge> : <NewBadge>关闭</NewBadge>;
          },
        },
        {
          dataIndex: 'isAvailable',
          title: '可用性',
          search: {
            shortcut: true,
            searchParamType: Boolean,
          },
          filterType: 'radio',
          valueEnum: [
            { label: '有效', value: true },
            { label: '无效', value: false },
          ],
          render: text => {
            return text ? <NewBadge>有效</NewBadge> : <NewBadge>无效</NewBadge>;
          },
        },
        {
          dataIndex: 'isSandbox',
          title: '环境',
          search: {
            shortcut: true,
            searchParamType: Boolean,
          },
          filterType: 'radio',
          valueEnum: [
            { label: '沙盒', value: true },
            { label: '线上', value: false },
          ],
          render: text => {
            return text ? <NewBadge>沙盒</NewBadge> : <NewBadge>线上</NewBadge>;
          },
        },
        {
          dataIndex: 'tags',
          title: '标签',
          search: { shortcut: true },
          filterType: 'input',
          valueType: 'tag',
        },
        {
          dataIndex: 'limit',
          title: '总额度',
          valueType: {
            type: 'money',
            currency: 'USD',
          },
        },
        {
          dataIndex: 'balance',
          title: '剩余额度',
          valueType: {
            type: 'money',
            currency: 'USD',
          },
        },
        {
          copyable: true,
          dataIndex: 'domain',
          title: '域名',
          filterType: 'input',
        },
        {
          copyable: true,
          dataIndex: 'email',
          title: '邮箱',
          filterType: 'input',
        },
        {
          dataIndex: 'createdAt',
          title: '创建时间',
          align: 'left',
          filterType: 'dateTimeRange',
          valueType: 'dateTime',
        },
      ]}
      scroll={{ x: 'max-content' }}
      id="id"
      rowKey="ID"
      request={(params, id) => {
        console.log(params, id);
      }}
    />
  </Story>
</Canvas>

## 服务端保存视图

<Canvas>
  <Story name="服务端保存视图">
    <ApolloTable
      dataSource={[
        {
          apiUsername: 'qq.dd.com',
          balance: '2857.00',
          createdAt: '2021-07-16T06:08:07.512Z',
          domain: 'qq.maybelddiever.com',
          email: 'qq@dd.com',
          ID: 'fd',
          isAvailable: true,
          isEnable: true,
          isSandbox: true,
          limit: '2857.00',
          name: '网关3-2',
          receiverEmail: 'qq@dd.com',
          receiverId: 'fdUHS2M2VRN64',
          updatedAt: '2021-07-23T08:51:20.615Z',
          description: null,
          tags: ['可收款', '单数::50'],
          proxyHost: '3.219.220.131',
          proxyPort: 4445,
          proxyUsername: 'u61310',
          __typename: 'Gateway',
        },
      ]}
      search={{
        queryProps: {
          placeholder: '筛选网关',
        },
        defaultSortValue: {
          field: 'createdAt',
          direction: 'DESC',
        },
        sortOptions: [
          {
            label: '创建时间（升序）',
            field: 'createdAt',
            direction: 'ASC',
          },
          {
            label: '创建时间（降序）',
            field: 'createdAt',
            direction: 'DESC',
          },
        ],
        selectedViews: {
          config: [
            {
              name: '沙盒',
              id: 'isSandbox',
              filters: {
                isSandbox: true,
              },
              orderBy: { field: 'createdAt', direction: 'DESC' },
            },
            {
              name: '线上',
              id: 'isNotSandbox',
              filters: {
                isSandbox: false,
              },
              orderBy: { field: 'createdAt', direction: 'DESC' },
            },
          ],
          store: {
            get: async () => {
              // 发送请求服务端视图数据
              await new Promise((resolve, reject) => {
                setTimeout(() => {
                  resolve();
                }, 1000);
              });
              return [];
            },
            add: async params => {
              try {
                // 发送请求添加视图，成功后要返回添加的 id 和 success 为 true，失败返回 success 为 false
                await new Promise((resolve, reject) => {
                  setTimeout(() => {
                    resolve();
                  }, 2000);
                });
                return {
                  id: '...',
                  success: true,
                };
              } catch (error) {
                return {
                  success: false,
                };
              }
            },
            remove: id => {
              try {
                // 发送请求删除视图，成功后要返回 success
                new Promise((resolve, reject) => {
                  setTimeout(() => {
                    resolve();
                  }, 2000);
                });
                return {
                  success: true,
                };
              } catch (error) {
                return {
                  success: false,
                };
              }
            },
            update: ({ id, name }) => {
              try {
                // 发送请求更新视图，成功后要返回 success
                return {
                  success: true,
                };
              } catch (error) {
                return {
                  success: false,
                };
              }
            },
          },
        },
      }}
      columns={[
        {
          copyable: true,
          dataIndex: 'ID',
          title: 'ID',
          filterType: 'input',
          search: {
            phrase: true,
          },
        },
        {
          dataIndex: 'name',
          title: '名称',
          filterType: 'input',
        },
        {
          dataIndex: 'isEnable',
          title: '开关',
          search: {
            shortcut: true,
            searchParamType: Boolean,
          },
          filterType: 'checkbox',
          valueEnum: [
            { label: '开启', value: true },
            { label: '关闭', value: false },
          ],
          render: text => {
            return text ? <NewBadge>开启</NewBadge> : <NewBadge>关闭</NewBadge>;
          },
        },
        {
          dataIndex: 'isAvailable',
          title: '可用性',
          search: {
            shortcut: true,
            searchParamType: Boolean,
          },
          filterType: 'radio',
          valueEnum: [
            { label: '有效', value: true },
            { label: '无效', value: false },
          ],
          render: text => {
            return text ? <NewBadge>有效</NewBadge> : <NewBadge>无效</NewBadge>;
          },
        },
        {
          dataIndex: 'isSandbox',
          title: '环境',
          search: {
            shortcut: true,
            searchParamType: Boolean,
          },
          filterType: 'radio',
          valueEnum: [
            { label: '沙盒', value: true },
            { label: '线上', value: false },
          ],
          render: text => {
            return text ? <NewBadge>沙盒</NewBadge> : <NewBadge>线上</NewBadge>;
          },
        },
        {
          dataIndex: 'tags',
          title: '标签',
          search: { shortcut: true },
          filterType: 'input',
          valueType: 'tag',
        },
        {
          dataIndex: 'limit',
          title: '总额度',
          valueType: {
            type: 'money',
            currency: 'USD',
          },
        },
        {
          dataIndex: 'balance',
          title: '剩余额度',
          valueType: {
            type: 'money',
            currency: 'USD',
          },
        },
        {
          copyable: true,
          dataIndex: 'domain',
          title: '域名',
          filterType: 'input',
        },
        {
          copyable: true,
          dataIndex: 'email',
          title: '邮箱',
          filterType: 'input',
        },
        {
          dataIndex: 'createdAt',
          title: '创建时间',
          align: 'left',
          filterType: 'dateTimeRange',
          valueType: 'dateTime',
        },
      ]}
      scroll={{ x: 'max-content' }}
      id="id"
      rowKey="ID"
      request={(params, id) => {
        console.log(params, id);
      }}
    />
  </Story>
</Canvas>

# API

#### <font color="red">注意事项：</font>

<font color="red">
  1、存储起来的筛选键值对的 key 值的优先级为 column 的 key > dataIndex，若 dataIndex
  为数组，则为最后一位。
</font>

| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| id | 表格的唯一 id，当 存储至 localStorage 的 key 值 | string | - |
| syncToUrl | 是否将筛选与 url 保存同步 | boolean | false |
| actionRef | 操作 | MutableRefObject<[ApolloTableActionType](#ApolloTableActionType)\> | - |
| pageInfo | 当前页的信息 | { startCursor: string \| null; endCursor: string \| null; hasPreviousPage: boolean; hasNextPage: boolean; } | - |
| search | 表格是否显示筛选排序，可配置筛选栏右边的额外操作 | false \| [searchProps](#searchProps) | - |
| pagination | 分页配置 | { pageSize: number; hideOnSinglePage: boolean } \| false | { pageSize: 10 } |
| request | 筛选排序改变触发 | (params) => Promise<void\> \| void | - |
| debounceTime | 防抖时间，必须大于 0 | number | 300 |
| options | 列配置 | {options: boolean} \| false | {options: true} |
| tableAlertRender | 配置批量操作工具栏，如果设置了 components 的 header 的 row（用此实现，会覆盖），将失效 | [tableAlertRenderProps](#tableAlertRenderProps) \| false | - |
| rowSelection | 批量操作配置，只列出多加的三个属性，开启允许全选模式 | {allowSelectAll?: boolean; selectAllDisabled?: boolean; onSelectedAllChange: (isSelectedAll: boolean) => void } | false |

#### searchProps

```
{
  extra?: ReactNode;
  helpText?: ReactNode;
  sortOptions?: { field: string; direction: OrderDirection; label: string }[];
  defaultSortValue?: {field: string; direction: OrderDirection };
  queryProps?: Omit<InputProps,"value" \| "defaultValue">;
  // 更多筛选器清除全部按钮回调
  onClearAll?: () => void;
  onSortChange?: (e: RadioChangeEvent) => void;
  selectedViews: {
    config?: {
      name: string;   // tab 的名称
      id: string;     // tab 显示在 url 上的 key
      query?: string;
      orderBy?: { field: string; direction: OrderDirection } | null;
      filters?: Record<string, any>;
    }[];
    // 服务端保存视图需要配置 store
    store?: {
      get: () => Promise<{
        name: string;
        id: string;
        query?: string;
        orderBy?: { field: string; direction: OrderDirection } | null;
        filters?: Record<string, any>;
      }[]>;
      add: (params: {
        name: string;
        query: string;
        orderBy: { field: string; direction: OrderDirection } | null;
        filters: Record<string, any>;
      }) => Promise<{ id?: string; success?: boolean }>;
      remove: (id: string) => Promise<{ success: boolean }>;
      update: (params: { id: string; name: string }) => Promise<{ success: boolean }>;
  };
  };
}
```

#### tableAlertRender

```
({
  selectedRowKeys: (number | string)[];
  selectedRows: T[];
  onCleanSelected: () => void;
  // 是否开启全选模式
  isSelectedAll: boolean;
}) => ({
  // 直接显示在操作栏
  promotedBulkActions?: {
    content: string;
    hidden?: boolean;
    disabled?: boolean;
    onClick: React.MouseEventHandler<HTMLElement>;
  }[];
  // 显示在其它操作里
  bulkActions?: {
    content: string;
    hidden?: boolean;
    disabled?: boolean;
    onClick: (e: React.MouseEvent<HTMLElement, MouseEvent>) => void;
  }[];
})
```

### Column（相对 antd 新增）

| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| copyable | 显示复制按钮 | boolean | false |
| valueType | 值的类型 | [ValueType](#ValueType) \| [ValueObjectType](#ValueObjectType) \| [ValueTypeFunction](#ValueTypeFunction) | - |
| filterType | 筛选的类型 | 'input' \| 'select' \| 'radio' \| 'checkbox' \| 'dateRange' \| 'dateRangeTime' | - |
| fieldProps | 筛选控件对应的 props | any | - |
| search | 配置 | {shortcut?: boolean; phrase?: boolean; searchParamType?: (val: string) => any; disabled?: boolean; allowClear?: boolean; onRemove?: () => void} | - |
| hidden | 在表格中不显示 | boolean | false |

### searchParamType：若 valueEnum 的 value 值为 boolean 类型或 number 类型要定义类型

```
searchParamType: Boolean
或
searchParamType: Number
或自定义 return 一个值
searchParamType: (val) => ...
```

### ApolloTableActionType

```
  interface ActionType {
    reload: () => void;  按照当前筛选条件重新请求
    apolloQuery: string; // 拼接好的 query 值
    queryValue: string;  // 输入框值
    sortValue: {field: string, direction: OrderDirection} | undefined; // 排序值
    filterValues: Record<string,any>;  // 筛选值
    setQueryValue: (value: string) => void; 设置输入框值，
    setSortValue: (value: {field: string, direction: OrderDirection}) => void; 设置排序值
    setFilterValues: (value: Record<string, any>) => void; 设置筛选值
    resetAndReload: () => void; 清空全部筛选条件、清空批量选择、回到第一页，并重新请求
    clearSelected: () => void; 清空选中，退出全选模式
}

const tableRef = useRef<ApolloTableActionType>();

tableRef.current.reload();

```

#### ValueType

| 类型       | 描述             | 渲染结果示例            |
| ---------- | ---------------- | ----------------------- |
| 'date'     | 日期             | 2020-11-16              |
| 'dateTime' | 日期和时间       | 2020-11-16 12:50:00     |
| 'time'     | 时间             | 12:50:00                |
| 'index'    | 行号             | -                       |
| 'percent'  | 百分号           | 23%                     |
| 'number'   | 数字             | 23.23                   |
| 'money'    | 货币             | ¥10,000.26、\$100、€100 |
| 'tag'      | 标签，值要为数组 | -                       |

#### ValueObjectType

##### 1. percent

| valueType 参数 | 参数类型  | 描述                       | 示例        |
| -------------- | --------- | -------------------------- | ----------- |
| type           | 'percent' | 当 type 为 'percent' 时    | -           |
| showSymbol     | boolean   | 是否显示正负号             | +23% (-23%) |
| useGrouping    | boolean   | 是否显示分隔符             | 10,000.00%  |
| precision      | number    | 保留小数点后位数，默认两位 | 23.00%      |

##### 2. money

| valueType 参数 | 参数类型 | 描述 | 示例 |
| --- | --- | --- | --- |
| type | 'money' | 当 type 为 'money' 时 | - |
| currency | string ｜（value:any, record:T, index:number）=> string | 货币代码 | "USD" |
| useGrouping | boolean | 是否显示分隔符 | \$10,000,000 |

#### 3. number

| valueType 参数 | 参数类型 | 描述                        | 示例       |
| -------------- | -------- | --------------------------- | ---------- |
| type           | 'number' | 当 type 为 'number' 时      | -          |
| precision      | number   | 保留小数点后位数，默认 3 位 | 23.000     |
| useGrouping    | boolean  | 是否显示分隔符              | 10,000,000 |

#### 4. tag

| valueType 参数 | 参数类型 | 描述 | 示例 |
| --- | --- | --- | --- | --- |
| type | 'tag' | 当 type 为 'tag' 时 | - |
| onClick | (tag: (string | number)[], value: any, record: T, index: number) => void | tag 点击回调 | - |

#### ValueTypeFunction

```
  (text, record, index ) => ValueType | ValueObjectType
```

### 获取 url 和 localStorage 参数的方法

| 名称                      | 说明                        | 类型                                |
| ------------------------- | --------------------------- | ----------------------------------- |
| getApolloTableQueryParams | 获取对应表格的 url 筛选参数 | (id: string) => Record<string, any> |

```
使用
getApolloTableQueryParams("tableId")
```

### 如需从其它页面跳到到表格页面并携带 url 参数，要遵循以下规则。

键值是对应的值（上方注意事项有说明键值对的 key），数组要用逗号(,)隔开，例如 多选 和 时间范围

```
示例
history.push({
  pathname: "/aa",
  query: {
    title: "123",
    date: [moment().toISOString(), moment().toISOString()].join(","),
    checkbox: ["a","b"].join(",")
  },
})
```
