electron中使用flash插件

let pluginName = null let pluginPath = null switch (process.platform) { case 'win32': pluginName = 'pepflashplayer.dll' break case 'darwin': pluginName = 'PepperFlashPlayer.plugin' break case 'linux': pluginName = 'libpepflashplayer.so' break } // 根据你的路径修改,这里做打包后路径判断 if (__dirname.includes(".asar")) { pluginPath = path.join(process.resourcesPath + '/lib/' + pluginName) } else { pluginPath = path.resolve(__dirname + '/lib/' + pluginName) } app.commandLine.appendSwitch('ppapi-flash-path', pluginPath) app.commandLine.appendSwitch('ppapi-flash-version', '32.0.0.363') 三个平台flash下载地址:https://wong-1251253615.cos.ap-shanghai.myqcloud.com/blog/images/2020-05-14/flash.7z

April 14, 2020 · 1 min · 58 words · Norman Wang

B站获取SESSDATA

注:大会员账号的SESSDATA才可以下载大会员专属视频 chrome浏览器打开bilibili 并登录 网页右键点击检查 点开下拉菜单依次选择application -> cookies -> www.bilibili.com 右边选择SESSDATA,复制SESSDATA值

January 25, 2020 · 1 min · 10 words · Norman Wang

electron-vue 快速入门

介绍 准备重构BilibiliVideoDownload,就开始学习electron,再加上自己是vue技术栈就选用了electron-vue electron-vue官网:点击访问 electron官网:点击访问 搭建 使用vue init确保安装@vue/cli @vue/cli-init # 安装脚手架样板代码 vue init simulatedgreg/electron-vue my-project # 安装依赖并运行你的程序 cd my-project yarn # 或者 npm install yarn run dev # 或者 npm run dev 踩坑 npm install 阶段遇到了electron安装超时的问题,有两种方法解决 安装cnpm运行cnpm install 设置npm代理 npm run dev 阶段遇到了process is not defined 删除node_modules 安装10.x.x版本的node,我本地是12.0.0,通过n模块安装的10.16.0 实现两个版本node共存。 按照issues里面的做法,会导致其他问题,最稳定的就是降低自己的node版本到10.x.x 技术细节 主进程和渲染进程 介绍 Electron 运行 package.json 的 main 脚本的进程被称为主进程。 在主进程中运行的脚本通过创建web页面来展示用户界面。 一个 Electron 应用总是有且只有一个主进程。 由于 Electron 使用了 Chromium 来展示 web 页面,所以 Chromium 的多进程架构也被使用到。 每个 Electron 中的 web 页面运行在它自己的渲染进程中。更多 ...

January 21, 2020 · 1 min · 115 words · Norman Wang

WEB端扫描二维码和条形码[优化版]

之前写过一个demo也是web端扫描条形码和二维码,但是有个问题。程序扫描的是整个可视区域范围不是扫描框,这就会导致如果扫描框也有条码会出错。这次的例子修复了这个问题,扫描区域就是扫描框的区域。而且对不同情况都有良好的兼容,可以把可视区域和扫描框长宽传入组件,组件会进行计算从摄像头中得到扫描框的图像进行识别。 Vue.component('scanner-box',{ props: { // 视口长宽 viewportWidth:{ type: Number }, viewportHeight:{ type: Number }, // 扫描框长宽 scanWidth:{ type: Number }, scanHeight:{ type: Number } }, data(){ return { // 摄像头分辨率 cameraWidth: 0, cameraHeight: 0, canvas1Width: 0, canvas1Height: 0 } }, methods: { handleImageSize(video,item1,item2){ let videoWidth = this.cameraWidth, videoHeight = this.cameraHeight, viewWidth = this.viewportWidth, viewHeight = this.viewportHeight, scanW = this.scanWidth, scanH = this.scanHeight, w,h; let context1 = item1.getContext("2d"), context2 = item2.getContext("2d"); if (viewWidth/viewHeight > videoWidth/videoHeight){ // 视口比大于摄像头分辨率比 => 摄像头高度需要裁剪 w = viewWidth,h = parseInt(w/(videoWidth/videoHeight)); }else if (viewWidth/viewHeight < videoWidth/videoHeight){ // 视口比小于摄像头分辨率比 => 摄像头宽度需要裁剪 h = viewHeight,w = parseInt(h*(videoWidth/videoHeight)); }else { // 视口比等于摄像头分辨率比 => 摄像头长宽都不需要裁剪 w = viewWidth,h = viewHeight; } this.canvas1Width = w; this.canvas1Height = h; this.$nextTick(() => { context1.drawImage(video,0,0,videoWidth,videoHeight,0,0,w,h); context2.drawImage(item1,(w/2)-(scanW/2),(h/2)-(scanH/2),scanW,scanH,0,0,scanW,scanH); }) }, initVideo(constrains){ let _this = this; if(navigator.mediaDevices.getUserMedia){ //最新标准API navigator.mediaDevices.getUserMedia(constrains).then(_this.videoSuccess).catch(_this.videoError); } else if (navigator.webkitGetUserMedia){ //webkit内核浏览器 navigator.webkitGetUserMedia(constrains).then(_this.videoSuccess).catch(_this.videoError); } else if (navigator.mozGetUserMedia){ //Firefox浏览器 navagator.mozGetUserMedia(constrains).then(_this.videoSuccess).catch(_this.videoError); } else if (navigator.getUserMedia){ //旧版API navigator.getUserMedia(constrains).then(_this.videoSuccess).catch(_this.videoError); } }, videoSuccess(stream){ let video = this.$refs.video, _this = this; //将视频流设置为video元素的源 video.srcObject = stream; //播放视频 video.play(); video.oncanplay = function () { // 摄像头分辨率 console.log('摄像头分辨率'); console.log(video.videoWidth + 'x' + video.videoHeight); // 视口分辨率 console.log('视口分辨率'); console.log(window.innerWidth + 'x' + window.innerHeight); _this.cameraWidth = video.videoWidth; _this.cameraHeight = video.videoHeight; // 发送图片进行识别 _this.readImg(); }; }, videoError(error){ console.log("访问用户媒体设备失败:",error.name,error.message); }, readImg(){ let video = this.$refs.video, canvas1 = this.$refs.canvas1, context = canvas1.getContext("2d"), canvas2 = this.$refs.canvas2, context2 = canvas2.getContext("2d"), _this = this; let timer = setInterval(function () { _this.handleImageSize(video,canvas1,canvas2); // 扫码条形码 let imgUri = canvas2.toDataURL(); _this.readBarcode(imgUri,timer); // 扫码二维码 let imageData = context2.getImageData(0, 0, _this.scanWidth, _this.scanHeight); _this.readQrcode(imageData.data,timer); },500) }, readBarcode(imgBase64,timer){ let _this = this; Quagga.decodeSingle({ decoder: { readers: ["code_128_reader"] }, // locate为true程序会自动寻找条码,找不到不会出结果。会对一些清晰度不高的图片有影响 locate: false, src: imgBase64 }, function(result){ if (result){ if(result.codeResult){ // 扫描成功后清除定时器,停止扫描 // clearInterval(timer); _this.$emit('ondata',{ type: 'barcode', result: result.codeResult.code}); }else { console.log("正在扫条形码...not detected"); } }else { console.log("正在扫条形码...not detected"); } }); }, readQrcode(data,timer){ let _this = this; let code = jsQR(data, _this.scanWidth, _this.scanHeight, { // 只支持白底黑码,默认支持白底黑码和黑底白码。 inversionAttempts: "dontInvert", }); if (code){ // clearInterval(timer); _this.$emit('ondata',{ type: 'qrcode', result: code.data}); //_this.$refs.audio.play(); }else { console.log('正在扫二维码...'); } } }, mounted(){ // 检测浏览器是否支持getUserMedia if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia){ //调用用户媒体设备,访问摄像头 this.initVideo({ video:{ width: window.innerWidth*2, facingMode: { // 强制后置摄像头,pc端做测试请注释掉,不然会报错 // exact: "environment" } } }); } else { alert("你的浏览器不支持访问用户媒体设备"); } Common.getOrientationChange(function (res) { console.log(res); if (res){ window.location.reload(); } }); }, template: `<div id="scanner"> <div class="model"> <div class="scanner-view"> <div class="scanner-view-arrow arrow1"></div> <div class="scanner-view-arrow arrow2"></div> <div class="scanner-view-arrow arrow3"></div> <div class="scanner-view-arrow arrow4"></div> <div class="scanner-line"></div> </div> <div class="scanner-text">放入框内,自动扫描</div> </div> <audio id="audio" ref="audio" src="./css/success.mp3" style="width: 0px;height: 0px"></audio> <video class="video-view" ref="video" autoplay playsinline="true" webkit-playsinline="true"></video> <canvas ref="canvas1" :width="canvas1Width" :height="canvas1Height" style="display: none"></canvas> <canvas ref="canvas2" :width="scanWidth" :height="scanHeight" style="display: none"></canvas> </div>` }); #app { /*width: 100%;*/ } .left, .right { width: 50%; float: left; } .left { background: #f7f7f7; height: 100vh; } .stockSearch-title { background: #fff; border: 1px solid #dcdfe6; color: #606266; font-weight: 600; height: 40px; line-height: 40px; position: relative; text-align: center; } .stockSearch-title a { color: #79bbff; font-size: 14px; position: absolute; left: 20px; } .stockSearch-title .iconLeft-1 { font-size: 14px; font-weight: 600; } .stockSearch-result { background: #fff; box-sizing: border-box; width: 92%; min-height: 500px; margin: 20px auto; padding: 12px 20px 15px 20px; } .stockSearch-result .caption{ color: #4db3a2; font-weight: 600; padding: 10px 0; } .table .is-waiting{ color: #c0c4cc; font-size: 16px; text-align: center; padding: 20px; } .table .hide { display: none; } .table table { background: #fff; border: 1px solid #dddddd; border-spacing: 0; border-collapse: collapse; color: #606266; font-size: 14px; width:100%; } .td-stock-title { font-weight: 600; padding: 8px; text-align: center; } .table tr:nth-of-type(5){ color: #428bca; } .table td { border: 1px solid #ddd; } .table td >div div { padding: 4px 8px; } .table td >div div:nth-child(odd) { background: #f9f9f9; } .table-num { /*color: #303133;*/ font-weight: 600; } .table-current { color: #fff; background: #64b1f1; font-size: 12px; padding: .2em .3em; border-radius: 4px; } /* 右侧扫码 */ #scanner { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; position: relative; } .model{ box-sizing: border-box; width: 50vw; height: 100vh; position: relative; z-index: 88; border-top: calc((100vh - 30vw)/2) solid rgba(0,0,0,.2); border-bottom: calc((100vh - 30vw)/2) solid rgba(0,0,0,.2); border-right: 10vw solid rgba(0,0,0,.2); border-left: 10vw solid rgba(0,0,0,.2); } .scanner-view{ box-sizing: border-box; width: 100%; height: 100%; position: relative; border: 1px solid rgba(255,255,255,.3); z-index: 89; } .scanner-line{ position: absolute; width: 100%; height: 1px; background: #49FF46; /*background: radial-gradient(ellipse,#71e52c,#001800);*/ border-radius: 20px; z-index: 90; animation: myScan 1s infinite alternate; } @keyframes myScan{ from { top: 0; } to { top: 30vw; } } .scanner-view-arrow{ position: absolute; width: 5vw; height: 5vw; border: 2px solid #09bb07; } .scanner-view-arrow.arrow1{ top: -1px; left: -1px; z-index: 99; border-right: none; border-bottom: none; } .scanner-view-arrow.arrow2{ top: -1px; right: -1px; z-index: 99; border-left: none; border-bottom: none; } .scanner-view-arrow.arrow3{ bottom: -1px; left: -1px; z-index: 99; border-right: none; border-top: none; } .scanner-view-arrow.arrow4{ bottom: -1px; right: -1px; z-index: 99; border-left: none; border-top: none; } .scanner-text { color: #909399; font-size: 20px; height: 40px; line-height: 40px; text-align: center; margin-top: 20px; } .video-view{ position: absolute; width: 50vw; height: 100vh; object-fit: cover; top: 0; left: 0; z-index: 80; }

September 20, 2019 · 4 min · 790 words · Norman Wang

bilibili通过弹幕查询用户

弹幕获取 首先通过视频aid获取cid 视频的aid又称av号,是视频url中av后面的一串数字 https://www.bilibili.com/av67289687 67289687就是这个视频的aid 使用aid去请求这个api https://api.bilibili.com/x/web-interface/view?aid=${aid} 即可得到cid 通过cid获取视频弹幕信息 拿到cid以后请求这个api可以得到弹幕信息,xml格式。 https://api.bilibili.com/x/v1/dm/list.so?oid=${cid} 文件转码 应为返回的xml弹幕文件的content-encoding为deflate,需要用到zlib来解压。 解码用户id b站弹幕是这样的形式 <d p="53.87100,1,25,16777215,1562172618,0,13ba9291,18366041035898882">艾欧尼亚</d> d标签值是弹幕内容,属性p里面依次是弹幕的出现时间,模式,字体大小,颜色,发送时间戳,弹幕池,用户Hash,数据库ID 其中要用的是用户Hash。用户Hash只是简单的把数字ID用ITU I.363.5算法进行了Hash。 有两种方法把用户Hash转成uid 使用第三方接口 https://biliquery.typcn.com/api/user/hash/用户Hash 自给自足 我这里有一个例子,借鉴了bilibili-helper const Crc32Engine = require('./crc32'); const crcEngine = new Crc32Engine(); const hashToUid = hash => { let extracted = /^b(\d+)$/.exec(hash); let uids = []; if (extracted && extracted[1]) { uids = [extracted[1]]; } else { uids = crcEngine.crack(hash); } return uids[uids.length-1]; }; module.exports = { hashToUid }; // crc32: https://github.com/blogwy/BilibiliVideoDownload/blob/master/utils/danmu/crc32.js 访问用户主页 https://space.bilibili.com/uid

September 12, 2019 · 1 min · 76 words · Norman Wang

[vue组件]日期时间选择器

安装 引入日期时间选择器 使用 <template> <div style="margin-left: 30px"> <date-picker mode="datetime" :default-time="1566270847000" :min-time="1562037247000" :max-time="1567394047000" @change="getTime"></date-picker> <date-picker mode="date" format="YYYY年MM月DD日" :min-time="1562037247000" :max-time="1567394047000" @change="getTime"></date-picker> <date-picker mode="month" :min-time="1496128969000" :max-time="1590823369000" @change="getTime"></date-picker> <date-picker mode="year" @change="getTime"></date-picker> </div> </template> <script> import datePicker from './components/datePicker.vue' export default { name: '', components: { datePicker }, data() { return {} }, methods: { getTime(date){ console.log(date); } } } </script> <style scoped> </style> 属性 属性 描述 类型 备注 mode 日期类型 Number(时间戳) 没有默认值,必填,可选值为(date/datetime/month/year) placeholderText 没有选择日期时的占位文字 String 请选择日期/月份/年份 defaultTime 默认时间 Number(时间戳) 没有默认值,选填 minTime 最小可选时间 Number(时间戳) 没有默认值,选填 maxTime 最大可选时间 Number(时间戳) 没有默认值,选填 format 格式化显示日期 String YYYY-MM-DD hh:mm:ss pickerWidth 组件宽 Number 250/155

August 22, 2019 · 1 min · 93 words · Norman Wang

自己写了一个Vue表单验证插件

轻量级表单验证插件,目前功能还不全可能会有BUG 入门 以Vue2.x为例 引入 在main.js中引入并use import WyValidate from 'wy-validate'; Vue.use(WyValidate); 页面使用 普通验证 添加v-validate自定义指令和v-validatecss类名,data-error目前可有可无 <div> <input type="text" class="v-validate" v-validate="rules1" data-error="" v-model="data"/> </div> 添加错误提示样式,类名为is-error-span,是写死在插件里的。这里给出一个简单的样式 .is-error-span{ color: #f56c6c!important; font-size: 14px!important; line-height: initial!important; padding-top: 3px!important; position: absolute!important; top: 100%!important; left: 0!important; } 按钮触发验证 在button上加入v-submit="'testSubmit'",testSubmit为验证成功后的函数名。必须加单引号,不然会被认为是变量。 <button v-submit="'testSubmit'">确认</button> 特殊情况 对于一些不方便写v-submit的时候可以参考以下 let elements = document.getElementsByClassName('v-validate'); let evObj = document.createEvent('Event'); evObj.initEvent('input', true, true); for (let element of elements) { element.dispatchEvent(evObj); } let errorInputs = document.getElementsByClassName('is-error-span'); if(errorInputs.length === 0){ // 这里写验证成功后的代码 } 定义规则 规则分为4类。是否为空、数字范围、类型、自定义正则 export default { name: 'app', data() { return { // 是否为空 rules1: { type: 0, required: true, message1: "不能为空" }, // 两个数之间 rules2: { type: 1, // required可选值为true/false required: true, // message1为required: true时候的提示 message1: "不能为空", // message1为数字不在范围时候的提示 message2: "请输入2位数", min: 10, max: 99 }, // 数据类型 rules3: { type: 3, required: true, message1: "不能为空", // textType可选值为 number email url chinese cellphonenumber(手机) phonenumber(固话) textType: 'number', message2: "请输入数字" }, // 自定义正则 rules4: { type: 4, required: true, message1: "不能为空", regex: '', message2: "请输入2位数" } } } } 规则说明 无 ...

August 16, 2019 · 1 min · 173 words · Norman Wang

小米路由器3刷开发版固件并安装MT工具箱翻墙

注:本教程适用与绝大部分小米路由器,不局限于3代 准备工作 在开始之前你需要申请一个小米账号并绑定要刷的路由器。 绑定方法:手机连接好小米路由器后,在应用市场下载小米wifi,登录并绑定。 刷入开发版固件 下载固件 打开下面网址下载对应的开发版固件 http://www1.miwifi.com/miwifi_download.html 备份数据 进入路由器后台 在常用设置 - 系统状态 里面点击新建备份 刷入系统 还是在系统状态页面点击手动升级,选择你下载的开发版rom 获取root权限(开启ssh) 注:获取root权限后小米路由器会失去保修 获取ssh文件和root密码 进入这个网址http://www1.miwifi.com/miwifi_open.html 下拉网页点击开启ssh工具 开始ssh 把ssh文件放入U盘根目录,U盘必须是FAT/FAT32格式 U盘插入路由器 拔掉路由器电源,网线不用拔 用牙签等细的东西抵住路由器的reset键 插入电源(不要松开reset键) 等待几秒路由器的黄灯开始闪烁放开reset键,并拔掉U盘 过一会路由器灯会自动变为蓝色,这时代表root权限获取成功 电脑打开命令行连接ssh,密码为网页开启ssh的密码 ssh root@192.168.31.1 安装MT工具箱3.0 ssh连接上后,输入以下代码安装工具箱 curl -s -k https://beta.misstar.com/download/$(uname -m)/mtinstall -o /tmp/mtinstall && chmod +x /tmp/mtinstall && /tmp/mtinstall 具体工具箱介绍请查看官方论坛以后工具箱如果有bug或者版本更新也请查看官方论坛 实测小米路由3MT工具箱地址为192.168.31.1:1024如果按照安装成功后给的端口进入会出现无法访问 安装SS插件翻墙 MT工具箱3.0集成了SS插件(支持SS/SSR),点击安装即可。

August 4, 2019 · 1 min · 51 words · Norman Wang

hexo博客搭建写作上传入门教程

准备工作 安装node 安装git 配置git node和git安装好以后,命令行依次输入node -v npm -v git --version如果返回版本号则安装成功,然后开始配置git的邮箱和名字,把下面命令中的名字和邮箱替换成自己的就行 git config --global user.name "John Doe" git config --global user.email johndoe@example.com 搭建博客 安装hexo npm install hexo-cli -g 开始搭建 hexo init 项目名 cd 项目名 npm i 生成静态页面 hexo g 启动本地服务 hexo s 访问url,这时你应该就看到自己创建的hexo博客,目前只有一个测试博文,主题也是默认的。 更换主题 写作 注:hexo只支持md语法 在你写完的md文件的头部加入标识才可以被hexo正确识别并生成静态文件,标识一般分为文章标题、文章时间、标签,下面是这篇博文的文章标识,机子tags要有缩进。 --- title: hexo博客搭建写作上传教程 date: 2019-08-01 tags: - hexo - github --- 文章标识可以根据主题进行自定义,前提是你有一定的前端编码能力。由于本文是入门教程就不谈这些了。 当你加入了标识后,把这个md文件复制到/source/_posts文件夹中,md的文件名没有要求和文章名字没有关系。 部署github 注:hexo博客可以部署到许多平台,具体请看官网教程 安装部署插件 打开命令行并进入博客根目录,输入下面命令安装插件 npm install hexo-deployer-git --save 配置github地址 打开博客的配置文件,根目录下面的_config.yml 找到deploy这个配置项,如果没有直接写一个,然后按照下面配置 deploy: type: git repo: git库路径 branch: 分支(不写代表主分支) # example deploy: type: git repo: https://github.com/blogwy/blogwy.github.io.git branch: 生成博客并部署 # 生成博客 hexo g # 在上传前最好先启动本地服务,看一下效果 hexo s # 部署 hexo d

August 1, 2019 · 1 min · 98 words · Norman Wang

Vue.js网页打印小票实例(二维码/条形码)

设备 Deli DL-730c 纸张是模切标签(100mm*100mm) chrome浏览器打印 注意事项 本人使用的纸张之间是有间隙的,请用直尺测量并在打印首选项里面设置好 这台打印机默认有一个垂直偏移,请事先在首选项里面设置为0 条形码、二维码生成库 二维码 条形码 源代码 <template> <div> // 用iframe实现区域打印 <iframe ref="printIframe" frameborder="0" scrolling="no" style="margin: 0px;padding: 0px;width: 0px;height: 0px;"></iframe> // 这里是需要打印的内容,根据需求可以隐藏也可以显示 <div ref="odiv" style="display: none"> // 纸张是100mm*100mm,根据公式计算长宽大约是377px(可以根据实际进行调整) <div v-for="(item,index) in printInfo" style="width: 377px;height: 378px;position: relative;box-sizing: border-box"> <div style="position: absolute;top: 25px; left: 5px;"> <div style="font-size: 18px;font-weight: 800">测试信息</div> <div style="font-size: 12px;font-weight: 600">{{ item.time }}</div> </div> <div style="position: absolute;top: 10px; right: 10px;"> <img :src="item.barCodeData | creatBarCode"/> </div> // 打印内容的css需要使用行内式,这样才能保证打印时候css起作用 <div style="position: absolute;top: 70px; left: 5px;width: 365px;height: 1px;border: none;border-top: 1px solid #555"></div> <div style="width:365px;position: absolute;top: 73px; left: 5px;font-size: 13px;display: flex;justify-content: center;align-items: center;flex-wrap: wrap;"> <div style="box-sizing: border-box;flex: none;width: 50%;line-height: 2">测试编码:<span style="font-weight: 600">{{ item.sapNo }}</span></div> <div style="box-sizing: border-box;flex: none;width: 50%;line-height: 2">测试名称:<span style="font-weight: 600">{{ item.mName }}</span></div> <div style="box-sizing: border-box;flex: none;width: 50%;line-height: 2">测试日期:<span style="font-weight: 600">{{ item.sDate }}</span></div> <div style="box-sizing: border-box;flex: none;width: 50%;line-height: 2">测试一项:<span style="font-weight: 600">{{ item.bDate }}</span></div> <div style="box-sizing: border-box;flex: none;width: 50%;line-height: 2">测试二项:<span style="font-weight: 600">{{ item.spec }}</span></div> <div style="box-sizing: border-box;flex: none;width: 50%;line-height: 2">测试三项:<span style="font-weight: 600">{{ item.gys }}</span></div> <div style="box-sizing: border-box;flex: none;width: 50%;line-height: 2">测试四项:<span style="font-weight: 600">{{ item.cctj }}</span></div> <div style="box-sizing: border-box;flex: none;width: 50%;line-height: 2">测试五项:<span style="font-weight: 600">{{ item.dkc }}</span> kg</div> <div style="box-sizing: border-box;flex: none;width: 50%;line-height: 2">测试六项:<span style="font-weight: 600">{{ item.dq }}</span> 天</div> <div style="box-sizing: border-box;flex: none;width: 50%;line-height: 2">测试七项:<span style="font-weight: 600">{{ item.is }}</span></div> <div style="box-sizing: border-box;flex: none;width: 100%;line-height:2">测试八项:<span style="font-weight: 600">{{ item.gmy }}</span></div> </div> <div style="position: absolute;top: 235px; left: 5px;width: 365px;height: 1px;border: none;border-top: 1px solid #555"></div> <div style="position: absolute;top: 252px; left: 66%;"> <img :src="item.qrCodeData | creatQrCode"/> </div> </div> </div> <button @click="printpage()">打印</button> </div> </template> <script> import JsBarcode from 'JsBarcode'; import qrcode from 'qrcode'; export default { name: 'test', data() { return { printInfo: [ { barCodeData: '21312313213', qrCodeData: '测试二维码测试二维码测试二维码', time: '2019-09-09 12:12:00', sapNo: '123456', mName: '测试名字', sDate: '2019-09-09', bDate: '12月', spec: '袋装25公斤', gys: '测试测试', cctj: '冷藏', dkc: '1000', dq: '12', is: '否', gmy: '' } ] } }, methods:{ printpage(id){ // 拿到要打印区域的dom结构并设置到Iframe的srcdoc属性上面 var printIframe = this.$refs.printIframe; var newstr = this.$refs.odiv.innerHTML; printIframe.setAttribute('srcdoc',newstr); printIframe.onload = function () { console.log(printIframe.contentWindow); // 去掉iframe里面的dom的body的padding margin的默认数值 printIframe.contentWindow.document.body.style.padding = '0px'; printIframe.contentWindow.document.body.style.margin = '0px'; // 开始打印 printIframe.contentWindow.focus(); printIframe.contentWindow.print(); }; } }, filters: { creatBarCode(barCodeData){ let canvas = document.createElement("canvas"); JsBarcode(canvas, barCodeData, { format: "CODE128", displayValue: true, margin: 0, height: 40, width: 1.5, fontSize: 12, textMargin: 0 }); return canvas.toDataURL("image/png"); }, creatQrCode(qrCodeData){ let typeNumber = 10; let errorCorrectionLevel = 'L'; qrcode.stringToBytes = qrcode.stringToBytesFuncs['UTF-8']; let qr = qrcode(typeNumber, errorCorrectionLevel); qr.addData(qrCodeData,'Byte'); qr.make(); return qr.createDataURL(2,0); } }, } </script> 打印预览 ...

July 25, 2019 · 2 min · 412 words · Norman Wang