From e1b028d486713eaf55aaf35fbf334aa568059c0d Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期二, 14 四月 2026 15:46:54 +0800
Subject: [PATCH] 项目复制
---
src/views/components/UploadBtn.vue | 287 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 287 insertions(+), 0 deletions(-)
diff --git a/src/views/components/UploadBtn.vue b/src/views/components/UploadBtn.vue
new file mode 100644
index 0000000..5e4647b
--- /dev/null
+++ b/src/views/components/UploadBtn.vue
@@ -0,0 +1,287 @@
+<template>
+ <el-upload
+ ref="upload"
+ class="my-3 uploader" action="#"
+ v-model:file-list="list"
+ :accept="acceptType"
+ :list-type="listType"
+ :http-request="uploadRequest"
+ :multiple="true"
+ :limit="limitFileCount"
+ :on-preview="handlePreview"
+ :on-remove="handleRemove"
+ :before-remove="beforeRemove"
+ :on-exceed="handleExceed"
+ :disabled="disabled"
+ :class="{ hideUpload: hideUpload }"
+ >
+ <template #default>
+ <template v-if="listType=='picture-card'">
+ <el-icon v-if="!disabled"><Plus /></el-icon>
+ <el-text v-if="disabled&&list.length==0">鏆傛湭涓婁紶</el-text>
+ </template>
+ <template v-else>
+ <el-row v-if="!disabled">
+ <el-button type="primary">
+ <el-row align="middle">
+ <Icon icon="material-symbols:upload-rounded" width="20" height="20" style="color: #fff" />
+ <el-text class="text-white ml-1">{{ againUploadFlag ? '閲嶆柊涓婁紶' : '绔嬪嵆涓婁紶' }}</el-text>
+ </el-row>
+ </el-button>
+ <el-text style="color: #666666" class="ml-4">
+ {{ tip }}
+ </el-text>
+ </el-row>
+ <el-row v-else>
+ <el-text class="ml-4" style="color: #a8abb2" v-if="disabled&&list.length==0">鏈笂浼犳枃浠�</el-text>
+ </el-row>
+ </template>
+ </template>
+ <template #file="{ file, index }">
+ <template v-if="listType=='picture-card'">
+ <el-image
+ ref="previewImg"
+ :src="file.url?.includes('http') ? file.url : $qxueyou.qxyRes + file.url"
+ :initial-index="initialPreviewImgIndex"
+ :preview-src-list="filterPreviewImgList"
+ >
+ </el-image>
+ <span class="el-upload-list__item-actions">
+ <span @click="previewImage(index)">
+ <el-icon><zoom-in /></el-icon>
+ </span>
+ <span @click="deleteFileItem(index)">
+ <el-icon><delete /></el-icon>
+ </span>
+ </span>
+ </template>
+ <template v-else>
+ <div class="file-box cursor-p" :style="{ 'margin-top': disabled && index==0 ? '-30px' : '' }">
+ <Icon
+ v-if="!disabled"
+ @click.stop="deleteFileItem(index)"
+ class="cursor-p mr-3"
+ icon="eva:close-fill"
+ width="18"
+ height="18"
+ style="color: #666666"
+ />
+ <FilePreview
+ :name="file.name"
+ :url="file.url"
+ :list="list"
+ :index="index"
+ ></FilePreview>
+ </div>
+ </template>
+ </template>
+ </el-upload>
+
+ <ElImageViewer
+ v-if="showImageViewer"
+ :url-list="filterPreviewImgList"
+ :initial-index="initialPreviewImgIndex"
+ @close="showImageViewer=false"
+ >
+ </ElImageViewer>
+
+ <el-dialog v-model="pdfPreviewFlag" top="5vh">
+ <div style="height: 84vh;">
+ <PdfPreview v-if="previewUrl&&pdfPreviewFlag" :url="previewUrl"></PdfPreview>
+ </div>
+ </el-dialog>
+
+</template>
+
+<script>
+const pdf = 'application/pdf'
+const xls = 'application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
+const doc = 'application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document'
+const image = 'image/*'
+const jpg = 'image/jpeg'
+const png = 'image/png'
+const zip = 'application/zip,application/x-zip-compressed'
+import { genFileId, ElImageViewer } from 'element-plus'
+import { getFileUrlName, getFileUrlType } from '@/utils/tool.js'
+import FilePreview from '@/views/components/FilePreview.vue'
+import PdfPreview from '@/views/components/PdfPreview.vue'
+export default {
+ components: {
+ ElImageViewer,
+ PdfPreview,
+ FilePreview
+ },
+ data() {
+ return {
+ list: [],
+ previewUrl: '',
+ pdfPreviewFlag: false,
+ initialPreviewImgIndex: 0,
+ showImageViewer: false,
+ }
+ },
+ props: {
+ listType: {
+ type: String,
+ default: 'text'
+ },
+ accept: {
+ type: Array,
+ default: () => {
+ return ['pdf', 'xls', 'doc', 'image', 'jpg', 'png', 'zip']
+ }
+ },
+ limitFileCount: {
+ type: Number,
+ default: 1
+ },
+ modelValue: {
+ type: Array,
+ default: () => {
+ return []
+ }
+ },
+ disabled: {
+ type: Boolean,
+ default: false
+ }
+ },
+ watch: {
+ modelValue: {
+ handler: function() {
+ this.list = this.modelValue || []
+ this.list.forEach(ele => {
+ if (!ele.name) {
+ ele.name = getFileUrlName(ele.url)
+ }
+ })
+ },
+ immediate: true,
+ deep: true
+ },
+ list: {
+ handler: function(val) {
+ this.$emit('update:modelValue', val)
+ },
+ immediate: true,
+ deep: true
+ }
+ },
+ computed: {
+ acceptType() {
+ let obj = { pdf, xls, doc, image, jpg, png, zip }
+ return this.accept.map(ele => obj[ele]).join(',')
+ },
+ tip() {
+ let obj = {
+ pdf: 'PDF',
+ xls: 'EXCEL',
+ doc: 'WORD',
+ image: '鍥剧墖',
+ jpg: 'JPEG/JPG',
+ png: 'PNG',
+ zip: 'ZIP'
+ }
+ let tip = this.accept.map(ele => obj[ele]).join('銆�')
+ return `鏀寔${tip}绫诲瀷鏂囦欢`
+ },
+ againUploadFlag() {
+ return this.limitFileCount == 1 && this.list.length == 1
+ },
+ filterPreviewImgList() {
+ let list = this.list.map(ele => ele.url?.includes('http') ? ele.url : this.$qxueyou.qxyRes + ele.url )
+ return list
+ },
+ hideUpload() {
+ return this.list.length >= this.limitFileCount
+ }
+ },
+ methods: {
+ uploadRequest(UploadRequestOptions) {
+ const data = {
+ file: UploadRequestOptions.file,
+ directory: ''
+ }
+ this.$axios.post('/infra/file/exam/upload', data, {
+ headers: { 'Content-Type': "multipart/form-data" }
+ }).then(res => {
+ let index = this.list.findIndex(ele => ele.uid == data.file.uid)
+ if (res.data.code == 0) {
+ let index = this.list.findIndex(ele => ele.uid == data.file.uid)
+ if (index != -1) {
+ this.list[index].uploadStatus = 'success'
+ let url = res.data.data
+ this.list[index].url = url
+ }
+ this.$message.success('涓婁紶鎴愬姛')
+ } else {
+ if (index != -1) {
+ this.list[index].uploadStatus = 'fail'
+ }
+ this.$message.error(res.data.msg || '涓婁紶澶辫触')
+ }
+ })
+ },
+ deleteFileItem(index) {
+ this.list.splice(index, 1)
+ },
+ previewImage(index) {
+ this.initialPreviewImgIndex = index
+ this.$refs.previewImg?.showPreview()
+ },
+ replaceUpload() {},
+ handleRemove() {},
+ beforeRemove() {},
+ handlePreview() {},
+ handleExceed(file) {
+ if (this.againUploadFlag) {
+ this.$refs.upload?.clearFiles()
+ let newFile = file[0]
+ newFile.uid = genFileId()
+ this.$refs.upload?.handleStart(newFile)
+ this.$refs.upload?.submit()
+ } else {
+ this.$message.error(`鏈�澶氭敮鎸佷笂浼� ${this.limitFileCount} 涓枃浠禶)
+ }
+ }
+ }
+}
+</script>
+
+<style scoped>
+.uploader .avatar {
+ width: 178px;
+ height: 178px;
+ display: block;
+}
+.hideUpload :deep(.el-upload--picture-card) {
+ display: none !important;
+}
+.file-box {
+ display: flex;
+ color: #007AFF;
+ align-content: center;
+ background-color: #ECF5FF;
+ padding: 8px;
+ font-size: 15px;
+ line-height: 16px;
+}
+.el-upload-list__item-actions {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background-color: rgba(0, 0, 0, 0.5); /* 鍗婇�忔槑榛戣壊钂欑増 */
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ opacity: 0; /* 榛樿閫忔槑 */
+ transition: opacity .3s; /* 娣诲姞杩囨浮鍔ㄧ敾鏁堟灉 */
+}
+
+/* 榧犳爣鎮仠鏃舵樉绀鸿挋鐗� */
+.el-upload-list__item:hover .el-upload-list__item-actions {
+ opacity: 1;
+}
+</style>
\ No newline at end of file
--
Gitblit v1.8.0