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

avatar
作者
猴君
阅读量:0

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="actImg">           <template v-slot="scope">             <el-image               @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;       this.textValue = `http://192.168.2.101:9000/?actId=${row.actId}`;       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> 

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!