vue 批量上传多张图片

297 阅读4分钟
 <el-upload ref="upload" action="#" :auto-upload="false" list-type="picture-card" :http-request="uploadFile" accept="image/png, image/jpeg" multiple :limit="9">
      <i class="el-icon-plus"></i>
 </el-upload>
 <el-progress :percentage="percent" v-if="percent > 0" />
 <el-button @click="submitUpload">发布</el-button>
data
data() {
    return {
      formData: {},
      percent: 0, //进度条
    }
}
  
methods
// 绑定在http-request,覆盖上传事件
    uploadFile(file) {
      this.formData.append("image[]", file.file);
      console.log(file, "0000000");
    },
    // 点击按钮触发
    async submitUpload() {
      this.formData = new FormData();
      this.$refs.upload.submit();
      const res = await CheckUpload(this.formData, this.onProcess);
      console.log(res.data);
      if (res.status !== 200) {
        return this.$message.error("发布失败!");
      }
      this.$refs.upload.clearFiles();
      this.$message.success("发布成功!");
      setTimeout(() => {
        this.percent = 0;
      }, 700);
    },
    onProcess(e) {
      const { loaded, total } = e;
      const uploadPrecent = ((loaded / total) * 100) | 0;
      console.log(uploadPrecent);
      this.percent = uploadPrecent;
    },
封装上传api
image.png
export const CheckUpload = (formData, callback1) => {
  // const data = vm.$qs.stringify(obj)
  return request({
    url: "index/upload",
    method: "POST",
    data: formData,
    headers: {
      'Content-Type': 'multipart/form-data'
      // "Content-Type":"application/x-www-form-urlencoded;charset-utf-8"
    },
    onUploadProgress: function (progressEvent) { //原生获取上传进度的事件
      if (progressEvent.lengthComputable) {
        //属性lengthComputable主要表明总共需要完成的工作量和已经完成的工作是否可以被测量
        //如果lengthComputable为false,就获取不到progressEvent.total和progressEvent.loaded
        callback1(progressEvent);
      }
    },
  })
}

dcc8f81b68c9a8c26e18eb5b5ce8a52.png

完整代码
<template>
  <Init>
    <div class="title">
      <div id="size-select">设备状态分布看板</div>
      <el-button @click.prevent.stop="guide" class="el-icon-s-opportunity" type="text"></el-button>
      <span id="hamburger-container">当前所有部门的设备状态分布情况</span>
      <span style="margin-left: 200px">
        <el-popover placement="bottom" width="800" trigger="click">
          <div class="top">
            <el-form :inline="true" :model="params" label-width="120px" class="formtop">
              <div class="side">
                <el-form-item>
                  <el-select v-model="params.large_code" placeholder="请选择设备大类" size="small" clearable>
                    <el-option v-for="item in $store.state.publicInterface.category" :label="item.title" :value="item.code" />
                  </el-select>
                </el-form-item>
                <el-form-item>
                  <Mytooltip :content="depart_name">
                    <el-cascader
                      @change="search_getCascader_name"
                      change-on-select
                      v-model="params.departmentId"
                      filterable
                      :options="departArray"
                      ref="cascader"
                      placeholder="请选择部门"
                      clearable
                      :props="optionProps"
                      size="small"
                    >
                      <template slot-scope="{ node, data }">
                        <span>{{ data.title }}</span>
                        <span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
                      </template>
                    </el-cascader>
                  </Mytooltip>
                </el-form-item>
                <el-form-item>
                  <el-select
                    v-model="params.duty_man"
                    filterable
                    remote
                    clearable
                    placeholder="责任人"
                    :remote-method="remoteMethod"
                    :loading="selecloading"
                    size="small"
                  >
                    <el-option v-for="item in options" :key="item.value" :label="item.name" :value="item.name"> </el-option>
                  </el-select>
                </el-form-item>
                <el-button @click="handle_filter" type="primary">筛选</el-button>
              </div>
            </el-form>
          </div>
          <el-button id="breadcrumb-container" slot="reference" class="el-icon-coin" type="text">筛选</el-button>
        </el-popover>
      </span>
    </div>
    <div class="overflow">
      <div class="content">
        <div class="left" id="header-search">
          <div id="echarts"></div>
        </div>
        <div id="screenfull" class="right">
          <div class="item" v-for="(item, index) in matter" :key="index">
            <div class="matter">{{ item.title }}</div>
            <div class="num" :class="'num_color' + (index + 1)"><countTo :startVal="startVal" :endVal="item.value" :duration="2000" :decimals="0" /></div>
            <!-- <template v-if="index === 1">
              <div style="display: flex; margin-top: 15px">
                <el-button class="green-border" plain>正常: <countTo :startVal="startVal" :endVal="normal_num" :duration="2000" :decimals="0" /> </el-button>
                <el-button class="red-border" plain>异常:<countTo :startVal="startVal" :endVal="abnormal_num" :duration="2000" :decimals="0" /></el-button>
              </div>
            </template> -->
          </div>
        </div>
      </div>
    </div>

    <el-upload ref="upload" action="#" :auto-upload="false" list-type="picture-card" :http-request="uploadFile" accept="image/png, image/jpeg" multiple :limit="9">
      <i class="el-icon-plus"></i>
    </el-upload>
    <el-progress :percentage="percent" v-if="percent > 0" />
    <el-button @click="submitUpload">发布</el-button>
  </Init>
</template>

<script>
import * as echarts from "echarts";
import { get_BulletinBoard } from "@/api/dashboard";
import { bulletinBoard, Echarts_bulletinBoard } from "./utils/mapping";
import { CheckUpload, getDepart, getAllPerson } from "@/api/publicInterface.js";

import countTo from "vue-count-to";
import Driver from "driver.js"; // import driver.js
import "driver.js/dist/driver.min.css"; // import driver.js css
import steps from "./steps";

export default {
  name: "dashboard",
  components: {
    countTo,
  },
  data() {
    return {
      formData: {},
      percent: 0,
      startVal: 0,
      endVal: null,
      matter: [],
      normal_num: "", //正常
      abnormal_num: "", //异常
      echartsData: [],
      large_category_code: "",

      depart_name: "",
      selecloading: false,
      options: [],
      departArray: [],
      params: {
        large_code: "",
        departmentId: "",
        duty_man: "",
      },

      optionProps: {
        checkStrictly: true,
        value: "id",
        label: "title",
      },
      driver: null,
    };
  },

  async created() {
    this.init();
    const { data } = await getDepart();
    this.departArray = [...data];
  },

  mounted() {
    this.driver = new Driver({ popoverClass: "driverjs-theme" });
  },

  watch: {
    departmentId() {
      if (this.$refs.cascader) {
        this.$refs.cascader.dropDownVisible = false; //监听值发生变化就关闭它
      }
    },
    deep: true,
  },

  methods: {
    // 绑定在http-request,覆盖上传事件
    uploadFile(file) {
      this.formData.append("image[]", file.file);
      console.log(file, "0000000");
    },
    // 点击按钮触发
    async submitUpload() {
      this.formData = new FormData();
      this.$refs.upload.submit();
      const res = await CheckUpload(this.formData, this.onProcess);
      console.log(res.data);
      if (res.status !== 200) {
        return this.$message.error("发布失败!");
      }
      this.$refs.upload.clearFiles();
      this.$message.success("发布成功!");
      setTimeout(() => {
        this.percent = 0;
      }, 700);
    },
    onProcess(e) {
      const { loaded, total } = e;
      const uploadPrecent = ((loaded / total) * 100) | 0;
      console.log(uploadPrecent);
      this.percent = uploadPrecent;
    },

    guide() {
      this.driver.defineSteps(steps);
      this.driver.start();
    },

    initEcharts(ajaxdata) {
      var myChart = echarts.init(document.getElementById("echarts"));
      myChart.setOption(
        {
          tooltip: {
            trigger: "item",
          },
          legend: {
            bottom: "2%",
            left: "center",
          },
          // 配置
          series: [
            {
              // name: 'Access From', //指引线上的标题
              type: "pie",
              radius: ["50%", "65%"],
              center: ["50%", "43%"], //设置饼图位置 x轴占50%,Y轴占43%
              avoidLabelOverlap: false,
              label: {
                // 默认状态下的标签设置
                show: true,
                position: "outside",
                formatter: "{b}\n{d}%",
                fontSize: 12,
                fontWeight: "bolder",
              },
              /*
            在 ECharts 中,emphasis 是用于定义在元素(如图表系列中的数据项)受到强调时的显示样式和交互行为的配置项。
            通过设置 emphasis,可以自定义鼠标悬停或其他强调状态下的元素样式,例如鼠标悬停时的标签样式、高亮显示、阴影效果等。
            */
              emphasis: {
                position: "outside",
                formatter: "{b}\n{d}%",
                label: {
                  show: true,
                  fontSize: 14,
                  fontWeight: "600",
                },
              },
              // data: [
              //   { value: 4.04, name: "在用" },
              //   { value: 2.04, name: "闲置" },
              //   { value: 5.2, name: "待保养" },
              //   { value: 4.04, name: "报废" },
              //   { value: 1.04, name: "即将报废" },
              //   { value: 3.04, name: "待验收入库" },
              // ],
              data: ajaxdata,
              itemStyle: {
                //饼状图上的文本显示
                borderRadius: 10, //色块为倒圆角
                borderColor: "#fff", // 色块边为白色收边
                borderWidth: 1.5, //色块白色收边宽度
                label: {
                  fontSize: 12, //指引线文字大小
                  fontWeight: "bolder", //文字是否加粗
                },
              },
            },
          ],
        },
        true
      );
    },
    async init() {
      const { data } = await get_BulletinBoard(this.params);
      const matter = bulletinBoard(data);
      this.matter = [...matter];
      this.$nextTick(() => {
        this.initEcharts(Echarts_bulletinBoard(data));
      });
    },

    search_getCascader_name() {
      this.$nextTick(() => {
        this.depart_name = this.$refs.cascader.presentText;
      });
    },

    remoteMethod(query) {
      // 输入值发生变化时的回调函数
      if (query !== "") {
        this.selecloading = true;
        this.getRemote(query);
      } else {
        this.options = [];
      }
    },
    getRemote: _.debounce(function (query) {
      // 防抖,设置1300毫秒请求一次后台
      getAllPerson({
        code_name: query,
      })
        .then((res) => {
          this.selecloading = false;
          this.options = res.data;
        })
        .catch((err) => {
          this.selecloading = false;
        });
    }, 800),

    async handle_filter() {
      if (this.params.departmentId && Array.isArray(this.params.departmentId)) {
        this.params.departmentId = this.params.departmentId.join(",");
      }
      this.params.page = 1;
      this.init();
    },
  },
};
</script>

<style lang="scss" scoped>
/* 标题 */
.title {
  div {
    font-size: 20px;
    font-weight: 500;
    margin-bottom: 7px;
  }

  span {
    color: #888;
    font-size: 15px;
  }
}

/* echarts看板 */
.overflow {
  overflow: auto;

  .content {
    margin-top: 20px;
    height: 420px;

    border-radius: 15px;
    display: flex;
    min-width: 1280px;

    .left {
      width: 600px;
      background-color: #fff;
      border-radius: 15px;
      display: flex;
      flex-direction: column;
      margin-right: 12px;

      #echarts {
        height: 420px;

        border-radius: 15px;
        display: flex;
        justify-content: center;
        align-items: center;
      }
    }

    /* 6个小盒子 */
    .right {
      border-radius: 15px;
      display: grid;
      width: 100%;
      grid-template-columns: repeat(3, 1fr);
      grid-auto-rows: minmax(100px, auto);
      grid-column-gap: 20px;
      grid-row-gap: 20px;

      .item {
        border-radius: 15px;
        height: 200.5px;
        background-color: #fff;
        display: flex;
        justify-content: start;
        flex-direction: column;
        align-items: center;

        .matter {
          font-size: 15px;
          color: #888;
          padding: 30px 0 40px 0;
        }

        .green-border {
          border: 1px solid yellowgreen;
          color: yellowgreen;
        }

        .red-border {
          border: 1px solid red;
          color: red;
        }

        .num_color1,
        .num_color2,
        .num_color3,
        .num_color4,
        .num_color5,
        .num_color6 {
          font-size: 30px;
        }

        .num_color1 {
          color: #93d2f3;
        }

        .num_color2 {
          color: green;
        }

        .num_color3 {
          color: red;
        }

        .num_color4 {
          color: #bd3124;
        }

        .num_color5 {
          color: #fcca00;
        }

        .num_color6 {
          color: #737373;
        }
      }
    }
  }
}
.driver-popover.driverjs-theme {
  background-color: #fde047;
  color: #000;
}

.driver-popover.driverjs-theme .driver-popover-title {
  font-size: 20px;
}

.driver-popover.driverjs-theme .driver-popover-title,
.driver-popover.driverjs-theme .driver-popover-description,
.driver-popover.driverjs-theme .driver-popover-progress-text {
  color: #000;
}

.driver-popover.driverjs-theme button {
  flex: 1;
  text-align: center;
  background-color: #000;
  color: #ffffff;
  border: 2px solid #000;
  text-shadow: none;
  font-size: 14px;
  padding: 5px 8px;
  border-radius: 6px;
}

.driver-popover.driverjs-theme button:hover {
  background-color: #000;
  color: #ffffff;
}

.driver-popover.driverjs-theme .driver-popover-navigation-btns {
  justify-content: space-between;
  gap: 3px;
}

.driver-popover.driverjs-theme .driver-popover-close-btn {
  color: #9b9b9b;
}

.driver-popover.driverjs-theme .driver-popover-close-btn:hover {
  color: #000;
}

.driver-popover.driverjs-theme .driver-popover-arrow-side-left.driver-popover-arrow {
  border-left-color: #fde047;
}

.driver-popover.driverjs-theme .driver-popover-arrow-side-right.driver-popover-arrow {
  border-right-color: #fde047;
}

.driver-popover.driverjs-theme .driver-popover-arrow-side-top.driver-popover-arrow {
  border-top-color: #fde047;
}

.driver-popover.driverjs-theme .driver-popover-arrow-side-bottom.driver-popover-arrow {
  border-bottom-color: #fde047;
}
</style>

<style lang="scss" scoped>
body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  row-gap: 1em;
  height: 100vh;
  margin: 0;
}
.btn {
  --background: mediumseagreen;
  width: 10em;
  padding: 0.5em 0.7em;
  cursor: pointer;
  background: var(--background);
  color: #fff;
  border: 0;
  border-radius: 30px;
  transition: all 0.3s;
}
.btn:focus {
  outline: var(--background) solid 1px;
}
.btn:active {
  outline-offset: 1px;
  outline-width: 4px;
}
.btn:hover {
  --background: #24864f;
}
::v-deep .el-upload--picture-card,
::v-deep .el-upload-list--picture-card .el-upload-list__item {
  width: 100px !important;
  height: 100px !important;
  line-height: 100px;
}
</style>