gzkx-package 0.1.46 → 0.1.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1068 -168
- package/dist/components/customComponents/commonPage/index.d.ts +3 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +12 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,269 +1,1169 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 自定义组件使用文档
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
本文档详细介绍了项目中四个核心自定义组件的使用方法和参数说明。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 目录
|
|
8
|
+
|
|
9
|
+
- [安装](#安装)
|
|
10
|
+
- [快速开始](#快速开始)
|
|
11
|
+
- [组件列表](#组件列表)
|
|
12
|
+
1. [CommonPage 通用页面组件](#1-commonpage-通用页面组件)
|
|
13
|
+
2. [CustomTable 自定义表格组件](#2-customtable-自定义表格组件)
|
|
14
|
+
3. [CustomForm 自定义表单组件](#3-customform-自定义表单组件)
|
|
15
|
+
4. [CustomAdd 新增/编辑弹窗组件](#4-customadd-新增编辑弹窗组件)
|
|
16
|
+
|
|
17
|
+
---
|
|
4
18
|
|
|
5
19
|
## 安装
|
|
6
20
|
|
|
21
|
+
### 使用 npm
|
|
22
|
+
|
|
7
23
|
```bash
|
|
8
24
|
npm install gzkx-package
|
|
9
|
-
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### 使用 yarn
|
|
28
|
+
|
|
29
|
+
```bash
|
|
10
30
|
yarn add gzkx-package
|
|
11
|
-
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 使用 pnpm
|
|
34
|
+
|
|
35
|
+
```bash
|
|
12
36
|
pnpm add gzkx-package
|
|
13
37
|
```
|
|
14
38
|
|
|
15
|
-
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 快速开始
|
|
42
|
+
|
|
43
|
+
### 1. 安装依赖
|
|
44
|
+
|
|
45
|
+
确保项目中已安装以下依赖(peerDependencies):
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm install antd axios dayjs lodash pinyin-pro react react-dom
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**版本要求:**
|
|
52
|
+
- `antd`: ^5.0.0
|
|
53
|
+
- `axios`: ^1.0.0
|
|
54
|
+
- `dayjs`: ^1.11.0
|
|
55
|
+
- `lodash`: ^4.17.0
|
|
56
|
+
- `pinyin-pro`: ^3.0.0
|
|
57
|
+
- `react`: ^18.0.0 或 ^19.0.0
|
|
58
|
+
- `react-dom`: ^18.0.0 或 ^19.0.0
|
|
59
|
+
|
|
60
|
+
### 2. 引入样式
|
|
61
|
+
|
|
62
|
+
在项目入口文件(如 `main.tsx` 或 `App.tsx`)中引入样式:
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
// 引入 Ant Design 样式
|
|
66
|
+
import 'antd/dist/reset.css';
|
|
67
|
+
|
|
68
|
+
// 引入组件库样式
|
|
69
|
+
import 'gzkx-package/style';
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 3. 基本使用
|
|
16
74
|
|
|
17
|
-
|
|
75
|
+
导入并使用组件:
|
|
18
76
|
|
|
19
77
|
```tsx
|
|
20
|
-
import React from 'react';
|
|
21
78
|
import { CommonPage } from 'gzkx-package';
|
|
22
|
-
|
|
79
|
+
import type { FormItemConfig } from 'gzkx-package';
|
|
80
|
+
import type { AddItemConfig } from 'gzkx-package';
|
|
23
81
|
import 'gzkx-package/dist/style.css';
|
|
24
82
|
|
|
25
|
-
|
|
26
|
-
|
|
83
|
+
|
|
84
|
+
const MyPage = () => {
|
|
85
|
+
// 搜索表单配置
|
|
86
|
+
const searchFormConfig: FormItemConfig[] = [
|
|
87
|
+
{
|
|
88
|
+
type: 'input',
|
|
89
|
+
label: '姓名',
|
|
90
|
+
name: 'name',
|
|
91
|
+
colSpan: 6,
|
|
92
|
+
},
|
|
93
|
+
];
|
|
94
|
+
|
|
95
|
+
// 新增/编辑表单配置
|
|
96
|
+
const addFormConfig: AddItemConfig[] = [
|
|
97
|
+
{
|
|
98
|
+
type: 'input',
|
|
99
|
+
label: '姓名',
|
|
100
|
+
name: 'name',
|
|
101
|
+
rules: [{ required: true, message: '请输入姓名' }],
|
|
102
|
+
colSpan: 12,
|
|
103
|
+
},
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
// 表格列配置
|
|
107
|
+
const tableColumns = [
|
|
108
|
+
{
|
|
109
|
+
title: '姓名',
|
|
110
|
+
dataIndex: 'name',
|
|
111
|
+
key: 'name',
|
|
112
|
+
width: 150,
|
|
113
|
+
},
|
|
114
|
+
];
|
|
115
|
+
|
|
116
|
+
// API 地址配置
|
|
117
|
+
const URL = {
|
|
118
|
+
search: '/user/list',
|
|
119
|
+
add: '/user/add',
|
|
120
|
+
edit: '/user/edit',
|
|
121
|
+
delete: '/user/delete',
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
return (
|
|
125
|
+
<CommonPage
|
|
126
|
+
searchFormConfig={searchFormConfig}
|
|
127
|
+
addFormConfig={addFormConfig}
|
|
128
|
+
tableColumns={tableColumns}
|
|
129
|
+
URL={URL}
|
|
130
|
+
tableId="my-table"
|
|
131
|
+
isReset={true}
|
|
132
|
+
/>
|
|
133
|
+
);
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
export default MyPage;
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### 4. 导出组件列表
|
|
140
|
+
|
|
141
|
+
本组件库主要导出以下组件:
|
|
142
|
+
|
|
143
|
+
| 组件名 | 说明 | 导入方式 |
|
|
144
|
+
|--------|------|---------|
|
|
145
|
+
| `CommonPage` | 通用页面组件 | `import { CommonPage } from 'gzkx-package'` |
|
|
146
|
+
| `CustomTable` | 自定义表格组件 | `import { CustomTable } from 'gzkx-package'` |
|
|
147
|
+
| `CustomForm` | 自定义表单组件 | `import { CustomForm } from 'gzkx-package'` |
|
|
148
|
+
| `CustomAdd` | 新增/编辑弹窗组件 | `import { CustomAdd } from 'gzkx-package'` |
|
|
149
|
+
|
|
150
|
+
### 5. TypeScript 类型导出
|
|
151
|
+
|
|
152
|
+
```tsx
|
|
153
|
+
import type {
|
|
154
|
+
FormItemConfig, // 搜索表单配置类型
|
|
155
|
+
AddItemConfig, // 新增/编辑表单配置类型
|
|
156
|
+
ValidateConfig, // 验证配置类型
|
|
157
|
+
CommonPageHandle, // CommonPage Ref 类型
|
|
158
|
+
} from 'gzkx-package';
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 组件列表
|
|
164
|
+
|
|
165
|
+
## 1. CommonPage 通用页面组件
|
|
166
|
+
|
|
167
|
+
### 1.1 组件概述
|
|
168
|
+
|
|
169
|
+
`CommonPage` 是一个集成了搜索表单、数据表格、新增/编辑弹窗的通用页面组件,适用于大部分 CRUD 操作场景。
|
|
170
|
+
|
|
171
|
+
### 1.2 Props 参数
|
|
172
|
+
|
|
173
|
+
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|
|
174
|
+
|--------|------|------|--------|------|
|
|
175
|
+
| `searchFormConfig` | `FormItemConfig[] \| null` | 是 | - | 搜索表单配置项数组 |
|
|
176
|
+
| `addFormConfig` | `AddItemConfig[]` | 是 | - | 新增/编辑表单配置项数组 |
|
|
177
|
+
| `tableColumns` | `any[]` | 是 | - | 表格列配置数组 |
|
|
178
|
+
| `URL` | `object` | 是 | - | API 接口地址配置,包含 `search`, `add`, `edit`, `delete`, `view` |
|
|
179
|
+
| `tableId` | `string` | 否 | - | 表格唯一 ID,用于保存用户的表格配置 |
|
|
180
|
+
| `isnopage` | `boolean` | 否 | `false` | 是否不分页 |
|
|
181
|
+
| `topHeight` | `number` | 否 | - | 顶部高度(像素) |
|
|
182
|
+
| `tableHeight` | `number` | 否 | `150` | 表格高度调整参数 |
|
|
183
|
+
| `actionWidth` | `number` | 否 | `150` | 操作列宽度 |
|
|
184
|
+
| `editText` | `string` | 否 | `'编辑'` | 编辑按钮文本 |
|
|
185
|
+
| `viewText` | `string` | 否 | `'查看'` | 查看按钮文本 |
|
|
186
|
+
| `delText` | `string` | 否 | `'删除'` | 删除按钮文本 |
|
|
187
|
+
| `isaddtab` | `boolean` | 否 | `false` | 新增/编辑表单是否分 Tab 显示 |
|
|
188
|
+
| `isReset` | `boolean` | 否 | `false` | 是否显示重置按钮 |
|
|
189
|
+
| `addisdisabled` | `object` | 否 | `{ isdisabled: false, message: '' }` | 新增按钮禁用配置 |
|
|
190
|
+
| `postParams` | `object` | 否 | - | 请求参数配置对象 |
|
|
191
|
+
| `limit` | `object` | 否 | 全部为 `true` | 操作权限限制配置 |
|
|
192
|
+
| `CustomOperations` | `ReactNode \| Function` | 否 | - | 自定义操作列内容 |
|
|
193
|
+
| `PropOtherButton` | `ReactNode \| Function` | 否 | - | 搜索表单右侧的其他按钮 |
|
|
194
|
+
| `CustomModalFooter` | `Function` | 否 | - | 自定义弹窗底部按钮 |
|
|
195
|
+
| `proplist` | `any[]` | 否 | - | 假数据(用于测试) |
|
|
196
|
+
| `editdclickback` | `Function` | 否 | - | 点击编辑/新增时的回调函数 |
|
|
197
|
+
| `oneditFormChange` | `Function` | 否 | - | 编辑表单值变化时的回调 |
|
|
198
|
+
| `onSearchFormChange` | `Function` | 否 | - | 搜索表单值变化时的回调 |
|
|
199
|
+
| `onRowClick` | `Function` | 否 | - | 表格行点击回调 |
|
|
200
|
+
| `onDelete` | `Function` | 否 | - | 删除成功后的回调 |
|
|
201
|
+
| `onSearch` | `Function` | 否 | - | 搜索按钮点击后的回调 |
|
|
202
|
+
| `onReset` | `Function` | 否 | - | 重置按钮点击后的回调 |
|
|
203
|
+
| `onView` | `Function` | 否 | - | 查看按钮点击后的回调 |
|
|
204
|
+
| `validateConfig` | `ValidateConfig` | 否 | - | 表单验证配置 |
|
|
205
|
+
| `tableConfig` | `any` | 否 | - | 表格额外配置 |
|
|
206
|
+
|
|
207
|
+
#### 1.2.1 详细参数说明
|
|
208
|
+
|
|
209
|
+
**postParams 对象结构:**
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
{
|
|
213
|
+
addParams?: any; // 新增时额外携带的参数
|
|
214
|
+
delParams?: any; // 删除时额外携带的参数
|
|
215
|
+
editParams?: any; // 编辑时额外携带的参数
|
|
216
|
+
searchParams?: any; // 搜索时额外携带的参数
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
**limit 对象结构:**
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
{
|
|
224
|
+
addLimit?: boolean; // 是否显示新增按钮,默认 true
|
|
225
|
+
delLimit?: boolean; // 是否显示删除按钮,默认 true
|
|
226
|
+
editLimit?: boolean; // 是否显示编辑按钮,默认 true
|
|
227
|
+
searchLimit?: boolean; // 是否显示搜索功能,默认 true
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**URL 对象结构:**
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
{
|
|
235
|
+
search: string; // 查询接口地址
|
|
236
|
+
add?: string; // 新增接口地址
|
|
237
|
+
edit?: string; // 编辑接口地址
|
|
238
|
+
delete?: string; // 删除接口地址
|
|
239
|
+
view?: string; // 查看接口地址(可选,如果没有则使用 edit)
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### 1.3 Ref 暴露的方法
|
|
244
|
+
|
|
245
|
+
使用 `ref` 可以调用组件内部方法:
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
interface CommonPageHandle {
|
|
249
|
+
getList: (parentParams?: any) => Promise<void>; // 刷新列表
|
|
250
|
+
setFieldsValue: (values: any) => void; // 设置表单字段值
|
|
251
|
+
getFieldsValue: () => any; // 获取表单字段值
|
|
252
|
+
reload: () => void; // 重新加载列表
|
|
253
|
+
getSearchFieldsValue: () => any; // 获取搜索表单值
|
|
254
|
+
setSearchFieldsValue: (values: any) => void; // 设置搜索表单值
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### 1.4 使用示例
|
|
259
|
+
|
|
260
|
+
```tsx
|
|
261
|
+
import { useRef } from 'react';
|
|
262
|
+
import CommonPage, { CommonPageHandle } from '@/components/customComponents/commonPage';
|
|
263
|
+
import { FormItemConfig } from '@/components/customComponents/CustomForm';
|
|
264
|
+
import { AddItemConfig } from '@/components/customComponents/CustomAdd';
|
|
265
|
+
|
|
266
|
+
const DemoPage = () => {
|
|
267
|
+
const pageRef = useRef<CommonPageHandle>(null);
|
|
268
|
+
|
|
269
|
+
// 搜索表单配置
|
|
270
|
+
const searchFormConfig: FormItemConfig[] = [
|
|
27
271
|
{
|
|
28
272
|
type: 'input',
|
|
29
|
-
label: '
|
|
273
|
+
label: '姓名',
|
|
30
274
|
name: 'name',
|
|
31
|
-
placeholder: '
|
|
275
|
+
placeholder: '请输入姓名',
|
|
276
|
+
colSpan: 6,
|
|
32
277
|
},
|
|
33
278
|
{
|
|
34
279
|
type: 'select',
|
|
35
280
|
label: '状态',
|
|
36
281
|
name: 'status',
|
|
37
282
|
options: [
|
|
38
|
-
{ label: '启用', value:
|
|
39
|
-
{ label: '禁用', value:
|
|
283
|
+
{ label: '启用', value: 1 },
|
|
284
|
+
{ label: '禁用', value: 0 },
|
|
40
285
|
],
|
|
286
|
+
colSpan: 6,
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
type: 'rangePicker',
|
|
290
|
+
label: '日期范围',
|
|
291
|
+
name: 'createTime/endTime',
|
|
292
|
+
colSpan: 6,
|
|
41
293
|
},
|
|
42
294
|
];
|
|
43
295
|
|
|
44
|
-
|
|
296
|
+
// 新增/编辑表单配置
|
|
297
|
+
const addFormConfig: AddItemConfig[] = [
|
|
45
298
|
{
|
|
46
299
|
type: 'input',
|
|
47
|
-
label: '
|
|
300
|
+
label: '姓名',
|
|
48
301
|
name: 'name',
|
|
49
|
-
rules: [{ required: true, message: '
|
|
302
|
+
rules: [{ required: true, message: '请输入姓名' }],
|
|
303
|
+
colSpan: 12,
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
type: 'InputNumber',
|
|
307
|
+
label: '年龄',
|
|
308
|
+
name: 'age',
|
|
309
|
+
colSpan: 12,
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
type: 'Radio',
|
|
313
|
+
label: '性别',
|
|
314
|
+
name: 'gender',
|
|
315
|
+
options: [
|
|
316
|
+
{ label: '男', value: 1 },
|
|
317
|
+
{ label: '女', value: 0 },
|
|
318
|
+
],
|
|
319
|
+
colSpan: 12,
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
type: 'textarea',
|
|
323
|
+
label: '备注',
|
|
324
|
+
name: 'remark',
|
|
325
|
+
colSpan: 24,
|
|
50
326
|
},
|
|
51
327
|
];
|
|
52
328
|
|
|
329
|
+
// 表格列配置
|
|
53
330
|
const tableColumns = [
|
|
54
331
|
{
|
|
55
|
-
title: '
|
|
56
|
-
dataIndex: 'id',
|
|
57
|
-
key: 'id',
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
title: '名称',
|
|
332
|
+
title: '姓名',
|
|
61
333
|
dataIndex: 'name',
|
|
62
334
|
key: 'name',
|
|
335
|
+
width: 150,
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
title: '年龄',
|
|
339
|
+
dataIndex: 'age',
|
|
340
|
+
key: 'age',
|
|
341
|
+
width: 100,
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
title: '性别',
|
|
345
|
+
dataIndex: 'gender',
|
|
346
|
+
key: 'gender',
|
|
347
|
+
width: 100,
|
|
348
|
+
render: (text: number) => (text === 1 ? '男' : '女'),
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
title: '创建时间',
|
|
352
|
+
dataIndex: 'createTime',
|
|
353
|
+
key: 'createTime',
|
|
354
|
+
width: 180,
|
|
63
355
|
},
|
|
64
356
|
];
|
|
65
357
|
|
|
358
|
+
// API 地址配置
|
|
66
359
|
const URL = {
|
|
67
|
-
search: '/api/
|
|
68
|
-
add: '/api/add',
|
|
69
|
-
edit: '/api/edit',
|
|
70
|
-
delete: '/api/delete',
|
|
360
|
+
search: '/api/user/list',
|
|
361
|
+
add: '/api/user/add',
|
|
362
|
+
edit: '/api/user/edit',
|
|
363
|
+
delete: '/api/user/delete',
|
|
71
364
|
};
|
|
72
365
|
|
|
73
366
|
return (
|
|
74
367
|
<CommonPage
|
|
368
|
+
ref={pageRef}
|
|
75
369
|
searchFormConfig={searchFormConfig}
|
|
76
370
|
addFormConfig={addFormConfig}
|
|
77
371
|
tableColumns={tableColumns}
|
|
78
372
|
URL={URL}
|
|
373
|
+
tableId="user-table"
|
|
374
|
+
isReset={true}
|
|
375
|
+
postParams={{
|
|
376
|
+
searchParams: { orgId: '123' },
|
|
377
|
+
}}
|
|
378
|
+
onRowClick={(record) => {
|
|
379
|
+
console.log('点击了行:', record);
|
|
380
|
+
}}
|
|
381
|
+
onDelete={(record) => {
|
|
382
|
+
console.log('删除了:', record);
|
|
383
|
+
}}
|
|
384
|
+
onSearch={() => {
|
|
385
|
+
console.log('搜索触发');
|
|
386
|
+
}}
|
|
387
|
+
onReset={() => {
|
|
388
|
+
console.log('重置触发');
|
|
389
|
+
}}
|
|
390
|
+
onView={(record) => {
|
|
391
|
+
console.log('查看了:', record);
|
|
392
|
+
}}
|
|
79
393
|
/>
|
|
80
394
|
);
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
export default DemoPage;
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
## 2. CustomTable 自定义表格组件
|
|
403
|
+
|
|
404
|
+
### 2.1 组件概述
|
|
405
|
+
|
|
406
|
+
`CustomTable` 是对 Ant Design Table 组件的增强封装,支持用户自定义表格列配置、保存配置到后端、序号列、树形数据等功能。
|
|
407
|
+
|
|
408
|
+
### 2.2 Props 参数
|
|
409
|
+
|
|
410
|
+
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|
|
411
|
+
|--------|------|------|--------|------|
|
|
412
|
+
| `columns` | `ColumnsType<any>` | 是 | - | 表格列配置 |
|
|
413
|
+
| `dataSource` | `any[]` | 是 | - | 表格数据源 |
|
|
414
|
+
| `loading` | `boolean` | 否 | `false` | 加载状态 |
|
|
415
|
+
| `pagination` | `object \| false` | 否 | - | 分页配置 |
|
|
416
|
+
| `handleTableChange` | `Function` | 否 | - | 表格变化回调 |
|
|
417
|
+
| `size` | `'small' \| 'middle' \| 'large'` | 否 | `'middle'` | 表格尺寸 |
|
|
418
|
+
| `tableId` | `string` | 否 | - | 表格唯一 ID,用于保存列配置 |
|
|
419
|
+
| `onRowClick` | `Function` | 否 | - | 行点击回调 |
|
|
420
|
+
| `page` | `object` | 否 | - | 分页信息(用于序号计算) |
|
|
421
|
+
| `showTableConfig` | `boolean` | 否 | `true` | 是否显示表格配置按钮和序号列 |
|
|
422
|
+
| `...rest` | `any` | 否 | - | 其他 Ant Design Table 原生属性 |
|
|
423
|
+
|
|
424
|
+
### 2.3 特色功能
|
|
425
|
+
|
|
426
|
+
1. **表格配置功能**:用户可以自定义列的显示、宽度、对齐方式、排序等,配置会保存到后端。
|
|
427
|
+
2. **自动序号列**:自动添加序号列(可通过 `showTableConfig` 控制)。
|
|
428
|
+
3. **树形数据支持**:支持展开/收起树形数据。
|
|
429
|
+
4. **Tooltip 支持**:单元格内容过长时自动显示 Tooltip。
|
|
430
|
+
|
|
431
|
+
### 2.4 使用示例
|
|
432
|
+
|
|
433
|
+
```tsx
|
|
434
|
+
import CustomTable from '@/components/customComponents/CustomTable';
|
|
435
|
+
|
|
436
|
+
const DemoTable = () => {
|
|
437
|
+
const [dataSource, setDataSource] = useState([]);
|
|
438
|
+
const [loading, setLoading] = useState(false);
|
|
439
|
+
const [pagination, setPagination] = useState({
|
|
440
|
+
current: 1,
|
|
441
|
+
pageSize: 10,
|
|
442
|
+
total: 0,
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
const columns = [
|
|
446
|
+
{
|
|
447
|
+
title: '姓名',
|
|
448
|
+
dataIndex: 'name',
|
|
449
|
+
key: 'name',
|
|
450
|
+
width: 150,
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
title: '年龄',
|
|
454
|
+
dataIndex: 'age',
|
|
455
|
+
key: 'age',
|
|
456
|
+
width: 100,
|
|
457
|
+
},
|
|
458
|
+
{
|
|
459
|
+
title: '地址',
|
|
460
|
+
dataIndex: 'address',
|
|
461
|
+
key: 'address',
|
|
462
|
+
width: 300,
|
|
463
|
+
},
|
|
464
|
+
];
|
|
465
|
+
|
|
466
|
+
return (
|
|
467
|
+
<CustomTable
|
|
468
|
+
columns={columns}
|
|
469
|
+
dataSource={dataSource}
|
|
470
|
+
loading={loading}
|
|
471
|
+
pagination={pagination}
|
|
472
|
+
tableId="demo-table"
|
|
473
|
+
page={pagination}
|
|
474
|
+
showTableConfig={true}
|
|
475
|
+
onRowClick={(record) => {
|
|
476
|
+
console.log('点击行:', record);
|
|
477
|
+
}}
|
|
478
|
+
handleTableChange={(newPagination) => {
|
|
479
|
+
setPagination(newPagination);
|
|
480
|
+
}}
|
|
481
|
+
/>
|
|
482
|
+
);
|
|
483
|
+
};
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
### 2.5 列配置弹窗说明
|
|
487
|
+
|
|
488
|
+
当 `showTableConfig={true}` 时,序号列旁边会显示设置图标,点击后打开配置弹窗,可以配置:
|
|
489
|
+
|
|
490
|
+
- **显示名称**:列的显示标题
|
|
491
|
+
- **表头对齐**:左/中/右对齐
|
|
492
|
+
- **内容对齐**:左/中/右对齐
|
|
493
|
+
- **数据格式**:字符串/数字/日期
|
|
494
|
+
- **宽度**:列宽
|
|
495
|
+
- **是否启用**:是否显示该列
|
|
496
|
+
- **允许排序**:是否允许排序
|
|
497
|
+
- **排序**:列的显示顺序
|
|
498
|
+
|
|
499
|
+
---
|
|
500
|
+
|
|
501
|
+
## 3. CustomForm 自定义表单组件
|
|
502
|
+
|
|
503
|
+
### 3.1 组件概述
|
|
504
|
+
|
|
505
|
+
`CustomForm` 是一个基于配置的表单组件,通过传入配置数组即可快速生成表单,支持多种表单项类型。
|
|
506
|
+
|
|
507
|
+
### 3.2 Props 参数
|
|
508
|
+
|
|
509
|
+
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|
|
510
|
+
|--------|------|------|--------|------|
|
|
511
|
+
| `config` | `FormItemConfig[]` | 是 | - | 表单项配置数组 |
|
|
512
|
+
| `onFinish` | `Function` | 否 | - | 表单提交回调 |
|
|
513
|
+
| `onSearch` | `Function` | 否 | - | 搜索按钮点击回调 |
|
|
514
|
+
| `onReset` | `Function` | 否 | - | 重置按钮点击回调 |
|
|
515
|
+
| `initialValues` | `object` | 否 | - | 表单初始值 |
|
|
516
|
+
| `layout` | `'horizontal' \| 'vertical' \| 'inline'` | 否 | `'horizontal'` | 表单布局 |
|
|
517
|
+
| `labelCol` | `object` | 否 | `{ span: 5 }` | label 栅格布局 |
|
|
518
|
+
| `wrapperCol` | `object` | 否 | `{ span: 19 }` | 控件栅格布局 |
|
|
519
|
+
| `submitButtonText` | `string` | 否 | `'搜索'` | 提交按钮文本 |
|
|
520
|
+
| `resetButtonText` | `string` | 否 | `'重置'` | 重置按钮文本 |
|
|
521
|
+
| `isReset` | `boolean` | 否 | `false` | 是否显示重置按钮 |
|
|
522
|
+
| `OtherButton` | `ReactNode \| Function` | 否 | - | 其他按钮 |
|
|
523
|
+
| `onSearchFormChange` | `Function` | 否 | - | 表单值变化回调 |
|
|
524
|
+
| `...restFormProps` | `any` | 否 | - | 其他 Ant Design Form 原生属性 |
|
|
525
|
+
|
|
526
|
+
### 3.3 FormItemConfig 配置项
|
|
527
|
+
|
|
528
|
+
```typescript
|
|
529
|
+
interface FormItemConfig {
|
|
530
|
+
type: 'input' | 'select' | 'rangePicker' | 'datePicker' | 'password' |
|
|
531
|
+
'treeSelect' | 'radio' | 'deptSelect' | 'orgSelect';
|
|
532
|
+
label: string; // 标签文本
|
|
533
|
+
name: string; // 字段名
|
|
534
|
+
placeholder?: string; // 占位符
|
|
535
|
+
options?: FormItemOption[]; // 选项(用于 select、radio 等)
|
|
536
|
+
rules?: any[]; // 验证规则
|
|
537
|
+
colSpan?: number; // 栅格占位(默认 6,即一行 4 个)
|
|
538
|
+
labelCol?: number; // label 栅格占位(默认 5)
|
|
539
|
+
wrapperCol?: number; // 控件栅格占位(默认 19)
|
|
540
|
+
initialValue?: any; // 初始值
|
|
541
|
+
defaultValue?: any; // 默认值
|
|
542
|
+
[key: string]: any; // 其他属性
|
|
81
543
|
}
|
|
82
544
|
|
|
83
|
-
|
|
545
|
+
interface FormItemOption {
|
|
546
|
+
label: React.ReactNode;
|
|
547
|
+
value: string | number;
|
|
548
|
+
}
|
|
84
549
|
```
|
|
85
550
|
|
|
86
|
-
###
|
|
551
|
+
### 3.4 支持的表单类型
|
|
552
|
+
|
|
553
|
+
| type 值 | 说明 | 额外属性 |
|
|
554
|
+
|---------|------|---------|
|
|
555
|
+
| `input` | 普通输入框 | - |
|
|
556
|
+
| `password` | 密码输入框 | - |
|
|
557
|
+
| `select` | 下拉选择 | `options` |
|
|
558
|
+
| `radio` | 单选框 | `options` |
|
|
559
|
+
| `rangePicker` | 日期范围选择 | - |
|
|
560
|
+
| `datePicker` | 日期选择 | - |
|
|
561
|
+
| `treeSelect` | 树形选择 | `options` (treeData 格式) |
|
|
562
|
+
| `deptSelect` | 科室选择(自动加载数据) | - |
|
|
563
|
+
| `orgSelect` | 机构选择(自动加载数据) | - |
|
|
564
|
+
|
|
565
|
+
### 3.5 Ref 暴露的方法
|
|
566
|
+
|
|
567
|
+
```typescript
|
|
568
|
+
interface CustomFormHandle {
|
|
569
|
+
setFieldsValue: (values: any) => void; // 设置表单值
|
|
570
|
+
getFieldsValue: () => any; // 获取表单值
|
|
571
|
+
}
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
### 3.6 使用示例
|
|
87
575
|
|
|
88
576
|
```tsx
|
|
89
|
-
import
|
|
90
|
-
import {
|
|
577
|
+
import { useRef } from 'react';
|
|
578
|
+
import CustomForm, { FormItemConfig } from '@/components/customComponents/CustomForm';
|
|
91
579
|
|
|
92
|
-
|
|
93
|
-
const
|
|
580
|
+
const DemoForm = () => {
|
|
581
|
+
const formRef = useRef<any>(null);
|
|
582
|
+
|
|
583
|
+
const formConfig: FormItemConfig[] = [
|
|
584
|
+
{
|
|
585
|
+
type: 'input',
|
|
586
|
+
label: '用户名',
|
|
587
|
+
name: 'username',
|
|
588
|
+
placeholder: '请输入用户名',
|
|
589
|
+
colSpan: 6,
|
|
590
|
+
rules: [{ required: true, message: '请输入用户名' }],
|
|
591
|
+
},
|
|
592
|
+
{
|
|
593
|
+
type: 'select',
|
|
594
|
+
label: '角色',
|
|
595
|
+
name: 'role',
|
|
596
|
+
options: [
|
|
597
|
+
{ label: '管理员', value: 'admin' },
|
|
598
|
+
{ label: '普通用户', value: 'user' },
|
|
599
|
+
],
|
|
600
|
+
colSpan: 6,
|
|
601
|
+
},
|
|
602
|
+
{
|
|
603
|
+
type: 'rangePicker',
|
|
604
|
+
label: '日期范围',
|
|
605
|
+
name: 'dateRange',
|
|
606
|
+
colSpan: 6,
|
|
607
|
+
},
|
|
608
|
+
{
|
|
609
|
+
type: 'orgSelect',
|
|
610
|
+
label: '机构',
|
|
611
|
+
name: 'orgId',
|
|
612
|
+
colSpan: 6,
|
|
613
|
+
},
|
|
614
|
+
];
|
|
94
615
|
|
|
95
|
-
const
|
|
96
|
-
|
|
616
|
+
const handleSearch = (values: any) => {
|
|
617
|
+
console.log('搜索参数:', values);
|
|
97
618
|
};
|
|
98
619
|
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
name: '测试名称',
|
|
102
|
-
});
|
|
620
|
+
const handleReset = (form: any) => {
|
|
621
|
+
console.log('重置表单');
|
|
103
622
|
};
|
|
104
623
|
|
|
105
624
|
return (
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
625
|
+
<CustomForm
|
|
626
|
+
ref={formRef}
|
|
627
|
+
config={formConfig}
|
|
628
|
+
onSearch={handleSearch}
|
|
629
|
+
onReset={handleReset}
|
|
630
|
+
isReset={true}
|
|
631
|
+
submitButtonText="查询"
|
|
632
|
+
resetButtonText="重置"
|
|
633
|
+
OtherButton={
|
|
634
|
+
<Button onClick={() => console.log(formRef.current?.getFieldsValue())}>
|
|
635
|
+
获取表单值
|
|
636
|
+
</Button>
|
|
637
|
+
}
|
|
638
|
+
/>
|
|
117
639
|
);
|
|
640
|
+
};
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
---
|
|
644
|
+
|
|
645
|
+
## 4. CustomAdd 新增/编辑弹窗组件
|
|
646
|
+
|
|
647
|
+
### 4.1 组件概述
|
|
648
|
+
|
|
649
|
+
`CustomAdd` 是一个功能强大的弹窗表单组件,支持新增、编辑、查看三种模式,支持多种表单项类型、表单验证、Tab 分组等。
|
|
650
|
+
|
|
651
|
+
### 4.2 Props 参数
|
|
652
|
+
|
|
653
|
+
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|
|
654
|
+
|--------|------|------|--------|------|
|
|
655
|
+
| `visible` | `boolean` | 是 | - | 弹窗是否可见 |
|
|
656
|
+
| `mode` | `'add' \| 'edit' \| 'view'` | 是 | - | 模式:新增/编辑/查看 |
|
|
657
|
+
| `config` | `AddItemConfig[]` | 是 | - | 表单项配置数组 |
|
|
658
|
+
| `initialValues` | `object` | 否 | - | 初始值(编辑/查看模式) |
|
|
659
|
+
| `onOk` | `Function` | 是 | - | 确定按钮回调 |
|
|
660
|
+
| `onCancel` | `Function` | 是 | - | 取消按钮回调 |
|
|
661
|
+
| `title` | `string` | 否 | 自动生成 | 弹窗标题 |
|
|
662
|
+
| `loading` | `boolean` | 否 | `false` | 确定按钮加载状态 |
|
|
663
|
+
| `tab` | `boolean` | 否 | `false` | 是否分 Tab 显示 |
|
|
664
|
+
| `modalProps` | `object` | 否 | - | Modal 额外属性 |
|
|
665
|
+
| `oneditFormChange` | `Function` | 否 | - | 表单值变化回调 |
|
|
666
|
+
| `CustomModalFooter` | `Function` | 否 | - | 自定义底部按钮 |
|
|
667
|
+
| `validateConfig` | `ValidateConfig` | 否 | - | 验证配置 |
|
|
668
|
+
|
|
669
|
+
### 4.3 AddItemConfig 配置项
|
|
670
|
+
|
|
671
|
+
```typescript
|
|
672
|
+
interface AddItemConfig {
|
|
673
|
+
type: 'input' | 'inputoption' | 'inputnumberoption' | 'select' |
|
|
674
|
+
'rangePicker' | 'datePicker' | 'password' | 'InputNumber' |
|
|
675
|
+
'Radio' | 'upload' | 'textarea' | 'area' | 'treeSelect' |
|
|
676
|
+
'richText' | 'doubleValue' | 'file' | 'deptSelect' |
|
|
677
|
+
'orgSelect' | 'uploadByte';
|
|
678
|
+
label: string; // 标签文本
|
|
679
|
+
name: string; // 字段名
|
|
680
|
+
placeholder?: string; // 占位符
|
|
681
|
+
options?: FormItemOption[]; // 选项
|
|
682
|
+
rules?: any[]; // 验证规则
|
|
683
|
+
colSpan?: number; // 栅格占位(默认 6)
|
|
684
|
+
defaultValue?: any; // 默认值
|
|
685
|
+
|
|
686
|
+
// 特殊字段(根据 type 使用)
|
|
687
|
+
optionname?: string; // inputoption 类型的下拉框字段名
|
|
688
|
+
labelName?: string; // select 类型保存 label 的字段名
|
|
689
|
+
firstLabel?: string; // doubleValue 第一个输入框字段名
|
|
690
|
+
secondLabel?: string; // doubleValue 第二个输入框字段名
|
|
691
|
+
separator?: string; // doubleValue 分隔符
|
|
692
|
+
dateFormat?: string; // 日期格式化字符串
|
|
693
|
+
|
|
694
|
+
[key: string]: any; // 其他属性
|
|
118
695
|
}
|
|
119
696
|
```
|
|
120
697
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
|
126
|
-
|
|
127
|
-
|
|
|
128
|
-
|
|
|
129
|
-
|
|
|
130
|
-
|
|
|
131
|
-
|
|
|
132
|
-
|
|
|
133
|
-
|
|
|
134
|
-
|
|
|
135
|
-
|
|
|
136
|
-
|
|
|
137
|
-
|
|
|
138
|
-
|
|
|
139
|
-
|
|
|
140
|
-
|
|
|
141
|
-
|
|
|
142
|
-
|
|
|
143
|
-
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
| oneditFormChange | 表单值变化回调 | (changedValues: any, allValues: any) => void | - |
|
|
147
|
-
| onRowClick | 行点击回调 | (record: any, event: any) => void | - |
|
|
148
|
-
| tableId | 表格ID(用于保存表格配置) | string | - |
|
|
149
|
-
| isaddtab | 是否使用 Tab 表单 | boolean | false |
|
|
150
|
-
|
|
151
|
-
### CommonPageHandle Methods
|
|
152
|
-
|
|
153
|
-
| 方法 | 说明 | 类型 |
|
|
154
|
-
|------|------|------|
|
|
155
|
-
| getList | 获取列表数据 | (parentParams?: any) => Promise<void> |
|
|
156
|
-
| setFieldsValue | 设置表单值 | (values: any) => void |
|
|
157
|
-
| getFieldsValue | 获取表单值 | () => any |
|
|
158
|
-
| reload | 重新加载列表 | () => void |
|
|
159
|
-
|
|
160
|
-
## 注意事项
|
|
161
|
-
|
|
162
|
-
### 依赖要求
|
|
163
|
-
|
|
164
|
-
本组件库依赖以下 peer dependencies,请确保在使用前已安装:
|
|
165
|
-
|
|
166
|
-
- `react` >= 18.0.0
|
|
167
|
-
- `react-dom` >= 18.0.0
|
|
168
|
-
- `antd` >= 5.0.0
|
|
169
|
-
- `lodash` >= 4.17.0
|
|
170
|
-
- `dayjs` >= 1.11.0
|
|
171
|
-
- `pinyin-pro` >= 3.0.0
|
|
172
|
-
- `axios` >= 1.0.0
|
|
173
|
-
|
|
174
|
-
### API 请求配置
|
|
175
|
-
|
|
176
|
-
组件内部使用 `commonPost` 函数进行 API 请求。由于组件依赖项目特定的 API 函数,您需要:
|
|
177
|
-
|
|
178
|
-
1. **提供 `commonPost` 函数**:组件需要从 `@/api/common` 导入 `commonPost` 函数。如果您的项目结构不同,需要:
|
|
179
|
-
- 创建对应的 API 文件,或
|
|
180
|
-
- 修改组件中的导入路径
|
|
181
|
-
|
|
182
|
-
2. **提供 `auth` 工具**:组件需要从 `@/utils/auth` 导入 `auth` 对象。如果您的项目结构不同,需要:
|
|
183
|
-
- 创建对应的工具文件,或
|
|
184
|
-
- 修改组件中的导入路径
|
|
185
|
-
|
|
186
|
-
3. **API 响应格式**:确保 API 返回符合以下格式:
|
|
698
|
+
### 4.4 支持的表单类型
|
|
699
|
+
|
|
700
|
+
| type 值 | 说明 | 额外配置 |
|
|
701
|
+
|---------|------|---------|
|
|
702
|
+
| `input` | 普通输入框 | 支持拼音码自动生成 |
|
|
703
|
+
| `password` | 密码输入框 | - |
|
|
704
|
+
| `textarea` | 多行文本 | - |
|
|
705
|
+
| `InputNumber` | 数字输入框 | - |
|
|
706
|
+
| `select` | 下拉选择 | `options`, `labelName` |
|
|
707
|
+
| `Radio` | 单选框 | `options` |
|
|
708
|
+
| `datePicker` | 日期选择 | `dateFormat` |
|
|
709
|
+
| `rangePicker` | 日期范围 | `dateFormat`,name 格式:"startDate/endDate" |
|
|
710
|
+
| `treeSelect` | 树形选择 | `options`, `multiple` |
|
|
711
|
+
| `upload` | 图片上传 | - |
|
|
712
|
+
| `file` | 文件上传 | - |
|
|
713
|
+
| `uploadByte` | 字节流上传 | - |
|
|
714
|
+
| `area` | 地址选择器 | - |
|
|
715
|
+
| `richText` | 富文本编辑器 | - |
|
|
716
|
+
| `deptSelect` | 科室选择 | - |
|
|
717
|
+
| `orgSelect` | 机构选择 | - |
|
|
718
|
+
| `inputoption` | 输入框+下拉框组合 | `optionname`, `options` |
|
|
719
|
+
| `inputnumberoption` | 数字输入框+下拉框组合 | `optionname`, `options` |
|
|
720
|
+
| `doubleValue` | 双输入框(如范围) | `firstLabel`, `secondLabel`, `separator` |
|
|
721
|
+
|
|
722
|
+
### 4.5 ValidateConfig 验证配置
|
|
187
723
|
|
|
188
724
|
```typescript
|
|
189
|
-
{
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
725
|
+
interface ValidateConfig {
|
|
726
|
+
validateApi: string; // 验证接口地址
|
|
727
|
+
validateFields: string[]; // 需要验证的字段名数组
|
|
728
|
+
validateMethod?: 'GET' | 'POST'; // 请求方法,默认 POST
|
|
729
|
+
validateParams?: (values: any) => any; // 自定义验证参数处理函数
|
|
730
|
+
validateMessage?: string; // 验证失败提示,默认 "验证失败"
|
|
731
|
+
union?: boolean; // 是否联合验证,默认 true
|
|
732
|
+
realtime?: boolean; // 是否实时验证,默认 false
|
|
733
|
+
realtimeDelay?: number; // 实时验证防抖延迟(毫秒),默认 500
|
|
734
|
+
group?: string[][]; // 分组验证配置
|
|
198
735
|
}
|
|
199
736
|
```
|
|
200
737
|
|
|
201
|
-
###
|
|
738
|
+
### 4.6 Ref 暴露的方法
|
|
739
|
+
|
|
740
|
+
```typescript
|
|
741
|
+
interface CustomAddHandle {
|
|
742
|
+
setFieldsValue: (values: any) => void; // 设置表单值
|
|
743
|
+
getFieldsValue: () => any; // 获取表单值
|
|
744
|
+
}
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
### 4.7 使用示例
|
|
748
|
+
|
|
749
|
+
#### 4.7.1 基础使用
|
|
750
|
+
|
|
751
|
+
```tsx
|
|
752
|
+
import { useState, useRef } from 'react';
|
|
753
|
+
import CustomAdd, { AddItemConfig } from '@/components/customComponents/CustomAdd';
|
|
754
|
+
|
|
755
|
+
const Demo = () => {
|
|
756
|
+
const [visible, setVisible] = useState(false);
|
|
757
|
+
const [mode, setMode] = useState<'add' | 'edit' | 'view'>('add');
|
|
758
|
+
const [initialValues, setInitialValues] = useState<any>(null);
|
|
759
|
+
const addRef = useRef<any>(null);
|
|
760
|
+
|
|
761
|
+
const addFormConfig: AddItemConfig[] = [
|
|
762
|
+
{
|
|
763
|
+
type: 'input',
|
|
764
|
+
label: '姓名',
|
|
765
|
+
name: 'name',
|
|
766
|
+
rules: [{ required: true, message: '请输入姓名' }],
|
|
767
|
+
colSpan: 12,
|
|
768
|
+
},
|
|
769
|
+
{
|
|
770
|
+
type: 'InputNumber',
|
|
771
|
+
label: '年龄',
|
|
772
|
+
name: 'age',
|
|
773
|
+
colSpan: 12,
|
|
774
|
+
},
|
|
775
|
+
{
|
|
776
|
+
type: 'Radio',
|
|
777
|
+
label: '性别',
|
|
778
|
+
name: 'gender',
|
|
779
|
+
options: [
|
|
780
|
+
{ label: '男', value: 1 },
|
|
781
|
+
{ label: '女', value: 0 },
|
|
782
|
+
],
|
|
783
|
+
colSpan: 12,
|
|
784
|
+
defaultValue: 1,
|
|
785
|
+
},
|
|
786
|
+
{
|
|
787
|
+
type: 'datePicker',
|
|
788
|
+
label: '出生日期',
|
|
789
|
+
name: 'birthDate',
|
|
790
|
+
dateFormat: 'YYYY-MM-DD',
|
|
791
|
+
colSpan: 12,
|
|
792
|
+
},
|
|
793
|
+
{
|
|
794
|
+
type: 'orgSelect',
|
|
795
|
+
label: '所属机构',
|
|
796
|
+
name: 'orgId',
|
|
797
|
+
rules: [{ required: true, message: '请选择机构' }],
|
|
798
|
+
colSpan: 12,
|
|
799
|
+
},
|
|
800
|
+
{
|
|
801
|
+
type: 'deptSelect',
|
|
802
|
+
label: '所属科室',
|
|
803
|
+
name: 'deptId',
|
|
804
|
+
colSpan: 12,
|
|
805
|
+
},
|
|
806
|
+
{
|
|
807
|
+
type: 'textarea',
|
|
808
|
+
label: '备注',
|
|
809
|
+
name: 'remark',
|
|
810
|
+
colSpan: 24,
|
|
811
|
+
},
|
|
812
|
+
];
|
|
813
|
+
|
|
814
|
+
const handleOk = async (values: any) => {
|
|
815
|
+
console.log('提交的值:', values);
|
|
816
|
+
// 调用接口...
|
|
817
|
+
setVisible(false);
|
|
818
|
+
};
|
|
819
|
+
|
|
820
|
+
return (
|
|
821
|
+
<>
|
|
822
|
+
<Button onClick={() => { setMode('add'); setVisible(true); }}>
|
|
823
|
+
新增
|
|
824
|
+
</Button>
|
|
825
|
+
|
|
826
|
+
<CustomAdd
|
|
827
|
+
ref={addRef}
|
|
828
|
+
visible={visible}
|
|
829
|
+
mode={mode}
|
|
830
|
+
config={addFormConfig}
|
|
831
|
+
initialValues={initialValues}
|
|
832
|
+
onOk={handleOk}
|
|
833
|
+
onCancel={() => setVisible(false)}
|
|
834
|
+
loading={false}
|
|
835
|
+
/>
|
|
836
|
+
</>
|
|
837
|
+
);
|
|
838
|
+
};
|
|
839
|
+
```
|
|
840
|
+
|
|
841
|
+
#### 4.7.2 分 Tab 使用
|
|
842
|
+
|
|
843
|
+
```tsx
|
|
844
|
+
const tabFormConfig = [
|
|
845
|
+
{
|
|
846
|
+
label: '基本信息',
|
|
847
|
+
children: [
|
|
848
|
+
{
|
|
849
|
+
type: 'input',
|
|
850
|
+
label: '姓名',
|
|
851
|
+
name: 'name',
|
|
852
|
+
rules: [{ required: true, message: '请输入姓名' }],
|
|
853
|
+
colSpan: 12,
|
|
854
|
+
},
|
|
855
|
+
{
|
|
856
|
+
type: 'InputNumber',
|
|
857
|
+
label: '年龄',
|
|
858
|
+
name: 'age',
|
|
859
|
+
colSpan: 12,
|
|
860
|
+
},
|
|
861
|
+
],
|
|
862
|
+
},
|
|
863
|
+
{
|
|
864
|
+
label: '详细信息',
|
|
865
|
+
children: [
|
|
866
|
+
{
|
|
867
|
+
type: 'textarea',
|
|
868
|
+
label: '个人简介',
|
|
869
|
+
name: 'bio',
|
|
870
|
+
colSpan: 24,
|
|
871
|
+
},
|
|
872
|
+
],
|
|
873
|
+
},
|
|
874
|
+
];
|
|
875
|
+
|
|
876
|
+
<CustomAdd
|
|
877
|
+
visible={visible}
|
|
878
|
+
mode={mode}
|
|
879
|
+
config={tabFormConfig}
|
|
880
|
+
tab={true} // 启用 Tab
|
|
881
|
+
onOk={handleOk}
|
|
882
|
+
onCancel={() => setVisible(false)}
|
|
883
|
+
/>
|
|
884
|
+
```
|
|
885
|
+
|
|
886
|
+
#### 4.7.3 带验证配置
|
|
887
|
+
|
|
888
|
+
```tsx
|
|
889
|
+
const validateConfig: ValidateConfig = {
|
|
890
|
+
validateApi: '/api/user/validate',
|
|
891
|
+
validateFields: ['username', 'email'],
|
|
892
|
+
validateMethod: 'POST',
|
|
893
|
+
union: true, // 联合验证
|
|
894
|
+
realtime: true, // 实时验证
|
|
895
|
+
realtimeDelay: 500, // 500ms 防抖
|
|
896
|
+
validateMessage: '字段重复',
|
|
897
|
+
};
|
|
898
|
+
|
|
899
|
+
<CustomAdd
|
|
900
|
+
visible={visible}
|
|
901
|
+
mode={mode}
|
|
902
|
+
config={addFormConfig}
|
|
903
|
+
validateConfig={validateConfig}
|
|
904
|
+
onOk={handleOk}
|
|
905
|
+
onCancel={() => setVisible(false)}
|
|
906
|
+
/>
|
|
907
|
+
```
|
|
202
908
|
|
|
203
|
-
|
|
909
|
+
#### 4.7.4 特殊类型示例
|
|
204
910
|
|
|
205
|
-
|
|
206
|
-
|
|
911
|
+
```tsx
|
|
912
|
+
// 双输入框(范围)
|
|
207
913
|
{
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
914
|
+
type: 'doubleValue',
|
|
915
|
+
label: '价格范围',
|
|
916
|
+
name: 'priceRange',
|
|
917
|
+
firstLabel: 'minPrice',
|
|
918
|
+
secondLabel: 'maxPrice',
|
|
919
|
+
firstPlaceholder: '最低价',
|
|
920
|
+
secondPlaceholder: '最高价',
|
|
921
|
+
separator: '至',
|
|
922
|
+
lastUnit: '元',
|
|
923
|
+
colSpan: 24,
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
// 输入框+下拉框组合
|
|
927
|
+
{
|
|
928
|
+
type: 'inputoption',
|
|
929
|
+
label: '剂量',
|
|
930
|
+
name: 'dosage',
|
|
931
|
+
optionname: 'dosageUnit',
|
|
932
|
+
options: [
|
|
933
|
+
{ label: 'mg', value: 'mg' },
|
|
934
|
+
{ label: 'g', value: 'g' },
|
|
935
|
+
],
|
|
936
|
+
colSpan: 12,
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
// 日期范围(自动拆分为两个字段)
|
|
940
|
+
{
|
|
941
|
+
type: 'rangePicker',
|
|
942
|
+
label: '有效期',
|
|
943
|
+
name: 'startDate/endDate', // 会自动拆分为 startDate 和 endDate
|
|
944
|
+
dateFormat: 'YYYY-MM-DD',
|
|
945
|
+
colSpan: 12,
|
|
213
946
|
}
|
|
214
947
|
```
|
|
215
948
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
- `src/api/table.ts` - 包含表格配置相关的 API 函数
|
|
949
|
+
---
|
|
950
|
+
|
|
951
|
+
## 5. 常见使用场景
|
|
952
|
+
|
|
953
|
+
### 5.1 完整的 CRUD 页面
|
|
222
954
|
|
|
223
|
-
|
|
955
|
+
```tsx
|
|
956
|
+
import { useRef } from 'react';
|
|
957
|
+
import CommonPage from '@/components/customComponents/commonPage';
|
|
958
|
+
|
|
959
|
+
const UserManagePage = () => {
|
|
960
|
+
const pageRef = useRef<any>(null);
|
|
224
961
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
962
|
+
const searchFormConfig = [
|
|
963
|
+
{ type: 'input', label: '用户名', name: 'username', colSpan: 6 },
|
|
964
|
+
{ type: 'input', label: '手机号', name: 'phone', colSpan: 6 },
|
|
965
|
+
{
|
|
966
|
+
type: 'select',
|
|
967
|
+
label: '状态',
|
|
968
|
+
name: 'status',
|
|
969
|
+
options: [
|
|
970
|
+
{ label: '启用', value: 1 },
|
|
971
|
+
{ label: '禁用', value: 0 },
|
|
972
|
+
],
|
|
973
|
+
colSpan: 6,
|
|
974
|
+
},
|
|
975
|
+
];
|
|
230
976
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
977
|
+
const addFormConfig = [
|
|
978
|
+
{
|
|
979
|
+
type: 'input',
|
|
980
|
+
label: '用户名',
|
|
981
|
+
name: 'username',
|
|
982
|
+
rules: [{ required: true, message: '请输入用户名' }],
|
|
983
|
+
colSpan: 12,
|
|
984
|
+
},
|
|
985
|
+
{
|
|
986
|
+
type: 'password',
|
|
987
|
+
label: '密码',
|
|
988
|
+
name: 'password',
|
|
989
|
+
rules: [{ required: true, message: '请输入密码' }],
|
|
990
|
+
colSpan: 12,
|
|
991
|
+
},
|
|
992
|
+
{ type: 'input', label: '手机号', name: 'phone', colSpan: 12 },
|
|
993
|
+
{ type: 'input', label: '邮箱', name: 'email', colSpan: 12 },
|
|
994
|
+
{
|
|
995
|
+
type: 'Radio',
|
|
996
|
+
label: '状态',
|
|
997
|
+
name: 'status',
|
|
998
|
+
options: [
|
|
999
|
+
{ label: '启用', value: 1 },
|
|
1000
|
+
{ label: '禁用', value: 0 },
|
|
1001
|
+
],
|
|
1002
|
+
defaultValue: 1,
|
|
1003
|
+
colSpan: 12,
|
|
1004
|
+
},
|
|
1005
|
+
];
|
|
234
1006
|
|
|
235
|
-
|
|
1007
|
+
const tableColumns = [
|
|
1008
|
+
{ title: '用户名', dataIndex: 'username', key: 'username', width: 150 },
|
|
1009
|
+
{ title: '手机号', dataIndex: 'phone', key: 'phone', width: 150 },
|
|
1010
|
+
{ title: '邮箱', dataIndex: 'email', key: 'email', width: 200 },
|
|
1011
|
+
{
|
|
1012
|
+
title: '状态',
|
|
1013
|
+
dataIndex: 'status',
|
|
1014
|
+
key: 'status',
|
|
1015
|
+
width: 100,
|
|
1016
|
+
render: (text: number) => text === 1 ? '启用' : '禁用',
|
|
1017
|
+
},
|
|
1018
|
+
{ title: '创建时间', dataIndex: 'createTime', key: 'createTime', width: 180 },
|
|
1019
|
+
];
|
|
236
1020
|
|
|
237
|
-
|
|
1021
|
+
const URL = {
|
|
1022
|
+
search: '/api/user/list',
|
|
1023
|
+
add: '/api/user/add',
|
|
1024
|
+
edit: '/api/user/edit',
|
|
1025
|
+
delete: '/api/user/delete',
|
|
1026
|
+
};
|
|
1027
|
+
|
|
1028
|
+
return (
|
|
1029
|
+
<CommonPage
|
|
1030
|
+
ref={pageRef}
|
|
1031
|
+
searchFormConfig={searchFormConfig}
|
|
1032
|
+
addFormConfig={addFormConfig}
|
|
1033
|
+
tableColumns={tableColumns}
|
|
1034
|
+
URL={URL}
|
|
1035
|
+
tableId="user-management-table"
|
|
1036
|
+
isReset={true}
|
|
1037
|
+
/>
|
|
1038
|
+
);
|
|
1039
|
+
};
|
|
1040
|
+
```
|
|
1041
|
+
|
|
1042
|
+
### 5.2 自定义操作列
|
|
238
1043
|
|
|
239
|
-
**方式1(推荐):**
|
|
240
1044
|
```tsx
|
|
241
|
-
|
|
1045
|
+
<CommonPage
|
|
1046
|
+
searchFormConfig={searchFormConfig}
|
|
1047
|
+
addFormConfig={addFormConfig}
|
|
1048
|
+
tableColumns={tableColumns}
|
|
1049
|
+
URL={URL}
|
|
1050
|
+
CustomOperations={(record) => (
|
|
1051
|
+
<>
|
|
1052
|
+
<a onClick={() => handleResetPassword(record)}>重置密码</a>
|
|
1053
|
+
<a onClick={() => handleAssignRole(record)}>分配角色</a>
|
|
1054
|
+
</>
|
|
1055
|
+
)}
|
|
1056
|
+
/>
|
|
242
1057
|
```
|
|
243
1058
|
|
|
244
|
-
|
|
1059
|
+
### 5.3 带权限控制
|
|
1060
|
+
|
|
245
1061
|
```tsx
|
|
246
|
-
|
|
1062
|
+
<CommonPage
|
|
1063
|
+
searchFormConfig={searchFormConfig}
|
|
1064
|
+
addFormConfig={addFormConfig}
|
|
1065
|
+
tableColumns={tableColumns}
|
|
1066
|
+
URL={URL}
|
|
1067
|
+
limit={{
|
|
1068
|
+
addLimit: hasPermission('user:add'),
|
|
1069
|
+
editLimit: hasPermission('user:edit'),
|
|
1070
|
+
delLimit: hasPermission('user:delete'),
|
|
1071
|
+
searchLimit: true,
|
|
1072
|
+
}}
|
|
1073
|
+
/>
|
|
247
1074
|
```
|
|
248
1075
|
|
|
249
|
-
|
|
1076
|
+
---
|
|
250
1077
|
|
|
251
|
-
##
|
|
1078
|
+
## 6. 注意事项
|
|
252
1079
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
1080
|
+
### 6.1 表单字段命名
|
|
1081
|
+
|
|
1082
|
+
1. **日期范围字段**:使用 `/` 分隔,如 `startDate/endDate`,组件会自动拆分为两个字段。
|
|
1083
|
+
2. **输入框+下拉框组合**:使用 `name` 和 `optionname` 分别定义两个字段。
|
|
1084
|
+
3. **双输入框**:使用 `firstLabel` 和 `secondLabel` 定义两个字段名。
|
|
256
1085
|
|
|
257
|
-
|
|
258
|
-
npm run dev
|
|
1086
|
+
### 6.2 数据格式
|
|
259
1087
|
|
|
260
|
-
|
|
261
|
-
|
|
1088
|
+
1. **日期数据**:后端返回的日期字符串会自动转换为 dayjs 对象,提交时根据 `dateFormat` 格式化。
|
|
1089
|
+
2. **树形选择多选**:多选时,后端返回逗号分隔的字符串(如 "1,2,3"),组件会自动转换为数组。
|
|
262
1090
|
|
|
263
|
-
|
|
264
|
-
|
|
1091
|
+
### 6.3 性能优化
|
|
1092
|
+
|
|
1093
|
+
1. **tableId**:为表格设置唯一 ID,用户的列配置会保存到后端,避免每次都重新配置。
|
|
1094
|
+
2. **防抖**:组件内部已对列表刷新、实时验证等操作做了防抖处理。
|
|
1095
|
+
|
|
1096
|
+
### 6.4 样式定制
|
|
1097
|
+
|
|
1098
|
+
组件使用了 CSS Modules,如需定制样式,可以:
|
|
1099
|
+
1. 通过 `className` 传入自定义类名
|
|
1100
|
+
2. 通过 `style` 传入内联样式
|
|
1101
|
+
3. 修改组件的 `.less` 文件
|
|
1102
|
+
|
|
1103
|
+
---
|
|
1104
|
+
|
|
1105
|
+
## 7. 常见问题
|
|
1106
|
+
|
|
1107
|
+
### Q1: 如何在表单提交前进行自定义验证?
|
|
1108
|
+
|
|
1109
|
+
使用 `validateConfig` 配置,指定验证接口和字段:
|
|
1110
|
+
|
|
1111
|
+
```tsx
|
|
1112
|
+
const validateConfig = {
|
|
1113
|
+
validateApi: '/api/validate',
|
|
1114
|
+
validateFields: ['username'],
|
|
1115
|
+
realtime: true,
|
|
1116
|
+
};
|
|
265
1117
|
```
|
|
266
1118
|
|
|
267
|
-
|
|
1119
|
+
### Q2: 如何实现联动选择(如省市区)?
|
|
1120
|
+
|
|
1121
|
+
1. 在 `CustomForm` 中使用 `onSearchFormChange` 监听字段变化
|
|
1122
|
+
2. 在 `CustomAdd` 中使用 `oneditFormChange` 监听字段变化
|
|
1123
|
+
|
|
1124
|
+
```tsx
|
|
1125
|
+
<CustomAdd
|
|
1126
|
+
oneditFormChange={(changedValues, allValues) => {
|
|
1127
|
+
if (changedValues.provinceId) {
|
|
1128
|
+
// 加载对应的城市列表
|
|
1129
|
+
loadCities(changedValues.provinceId);
|
|
1130
|
+
}
|
|
1131
|
+
}}
|
|
1132
|
+
/>
|
|
1133
|
+
```
|
|
1134
|
+
|
|
1135
|
+
### Q3: 如何获取/设置表单值?
|
|
1136
|
+
|
|
1137
|
+
使用 `ref` 调用组件方法:
|
|
1138
|
+
|
|
1139
|
+
```tsx
|
|
1140
|
+
const formRef = useRef<any>(null);
|
|
1141
|
+
|
|
1142
|
+
// 获取值
|
|
1143
|
+
const values = formRef.current?.getFieldsValue();
|
|
1144
|
+
|
|
1145
|
+
// 设置值
|
|
1146
|
+
formRef.current?.setFieldsValue({ name: '张三' });
|
|
1147
|
+
```
|
|
1148
|
+
|
|
1149
|
+
### Q4: 查看模式如何支持双击复制?
|
|
1150
|
+
|
|
1151
|
+
`CustomAdd` 组件在 `view` 模式下,大部分字段支持双击复制功能,会自动将字段值复制到剪贴板。
|
|
1152
|
+
|
|
1153
|
+
### Q5: 如何实现表格行高亮选中?
|
|
1154
|
+
|
|
1155
|
+
在 `CommonPage` 中,点击的行会自动高亮,通过 `currentRecord` 状态和 `rowClassName` 实现。
|
|
1156
|
+
|
|
1157
|
+
---
|
|
1158
|
+
|
|
1159
|
+
## 8. 更新日志
|
|
1160
|
+
|
|
1161
|
+
- **2025-11-24**: CustomTable 添加了表格配置保存功能
|
|
1162
|
+
- **2025-04-27**: CommonPage 组件创建
|
|
1163
|
+
- **2025-04-23**: CustomTable 组件创建
|
|
1164
|
+
|
|
1165
|
+
---
|
|
1166
|
+
|
|
1167
|
+
## 9. 技术支持
|
|
268
1168
|
|
|
269
|
-
|
|
1169
|
+
如有问题,请联系开发团队或查看源代码注释。
|