@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 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.36",
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/icons": "3.0.36",
50
- "@fe-free/tool": "3.0.36"
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 { EditOutlined, EyeOutlined } from '@fe-free/icons';
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 newColumns = useMemo(() => {
106
- const idField = tableProps.rowKey || 'id';
107
-
108
- const operateColumn = {
109
- title: '操作',
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
- return tableProps.columns as TableProps['columns'];
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(tableProps.columns),
131
+ ...getTableScroll(newColumns),
316
132
  y: '100%',
317
133
  },
318
134
  };
319
135
  }
320
136
 
321
137
  return tableProps;
322
- }, [tableProps, fullPage]);
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}
@@ -1,5 +1,5 @@
1
1
  import { DeleteOutlined } from '@fe-free/icons';
2
- import { Modal, Tooltip } from 'antd';
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
- Modal.confirm({
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,
@@ -1,5 +1,5 @@
1
1
  import { DrawerForm, ProForm } from '@ant-design/pro-components';
2
- import { message, Spin } from 'antd';
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) => {
@@ -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: data.length,
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 { Modal } from 'antd';
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
- Modal.confirm({
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) {
@@ -1,3 +1,4 @@
1
+ // eslint-disable-next-line no-restricted-imports
1
2
  import { message } from 'antd';
2
3
  import type { AxiosRequestConfig, AxiosResponse } from 'axios';
3
4
  import { AxiosError } from 'axios';
@@ -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, message } from 'antd';
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(() => {