feat(components): 新增表单上传组件
This commit is contained in:
parent
da1c16e023
commit
03c8a7f5b7
@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, useAttrs, watch } from 'vue';
|
import { useAttrs } from 'vue';
|
||||||
import type { UploadFileInfo, UploadProps } from 'naive-ui';
|
import type { UploadFileInfo, UploadProps } from 'naive-ui';
|
||||||
import { fetchBatchDeleteOss } from '@/service/api/system/oss';
|
import { fetchBatchDeleteOss } from '@/service/api/system/oss';
|
||||||
import { getToken } from '@/store/modules/auth/shared';
|
import { getToken } from '@/store/modules/auth/shared';
|
||||||
@ -34,19 +34,9 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
const attrs: UploadProps = useAttrs();
|
const attrs: UploadProps = useAttrs();
|
||||||
|
|
||||||
let fileNum = 0;
|
let fileNum = 0;
|
||||||
const fileList = ref<UploadFileInfo[]>([]);
|
const fileList = defineModel<UploadFileInfo[]>('fileList', {
|
||||||
|
default: () => []
|
||||||
const needRelaodData = ref(false);
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
needRelaodData
|
|
||||||
});
|
});
|
||||||
watch(
|
|
||||||
() => fileList.value,
|
|
||||||
newValue => {
|
|
||||||
needRelaodData.value = newValue.length > 0;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const isHttpProxy = import.meta.env.DEV && import.meta.env.VITE_HTTP_PROXY === 'Y';
|
const isHttpProxy = import.meta.env.DEV && import.meta.env.VITE_HTTP_PROXY === 'Y';
|
||||||
const { baseURL } = getServiceBaseURL(import.meta.env, isHttpProxy);
|
const { baseURL } = getServiceBaseURL(import.meta.env, isHttpProxy);
|
||||||
@ -119,11 +109,12 @@ function handleError(options: { file: UploadFileInfo; event?: ProgressEvent }) {
|
|||||||
|
|
||||||
async function handleRemove(file: UploadFileInfo) {
|
async function handleRemove(file: UploadFileInfo) {
|
||||||
if (file.status !== 'finished') {
|
if (file.status !== 'finished') {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
const { error } = await fetchBatchDeleteOss([file.id]);
|
const { error } = await fetchBatchDeleteOss([file.id]);
|
||||||
if (error) return;
|
if (error) return false;
|
||||||
window.$message?.success('删除成功');
|
window.$message?.success('删除成功');
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
46
src/components/custom/oss-upload.vue
Normal file
46
src/components/custom/oss-upload.vue
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { onMounted, ref, useAttrs, watch } from 'vue';
|
||||||
|
import type { UploadFileInfo } from 'naive-ui';
|
||||||
|
import { fetchGetOssListByIds } from '@/service/api/system/oss';
|
||||||
|
import { isNotNull } from '@/utils/common';
|
||||||
|
import FileUpload from '@/components/custom/file-upload.vue';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'OssUpload'
|
||||||
|
});
|
||||||
|
|
||||||
|
const attrs = useAttrs();
|
||||||
|
|
||||||
|
const value = defineModel<string>('value', { default: '' });
|
||||||
|
|
||||||
|
const fileList = ref<UploadFileInfo[]>([]);
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
fileList.value = [];
|
||||||
|
const ossIds = value.value.split(',')?.filter(item => isNotNull(item));
|
||||||
|
if (ossIds.length > 0) {
|
||||||
|
const { error, data } = await fetchGetOssListByIds(ossIds);
|
||||||
|
if (error) return;
|
||||||
|
fileList.value = data.map(item => ({
|
||||||
|
id: String(item.ossId),
|
||||||
|
url: item.url,
|
||||||
|
name: item.originalName,
|
||||||
|
status: 'finished'
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
fileList,
|
||||||
|
val => {
|
||||||
|
value.value = val.map(item => item.id).join(',');
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<FileUpload v-bind="attrs" v-model:file-list="fileList" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
@ -1,4 +1,3 @@
|
|||||||
import type { AxiosRequestConfig, GenericAbortSignal } from 'axios';
|
|
||||||
import { request } from '@/service/request';
|
import { request } from '@/service/request';
|
||||||
|
|
||||||
/** 获取文件管理列表 */
|
/** 获取文件管理列表 */
|
||||||
@ -18,36 +17,10 @@ export function fetchBatchDeleteOss(ossIds: CommonType.IdType[]) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Axios上传进度事件 */
|
// 查询OSS对象基于id串
|
||||||
export type AxiosProgressEvent = AxiosRequestConfig['onUploadProgress'];
|
export function fetchGetOssListByIds(ossIds: CommonType.IdType[]) {
|
||||||
|
return request<Api.System.Oss[]>({
|
||||||
/** 默认上传结果 */
|
url: `/resource/oss/listByIds/${ossIds.join(',')}`,
|
||||||
export interface UploadResult {
|
method: 'get'
|
||||||
url: string;
|
|
||||||
fileName: string;
|
|
||||||
ossId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UploadApiOptions {
|
|
||||||
onUploadProgress?: AxiosProgressEvent;
|
|
||||||
signal?: GenericAbortSignal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 上传文件接口 */
|
|
||||||
export function uploadApi(file: File | Blob, options?: UploadApiOptions) {
|
|
||||||
const { onUploadProgress, signal } = options ?? {};
|
|
||||||
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append('file', file);
|
|
||||||
|
|
||||||
return request<UploadResult>({
|
|
||||||
url: '/resource/oss/upload',
|
|
||||||
method: 'post',
|
|
||||||
data: formData,
|
|
||||||
onUploadProgress,
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'multipart/form-data'
|
|
||||||
},
|
|
||||||
signal
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
1
src/typings/components.d.ts
vendored
1
src/typings/components.d.ts
vendored
@ -129,6 +129,7 @@ declare module 'vue' {
|
|||||||
NUpload: typeof import('naive-ui')['NUpload']
|
NUpload: typeof import('naive-ui')['NUpload']
|
||||||
NUploadDragger: typeof import('naive-ui')['NUploadDragger']
|
NUploadDragger: typeof import('naive-ui')['NUploadDragger']
|
||||||
NWatermark: typeof import('naive-ui')['NWatermark']
|
NWatermark: typeof import('naive-ui')['NWatermark']
|
||||||
|
OssUpload: typeof import('./../components/custom/oss-upload.vue')['default']
|
||||||
PinToggler: typeof import('./../components/common/pin-toggler.vue')['default']
|
PinToggler: typeof import('./../components/common/pin-toggler.vue')['default']
|
||||||
PostSelect: typeof import('./../components/custom/post-select.vue')['default']
|
PostSelect: typeof import('./../components/custom/post-select.vue')['default']
|
||||||
ReloadButton: typeof import('./../components/common/reload-button.vue')['default']
|
ReloadButton: typeof import('./../components/common/reload-button.vue')['default']
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref, watch } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
|
import type { UploadFileInfo } from 'naive-ui';
|
||||||
import FileUpload from '@/components/custom/file-upload.vue';
|
import FileUpload from '@/components/custom/file-upload.vue';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'OssUploadModal'
|
name: 'OssUploadModal'
|
||||||
});
|
});
|
||||||
const fileUploadRef = ref<InstanceType<typeof FileUpload> | null>(null);
|
|
||||||
interface Props {
|
interface Props {
|
||||||
uploadType: 'file' | 'image';
|
uploadType: 'file' | 'image';
|
||||||
}
|
}
|
||||||
@ -26,6 +27,8 @@ const accept = computed(() => {
|
|||||||
return props.uploadType === 'file' ? '.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.pdf' : '.jpg,.jpeg,.png,.gif,.bmp,.webp';
|
return props.uploadType === 'file' ? '.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.pdf' : '.jpg,.jpeg,.png,.gif,.bmp,.webp';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const fileList = ref<UploadFileInfo[]>([]);
|
||||||
|
|
||||||
function handleUpdateModelWhenUpload() {}
|
function handleUpdateModelWhenUpload() {}
|
||||||
|
|
||||||
function closeDrawer() {
|
function closeDrawer() {
|
||||||
@ -34,7 +37,7 @@ function closeDrawer() {
|
|||||||
|
|
||||||
function handleClose() {
|
function handleClose() {
|
||||||
closeDrawer();
|
closeDrawer();
|
||||||
if (fileUploadRef.value?.needRelaodData) {
|
if (fileList.value?.length > 0) {
|
||||||
emit('close');
|
emit('close');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,7 +59,7 @@ watch(visible, () => {
|
|||||||
:bordered="false"
|
:bordered="false"
|
||||||
@after-leave="handleClose"
|
@after-leave="handleClose"
|
||||||
>
|
>
|
||||||
<FileUpload ref="fileUploadRef" :upload-type="uploadType" :accept="accept" />
|
<FileUpload v-model:file-list="fileList" :upload-type="uploadType" :accept="accept" />
|
||||||
</NModal>
|
</NModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user