Skip to content

feat: add examples: form-upload #5955

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions apps/backend-mock/api/upload.ts
Original file line number Diff line number Diff line change
@@ -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/[email protected]/source/logo-v1.webp',
});
// return useResponseError("test")
});
1 change: 1 addition & 0 deletions apps/backend-mock/routes/[...].ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export default defineEventHandler(() => {
<li><a href="/api/menu">/api/menu/all</a></li>
<li><a href="/api/auth/codes">/api/auth/codes</a></li>
<li><a href="/api/auth/login">/api/auth/login</a></li>
<li><a href="/api/upload">/api/upload</a></li>
</ul>
`;
});
25 changes: 25 additions & 0 deletions playground/src/api/examples/upload.ts
Original file line number Diff line number Diff line change
@@ -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)));
}
}
6 changes: 5 additions & 1 deletion playground/src/locales/langs/en-US/examples.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
6 changes: 5 additions & 1 deletion playground/src/locales/langs/zh-CN/examples.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@
"dynamic": "动态表单",
"custom": "自定义组件",
"api": "Api",
"merge": "合并表单"
"merge": "合并表单",
"upload-error": "部分文件上传失败",
"upload-urls": "文件上传后的网址",
"file": "文件",
"upload-image": "点击上传图片"
},
"vxeTable": {
"title": "Vxe 表格",
Expand Down
58 changes: 57 additions & 1 deletion playground/src/views/examples/form/basic.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<script lang="ts" setup>
import { h, ref } from 'vue';
import type { UploadFile } from 'ant-design-vue';

import { h, ref, toRaw } from 'vue';

import { Page } from '@vben/common-ui';

Expand All @@ -9,6 +11,8 @@ import dayjs from 'dayjs';

import { useVbenForm, z } from '#/adapter/form';
import { getAllMenusApi } from '#/api';
import { upload_file } from '#/api/examples/upload';
import { $t } from '#/locales';

import DocButton from '../doc-button.vue';

Expand Down Expand Up @@ -329,12 +333,56 @@ const [BaseForm, baseFormApi] = useVbenForm({
fieldName: 'treeSelect',
label: '树选择',
},
{
component: 'Upload',
componentProps: {
// 更多属性见:https://ant.design/components/upload-cn
accept: '.png,.jpg,.jpeg',
// 自动携带认证信息
customRequest: upload_file,
disabled: false,
maxCount: 1,
multiple: false,
showUploadList: true,
// 上传列表的内建样式,支持四种基本样式 text, picture, picture-card 和 picture-circle
listType: 'picture-card',
},
fieldName: 'files',
label: $t('examples.form.file'),
renderComponentContent: () => {
return {
default: () => $t('examples.form.upload-image'),
};
},
rules: 'required',
},
],
// 大屏一行显示3个,中屏一行显示2个,小屏一行显示1个
wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3',
});

function onSubmit(values: Record<string, any>) {
const files = toRaw(values.files) as UploadFile[];
const doneFiles = files.filter((file) => file.status === 'done');
const failedFiles = files.filter((file) => file.status !== 'done');

const msg = [
...doneFiles.map((file) => file.response?.url || file.url),
...failedFiles.map((file) => file.name),
].join(', ');

if (failedFiles.length === 0) {
message.success({
content: `${$t('examples.form.upload-urls')}: ${msg}`,
});
} else {
message.error({
content: `${$t('examples.form.upload-error')}: ${msg}`,
});
return;
}
// 如果需要可提交前替换为需要的urls
values.files = doneFiles.map((file) => file.response?.url || file.url);
message.success({
content: `form values: ${JSON.stringify(values)}`,
});
Expand All @@ -347,6 +395,14 @@ function handleSetFormValue() {
baseFormApi.setValues({
checkboxGroup: ['1'],
datePicker: dayjs('2022-01-01'),
files: [
{
name: 'example.png',
status: 'done',
uid: '-1',
url: 'https://unpkg.com/@vbenjs/[email protected]/source/logo-v1.webp',
},
],
mentions: '@afc163',
number: 3,
options: '1',
Expand Down