npm package: @magicbe/antd-crud
Description: antd crud table
Author: wang quan
Latest version: 0.0.63

# @magicbe/antd-crud

一个基于 Ant Design 的 CRUD 表格组件库，简化开发中的增删改查操作。

## 特性

- 快速构建完整的 CRUD 表格界面
- 支持多种表单字段类型
- 内置筛选、新增、编辑、删除功能
- 支持主操作按钮和行操作按钮
- 支持操作钩子函数（before/handle/after）
- 支持字段动态显示/隐藏
- 支持错误弹窗配置
- 基于 Ant Design，样式统一

## 安装

```bash
# 使用 npm
npm install @magicbe/antd-crud

# 使用 yarn
yarn add @magicbe/antd-crud

# 使用 pnpm
pnpm add @magicbe/antd-crud
```

## 依赖

- antd: 5.22.5+
- react: 18.2.0+
- react-dom: 18.2.0+

## 基本使用

```tsx
import React from 'react';
import { CrudTable, type ContentProps, type ColumnType, type delHandle, type editHandle, type addHandle } from '@magicbe/antd-crud';

interface User {
    id: number;
    name: string;
    age: number;
    address: string;
}

const columns: ColumnType<User>['columns'] = [
    {
        title: '姓名',
        dataIndex: 'name',
        filter: 'Input',
        field: {
            type: 'Input',
            rules: [{ required: true }],
        },
        add: true,
        edit: true,
    },
    {
        title: '年龄',
        dataIndex: 'age',
        field: 'InputNumber',
        add: true,
        edit: true,
    },
    {
        title: '地址',
        dataIndex: 'address',
        field: 'TextArea',
        add: true,
        edit: true,
    },
    {
        title: "所属区域",
        dataIndex: "region",
        field: {
            type: "Select",
            option: {
                options: [
                    { label: "区域1", value: "1" },
                    { label: "区域2", value: "2" },
                ]
            },
            rules: [{ required: true }]
        },
        edit: true,
    },
];

const App: React.FC = () => {
    const getSources: ContentProps<User>['getSources'] = async (params: any = {}) => {
        const {
            current: page = 1,
            pageSize: size = 10,
        } = params;

        return {
            sources: [
                { id: 1, name: '张三', age: 28, address: '北京市海淀区' },
                { id: 2, name: '李四', age: 32, address: '上海市浦东新区' },
            ],
            total: 2,
            page,
            size,
        };
    };

    const add: addHandle = async (value) => {
        console.log('add:', value);
        return Promise.resolve();
    };

    const edit: editHandle = async (value) => {
        console.log('edit:', value);
        return Promise.resolve();
    };

    const del: delHandle = async (value) => {      
        console.log('delete:', value);
        return Promise.resolve();
    };

    return (
        <CrudTable
            columns={columns}
            getSources={getSources}
            add={add}
            edit={edit}
            del={del}
            rowKey="id"
        />
    );
};

export default App;
```

## API 文档

### CrudTable

主要组件，集成了筛选、操作按钮和表格功能。

#### 属性

| 属性名 | 类型 | 说明 |
|--------|------|------|
| columns | ColumnType[] | 表格列配置 |
| getSources | (params?: GetSourceFunctionParams) => Promise\<Source\> | 获取数据的方法 |
| add | add \| addHandleMap | 新增操作方法 |
| edit | edit \| editHandleMap | 编辑操作方法 |
| del | delHandle \| Partial\<HandleMap\<delHandle\>\> | 删除操作方法 |
| action | Action | 自定义操作按钮 |
| rowSelection | RowSelectionType \| AntdTableProps['rowSelection'] | 行选择配置 |
| pagination | false | 是否显示分页（暂仅支持false） |
| drawer | number \| DrawerProps | 抽屉配置 |
| pageSizeOptions | PaginationProps['pageSizeOptions'] | 每页条数选项 |
| actionColumn | ColumnType\<any\> | 操作列配置 |
| rowKey | string \| ((record: any) => string) | 行数据的唯一标识 |

### ColumnType

表格列配置，继承自 Ant Design 的 ColumnType，增加了以下属性：

| 属性名 | 类型 | 说明 |
|--------|------|------|
| field | ColumnFieldKeys \| ColumnField \| React.FC | 表单字段类型 |
| filter | boolean \| ColumnFieldKeys \| ColumnField \| React.FC | 筛选字段类型 |
| add | boolean \| ColumnFieldKeys \| ColumnField \| React.FC | 新增表单字段类型 |
| edit | boolean \| ColumnFieldKeys \| ColumnField \| React.FC | 编辑表单字段类型 |

### ColumnField 类型

支持的表单字段类型：

| 类型 | 说明 |
|------|------|
| Hidden | 隐藏字段 |
| Input | 输入框 |
| Input.Password | 密码输入框 |
| TextArea | 长文本输入框 |
| InputNumber | 数字输入框 |
| Select | 选择器 |
| Cascader | 级联选择 |
| TreeSelect | 树选择 |
| Checkbox | 多选框 |
| Checkbox.Group | 多选框组 |
| DatePicker | 日期选择框 |
| DatePicker.YearPicker | 年选择框 |
| DatePicker.MonthPicker | 月选择框 |
| DatePicker.WeekPicker | 周选择框 |
| DatePicker.TimePicker | 时间选择框 |
| DatePicker.RangePicker | 时间范围选择框 |
| DatePicker.QuarterPicker | 季度选择框 |
| TimePicker | 时间选择框 |
| TimePicker.RangePicker | 时间范围选择框 |
| Radio | 单选框 |
| Radio.Group | 单选框组 |
| Switch | 开关 |

### ColumnField 配置

```tsx
interface BaseColumnField<T extends string, O = any> {
    type: T;
    option?: O;
    rules?: Rule[];
    order?: number;
    filter?: (values: AnyObject, form: FormInstance) => boolean;
}
```

| 属性名 | 类型 | 说明 |
|--------|------|------|
| type | string | 字段类型 |
| option | object | 传递给组件的属性 |
| rules | Rule[] | 表单验证规则 |
| order | number | 字段排序 |
| filter | (values, form) => boolean | 动态显示/隐藏字段 |

### Source 类型

```tsx
type Source<RecordType = AnyObject> = {
    sources: RecordType[];
    total?: number;
    page?: number;
    size?: number;
}
```

### 操作方法

#### add / edit 方法

支持两种形式：

```tsx
type addHandle = (value: any, selection: Selection) => Promise<any>;

type addHandleMap = Partial<HandleMap<addHandle>> & {
    init?: addHandleInit
};

type add = addHandle | addHandleMap;
```

**简单形式：**

```tsx
const add: addHandle = async (value, selection) => {
    console.log(value, selection);
};
```

**钩子形式：**

```tsx
const add: addHandleMap = {
    init: async (selection) => {
        return { name: '默认值' };
    },
    before: async (value, selection) => {},
    handle: async (value, selection) => {},
    after: async (value, selection) => {},
};
```

#### del 方法

```tsx
type delHandle = (selection: Selection) => Promise<any>;

type del = delHandle | Partial<HandleMap<delHandle>>;
```

### Selection 类型

```tsx
interface Selection<RecordType = AnyObject> {
    keys?: React.Key[];
    rows?: RecordType[];
}
```

### Action 配置

操作按钮支持多种配置方式：

```tsx
type Action = boolean | React.FC | React.FC[] | CustomAction;

interface CustomAction {
    master?: boolean | React.FC | React.FC[] | MasterCustomActionGroup;
    record?: boolean | React.FC | React.FC[] | RecordCustomActionGroup;
}

interface MasterCustomActionGroup {
    add?: boolean | React.FC;
    del?: boolean | React.FC;
    edit?: boolean | React.FC;
}

interface RecordCustomActionGroup {
    add?: boolean | React.FC;
    del?: boolean | React.FC;
    edit?: boolean | React.FC;
}
```

### 导出组件

#### TableContextProvider 和 useTableContext

提供表格上下文，可用于自定义组件中获取表格状态和方法。

```tsx
import { TableContextProvider, useTableContext } from '@magicbe/antd-crud';

const CustomComponent: React.FC = () => {
    const { table_ref, filter_ref, form_ref, add, edit, del } = useTableContext();
    
    const handleRefresh = () => {
        table_ref?.current?.loadRecords();
    };
    
    return <button onClick={handleRefresh}>刷新数据</button>;
};
```

#### Filter

筛选组件，可单独使用。

#### Action

主操作按钮组件，提供了新增、编辑、删除等默认操作。

导出的子组件：
- `AppendAction` (别名: `MastAppend`) - 新增按钮
- `DeleteAction` (别名: `MastDelete`) - 删除按钮
- `EditAction` (别名: `MastEdit`) - 编辑按钮

#### Table

表格组件，继承自 Ant Design 的 Table。

导出的子组件：
- `AppendAction` (别名: `RowAppend`) - 行新增按钮
- `DeleteAction` (别名: `RowDelete`) - 行删除按钮
- `EditAction` (别名: `RowEdit`) - 行编辑按钮

#### DrawerContentContextProvider 和 useDrawerContentContext

抽屉内容上下文，用于控制抽屉的渲染位置。

```tsx
import { DrawerContentContextProvider, useDrawerContentContext } from '@magicbe/antd-crud';
```

#### CrudConfigProvider

配置提供者，继承自 Ant Design 的 ConfigProvider。

```tsx
import { CrudConfigProvider, CrudConfigContextProvider, useCrudConfigContext } from '@magicbe/antd-crud';

interface CustomConfigProviderProps {
    showErrorModal?: boolean;
}

const App: React.FC = () => {
    return (
        <CrudConfigProvider 
            theme={{ token: { colorPrimary: '#1890ff' } }}
            showErrorModal={false}
        >
            <CrudTable {...props} />
        </CrudConfigProvider>
    );
};
```

### ContentRef

通过 ref 暴露的方法：

```tsx
interface ContentRef<RecordType = AnyObject> {
    filter_ref: React.RefObject<FilterRef>;
    action_ref: React.RefObject<ActionRef>;
    table_ref: React.RefObject<TableRef<RecordType>>;
    form_ref: React.RefObject<FormRef>;
}

interface TableRef<RecordType = AnyObject> {
    getPageData: () => { current?: number; pageSize?: number };
    getRecords: () => RecordType[];
    loadRecords: (params?: any) => void;
    selected_keys: React.Key[];
    selected_rows: RecordType[];
    setSelected_keys: React.Dispatch<React.SetStateAction<React.Key[]>>;
    setSelected_rows: React.Dispatch<React.SetStateAction<RecordType[]>>;
}
```

## 高级用法

### 自定义操作按钮

```tsx
<CrudTable
    columns={columns}
    getSources={getSources}
    action={{
        master: {
            add: true,
            del: true,
        },
        record: {
            edit: true,
            del: true,
        },
    }}
/>
```

### 使用自定义组件

```tsx
const CustomAddButton: React.FC = () => {
    return <Button type="primary">自定义新增</Button>;
};

<CrudTable
    action={{
        master: {
            add: CustomAddButton,
        },
    }}
/>
```

### 字段动态显示

```tsx
const columns: ColumnType[] = [
    {
        title: '类型',
        dataIndex: 'type',
        field: {
            type: 'Select',
            option: {
                options: [
                    { label: '类型A', value: 'A' },
                    { label: '类型B', value: 'B' },
                ]
            }
        },
    },
    {
        title: '类型A专属字段',
        dataIndex: 'fieldA',
        field: {
            type: 'Input',
            filter: (values, form) => values.type === 'A',
        },
    },
];
```

### 使用 ref 控制表格

```tsx
import { CrudTable, type ContentRef } from '@magicbe/antd-crud';

const App: React.FC = () => {
    const crudRef = React.useRef<ContentRef>(null);

    const handleRefresh = () => {
        crudRef.current?.table_ref.current?.loadRecords();
    };

    const getSelectedRows = () => {
        return crudRef.current?.table_ref.current?.selected_rows;
    };

    return (
        <>
            <Button onClick={handleRefresh}>刷新</Button>
            <CrudTable ref={crudRef} {...props} />
        </>
    );
};
```

## 注意事项

1. 组件依赖 antd 5.22.5 及以上版本，请确保项目中 antd 版本符合要求。
2. 目前 pagination 仅支持设置为 false，分页功能内置实现。
3. 自定义组件时，请使用 TableContextProvider 包裹以确保能正确获取上下文。
4. 使用 `showErrorModal` 配置可以控制是否在操作失败时显示错误弹窗。

## License

MIT