From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目
---
src/components/UploadFile/src/UploadFile.vue | 235 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 235 insertions(+), 0 deletions(-)
diff --git a/src/components/UploadFile/src/UploadFile.vue b/src/components/UploadFile/src/UploadFile.vue
new file mode 100644
index 0000000..96fe1bc
--- /dev/null
+++ b/src/components/UploadFile/src/UploadFile.vue
@@ -0,0 +1,235 @@
+<template>
+ <div v-if="!disabled" class="upload-file">
+ <el-upload
+ ref="uploadRef"
+ v-model:file-list="fileList"
+ :action="uploadUrl"
+ :auto-upload="autoUpload"
+ :before-upload="beforeUpload"
+ :disabled="disabled"
+ :drag="drag"
+ :http-request="httpRequest"
+ :limit="props.limit"
+ :multiple="props.limit > 1"
+ :on-error="excelUploadError"
+ :on-exceed="handleExceed"
+ :on-preview="handlePreview"
+ :on-remove="handleRemove"
+ :on-success="handleFileSuccess"
+ :show-file-list="true"
+ class="upload-file-uploader"
+ name="file"
+ >
+ <el-button type="primary">
+ <Icon icon="ep:upload-filled" />
+ 閫夊彇鏂囦欢
+ </el-button>
+ <template v-if="isShowTip" #tip>
+ <div style="font-size: 8px">
+ 澶у皬涓嶈秴杩� <b style="color: #f56c6c">{{ fileSize }}MB</b>
+ </div>
+ <div style="font-size: 8px">
+ 鏍煎紡涓� <b style="color: #f56c6c">{{ fileType.join('/') }}</b> 鐨勬枃浠�
+ </div>
+ </template>
+ <template #file="row">
+ <div class="flex items-center">
+ <span>{{ row.file.name }}</span>
+ <div class="ml-10px">
+ <el-link
+ :href="row.file.url"
+ :underline="false"
+ download
+ target="_blank"
+ type="primary"
+ >
+ 涓嬭浇
+ </el-link>
+ </div>
+ <div class="ml-10px">
+ <el-button link type="danger" @click="handleRemove(row.file)"> 鍒犻櫎</el-button>
+ </div>
+ </div>
+ </template>
+ </el-upload>
+ </div>
+
+ <!-- 涓婁紶鎿嶄綔绂佺敤鏃� -->
+ <div v-if="disabled" class="upload-file">
+ <div v-for="(file, index) in fileList" :key="index" class="flex items-center file-list-item">
+ <span>{{ file.name }}</span>
+ <div class="ml-10px">
+ <el-link :href="file.url" :underline="false" download target="_blank" type="primary">
+ 涓嬭浇
+ </el-link>
+ </div>
+ </div>
+ </div>
+</template>
+<script lang="ts" setup>
+import { propTypes } from '@/utils/propTypes'
+import type { UploadInstance, UploadProps, UploadRawFile, UploadUserFile } from 'element-plus'
+import { isString } from '@/utils/is'
+import { useUpload } from '@/components/UploadFile/src/useUpload'
+import { UploadFile } from 'element-plus/es/components/upload/src/upload'
+
+defineOptions({ name: 'UploadFile' })
+
+const message = useMessage() // 娑堟伅寮圭獥
+const emit = defineEmits(['update:modelValue'])
+
+const props = defineProps({
+ modelValue: propTypes.oneOfType<string | string[]>([String, Array<String>]).isRequired,
+ fileType: propTypes.array.def(['doc', 'xls', 'ppt', 'txt', 'pdf']), // 鏂囦欢绫诲瀷, 渚嬪['png', 'jpg', 'jpeg']
+ fileSize: propTypes.number.def(5), // 澶у皬闄愬埗(MB)
+ limit: propTypes.number.def(5), // 鏁伴噺闄愬埗
+ autoUpload: propTypes.bool.def(true), // 鑷姩涓婁紶
+ drag: propTypes.bool.def(false), // 鎷栨嫿涓婁紶
+ isShowTip: propTypes.bool.def(true), // 鏄惁鏄剧ず鎻愮ず
+ disabled: propTypes.bool.def(false), // 鏄惁绂佺敤涓婁紶缁勪欢 ==> 闈炲繀浼狅紙榛樿涓� false锛�
+ directory: propTypes.string.def(undefined) // 涓婁紶鐩綍 ==> 闈炲繀浼狅紙榛樿涓� undefined锛�
+})
+
+// ========== 涓婁紶鐩稿叧 ==========
+const uploadRef = ref<UploadInstance>()
+const uploadList = ref<UploadUserFile[]>([])
+const fileList = ref<UploadUserFile[]>([])
+const uploadNumber = ref<number>(0)
+
+const { uploadUrl, httpRequest } = useUpload(props.directory)
+
+// 鏂囦欢涓婁紶涔嬪墠鍒ゆ柇
+const beforeUpload: UploadProps['beforeUpload'] = (file: UploadRawFile) => {
+ if (fileList.value.length >= props.limit) {
+ message.error(`涓婁紶鏂囦欢鏁伴噺涓嶈兘瓒呰繃${props.limit}涓�!`)
+ return false
+ }
+ let fileExtension = ''
+ if (file.name.lastIndexOf('.') > -1) {
+ fileExtension = file.name.slice(file.name.lastIndexOf('.') + 1)
+ }
+ const isImg = props.fileType.some((type: string) => {
+ if (file.type.indexOf(type) > -1) return true
+ return !!(fileExtension && fileExtension.indexOf(type) > -1)
+ })
+ const isLimit = file.size < props.fileSize * 1024 * 1024
+ if (!isImg) {
+ message.error(`鏂囦欢鏍煎紡涓嶆纭�, 璇蜂笂浼�${props.fileType.join('/')}鏍煎紡!`)
+ return false
+ }
+ if (!isLimit) {
+ message.error(`涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃${props.fileSize}MB!`)
+ return false
+ }
+ message.success('姝e湪涓婁紶鏂囦欢锛岃绋嶅��...')
+ // 鍙湁鍦ㄩ獙璇侀�氳繃鍚庢墠澧炲姞璁℃暟鍣�
+ uploadNumber.value++
+ return true
+}
+// 澶勭悊涓婁紶鐨勬枃浠跺彂鐢熷彉鍖�
+// const handleFileChange = (uploadFile: UploadFile): void => {
+// uploadRef.value.data.path = uploadFile.name
+// }
+// 鏂囦欢涓婁紶鎴愬姛
+const handleFileSuccess: UploadProps['onSuccess'] = (res: any): void => {
+ message.success('涓婁紶鎴愬姛')
+ // 鍒犻櫎鑷韩
+ const index = fileList.value.findIndex((item) => item.response?.data === res.data)
+ fileList.value.splice(index, 1)
+ uploadList.value.push({ name: res.data, url: res.data })
+ if (uploadList.value.length == uploadNumber.value) {
+ fileList.value.push(...uploadList.value)
+ uploadList.value = []
+ uploadNumber.value = 0
+ emitUpdateModelValue()
+ }
+}
+// 鏂囦欢鏁拌秴鍑烘彁绀�
+const handleExceed: UploadProps['onExceed'] = (): void => {
+ message.error(`涓婁紶鏂囦欢鏁伴噺涓嶈兘瓒呰繃${props.limit}涓�!`)
+}
+// 涓婁紶閿欒鎻愮ず
+const excelUploadError: UploadProps['onError'] = (): void => {
+ message.error('瀵煎叆鏁版嵁澶辫触锛岃鎮ㄩ噸鏂颁笂浼狅紒')
+ // 涓婁紶澶辫触鏃跺噺灏戣鏁板櫒锛岄伩鍏嶅悗缁笂浼犺闃诲
+ uploadNumber.value = Math.max(0, uploadNumber.value - 1)
+}
+// 鍒犻櫎涓婁紶鏂囦欢
+const handleRemove = (file: UploadFile) => {
+ const index = fileList.value.map((f) => f.name).indexOf(file.name)
+ if (index > -1) {
+ fileList.value.splice(index, 1)
+ emitUpdateModelValue()
+ }
+}
+const handlePreview: UploadProps['onPreview'] = (uploadFile) => {
+ console.log(uploadFile)
+}
+
+// 鐩戝惉妯″瀷缁戝畾鍊煎彉鍔�
+watch(
+ () => props.modelValue,
+ (val: string | string[]) => {
+ if (!val) {
+ fileList.value = [] // fix锛氬鐞嗘帀缂撳瓨锛岃〃鍗曢噸缃悗涓婁紶缁勪欢鐨勫唴瀹瑰苟娌℃湁閲嶇疆
+ return
+ }
+
+ fileList.value = [] // 淇濋殰鏁版嵁涓虹┖
+ // 鎯呭喌1锛氬瓧绗︿覆
+ if (isString(val)) {
+ fileList.value.push(
+ ...val.split(',').map((url) => ({ name: url.substring(url.lastIndexOf('/') + 1), url }))
+ )
+ return
+ }
+ // 鎯呭喌2锛氭暟缁�
+ fileList.value.push(
+ ...(val as string[]).map((url) => ({ name: url.substring(url.lastIndexOf('/') + 1), url }))
+ )
+ },
+ { immediate: true, deep: true }
+)
+// 鍙戦�佹枃浠堕摼鎺ュ垪琛ㄦ洿鏂�
+const emitUpdateModelValue = () => {
+ // 鎯呭喌1锛氭暟缁勭粨鏋�
+ let result: string | string[] = fileList.value.map((file) => file.url!)
+ // 鎯呭喌2锛氶�楀彿鍒嗛殧鐨勫瓧绗︿覆
+ if (props.limit === 1 || isString(props.modelValue)) {
+ result = result.join(',')
+ }
+ emit('update:modelValue', result)
+}
+</script>
+<style lang="scss" scoped>
+.upload-file-uploader {
+ margin-bottom: 5px;
+}
+
+:deep(.upload-file-list .el-upload-list__item) {
+ position: relative;
+ margin-bottom: 10px;
+ line-height: 2;
+ border: 1px solid #e4e7ed;
+}
+
+:deep(.el-upload-list__item-file-name) {
+ max-width: 250px;
+}
+
+:deep(.upload-file-list .ele-upload-list__item-content) {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ color: inherit;
+}
+
+:deep(.ele-upload-list__item-content-action .el-link) {
+ margin-right: 10px;
+}
+
+.file-list-item {
+ border: 1px dashed var(--el-border-color-darker);
+ border-radius: 8px;
+}
+</style>
--
Gitblit v1.8.0