@fe-free/core 3.0.15 → 3.0.16

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,12 @@
1
1
  # @fe-free/core
2
2
 
3
+ ## 3.0.16
4
+
5
+ ### Patch Changes
6
+
7
+ - feat: upload
8
+ - @fe-free/tool@3.0.16
9
+
3
10
  ## 3.0.15
4
11
 
5
12
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fe-free/core",
3
- "version": "3.0.15",
3
+ "version": "3.0.16",
4
4
  "description": "",
5
5
  "main": "./src/index.ts",
6
6
  "author": "",
@@ -41,7 +41,7 @@
41
41
  "safe-stable-stringify": "^2.5.0",
42
42
  "vanilla-jsoneditor": "^0.23.1",
43
43
  "zustand": "^4.5.4",
44
- "@fe-free/tool": "3.0.15"
44
+ "@fe-free/tool": "3.0.16"
45
45
  },
46
46
  "peerDependencies": {
47
47
  "@ant-design/pro-components": "2.8.9",
@@ -210,7 +210,7 @@ function customRequest(option: any) {
210
210
  },
211
211
  });
212
212
  }
213
- }, 100);
213
+ }, 1000);
214
214
 
215
215
  // 返回 abort 方法,用于取消上传
216
216
  return {
@@ -239,6 +239,29 @@ export const ProFormUploadComponent: Story = {
239
239
  name="files_dragger"
240
240
  fieldProps={{ multiple: true, maxCount: 2, customRequest }}
241
241
  />
242
+ <ProFormUploadDragger
243
+ label="knowledge_files_dragger"
244
+ name="knowledge_files_dragger"
245
+ fieldProps={{
246
+ accept: '.doc,.docx,.pdf,.ppt,.jpg, jpeg,.png,.mp3,.mp4,.txt,.markdown,.excel',
247
+ multiple: true,
248
+ maxCount: 100,
249
+ customRequest,
250
+ showStatus: true,
251
+ description: (
252
+ <div>
253
+ <div className="text-01">
254
+ 支持doc、docx、pdf、ppt、jpg、png、mp3、mp4、txt、markdown、excel格式文件
255
+ </div>
256
+ <div className="text-03">
257
+ pdf
258
+ 文件不超过100MiB、图片文件不超过10MiB、音频文件不超过300MiB、视频文件不超过400MiB
259
+ 其他单文件不超过50MiB 单次最多上传 100 个文件
260
+ </div>
261
+ </div>
262
+ ),
263
+ }}
264
+ />
242
265
  <ProFormUpload
243
266
  label="files"
244
267
  name="files"
@@ -1,5 +1,7 @@
1
1
  // 避免循环引用
2
2
  import { ProForm, type ProFormItemProps } from '@ant-design/pro-components';
3
+ import { App } from 'antd';
4
+ import { useState } from 'react';
3
5
  import type {
4
6
  AvatarImageUploadProps,
5
7
  ImageUploadDraggerProps,
@@ -27,9 +29,38 @@ function ProFormUpload(props: ProFormItemProps<UploadProps>) {
27
29
 
28
30
  function ProFormUploadDragger(props: ProFormItemProps<UploadDraggerProps>) {
29
31
  const { fieldProps, ...rest } = props;
32
+ const { message } = App.useApp();
33
+
34
+ const [info, setInfo] = useState<any>(undefined);
35
+
36
+ const successList = info?.fileList
37
+ ?.map((item) => item.url || item.response?.data.url)
38
+ .filter(Boolean);
39
+
30
40
  return (
31
- <ProForm.Item {...rest}>
32
- <UploadDragger {...fieldProps} />
41
+ <ProForm.Item
42
+ {...rest}
43
+ validateTrigger={['onSubmit']}
44
+ rules={[
45
+ ...(props.rules || []),
46
+ {
47
+ validator: () => {
48
+ if (successList?.length !== info?.fileList?.length) {
49
+ message.error('存在未成功的文件,请处理!');
50
+ return Promise.reject('');
51
+ }
52
+ return Promise.resolve();
53
+ },
54
+ },
55
+ ]}
56
+ >
57
+ <UploadDragger
58
+ {...fieldProps}
59
+ onChangeOriginal={(info) => {
60
+ setInfo(info);
61
+ fieldProps?.onChangeOriginal?.(info);
62
+ }}
63
+ />
33
64
  </ProForm.Item>
34
65
  );
35
66
  }
@@ -1,9 +1,11 @@
1
- // 避免循环引用
2
1
  import { DeleteOutlined, InboxOutlined, PlusOutlined, UploadOutlined } from '@ant-design/icons';
3
2
  import type { UploadProps as AntdUploadProps, UploadFile } from 'antd';
4
3
  import { Upload as AntdUpload, Avatar, Button, message } from 'antd';
4
+ import type { UploadChangeParam } from 'antd/es/upload';
5
5
  import classNames from 'classnames';
6
+ import type { ReactNode } from 'react';
6
7
  import { useCallback, useMemo, useState } from 'react';
8
+ import './style.scss';
7
9
 
8
10
  interface UploadBaseProps {
9
11
  value?: string[] | string;
@@ -20,8 +22,10 @@ interface UploadProps extends UploadBaseProps {
20
22
  showCount?: boolean;
21
23
  }
22
24
 
23
- function useUpload(props: ImageUploadProps) {
24
- const { value, onChange, multiple, maxCount } = props;
25
+ function useUpload(
26
+ props: ImageUploadProps & { onChangeOriginal?: (info: UploadChangeParam<UploadFile>) => void },
27
+ ) {
28
+ const { value, onChange, multiple, maxCount, onChangeOriginal } = props;
25
29
  // 转换成 Upload 格式。
26
30
  const defaultFileList = useMemo(() => {
27
31
  if (!value) {
@@ -35,6 +39,9 @@ function useUpload(props: ImageUploadProps) {
35
39
  // 存起来,已选的文件。以便做一些判断。
36
40
  const [fileList, setFileList] = useState<UploadFile[]>(defaultFileList);
37
41
 
42
+ // 找到真正上传成功的。
43
+ const successList = fileList.map((item) => item.url || item.response?.data.url).filter(Boolean);
44
+
38
45
  const handleChange = useCallback(
39
46
  (info) => {
40
47
  setFileList(info.fileList);
@@ -45,8 +52,10 @@ function useUpload(props: ImageUploadProps) {
45
52
  .filter(Boolean);
46
53
 
47
54
  onChange?.(multiple ? newValue : newValue[0]);
55
+
56
+ onChangeOriginal?.(info);
48
57
  },
49
- [multiple, onChange],
58
+ [multiple, onChange, onChangeOriginal],
50
59
  );
51
60
 
52
61
  // 选文件还是可能多选,如果多选,则提示。
@@ -78,6 +87,7 @@ function useUpload(props: ImageUploadProps) {
78
87
  beforeUpload: handleBeforeUpload,
79
88
  isDisabled,
80
89
  fileList,
90
+ successList,
81
91
  };
82
92
  }
83
93
 
@@ -115,11 +125,43 @@ function Upload(props: ImageUploadProps) {
115
125
 
116
126
  interface UploadDraggerProps extends UploadBaseProps {
117
127
  title?: string;
118
- description?: string;
128
+ description?: string | ReactNode;
129
+ onChangeOriginal?: (info: UploadChangeParam<UploadFile>) => void;
130
+ showStatus?: boolean;
119
131
  }
120
132
  function UploadDragger(props: UploadDraggerProps) {
121
- const { multiple, maxCount, action, customRequest, listType, accept, title, description } = props;
122
- const { onChange, beforeUpload, isDisabled, fileList } = useUpload(props);
133
+ const {
134
+ multiple,
135
+ maxCount,
136
+ action,
137
+ customRequest,
138
+ listType,
139
+ accept,
140
+ title,
141
+ description,
142
+ showStatus,
143
+ } = props;
144
+ const { onChange, beforeUpload, isDisabled, fileList, successList } = useUpload(props);
145
+
146
+ const itemRender = useCallback(
147
+ (originNode, file, fileList) => {
148
+ const isFirst = fileList.findIndex((item) => item.uid === file.uid) === 0;
149
+
150
+ if (maxCount && maxCount > 1 && showStatus && isFirst) {
151
+ return (
152
+ <div>
153
+ <div className="py-1">
154
+ 文件数量 ({successList.length}/{fileList.length})
155
+ </div>
156
+ {originNode}
157
+ </div>
158
+ );
159
+ }
160
+
161
+ return originNode;
162
+ },
163
+ [maxCount, showStatus, successList.length],
164
+ );
123
165
 
124
166
  return (
125
167
  <AntdUpload.Dragger
@@ -134,6 +176,10 @@ function UploadDragger(props: UploadDraggerProps) {
134
176
  beforeUpload={beforeUpload}
135
177
  // 不可,否则会没法删除
136
178
  // disabled={isDisabled}
179
+ className={classNames('fec-upload-dragger', {
180
+ 'fec-upload-dragger-count-ten': fileList.length >= 10,
181
+ })}
182
+ itemRender={itemRender}
137
183
  >
138
184
  <div
139
185
  className={classNames({
@@ -0,0 +1,8 @@
1
+ .fec-upload-dragger {
2
+ &.fec-upload-dragger-count-ten {
3
+ .ant-upload-list.ant-upload-list-text {
4
+ max-height: calc(10 * 30px);
5
+ overflow: auto;
6
+ }
7
+ }
8
+ }