80 lines
2.0 KiB
Vue
80 lines
2.0 KiB
Vue
<script setup lang="ts">
|
|
import { useMessage } from 'naive-ui'
|
|
import { computed, ref, watch } from 'vue'
|
|
|
|
import { selectFilesCom } from '@/components/file/upload-files.js'
|
|
import type { UploadFileDto } from '@/types/user.js'
|
|
|
|
const MESSAGE = useMessage()
|
|
|
|
const { max, extensions, loadFiles } = defineProps<{
|
|
max: number
|
|
extensions: string[]
|
|
loadFiles: () => Promise<UploadFileDto[]>
|
|
}>()
|
|
|
|
const showModal = defineModel('showModal', { required: true })
|
|
|
|
const files = ref<UploadFileDto[]>([])
|
|
const tempFiles = ref<UploadFileDto[]>([])
|
|
const selectFiles = defineModel<UploadFileDto[]>('selectFiles', { required: true })
|
|
|
|
function selectFile(file: UploadFileDto) {
|
|
if (tempFiles.value.length < max) {
|
|
tempFiles.value.push(file)
|
|
return true
|
|
} else {
|
|
MESSAGE.warning('可选择文件数量达到上限……')
|
|
return false
|
|
}
|
|
}
|
|
|
|
function removeFile(file: UploadFileDto) {
|
|
const i = tempFiles.value.findIndex((item) => item.id === file.id)
|
|
if (i >= 0) {
|
|
tempFiles.value.splice(i, 1)
|
|
}
|
|
return true
|
|
}
|
|
|
|
watch(showModal, async () => {
|
|
tempFiles.value = [] // 每次打开模态框时都重置已选文件
|
|
files.value = await loadFiles()
|
|
})
|
|
|
|
const tip_1 = computed(() => (max > 1 ? `请选择至少 ${max} 个文件。` : '请选择一个文件。'))
|
|
const tip_2 = computed(() => `允许的文件类型:${extensions.join('、')}。`)
|
|
</script>
|
|
|
|
<template>
|
|
<n-modal
|
|
preset="card"
|
|
style="max-width: 600px; max-height: 600px"
|
|
title="选择文件"
|
|
content-scrollable
|
|
v-model:show="showModal"
|
|
>
|
|
<n-flex vertical>
|
|
<n-alert type="info">
|
|
{{ tip_1 }}
|
|
{{ tip_2 }}
|
|
</n-alert>
|
|
<component :is="selectFilesCom(files, selectFile, removeFile)" />
|
|
<n-button
|
|
type="primary"
|
|
secondary
|
|
@click="
|
|
() => {
|
|
selectFiles = tempFiles
|
|
showModal = false
|
|
}
|
|
"
|
|
>
|
|
确认选择
|
|
</n-button>
|
|
</n-flex>
|
|
</n-modal>
|
|
</template>
|
|
|
|
<style scoped></style>
|