【FileShowCom 组件】文件预览:图片预览 el-image,其余文件预览打开新窗口或者下载

这里写目录标题

FileShowCom 组件代码

html 复制代码
<template>
  <div class="file-show-com">
    <template v-for="(file, index) in fileList">
      <el-image
        v-if="isImage(file)"
        :key="'img-' + index"
        class="file-image"
        :src="getFileUrl(file)"
        :preview-src-list="[getFileUrl(file)]"
        fit="cover"
      >
        <div slot="error" class="image-error">
          <i class="el-icon-picture-outline" title="图片加载失败"></i>
        </div>
      </el-image>
      <el-link
        v-else
        :key="'link-' + index"
        type="primary"
        :href="getFileUrl(file)"
        :download="getFileName(file)"
        target="_blank"
      >
        <i class="el-icon-document"></i>
        {{ getFileName(file) }}
      </el-link>
      <span
        v-if="index < fileList.length - 1"
        :key="'separator-' + index"
        class="file-separator"
      ></span>
    </template>
  </div>
</template>

<script>
export default {
  name: 'FileShowCom',
  props: {
    fileList: {
      type: Array,
      default: () => []
    },
    fileNameField: {
      type: String,
      default: 'wjmc'
    },
    filePathField: {
      type: String,
      default: 'wjlj'
    },
    fileTypeField: {
      type: String,
      default: 'wjgs' // 文件格式不带点,例如:jpg,不是.jpg
    }
  },
  computed: {},
  methods: {
    isImage(file) {
      if (!file) return false
      let ext = null
      if (file[this.fileTypeField]) {
        ext = file[this.fileTypeField]
      } else {
        const url = typeof file === 'string' ? file : file[this.filePathField]
        const name = typeof file === 'string' ? file : file[this.fileNameField]
        if (!url && !name) return false
        const urlSplit = url.split('.')
        const nameSplit = name.split('.')
        if (urlSplit.length > 1) ext = urlSplit.pop().toLowerCase()
        else if (nameSplit.length > 1) ext = nameSplit.pop().toLowerCase()
      }
      return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'].includes(ext)
    },
    getFileUrl(file) {
      return typeof file === 'string' ? file : file[this.filePathField]
    },
    getFileName(file) {
      if (!file) return ''
      if (typeof file === 'string') {
        return file.split('/').pop() || file
      }
      return (
        file[this.fileNameField] ||
        (file[this.filePathField] ? file[this.filePathField].split('/').pop() : '') ||
        ''
      )
    }
  }
}
</script>

<style scoped>
.file-show-com {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
}
.file-image {
  width: 40px;
  height: 40px;
  border-radius: 4px;
  cursor: pointer;
}
.image-error {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  background: #f5f7fa;
  color: #909399;
  font-size: 18px;
}
.file-separator {
  margin: 0 8px;
  color: #dcdfe6;
}
</style>

组件使用

html 复制代码
<FileShowCom
   :file-list="[
    {
      wjmc: 'example.jpg',
      wjlj: 'https://images.dog.ceo/breeds/pembroke/n02113023_5362.jpg'
    },
    {
      wjmc: 'DOC.doc',
      wjlj: 'https://images.dog.ceo/breeds/pembroke/n02113023_5362.doc'
    },
    {
      wjmc: 'MP4.mp4',
      wjlj:
        'https://live-s3m.mediav.com/nativevideo/dec07f3b3b0953722b738ced98fe148d-bit_cloud768.mp4'
    },
    {
      wjmc: 'PDF.pdf',
      wjlj:
        'http://192.168.0.42:9000/oss/ajax/bucket/file/supervisecore/ACTIVITY/20260407/42mZWFifrYySXhPl+4H6Eg==.pdf'
    }
  ]"
/>

页面展示


相关推荐
风骏时光牛马10 分钟前
AI源码分析:拆解模型底层实现逻辑
前端
BillKu18 分钟前
全局样式变量:CSS 自定义属性(--border-color)和SCSS 变量($border-color)的说明
javascript·css·scss
IT_陈寒31 分钟前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端
菜鸟~noob23332 分钟前
【电子战】 第01篇:噪声、门限与虚警/检测概率(PFA/PD)【含matlab代码】
开发语言·matlab
奇牙coding12334 分钟前
GPT-6-Astra API 接入教程:OpenRouter 路由配置 + Python/curl 示例 + 静默降级踩坑
开发语言·python·gpt·ai
乘风gg41 分钟前
DeepSeek V4.1 Flash 来了,明天中午 Flash 降价 60%
前端·ai编程·claude
默_笙1 小时前
❗ 给金鱼装记忆(上):从白板到笔记本,AI 的短期记忆生存指南
前端·javascript
酷酷的逗逗乐1 小时前
前端转 Agent 开发 · 第五节:Memory 会话记忆
前端·程序员
掘金挖土1 小时前
前端手摸手跑路之 AI 应用开发(二)
前端·后端
lzx_0021 小时前
C++11(一)
开发语言·c++·算法