@cqsjjb/jjb-react-admin-component 3.2.0-rc.1 → 3.3.0-beta.1
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/BMap/README.md +58 -0
- package/Editor/README.md +57 -0
- package/FileUploader/README.md +51 -0
- package/FormilyDescriptions/README.md +64 -0
- package/ImageCropper/README.md +84 -0
- package/ImageUploader/README.md +73 -0
- package/ListDataContainer/index.d.ts +190 -0
- package/ListDataContainer/index.js +205 -0
- package/PageLayout/README.md +41 -0
- package/SearchForm/README.md +66 -0
- package/Table/README.md +36 -0
- package/Table/index.d.ts +1 -1
- package/Table/index.js +2 -2
- package/TableAction/README.md +56 -0
- package/package.json +4 -2
- package/ControlWrapper/index.less +0 -38
package/BMap/README.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
百度地图组件
|
|
2
|
+
|
|
3
|
+
## 代码演示
|
|
4
|
+
|
|
5
|
+
```jsx
|
|
6
|
+
import { useState } from 'react';
|
|
7
|
+
import { Button } from 'antd';
|
|
8
|
+
import BMap from '@cqsjjb/jjb-react-admin-component/BMap';
|
|
9
|
+
|
|
10
|
+
function App() {
|
|
11
|
+
const [ open, setOpen ] = useState(false);
|
|
12
|
+
return (
|
|
13
|
+
<>
|
|
14
|
+
<Button onClick={() => setOpen(true)}>打开地图</Button>
|
|
15
|
+
{open && (
|
|
16
|
+
<BMap
|
|
17
|
+
onOk={data => {
|
|
18
|
+
console.log(data);
|
|
19
|
+
setOpen(false);
|
|
20
|
+
}}
|
|
21
|
+
onCacnel={() => {
|
|
22
|
+
setOpen(false);
|
|
23
|
+
}}
|
|
24
|
+
/>
|
|
25
|
+
)}
|
|
26
|
+
</>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## API
|
|
32
|
+
|
|
33
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
34
|
+
|----------|:-----|:---------------------------------------------------------------------------------------------------------:|--------:|
|
|
35
|
+
| lng | 经度 | `number` | 116.404 |
|
|
36
|
+
| lat | 纬度 | `number` | 39.915 |
|
|
37
|
+
| title | 弹窗标题 | `string` | 百度地图 |
|
|
38
|
+
| width | 弹窗宽度 | `number` | 700 |
|
|
39
|
+
| onOk | 确认回调 | (data: { lng: number, lat: number, comp: <span style="color: red">IComp</span>, compText: Text }) => void | - |
|
|
40
|
+
| onCancel | 取消回调 | `() => void` | 700 |
|
|
41
|
+
|
|
42
|
+
## 确认回调-IComp
|
|
43
|
+
|
|
44
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
45
|
+
|--------------|:----|:--------:|----:|
|
|
46
|
+
| province | 省份 | `string` | - |
|
|
47
|
+
| city | 城市 | `string` | - |
|
|
48
|
+
| district | 区县 | `string` | - |
|
|
49
|
+
| street | 街道 | `string` | - |
|
|
50
|
+
| streetNumber | 门牌号 | `string` | - |
|
|
51
|
+
|
|
52
|
+
## 常见问题
|
|
53
|
+
* 未导入百度地图文件,生成地图失败!
|
|
54
|
+
|
|
55
|
+
请确认应用public/index.html中是否导入百度地图SDK。
|
|
56
|
+
* onOk确认回调compText为undefined
|
|
57
|
+
|
|
58
|
+
请确认百度地图是否授权Web应用。
|
package/Editor/README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
富文本组件组件,基于WangEditor实现。
|
|
2
|
+
|
|
3
|
+
## 代码演示
|
|
4
|
+
|
|
5
|
+
```jsx
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import { Form } from 'antd';
|
|
8
|
+
import Editor from '@cqsjjb/jjb-react-admin-component/Editor';
|
|
9
|
+
|
|
10
|
+
function App() {
|
|
11
|
+
return (
|
|
12
|
+
<Form>
|
|
13
|
+
<Form.Item
|
|
14
|
+
name="content"
|
|
15
|
+
label="内容"
|
|
16
|
+
>
|
|
17
|
+
<Editor />
|
|
18
|
+
</Form.Item>
|
|
19
|
+
</Form>
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## API
|
|
25
|
+
|
|
26
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
27
|
+
|---------------------|:-------------------------|:---------------------------------:|--------------------------------------:|
|
|
28
|
+
| bordered | 是否要边框 | `string` | false |
|
|
29
|
+
| borderStyle | 边框样式,`bordered`为`true`有效 | `string` | solid |
|
|
30
|
+
| borderColor | 边框颜色,`bordered`为`true`有效 | `string` | #e8e8e8 |
|
|
31
|
+
| borderWidth | 边框宽度,`bordered`为`true`有效 | `number` | 1 |
|
|
32
|
+
| borderRadius | 边框圆角,`bordered`为`true`有效 | `number` | 2 |
|
|
33
|
+
| value | 内容,受控 | `string` | - |
|
|
34
|
+
| mode | 模式 | `default` `simple` | default |
|
|
35
|
+
| height | 高度 | `string` | 300 |
|
|
36
|
+
| zIndex | 层级 | `string` | 1000 |
|
|
37
|
+
| disabled | 是否禁用 | `boolean` | false |
|
|
38
|
+
| uploadUrl | 上传地址 | `string` | /attachment/files/upload-speed-simple |
|
|
39
|
+
| uploadFileName | 上传文件名 | `string` | file |
|
|
40
|
+
| uploadImageFileSize | 图片上传大小,单位`byte` | `number` | 5MB |
|
|
41
|
+
| uploadVideoFileSize | 视频上传大小,单位`byte` | `number` | 5MB |
|
|
42
|
+
| uploadHeaders | 上传请求头 | `Record<string, string>` | - |
|
|
43
|
+
| uploadCustomRequest | 自定义上传 | `(file: File) => Promise<string>` | - |
|
|
44
|
+
| placeholder | 占位符 | `string` | 请输入... |
|
|
45
|
+
| onBlur | 失去焦点回调 | `() => void` | - |
|
|
46
|
+
| onFocus | 获得焦点回调 | `() => void() => void` | - |
|
|
47
|
+
| onChange | 内容变化回调、受控 | `(value: string) => void` | - |
|
|
48
|
+
| ref | 实例 | `React.Ref<EditorFC>` | - |
|
|
49
|
+
|
|
50
|
+
## EditorFC
|
|
51
|
+
|
|
52
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
53
|
+
|-------------------|:---------|:------------------------:|----:|
|
|
54
|
+
| getEditorInstance | 获取编辑器实例 | `() => any` | - |
|
|
55
|
+
| getHtml | 手动获取html | `() => string` | - |
|
|
56
|
+
| setHtml | 手动设置html | `(html: string) => void` | - |
|
|
57
|
+
| getPlainText | 手动获取纯文本 | `() => string` | - |
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
文件上传组件
|
|
2
|
+
|
|
3
|
+
## 代码演示
|
|
4
|
+
|
|
5
|
+
```jsx
|
|
6
|
+
import React, { useState } from 'react';
|
|
7
|
+
import { Form } from 'antd';
|
|
8
|
+
import FileUploader, { getValueProps, getValueFromEvent } from '@cqsjjb/jjb-react-admin-component/FileUploader';
|
|
9
|
+
|
|
10
|
+
function App() {
|
|
11
|
+
const [ form ] = Form.useForm();
|
|
12
|
+
return (
|
|
13
|
+
<Form>
|
|
14
|
+
<Form.Item
|
|
15
|
+
label="文件图片"
|
|
16
|
+
name="FileUrl"
|
|
17
|
+
getValueProps={getValueProps}
|
|
18
|
+
getValueFromEvent={getValueFromEvent}
|
|
19
|
+
>
|
|
20
|
+
<FileUploader action="httpx://xxx.xxx.xx" />
|
|
21
|
+
</Form.Item>
|
|
22
|
+
</Form>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`Array<SearchFormConfig>`
|
|
28
|
+
|
|
29
|
+
## API
|
|
30
|
+
|
|
31
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
32
|
+
|----------------------------|:---------------------------------------------------------------------|:------------------------------------------------------:|------:|
|
|
33
|
+
| size | 文件大小,单位:KB | `number` | 5120 |
|
|
34
|
+
| buttonProps | 组件内部按钮属性 参考 https://ant-design.antgroup.com/components/button-cn#api | `ButtonProps` | - |
|
|
35
|
+
| data | 额外的数据 | `Record<string, any>` | - |
|
|
36
|
+
| value | 值,受控 | `any` | - |
|
|
37
|
+
| accept | 上传类型 参考`MIME`类型 | `string` | * |
|
|
38
|
+
| action | 组件高度 | `string` | - |
|
|
39
|
+
| preview | 是否支持预览 | `boolean` | false |
|
|
40
|
+
| headers | 请求头 | `Record<string, any>` | - |
|
|
41
|
+
| maxCount | 最多上传数,`multiple`为`true`有效 | `number` | 99 |
|
|
42
|
+
| multiple | 上传多个文件 | `boolean` | false |
|
|
43
|
+
| disabled | 是否禁用 | `boolean` | false |
|
|
44
|
+
| fieldName | 上传文件的字段名 | `string` | file |
|
|
45
|
+
| showDelete | 显示删除图标 | `boolean` | true |
|
|
46
|
+
| customRequest | 自定义请求 | `(res: AxiosResponse) => void` | - |
|
|
47
|
+
| onChange | 受控值改变回调 | `(value: any) => void` | - |
|
|
48
|
+
| onBeforeUploadVerifySize | 上传前验证文件大小 | `(fileSize: number, maxSize: number) => Promise<void>` | - |
|
|
49
|
+
| onBeforeUploadVerifyAccept | 上传前验证文件类型 | `(fileType: string, accept: string) => Promise<void>` | - |
|
|
50
|
+
|
|
51
|
+
**注意:这个组件的`multiple`仅为可以上传多个文件,但不是支持选择多个文件,若要上传选择多个文件,建议使用`antd/Upload`组件**
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
动态表单详情渲染
|
|
2
|
+
|
|
3
|
+
## 代码演示
|
|
4
|
+
|
|
5
|
+
```jsx
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import { Form } from 'antd';
|
|
8
|
+
import FormilyDescriptions from '@cqsjjb/jjb-react-admin-component/FormilyDescriptions';
|
|
9
|
+
|
|
10
|
+
function App() {
|
|
11
|
+
// 这段配置数据从接口获取
|
|
12
|
+
const schema = [
|
|
13
|
+
{
|
|
14
|
+
fieldCode: 'name',
|
|
15
|
+
fieldDataTypeEnum: 'varchar',
|
|
16
|
+
fieldLength: 255,
|
|
17
|
+
fieldSort: 0,
|
|
18
|
+
formType: 'Input',
|
|
19
|
+
fromComponentEnum: 'FIELD_TEXT',
|
|
20
|
+
fromComponentInfoEnum: 'SINGLE_LINE_TEXT_SECTION',
|
|
21
|
+
name: '用户名',
|
|
22
|
+
parentCode: null,
|
|
23
|
+
requiredEnum: 'TRUE'
|
|
24
|
+
}
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<FormilyDescriptions
|
|
29
|
+
schema={schema}
|
|
30
|
+
values={{ name: '张三' }}
|
|
31
|
+
/>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## API
|
|
37
|
+
|
|
38
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
39
|
+
|----------------|:--------------------------------------------------------------------------|:-----------------------------------------------------------:|--------:|
|
|
40
|
+
| schema | 表单配置 (注意不是原始配置`config`,而是后端转换后的配置) | `Array<FormilySchema>` | - |
|
|
41
|
+
| values | 表单数据 | `Record<string, FormilyValue>` | - |
|
|
42
|
+
| size | 详情组件大小 | `small` `middle` `default` | default |
|
|
43
|
+
| maxTagCount | 内部`TreeSelect`组件的最大显示标签数量 | `number` | 1 |
|
|
44
|
+
| renderItemText | 自定义渲染文本 | `(params: { text: any; name?: string }) => React.ReactNode` | - |
|
|
45
|
+
| imageWidth | 内部缩略图宽度 | `number` | 64 |
|
|
46
|
+
| imageHeight | 内部缩略图高度 | `number` | 64 |
|
|
47
|
+
| extraFileLink | 附件预览,`true`打开浏览器窗口,`false`弹窗打开 | `boolean` | false |
|
|
48
|
+
| imagePreview | 图片预览配置,参考 https://ant-design.antgroup.com/components/image-cn#previewtype | `PreviewType` | - |
|
|
49
|
+
|
|
50
|
+
其属性参考 https://ant-design.antgroup.com/components/descriptions-cn#descriptions
|
|
51
|
+
|
|
52
|
+
## FormilySchema
|
|
53
|
+
|
|
54
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
55
|
+
|-----------------------|:--------------|:--------------:|----:|
|
|
56
|
+
| fieldCode | 字段编码 | `string` | - |
|
|
57
|
+
| fieldDataTypeEnum | 字段数据类型 | `string` | - |
|
|
58
|
+
| fieldLength | 字段长度 | `number` | - |
|
|
59
|
+
| fieldSort | 字段排序 | `number` | - |
|
|
60
|
+
| formType | 表单组件类型 | `string` | - |
|
|
61
|
+
| fromComponentEnum | 表单组件输出值格式类型枚举 | `string` | - |
|
|
62
|
+
| fromComponentInfoEnum | 表单组件信息枚举 | `string` | - |
|
|
63
|
+
| name | 字段名称 | `string` | - |
|
|
64
|
+
| requiredEnum | 是否必填 | `TRUE` `FALSE` | - |
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
单图裁剪组件
|
|
2
|
+
|
|
3
|
+
## 代码演示
|
|
4
|
+
|
|
5
|
+
```jsx
|
|
6
|
+
import React, { useState, useRef } from 'react';
|
|
7
|
+
import { Button } from 'antd';
|
|
8
|
+
import ImageCropper from '~/components/publish/ImageCropper';
|
|
9
|
+
|
|
10
|
+
function App() {
|
|
11
|
+
const cropper = useRef();
|
|
12
|
+
const [ resource, setResource ] = useState();
|
|
13
|
+
const onUpload = () => {
|
|
14
|
+
const input = document.createElement('input');
|
|
15
|
+
input.type = 'file';
|
|
16
|
+
input.click();
|
|
17
|
+
input.onchange = e => {
|
|
18
|
+
setResource(e.target.files[ 0 ]);
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const onCropper = () => {
|
|
23
|
+
console.log(cropper.current.toDataFile());
|
|
24
|
+
};
|
|
25
|
+
return (
|
|
26
|
+
<>
|
|
27
|
+
<Button onClick={onUpload}>
|
|
28
|
+
上传文件
|
|
29
|
+
</Button>
|
|
30
|
+
<Button onClick={onCropper}>
|
|
31
|
+
获取裁剪后的图片
|
|
32
|
+
</Button>
|
|
33
|
+
<ImageCropper
|
|
34
|
+
ref={cropper}
|
|
35
|
+
resource={resource}
|
|
36
|
+
/>
|
|
37
|
+
</>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## API
|
|
43
|
+
|
|
44
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
45
|
+
|----------|:--------------------|:----------------------------:|-------:|
|
|
46
|
+
| width | 宽度 | `number` | 400 |
|
|
47
|
+
| height | 高度 | `number` | 400 |
|
|
48
|
+
| locked | 是否锁定裁剪框大小 | `boolean` | false |
|
|
49
|
+
| aspect | 裁剪框宽高比 | `number` | 16 / 9 |
|
|
50
|
+
| resource | 裁剪的资源,文件对象或`base64` | `File` `string` | - |
|
|
51
|
+
| ref | 裁剪实例 | `React.Ref<ImageCropperRef>` | - |
|
|
52
|
+
|
|
53
|
+
## ImageCropperRef 裁剪实例
|
|
54
|
+
|
|
55
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
56
|
+
|---------------------|:---------------------|:------------------------------------------:|----:|
|
|
57
|
+
| toDataURL | 转换为dataURL | `(quality?: number) => ToDataURLResult` | 400 |
|
|
58
|
+
| toDataFile | 转换为dataFile | `() => ToDataFileResult` | 400 |
|
|
59
|
+
| toBlobURL | 转换为blobURL | `() => string` | - |
|
|
60
|
+
| toDataImageText | 转换为dataImageText | `() => string` | - |
|
|
61
|
+
| toDataImageInstance | 转换为dataImageInstance | `() => Promise<ToDataImageInstanceResult>` | - |
|
|
62
|
+
|
|
63
|
+
## ToDataURLResult
|
|
64
|
+
|
|
65
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
66
|
+
|--------|:-------|:--------:|----:|
|
|
67
|
+
| md5 | 文件MD5 | `string` | - |
|
|
68
|
+
| base64 | base64 | `string` | - |
|
|
69
|
+
|
|
70
|
+
## ToDataFileResult
|
|
71
|
+
|
|
72
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
73
|
+
|------|:------|:--------:|----:|
|
|
74
|
+
| md5 | 文件MD5 | `string` | - |
|
|
75
|
+
| file | 文件对象 | `File` | - |
|
|
76
|
+
|
|
77
|
+
## ToDataImageInstanceResult
|
|
78
|
+
|
|
79
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
80
|
+
|----------|:-----|:------------------:|----:|
|
|
81
|
+
| src | 文件资源 | `string` | - |
|
|
82
|
+
| width | 宽度 | `number` | - |
|
|
83
|
+
| height | 高度 | `number` | - |
|
|
84
|
+
| instance | 实例 | `HTMLImageElement` | - |
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
单图上传组件
|
|
2
|
+
|
|
3
|
+
## 代码演示
|
|
4
|
+
|
|
5
|
+
```jsx
|
|
6
|
+
import { useState } from 'react';
|
|
7
|
+
import { Button, Form } from 'antd';
|
|
8
|
+
import ImageUploader, { getValueProps, getValueFromEvent } from '@cqsjjb/jjb-react-admin-component/ImageUploader';
|
|
9
|
+
|
|
10
|
+
function App() {
|
|
11
|
+
const [ form ] = Form.useForm();
|
|
12
|
+
return (
|
|
13
|
+
<Form>
|
|
14
|
+
<Form.Item
|
|
15
|
+
label="上传图片"
|
|
16
|
+
name="imageUrl"
|
|
17
|
+
getValueProps={getValueProps}
|
|
18
|
+
getValueFromEvent={getValueFromEvent}
|
|
19
|
+
>
|
|
20
|
+
<ImageUploader action="httpx://xxx.xxx.xx" />
|
|
21
|
+
</Form.Item>
|
|
22
|
+
</Form>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## API
|
|
28
|
+
|
|
29
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
30
|
+
|-------------------|:-----------------------------|:---------------------------:|--------------------------------------------:|
|
|
31
|
+
| wh | 宽高比 | `string` | 50*50 |
|
|
32
|
+
| tip | 提示文本 | `string` | 点击上传 |
|
|
33
|
+
| size | 文件大小,单位:KB | `number` | 5120 |
|
|
34
|
+
| data | 额外的数据 | `Record<string, any>` | - |
|
|
35
|
+
| value | 值,受控 | `any` | - |
|
|
36
|
+
| width | 组件宽度 | `number` | 120 |
|
|
37
|
+
| height | 组件高度 | `number` | 120 |
|
|
38
|
+
| action | 组件高度 | `number` | 120 |
|
|
39
|
+
| preview | 是否支持预览 | `boolean` | true |
|
|
40
|
+
| disabled | 是否禁用 | `boolean` | false |
|
|
41
|
+
| fieldName | 上传文件的字段名 | `string` | file |
|
|
42
|
+
| borderStyle | 边框样式 | `string` | dashed |
|
|
43
|
+
| borderColor | 边框颜色 | `string` | #d9d9d9 |
|
|
44
|
+
| borderWidth | 边框宽度 | `number` | 1 |
|
|
45
|
+
| borderRadius | 边框圆角 | `number` | 2 |
|
|
46
|
+
| cropper | 是否开启裁剪 | `boolean` | false |
|
|
47
|
+
| cropperConfig | 裁剪配置,`cropper`为`true`时有效 | `CropperConfig` | - |
|
|
48
|
+
| backgroundColor | 背景颜色 | `string` | #fafafa |
|
|
49
|
+
| customRequest | 自定义请求 | `(res: {data: any}) => void | Promise<{fileId: string, fileUrl: string}>` | - |
|
|
50
|
+
| onChange | 受控值改变回调 | `(value: any) => void` | - |
|
|
51
|
+
| compression | 是否支持压缩 | `boolean` | false |
|
|
52
|
+
| compressionConfig | 压缩配置,`compression`为`true`时有效 | `CompressionConfig` | - |
|
|
53
|
+
| needToken | 是否需要token | `boolean` | true |
|
|
54
|
+
|
|
55
|
+
## CropperConfig 裁剪配置
|
|
56
|
+
|
|
57
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
58
|
+
|--------|:----------|:---------:|-------:|
|
|
59
|
+
| width | 宽度 | `number` | 400 |
|
|
60
|
+
| height | 高度 | `number` | 400 |
|
|
61
|
+
| locked | 锁定不可缩放裁剪框 | `boolean` | false |
|
|
62
|
+
| aspect | 宽高比 | `number` | 16 / 9 |
|
|
63
|
+
|
|
64
|
+
## CompressionConfig 压缩配置
|
|
65
|
+
|
|
66
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
67
|
+
|----------|:-----|:---------------:|-----:|
|
|
68
|
+
| quality | 压缩质量 | `number` | 0.6 |
|
|
69
|
+
| backType | 压缩类型 | `file` `base64` | file |
|
|
70
|
+
|
|
71
|
+
## Form表单辅助
|
|
72
|
+
* getValueFromEvent
|
|
73
|
+
* getValueProps
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
|
|
2
|
+
import React, { ReactNode, ReactElement, RefAttributes } from 'react';
|
|
3
|
+
import { TableProps, FormItemProps } from 'antd';
|
|
4
|
+
import { OverTableProps } from '../Table';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 基础表单项组件的通用类型约束
|
|
8
|
+
* 描述:定义搜索表单中所有表单项组件(如 Select、Input、DatePicker 等)的公共属性,
|
|
9
|
+
* 确保不同类型的表单项都能兼容「清除、占位符、子元素」等基础能力
|
|
10
|
+
* @type {BaseFieldComponent}
|
|
11
|
+
*/
|
|
12
|
+
type BaseFieldComponent = React.ComponentType<{
|
|
13
|
+
/** 是否支持清空选中值/输入值(通用表单项能力) */
|
|
14
|
+
allowClear?: boolean;
|
|
15
|
+
/** 输入/选择提示文本(提升用户体验) */
|
|
16
|
+
placeholder?: string;
|
|
17
|
+
/** 组件的子元素(如 Select.Option、DatePicker 的下拉内容等) */
|
|
18
|
+
children?: ReactNode;
|
|
19
|
+
/** 兼容组件的自定义属性(如 Select 的 options、Input 的 maxLength 等,避免类型约束过死) */
|
|
20
|
+
[key: string]: any;
|
|
21
|
+
}>;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* 搜索表单单个配置项的接口
|
|
25
|
+
* 描述:用于定义搜索表单中每一个表单项的完整配置,包括组件类型、字段名、校验规则等,
|
|
26
|
+
* 组件内部会根据该配置自动生成对应的 Form.Item 结构
|
|
27
|
+
*
|
|
28
|
+
* @interface SearchFormItemConfig
|
|
29
|
+
*/
|
|
30
|
+
export interface SearchFormItemConfig {
|
|
31
|
+
/** 表单项的核心组件(如 Select、Input、DatePicker 等,需符合 BaseFieldComponent 类型) */
|
|
32
|
+
field: BaseFieldComponent;
|
|
33
|
+
/** 表单项对应的表单字段名(与 form.validateFields() 返回的键名一致,用于数据提交) */
|
|
34
|
+
name: string;
|
|
35
|
+
/** 表单项的标签文本(显示在输入组件左侧,用于用户识别) */
|
|
36
|
+
label: string;
|
|
37
|
+
/** 传递给表单项组件的自定义属性(如 Select 的 options、Input 的 disabled 等) */
|
|
38
|
+
fieldProps?: Record<string, any>;
|
|
39
|
+
/** 传递给 antd Form.Item 的自定义属性(如 rules、hasFeedback、className 等) */
|
|
40
|
+
itemProps?: FormItemProps & Record<string, any>;
|
|
41
|
+
/** 表单项组件的子元素(如 Select.Option 列表、Radio.Group 的 Radio 按钮等) */
|
|
42
|
+
content?: ReactNode;
|
|
43
|
+
/** 是否为必填项(为 true 时,组件内部会自动添加「必填校验规则」和「*」标记) */
|
|
44
|
+
required?: boolean;
|
|
45
|
+
/** 兼容其他未明确列举的自定义属性(如 Form.Item 的 extra 提示文本等,预留扩展能力) */
|
|
46
|
+
[key: string]: any;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* ListDataContainer 组件的 Props 接口
|
|
51
|
+
* 描述:定义通用列表容器组件的所有可配置属性,支持表格类型切换、搜索表单配置、分页初始值等,
|
|
52
|
+
* 通过泛型 T 关联「表格类型」和「表格属性」,确保类型一致性
|
|
53
|
+
*
|
|
54
|
+
* @interface ListDataContainerProps
|
|
55
|
+
* @template T - 表格类型开关(true = 使用 ProTable;false = 使用 antd 原生 Table,默认 false)
|
|
56
|
+
*/
|
|
57
|
+
export interface ListDataContainerProps<T extends boolean = false> {
|
|
58
|
+
/**
|
|
59
|
+
* 表格列配置
|
|
60
|
+
* 描述:遵循 antd Table 组件的 columns 规范(即使使用 ProTable,列配置结构也与 antd 一致),
|
|
61
|
+
* 用于定义表格的列名、数据映射、渲染逻辑等
|
|
62
|
+
* @type {TableProps<any>['columns']}
|
|
63
|
+
*/
|
|
64
|
+
columns: TableProps<any>['columns'];
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* 数据请求接口函数
|
|
68
|
+
* 描述:组件内部会调用该函数获取表格数据,需返回包含「列表数据」和「总数」的 Promise,
|
|
69
|
+
* 参数自动携带「分页信息」和「搜索表单值」,支持外部传入参数覆盖
|
|
70
|
+
*
|
|
71
|
+
* @param {Object} params - 请求参数(分页参数 + 搜索表单参数 + 外部覆盖参数)
|
|
72
|
+
* @param {number} params.page - 当前页码(由组件内部分页状态维护)
|
|
73
|
+
* @param {number} params.pageSize - 每页条数(由组件内部分页状态维护)
|
|
74
|
+
* @param {any} params[key] - 搜索表单字段(与 searchFormConfig 中的 name 对应)
|
|
75
|
+
* @returns {Promise<Object>} 数据响应(需包含 list 和 total 字段)
|
|
76
|
+
* @returns {Array} response.data.list - 表格数据源数组
|
|
77
|
+
* @returns {number} response.data.total - 数据总数(用于分页计算)
|
|
78
|
+
*/
|
|
79
|
+
fetchDataApi: (params: {
|
|
80
|
+
page: number;
|
|
81
|
+
pageSize: number;
|
|
82
|
+
[key: string]: any;
|
|
83
|
+
}) => Promise<{
|
|
84
|
+
data: {
|
|
85
|
+
list: any[];
|
|
86
|
+
total: number;
|
|
87
|
+
[key: string]: any;
|
|
88
|
+
};
|
|
89
|
+
[key: string]: any;
|
|
90
|
+
}>;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* 搜索表单配置数组
|
|
94
|
+
* 描述:由 SearchFormItemConfig 类型的配置项组成,组件内部会根据该数组自动生成搜索表单,
|
|
95
|
+
* 不传递则不显示搜索表单
|
|
96
|
+
* @type {SearchFormItemConfig[]}
|
|
97
|
+
* @optional
|
|
98
|
+
*/
|
|
99
|
+
searchFormConfig?: SearchFormItemConfig[];
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* 表格行的唯一标识字段名
|
|
103
|
+
* 描述:用于 antd Table/ProTable 的 rowKey 属性,确保表格行的唯一性(避免渲染警告),
|
|
104
|
+
* 默认值为 'id'(若数据的唯一标识字段不是 id,需手动传递)
|
|
105
|
+
* @type {string}
|
|
106
|
+
* @default 'id'
|
|
107
|
+
* @optional
|
|
108
|
+
*/
|
|
109
|
+
rowKey?: string;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* 初始分页配置
|
|
113
|
+
* 描述:定义表格初始的分页状态(如默认页码、每页条数、是否显示分页控件等),
|
|
114
|
+
* 基于 antd Table 的 pagination 类型扩展,确保分页能力符合通用需求
|
|
115
|
+
*
|
|
116
|
+
* @type {TableProps<any>['pagination'] & Object}
|
|
117
|
+
* @property {number} [current=1] - 默认当前页码
|
|
118
|
+
* @property {number} [pageSize=10] - 默认每页条数
|
|
119
|
+
* @property {boolean} [showSizeChanger=true] - 是否显示「条数切换」控件(如 10/20/50 条)
|
|
120
|
+
* @property {boolean} [showQuickJumper=true] - 是否显示「快速跳转」输入框
|
|
121
|
+
* @property {Function} [showTotal] - 总数显示文案(如 (total) => `共 ${total} 条`)
|
|
122
|
+
* @optional
|
|
123
|
+
*/
|
|
124
|
+
initialPagination?: TableProps<any>['pagination'] & {
|
|
125
|
+
current?: number;
|
|
126
|
+
pageSize?: number;
|
|
127
|
+
showSizeChanger?: boolean;
|
|
128
|
+
showQuickJumper?: boolean;
|
|
129
|
+
showTotal?: (total: number) => ReactNode;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* 表格组件的自定义属性
|
|
134
|
+
* 描述:根据 proTable 开关动态匹配对应的表格属性类型,支持覆盖组件内部的默认配置(如 loading、pagination 等)
|
|
135
|
+
* - 当 proTable={true} 时:支持 OverTableProps(项目自定义 ProTable 的所有属性)
|
|
136
|
+
* - 当 proTable={false} 时:支持 TableProps(antd 原生 Table 的所有属性)
|
|
137
|
+
*
|
|
138
|
+
* @type {T extends true ? OverTableProps<any> : TableProps<any>}
|
|
139
|
+
* @optional
|
|
140
|
+
* @example
|
|
141
|
+
*/
|
|
142
|
+
tableProps?: T extends true
|
|
143
|
+
? OverTableProps // ProTable 专属属性(如 search、toolBar 等)
|
|
144
|
+
: TableProps<any>; // antd 原生 Table 属性(如 bordered、scroll 等)
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* 表格类型切换开关
|
|
148
|
+
* 描述:控制组件内部使用「项目自定义 ProTable」还是「antd 原生 Table」,
|
|
149
|
+
* 泛型 T 会自动根据该值推断,确保 tableProps 类型匹配
|
|
150
|
+
*
|
|
151
|
+
* @type {T}
|
|
152
|
+
* @default false - 默认使用 antd 原生 Table
|
|
153
|
+
* @optional
|
|
154
|
+
*/
|
|
155
|
+
proTable?: T;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* ListDataContainer 组件通过 ref 暴露的方法接口
|
|
160
|
+
* 描述:组件内部通过 useImperativeHandle 暴露的方法,允许父组件调用以实现「数据刷新」等能力
|
|
161
|
+
*
|
|
162
|
+
* @interface ListDataContainerExposedMethods
|
|
163
|
+
*/
|
|
164
|
+
export interface ListDataContainerExposedMethods {
|
|
165
|
+
/**
|
|
166
|
+
* 数据刷新方法
|
|
167
|
+
* 描述:触发表格数据重新请求,支持传入参数覆盖默认的「分页+搜索」参数,
|
|
168
|
+
* 适用于父组件主动刷新数据(如弹窗关闭后刷新列表)
|
|
169
|
+
*
|
|
170
|
+
* @param {Record<string, any>} [overrideParams] - 覆盖请求的参数(如 { status: 1, type: 2 })
|
|
171
|
+
* @returns {Promise<void>} - 数据请求完成的 Promise(可用于等待刷新结束)
|
|
172
|
+
*/
|
|
173
|
+
loadDataSource: (overrideParams?: Record<string, any>) => Promise<void>;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* 通用列表数据容器组件声明
|
|
178
|
+
* 描述:泛型组件,整合「搜索表单 + 表格 + 分页 + 数据请求」的完整列表解决方案,
|
|
179
|
+
* 支持切换表格类型,暴露刷新方法,适用于项目中各类列表页面(如数据管理、列表查询等)
|
|
180
|
+
*
|
|
181
|
+
* @component ListDataContainer
|
|
182
|
+
* @template T - 表格类型开关(true = ProTable;false = antd Table,默认 false)
|
|
183
|
+
* @param {ListDataContainerProps<T> & RefAttributes<ListDataContainerExposedMethods>} props - 组件 props
|
|
184
|
+
* @returns {ReactElement} - 列表容器组件的 React 元素
|
|
185
|
+
*/
|
|
186
|
+
declare const ListDataContainer: <T extends boolean = false>(
|
|
187
|
+
props: ListDataContainerProps<T> & RefAttributes<ListDataContainerExposedMethods>
|
|
188
|
+
) => ReactElement;
|
|
189
|
+
|
|
190
|
+
export default ListDataContainer;
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
2
|
+
import React, { useState, useEffect, useCallback, useImperativeHandle, forwardRef } from 'react';
|
|
3
|
+
import { Table, Row, Col, Form } from 'antd';
|
|
4
|
+
import { isEqual } from 'lodash';
|
|
5
|
+
import SearchForm from '../SearchForm';
|
|
6
|
+
import ProTable from '../Table';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @component ListDataContainer
|
|
10
|
+
* @description 通用列表数据容器组件,提供搜索表单、数据表格、分页等功能的完整列表页面解决方案
|
|
11
|
+
*
|
|
12
|
+
* @props {Array} columns - 表格列配置,遵循Ant Design Table组件的columns规范
|
|
13
|
+
* @props {Function} fetchDataApi - 数据获取API函数,接收分页和搜索参数,返回包含list和total的对象
|
|
14
|
+
* @props {Array} searchFormConfig - 搜索表单配置数组
|
|
15
|
+
* @param {React.Component} searchFormConfig[].field - 表单项组件(如ControlWrapper.Select)
|
|
16
|
+
* @param {string} searchFormConfig[].name - 表单项字段名
|
|
17
|
+
* @param {string} searchFormConfig[].label - 表单项标签
|
|
18
|
+
* @param {Object} searchFormConfig[].fieldProps - 传递给字段组件的属性
|
|
19
|
+
* @param {Object} searchFormConfig[].itemProps - 传递给Form.Item的属性
|
|
20
|
+
* @param {React.ReactNode} searchFormConfig[].content - 字段组件的子元素(如Select.Option列表)
|
|
21
|
+
* @param {boolean} searchFormConfig[].required - 是否必填
|
|
22
|
+
* @props {string} rowKey - 表格行键值,默认为'id'
|
|
23
|
+
* @props {Object} initialPagination - 初始分页配置,包含current、pageSize等分页属性
|
|
24
|
+
* @props {Object} tableProps - 传递给Table组件的属性
|
|
25
|
+
* @props {boolean} proTable - 是否使用ProTable组件,默认为false
|
|
26
|
+
* @example
|
|
27
|
+
* // 基础用法
|
|
28
|
+
* <ListDataContainer
|
|
29
|
+
* columns={tableColumns}
|
|
30
|
+
* fetchDataApi={getCourseList}
|
|
31
|
+
* searchFormConfig={[
|
|
32
|
+
* {
|
|
33
|
+
* field: Select,
|
|
34
|
+
* name: 'status',
|
|
35
|
+
* label: '状态',
|
|
36
|
+
* }
|
|
37
|
+
* {
|
|
38
|
+
* field: Input,
|
|
39
|
+
* name: 'name',
|
|
40
|
+
* label: '名称',
|
|
41
|
+
* required: true,
|
|
42
|
+
* }
|
|
43
|
+
* ]}
|
|
44
|
+
* />
|
|
45
|
+
*
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
const SELECT_COMPONENTS = ['Select', 'TreeSelect', 'Cascader', 'DatePicker', 'TimePicker', 'Checkbox', 'Radio', 'Switch', 'Slider', 'Upload'];
|
|
49
|
+
const INPUT_COMPONENTS = ['Input', 'InputNumber'];
|
|
50
|
+
const ListDataContainer = /*#__PURE__*/forwardRef(({
|
|
51
|
+
columns,
|
|
52
|
+
fetchDataApi,
|
|
53
|
+
searchFormConfig = [],
|
|
54
|
+
rowKey = 'id',
|
|
55
|
+
initialPagination = {
|
|
56
|
+
current: 1,
|
|
57
|
+
pageSize: 10,
|
|
58
|
+
showSizeChanger: true,
|
|
59
|
+
showQuickJumper: true,
|
|
60
|
+
showTotal: total => `共 ${total} 条记录`
|
|
61
|
+
},
|
|
62
|
+
tableProps = {},
|
|
63
|
+
proTable = false
|
|
64
|
+
}, ref) => {
|
|
65
|
+
const [form] = Form.useForm();
|
|
66
|
+
const [tableData, setTableData] = useState([]);
|
|
67
|
+
const [loading, setLoading] = useState(false);
|
|
68
|
+
const [pagination, setPagination] = useState(initialPagination);
|
|
69
|
+
const [totalCount, setTotalCount] = useState(0);
|
|
70
|
+
const getComponentName = Component => {
|
|
71
|
+
return Component.displayName || Component.constructor.name;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* 数据加载与刷新方法
|
|
76
|
+
* @param {Object} [overrideParams={}] - 可选,用于覆盖内部参数的键值对
|
|
77
|
+
* 若传入,会覆盖同名的表单参数和分页参数(如page、pageSize或搜索字段)
|
|
78
|
+
*/
|
|
79
|
+
const loadDataSource = useCallback(async (overrideParams = {}) => {
|
|
80
|
+
if (!fetchDataApi) return;
|
|
81
|
+
setLoading(true);
|
|
82
|
+
try {
|
|
83
|
+
// 1. 获取组件内部的表单参数
|
|
84
|
+
const formValues = await form.validateFields();
|
|
85
|
+
|
|
86
|
+
// 2. 构造基础参数:分页参数 + 表单参数
|
|
87
|
+
const baseParams = {
|
|
88
|
+
page: pagination.current,
|
|
89
|
+
pageSize: pagination.pageSize,
|
|
90
|
+
...formValues
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// 3. 用外部传入的参数覆盖基础参数(同名参数以外部为准)
|
|
94
|
+
const requestParams = {
|
|
95
|
+
...baseParams,
|
|
96
|
+
...overrideParams
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// 4. 发起请求
|
|
100
|
+
const response = await fetchDataApi(requestParams);
|
|
101
|
+
setTableData(response.data.list || []);
|
|
102
|
+
setTotalCount(response.data.total || 0);
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.error('列表数据请求失败:', error);
|
|
105
|
+
setTableData([]);
|
|
106
|
+
setTotalCount(0);
|
|
107
|
+
} finally {
|
|
108
|
+
setLoading(false);
|
|
109
|
+
}
|
|
110
|
+
}, [fetchDataApi, pagination, form]);
|
|
111
|
+
|
|
112
|
+
// 暴露刷新方法给父组件
|
|
113
|
+
useImperativeHandle(ref, () => ({
|
|
114
|
+
// 外部调用时可传入覆盖参数
|
|
115
|
+
loadDataSource: (overrideParams = {}) => loadDataSource(overrideParams)
|
|
116
|
+
}));
|
|
117
|
+
const handleFinish = values => {
|
|
118
|
+
// 搜索时重置到第一页,并用表单值覆盖(values会合并到baseParams中)
|
|
119
|
+
setPagination(prev => ({
|
|
120
|
+
...prev,
|
|
121
|
+
current: 1
|
|
122
|
+
}));
|
|
123
|
+
loadDataSource(values);
|
|
124
|
+
};
|
|
125
|
+
const handleReset = () => {
|
|
126
|
+
// 清空表单
|
|
127
|
+
form.setFieldsValue(searchFormConfig.reduce((obj, item) => {
|
|
128
|
+
obj[item.name] = undefined;
|
|
129
|
+
return obj;
|
|
130
|
+
}, {}));
|
|
131
|
+
// 重置分页并使用内部默认参数查询
|
|
132
|
+
setPagination(initialPagination);
|
|
133
|
+
loadDataSource();
|
|
134
|
+
};
|
|
135
|
+
const handlePaginationChange = newPagination => {
|
|
136
|
+
// 更新分页后,用新分页参数查询
|
|
137
|
+
setPagination(newPagination);
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
// 分页变化时自动重新加载
|
|
141
|
+
useEffect(() => {
|
|
142
|
+
// 避免初始加载时重复调用,判断两个对象是否相等
|
|
143
|
+
if (!isEqual(pagination, initialPagination)) {
|
|
144
|
+
loadDataSource();
|
|
145
|
+
}
|
|
146
|
+
}, [pagination, loadDataSource]);
|
|
147
|
+
const generateFormItems = () => {
|
|
148
|
+
return searchFormConfig.map((item, index) => {
|
|
149
|
+
const {
|
|
150
|
+
field: FieldComponent,
|
|
151
|
+
name,
|
|
152
|
+
label,
|
|
153
|
+
required,
|
|
154
|
+
fieldProps = {},
|
|
155
|
+
itemProps = {},
|
|
156
|
+
content,
|
|
157
|
+
...restProps
|
|
158
|
+
} = item;
|
|
159
|
+
return /*#__PURE__*/React.createElement(Form.Item, _extends({
|
|
160
|
+
key: `search-item-${name}-${index}`,
|
|
161
|
+
name: name,
|
|
162
|
+
label: label
|
|
163
|
+
}, required ? {
|
|
164
|
+
required: true,
|
|
165
|
+
rules: [{
|
|
166
|
+
required: true,
|
|
167
|
+
message: `${SELECT_COMPONENTS.includes(getComponentName(FieldComponent)) ? '请选择' : '请输入'}${label}`
|
|
168
|
+
}]
|
|
169
|
+
} : {}, itemProps, restProps), /*#__PURE__*/React.createElement(FieldComponent, _extends({
|
|
170
|
+
allowClear: true,
|
|
171
|
+
placeholder: `${SELECT_COMPONENTS.includes(getComponentName(FieldComponent)) ? '请选择' : '请输入'}${label}`
|
|
172
|
+
}, fieldProps), content || null));
|
|
173
|
+
}).filter(Boolean);
|
|
174
|
+
};
|
|
175
|
+
const TableComponent = proTable ? ProTable : Table;
|
|
176
|
+
return /*#__PURE__*/React.createElement(Row, {
|
|
177
|
+
gutter: [16, 24]
|
|
178
|
+
}, /*#__PURE__*/React.createElement(Col, {
|
|
179
|
+
span: 24
|
|
180
|
+
}, /*#__PURE__*/React.createElement(SearchForm, {
|
|
181
|
+
expand: true,
|
|
182
|
+
form: form,
|
|
183
|
+
loading: loading,
|
|
184
|
+
formLine: generateFormItems(),
|
|
185
|
+
onReset: handleReset,
|
|
186
|
+
onFinish: handleFinish
|
|
187
|
+
})), /*#__PURE__*/React.createElement(Col, {
|
|
188
|
+
span: 24
|
|
189
|
+
}, /*#__PURE__*/React.createElement(TableComponent, _extends({
|
|
190
|
+
columns: columns,
|
|
191
|
+
dataSource: tableData,
|
|
192
|
+
rowKey: rowKey,
|
|
193
|
+
loading: loading,
|
|
194
|
+
pagination: {
|
|
195
|
+
...pagination,
|
|
196
|
+
total: totalCount
|
|
197
|
+
},
|
|
198
|
+
onChange: handlePaginationChange,
|
|
199
|
+
scroll: {
|
|
200
|
+
x: 'max-content'
|
|
201
|
+
},
|
|
202
|
+
bordered: true
|
|
203
|
+
}, tableProps))));
|
|
204
|
+
});
|
|
205
|
+
export default ListDataContainer;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
页面布局组件
|
|
2
|
+
|
|
3
|
+
## 代码演示
|
|
4
|
+
|
|
5
|
+
```jsx
|
|
6
|
+
import { useState } from 'react';
|
|
7
|
+
import { Button } from 'antd';
|
|
8
|
+
import PageLayout from '@cqsjjb/jjb-react-admin-component/PageLayout';
|
|
9
|
+
|
|
10
|
+
function App() {
|
|
11
|
+
return (
|
|
12
|
+
<PageLayout title="用户中心">
|
|
13
|
+
|
|
14
|
+
</PageLayout>
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## API
|
|
20
|
+
|
|
21
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
22
|
+
|-----------------|:-----------|:---------------:|------:|
|
|
23
|
+
| title | 页面标题 | `string` | - |
|
|
24
|
+
| extra | 右上角扩展 | `ReactNode` | - |
|
|
25
|
+
| header | 自定义头部 | `ReactNode` | - |
|
|
26
|
+
| footer | 自定义底部 | `ReactNode` | - |
|
|
27
|
+
| history | 路由历史对象 | `History` | - |
|
|
28
|
+
| noStyle | 去除所有样式 | `boolean` | false |
|
|
29
|
+
| noBorder | 取消边框 | `boolean` | false |
|
|
30
|
+
| formLine | form 表单行 | `ReactNode[]` | - |
|
|
31
|
+
| formLineStyle | form 表单行样式 | `CSSProperties` | - |
|
|
32
|
+
| previous | 显示返回上一页 | `boolean` | false |
|
|
33
|
+
| transparent | 背景透明 | `boolean` | false |
|
|
34
|
+
| contentStyle | 内容区样式 | `CSSProperties` | - |
|
|
35
|
+
| footerStyle | 底部样式 | `CSSProperties` | - |
|
|
36
|
+
| pageHeaderStyle | 头部样式 | `CSSProperties` | - |
|
|
37
|
+
| style | 自定义返回事件 | `CSSProperties` | - |
|
|
38
|
+
| onBack | 容器样式 | `() => void` | - |
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
注意:`previous`为`true`时`history`必传,否则点击返回无效。
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
[搜索表单组件
|
|
2
|
+
|
|
3
|
+
## 代码演示
|
|
4
|
+
|
|
5
|
+
```jsx
|
|
6
|
+
import { useState, userRef } from 'react';
|
|
7
|
+
import { Button, Form, Input } from 'antd';
|
|
8
|
+
import SearchForm from '@cqsjjb/jjb-react-admin-component/SearchForm';
|
|
9
|
+
import PageLayout from '@cqsjjb/jjb-react-admin-component/PageLayout';
|
|
10
|
+
|
|
11
|
+
function App() {
|
|
12
|
+
const form = useRef();
|
|
13
|
+
|
|
14
|
+
// 提交
|
|
15
|
+
const onFinish = values => {
|
|
16
|
+
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<PageLayout
|
|
21
|
+
title="用户中心"
|
|
22
|
+
formLine={(
|
|
23
|
+
<SearchForm
|
|
24
|
+
form={form}
|
|
25
|
+
formLine={[
|
|
26
|
+
<Form.Item
|
|
27
|
+
noStyle
|
|
28
|
+
name="keyword"
|
|
29
|
+
>
|
|
30
|
+
<Input
|
|
31
|
+
allowClear
|
|
32
|
+
placeholder="请输入关键字"
|
|
33
|
+
/>
|
|
34
|
+
</Form.Item>
|
|
35
|
+
]}
|
|
36
|
+
onReset={() => {
|
|
37
|
+
form.current.submit();
|
|
38
|
+
}}
|
|
39
|
+
onFinish={onFinish}
|
|
40
|
+
/>
|
|
41
|
+
)}
|
|
42
|
+
>
|
|
43
|
+
|
|
44
|
+
</PageLayout>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## API
|
|
50
|
+
|
|
51
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
52
|
+
|---------------|:--------------------------|:-----------------------------------------------:|------:|
|
|
53
|
+
| form | form 实例 | `React.RefObject<FormInstance>` | - |
|
|
54
|
+
| style | 样式 | `CSSProperties` | - |
|
|
55
|
+
| expand | 是否展开,受控模式 | `boolean` | false |
|
|
56
|
+
| defaultExpand | 内部默认展开状态,仅在 expand 未传入时生效 | `boolean` | false |
|
|
57
|
+
| colSize | 列数 | `number` | 3 |
|
|
58
|
+
| loading | 查询 loading 状态 | `boolean` | false |
|
|
59
|
+
| formLine | 表单行节点数组 | `ReactNode[]` | - |
|
|
60
|
+
| initialValues | 表单初始值 | `Record<string, any>` | - |
|
|
61
|
+
| onRef | 获取 form 实例回调(已废弃) | `(form: React.RefObject<FormInstance>) => void` | - |
|
|
62
|
+
| onReset | 重置回调 | `(values: Record<string, any>) => void` | - |
|
|
63
|
+
| onFinish | 提交回调 | `(values: Record<string, any>) => void` | - |
|
|
64
|
+
| onExpand | 展开/收起状态变化回调 | `(open: boolean) => void` | - |
|
|
65
|
+
|
|
66
|
+
]()
|
package/Table/README.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
高级Table,基于ProAntd实现
|
|
2
|
+
|
|
3
|
+
## 代码演示
|
|
4
|
+
|
|
5
|
+
```jsx
|
|
6
|
+
import Table from '@cqsjjb/jjb-react-admin-component/Table';
|
|
7
|
+
|
|
8
|
+
function App() {
|
|
9
|
+
return (
|
|
10
|
+
<>
|
|
11
|
+
<Table
|
|
12
|
+
columns={[
|
|
13
|
+
{
|
|
14
|
+
title: 'ID',
|
|
15
|
+
dataIndex: 'id'
|
|
16
|
+
}
|
|
17
|
+
]}
|
|
18
|
+
dataSource={[
|
|
19
|
+
{
|
|
20
|
+
id: 1
|
|
21
|
+
}
|
|
22
|
+
]}
|
|
23
|
+
/>
|
|
24
|
+
</>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## API
|
|
30
|
+
|
|
31
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
32
|
+
|-----------------|:-------------------------------------------------------------|:---------:|------:|
|
|
33
|
+
| disabledResizer | 是否禁用内容区滚动,设置true自动将适配内容区滚动高度 | `boolean` | false |
|
|
34
|
+
| storeIndex | 当一个路由下存在多个表格的情况下 需要给每一个表格设置一个唯一存储索引 若没有设置则使用默认索引,请注意缓存数据会被覆盖 | `number` | - |
|
|
35
|
+
|
|
36
|
+
其他属性参考 https://ant-design.antgroup.com/components/table-cn#api
|
package/Table/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import * as React from 'react';
|
|
|
3
3
|
// @ts-ignore
|
|
4
4
|
import type { TableProps } from 'antd';
|
|
5
5
|
|
|
6
|
-
interface OverTableProps extends TableProps {
|
|
6
|
+
export interface OverTableProps extends TableProps {
|
|
7
7
|
// 是否禁用内容区滚动,默认-false
|
|
8
8
|
disabledResizer?: boolean;
|
|
9
9
|
// 当一个路由下存在多个表格的情况下 需要给每一个表格设置一个唯一存储索引 若没有设置则使用默认索引,请注意缓存数据会被覆盖
|
package/Table/index.js
CHANGED
|
@@ -88,7 +88,7 @@ export default function TablePro(props) {
|
|
|
88
88
|
if (enabledResizer) {
|
|
89
89
|
scroll.y = tableHeight;
|
|
90
90
|
}
|
|
91
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ProTable, _extends({
|
|
91
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ProTable, _extends({
|
|
92
92
|
ghost: true,
|
|
93
93
|
columnEmptyText: true,
|
|
94
94
|
size: size,
|
|
@@ -113,5 +113,5 @@ export default function TablePro(props) {
|
|
|
113
113
|
persistenceType: 'localStorage'
|
|
114
114
|
},
|
|
115
115
|
onSizeChange: setSize
|
|
116
|
-
})));
|
|
116
|
+
}, props)));
|
|
117
117
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
表格操作项组件,当操作按钮数量大于最大可显示数量,多余部分显示为"..."并用下拉菜单显示。
|
|
2
|
+
|
|
3
|
+
## 代码演示
|
|
4
|
+
|
|
5
|
+
```jsx
|
|
6
|
+
import { useState } from 'react';
|
|
7
|
+
import { Button, Table } from 'antd';
|
|
8
|
+
import TableAction from '@cqsjjb/jjb-react-admin-component/TableAction';
|
|
9
|
+
|
|
10
|
+
function App() {
|
|
11
|
+
const [ open, setOpen ] = useState(false);
|
|
12
|
+
return (
|
|
13
|
+
<>
|
|
14
|
+
<Button onClick={() => setOpen(true)}>打开地图</Button>
|
|
15
|
+
<Table
|
|
16
|
+
columns={[
|
|
17
|
+
{
|
|
18
|
+
title: 'ID',
|
|
19
|
+
dataIndex: 'id'
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
title: '操作',
|
|
23
|
+
render: () => (
|
|
24
|
+
<TableAction>
|
|
25
|
+
<a>
|
|
26
|
+
编辑
|
|
27
|
+
</a>
|
|
28
|
+
<a>
|
|
29
|
+
删除
|
|
30
|
+
</a>
|
|
31
|
+
<a>
|
|
32
|
+
详情
|
|
33
|
+
</a>
|
|
34
|
+
{/*多余部分*/}
|
|
35
|
+
<a>
|
|
36
|
+
复制
|
|
37
|
+
</a>
|
|
38
|
+
</TableAction>
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
]}
|
|
42
|
+
/>
|
|
43
|
+
</>
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## API
|
|
49
|
+
|
|
50
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
51
|
+
|-----------|:----------------------------------------------------------------------|:------------:|-------------:|
|
|
52
|
+
| icon | 图标 | `React.Node` | MoreOutlined |
|
|
53
|
+
| maximum | 最大显示数量,超出的会放入下拉菜单 | `number` | 3 |
|
|
54
|
+
| space | 按钮之间的间距 | `number` | 8 |
|
|
55
|
+
| placement | 下拉菜单显示位置,参考 https://ant-design.antgroup.com/components/tooltip-cn#api | `string` | bottomRight |
|
|
56
|
+
| trigger | 下拉触发方式,参考 https://ant-design.antgroup.com/components/tooltip-cn#api | `string` | hover |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cqsjjb/jjb-react-admin-component",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0-beta.1",
|
|
4
4
|
"description": "jjb-react-admin-组件库@new",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"author": "jjb-front-team",
|
|
@@ -10,12 +10,14 @@
|
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"axios": "^1.6.5",
|
|
13
|
+
"lodash": "^4.17.21",
|
|
13
14
|
"spark-md5": "^3.0.2",
|
|
14
15
|
"cropperjs": "^1.6.2",
|
|
15
16
|
"@wangeditor-next/editor": "latest",
|
|
16
17
|
"@cqsjjb-formily/renderer": "latest",
|
|
17
18
|
"@ant-design/pro-layout": "latest",
|
|
18
19
|
"use-antd-resizable-header": "latest",
|
|
19
|
-
"@ant-design/pro-components": "latest"
|
|
20
|
+
"@ant-design/pro-components": "latest",
|
|
21
|
+
"react-cropper": "2.3.3"
|
|
20
22
|
}
|
|
21
23
|
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
@com-prefix-cls: if(isdefined(@ant-prefix), @ant-prefix, ant);
|
|
2
|
-
|
|
3
|
-
.@{com-prefix-cls}-form-item-control-label-wrapper {
|
|
4
|
-
.@{com-prefix-cls}-form-item-control-label-span {
|
|
5
|
-
border: 1px solid #d9d9d9;
|
|
6
|
-
height: 32px;
|
|
7
|
-
line-height: 30px;
|
|
8
|
-
box-sizing: border-box;
|
|
9
|
-
margin-right: -1px;
|
|
10
|
-
padding: 0 2px 0 8px;
|
|
11
|
-
border-top-left-radius: 4px;
|
|
12
|
-
border-bottom-left-radius: 4px;
|
|
13
|
-
white-space: nowrap;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
&.@{com-prefix-cls}-form-item-control-label-has {
|
|
17
|
-
.@{com-prefix-cls}-select-selector, .@{com-prefix-cls}-picker, .@{com-prefix-cls}-input, .@{com-prefix-cls}-input-affix-wrapper {
|
|
18
|
-
border-top-left-radius: 0;
|
|
19
|
-
border-bottom-left-radius: 0;
|
|
20
|
-
border-left-color: transparent !important;
|
|
21
|
-
&:hover, &:focus, &:focus-within{
|
|
22
|
-
border-left-color: @colorPrimary !important;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
&-default {
|
|
28
|
-
.@{com-prefix-cls}-form-item-control-label-span {
|
|
29
|
-
border-color: #d9d9d9;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
&-dark {
|
|
34
|
-
.@{com-prefix-cls}-form-item-control-label-span {
|
|
35
|
-
border-color: #424242;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|