element 图片和pdf上传,组件封装

 先说下具体思路,需要实现一个图片,pdf ,图片+pdf,三种类型的上传功能,并且还需要展示和删除。

1.封装上传图片组件

2.传不同的类型,用来校验图片或者PDF上传了几张,图片的大小。

3.因为是上传的有图片和pdf ,所以要区分开来,值放在对应字段中,方便后面的回显

不理解的可以留言

// 上传图片 
// tableItem是列表中那一条数据,reportType是要求给后端传的类型,size图片大小M,accept图片类型
<UploadFile v-model="getSendReportData.report.ossFileUploads" :rowInfo="tableItem" reportType="report" :size="10" accept="image/jpeg,image/png" />

// 展示图片 otherData在这里意思是,传PDF的数据,删除图片,PDF必须保留一张,所以后面会相加做判断
<PopList v-model="getSendReportData.report.ossFileUploads" :otherData="getSendReportData.report.ossPDFUploads" fileType="image" />

// 上传pdf
<UploadFile btnTit="选择文件" v-model="getSendReportData.report.ossPDFUploads" :rowInfo="tableItem" reportType="report" :size="50" accept="application/pdf" />

// 展示PDF otherData在这里意思是,传图片的数据,删除图片,PDF必须保留一张,所以后面会相加做判断
<PopList v-model="getSendReportData.report.ossPDFUploads" :otherData="getSendReportData.report.ossFileUploads" fileType="pdf"/>


// 上传图片和PDF
<UploadFile v-model="getSendReportData.conclusion.ossUploads" :rowInfo="tableItem" reportType="conclusion" :size="10" accept="image/jpeg,image/png,application/pdf" />

// 展示图片和PDF 这里不传otherData,因为删除功能没有要求至少保留一张图片,所以删除图片不做限制
<PopList v-model="getSendReportData.conclusion.ossUploads" fileType="imgAndPdf" />

data () {
    return {
          tableItem: null, // 表格行信息
          getSendReportData: {
            report: {
              itemId: null,
              ossFileUploads: [], // 图片
              ossPDFUploads: [] // PDF
            },
         // 是否有总检报告
            conclusion: {
              itemId: null,
              ossUploads: []
            }
      },    
    }
}

图片上传组件 UploadFile

<template>
  <div class="upload-block">
    <el-upload :headers="headers" action="/api/oss/file/upload" :show-file-list="false" :accept="accept" :on-success="handleUploadSuccess" :before-upload="beforeFileUpload">
      <div class="t-a-l">
        <el-button size="small" type="primary">{{btnTit}}</el-button><br />
      </div>
    </el-upload>
  </div>
</template>

<script>
// Loading图片上传用来加载,Loading存在 vuex了,具体代码可以查看我之前写的
import { Loading } from 'element-ui'
let loadingInstance = null
export default {
  name: 'uploadFile',
  props: {
    btnTit: {
      default: '点击上传'
    },
    // 行信息
    rowInfo: {
      type: Object,
      default: () => ({})
    },
    // 报告类型 report 结果报告 conclusion 筛查小结报告
    reportType: {
      default: ''
    },
    value: {
      type: Array,
      default: () => ([])
    },
    accept: {
      default: 'image/jpeg,image/png'
    },
    size: {
      default: 10
    }
  },
  data () {
    return {
      files: [],
      headers: {
        Authorization: 'Bearer ' + localStorage.getItem('Authorization')
        },
      len: [] // 用来记录上传了几张
    }
  },
  watch: {
    value: {
      handler (value) {
        this.files = value
        // 因为item.deleted为0才是实际的数据,和后端约定的,所以我这里需要过滤出实际的数据,方便后面判断上传了几张
        this.len = value.filter(item => item.deleted === 0).length
      },
      immediate: true
    }
  },
  model: {
    prop: 'value',
    event: 'handleUploadSuccess'
  },
  methods: {
    beforeFileUpload (file) {
      if (this.len >= this.size && this.accept === 'image/jpeg,image/png') { // 图片
        this.$message.error(`最多可以上传${this.size}张图片`)
        return false
      }
      if (this.len >= this.size && this.accept === 'application/pdf') { // PDF
        this.$message.error(`最多可以上传${this.size}个文件`)
        return false
      }
      if (this.len >= this.size && this.accept === 'image/png,image/jpeg,application/pdf') { // 其它文件类型
        this.$message.error(`最多可以上传${this.size}份`) // 其它文件类型
        return false
      }
      // 图片 10M  pdf 50M
      loadingInstance = Loading.service(this.$store.state.LoadingoOptions)
      const fileSize = file.size / 1024 / 1024 < this.size
      if (!fileSize) {
        if (this.accept === 'image/jpeg,image/png') { // 图片
          this.$message.error(`单张图片大小不能超过${this.size}MB!`)
        } else if (this.accept === 'application/pdf') { // PDF
          this.$message.error(`单个文件大小不能超过${this.size}MB!`)
        } else { // 其它文件类型
          this.$message.error(`单个文件大小不能超过${this.size}MB!`)
        }
        loadingInstance.close()
      }
      return fileSize
    },
    handleUploadSuccess (res, file) {
      if (res.code !== 200) {
        this.$message.error(res.msg)
        return false
      }
      const { filePath, thumbnailPath } = res.data
      this.files.push({
        filePath: filePath,
        thumbnailPath: thumbnailPath,
        dataId: this.rowInfo.id,
        type: this.reportType,
        deleted: 0 // 文件上传成功后,均增加一个deleted字段表示 0 保留 1 删除
      })
      loadingInstance.close()
      this.$message.success('上传成功')
      this.$emit('handleUploadSuccess', this.files)
    }
  }
}
</script>

<style lang="less" scoped>
.t-a-l {
  text-align: left;
}
</style>

图片/PDF回显组件 PopList

<template>
  <div class="itemlist">
    <template v-for="(item,index) in imglist">
      <li v-if="item.deleted === 0" :key="index">
        <img v-if="fileType === 'image'" :src="item.filePath" alt="">
        <img v-if="fileType === 'pdf'" :src="item.thumbnailPath" alt="">
        <img v-else :src="(item.filePath.indexOf('.pdf') > -1 || item.filePath.indexOf('.PDF') > -1) ? item.thumbnailPath : item.filePath" alt="">
        <i class="iconfont icon-shanchu" @click="del(item,index)"></i>
      </li>
    </template>
  </div>
</template>

<script>
export default {
  data () {
    return {
      imglist: []
    }
  },
  props: {
    value: {
      default: () => []
    },
    otherData: {
      default: () => []
    },
    fileType: {
      default: ''
    }
  },
  watch: {
    value: {
      deep: true,
      immediate: true,
      handler (val) {
        this.imglist = val
      }
    }
  },
  model: {
    prop: 'value',
    event: 'getValue'
  },
  methods: {
    del (item, index) {
       // 拿到图片和pdf的长度
      const tablen1 = this.imglist.filter(item => item.deleted === 0).length
      const tablen2 = this.otherData.filter(item => item.deleted === 0).length
      if (item.id) {
        if (this.fileType !== 'imgAndPdf' && (tablen1 + tablen2) <= 1) {
          this.$message.error('至少保留一张图片或一个PDF文件')
          return false
        }
        this.imglist[index].deleted = 1
      } else {
        // 判断是不是imgpdf,如果是,则不需要判断长度,否则需要判断长度
        if (this.fileType === 'imgAndPdf') {
          this.imglist.splice(index, 1)
        } else {
          if ((tablen1 + tablen2) > 1) {
            this.imglist.splice(index, 1)
          } else {
            this.$message.error('至少保留一张图片')
            return false
          }
        }
      }
      this.$emit('getValue', this.imglist)
    }
  }
}
</script>

<style lang="less" scoped>
.itemlist {
  display: flex;
  flex-wrap: wrap;
  li {
    width: 100px;
    height: 100px;
    border: 1px dashed #ccc;
    border-radius: 4px;
    overflow: hidden;
    margin: 0 10px 10px 0;
    position: relative;
    img {
      width: 100px;
      height: 100px;
    }
    .icon-shanchu {
      position: absolute;
      top: 4px;
      right: 6px;
      font-size: 20px;
      color: red;
      cursor: pointer;
    }
  }
}
</style>

完整的代码

<!-- 弹窗 -->
    <el-dialog title="提交报告" class="upload-dialog" :visible.sync="dialog.one" :close-on-click-modal="false" width="960px">
      <el-form :model="conclusionForm" ref="conclusionForm" label-width="120px" class="demo-ruleForm">
        <Title title="图片格式" />
        <el-form-item label="" prop="选择图片" key="report-img" label-width="10px">
          <UploadFile v-model="getSendReportData.report.ossFileUploads" :rowInfo="tableItem" reportType="report" :size="10" accept="image/jpeg,image/png" />
          <font class="upload-text">只能上传jpg/png文件,且不超过10M,最多可以上传10张图片</font>
          <PopList v-model="getSendReportData.report.ossFileUploads" :otherData="getSendReportData.report.ossPDFUploads" fileType="image" />
        </el-form-item>
        <Title title="PDF格式" />
        <el-form-item label="" prop="选择PDF" label-width="10px">
          <UploadFile btnTit="选择文件" v-model="getSendReportData.report.ossPDFUploads" :rowInfo="tableItem" reportType="report" :size="50" accept="application/pdf" />
          <font class="upload-text">单个文件不超过50M,最多可以上传10个文件</font>
          <PopList v-model="getSendReportData.report.ossPDFUploads" :otherData="getSendReportData.report.ossFileUploads" fileType="pdf" />
        </el-form-item>
        <!-- <Title title="筛查小结" /> -->
        <!-- :rules="conclusionTypeRule" key="screenConclusionType" -->
        <el-form-item label="是否有总检报告" prop="screenConclusionType">
          <el-radio-group v-model="conclusionForm.screenConclusionType">
            <el-radio :label="0">无</el-radio>
            <el-radio :label="1">文件类</el-radio>
            <el-radio :label="2">文字输入</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="" prop="选择文件" label-width="10px" v-show="conclusionForm.screenConclusionType === 1" key="conclusionFile">
          <UploadFile v-model="getSendReportData.conclusion.ossUploads" :rowInfo="tableItem" reportType="conclusion" :size="10" accept="image/jpeg,image/png,application/pdf" />
          <font class="upload-text">只能上传jpg/png/pdf文件,且不超过10M,最多可以上传10份</font>
          <PopList v-model="getSendReportData.conclusion.ossUploads" fileType="imgAndPdf" />
        </el-form-item>
        <el-form-item label="" prop="screenConclusionText" :rules="conclusionForm.screenConclusionType === 2 ? conclusionTextRule : undefined" key="screenConclusionText" v-show="conclusionForm.screenConclusionType === 2">
          <el-input type="textarea" class="w-500" placeholder="请依据本次检查提供健康指导建议" v-model="conclusionForm.screenConclusionText" :rows="10" :maxlength="300" show-word-limit></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="handlerClose">取 消</el-button>
        <el-button type="primary" @click="handlerSend">确 定</el-button>
      </span>
    </el-dialog>


data () {
    return { 
        tableItem: null, // 表格行信息
getSendReportData: {
        // 上传报告
        report: {
          itemId: null,
          ossFileUploads: [], // 图片
          ossPDFUploads: [] // PDF
        },
        // 筛查小结
        conclusion: {
          itemId: null,
          ossUploads: []
        }
      }, // 单条发送报告
      conclusionForm: {
        screenConclusionType: 0,
        screenConclusionText: ''
      },
      conclusionTypeRule: { required: true, message: '请选择类型', trigger: 'change' },
      conclusionTextRule: { required: true, message: '请输入依据本次检查提供健康指导建议', trigger: 'blur' },
      dialog: {
        one: false
      },
    }
   }



methods: {
      // 查看报告
    async getSendReportPop (row) {
      this.dialog.one = true
      this.getSendReportData.report.ossFileUploads = []
      this.getSendReportData.report.ossPDFUploads = []
      this.tableItem = row
      this.conclusionForm = JSON.parse(JSON.stringify(row))
      const id = this.tableItem.id
      const res = await getScreeningFileList(id, 'report')
      const reportRes = res.data
      if (reportRes && reportRes.length > 0) {
        this.getSendReportData.report.itemId = reportRes[0].dataId
        reportRes.forEach((item) => {
          if (item.filePath.indexOf('.pdf') > -1 || item.filePath.indexOf('.PDF') > -1) {
            // pdf
            this.getSendReportData.report.ossPDFUploads.push(item)
          } else {
            // image
            this.getSendReportData.report.ossFileUploads.push(item)
          }
        })
      }
      // 如果“筛查小结”的类型是文件类
      if (this.conclusionForm.screenConclusionType === 1) {
        this.getConclusionInfo() // 获取文件的详情
      }
    },
    // 根据筛查小结类型获取文件数据
    async getConclusionInfo () {
      const id = this.tableItem.id
      this.getSendReportData.conclusion.ossUploads = []
      const res = await getScreeningFileList(id, 'conclusion')
      const conclusionRes = res.data
      if (conclusionRes && conclusionRes.length > 0) {
        this.getSendReportData.conclusion.itemId = conclusionRes[0].dataId
        conclusionRes.forEach((item) => {
          this.getSendReportData.conclusion.ossUploads.push(item)
        })
      }
    },
    // 弹窗确定
    handlerSend () {
      const report = [...this.getSendReportData.report.ossFileUploads, ...this.getSendReportData.report.ossPDFUploads]
      const conclusion = [...this.getSendReportData.conclusion.ossUploads]
      // 当筛查小结类型切换到文字并操作确定操作时,将筛查小结的deleted标识 都至为1 表示需要删除的数据
      const noUseConclusion = this.getSendReportData.conclusion.ossUploads.map(item => {
        return {
          ...item,
          deleted: 1
        }
      })
      if (report.length === 0) {
        this.$message.error('请至少上传一张图片或一个PDF文件')
        return
      }
      if (this.conclusionForm.screenConclusionType === 1 && conclusion.length === 0) {
        this.$message.error('请上传总检报告文件')
        return
      }
      this.$refs.conclusionForm.validate(async valid => {
        if (valid) {
          const options = {
            itemId: this.tableItem.id,
            // 类型是文件类 需要上传筛查小结的文件
            ossFileUploads: this.conclusionForm.screenConclusionType === 1 ? [...report, ...conclusion] : [...report, ...noUseConclusion],
            screenConclusionType: this.conclusionForm.screenConclusionType,
            screenConclusionText: this.conclusionForm.screenConclusionType === 2 ? this.conclusionForm.screenConclusionText : ''
          }
          const res = await sendScreeningFile(options)
          if (res.code === 200) {
            this.$message.success('操作成功')
            this.dialog.one = false
          }
          this.getTableList()
        }
      })
    },
    // 取消上传
    handlerClose () {
      this.dialog.one = false
      // 取消时恢复筛查小结的初始状态
      this.conclusionForm.screenConclusionType = this.tableItem.screenConclusionType
    }
}
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
对于封装 Element 组件,你可以按照以下步骤进行: 1. 创建一个独立的组件文件:在你的项目中创建一个新的组件文件,命名为`ElementWrapper.vue`(或其他你喜欢的名字)。 2. 引入 Element UI 库:在组件文件中引入 Element UI 库,通常使用以下代码: ```javascript import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; ``` 3. 注册组件:在组件文件中注册 Element UI 组件,你可以全局注册或局部注册。全局注册可以在任何地方使用该组件,而局部注册只能在当前组件内使用。以下是一个全局注册的示例: ```javascript Vue.use(ElementUI); ``` 4. 编写组件模板:在组件文件中编写 Element UI 组件的模板代码,可以参考官方文档来使用不同的组件。例如,创建一个包含按钮和表单的示例模板: ```html <template> <div> <el-button type="primary">Primary Button</el-button> <el-form> <!-- 表单内容 --> </el-form> </div> </template> ``` 5. 编写组件逻辑:根据需要,在组件文件中编写相关的逻辑代码。例如,处理按钮点击事件或表单提交事件等。 6. 导出组件:最后,在组件文件中导出该组件,以便在其他地方引用。以下是一个导出的示例: ```javascript export default { name: 'ElementWrapper', // ... }; ``` 完成上述步骤后,你就可以在其他组件中使用封装好的 Element 组件了。只需要在其他组件中引入`ElementWrapper.vue`文件,并在模板中使用`<element-wrapper></element-wrapper>`标签即可。记得确保 Element UI 库已经安装并配置正确。希望这些步骤对你有帮助!如果有任何问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学不会•

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值