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/UploadImg.vue | 272 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 272 insertions(+), 0 deletions(-)
diff --git a/src/components/UploadFile/src/UploadImg.vue b/src/components/UploadFile/src/UploadImg.vue
new file mode 100644
index 0000000..66e9d0c
--- /dev/null
+++ b/src/components/UploadFile/src/UploadImg.vue
@@ -0,0 +1,272 @@
+<template>
+ <div class="upload-box">
+ <el-upload
+ :id="uuid"
+ :accept="fileType.join(',')"
+ :action="uploadUrl"
+ :before-upload="beforeUpload"
+ :class="['upload', drag ? 'no-border' : '']"
+ :disabled="disabled"
+ :drag="drag"
+ :http-request="httpRequest"
+ :multiple="false"
+ :on-error="uploadError"
+ :on-success="uploadSuccess"
+ :show-file-list="false"
+ >
+ <template v-if="modelValue">
+ <img :src="modelValue" class="upload-image" />
+ <div class="upload-handle" @click.stop>
+ <div v-if="!disabled" class="handle-icon" @click="editImg">
+ <Icon icon="ep:edit" />
+ <span v-if="showBtnText">{{ t('action.edit') }}</span>
+ </div>
+ <div class="handle-icon" @click="imagePreview(modelValue)">
+ <Icon icon="ep:zoom-in" />
+ <span v-if="showBtnText">{{ t('action.detail') }}</span>
+ </div>
+ <div v-if="showDelete && !disabled" class="handle-icon" @click="deleteImg">
+ <Icon icon="ep:delete" />
+ <span v-if="showBtnText">{{ t('action.del') }}</span>
+ </div>
+ </div>
+ </template>
+ <template v-else>
+ <div class="upload-empty">
+ <slot name="empty">
+ <Icon icon="ep:plus" />
+ <!-- <span>璇蜂笂浼犲浘鐗�</span> -->
+ </slot>
+ </div>
+ </template>
+ </el-upload>
+ <div class="el-upload__tip">
+ <slot name="tip"></slot>
+ </div>
+ </div>
+</template>
+
+<script lang="ts" setup>
+import type { UploadProps } from 'element-plus'
+
+import { generateUUID } from '@/utils'
+import { propTypes } from '@/utils/propTypes'
+import { createImageViewer } from '@/components/ImageViewer'
+import { useUpload } from '@/components/UploadFile/src/useUpload'
+
+defineOptions({ name: 'UploadImg' })
+
+type FileTypes =
+ | 'image/apng'
+ | 'image/bmp'
+ | 'image/gif'
+ | 'image/jpeg'
+ | 'image/pjpeg'
+ | 'image/png'
+ | 'image/svg+xml'
+ | 'image/tiff'
+ | 'image/webp'
+ | 'image/x-icon'
+
+// 鎺ュ彈鐖剁粍浠跺弬鏁�
+const props = defineProps({
+ modelValue: propTypes.string.def(''),
+ drag: propTypes.bool.def(true), // 鏄惁鏀寔鎷栨嫿涓婁紶 ==> 闈炲繀浼狅紙榛樿涓� true锛�
+ disabled: propTypes.bool.def(false), // 鏄惁绂佺敤涓婁紶缁勪欢 ==> 闈炲繀浼狅紙榛樿涓� false锛�
+ fileSize: propTypes.number.def(5), // 鍥剧墖澶у皬闄愬埗 ==> 闈炲繀浼狅紙榛樿涓� 5M锛�
+ fileType: propTypes.array.def(['image/jpeg', 'image/png', 'image/gif']), // 鍥剧墖绫诲瀷闄愬埗 ==> 闈炲繀浼狅紙榛樿涓� ["image/jpeg", "image/png", "image/gif"]锛�
+ height: propTypes.string.def('150px'), // 缁勪欢楂樺害 ==> 闈炲繀浼狅紙榛樿涓� 150px锛�
+ width: propTypes.string.def('150px'), // 缁勪欢瀹藉害 ==> 闈炲繀浼狅紙榛樿涓� 150px锛�
+ borderradius: propTypes.string.def('8px'), // 缁勪欢杈规鍦嗚 ==> 闈炲繀浼狅紙榛樿涓� 8px锛�
+ showDelete: propTypes.bool.def(true), // 鏄惁鏄剧ず鍒犻櫎鎸夐挳
+ showBtnText: propTypes.bool.def(true), // 鏄惁鏄剧ず鎸夐挳鏂囧瓧
+ directory: propTypes.string.def(undefined) // 涓婁紶鐩綍 ==> 闈炲繀浼狅紙榛樿涓� undefined锛�
+})
+const { t } = useI18n() // 鍥介檯鍖�
+const message = useMessage() // 娑堟伅寮圭獥
+// 鐢熸垚缁勪欢鍞竴id
+const uuid = ref('id-' + generateUUID())
+// 鏌ョ湅鍥剧墖
+const imagePreview = (imgUrl: string) => {
+ createImageViewer({
+ zIndex: 9999999,
+ urlList: [imgUrl]
+ })
+}
+
+const emit = defineEmits(['update:modelValue'])
+
+const deleteImg = () => {
+ emit('update:modelValue', '')
+}
+
+const { uploadUrl, httpRequest } = useUpload(props.directory)
+
+const editImg = () => {
+ const dom = document.querySelector(`#${uuid.value} .el-upload__input`)
+ dom && dom.dispatchEvent(new MouseEvent('click'))
+}
+
+const beforeUpload: UploadProps['beforeUpload'] = (rawFile) => {
+ const imgSize = rawFile.size / 1024 / 1024 < props.fileSize
+ const imgType = props.fileType
+ if (!imgType.includes(rawFile.type as FileTypes))
+ message.notifyWarning('涓婁紶鍥剧墖涓嶇鍚堟墍闇�鐨勬牸寮忥紒')
+ if (!imgSize) message.notifyWarning(`涓婁紶鍥剧墖澶у皬涓嶈兘瓒呰繃 ${props.fileSize}M锛乣)
+ return imgType.includes(rawFile.type as FileTypes) && imgSize
+}
+
+// 鍥剧墖涓婁紶鎴愬姛鎻愮ず
+const uploadSuccess: UploadProps['onSuccess'] = (res: any): void => {
+ message.success('涓婁紶鎴愬姛')
+ emit('update:modelValue', res.data)
+}
+
+// 鍥剧墖涓婁紶閿欒鎻愮ず
+const uploadError = () => {
+ message.notifyError('鍥剧墖涓婁紶澶辫触锛岃鎮ㄩ噸鏂颁笂浼狅紒')
+}
+</script>
+<style lang="scss" scoped>
+.is-error {
+ .upload {
+ :deep(.el-upload),
+ :deep(.el-upload-dragger) {
+ border: 1px dashed var(--el-color-danger) !important;
+
+ &:hover {
+ border-color: var(--el-color-primary) !important;
+ }
+ }
+ }
+}
+
+:deep(.disabled) {
+ .el-upload,
+ .el-upload-dragger {
+ cursor: not-allowed !important;
+ background: var(--el-disabled-bg-color);
+ border: 1px dashed var(--el-border-color-darker) !important;
+
+ &:hover {
+ border: 1px dashed var(--el-border-color-darker) !important;
+ }
+ }
+}
+
+.upload-box {
+ .no-border {
+ :deep(.el-upload) {
+ border: none !important;
+ }
+ }
+
+ :deep(.upload) {
+ .el-upload {
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: v-bind(width);
+ height: v-bind(height);
+ overflow: hidden;
+ border: 1px dashed var(--el-border-color-darker);
+ border-radius: v-bind(borderradius);
+ transition: var(--el-transition-duration-fast);
+
+ &:hover {
+ border-color: var(--el-color-primary);
+
+ .upload-handle {
+ opacity: 1;
+ }
+ }
+
+ .el-upload-dragger {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ height: 100%;
+ padding: 0;
+ overflow: hidden;
+ background-color: transparent;
+ border: 1px dashed var(--el-border-color-darker);
+ border-radius: v-bind(borderradius);
+
+ &:hover {
+ border: 1px dashed var(--el-color-primary);
+ }
+ }
+
+ .el-upload-dragger.is-dragover {
+ background-color: var(--el-color-primary-light-9);
+ border: 2px dashed var(--el-color-primary) !important;
+ }
+
+ .upload-image {
+ width: 100%;
+ height: 100%;
+ object-fit: contain;
+ }
+
+ .upload-empty {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ font-size: 12px;
+ line-height: 30px;
+ color: var(--el-color-info);
+
+ .el-icon {
+ font-size: 28px;
+ color: var(--el-text-color-secondary);
+ }
+ }
+
+ .upload-handle {
+ position: absolute;
+ top: 0;
+ right: 0;
+ display: flex;
+ width: 100%;
+ height: 100%;
+ cursor: pointer;
+ background: rgb(0 0 0 / 60%);
+ opacity: 0;
+ box-sizing: border-box;
+ transition: var(--el-transition-duration-fast);
+ align-items: center;
+ justify-content: center;
+
+ .handle-icon {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 0 6%;
+ color: aliceblue;
+
+ .el-icon {
+ margin-bottom: 40%;
+ font-size: 130%;
+ line-height: 130%;
+ }
+
+ span {
+ font-size: 85%;
+ line-height: 85%;
+ }
+ }
+ }
+ }
+ }
+
+ .el-upload__tip {
+ line-height: 18px;
+ text-align: center;
+ }
+}
+</style>
--
Gitblit v1.8.0