1. 程式人生 > >vue元件系列2、拖放上傳

vue元件系列2、拖放上傳

開發十年,就只剩下這套架構體系了! >>>   

直接上原始碼,就是樣式不太好看,但是該有的功能都有啦

 <template>
  <div
    class="pre_upload"
    @drop="okdrop($event)"
    @dragover="allowDrop($event)"
  >
    <div class="pre_leve_one"></div>
    <div class="pre_leve_two">
      <h4>請把檔案拖放到這裡來</h4>
      <div
        di="files_data"
        class="pre_files_data"
        v-show="show_tab"
      >
        <table class="pre_dataintable">
          <thead>
            <tr>
              <th>序號</th>
              <th>名稱</th>
              <th>型別</th>
              <th>Y/N</th>
              <th>大小</th>
              <th>進度</th>
              <th>操作</th>
            </tr>
          </thead>
          <tbody>
            <tr
              v-for="(item,index) in pre_flies"
              :key="index"
            >
              <td>{{item.id}}</td>
              <td
                class="pre_tab_name"
                v-on:mousemove="lookImage(item)"
                v-on:mouseout="closeImage(item)"
              >{{item.name}}</td>
              <td>{{item.type}}</td>
              <td>{{item.flag}}</td>
              <td>{{item.size}}&nbsp;KB</td>
              <td>{{item.up}}</td>
              <td>
                <button
                  class="pre_btn_canle"
                  @click="del_files(item.id)"
                >取消上傳</button>
              </td>
            </tr>
          </tbody>
        </table>
        <div>
          <button
            class="pre_btn_del_all"
            @click="canle_all"
          >全部取消</button>&nbsp;&nbsp;
          <button
            class="pre_btn_up"
            @click="submit_files"
          >上傳</button>
        </div>
      </div>

      <!-- 使用畫布驗證上傳圖片轉換是否正確  -->
      <!-- <p>畫布:</p>
      <canvas
        id="myCanvas"
        width="500"
        height="300"
        style="border:1px solid #d3d3d3;background:#ffffff;"
      >
      Your browser does not support the HTML5 canvas tag.
      </canvas>-->
      <!-- 畫布驗證過程有非同步 還是img直接 -->
      <div
        class="pre_show_img"
        v-show="show_img"
      >
        <img :src="imgsrc">
      </div>

    </div>
  </div>
</template> 

<script>
/*
名稱:拖放上傳元件
日期:2019-03-14
作者:hj
目標:
1、將拖放的檔名稱展示出來:拖放過來的有可能是一堆檔案和資料夾混合 當放置被拖資料時,會發生 drop 事件。
2、顯示上傳檔案的進度
3、最好可以支援預覽(只可以圖片預覽)

*/

import { base_encode } from "@/utils/base64.js";
import { GetShort } from "@/utils/localstore.js";

export default {
  name: "pre_uploadfile2",
  data() {
    return {
      pre_flies: [],
      exist_data: [],
      show_tab: false,
      show_img:false,
      imgsrc: ""
    };
  },  
  methods: {
    okdrop: async function(ev) {
      // 呼叫 preventDefault() 來避免瀏覽器對資料的預設處理(drop 事件的預設行為是以連結形式開啟)
      ev.preventDefault();
      // 通過 dataTransfer.getData("Text") 方法獲得被拖的資料。該方法將返回在 setData() 方法中設定為相同型別的任何資料。
      // var data=ev.dataTransfer.getData("Text");
      var back_data = [],
        ok_data = [];
      back_data = ev.dataTransfer.files; //獲取檔案           
      for (var i = 0; i < back_data.length; i++) {
        var td = {};
        td.id = i + 1;
        td.name = back_data[i].name;
        td.type = back_data[i].type;
        // td.size=Math.round(Number(back_data[i].size)/1024);
        td.size = (Number(back_data[i].size) / 1024).toFixed(0);
        if (
          String(td.type)
            .toLowerCase()
            .indexOf(".exe") > 0
        ) {
          td.flag = "NO";
        } else {
          td.flag = "YES";
        }
        td.up = 0 + "%";
        td.filedata = await this.convertFileToString(back_data[i]);        
        ok_data[i] = td;
      }
      var j = 0;
      j = this.exist_data.length; 
      if (j > 0) {
        for (var i = 0; i < ok_data.length; i++) {
          this.exist_data[j] = ok_data[i];
          j += 1;
        }
        // 如果是多次拖放,需要進行二次整理
        var temp_d=[];
        for(var i=0;i<this.exist_data.length;i++){
          var temp_o={};
          temp_o.id = i + 1;
          temp_o.name = this.exist_data[i].name;
          temp_o.type = this.exist_data[i].type;
          temp_o.size = this.exist_data[i].size;
          temp_o.flag = this.exist_data[i].flag;
          temp_o.up = this.exist_data[i].up;
          temp_o.filedata= this.exist_data[i].filedata;
          temp_d[i]=temp_o;
        }
        this.pre_flies=temp_d;
      } else {
        this.exist_data = ok_data;
        this.pre_flies = this.exist_data;
      }
      
     
      this.show_tab = true;
      // var tf=document.getElementById("files_data");
      // tf.target.appendChild(files);
    },
    allowDrop: function(ev) {
      ev.preventDefault();
    },
    convertFileToString: function(tempfile) {
      return new Promise(resolve => {
        var tf = new FileReader();
        tf.readAsDataURL(tempfile);
        tf.onload = function() {
          resolve(this.result);
        };
      });
    },
    submit_files: async function() {
      this.exist_data = [];
      for (var i = 0; i < this.pre_flies.length; i++) {
        /*這塊應該還可以用vuex 封裝*/ 
        var postdata = "";
        postdata =
          '{"action":"data_upfile_db","user_no":"' +
          GetShort("userno") +
          '","upfile_name":"' +
          this.pre_flies[i].name +
          '","upfile_type":"' +
          this.pre_flies[i].type +
          '","upfile_size":"' +
          this.pre_flies[i].size +
          '","upfile_data":"' +
          this.pre_flies[i].filedata +
          '"}';
        postdata =
          '{"method":"File_load","data":"' + base_encode(postdata) + '"}';
        var tp = this.pre_flies[i];
        await this.updatabyquere(postdata, tp);
      }
    },
    updatabyquere: function(postdata, tp) {
      this.$postfile(
        "/Data_Back",
        postdata,
        res => {
          var loaded = 0,
            total = 0;
          loaded = res.loaded;
          total = res.total;
          this.$nextTick(() => {
            // console.log(tp);
            tp.up = ((loaded / total) * 100).toFixed(2) + " %";
          });
        }
      ).then(res => {
        try {
          res = JSON.parse(res);
          res = res.data;
          if (res.status == 1) {
            tp.up = "上傳成功";
          } else {
            tp.up = "上傳失敗";
          }
        } catch (ex) {
          tp.up = "上傳失敗";
        }
      });
    },
    del_files: function(id) {
      var data = []; 
      var j=0;
      for (var i = 0; i < this.pre_flies.length; i++) {        
        if (this.pre_flies[i].id != id) {
          data[j] = this.pre_flies[i];
          j+=1;
        }
      }
      this.pre_flies = data;
      if (this.pre_flies.length == 0) {
        this.show_tab = false;
      }
    },
    canle_all: function() {
      this.pre_flies = [];      
      this.exist_data = [];
      this.show_tab = false;
    },
    lookImage:function(parm){
      console.log('進來'+parm.name);
      if (/\.(gif|jpg|jpeg|png|GIF|JPG|PNG|ico)$/.test(parm.name)) {
        this.imgsrc=parm.filedata;
        this.show_img=true;
      }
    },
    closeImage:function(parm){
      console.log('出去');
      this.show_img=false;
    }
  }
};
</script>


<style scoped>
.pre_upload {
  width: 100%;
  min-height: 200px;
  height: 100%;
  background-color: azure;
  text-align: center;
  /* padding: 10px 20px 10px 20px; */
}
.pre_leve_one {
  height: 5px;
}

.pre_leve_two {
  /* padding: 5px; */
  margin: 15px;
  margin-top: 15px;
  border: 1px solid #191970;
  min-height: 200px;
  height: auto;
}

.pre_files_data {
  width: 100%;
  min-height: 200px;
  height: auto;
  /* padding: 10px 20px 10px 20px; */
}

.pre_files_data > ul {
  list-style: none;
}
.pre_files_data > ul > li {
  border: 1px solid black;
}
.pre_files_data > ul > li > span {
  margin-left: 5px;
}

.pre_dataintable {
  margin-top: 15px;
  border-collapse: collapse;
  border: 1px solid #aaa;
  width: 95%;
  /* padding 沒有作用 */
  /* padding: 0px 5px 10px 5px; */
  position: relative;
  left: 2%;
}
.pre_dataintable th {
  vertical-align: baseline;
  padding: 5px 15px 5px 6px;
  background-color: #c1ffc1;
  border: 1px solid #3f3f3f;
  text-align: left;
  color: #000000;
  font-size: 16px;
  font-weight: bolder;
}
.pre_dataintable td {
  vertical-align: text-top;
  padding: 6px 15px 6px 6px;
  border: 1px solid #aaa;
}
.pre_dataintable tr:nth-child(odd) {
  background-color: #f5f5f5;
}
.pre_dataintable tr:nth-child(even) {
  background-color: #fff;
}

.pre_tab_name {
  cursor: pointer;
}
.pre_tab_name:hover {
  cursor: pointer;
  background-color: #aaa;
}
/* 全部取消按鈕 */
.pre_btn_del_all {
  color: crimson;
  font-weight: bold;
  font-size: 16px;
  width: 100px;
  height: 30px;
}
/* 上傳按鈕 */
.pre_btn_up {
  color: chartreuse;
  font-weight: bold;
  font-size: 16px;
  width: 100px;
  height: 30px;
}
/* 刪除按鈕 */
.pre_btn_canle {
  color: crimson;
  font-weight: bold;
  font-size: 16px;
  width: 80px;
  height: 25px;
}
.pre_show_img {
  width: 400px;
  height: 400px;
  text-align: center;
  margin-top: -40px;
  /* background-color: #000000; */
}
.pre_show_img > img {
  width: auto;
  height: 100%;
}
</style>