refactor(front): update FileShareDrawer and FileUploadField components to handle multiple files and improve file type checks

This commit is contained in:
keven1024
2025-08-14 16:50:43 +08:00
parent 4d0a6f0a49
commit 3d173d0321
3 changed files with 217 additions and 179 deletions

View File

@@ -1,42 +1,71 @@
<script setup lang="ts">
import FileUpload from "@/components/FileUpload.vue";
import { cx } from "class-variance-authority";
import type { RuleExpression } from "vee-validate";
import FileUpload from '@/components/FileUpload.vue'
import { cx } from 'class-variance-authority'
import type { RuleExpression } from 'vee-validate'
import Button from '../ui/button/Button.vue'
import { PlusIcon } from 'lucide-vue-next'
import { isEmpty } from 'lodash-es'
const props = defineProps<{
name: string;
rules?: RuleExpression<File>;
}>();
const { value, setValue } = useField<File>(props?.name, props?.rules);
const { t } = useI18n();
name: string
rules?: RuleExpression<File[]>
}>()
const { value, setValue } = useField<File[]>(props?.name, props?.rules)
const { t } = useI18n()
</script>
<template>
<FileUpload
@onChange="
(file) => {
setValue(file);
}
"
v-slot="{ isOverDropZone }"
>
<div
:class="
cx(
'bg-white/50 rounded-md p-2 w-full h-40 flex flex-col items-center justify-center border border-dashed border-black/20 cursor-pointer text-gray-500 gap-3',
isOverDropZone && '!bg-green-100/50 ',
)
"
<FileUpload
@onChange="
(file) => {
// 这里没hash我们姑且认为name和size,type都一样的为同一个文件
setValue([...(value?.filter((r) => r?.name !== file?.name || r?.type !== file?.type || r?.size !== file?.size) || []), file])
}
"
v-slot="{ isOverDropZone }"
>
<template v-if="!!value">
<FilePreviewView :value="value" />
</template>
<template v-else>
<LucideUpload class="size-10" />
<div class="text-sm">
{{ t("file.uploadFilePlaceholder") }}
<div
:class="
cx(
'bg-white/50 rounded-md p-2 w-full min-h-40 flex flex-col items-center justify-center border border-dashed border-black/20 cursor-pointer text-gray-500 gap-3 transition-all duration-300',
isOverDropZone && '!bg-green-100/50 '
)
"
>
<template v-if="!isEmpty(value)">
<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-5 w-full">
<div v-for="item in value" :key="item?.name" class="flex flex-col items-center justify-center relative">
<div class="absolute top-0 right-0">
<Button
class="size-5 p-0 bg-red-500/20 hover:bg-red-500/60 text-red-500 hover:text-white"
@click="
(e) => {
e.stopPropagation()
setValue(
value?.filter((r) => r?.name !== item?.name || r?.type !== item?.type || r?.size !== item?.size) || []
)
}
"
>
<LucideX class="size-3" />
</Button>
</div>
<FilePreviewView :value="item" />
</div>
<div class="flex flex-col items-center justify-center opacity-50 gap-1">
<div class="size-16 flex justify-center items-center rounded-xl bg-white/80">
<PlusIcon class="size-7" />
</div>
<div class="mb-3">添加更多</div>
</div>
</div>
</template>
<template v-else>
<LucideUpload class="size-10" />
<div class="text-sm">
{{ t('file.uploadFilePlaceholder') }}
</div>
</template>
</div>
</template>
</div>
</FileUpload>
</FileUpload>
</template>