Vue3 上传后的文件智能预览(实战体会)

目录

  • 前言
  • [1. Demo1](#1. Demo1)
  • [2. Demo2](#2. Demo2)

前言

🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF
爬虫神器,无代码爬取,就来:bright.cn

此处的基本知识涉及较少,主要以Demo的形式供大家学习,从实战中触发

本身url是在线链接且是以数组的形式存在

开源项目来源:https://gitee.com/zhijiantianya/ruoyi-vue-pro

1. Demo1

本身一开始以Minio的形式上传,以文件的形式进行命名:

后续用户需要一个个点击才能看到是什么文件

html 复制代码
 <el-form-item label="单证附件" prop="imgPath">
   <UploadFile v-model="formData.imgPath" limit="10" />
 </el-form-item>
  1. 把 imgPath 按逗号分割为数组

  2. 遍历数组,每个链接:

    如果是图片(比如后缀是 .jpg、.png 等),就渲染成 <el-image>

    如果不是图片,就渲染成带下载链接的文件名

示例的Demo如下:

html 复制代码
<template>
  <div class="file-preview-list">
    <div
      v-for="(item, index) in fileList"
      :key="index"
      class="preview-item"
    >
      <el-image
        v-if="isImage(item)"
        :src="item"
        :preview-src-list="[item]"
        fit="cover"
        style="width: 100px; height: 100px; margin-right: 10px;"
      >
        <template #error>
          <div style="font-size: 12px; color: #999;">加载失败</div>
        </template>
      </el-image>

      <a
        v-else
        :href="item"
        target="_blank"
        style="color: #409EFF; text-decoration: underline;"
      >
        文件 {{ index + 1 }}
      </a>
    </div>
  </div>
</template>

<script setup>
import { computed } from 'vue';

const props = defineProps({
  modelValue: String
});

const fileList = computed(() => {
  return props.modelValue
    ? props.modelValue.split(',').map(item => item.trim())
    : [];
});

const isImage = (url) => {
  return /\.(jpg|jpeg|png|gif|bmp|webp)$/i.test(url);
};
</script>

<style scoped>
.file-preview-list {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.preview-item {
  display: flex;
  align-items: center;
}
</style>

组件这样使用:

html 复制代码
<el-form-item label="单证附件" prop="imgPath">
  <UploadFile v-model="formData.imgPath" limit="10" />
  <UploadPreview v-model="formData.imgPath" />
</el-form-item>

后续由于图片有些过大,对应以正在加载的形式呈现:

html 复制代码
<template>
  <div class="file-preview-list">
    <div
      v-for="(item, index) in fileList"
      :key="index"
      class="preview-item"
    >
      <el-image
        v-if="isImage(item)"
        :src="item"
        :preview-src-list="[item]"
        fit="cover"
        style="width: 100px; height: 100px; margin-right: 10px;"
      >
        <template #placeholder>
          <div
            style="display: flex; align-items: center; justify-content: center; height: 100%; color: #aaa; font-size: 12px;"
          >
            正在加载...
          </div>
        </template>
        <template #error>
          <div style="font-size: 12px; color: #999;">加载失败</div>
        </template>
      </el-image>

      <a
        v-else
        :href="item"
        target="_blank"
        style="color: #409EFF; text-decoration: underline;"
      >
        文件 {{ index + 1 }}
      </a>
    </div>
  </div>
</template>

<script setup>
import { computed } from 'vue';

const props = defineProps({
  modelValue: String
});

const fileList = computed(() => {
  return props.modelValue
    ? props.modelValue.split(',').map(item => item.trim())
    : [];
});

const isImage = (url) => {
  return /\.(jpg|jpeg|png|gif|bmp|webp)$/i.test(url);
};
</script>

<style scoped>
.file-preview-list {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.preview-item {
  display: flex;
  align-items: center;
}
</style>

✅ 推荐结构(用 el-row + 两个 el-col)

原来的结构是把所有内容都放在了一个 el-form-item 里面,这样不太好控制布局

建议改成下面这样:

html 复制代码
<el-row>
  <!-- 左侧:上传控件 -->
  <el-col :span="12">
    <el-form-item label="单证附件" prop="imgPath">
      <UploadFile v-model="formData.imgPath" limit="10" />
    </el-form-item>
  </el-col>

  <el-col :span="12">
    <div style="margin-bottom: 8px; font-weight: bold;">附件预览</div>
    <UploadPreview v-model="formData.imgPath" />
  </el-col>
</el-row>

最终截图如下:

2. Demo2

另外一种呈现的方式如下:

html 复制代码
<el-table-column label="照片" align="center" prop="imgPath" width="500" fixed="left">
	<template #default="{ row }">
	  <div v-if="row.imgPath && row.imgPath.length > 0" class="damage-images">
	    <el-image
	      v-for="(img, index) in row.imgPath"
	      :key="index"
	      class="h-80px w-80px"
	      lazy
	      :src="img"
	      :preview-src-list="row.imgPath"
	      preview-teleported
	      fit="cover"
	    />
	  </div>
	  <div v-else class="no-image">无图片</div>
	</template>
</el-table-column>
相关推荐
有颜有货3 小时前
网站开发技术是什么?网站开发技术的定义,分类,特点,要求一文看懂
css·html·web·网站开发
大漠_w3cpluscom6 小时前
利用现代 CSS 实现区间选择
前端·css·html
酉鬼女又兒6 小时前
HTML基础实例样式详解零基础快速入门Web开发(可备赛蓝桥杯Web应用开发赛道) 助力快速拿奖
前端·javascript·职场和发展·蓝桥杯·html·html5·web
kyriewen7 小时前
响应式设计:一套代码,手机平板电脑全拿下
前端·css·html
用户2986985301410 小时前
告别手动复制:.NET 将网页数据一键导出为 Excel
后端·html·excel
麦麦鸡腿堡10 小时前
JavaWeb_HTML/CSS快速入门
前端·css·html
吾爱iis11 小时前
OTOClaw - 智能龙虾,一键部署OpenClaw龙虾、轻松养龙虾
vue·tauri·openclaw·otoclaw
..过云雨11 小时前
【负载均衡oj项目】04. oj_server题目信息获取、界面渲染、负载均衡、后台交互功能
运维·c++·html·负载均衡·交互
..过云雨12 小时前
【负载均衡oj项目】02. comm公共文件夹设计 - 包含所有需要用到的自定义工具
数据库·c++·mysql·html·负载均衡
optimistic_chen12 小时前
【Vue入门】组件及组件化
前端·javascript·vue.js·html·组件