第二阶段代码
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, onMounted } from 'vue'
|
||||
import { ElDialog, ElUpload, ElButton, ElMessage } from 'element-plus'
|
||||
import type { UploadProps, UploadFile, UploadRawFile } from 'element-plus'
|
||||
import { useUpload } from '#/components/upload/use-upload'
|
||||
import { loadPdfLib,checkPdfJavaScript } from './pdf'
|
||||
|
||||
interface RowData {
|
||||
id?: number
|
||||
name?: string
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
visible: boolean
|
||||
rowData: RowData | null
|
||||
directory?: string
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:visible': [value: boolean]
|
||||
'success': [url: string, file: UploadFile]
|
||||
}>()
|
||||
|
||||
const fileList = ref<UploadFile[]>([])
|
||||
const uploading = ref(false)
|
||||
|
||||
const { uploadUrl, httpRequest } = useUpload(props.directory)
|
||||
|
||||
// 文件大小限制 10MB
|
||||
const maxFileSize = 10
|
||||
|
||||
// 允许的文件类型
|
||||
const acceptTypes = '.pdf'
|
||||
|
||||
// 监听弹窗关闭时清空文件列表
|
||||
watch(() => props.visible, (val) => {
|
||||
if (!val) {
|
||||
fileList.value = []
|
||||
uploading.value = false
|
||||
}
|
||||
})
|
||||
// 上传前校验
|
||||
const beforeUpload: UploadProps['beforeUpload'] = async (file: UploadRawFile) => {
|
||||
const isLt20M = file.size / 1024 / 1024 < maxFileSize
|
||||
if (!isLt20M) {
|
||||
ElMessage.error(`文件大小不能超过 ${maxFileSize}MB!`)
|
||||
return false
|
||||
}
|
||||
|
||||
try {
|
||||
await loadPdfLib()
|
||||
const bytes = await file.arrayBuffer()
|
||||
const hasJavaScript = await checkPdfJavaScript(bytes)
|
||||
if (hasJavaScript) {
|
||||
ElMessage.error('PDF 文件包含 JavaScript 代码,不允许上传')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} catch (error) {
|
||||
console.error('PDF 检测失败:', error)
|
||||
ElMessage.error('PDF 文件检测失败,请重试')
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 自定义上传请求
|
||||
const handleHttpRequest = (options: any) => {
|
||||
uploading.value = true
|
||||
return httpRequest(options.file)
|
||||
}
|
||||
|
||||
// 上传成功
|
||||
const handleSuccess: UploadProps['onSuccess'] = (response: any, file: UploadFile) => {
|
||||
uploading.value = false
|
||||
ElMessage.success('上传成功')
|
||||
emit('success', response, file)
|
||||
handleClose()
|
||||
}
|
||||
|
||||
// 上传失败
|
||||
const handleError: UploadProps['onError'] = () => {
|
||||
uploading.value = false
|
||||
ElMessage.error('上传失败,请重试')
|
||||
}
|
||||
|
||||
// 关闭弹窗
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false)
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElDialog
|
||||
:model-value="visible"
|
||||
title="附件上传"
|
||||
width="500px"
|
||||
@update:model-value="emit('update:visible', $event)"
|
||||
@close="handleClose"
|
||||
>
|
||||
<div class="upload-container">
|
||||
<ElUpload
|
||||
v-model:file-list="fileList"
|
||||
class="upload-demo"
|
||||
drag
|
||||
:action="uploadUrl"
|
||||
:http-request="handleHttpRequest"
|
||||
:before-upload="beforeUpload"
|
||||
:on-success="handleSuccess"
|
||||
:on-error="handleError"
|
||||
:accept="acceptTypes"
|
||||
:limit="1"
|
||||
:disabled="uploading"
|
||||
>
|
||||
<div
|
||||
class="flex min-h-[200px] flex-col items-center justify-center py-8"
|
||||
>
|
||||
<span
|
||||
class="icon-[mdi--cloud-upload-outline] mb-4 text-6xl text-gray-400"
|
||||
></span>
|
||||
<div class="text-base text-gray-600">
|
||||
点击或拖拽文件到此区域上传
|
||||
</div>
|
||||
<div class="mt-2 text-sm text-gray-400">
|
||||
支持 {{acceptTypes}} 文件
|
||||
</div>
|
||||
</div>
|
||||
</ElUpload>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<ElButton @click="handleClose" :disabled="uploading">取消</ElButton>
|
||||
</template>
|
||||
</ElDialog>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.upload-container {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.upload-demo {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.el-upload-dragger) {
|
||||
width: 100%;
|
||||
padding: 40px 20px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user