diff --git a/apps/backend-mock/api/upload.ts b/apps/backend-mock/api/upload.ts
new file mode 100644
index 00000000000..1bb9e602d6b
--- /dev/null
+++ b/apps/backend-mock/api/upload.ts
@@ -0,0 +1,13 @@
+import { verifyAccessToken } from '~/utils/jwt-utils';
+import { unAuthorizedResponse } from '~/utils/response';
+
+export default eventHandler((event) => {
+ const userinfo = verifyAccessToken(event);
+ if (!userinfo) {
+ return unAuthorizedResponse(event);
+ }
+ return useResponseSuccess({
+ url: 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp',
+ });
+ // return useResponseError("test")
+});
diff --git a/apps/backend-mock/routes/[...].ts b/apps/backend-mock/routes/[...].ts
index 70c5f7c745d..99f544b6616 100644
--- a/apps/backend-mock/routes/[...].ts
+++ b/apps/backend-mock/routes/[...].ts
@@ -7,6 +7,7 @@ export default defineEventHandler(() => {
/api/menu/all
/api/auth/codes
/api/auth/login
+/api/upload
`;
});
diff --git a/playground/src/api/examples/upload.ts b/playground/src/api/examples/upload.ts
new file mode 100644
index 00000000000..246d4f26700
--- /dev/null
+++ b/playground/src/api/examples/upload.ts
@@ -0,0 +1,25 @@
+import { requestClient } from '#/api/request';
+
+interface UploadFileParams {
+ file: File;
+ onError?: (error: Error) => void;
+ onProgress?: (progress: { percent: number }) => void;
+ onSuccess?: (data: any, file: File) => void;
+}
+export async function upload_file({
+ file,
+ onError,
+ onProgress,
+ onSuccess,
+}: UploadFileParams) {
+ try {
+ onProgress?.({ percent: 0 });
+
+ const data = await requestClient.upload('/upload', { file });
+
+ onProgress?.({ percent: 100 });
+ onSuccess?.(data, file);
+ } catch (error) {
+ onError?.(error instanceof Error ? error : new Error(String(error)));
+ }
+}
diff --git a/playground/src/locales/langs/en-US/examples.json b/playground/src/locales/langs/en-US/examples.json
index 1a25a983b1e..9335b28b783 100644
--- a/playground/src/locales/langs/en-US/examples.json
+++ b/playground/src/locales/langs/en-US/examples.json
@@ -18,7 +18,11 @@
"dynamic": "Dynamic Form",
"custom": "Custom Component",
"api": "Api",
- "merge": "Merge Form"
+ "merge": "Merge Form",
+ "upload-error": "Partial file upload failed",
+ "upload-urls": "Urls after file upload",
+ "file": "file",
+ "upload-image": "Click to upload image"
},
"vxeTable": {
"title": "Vxe Table",
diff --git a/playground/src/locales/langs/zh-CN/examples.json b/playground/src/locales/langs/zh-CN/examples.json
index 8f15d0202e1..ff11d7fd22a 100644
--- a/playground/src/locales/langs/zh-CN/examples.json
+++ b/playground/src/locales/langs/zh-CN/examples.json
@@ -21,7 +21,11 @@
"dynamic": "动态表单",
"custom": "自定义组件",
"api": "Api",
- "merge": "合并表单"
+ "merge": "合并表单",
+ "upload-error": "部分文件上传失败",
+ "upload-urls": "文件上传后的网址",
+ "file": "文件",
+ "upload-image": "点击上传图片"
},
"vxeTable": {
"title": "Vxe 表格",
diff --git a/playground/src/views/examples/form/basic.vue b/playground/src/views/examples/form/basic.vue
index b98ace26cb9..d0e91d33a6b 100644
--- a/playground/src/views/examples/form/basic.vue
+++ b/playground/src/views/examples/form/basic.vue
@@ -1,5 +1,7 @@