@fe-free/core 3.0.36 → 3.0.38
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/CHANGELOG.md +16 -0
- package/package.json +3 -3
- package/src/crud/crud.tsx +13 -196
- package/src/crud/crud_delete.tsx +4 -3
- package/src/crud/crud_detail.tsx +2 -1
- package/src/crud/demo/data.tsx +5 -2
- package/src/crud/use_no_column.tsx +43 -0
- package/src/crud/use_operate.tsx +248 -0
- package/src/crud/use_row_selection.tsx +5 -3
- package/src/global/error.ts +1 -0
- package/src/upload/index.tsx +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @fe-free/core
|
|
2
2
|
|
|
3
|
+
## 3.0.38
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- feat: some
|
|
8
|
+
- @fe-free/icons@3.0.38
|
|
9
|
+
- @fe-free/tool@3.0.38
|
|
10
|
+
|
|
11
|
+
## 3.0.37
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- feat: crud
|
|
16
|
+
- @fe-free/icons@3.0.37
|
|
17
|
+
- @fe-free/tool@3.0.37
|
|
18
|
+
|
|
3
19
|
## 3.0.36
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fe-free/core",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.38",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"author": "",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"antd": "^5.27.1",
|
|
47
47
|
"dayjs": "~1.11.10",
|
|
48
48
|
"react": "^19.2.0",
|
|
49
|
-
"@fe-free/
|
|
50
|
-
"@fe-free/
|
|
49
|
+
"@fe-free/tool": "3.0.38",
|
|
50
|
+
"@fe-free/icons": "3.0.38"
|
|
51
51
|
},
|
|
52
52
|
"scripts": {
|
|
53
53
|
"test": "echo \"Error: no test specified\" && exit 1"
|
package/src/crud/crud.tsx
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
import type { ActionType } from '@ant-design/pro-components';
|
|
2
|
-
import {
|
|
3
|
-
import { Button, message, Tooltip } from 'antd';
|
|
2
|
+
import { Button } from 'antd';
|
|
4
3
|
import classNames from 'classnames';
|
|
5
|
-
import { isString } from 'lodash-es';
|
|
6
4
|
import { useCallback, useImperativeHandle, useMemo, useRef } from 'react';
|
|
7
|
-
import { Link } from 'react-router-dom';
|
|
8
|
-
import { OperateDelete } from './crud_delete';
|
|
9
5
|
import { CRUDDetail } from './crud_detail';
|
|
10
6
|
import './style.scss';
|
|
11
|
-
import type { TableProps } from './table';
|
|
12
7
|
import { getTableScroll, Table } from './table';
|
|
13
8
|
import type { CRUDProps } from './types';
|
|
9
|
+
import { useNoColumn } from './use_no_column';
|
|
10
|
+
import { useOperate } from './use_operate';
|
|
14
11
|
import { useRowSelection } from './use_row_selection';
|
|
15
12
|
import { useTips } from './use_tips';
|
|
16
13
|
|
|
@@ -21,11 +18,7 @@ function CRUD<DataSource extends Record<string, any> = any, Key extends string |
|
|
|
21
18
|
actions,
|
|
22
19
|
tableProps,
|
|
23
20
|
createButton,
|
|
24
|
-
operateColumnProps,
|
|
25
21
|
readProps,
|
|
26
|
-
requestDeleteByRecord,
|
|
27
|
-
deleteProps,
|
|
28
|
-
detailIdIndex,
|
|
29
22
|
detailForm,
|
|
30
23
|
requestGetByRecord,
|
|
31
24
|
createProps,
|
|
@@ -73,195 +66,18 @@ function CRUD<DataSource extends Record<string, any> = any, Key extends string |
|
|
|
73
66
|
],
|
|
74
67
|
);
|
|
75
68
|
|
|
76
|
-
const getHandleDelete = useCallback(
|
|
77
|
-
(record) => {
|
|
78
|
-
return () => {
|
|
79
|
-
if (requestDeleteByRecord) {
|
|
80
|
-
let content = '删除成功';
|
|
81
|
-
if (deleteProps?.successText) {
|
|
82
|
-
content = isString(deleteProps.successText)
|
|
83
|
-
? deleteProps.successText
|
|
84
|
-
: deleteProps.successText();
|
|
85
|
-
}
|
|
86
|
-
return requestDeleteByRecord(record).then(() => {
|
|
87
|
-
message.open({
|
|
88
|
-
type: 'success',
|
|
89
|
-
content,
|
|
90
|
-
});
|
|
91
|
-
actionRef.current?.reload();
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
throw new Error('没有传 requestDeleteByRecord');
|
|
96
|
-
};
|
|
97
|
-
},
|
|
98
|
-
[deleteProps, requestDeleteByRecord],
|
|
99
|
-
);
|
|
100
|
-
|
|
101
69
|
const handleReload = useCallback(() => {
|
|
102
70
|
actionRef.current?.reload();
|
|
103
71
|
}, []);
|
|
104
72
|
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
fixed: 'right',
|
|
111
|
-
align: 'center',
|
|
112
|
-
width: operateColumnProps?.width || 120,
|
|
113
|
-
render: function (_, record) {
|
|
114
|
-
const btns: React.ReactNode[] = [];
|
|
115
|
-
|
|
116
|
-
if (actions.includes('read')) {
|
|
117
|
-
const hidden = readProps?.operateIsHidden?.(record) || false;
|
|
118
|
-
if (!hidden) {
|
|
119
|
-
const disabled = readProps?.operateIsDisabled?.(record) || false;
|
|
120
|
-
if (disabled) {
|
|
121
|
-
btns.push(
|
|
122
|
-
<Tooltip title={readProps?.operateText || '查看'}>
|
|
123
|
-
<span key="read" className="cursor-not-allowed text-lg text-03">
|
|
124
|
-
{readProps?.operateText || <EyeOutlined />}
|
|
125
|
-
</span>
|
|
126
|
-
</Tooltip>,
|
|
127
|
-
);
|
|
128
|
-
} else {
|
|
129
|
-
btns.push(
|
|
130
|
-
<CRUDDetail
|
|
131
|
-
key="read"
|
|
132
|
-
id={record[idField]}
|
|
133
|
-
record={record}
|
|
134
|
-
onSuccess={handleReload}
|
|
135
|
-
trigger={
|
|
136
|
-
<Tooltip title={readProps?.operateText || '查看'}>
|
|
137
|
-
<a className="text-lg">{readProps?.operateText || <EyeOutlined />}</a>
|
|
138
|
-
</Tooltip>
|
|
139
|
-
}
|
|
140
|
-
action="read"
|
|
141
|
-
{...detailProps}
|
|
142
|
-
/>,
|
|
143
|
-
);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (actions.includes('read_detail')) {
|
|
149
|
-
const hidden = readProps?.operateIsHidden?.(record) || false;
|
|
150
|
-
if (!hidden) {
|
|
151
|
-
const disabled = readProps?.operateIsDisabled?.(record) || false;
|
|
152
|
-
if (disabled) {
|
|
153
|
-
btns.push(
|
|
154
|
-
<Tooltip title={readProps?.operateText || '查看'}>
|
|
155
|
-
<span key="read" className="cursor-not-allowed text-lg text-03">
|
|
156
|
-
{readProps?.operateText || <EyeOutlined />}
|
|
157
|
-
</span>
|
|
158
|
-
</Tooltip>,
|
|
159
|
-
);
|
|
160
|
-
} else {
|
|
161
|
-
btns.push(
|
|
162
|
-
<Tooltip title={readProps?.operateText || '查看'}>
|
|
163
|
-
<Link
|
|
164
|
-
key="read_detail"
|
|
165
|
-
to={`./detail/${record[detailIdIndex || 'id']}`}
|
|
166
|
-
target={readProps?.target}
|
|
167
|
-
className="text-lg"
|
|
168
|
-
>
|
|
169
|
-
{readProps?.operateText || <EyeOutlined />}
|
|
170
|
-
</Link>
|
|
171
|
-
</Tooltip>,
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
if (actions.includes('update')) {
|
|
178
|
-
const hidden = updateProps?.operateIsHidden?.(record) || false;
|
|
179
|
-
if (!hidden) {
|
|
180
|
-
const disabled = updateProps?.operateIsDisabled?.(record) || false;
|
|
181
|
-
|
|
182
|
-
if (disabled) {
|
|
183
|
-
btns.push(
|
|
184
|
-
<Tooltip title={updateProps?.operateText || '编辑'}>
|
|
185
|
-
<span key="update" className="cursor-not-allowed text-lg text-03">
|
|
186
|
-
{updateProps?.operateText || <EditOutlined />}
|
|
187
|
-
</span>
|
|
188
|
-
</Tooltip>,
|
|
189
|
-
);
|
|
190
|
-
} else {
|
|
191
|
-
btns.push(
|
|
192
|
-
<CRUDDetail
|
|
193
|
-
key="update"
|
|
194
|
-
id={record[idField]}
|
|
195
|
-
record={record}
|
|
196
|
-
onSuccess={handleReload}
|
|
197
|
-
trigger={
|
|
198
|
-
<Tooltip title={updateProps?.operateText || '编辑'}>
|
|
199
|
-
<a className="text-lg">{updateProps?.operateText || <EditOutlined />}</a>
|
|
200
|
-
</Tooltip>
|
|
201
|
-
}
|
|
202
|
-
action="update"
|
|
203
|
-
{...detailProps}
|
|
204
|
-
/>,
|
|
205
|
-
);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
if (actions.includes('delete') && deleteProps) {
|
|
211
|
-
const hidden = deleteProps?.operateIsHidden?.(record) || false;
|
|
212
|
-
if (!hidden) {
|
|
213
|
-
const disabled = deleteProps?.operateIsDisabled?.(record) || false;
|
|
214
|
-
btns.push(
|
|
215
|
-
<OperateDelete
|
|
216
|
-
key="delete"
|
|
217
|
-
name={record[deleteProps.nameIndex]}
|
|
218
|
-
desc={deleteProps.desc}
|
|
219
|
-
operateText={deleteProps.operateText}
|
|
220
|
-
disabled={disabled}
|
|
221
|
-
onDelete={getHandleDelete(record)}
|
|
222
|
-
/>,
|
|
223
|
-
);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
return (
|
|
228
|
-
<div className="fec-crud-operate-column flex justify-center gap-4">
|
|
229
|
-
{operateColumnProps?.moreOperator && operateColumnProps.moreOperator(record)}
|
|
230
|
-
{btns}
|
|
231
|
-
{operateColumnProps?.moreOperatorAfter && operateColumnProps.moreOperatorAfter(record)}
|
|
232
|
-
</div>
|
|
233
|
-
);
|
|
234
|
-
},
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
if (
|
|
238
|
-
actions.includes('read') ||
|
|
239
|
-
actions.includes('read_detail') ||
|
|
240
|
-
actions.includes('update') ||
|
|
241
|
-
actions.includes('delete') ||
|
|
242
|
-
operateColumnProps?.moreOperator ||
|
|
243
|
-
operateColumnProps?.moreOperatorAfter
|
|
244
|
-
) {
|
|
245
|
-
return [
|
|
246
|
-
...(tableProps.columns || tableProps.columns || []),
|
|
247
|
-
operateColumn,
|
|
248
|
-
] as TableProps['columns'];
|
|
249
|
-
}
|
|
73
|
+
const { columns: operateColumns } = useOperate(props, detailProps, actionRef);
|
|
74
|
+
const { columns: noColumnColumns, request: noRequest } = useNoColumn({
|
|
75
|
+
request: tableProps.request,
|
|
76
|
+
columns: operateColumns,
|
|
77
|
+
});
|
|
250
78
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
tableProps.rowKey,
|
|
254
|
-
tableProps.columns,
|
|
255
|
-
operateColumnProps,
|
|
256
|
-
actions,
|
|
257
|
-
deleteProps,
|
|
258
|
-
readProps,
|
|
259
|
-
handleReload,
|
|
260
|
-
detailProps,
|
|
261
|
-
detailIdIndex,
|
|
262
|
-
updateProps,
|
|
263
|
-
getHandleDelete,
|
|
264
|
-
]);
|
|
79
|
+
const newColumns = noColumnColumns;
|
|
80
|
+
const newRequest = noRequest;
|
|
265
81
|
|
|
266
82
|
const toolBarRender = useCallback(
|
|
267
83
|
(...args) =>
|
|
@@ -312,14 +128,14 @@ function CRUD<DataSource extends Record<string, any> = any, Key extends string |
|
|
|
312
128
|
return {
|
|
313
129
|
...tableProps,
|
|
314
130
|
scroll: {
|
|
315
|
-
...getTableScroll(
|
|
131
|
+
...getTableScroll(newColumns),
|
|
316
132
|
y: '100%',
|
|
317
133
|
},
|
|
318
134
|
};
|
|
319
135
|
}
|
|
320
136
|
|
|
321
137
|
return tableProps;
|
|
322
|
-
}, [tableProps,
|
|
138
|
+
}, [fullPage, tableProps, newColumns]);
|
|
323
139
|
|
|
324
140
|
return (
|
|
325
141
|
<div
|
|
@@ -337,6 +153,7 @@ function CRUD<DataSource extends Record<string, any> = any, Key extends string |
|
|
|
337
153
|
actionRef={actionRef}
|
|
338
154
|
toolBarRender={toolBarRender}
|
|
339
155
|
columns={newColumns}
|
|
156
|
+
request={newRequest}
|
|
340
157
|
rowSelection={rowSelection}
|
|
341
158
|
tableAlertRender={tableAlertRender}
|
|
342
159
|
tableAlertOptionRender={tableAlertOptionRender}
|
package/src/crud/crud_delete.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DeleteOutlined } from '@fe-free/icons';
|
|
2
|
-
import {
|
|
2
|
+
import { App, Tooltip } from 'antd';
|
|
3
3
|
import { useCallback } from 'react';
|
|
4
4
|
|
|
5
5
|
interface Params {
|
|
@@ -12,10 +12,11 @@ interface Params {
|
|
|
12
12
|
|
|
13
13
|
function useDelete(params: Params) {
|
|
14
14
|
const { name, desc, onDelete } = params;
|
|
15
|
+
const { modal } = App.useApp();
|
|
15
16
|
|
|
16
17
|
const doDelete = useCallback(async () => {
|
|
17
18
|
await new Promise((resolve) => {
|
|
18
|
-
|
|
19
|
+
modal.confirm({
|
|
19
20
|
title: `确认删除 “${name}” 吗?`,
|
|
20
21
|
content: desc || '删除后不可恢复,请谨慎操作',
|
|
21
22
|
okText: '确定',
|
|
@@ -28,7 +29,7 @@ function useDelete(params: Params) {
|
|
|
28
29
|
},
|
|
29
30
|
});
|
|
30
31
|
});
|
|
31
|
-
}, [name, desc, onDelete]);
|
|
32
|
+
}, [modal, name, desc, onDelete]);
|
|
32
33
|
|
|
33
34
|
return {
|
|
34
35
|
doDelete,
|
package/src/crud/crud_detail.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DrawerForm, ProForm } from '@ant-design/pro-components';
|
|
2
|
-
import {
|
|
2
|
+
import { App, Spin } from 'antd';
|
|
3
3
|
import classNames from 'classnames';
|
|
4
4
|
import { isString } from 'lodash-es';
|
|
5
5
|
import { useCallback, useMemo, useState } from 'react';
|
|
@@ -54,6 +54,7 @@ function CRUDDetail(props: CRUDDetailProps) {
|
|
|
54
54
|
const [isOpen, setIsOpen] = useState(false);
|
|
55
55
|
const [loading, setLoading] = useState(id ? true : false);
|
|
56
56
|
const [form] = ProForm.useForm(detailFormInstance);
|
|
57
|
+
const { message } = App.useApp();
|
|
57
58
|
|
|
58
59
|
const handleFinish = useCallback(
|
|
59
60
|
async (values) => {
|
package/src/crud/demo/data.tsx
CHANGED
|
@@ -58,7 +58,10 @@ let fakeData = makeData(21);
|
|
|
58
58
|
async function fakeRequest(params) {
|
|
59
59
|
console.log('fakeRequest', params);
|
|
60
60
|
|
|
61
|
-
let data = fakeData
|
|
61
|
+
let data = fakeData.slice(
|
|
62
|
+
(params.current - 1) * params.pageSize,
|
|
63
|
+
params.current * params.pageSize,
|
|
64
|
+
);
|
|
62
65
|
Object.keys(params).forEach((field) => {
|
|
63
66
|
if (params[field] !== undefined && params[field] !== '') {
|
|
64
67
|
data = data.filter((item) => {
|
|
@@ -75,7 +78,7 @@ async function fakeRequest(params) {
|
|
|
75
78
|
resolve({
|
|
76
79
|
data,
|
|
77
80
|
success: true,
|
|
78
|
-
total:
|
|
81
|
+
total: fakeData.length,
|
|
79
82
|
});
|
|
80
83
|
}, 1000);
|
|
81
84
|
}) as Promise<any>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { useCallback, useRef } from 'react';
|
|
2
|
+
import { CustomValueTypeEnum } from '../value_type_map';
|
|
3
|
+
|
|
4
|
+
function useNoColumn({ request, columns }) {
|
|
5
|
+
const refCurrent = useRef<number>(1);
|
|
6
|
+
const refPageSize = useRef<number>(20);
|
|
7
|
+
|
|
8
|
+
const newRequest = useCallback(
|
|
9
|
+
async (params) => {
|
|
10
|
+
const { current, pageSize } = params;
|
|
11
|
+
|
|
12
|
+
const res = await request(params);
|
|
13
|
+
|
|
14
|
+
// after request, 才更新,数据才准确
|
|
15
|
+
refCurrent.current = current;
|
|
16
|
+
refPageSize.current = pageSize;
|
|
17
|
+
|
|
18
|
+
return res;
|
|
19
|
+
},
|
|
20
|
+
[request],
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
const newColumns = useCallback(() => {
|
|
24
|
+
return columns?.map((column) => {
|
|
25
|
+
if (column.valueType === CustomValueTypeEnum.CustomSerialNumber) {
|
|
26
|
+
return {
|
|
27
|
+
render: (_, __, index) => {
|
|
28
|
+
return (refCurrent.current - 1) * refPageSize.current + index + 1;
|
|
29
|
+
},
|
|
30
|
+
...column,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
return column;
|
|
34
|
+
});
|
|
35
|
+
}, [columns]);
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
columns: newColumns(),
|
|
39
|
+
request: newRequest,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { useNoColumn };
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { EditOutlined, EyeOutlined } from '@fe-free/icons';
|
|
2
|
+
import { message, Tooltip } from 'antd';
|
|
3
|
+
import { isString } from 'lodash-es';
|
|
4
|
+
import { useCallback, useMemo } from 'react';
|
|
5
|
+
import { Link } from 'react-router-dom';
|
|
6
|
+
import { OperateDelete } from './crud_delete';
|
|
7
|
+
import { CRUDDetail } from './crud_detail';
|
|
8
|
+
import type { TableProps } from './table';
|
|
9
|
+
|
|
10
|
+
function useOperate(props, detailProps, actionRef) {
|
|
11
|
+
const {
|
|
12
|
+
actions,
|
|
13
|
+
tableProps,
|
|
14
|
+
operateColumnProps,
|
|
15
|
+
readProps,
|
|
16
|
+
updateProps,
|
|
17
|
+
deleteProps,
|
|
18
|
+
detailIdIndex,
|
|
19
|
+
requestDeleteByRecord,
|
|
20
|
+
} = props;
|
|
21
|
+
|
|
22
|
+
const idField = tableProps.rowKey || 'id';
|
|
23
|
+
|
|
24
|
+
const getHandleDelete = useCallback(
|
|
25
|
+
(record) => {
|
|
26
|
+
return () => {
|
|
27
|
+
if (requestDeleteByRecord) {
|
|
28
|
+
let content = '删除成功';
|
|
29
|
+
if (deleteProps?.successText) {
|
|
30
|
+
content = isString(deleteProps.successText)
|
|
31
|
+
? deleteProps.successText
|
|
32
|
+
: deleteProps.successText();
|
|
33
|
+
}
|
|
34
|
+
return requestDeleteByRecord(record).then(() => {
|
|
35
|
+
message.open({
|
|
36
|
+
type: 'success',
|
|
37
|
+
content,
|
|
38
|
+
});
|
|
39
|
+
actionRef.current?.reload();
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
throw new Error('没有传 requestDeleteByRecord');
|
|
44
|
+
};
|
|
45
|
+
},
|
|
46
|
+
[actionRef, deleteProps, requestDeleteByRecord],
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const handleReload = useCallback(() => {
|
|
50
|
+
actionRef.current?.reload();
|
|
51
|
+
}, [actionRef]);
|
|
52
|
+
|
|
53
|
+
const readOperate = useCallback(
|
|
54
|
+
(record) => {
|
|
55
|
+
const hidden = readProps?.operateIsHidden?.(record) || false;
|
|
56
|
+
|
|
57
|
+
if (!hidden) {
|
|
58
|
+
const disabled = readProps?.operateIsDisabled?.(record) || false;
|
|
59
|
+
if (disabled) {
|
|
60
|
+
return (
|
|
61
|
+
<Tooltip title={readProps?.operateText || '查看'}>
|
|
62
|
+
<span key="read" className="cursor-not-allowed text-lg text-03">
|
|
63
|
+
{readProps?.operateText || <EyeOutlined />}
|
|
64
|
+
</span>
|
|
65
|
+
</Tooltip>
|
|
66
|
+
);
|
|
67
|
+
} else {
|
|
68
|
+
return (
|
|
69
|
+
<CRUDDetail
|
|
70
|
+
key="read"
|
|
71
|
+
id={record[idField]}
|
|
72
|
+
record={record}
|
|
73
|
+
onSuccess={handleReload}
|
|
74
|
+
trigger={
|
|
75
|
+
<Tooltip title={readProps?.operateText || '查看'}>
|
|
76
|
+
<a className="text-lg">{readProps?.operateText || <EyeOutlined />}</a>
|
|
77
|
+
</Tooltip>
|
|
78
|
+
}
|
|
79
|
+
action="read"
|
|
80
|
+
{...detailProps}
|
|
81
|
+
/>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
},
|
|
87
|
+
[detailProps, handleReload, idField, readProps],
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
const readDetailOperate = useCallback(
|
|
91
|
+
(record) => {
|
|
92
|
+
const hidden = readProps?.operateIsHidden?.(record) || false;
|
|
93
|
+
if (!hidden) {
|
|
94
|
+
const disabled = readProps?.operateIsDisabled?.(record) || false;
|
|
95
|
+
if (disabled) {
|
|
96
|
+
return (
|
|
97
|
+
<Tooltip title={readProps?.operateText || '查看'}>
|
|
98
|
+
<span key="read" className="cursor-not-allowed text-lg text-03">
|
|
99
|
+
{readProps?.operateText || <EyeOutlined />}
|
|
100
|
+
</span>
|
|
101
|
+
</Tooltip>
|
|
102
|
+
);
|
|
103
|
+
} else {
|
|
104
|
+
return (
|
|
105
|
+
<Tooltip title={readProps?.operateText || '查看'}>
|
|
106
|
+
<Link
|
|
107
|
+
key="read_detail"
|
|
108
|
+
to={`./detail/${record[detailIdIndex || 'id']}`}
|
|
109
|
+
target={readProps?.target}
|
|
110
|
+
className="text-lg"
|
|
111
|
+
>
|
|
112
|
+
{readProps?.operateText || <EyeOutlined />}
|
|
113
|
+
</Link>
|
|
114
|
+
</Tooltip>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
},
|
|
120
|
+
[detailIdIndex, readProps],
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
const updateOperate = useCallback(
|
|
124
|
+
(record) => {
|
|
125
|
+
const hidden = updateProps?.operateIsHidden?.(record) || false;
|
|
126
|
+
if (!hidden) {
|
|
127
|
+
const disabled = updateProps?.operateIsDisabled?.(record) || false;
|
|
128
|
+
|
|
129
|
+
if (disabled) {
|
|
130
|
+
return (
|
|
131
|
+
<Tooltip title={updateProps?.operateText || '编辑'}>
|
|
132
|
+
<span key="update" className="cursor-not-allowed text-lg text-03">
|
|
133
|
+
{updateProps?.operateText || <EditOutlined />}
|
|
134
|
+
</span>
|
|
135
|
+
</Tooltip>
|
|
136
|
+
);
|
|
137
|
+
} else {
|
|
138
|
+
return (
|
|
139
|
+
<CRUDDetail
|
|
140
|
+
key="update"
|
|
141
|
+
id={record[idField]}
|
|
142
|
+
record={record}
|
|
143
|
+
onSuccess={handleReload}
|
|
144
|
+
trigger={
|
|
145
|
+
<Tooltip title={updateProps?.operateText || '编辑'}>
|
|
146
|
+
<a className="text-lg">{updateProps?.operateText || <EditOutlined />}</a>
|
|
147
|
+
</Tooltip>
|
|
148
|
+
}
|
|
149
|
+
action="update"
|
|
150
|
+
{...detailProps}
|
|
151
|
+
/>
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return null;
|
|
157
|
+
},
|
|
158
|
+
[detailProps, handleReload, idField, updateProps],
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
const deleteOperate = useCallback(
|
|
162
|
+
(record) => {
|
|
163
|
+
const hidden = deleteProps?.operateIsHidden?.(record) || false;
|
|
164
|
+
if (!hidden) {
|
|
165
|
+
const disabled = deleteProps?.operateIsDisabled?.(record) || false;
|
|
166
|
+
return (
|
|
167
|
+
<OperateDelete
|
|
168
|
+
key="delete"
|
|
169
|
+
name={record[deleteProps.nameIndex]}
|
|
170
|
+
desc={deleteProps.desc}
|
|
171
|
+
operateText={deleteProps.operateText}
|
|
172
|
+
disabled={disabled}
|
|
173
|
+
onDelete={getHandleDelete(record)}
|
|
174
|
+
/>
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
return null;
|
|
178
|
+
},
|
|
179
|
+
[deleteProps, getHandleDelete],
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
const newColumns = useMemo(() => {
|
|
183
|
+
const operateColumn = {
|
|
184
|
+
title: '操作',
|
|
185
|
+
fixed: 'right',
|
|
186
|
+
align: 'center',
|
|
187
|
+
width: operateColumnProps?.width || 120,
|
|
188
|
+
render: function (_, record) {
|
|
189
|
+
const btns: React.ReactNode[] = [];
|
|
190
|
+
|
|
191
|
+
if (actions.includes('read')) {
|
|
192
|
+
btns.push(readOperate(record));
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (actions.includes('read_detail')) {
|
|
196
|
+
btns.push(readDetailOperate(record));
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (actions.includes('update')) {
|
|
200
|
+
btns.push(updateOperate(record));
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (actions.includes('delete') && deleteProps) {
|
|
204
|
+
btns.push(deleteOperate(record));
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return (
|
|
208
|
+
<div className="fec-crud-operate-column flex justify-center gap-4">
|
|
209
|
+
{operateColumnProps?.moreOperator && operateColumnProps.moreOperator(record)}
|
|
210
|
+
{btns}
|
|
211
|
+
{operateColumnProps?.moreOperatorAfter && operateColumnProps.moreOperatorAfter(record)}
|
|
212
|
+
</div>
|
|
213
|
+
);
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
if (
|
|
218
|
+
actions.includes('read') ||
|
|
219
|
+
actions.includes('read_detail') ||
|
|
220
|
+
actions.includes('update') ||
|
|
221
|
+
actions.includes('delete') ||
|
|
222
|
+
operateColumnProps?.moreOperator ||
|
|
223
|
+
operateColumnProps?.moreOperatorAfter
|
|
224
|
+
) {
|
|
225
|
+
return [
|
|
226
|
+
...(tableProps.columns || tableProps.columns || []),
|
|
227
|
+
operateColumn,
|
|
228
|
+
] as TableProps['columns'];
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return tableProps.columns as TableProps['columns'];
|
|
232
|
+
}, [
|
|
233
|
+
operateColumnProps,
|
|
234
|
+
actions,
|
|
235
|
+
tableProps.columns,
|
|
236
|
+
deleteProps,
|
|
237
|
+
readOperate,
|
|
238
|
+
readDetailOperate,
|
|
239
|
+
updateOperate,
|
|
240
|
+
deleteOperate,
|
|
241
|
+
]);
|
|
242
|
+
|
|
243
|
+
return {
|
|
244
|
+
columns: newColumns,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export { useOperate };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ActionType } from '@ant-design/pro-components';
|
|
2
|
-
import {
|
|
2
|
+
import { App } from 'antd';
|
|
3
3
|
import type { MutableRefObject } from 'react';
|
|
4
4
|
import { useCallback, useMemo } from 'react';
|
|
5
5
|
import { LoadingButton } from '../button';
|
|
@@ -14,6 +14,8 @@ function useRowSelection<DataSource, Key>({
|
|
|
14
14
|
batchActions?: CRUDProps<DataSource, Key>['batchActions'];
|
|
15
15
|
actionRef?: MutableRefObject<ActionType | undefined>;
|
|
16
16
|
}) {
|
|
17
|
+
const { modal } = App.useApp();
|
|
18
|
+
|
|
17
19
|
const rowSelection = useMemo(
|
|
18
20
|
() => ({
|
|
19
21
|
...originRowSelection,
|
|
@@ -48,7 +50,7 @@ function useRowSelection<DataSource, Key>({
|
|
|
48
50
|
onClick={async (event) => {
|
|
49
51
|
if (action.danger) {
|
|
50
52
|
await new Promise((resolve) => {
|
|
51
|
-
|
|
53
|
+
modal.confirm({
|
|
52
54
|
title: `确定要执行 ${action.btnText} 吗?`,
|
|
53
55
|
onOk: () => {
|
|
54
56
|
resolve(
|
|
@@ -79,7 +81,7 @@ function useRowSelection<DataSource, Key>({
|
|
|
79
81
|
</div>
|
|
80
82
|
);
|
|
81
83
|
},
|
|
82
|
-
[actionRef, batchActions],
|
|
84
|
+
[actionRef, batchActions, modal],
|
|
83
85
|
);
|
|
84
86
|
|
|
85
87
|
if (!batchActions || batchActions.length === 0) {
|
package/src/global/error.ts
CHANGED
package/src/upload/index.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DeleteOutlined, InboxOutlined, PlusOutlined, UploadOutlined } from '@fe-free/icons';
|
|
2
2
|
import type { UploadProps as AntdUploadProps, UploadFile } from 'antd';
|
|
3
|
-
import { Upload as AntdUpload, Avatar, Button
|
|
3
|
+
import { Upload as AntdUpload, App, Avatar, Button } from 'antd';
|
|
4
4
|
import type { UploadChangeParam } from 'antd/es/upload';
|
|
5
5
|
import classNames from 'classnames';
|
|
6
6
|
import type { ReactNode } from 'react';
|
|
@@ -26,6 +26,7 @@ interface UploadProps extends UploadBaseProps {
|
|
|
26
26
|
function useUpload(
|
|
27
27
|
props: ImageUploadProps & { onChangeOriginal?: (info: UploadChangeParam<UploadFile>) => void },
|
|
28
28
|
) {
|
|
29
|
+
const { message } = App.useApp();
|
|
29
30
|
const { value, onChange, multiple, maxCount, onChangeOriginal } = props;
|
|
30
31
|
// 转换成 Upload 格式。
|
|
31
32
|
const defaultFileList = useMemo(() => {
|