Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into v-next-dev
This commit is contained in:
@@ -212,7 +212,12 @@ setupVbenVxeTable({
|
||||
Popconfirm,
|
||||
{
|
||||
getPopupContainer(el) {
|
||||
return el.closest('tbody') || document.body;
|
||||
return (
|
||||
el
|
||||
.closest('.vxe-table--viewport-wrapper')
|
||||
?.querySelector('.vxe-table--main-wrapper')
|
||||
?.querySelector('tbody') || document.body
|
||||
);
|
||||
},
|
||||
placement: 'topLeft',
|
||||
title: $t('ui.actionTitle.delete', [attrs?.nameTitle || '']),
|
||||
|
||||
25
playground/src/api/examples/upload.ts
Normal file
25
playground/src/api/examples/upload.ts
Normal file
@@ -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)));
|
||||
}
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
@@ -21,7 +21,11 @@
|
||||
"dynamic": "动态表单",
|
||||
"custom": "自定义组件",
|
||||
"api": "Api",
|
||||
"merge": "合并表单"
|
||||
"merge": "合并表单",
|
||||
"upload-error": "部分文件上传失败",
|
||||
"upload-urls": "文件上传后的网址",
|
||||
"file": "文件",
|
||||
"upload-image": "点击上传图片"
|
||||
},
|
||||
"vxeTable": {
|
||||
"title": "Vxe 表格",
|
||||
|
||||
@@ -30,5 +30,6 @@ function lockDrawer() {
|
||||
<Button type="primary" @click="lockDrawer">锁定抽屉状态</Button>
|
||||
<!-- <template #prepend-footer> slot </template> -->
|
||||
<!-- <template #append-footer> prepend slot </template> -->
|
||||
<!-- <template #center-footer> center slot </template> -->
|
||||
</Drawer>
|
||||
</template>
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -42,6 +46,9 @@ const [BaseForm, baseFormApi] = useVbenForm({
|
||||
fieldMappingTime: [['rangePicker', ['startTime', 'endTime'], 'YYYY-MM-DD']],
|
||||
// 提交函数
|
||||
handleSubmit: onSubmit,
|
||||
handleValuesChange(_values, fieldsChanged) {
|
||||
message.info(`表单以下字段发生变化:${fieldsChanged.join(',')}`);
|
||||
},
|
||||
|
||||
// 垂直布局,label和input在不同行,值为vertical
|
||||
// 水平布局,label和input在同一行
|
||||
@@ -326,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)}`,
|
||||
});
|
||||
@@ -344,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/static-source@0.1.7/source/logo-v1.webp',
|
||||
},
|
||||
],
|
||||
mentions: '@afc163',
|
||||
number: 3,
|
||||
options: '1',
|
||||
|
||||
@@ -37,7 +37,7 @@ const [Modal, modalApi] = useVbenModal({
|
||||
const { valid } = await formApi.validate();
|
||||
if (valid) {
|
||||
modalApi.lock();
|
||||
const data = formApi.getValues();
|
||||
const data = await formApi.getValues();
|
||||
try {
|
||||
await (formData.value?.id
|
||||
? updateDept(formData.value.id, data)
|
||||
|
||||
@@ -11,7 +11,7 @@ export function getMenuTypeOptions() {
|
||||
value: 'catalog',
|
||||
},
|
||||
{ color: 'default', label: $t('system.menu.typeMenu'), value: 'menu' },
|
||||
{ color: 'error', label: $t('system.menu.typeButton'), value: 'button' },
|
||||
{ color: 'error', label: $t('system.menu.typeButton'), value: 'action' },
|
||||
{
|
||||
color: 'success',
|
||||
label: $t('system.menu.typeEmbedded'),
|
||||
|
||||
@@ -241,10 +241,10 @@ const schema: VbenFormSchema[] = [
|
||||
component: 'Input',
|
||||
dependencies: {
|
||||
rules: (values) => {
|
||||
return values.type === 'button' ? 'required' : null;
|
||||
return values.type === 'action' ? 'required' : null;
|
||||
},
|
||||
show: (values) => {
|
||||
return ['button', 'catalog', 'embedded', 'menu'].includes(values.type);
|
||||
return ['action', 'catalog', 'embedded', 'menu'].includes(values.type);
|
||||
},
|
||||
triggerFields: ['type'],
|
||||
},
|
||||
@@ -277,7 +277,7 @@ const schema: VbenFormSchema[] = [
|
||||
},
|
||||
dependencies: {
|
||||
show: (values) => {
|
||||
return values.type !== 'button';
|
||||
return values.type !== 'action';
|
||||
},
|
||||
triggerFields: ['type'],
|
||||
},
|
||||
@@ -295,7 +295,7 @@ const schema: VbenFormSchema[] = [
|
||||
},
|
||||
dependencies: {
|
||||
show: (values) => {
|
||||
return values.type !== 'button';
|
||||
return values.type !== 'action';
|
||||
},
|
||||
triggerFields: ['type'],
|
||||
},
|
||||
@@ -314,7 +314,7 @@ const schema: VbenFormSchema[] = [
|
||||
},
|
||||
dependencies: {
|
||||
show: (values) => {
|
||||
return values.type !== 'button';
|
||||
return values.type !== 'action';
|
||||
},
|
||||
triggerFields: ['type'],
|
||||
},
|
||||
@@ -325,7 +325,7 @@ const schema: VbenFormSchema[] = [
|
||||
component: 'Divider',
|
||||
dependencies: {
|
||||
show: (values) => {
|
||||
return !['button', 'link'].includes(values.type);
|
||||
return !['action', 'link'].includes(values.type);
|
||||
},
|
||||
triggerFields: ['type'],
|
||||
},
|
||||
@@ -372,7 +372,7 @@ const schema: VbenFormSchema[] = [
|
||||
component: 'Checkbox',
|
||||
dependencies: {
|
||||
show: (values) => {
|
||||
return !['button'].includes(values.type);
|
||||
return !['action'].includes(values.type);
|
||||
},
|
||||
triggerFields: ['type'],
|
||||
},
|
||||
@@ -402,7 +402,7 @@ const schema: VbenFormSchema[] = [
|
||||
component: 'Checkbox',
|
||||
dependencies: {
|
||||
show: (values) => {
|
||||
return !['button', 'link'].includes(values.type);
|
||||
return !['action', 'link'].includes(values.type);
|
||||
},
|
||||
triggerFields: ['type'],
|
||||
},
|
||||
@@ -417,7 +417,7 @@ const schema: VbenFormSchema[] = [
|
||||
component: 'Checkbox',
|
||||
dependencies: {
|
||||
show: (values) => {
|
||||
return !['button', 'link'].includes(values.type);
|
||||
return !['action', 'link'].includes(values.type);
|
||||
},
|
||||
triggerFields: ['type'],
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user