实现生成二维码,在table显示,图片预览可下载

utils/images/downLoadRemoteFile.js

/**
 * 获取 blob 实现不跳转下载
 * @param  {String} url 目标文件地址
 * @return {Promise}
 */
const getBlob = (url) => {
  return new Promise(resolve => {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.responseType = 'blob';
    xhr.onload = () => {
      if (xhr.status === 200) {
        resolve(xhr.response);
      }
    };
    xhr.send();
  });
}
/**
 * 保存
 * @param  {Blob} blob
 * @param  {String} filename 想要保存的文件名称
 */
const saveAs = (blob, filename) => {
  if (window.navigator.msSaveOrOpenBlob) {
    navigator.msSaveBlob(blob, filename);
  } else {
    let link = document.createElement('a');
    let body = document.querySelector('body');
    link.href = window.URL.createObjectURL(blob);
    link.download = filename;
    // fix Firefox
    link.style.display = 'none';
    body.appendChild(link);
    link.click();
    body.removeChild(link);
    window.URL.revokeObjectURL(link.href);
  }
}
/**
 * 下载--获取文件 Blob,然后下载重命名
 * @param  {String} url 目标文件地址
 * @param  {String} filename 想要保存的文件名称
 */
const downLoadRemoteFile = (url, filename) => {
  getBlob(url).then(blob => {
    saveAs(blob, filename);
  });
}
 
export default downLoadRemoteFile;

页面:

<template>
  <div class="app-container">
    <el-form
      :model="queryParams"
      ref="queryForm"
      size="small"
      :inline="true"
      v-show="showSearch"
      label-width="100px"
    >
      <el-form-item label="活动名称" prop="actName">
        <el-input
          v-model="queryParams.actName"
          placeholder="请输入活动名称"
          clearable
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>
      <el-form-item label="归属区域" prop="officeId">
        <!-- <el-input
          v-model="queryParams.officeId"
          placeholder="请输入归属区域"
          clearable
          @keyup.enter.native="handleQuery"
        /> -->
        <TreeSelect
          class="treeselect-main"
          v-model="queryParams.officeId"
          :options="areaBelongOptions"
          :normalizer="normalizer"
          placeholder="请输入归属区域"
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>
      <el-form-item label="活动创建时间" prop="dateRange">
        <el-date-picker
          :picker-options="pickerOptions"
          v-model="dateRange"
          style="width: 300px"
          value-format="yyyy-MM-dd HH:mm:ss"
          type="datetimerange"
          range-separator="-"
          start-placeholder="开始时间"
          end-placeholder="结束时间"
          :default-time="['00:00:00', '23:59:59']"
        ></el-date-picker>
      </el-form-item>
      <el-form-item>
        <el-button
          type="primary"
          icon="el-icon-search"
          size="mini"
          @click="handleQuery"
          >搜索</el-button
        >
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
          >重置</el-button
        >
      </el-form-item>
    </el-form>

    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button
          type="primary"
          plain
          icon="el-icon-plus"
          size="mini"
          @click="handleAdd"
          v-hasPermi="['edu:activity:add']"
          >新增</el-button
        >
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="success"
          plain
          icon="el-icon-edit"
          size="mini"
          :disabled="single"
          @click="handleUpdate"
          v-hasPermi="['edu:activity:edit']"
          >修改</el-button
        >
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="danger"
          plain
          icon="el-icon-delete"
          size="mini"
          :disabled="multiple"
          @click="handleDelete"
          v-hasPermi="['edu:activity:remove']"
          >删除</el-button
        >
      </el-col>
      <!-- <el-col :span="1.5">
        <el-button
          type="warning"
          plain
          icon="el-icon-upload2"
          size="mini"
          @click="uploadQrcode"
          v-hasPermi="['edu:activity:export']"
          >上传二维码</el-button
        >
      </el-col> -->
      <right-toolbar
        :showSearch.sync="showSearch"
        @queryTable="getList"
      ></right-toolbar>
    </el-row>
    <qrcodeDialog :visible.sync="qrcodeShow" :actList.sync="actList" />

    <!-- 表格内容 -->
    <div class="table">
      <el-table
        border
        v-loading="loading"
        :data="activityList"
        @selection-change="handleSelectionChange"
      >
        <el-table-column align="center" label="活动主图" prop="actImg">
          <template v-slot="scope">
            <el-image style="width: 60px; height: 40px" :src="scope.row.actImg">
            </el-image>
          </template>
        </el-table-column>
        <el-table-column
          show-overflow-tooltip
          v-for="column in columns"
          :key="column.prop"
          :label="column.label"
          :align="column.align"
          :prop="column.prop"
          height="200"
        >
          <template v-if="column.slot" v-slot="scope">
            <div class="my-table-td-content">
              <slot
                :name="column.prop"
                :scope="scope.row"
                :index="scope.$index"
              >
                <span>{{ column.slot(scope.row) }}</span>
              </slot>
            </div>
          </template>
        </el-table-column>
        <el-table-column
          align="center"
          prop="prop"
          label="报名时间"
          show-overflow-tooltip
        >
          <template v-slot="scope">
            <span>{{ scope.row.signStart }}~{{ scope.row.signEnd }}</span>
          </template>
        </el-table-column>
        <el-table-column align="center" label="二维码" prop="actQrcode">
          <template v-slot="scope">
            <el-image
              v-if="scope.row.actImg&&scope.row.actQrcode"
              @click.stop.prevent="clickImage"
              style="width: 40px; height: 40px"
              :src="scope.row.actQrcode"
              :preview-src-list="getPreviewList(scope.row.actQrcode)"
            >
            </el-image>
          </template>
        </el-table-column>
        <el-table-column
          label="操作"
          align="center"
          class-name="small-padding fixed-width"
        >
          <template slot-scope="scope">
            <el-button
              size="mini"
              type="text"
              icon="el-icon-edit"
              @click="handleUpdate(scope.row)"
              v-hasPermi="['edu:paper:edit']"
              >修改</el-button
            >
            <el-button
              size="mini"
              type="text"
              icon="el-icon-link"
              @click="uploadQrcode(scope.row)"
              v-hasPermi="['edu:paper:edit']"
              >生成二维码</el-button
            >
            <el-button
              size="mini"
              type="text"
              icon="el-icon-delete"
              @click="handleDelete(scope.row)"
              v-hasPermi="['edu:paper:remove']"
              >删除</el-button
            >
          </template>
        </el-table-column>
      </el-table>
    </div>
    <div class="code" style="display: none">
      <vue-qr
        v-if="vueQrStatus"
        ref="qrCode"
        :text="textValue"
        :logoSrc="logoPath"
        :logoScale="40"
        :size="190"
        :margin="10"
        :callback="testCallback"
      />
    </div>
    <pagination
      v-show="total > 0"
      :total="total"
      :page.sync="queryParams.pageNum"
      :limit.sync="queryParams.pageSize"
      @pagination="getList"
    />
    <!-- 添加或修改活动对话框 -->
    <addEditActivityDialog
      :visible.sync="addEditVisible"
      :areaBelongOptions.sync="areaBelongOptions"
      :isEdit.sync="isEdit"
      :title.sync="title"
      :actId.sync="actId"
      :selectRow.sync="selectRow"
      @getList="getList()"
    />
  </div>
</template>

<script>
import {
  listActivity,
  getActivity,
  delActivity,
  saveQrcode,
  updateActivity,
} from "@/api/edu/activity";
import { listDept } from "@/api/system/dept";
import addEditActivityDialog from "./component/addEditActivityDialog.vue";
import qrcodeDialog from "./component/qrcodeDialog.vue";
import logoImg from "@/assets/logo/logo.png";
import VueQr from "vue-qr";
import { uploadFile2 } from "@/utils/upload-file";
import dayjs from "dayjs";
import downLoadRemoteFile from "@/utils/images/downLoadRemoteFile";

export default {
  name: "Activity",
  components: {
    addEditActivityDialog,
    qrcodeDialog,
    VueQr,
  }, //
  data() {
    return {
      imageDisplay: "",
      //选中得id
      rowActId: "",
      // 控制二维码得生成
      vueQrStatus: false,
      // 二维码logo
      logoPath: logoImg,
      // 二维码text
      textValue: "",
      qrcodeShow: false,
      actList: [],
      // 活动id
      actId: "",
      // 增加修改-table某一行row的值
      selectRow: {},
      // 增加修改-弹出层标题
      title: "",
      // 增加修改-编辑状态
      isEdit: false,
      // 归属区域list
      areaBelongOptions: [],
      // 增加编辑弹出框展示
      addEditVisible: false,
      // 日期范围
      dateRange: [],
      // 遮罩层
      loading: true,
      // 选中数组
      ids: [],
      // 子表选中数据
      checkedEduActivityPaper: [],
      // 非单个禁用
      single: true,
      // 非多个禁用
      multiple: true,
      // 显示搜索条件
      showSearch: true,
      // 总条数
      total: 0,
      // 活动表格数据
      activityList: [],
      // 活动竞赛试卷表格数据
      eduActivityPaperList: [],
      // 是否显示弹出层
      open: false,
      // 查询参数

      queryParams: {
        pageNum: 1,
        pageSize: 10,
        actName: null,
        officeId: null,
      },
      // 表单参数
      form: {},
      // 表单校验
      rules: {},
      columns: [
        { label: "活动名称", align: "center", prop: "actName" },
        // { label: "活动主图", align: "center", prop: "actImg" },
        { label: "活动归属区域", align: "center", prop: "officeName" },
        { label: "状态", align: "center", prop: "statusName" },
        { label: "竞赛时间", align: "center", prop: "competitionTime" },
        // { label: "活动海报", align: "center", prop: "actPoster" },
        // { label: "活动简介", align: "center", prop: "actMemo" },
      ],
      pickerOptions: {
        shortcuts: [
          {
            text: "最近一周",
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
              picker.$emit("pick", [start, end]);
            },
          },
          {
            text: "最近一个月",
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
              picker.$emit("pick", [start, end]);
            },
          },
        ],
      },
    };
  },
  created() {
    this.getList();
    this.getTreeList();
  },
  methods: {
    // 二维码生成得callback
    testCallback(dataUrl, id) {
      const file = this.base64ToFile(dataUrl, "image.png");
      // console.log(file, "dataUrl");
      // const reader = new FileReader();
      // reader.onload = function (event) {
      //   document.getElementById("imageDisplay").src = event.target.result;
      // };
      // reader.readAsDataURL(file);
      // return;

      console.log(file, "file");
      // console.log(dataUrl, id);
      const TODAY = dayjs().format("YYYY/MM/DD");
      uploadFile2(`/quiz/cover/${TODAY}/`, file, (err, data) => {
        if (err) {
          this.$modal.msgError(`上传失败:${err}`);
        } else {
          const imageUrl = `http://${data.Location}`;
          console.log(imageUrl, "imageUrl");
          const qrcodeUrl = imageUrl;
          saveQrcode({ actId: this.rowActId, qrcodeUrl: qrcodeUrl }).then(
            (res) => {
              if (res.code === 200) {
                this.$modal.msgSuccess("生成二维码成功");
                this.getList();
                // this.open = false;
              }
            }
          );
        }
      });
    },

    // 上传二维码
    uploadQrcode(row) {
      this.rowActId = row.actId;
      const actId = row.actId;
      const officeId = row.officeId;
      this.textValue = `http://192.168.1.101:8080/?actId=${actId}&officeId=${officeId }`;
      this.$nextTick(() => {
        // 控制二维码得生成;
        this.vueQrStatus = true;
      });
      // console.log(this.qrcodeUrl, this.rowActId, "this.qrcodeUrl");
    },
    // 转换base64图片方法
    base64ToFile(base64Data, filename) {
      // 将base64的数据部分提取出来
      const parts = base64Data.split(";base64,");
      const contentType = parts[0].split(":")[1];
      const raw = window.atob(parts[1]);
      // 将原始数据转换为Uint8Array
      const rawLength = raw.length;
      const uInt8Array = new Uint8Array(rawLength);
      for (let i = 0; i < rawLength; ++i) {
        uInt8Array[i] = raw.charCodeAt(i);
      }
      // 使用Blob对象创建File对象
      const blob = new Blob([uInt8Array], { type: contentType });
      blob.lastModifiedDate = new Date();
      blob.name = filename;
      return new File([blob], filename, { type: contentType });
    },
    getTreeList() {
      listDept().then((response) => {
        this.areaBelongOptions = this.handleTree(response.data, "deptId");
      });
    },
    /** 查询活动列表 */
    getList() {
      this.loading = true;
      listActivity(this.addDateRange(this.queryParams, this.dateRange)).then(
        (response) => {
          this.activityList = response.rows;
          this.total = response.total;
          this.loading = false;
        }
      );
    },

    /** 搜索按钮操作 */
    handleQuery() {
      this.queryParams.pageNum = 1;
      this.getList();
    },
    /** 重置按钮操作 */
    resetQuery() {
      // 置空时间区间
      this.dateRange = "";
      this.resetForm("queryForm");
      this.handleQuery();
    },
    // 多选框选中数据
    handleSelectionChange(selection) {
      this.ids = selection.map((item) => item.actId);
      this.single = selection.length !== 1;
      this.multiple = !selection.length;
    },
    /** 新增按钮操作 */
    handleAdd() {
      this.addEditVisible = true;
      this.title = "添加活动";
      // 增加状态
      this.isEdit = false;
      // this.reset();
      // this.open = true;
    },

    /** 修改按钮操作 */
    handleUpdate(row) {
      // 打开弹出层
      this.addEditVisible = true;
      // 编辑状态;
      this.isEdit = true;
      //传入title
      this.title = "修改活动";
      // 传入活动id
      this.actId = row.actId;
      // 获取详情传值子组件
      getActivity(row.actId).then((response) => {
        this.selectRow = response.data;
      });
    },

    /** 删除按钮操作 */
    handleDelete(row) {
      const actIds = row.actId;
      this.$modal
        .confirm('是否确认删除活动编号为"' + actIds + '"的数据项?')
        .then(function () {
          return delActivity(actIds);
        })
        .then(() => {
          this.getList();
          this.$modal.msgSuccess("删除成功");
        })
        .catch(() => {});
    },

    /**
     * @description: 查看-大图预览, 仅预览当前大图
     * @param {String} imgUrl 当前图片URL
     * @return {Array} arr 当前图片为第一个的大图
     */
    getPreviewList(imgUrl) {
      return [imgUrl];
    },

    /**
     * @description: 预览的图片添加下载按钮
     */
    clickImage() {
      this.$nextTick(() => {
        let wrapper = document.getElementsByClassName(
          "el-image-viewer__actions__inner"
        );
        if (wrapper.length > 0) {
          let downImg = document.createElement("i");
          downImg.setAttribute("class", "el-icon-download");
          downImg.style.cursor = "pointer";
          wrapper[0].appendChild(downImg);
          this.cusClickHandler(downImg);
        }
      });
    },

    /**
     * @description: 预览的图片给下载按钮添加事件
     * @param {HTMLElement} downImg 下载按钮元素
     */
    cusClickHandler(downImg) {
      downImg.addEventListener("click", () => {
        const imgUrl = document.getElementsByClassName(
          "el-image-viewer__img"
        )[0].src;
        const fileName = this.getFileNameFromUrl(imgUrl);
        downLoadRemoteFile(imgUrl, fileName);
      });
    },

    /**
     * @description: 从 URL 中提取文件名的辅助方法
     * @param {String} url 图片的 URL
     * @return {String} 文件名
     */
    getFileNameFromUrl(url) {
      return url.substring(url.lastIndexOf("/") + 1);
    },

    /** 转换部门数据结构 */
    normalizer(node) {
      if (node.children && !node.children.length) {
        delete node.children;
      }
      return {
        id: node.deptId,
        label: node.deptName,
        children: node.children,
      };
    },
  },
};
</script>
<style lang="scss">
.treeselect-main {
  width: 250px;
  line-height: 30px;
  .vue-treeselect__placeholder {
    line-height: 28px;
  }
  .vue-treeselect__control {
    height: 28px;
  }
  .vue-treeselect__menu {
    border: none;
    font-weight: 100;
  }
}
.table {
  .el-table__cell {
    .cell {
      white-space: nowrap;
      text-overflow: ellipsis;
      overflow: hidden;
      word-break: break-all;
    }
  }
}
</style>

这样写,在项目中会出现二维码和其他行错位的问题,目前没有解决

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值