Vue页面内公共的多类型附件图片上传区域并适用折叠面板

在前端项目中,附件上传是很常用的功能,几乎所有的app相关项目中都会使用到,一般在选择使用某个前端UI框架时,可以查找其内封装好的图片上传组件,但某些情况下可能并不适用于自身的项目需求,本文中实现的附件上传区域支持超多类型附件分类型上传,并且可根据特定条件具体展示某些类型的附件上传,本文中是直接摘自具体的页面,后面会抽时间单独封装出来一个附件上传的组件。

 

一、Vue页面内附件展示区域代码

 1 <div class="retuinfo">
 2           <div class="theadInfo-headline">
 3             <span></span>
 4             {{FileDivName}}
 5           </div>
 6           <Collapse v-model="defaultCollapse">
 7             <Panel v-for="(item,pngIndex) in pngFileArray" v-bind:key="pngIndex" :name="item.num" v-show="item.isshow">
 8               {{item.name}}
 9               <div class="obsfilesdiv" slot="content">
10                 <div v-for="(obs,index) in item.files" v-bind:key="index" class="obsfileslist">
11                   <input ref="fileImg" type="file" accept="image/*;capture=camera" style="display: none;"
12                     @change="setObsFile(item.num,1,obs.FileType,obs.Num,obs.Code)">
13                   <label style="color:#6d7180; font-size: 20px;">{{obs.FileType}}<span style="color:red;"
14                       v-show="obs.FileType!='其他'">*</span></label>
15                   <ul class="obsfilesul">
16                     <li v-for="(objitem,objindex) in obs.FileObj" v-bind:key="objindex">
17                       <img :src="objitem.imgurl ? objitem.imgurl : fileUrl"
18                         @click="showObsFiles(obs.FileFlag,objitem.imgurl)" />
19                       <img src="../../../img/other/wrong.png" v-show="objitem.IsCanEdit" class="wrong_class"
20                         @click="deleteObsFlie(item.num,index,objindex,objitem.imgid,objitem.imgurl)" />
21                     </li>
22                     <li style="border: 4px solid #f3f3f3;" @click="PlusClick(obs.FileType,obs.FileFlag,obs.Num)">
23                       <img src="../../../img/icon-adds.png" alt="" />
24                     </li>
25                     <div style="clear:both;"></div>
26                   </ul>
27                 </div>
28               </div>
29             </Panel>
30           </Collapse>
31         </div>
32         <div class="modal" v-show="viewBigImg">
33             <div class="img-view-modal" style="text-align: right;">
34                 <img :src="viewImgURL" style="width: 100%;" @click="hideShow(0)">
35                 <Icon type="md-close" style="margin-right: 20px;" size='20' @click="hideShow(0)" />
36             </div>
37         </div>
38       </div>
Vue项目引入了以下UI框架:(若想拿来即用 需要先在main.js中引入)
IView、MintUI、Vant 此段代码只要确保引入IView即可正常使用

二、数据绑定设计

具体的不详细展开说,数组与通过属性控制,很好理解。

pngFileArray: [{
            num: '0',
            name: '整车',
            isshow: localStorage.getItem("RoleName").indexOf('铭牌质检员') != -1 ? true : false,
            files: [ //FileFlag://1:图片;2:视频  3.其他
              {
                FileType: '整车铭牌图片',
                Code: '201',
                Num: 0,
                FileFlag: 1,
                FileObj: [],
                IsNoFile: true
              },
              {
                FileType: '车架VIN图片',
                Code: '207',
                Num: 1,
                FileFlag: 1,
                FileObj: [],
                IsNoFile: true
              },
              {
                FileType: '终端图片',
                Code: '301',
                Num: 2,
                FileFlag: 1,
                FileObj: [],
                IsNoFile: true
              }
            ]
          },
          {
            num: '1',
            name: '里程',
            isshow: localStorage.getItem("RoleName").indexOf('客户经理') != -1 ? true : false,
            files: [{
                FileType: '里程表照片',
                Code: '701',
                Num: 3,
                FileFlag: 1,
                FileObj: [],
                IsNoFile: true
              }
            ]
          }
        ],

 

三、绑定的方法

1.图片加载方法:

 1 //获取图片列表
 2       getImageList() {
 3         this.$indicator.open({
 4           text: '图片加载中...',
 5           spinnerType: 'snake'
 6         });
 7         let _this = this;
 8         let downRequest ={
 9             'crm_vin': this.parms.crm_vin,
10             'crm_vehiclenumber': this.parms.crm_vehiclenumber
11           };
12         let imgListParams = {
13           "ImageDownRequest": JSON.stringify(downRequest),
14           "username": localStorage.getItem("usernameone"),
15           "password": localStorage.getItem("password")
16         };
17         console.log("获取图片列表参数:", imgListParams);
18         _this.$ajax.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded;'; //配置请求头
19         this.$ajax.post(this.imageListUrl, this.$qs.stringify(imgListParams)).then(resdata => {
20           _this.$indicator.close();
21           console.log("获取到的图片列表数据:", resdata);
22           let data = resdata.data;
23           console.log("转换后的图片列表数据:", data);
24           if (resdata.status != 200) {
25             _this.$toast({
26               message: '获取图片列表失败!',
27               duration: 3000
28             });
29             return;
30           }
31           //先清空原有的图片列表
32           _this.pngFileArray.forEach((rr,index,array) =>{
33             for(var file=0;file<rr.files.length;file++){
34               _this.pngFileArray[index].files[file].FileObj = [];
35               _this.pngFileArray[index].files[file].IsNoFile = true;
36             }
37           });
38           //将图片列表写入页面各图片分类区域
39           for(var i=0;i<data.length;i++){
40             _this.pngFileArray.forEach((rr,index,array) =>{
41               for(var file=0;file<rr.files.length;file++){
42                 if(data[i].crm_imagetypeno==rr.files[file].Code){
43                   let putparm = {
44                     "IsCanEdit":false,
45                     "imgid": data[i].crm_careimageId,
46                     "imgurl": data[i].ImageUrl
47                   };
48                   _this.pngFileArray[index].files[file].FileObj.push(putparm);
49                   _this.pngFileArray[index].files[file].IsNoFile = false;
50                 }
51               }
52             });
53 
54           }
55         }).catch(function(error) {
56           _this.$indicator.close();
57           _this.$toast({
58             message: error,
59             duration: 3000
60           });
61         });
62       },

 

2.图片展示方法

showObsFiles(type, url) { //展示图片或视频
        console.log("展示附件:" + type);
        if (type == 1) { //图片
          this.viewBigImg = true;
          this.viewImgURL = url;
        } else { //文件
          this.$messagebox.alert("不支持查看文件,请到PC端操作!", "提示");
          return;
        }
      },

 

3.上传图片相关方法 

(最开始设计的是支持图片、视频和其他类型文件等上传,项目中已实现,本文中不做拓展)

  1 PlusClick(type, flag, num) {
  2         console.log("当前附件类型:" + type);
  3         console.log("当前附件序号:" + num);
  4         this.currentFileType = type;
  5         if (flag == 1) { // 图片上传
  6           this.$refs.fileImg[num].dispatchEvent(new MouseEvent('click'));
  7         } else if (flag == 2) { // 视频上传
  8           this.$refs.fileVideo[num].dispatchEvent(new MouseEvent('click'));
  9         } else { // 其他类型文件
 10           this.$refs.filElem[num].dispatchEvent(new MouseEvent('click'));
 11         }
 12       },
 13 setObsFile(classify, type, obsFileType, num, code) { //保存图片到crm中
 14         var _this = this;
 15         var inputFile; //文件流
 16         console.log("图片大分类:" + classify + " " + obsFileType + " " + num) + " 图片编码:" + code;
 17         if (type == 1) {
 18           inputFile = this.$refs.fileImg[num].files[0];
 19           this.$refs.fileImg[num].value = '';
 20         }
 21         var fileName = inputFile.name;
 22         if (!inputFile) {
 23           return;
 24         }
 25         if (inputFile.type == 'image/jpg' || inputFile.type == 'image/jpeg' || inputFile.type == 'image/png' ||
 26           inputFile.type ==
 27           'image/gif') {} else {
 28           this.$messagebox.alert("请上传图片", "提示");
 29           return;
 30         }
 31         _this.$indicator.open({
 32           text: '文件上传中,请稍候...',
 33           spinnerType: 'snake'
 34         });
 35         //图片压缩与转换成base64文件流
 36         var reader = new FileReader();
 37         reader.readAsDataURL(inputFile);
 38         reader.onloadend = function(e) {
 39           let result = this.result;
 40           console.log('********未压缩前的图片大小******** :' + result.length / 1024)
 41           _this.pulic.dealImage(result, {}, function(base64) {
 42             console.log('********压缩后的图片大小******** :' + base64.length / 1024)
 43             _this.putObsFile(classify, fileName, base64, obsFileType, code);
 44           });
 45           //reader.result.substring(this.result.indexOf(',')+1);
 46           // 'data:image/png;base64,'+reader.result
 47         }
 48       },
 49       putObsFile(classify, fileName, base64, obsFileType, code) { //抽出公共上传图片文件方法
 50         var _this = this;
 51         let usernameone = this.$Base64.encode("administrator");
 52         let password = this.$Base64.encode("pass@word1");
 53         let parmsImages = {
 54           crm_newenergyid: localStorage.getItem("crm_newenergyid"),
 55           vin: _this.parms.crm_vin,
 56           crm_vehiclenumber: _this.parms.crm_vehiclenumber,
 57           CareType: code,
 58           CreateBy: localStorage.getItem("SystemUserId"),
 59           ImageStr: base64.split(",")[1],
 60           username: usernameone,
 61           password: password
 62         }
 63         let parms = {
 64           ImageMessage: JSON.stringify(parmsImages)
 65         }
 66         console.log(JSON.stringify(parmsImages));
 67         console.log(JSON.stringify(parms));
 68         _this.$ajax.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded;'; //配置请求头
 69         _this.$ajax.post(_this.imageSaveUrl, _this.$qs.stringify(parms))
 70           .then(resdata => {
 71             _this.$indicator.close();
 72             console.log("接口响应数据:", resdata);
 73             let data = resdata.data;
 74             console.log("转换后的响应数据:", data);
 75             if (resdata.status != 200) {
 76               _this.$toast({
 77                 message: '保存失败!接口调用异常',
 78                 duration: 3000
 79               });
 80               return;
 81             }
 82             //将上传成功后的图片url回写到页面的图片分类url中
 83             console.log("当前分类下的所有图片类型:" + JSON.stringify(_this.pngFileArray[parseInt(classify)].files));
 84             for (var i = 0; i < _this.pngFileArray[parseInt(classify)].files.length; i++) { //遍历当前分类下的图片类型数组  并赋值后台返回的数据
 85               if (obsFileType == _this.pngFileArray[parseInt(classify)].files[i].FileType) {
 86                 //设置图片文件路径等 putparm
 87                 let putparm = {
 88                   "IsCanEdit":true,
 89                   "imgid": data.crm_careimageId,
 90                   "imgurl": data.ImageUrl
 91                 };
 92                 _this.pngFileArray[parseInt(classify)].files[i].FileObj.push(putparm);
 93                 _this.pngFileArray[parseInt(classify)].files[i].IsNoFile = false;
 94               }
 95             }
 96             _this.$messagebox.alert("附件上传成功", "提示");
 97           }).catch(err => {
 98             console.log(JSON.stringify(err));
 99             _this.$toast({
100               message: '上传失败',
101               duration: 1500
102             });
103             _this.$indicator.close();
104           });
105       },

 

 

4.删除图片方法

(本文中是只有未提交的图片可删除,若已提交过的图片即页面初始加载获取到的图片不可以删除)

 1 deleteObsFlie(classify,num,index,id,url) { //删除附件
 2         var _this = this;
 3         this.$messagebox.confirm('确定删除该图片吗?', "确认").then(action => {
 4           var del_param = {
 5             "id": id,
 6             "url": url
 7           };
 8           _this.$indicator.open({
 9             text: '删除图片中,请稍候...',
10             spinnerType: 'snake'
11           });
12           _this.$ajax.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded;'; //配置请求头
13           _this.PromiseCall(_this.DelImgFilesURL, _this.$qs.stringify(del_param))
14             .then(data => {
15               _this.$indicator.close();
16               console.log(JSON.stringify(data));
17               if (data.status != 200) {
18                _this.$messagebox.alert("删除图片失败", "提示");
19                return;
20               }
21               _this.pngFileArray[parseInt(classify)].files[num].FileObj.splice(index, 1);
22               _this.$toast({
23                 message: '删除图片成功',
24                 duration: 1500
25               });
26             }).catch(err => {
27               _this.doCatch(err);
28               _this.$toast({
29                 message: '删除图片失败'+err,
30                 duration: 1500
31               });
32               _this.$indicator.close();
33             });
34         });
35       },

 

四、CSS样式

.retuinfo {
    width: 96%;
    height: auto;
    margin-top: 20px;
    margin-left: 2%;
    background-color: #F5F7FA;
    border-radius: 15px;
  }
.theadInfo-headline {
    width: 100%;
    height: 80px;
    background: #F3F3F3;
    display: flex;
    padding-left: 30px;
    align-items: center;
    font-size: 28px;
    color: #666666;
    border-radius: 15px;
  }
  .theadInfo-headline span {
    width: 6px;
    height: 32px;
    background: #5576AB;
    border-radius: 3px;
    margin-right: 10px;
  }
.ivu-collapse-header {
    height: 40px;
    align-items: center;
    display: flex;
  }
.obsfilesdiv {
    width: 100%;
    height: auto;
    margin-top: .5rem;
    margin-bottom: 50px;
}
.obsfileslist {
    width: 100%;
    height: auto;
    padding: 0.5rem 0.5rem;
    background: #fff;
}
.obsfilesul {
    width: 100%;
    height: auto;
    padding-bottom: 8px;
}
.obsfilesul li {
    width: 120px;
    height: 120px;
    float: left;
    margin-top: .3rem;
    overflow: hidden;
    margin-right: .3rem;
    border: none;
}
.obsfilesul li img {
    width: 100%;
    height: 100%;
}
.imglist {
    width: 100%;
    margin-top: .5rem;
    margin-bottom: 6rem;
}
.modal {
    background-color: #A9A9A9;
    position: fixed;
    z-index: 99;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    padding-top: 4rem;
    /*opacity: 0.5;*/
    align-items: center;
    /*定义body的元素垂直居中*/
    justify-content: center;
    /*定义body的里的元素水平居中*/
}
.modal img {
    animation-name: zoom;
    animation-duration: 0.6s;
    display: block;
    padding: 10px;
    margin: auto;
    max-width: 100%;
    max-height: 100%;
    box-shadow: 0 2px 6px rgb(0, 0, 0, 0), 0 10px 20px rgb(0, 0, 0, 0);
    border-radius: 12px;
    border: 1px solid white;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
}
.showname {
    width: 100px;
    height: 60px;
    position: relative;
    top: -4.5rem;
    white-space: normal;
    word-break: break-all;
    word-wrap: break-word;
}
.wrong_class {
    width: 30% !important;
    height: 30% !important;
    position: relative;
    top: -3.8rem;
    left: 2.6rem;
}
.wrongs_class {
    width: 4% !important;
    height: 4% !important;
    position: relative;
    /*top: -5.2em;*/
    left: 0.5rem;
}
View Code

 

最后附上实际效果图:

 

 

 

 

 

 

 

posted @ 2021-12-23 14:17  流浪阿丁  阅读(1167)  评论(1编辑  收藏  举报