Browse Source

feat: upload afterUpload support return url (#2346)

pointhalo 1 year ago
parent
commit
f7cce1f0f3

+ 7 - 4
content/input/upload/index-en-US.md

@@ -1181,10 +1181,13 @@ afterUpload is triggered when the upload is completed (xhr.onload) and no error
 ```ts
 ```ts
 // afterUploadResult:
 // afterUploadResult:
 {
 {
-     status?:'success' |'uploadFail' |'validateFail' |'validating' |'uploading' |'wait',
-     validateMessage?: React.ReactNode | string, // file validation information
-     autoRemove: boolean, // Whether to remove the file from the fileList, the default is false
-     name: string,
+    status?:'success' |'uploadFail' |'validateFail' |'validating' |'uploading' |'wait',
+    validateMessage?: React.ReactNode | string, // file validation information
+    autoRemove?: boolean, // Whether to remove the file from the fileList, the default is false
+    name?: string;
+    // The URL for previewing image file, usually the storage address returned by the Server after receiving response, supported since v2.63.
+    // Previous versions can also manually update the controlled properties in the fileList through onChange callback.
+    url?: string; // support after v2.63
 }
 }
 ```
 ```
 
 

+ 26 - 26
content/input/upload/index.md

@@ -630,7 +630,8 @@ import { IconUpload } from '@douyinfe/semi-icons';
 
 
 ### 图片墙
 ### 图片墙
 
 
-设置 `listType = 'picture'`,用户可以上传图片并在列表中显示缩略图
+设置 `listType = 'picture'`,用户可以上传图片并在列表中显示缩略图  
+如果通过 defaultFileList 或 fileList 设置已上传的文件列表时,会自动读取对象数组中的 url 属性用于展示图片
 
 
 ```jsx live=true width=48%
 ```jsx live=true width=48%
 import React from 'react';
 import React from 'react';
@@ -784,6 +785,7 @@ import { IconPlus, IconEyeOpened } from '@douyinfe/semi-icons';
 
 
 ### 图片墙设置宽高
 ### 图片墙设置宽高
 通过设置 picHeight, picWidth ( v2.42 后提供),可以统一设置图片墙元素的宽高
 通过设置 picHeight, picWidth ( v2.42 后提供),可以统一设置图片墙元素的宽高
+如果同时使用 `renderThumbnail` return Image 组件来实现点击放大预览,你需要同时指定 Image 组件的 width 和 height
 
 
 ```jsx live=true dir="column"
 ```jsx live=true dir="column"
 import React from 'react';
 import React from 'react';
@@ -813,6 +815,7 @@ import { IconPlus } from '@douyinfe/semi-icons';
                 defaultFileList={defaultFileList}
                 defaultFileList={defaultFileList}
                 picHeight={110}
                 picHeight={110}
                 picWidth={200}
                 picWidth={200}
+                renderThumbnail={(file) => (<Image src={file.url} width={200} height={110} />)}
             >
             >
                 <IconPlus size="extra-large" style={{ margin: 4 }} />
                 <IconPlus size="extra-large" style={{ margin: 4 }} />
                 点击添加图片
                 点击添加图片
@@ -822,8 +825,6 @@ import { IconPlus } from '@douyinfe/semi-icons';
 };
 };
 ```
 ```
 
 
-
-
 设置 `hotSpotLocation` 自定义点击热区的顺序,默认在照片墙列表结尾
 设置 `hotSpotLocation` 自定义点击热区的顺序,默认在照片墙列表结尾
 
 
 ```jsx live=true width=48%
 ```jsx live=true width=48%
@@ -1186,15 +1187,21 @@ class AsyncBeforeUploadDemo extends React.Component {
 
 
 可以通过 `afterUpload` 钩子,对文件状态,校验信息,文件名进行更新。  
 可以通过 `afterUpload` 钩子,对文件状态,校验信息,文件名进行更新。  
 `({ response: any, file: FileItem, fileList: Array<FileItem> }) => afterUploadResult`  
 `({ response: any, file: FileItem, fileList: Array<FileItem> }) => afterUploadResult`  
-afterUpload 在上传完成后(xhr.onload)且没有发生错误的情况下触发,需返回一个 Object 对象(不支持异步返回),具体结构如下
+`afterUpload` 在上传完成后(`xhr.onload`)且没有发生错误的情况下触发,需返回一个 Object 对象(不支持异步返回),具体结构如下
 
 
 ```ts
 ```ts
 // afterUploadResult:
 // afterUploadResult:
 {
 {
-    status?: 'success' | 'uploadFail' | 'validateFail' | 'validating' | 'uploading' | 'wait',
-    validateMessage?: React.ReactNode | string, // 文件的校验信息
-    autoRemove: boolean, // 是否从fileList中移除该文件,默认为false
-    name: string,
+    status?: 'success' | 'uploadFail' | 'validateFail' | 'validating' | 'uploading' | 'wait';
+    // 文件的校验信息
+    validateMessage?: React.ReactNode | string;
+    // 是否从fileList中移除该文件,默认为false
+    autoRemove?: boolean;
+    // 文件的名称
+    name?: string;
+    // 预览文件的url,一般为当次上传请求中 Server 接收到文件后返回的存储地址,v2.63后支持传入。
+    // 之前的版本也可以通过 onChange 中结合 status 手动更新受控 fileList 中的属性实现
+    url?: string 
 }
 }
 ```
 ```
 
 
@@ -1203,14 +1210,8 @@ import React from 'react';
 import { Upload, Button } from '@douyinfe/semi-ui';
 import { Upload, Button } from '@douyinfe/semi-ui';
 import { IconUpload } from '@douyinfe/semi-icons';
 import { IconUpload } from '@douyinfe/semi-icons';
 
 
-class ValidateDemo extends React.Component {
-    constructor(props) {
-        super(props);
-        this.state = {};
-        this.count = 0;
-    }
-
-    afterUpload({ response, file }) {
+() => {
+    const afterUpload = ({ response, file }) => {
         // 可以根据业务接口返回,决定当次上传是否成功
         // 可以根据业务接口返回,决定当次上传是否成功
         if (response.status_code === 200) {
         if (response.status_code === 200) {
             return {
             return {
@@ -1218,21 +1219,20 @@ class ValidateDemo extends React.Component {
                 status: 'uploadFail',
                 status: 'uploadFail',
                 validateMessage: '内容不合法',
                 validateMessage: '内容不合法',
                 name: 'RenameByServer.jpg',
                 name: 'RenameByServer.jpg',
+                url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/edit-bag.jpeg'
             };
             };
         } else {
         } else {
             return {};
             return {};
         }
         }
-    }
+    };
 
 
-    render() {
-        return (
-            <Upload action="https://api.semi.design/upload" afterUpload={this.afterUpload}>
-                <Button icon={<IconUpload />} theme="light">
-                    点击上传
-                </Button>
-            </Upload>
-        );
-    }
+    return (
+        <Upload action="https://api.semi.design/upload" afterUpload={afterUpload}>
+            <Button icon={<IconUpload />} theme="light">
+                点击上传
+            </Button>
+        </Upload>
+    )
 }
 }
 ```
 ```
 
 

+ 4 - 2
packages/semi-foundation/upload/foundation.ts

@@ -60,7 +60,8 @@ export interface AfterUploadResult {
     autoRemove?: boolean;
     autoRemove?: boolean;
     status?: string;
     status?: string;
     validateMessage?: unknown;
     validateMessage?: unknown;
-    name?: string
+    name?: string;
+    url?: string
 }
 }
 
 
 export interface UploadAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
 export interface UploadAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
@@ -646,7 +647,7 @@ class UploadFoundation<P = Record<string, any>, S = Record<string, any>> extends
         e ? (newFileList[index].event = e) : null;
         e ? (newFileList[index].event = e) : null;
 
 
         if (afterUpload && typeof afterUpload === 'function') {
         if (afterUpload && typeof afterUpload === 'function') {
-            const { autoRemove, status, validateMessage, name } =
+            const { autoRemove, status, validateMessage, name, url } =
                 this._adapter.notifyAfterUpload({
                 this._adapter.notifyAfterUpload({
                     response: body,
                     response: body,
                     file: newFileList[index],
                     file: newFileList[index],
@@ -655,6 +656,7 @@ class UploadFoundation<P = Record<string, any>, S = Record<string, any>> extends
             status ? (newFileList[index].status = status) : null;
             status ? (newFileList[index].status = status) : null;
             validateMessage ? (newFileList[index].validateMessage = validateMessage) : null;
             validateMessage ? (newFileList[index].validateMessage = validateMessage) : null;
             name ? (newFileList[index].name = name) : null;
             name ? (newFileList[index].name = name) : null;
+            url ? (newFileList[index].url = url) : null;
             autoRemove ? newFileList.splice(index, 1) : null;
             autoRemove ? newFileList.splice(index, 1) : null;
         }
         }
         this._adapter.notifySuccess(body, fileInstance, newFileList);
         this._adapter.notifySuccess(body, fileInstance, newFileList);