| | |
| | | // #endif
|
| | | }
|
| | | // #endif
|
| | | // #ifdef PUB_CUSTOMER
|
| | | uni.reLaunch({
|
| | | url: '/pages/home/home'
|
| | | })
|
| | | // #ifdef PUB_CUSTOMER |
| | | // 需要处理一下,判断是跳转登录还是原封不动 |
| | | if(options.partnerUserId){ |
| | | //需要去注册页面 |
| | | console.log('options',options) |
| | | |
| | | }else{ |
| | | uni.reLaunch({ |
| | | url: '/pages/home/home' |
| | | }) |
| | | }
|
| | | |
| | | // #endif
|
| | |
|
| | | },
|
对比新文件 |
| | |
| | | <template> |
| | | <view style="position: fixed;z-index: -9999;"> |
| | | <canvas id="myQrcode" :canvas-id="canvasID" :style="{width:canvasWidth+'px',height:canvasHeight+'px'}"></canvas> |
| | | <view v-if="qrCode == ''"> |
| | | <QRCode ref="qrcode" /> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import QRCode from "../qr_code/qrcode.vue" |
| | | var _this; |
| | | export default { |
| | | name: 'canvas-images', |
| | | props: { |
| | | // canvasID 等同于 canvas-id |
| | | canvasID: { |
| | | Type: String, |
| | | default: 'myQrcode' |
| | | }, |
| | | canvasWidth: { // 画布宽度 |
| | | Type: 'int', |
| | | default: 375 |
| | | }, |
| | | canvasHeight: { // 画布高度 |
| | | Type: 'int', |
| | | default: 650 |
| | | }, |
| | | shareTitle: { // 分享标题 |
| | | Type: 'String', |
| | | default: '我是这张图片的标题' |
| | | }, |
| | | goodsTitle: { // 商品宣传标题 |
| | | Type: 'String', |
| | | default: '' |
| | | }, |
| | | goodsTitle2: { // 商品宣传标题 |
| | | Type: 'String', |
| | | default: '' |
| | | }, |
| | | |
| | | shareImage: { // 分享图片 |
| | | Type: 'String', |
| | | default: '' |
| | | }, |
| | | qrSize: { // 二维码大小 |
| | | Type: 'int', |
| | | default: 100 |
| | | }, |
| | | qrUrl: { // 生成二维码的链接 |
| | | Type: 'String', |
| | | default: 'https://ext.dcloud.net.cn/plugin?id=5747' |
| | | } |
| | | }, |
| | | components: { |
| | | QRCode |
| | | }, |
| | | data() { |
| | | return { |
| | | qrCode: '', // 二维码 |
| | | localImgPath: '', |
| | | canvas: undefined |
| | | } |
| | | }, |
| | | mounted() { |
| | | _this = this; |
| | | }, |
| | | methods: { |
| | | // downloadImg() { |
| | | // let that = this |
| | | // const query = uni.createSelectorQuery() |
| | | // console.log('canvasID',this.canvasID) |
| | | // query.select('#myQrcode') |
| | | // .fields({ |
| | | // node: true, |
| | | // size: true |
| | | // }) |
| | | // .exec((res) => { |
| | | // console.log('query',res) |
| | | // var canvas = res[0].node |
| | | // uni.canvasToTempFilePath({ |
| | | // canvasId: this.canvasID, |
| | | // canvas: canvas, |
| | | // x: 0, |
| | | // y: 0, |
| | | // width: this.canvasWidth, |
| | | // height: this.canvasHeight, |
| | | // destWidth: this.canvasWidth, |
| | | // destHeight: this.canvasHeight, |
| | | // success(res) { |
| | | // console.log('二维码临时路径:', res.tempFilePath) |
| | | // uni.saveImageToPhotosAlbum({ |
| | | // filePath: res.tempFilePath, |
| | | // success: function() { |
| | | // console.log('save success'); |
| | | // uni.showToast({ |
| | | // title: '保存成功' |
| | | // }) |
| | | // }, |
| | | // fail(res) { |
| | | // console.error(res) |
| | | // uni.showToast({ |
| | | // title: '保存失败。', |
| | | // icon: 'error' |
| | | // }) |
| | | // } |
| | | // }) |
| | | // }, |
| | | // fail(res) { |
| | | // console.error('fail', res) |
| | | |
| | | // uni.showToast({ |
| | | // title: '保存失败', |
| | | // icon: 'error' |
| | | // }) |
| | | // } |
| | | // }) |
| | | |
| | | // }) |
| | | |
| | | // }, |
| | | |
| | | // 创建二维码 |
| | | canvasCreate() { |
| | | this.localImgPath = this.shareImage |
| | | console.log('this.shareImage', this.shareImage) |
| | | if (this.shareImage && this.shareImage.startsWith('https://')) { |
| | | uni.getImageInfo({ |
| | | src: _this.shareImage, |
| | | success(res) { |
| | | console.log('getImageInfo res', res) |
| | | _this.localImgPath = res.path |
| | | _this.$refs.qrcode.make({ |
| | | size: _this.qrSize, |
| | | text: _this.qrUrl |
| | | }) |
| | | .then(res => { |
| | | // 返回的res与uni.canvasToTempFilePath返回一致 |
| | | // console.log(res) |
| | | _this.qrCode = res.tempFilePath; |
| | | _this.onCanvas(); |
| | | }); |
| | | }, |
| | | fail(error) { |
| | | this.$message.showToast('加载图片错误') |
| | | } |
| | | }) |
| | | } else { |
| | | _this.$refs.qrcode.make({ |
| | | size: _this.qrSize, |
| | | text: _this.qrUrl |
| | | }) |
| | | .then(res => { |
| | | // 返回的res与uni.canvasToTempFilePath返回一致 |
| | | // console.log(res) |
| | | _this.qrCode = res.tempFilePath; |
| | | _this.onCanvas(); |
| | | }); |
| | | } |
| | | |
| | | |
| | | }, |
| | | // 画图 |
| | | async onCanvas() { |
| | | uni.showLoading({ |
| | | title: "分享图片生成中..." |
| | | }); |
| | | const ctx = uni.createCanvasContext(_this.canvasID, _this); |
| | | // 设置 canvas 背景色 |
| | | ctx.setFillStyle('#FFFFFF'); |
| | | ctx.fillRect(0, 0, _this.canvasWidth, _this.canvasHeight); |
| | | ctx.setFillStyle('#000000'); |
| | | // 背景图片 |
| | | //需要下载图片 |
| | | |
| | | if (_this.localImgPath) { |
| | | console.log('localImgPath', _this.localImgPath) |
| | | ctx.drawImage(_this.localImgPath, 20, 20, 335, 500); |
| | | } |
| | | // ctx.setFontSize(18); |
| | | // ctx.setTextAlign('center'); |
| | | // ctx.fillText(_this.shareTitle, _this.canvasWidth / 2, 30); |
| | | // 左边标题 |
| | | ctx.setTextAlign('left') |
| | | ctx.setFontSize(22) |
| | | _this.writeTextOnCanvas(ctx, 20, 21, _this.goodsTitle, 20, 560); |
| | | ctx.setTextAlign('left') |
| | | ctx.setFontSize(16) |
| | | _this.writeTextOnCanvas(ctx, 20, 21, _this.goodsTitle2, 20, 585); |
| | | // 设置虚线 |
| | | // ctx.setStrokeStyle('#333333'); |
| | | // ctx.setLineDash([5, 10], 2); |
| | | // ctx.beginPath(); |
| | | // ctx.moveTo(220, 340); |
| | | // ctx.lineTo(220, 420); |
| | | // ctx.stroke(); |
| | | // 二维码 |
| | | ctx.drawImage(_this.qrCode, 250, 520, 100, 100); |
| | | // ctx.draw(); |
| | | |
| | | // 延迟后渲染至canvas上 |
| | | let pic = await _this.setTime(ctx) |
| | | _this.$emit('success', pic); |
| | | }, |
| | | /** |
| | | * @param {Object} ctx_2d getContext("2d") 对象 |
| | | * @param {int} lineheight 段落文本行高 |
| | | * @param {int} bytelength 设置单字节文字一行内的数量 |
| | | * @param {string} text 写入画面的段落文本 |
| | | * @param {int} startleft 开始绘制文本的 x 坐标位置(相对于画布) |
| | | * @param {int} starttop 开始绘制文本的 y 坐标位置(相对于画布) |
| | | */ |
| | | writeTextOnCanvas(ctx_2d, lineheight, bytelength, text, startleft, starttop) { |
| | | // 获取字符串的真实长度(字节长度) |
| | | function getTrueLength(str) { |
| | | var len = str.length, |
| | | truelen = 0; |
| | | for (var x = 0; x < len; x++) { |
| | | if (str.charCodeAt(x) > 128) { |
| | | truelen += 2; |
| | | } else { |
| | | truelen += 1; |
| | | } |
| | | } |
| | | return truelen; |
| | | } |
| | | // 按字节长度截取字符串,返回substr截取位置 |
| | | function cutString(str, leng) { |
| | | var len = str.length, |
| | | tlen = len, |
| | | nlen = 0; |
| | | for (var x = 0; x < len; x++) { |
| | | if (str.charCodeAt(x) > 128) { |
| | | if (nlen + 2 < leng) { |
| | | nlen += 2; |
| | | } else { |
| | | tlen = x; |
| | | break; |
| | | } |
| | | } else { |
| | | if (nlen + 1 < leng) { |
| | | nlen += 1; |
| | | } else { |
| | | tlen = x; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | return tlen; |
| | | } |
| | | for (var i = 1; getTrueLength(text) > 0; i++) { |
| | | var tl = cutString(text, bytelength); |
| | | ctx_2d.fillText(text.substr(0, tl).replace(/^\s+|\s+$/, ""), startleft, (i - 1) * lineheight + |
| | | starttop); |
| | | text = text.substr(tl); |
| | | } |
| | | }, |
| | | // 彻底改成同步 防止拿到的图片地址为空 |
| | | setTime(ctx) { |
| | | return new Promise((resole, err) => { |
| | | setTimeout(() => { |
| | | ctx.draw(false, async () => { |
| | | let pic = await _this.getNewPic(); |
| | | resole(pic) |
| | | }); |
| | | }, 600) |
| | | }) |
| | | }, |
| | | // 获取新的图片地址 |
| | | getNewPic() { |
| | | return new Promise((resolve, errs) => { |
| | | setTimeout(() => { |
| | | uni.canvasToTempFilePath({ |
| | | canvasId: _this.canvasID, |
| | | quality: 1, |
| | | complete: (res) => { |
| | | // 在H5平台下,tempFilePath 为 base64 |
| | | // 关闭showLoading |
| | | uni.hideLoading(); |
| | | // 储存海报地址 也是分享的地址 |
| | | resolve(res.tempFilePath) |
| | | } |
| | | }, _this); |
| | | }, 200) |
| | | }) |
| | | }, |
| | | }, |
| | | mounted() { |
| | | _this = this; |
| | | } |
| | | } |
| | | </script> |
对比新文件 |
| | |
| | | //--------------------------------------------------------------------- |
| | | // github https://github.com/Sansnn/uQRCode |
| | | // version 2.0.2 |
| | | //--------------------------------------------------------------------- |
| | | |
| | | let uQRCode = {}; |
| | | |
| | | (function() { |
| | | //--------------------------------------------------------------------- |
| | | // QRCode for JavaScript |
| | | // |
| | | // Copyright (c) 2009 Kazuhiko Arase |
| | | // |
| | | // URL: http://www.d-project.com/ |
| | | // |
| | | // Licensed under the MIT license: |
| | | // http://www.opensource.org/licenses/mit-license.php |
| | | // |
| | | // The word "QR Code" is registered trademark of |
| | | // DENSO WAVE INCORPORATED |
| | | // http://www.denso-wave.com/qrcode/faqpatent-e.html |
| | | // |
| | | //--------------------------------------------------------------------- |
| | | |
| | | //--------------------------------------------------------------------- |
| | | // QR8bitByte |
| | | //--------------------------------------------------------------------- |
| | | |
| | | function QR8bitByte(data) { |
| | | this.mode = QRMode.MODE_8BIT_BYTE; |
| | | this.data = data; |
| | | } |
| | | |
| | | QR8bitByte.prototype = { |
| | | |
| | | getLength: function(buffer) { |
| | | return this.data.length; |
| | | }, |
| | | |
| | | write: function(buffer) { |
| | | for (var i = 0; i < this.data.length; i++) { |
| | | // not JIS ... |
| | | buffer.put(this.data.charCodeAt(i), 8); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | //--------------------------------------------------------------------- |
| | | // QRCode |
| | | //--------------------------------------------------------------------- |
| | | |
| | | function QRCode(typeNumber, errorCorrectLevel) { |
| | | this.typeNumber = typeNumber; |
| | | this.errorCorrectLevel = errorCorrectLevel; |
| | | this.modules = null; |
| | | this.moduleCount = 0; |
| | | this.dataCache = null; |
| | | this.dataList = new Array(); |
| | | } |
| | | |
| | | QRCode.prototype = { |
| | | |
| | | addData: function(data) { |
| | | var newData = new QR8bitByte(data); |
| | | this.dataList.push(newData); |
| | | this.dataCache = null; |
| | | }, |
| | | |
| | | isDark: function(row, col) { |
| | | if (row < 0 || this.moduleCount <= row || col < 0 || this.moduleCount <= col) { |
| | | throw new Error(row + "," + col); |
| | | } |
| | | return this.modules[row][col]; |
| | | }, |
| | | |
| | | getModuleCount: function() { |
| | | return this.moduleCount; |
| | | }, |
| | | |
| | | make: function() { |
| | | // Calculate automatically typeNumber if provided is < 1 |
| | | if (this.typeNumber < 1) { |
| | | var typeNumber = 1; |
| | | for (typeNumber = 1; typeNumber < 40; typeNumber++) { |
| | | var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, this.errorCorrectLevel); |
| | | |
| | | var buffer = new QRBitBuffer(); |
| | | var totalDataCount = 0; |
| | | for (var i = 0; i < rsBlocks.length; i++) { |
| | | totalDataCount += rsBlocks[i].dataCount; |
| | | } |
| | | |
| | | for (var i = 0; i < this.dataList.length; i++) { |
| | | var data = this.dataList[i]; |
| | | buffer.put(data.mode, 4); |
| | | buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber)); |
| | | data.write(buffer); |
| | | } |
| | | if (buffer.getLengthInBits() <= totalDataCount * 8) |
| | | break; |
| | | } |
| | | this.typeNumber = typeNumber; |
| | | } |
| | | this.makeImpl(false, this.getBestMaskPattern()); |
| | | }, |
| | | |
| | | makeImpl: function(test, maskPattern) { |
| | | |
| | | this.moduleCount = this.typeNumber * 4 + 17; |
| | | this.modules = new Array(this.moduleCount); |
| | | |
| | | for (var row = 0; row < this.moduleCount; row++) { |
| | | |
| | | this.modules[row] = new Array(this.moduleCount); |
| | | |
| | | for (var col = 0; col < this.moduleCount; col++) { |
| | | this.modules[row][col] = null; //(col + row) % 3; |
| | | } |
| | | } |
| | | |
| | | this.setupPositionProbePattern(0, 0); |
| | | this.setupPositionProbePattern(this.moduleCount - 7, 0); |
| | | this.setupPositionProbePattern(0, this.moduleCount - 7); |
| | | this.setupPositionAdjustPattern(); |
| | | this.setupTimingPattern(); |
| | | this.setupTypeInfo(test, maskPattern); |
| | | |
| | | if (this.typeNumber >= 7) { |
| | | this.setupTypeNumber(test); |
| | | } |
| | | |
| | | if (this.dataCache == null) { |
| | | this.dataCache = QRCode.createData(this.typeNumber, this.errorCorrectLevel, this.dataList); |
| | | } |
| | | |
| | | this.mapData(this.dataCache, maskPattern); |
| | | }, |
| | | |
| | | setupPositionProbePattern: function(row, col) { |
| | | |
| | | for (var r = -1; r <= 7; r++) { |
| | | |
| | | if (row + r <= -1 || this.moduleCount <= row + r) continue; |
| | | |
| | | for (var c = -1; c <= 7; c++) { |
| | | |
| | | if (col + c <= -1 || this.moduleCount <= col + c) continue; |
| | | |
| | | if ((0 <= r && r <= 6 && (c == 0 || c == 6)) || |
| | | (0 <= c && c <= 6 && (r == 0 || r == 6)) || |
| | | (2 <= r && r <= 4 && 2 <= c && c <= 4)) { |
| | | this.modules[row + r][col + c] = true; |
| | | } else { |
| | | this.modules[row + r][col + c] = false; |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | |
| | | getBestMaskPattern: function() { |
| | | |
| | | var minLostPoint = 0; |
| | | var pattern = 0; |
| | | |
| | | for (var i = 0; i < 8; i++) { |
| | | |
| | | this.makeImpl(true, i); |
| | | |
| | | var lostPoint = QRUtil.getLostPoint(this); |
| | | |
| | | if (i == 0 || minLostPoint > lostPoint) { |
| | | minLostPoint = lostPoint; |
| | | pattern = i; |
| | | } |
| | | } |
| | | |
| | | return pattern; |
| | | }, |
| | | |
| | | createMovieClip: function(target_mc, instance_name, depth) { |
| | | |
| | | var qr_mc = target_mc.createEmptyMovieClip(instance_name, depth); |
| | | var cs = 1; |
| | | |
| | | this.make(); |
| | | |
| | | for (var row = 0; row < this.modules.length; row++) { |
| | | |
| | | var y = row * cs; |
| | | |
| | | for (var col = 0; col < this.modules[row].length; col++) { |
| | | |
| | | var x = col * cs; |
| | | var dark = this.modules[row][col]; |
| | | |
| | | if (dark) { |
| | | qr_mc.beginFill(0, 100); |
| | | qr_mc.moveTo(x, y); |
| | | qr_mc.lineTo(x + cs, y); |
| | | qr_mc.lineTo(x + cs, y + cs); |
| | | qr_mc.lineTo(x, y + cs); |
| | | qr_mc.endFill(); |
| | | } |
| | | } |
| | | } |
| | | return qr_mc; |
| | | }, |
| | | |
| | | setupTimingPattern: function() { |
| | | |
| | | for (var r = 8; r < this.moduleCount - 8; r++) { |
| | | if (this.modules[r][6] != null) { |
| | | continue; |
| | | } |
| | | this.modules[r][6] = (r % 2 == 0); |
| | | } |
| | | |
| | | for (var c = 8; c < this.moduleCount - 8; c++) { |
| | | if (this.modules[6][c] != null) { |
| | | continue; |
| | | } |
| | | this.modules[6][c] = (c % 2 == 0); |
| | | } |
| | | }, |
| | | |
| | | setupPositionAdjustPattern: function() { |
| | | |
| | | var pos = QRUtil.getPatternPosition(this.typeNumber); |
| | | |
| | | for (var i = 0; i < pos.length; i++) { |
| | | |
| | | for (var j = 0; j < pos.length; j++) { |
| | | |
| | | var row = pos[i]; |
| | | var col = pos[j]; |
| | | |
| | | if (this.modules[row][col] != null) { |
| | | continue; |
| | | } |
| | | |
| | | for (var r = -2; r <= 2; r++) { |
| | | |
| | | for (var c = -2; c <= 2; c++) { |
| | | |
| | | if (r == -2 || r == 2 || c == -2 || c == 2 || |
| | | (r == 0 && c == 0)) { |
| | | this.modules[row + r][col + c] = true; |
| | | } else { |
| | | this.modules[row + r][col + c] = false; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | |
| | | setupTypeNumber: function(test) { |
| | | |
| | | var bits = QRUtil.getBCHTypeNumber(this.typeNumber); |
| | | |
| | | for (var i = 0; i < 18; i++) { |
| | | var mod = (!test && ((bits >> i) & 1) == 1); |
| | | this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod; |
| | | } |
| | | |
| | | for (var i = 0; i < 18; i++) { |
| | | var mod = (!test && ((bits >> i) & 1) == 1); |
| | | this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod; |
| | | } |
| | | }, |
| | | |
| | | setupTypeInfo: function(test, maskPattern) { |
| | | |
| | | var data = (this.errorCorrectLevel << 3) | maskPattern; |
| | | var bits = QRUtil.getBCHTypeInfo(data); |
| | | |
| | | // vertical |
| | | for (var i = 0; i < 15; i++) { |
| | | |
| | | var mod = (!test && ((bits >> i) & 1) == 1); |
| | | |
| | | if (i < 6) { |
| | | this.modules[i][8] = mod; |
| | | } else if (i < 8) { |
| | | this.modules[i + 1][8] = mod; |
| | | } else { |
| | | this.modules[this.moduleCount - 15 + i][8] = mod; |
| | | } |
| | | } |
| | | |
| | | // horizontal |
| | | for (var i = 0; i < 15; i++) { |
| | | |
| | | var mod = (!test && ((bits >> i) & 1) == 1); |
| | | |
| | | if (i < 8) { |
| | | this.modules[8][this.moduleCount - i - 1] = mod; |
| | | } else if (i < 9) { |
| | | this.modules[8][15 - i - 1 + 1] = mod; |
| | | } else { |
| | | this.modules[8][15 - i - 1] = mod; |
| | | } |
| | | } |
| | | |
| | | // fixed module |
| | | this.modules[this.moduleCount - 8][8] = (!test); |
| | | |
| | | }, |
| | | |
| | | mapData: function(data, maskPattern) { |
| | | |
| | | var inc = -1; |
| | | var row = this.moduleCount - 1; |
| | | var bitIndex = 7; |
| | | var byteIndex = 0; |
| | | |
| | | for (var col = this.moduleCount - 1; col > 0; col -= 2) { |
| | | |
| | | if (col == 6) col--; |
| | | |
| | | while (true) { |
| | | |
| | | for (var c = 0; c < 2; c++) { |
| | | |
| | | if (this.modules[row][col - c] == null) { |
| | | |
| | | var dark = false; |
| | | |
| | | if (byteIndex < data.length) { |
| | | dark = (((data[byteIndex] >>> bitIndex) & 1) == 1); |
| | | } |
| | | |
| | | var mask = QRUtil.getMask(maskPattern, row, col - c); |
| | | |
| | | if (mask) { |
| | | dark = !dark; |
| | | } |
| | | |
| | | this.modules[row][col - c] = dark; |
| | | bitIndex--; |
| | | |
| | | if (bitIndex == -1) { |
| | | byteIndex++; |
| | | bitIndex = 7; |
| | | } |
| | | } |
| | | } |
| | | |
| | | row += inc; |
| | | |
| | | if (row < 0 || this.moduleCount <= row) { |
| | | row -= inc; |
| | | inc = -inc; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | |
| | | QRCode.PAD0 = 0xEC; |
| | | QRCode.PAD1 = 0x11; |
| | | |
| | | QRCode.createData = function(typeNumber, errorCorrectLevel, dataList) { |
| | | |
| | | var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel); |
| | | |
| | | var buffer = new QRBitBuffer(); |
| | | |
| | | for (var i = 0; i < dataList.length; i++) { |
| | | var data = dataList[i]; |
| | | buffer.put(data.mode, 4); |
| | | buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber)); |
| | | data.write(buffer); |
| | | } |
| | | |
| | | // calc num max data. |
| | | var totalDataCount = 0; |
| | | for (var i = 0; i < rsBlocks.length; i++) { |
| | | totalDataCount += rsBlocks[i].dataCount; |
| | | } |
| | | |
| | | if (buffer.getLengthInBits() > totalDataCount * 8) { |
| | | throw new Error("code length overflow. (" + |
| | | buffer.getLengthInBits() + |
| | | ">" + |
| | | totalDataCount * 8 + |
| | | ")"); |
| | | } |
| | | |
| | | // end code |
| | | if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) { |
| | | buffer.put(0, 4); |
| | | } |
| | | |
| | | // padding |
| | | while (buffer.getLengthInBits() % 8 != 0) { |
| | | buffer.putBit(false); |
| | | } |
| | | |
| | | // padding |
| | | while (true) { |
| | | |
| | | if (buffer.getLengthInBits() >= totalDataCount * 8) { |
| | | break; |
| | | } |
| | | buffer.put(QRCode.PAD0, 8); |
| | | |
| | | if (buffer.getLengthInBits() >= totalDataCount * 8) { |
| | | break; |
| | | } |
| | | buffer.put(QRCode.PAD1, 8); |
| | | } |
| | | |
| | | return QRCode.createBytes(buffer, rsBlocks); |
| | | } |
| | | |
| | | QRCode.createBytes = function(buffer, rsBlocks) { |
| | | var offset = 0; |
| | | var maxDcCount = 0; |
| | | var maxEcCount = 0; |
| | | |
| | | var dcdata = new Array(rsBlocks.length); |
| | | var ecdata = new Array(rsBlocks.length); |
| | | |
| | | for (var r = 0; r < rsBlocks.length; r++) { |
| | | |
| | | var dcCount = rsBlocks[r].dataCount; |
| | | var ecCount = rsBlocks[r].totalCount - dcCount; |
| | | |
| | | maxDcCount = Math.max(maxDcCount, dcCount); |
| | | maxEcCount = Math.max(maxEcCount, ecCount); |
| | | |
| | | dcdata[r] = new Array(dcCount); |
| | | |
| | | for (var i = 0; i < dcdata[r].length; i++) { |
| | | dcdata[r][i] = 0xff & buffer.buffer[i + offset]; |
| | | } |
| | | offset += dcCount; |
| | | |
| | | var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount); |
| | | var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1); |
| | | |
| | | var modPoly = rawPoly.mod(rsPoly); |
| | | ecdata[r] = new Array(rsPoly.getLength() - 1); |
| | | for (var i = 0; i < ecdata[r].length; i++) { |
| | | var modIndex = i + modPoly.getLength() - ecdata[r].length; |
| | | ecdata[r][i] = (modIndex >= 0) ? modPoly.get(modIndex) : 0; |
| | | } |
| | | |
| | | } |
| | | |
| | | var totalCodeCount = 0; |
| | | for (var i = 0; i < rsBlocks.length; i++) { |
| | | totalCodeCount += rsBlocks[i].totalCount; |
| | | } |
| | | |
| | | var data = new Array(totalCodeCount); |
| | | var index = 0; |
| | | |
| | | for (var i = 0; i < maxDcCount; i++) { |
| | | for (var r = 0; r < rsBlocks.length; r++) { |
| | | if (i < dcdata[r].length) { |
| | | data[index++] = dcdata[r][i]; |
| | | } |
| | | } |
| | | } |
| | | |
| | | for (var i = 0; i < maxEcCount; i++) { |
| | | for (var r = 0; r < rsBlocks.length; r++) { |
| | | if (i < ecdata[r].length) { |
| | | data[index++] = ecdata[r][i]; |
| | | } |
| | | } |
| | | } |
| | | return data; |
| | | } |
| | | |
| | | //--------------------------------------------------------------------- |
| | | // QRMode |
| | | //--------------------------------------------------------------------- |
| | | |
| | | var QRMode = { |
| | | MODE_NUMBER: 1 << 0, |
| | | MODE_ALPHA_NUM: 1 << 1, |
| | | MODE_8BIT_BYTE: 1 << 2, |
| | | MODE_KANJI: 1 << 3 |
| | | }; |
| | | |
| | | //--------------------------------------------------------------------- |
| | | // QRErrorCorrectLevel |
| | | //--------------------------------------------------------------------- |
| | | |
| | | var QRErrorCorrectLevel = { |
| | | L: 1, |
| | | M: 0, |
| | | Q: 3, |
| | | H: 2 |
| | | }; |
| | | |
| | | //--------------------------------------------------------------------- |
| | | // QRMaskPattern |
| | | //--------------------------------------------------------------------- |
| | | |
| | | var QRMaskPattern = { |
| | | PATTERN000: 0, |
| | | PATTERN001: 1, |
| | | PATTERN010: 2, |
| | | PATTERN011: 3, |
| | | PATTERN100: 4, |
| | | PATTERN101: 5, |
| | | PATTERN110: 6, |
| | | PATTERN111: 7 |
| | | }; |
| | | |
| | | //--------------------------------------------------------------------- |
| | | // QRUtil |
| | | //--------------------------------------------------------------------- |
| | | |
| | | var QRUtil = { |
| | | |
| | | PATTERN_POSITION_TABLE: [ |
| | | [], |
| | | [6, 18], |
| | | [6, 22], |
| | | [6, 26], |
| | | [6, 30], |
| | | [6, 34], |
| | | [6, 22, 38], |
| | | [6, 24, 42], |
| | | [6, 26, 46], |
| | | [6, 28, 50], |
| | | [6, 30, 54], |
| | | [6, 32, 58], |
| | | [6, 34, 62], |
| | | [6, 26, 46, 66], |
| | | [6, 26, 48, 70], |
| | | [6, 26, 50, 74], |
| | | [6, 30, 54, 78], |
| | | [6, 30, 56, 82], |
| | | [6, 30, 58, 86], |
| | | [6, 34, 62, 90], |
| | | [6, 28, 50, 72, 94], |
| | | [6, 26, 50, 74, 98], |
| | | [6, 30, 54, 78, 102], |
| | | [6, 28, 54, 80, 106], |
| | | [6, 32, 58, 84, 110], |
| | | [6, 30, 58, 86, 114], |
| | | [6, 34, 62, 90, 118], |
| | | [6, 26, 50, 74, 98, 122], |
| | | [6, 30, 54, 78, 102, 126], |
| | | [6, 26, 52, 78, 104, 130], |
| | | [6, 30, 56, 82, 108, 134], |
| | | [6, 34, 60, 86, 112, 138], |
| | | [6, 30, 58, 86, 114, 142], |
| | | [6, 34, 62, 90, 118, 146], |
| | | [6, 30, 54, 78, 102, 126, 150], |
| | | [6, 24, 50, 76, 102, 128, 154], |
| | | [6, 28, 54, 80, 106, 132, 158], |
| | | [6, 32, 58, 84, 110, 136, 162], |
| | | [6, 26, 54, 82, 110, 138, 166], |
| | | [6, 30, 58, 86, 114, 142, 170] |
| | | ], |
| | | |
| | | G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0), |
| | | G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0), |
| | | G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1), |
| | | |
| | | getBCHTypeInfo: function(data) { |
| | | var d = data << 10; |
| | | while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) { |
| | | d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15))); |
| | | } |
| | | return ((data << 10) | d) ^ QRUtil.G15_MASK; |
| | | }, |
| | | |
| | | getBCHTypeNumber: function(data) { |
| | | var d = data << 12; |
| | | while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) { |
| | | d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18))); |
| | | } |
| | | return (data << 12) | d; |
| | | }, |
| | | |
| | | getBCHDigit: function(data) { |
| | | |
| | | var digit = 0; |
| | | |
| | | while (data != 0) { |
| | | digit++; |
| | | data >>>= 1; |
| | | } |
| | | |
| | | return digit; |
| | | }, |
| | | |
| | | getPatternPosition: function(typeNumber) { |
| | | return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1]; |
| | | }, |
| | | |
| | | getMask: function(maskPattern, i, j) { |
| | | |
| | | switch (maskPattern) { |
| | | |
| | | case QRMaskPattern.PATTERN000: |
| | | return (i + j) % 2 == 0; |
| | | case QRMaskPattern.PATTERN001: |
| | | return i % 2 == 0; |
| | | case QRMaskPattern.PATTERN010: |
| | | return j % 3 == 0; |
| | | case QRMaskPattern.PATTERN011: |
| | | return (i + j) % 3 == 0; |
| | | case QRMaskPattern.PATTERN100: |
| | | return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0; |
| | | case QRMaskPattern.PATTERN101: |
| | | return (i * j) % 2 + (i * j) % 3 == 0; |
| | | case QRMaskPattern.PATTERN110: |
| | | return ((i * j) % 2 + (i * j) % 3) % 2 == 0; |
| | | case QRMaskPattern.PATTERN111: |
| | | return ((i * j) % 3 + (i + j) % 2) % 2 == 0; |
| | | |
| | | default: |
| | | throw new Error("bad maskPattern:" + maskPattern); |
| | | } |
| | | }, |
| | | |
| | | getErrorCorrectPolynomial: function(errorCorrectLength) { |
| | | |
| | | var a = new QRPolynomial([1], 0); |
| | | |
| | | for (var i = 0; i < errorCorrectLength; i++) { |
| | | a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0)); |
| | | } |
| | | |
| | | return a; |
| | | }, |
| | | |
| | | getLengthInBits: function(mode, type) { |
| | | |
| | | if (1 <= type && type < 10) { |
| | | |
| | | // 1 - 9 |
| | | |
| | | switch (mode) { |
| | | case QRMode.MODE_NUMBER: |
| | | return 10; |
| | | case QRMode.MODE_ALPHA_NUM: |
| | | return 9; |
| | | case QRMode.MODE_8BIT_BYTE: |
| | | return 8; |
| | | case QRMode.MODE_KANJI: |
| | | return 8; |
| | | default: |
| | | throw new Error("mode:" + mode); |
| | | } |
| | | |
| | | } else if (type < 27) { |
| | | |
| | | // 10 - 26 |
| | | |
| | | switch (mode) { |
| | | case QRMode.MODE_NUMBER: |
| | | return 12; |
| | | case QRMode.MODE_ALPHA_NUM: |
| | | return 11; |
| | | case QRMode.MODE_8BIT_BYTE: |
| | | return 16; |
| | | case QRMode.MODE_KANJI: |
| | | return 10; |
| | | default: |
| | | throw new Error("mode:" + mode); |
| | | } |
| | | |
| | | } else if (type < 41) { |
| | | |
| | | // 27 - 40 |
| | | |
| | | switch (mode) { |
| | | case QRMode.MODE_NUMBER: |
| | | return 14; |
| | | case QRMode.MODE_ALPHA_NUM: |
| | | return 13; |
| | | case QRMode.MODE_8BIT_BYTE: |
| | | return 16; |
| | | case QRMode.MODE_KANJI: |
| | | return 12; |
| | | default: |
| | | throw new Error("mode:" + mode); |
| | | } |
| | | |
| | | } else { |
| | | throw new Error("type:" + type); |
| | | } |
| | | }, |
| | | |
| | | getLostPoint: function(qrCode) { |
| | | |
| | | var moduleCount = qrCode.getModuleCount(); |
| | | |
| | | var lostPoint = 0; |
| | | |
| | | // LEVEL1 |
| | | |
| | | for (var row = 0; row < moduleCount; row++) { |
| | | |
| | | for (var col = 0; col < moduleCount; col++) { |
| | | |
| | | var sameCount = 0; |
| | | var dark = qrCode.isDark(row, col); |
| | | |
| | | for (var r = -1; r <= 1; r++) { |
| | | |
| | | if (row + r < 0 || moduleCount <= row + r) { |
| | | continue; |
| | | } |
| | | |
| | | for (var c = -1; c <= 1; c++) { |
| | | |
| | | if (col + c < 0 || moduleCount <= col + c) { |
| | | continue; |
| | | } |
| | | |
| | | if (r == 0 && c == 0) { |
| | | continue; |
| | | } |
| | | |
| | | if (dark == qrCode.isDark(row + r, col + c)) { |
| | | sameCount++; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (sameCount > 5) { |
| | | lostPoint += (3 + sameCount - 5); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // LEVEL2 |
| | | |
| | | for (var row = 0; row < moduleCount - 1; row++) { |
| | | for (var col = 0; col < moduleCount - 1; col++) { |
| | | var count = 0; |
| | | if (qrCode.isDark(row, col)) count++; |
| | | if (qrCode.isDark(row + 1, col)) count++; |
| | | if (qrCode.isDark(row, col + 1)) count++; |
| | | if (qrCode.isDark(row + 1, col + 1)) count++; |
| | | if (count == 0 || count == 4) { |
| | | lostPoint += 3; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // LEVEL3 |
| | | |
| | | for (var row = 0; row < moduleCount; row++) { |
| | | for (var col = 0; col < moduleCount - 6; col++) { |
| | | if (qrCode.isDark(row, col) && |
| | | !qrCode.isDark(row, col + 1) && |
| | | qrCode.isDark(row, col + 2) && |
| | | qrCode.isDark(row, col + 3) && |
| | | qrCode.isDark(row, col + 4) && |
| | | !qrCode.isDark(row, col + 5) && |
| | | qrCode.isDark(row, col + 6)) { |
| | | lostPoint += 40; |
| | | } |
| | | } |
| | | } |
| | | |
| | | for (var col = 0; col < moduleCount; col++) { |
| | | for (var row = 0; row < moduleCount - 6; row++) { |
| | | if (qrCode.isDark(row, col) && |
| | | !qrCode.isDark(row + 1, col) && |
| | | qrCode.isDark(row + 2, col) && |
| | | qrCode.isDark(row + 3, col) && |
| | | qrCode.isDark(row + 4, col) && |
| | | !qrCode.isDark(row + 5, col) && |
| | | qrCode.isDark(row + 6, col)) { |
| | | lostPoint += 40; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // LEVEL4 |
| | | |
| | | var darkCount = 0; |
| | | |
| | | for (var col = 0; col < moduleCount; col++) { |
| | | for (var row = 0; row < moduleCount; row++) { |
| | | if (qrCode.isDark(row, col)) { |
| | | darkCount++; |
| | | } |
| | | } |
| | | } |
| | | |
| | | var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5; |
| | | lostPoint += ratio * 10; |
| | | |
| | | return lostPoint; |
| | | } |
| | | |
| | | }; |
| | | |
| | | |
| | | //--------------------------------------------------------------------- |
| | | // QRMath |
| | | //--------------------------------------------------------------------- |
| | | |
| | | var QRMath = { |
| | | |
| | | glog: function(n) { |
| | | |
| | | if (n < 1) { |
| | | throw new Error("glog(" + n + ")"); |
| | | } |
| | | |
| | | return QRMath.LOG_TABLE[n]; |
| | | }, |
| | | |
| | | gexp: function(n) { |
| | | |
| | | while (n < 0) { |
| | | n += 255; |
| | | } |
| | | |
| | | while (n >= 256) { |
| | | n -= 255; |
| | | } |
| | | |
| | | return QRMath.EXP_TABLE[n]; |
| | | }, |
| | | |
| | | EXP_TABLE: new Array(256), |
| | | |
| | | LOG_TABLE: new Array(256) |
| | | |
| | | }; |
| | | |
| | | for (var i = 0; i < 8; i++) { |
| | | QRMath.EXP_TABLE[i] = 1 << i; |
| | | } |
| | | for (var i = 8; i < 256; i++) { |
| | | QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] ^ |
| | | QRMath.EXP_TABLE[i - 5] ^ |
| | | QRMath.EXP_TABLE[i - 6] ^ |
| | | QRMath.EXP_TABLE[i - 8]; |
| | | } |
| | | for (var i = 0; i < 255; i++) { |
| | | QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i; |
| | | } |
| | | |
| | | //--------------------------------------------------------------------- |
| | | // QRPolynomial |
| | | //--------------------------------------------------------------------- |
| | | |
| | | function QRPolynomial(num, shift) { |
| | | |
| | | if (num.length == undefined) { |
| | | throw new Error(num.length + "/" + shift); |
| | | } |
| | | |
| | | var offset = 0; |
| | | |
| | | while (offset < num.length && num[offset] == 0) { |
| | | offset++; |
| | | } |
| | | |
| | | this.num = new Array(num.length - offset + shift); |
| | | for (var i = 0; i < num.length - offset; i++) { |
| | | this.num[i] = num[i + offset]; |
| | | } |
| | | } |
| | | |
| | | QRPolynomial.prototype = { |
| | | |
| | | get: function(index) { |
| | | return this.num[index]; |
| | | }, |
| | | |
| | | getLength: function() { |
| | | return this.num.length; |
| | | }, |
| | | |
| | | multiply: function(e) { |
| | | |
| | | var num = new Array(this.getLength() + e.getLength() - 1); |
| | | |
| | | for (var i = 0; i < this.getLength(); i++) { |
| | | for (var j = 0; j < e.getLength(); j++) { |
| | | num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j))); |
| | | } |
| | | } |
| | | |
| | | return new QRPolynomial(num, 0); |
| | | }, |
| | | |
| | | mod: function(e) { |
| | | |
| | | if (this.getLength() - e.getLength() < 0) { |
| | | return this; |
| | | } |
| | | |
| | | var ratio = QRMath.glog(this.get(0)) - QRMath.glog(e.get(0)); |
| | | |
| | | var num = new Array(this.getLength()); |
| | | |
| | | for (var i = 0; i < this.getLength(); i++) { |
| | | num[i] = this.get(i); |
| | | } |
| | | |
| | | for (var i = 0; i < e.getLength(); i++) { |
| | | num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio); |
| | | } |
| | | |
| | | // recursive call |
| | | return new QRPolynomial(num, 0).mod(e); |
| | | } |
| | | }; |
| | | |
| | | //--------------------------------------------------------------------- |
| | | // QRRSBlock |
| | | //--------------------------------------------------------------------- |
| | | |
| | | function QRRSBlock(totalCount, dataCount) { |
| | | this.totalCount = totalCount; |
| | | this.dataCount = dataCount; |
| | | } |
| | | |
| | | QRRSBlock.RS_BLOCK_TABLE = [ |
| | | |
| | | // L |
| | | // M |
| | | // Q |
| | | // H |
| | | |
| | | // 1 |
| | | [1, 26, 19], |
| | | [1, 26, 16], |
| | | [1, 26, 13], |
| | | [1, 26, 9], |
| | | |
| | | // 2 |
| | | [1, 44, 34], |
| | | [1, 44, 28], |
| | | [1, 44, 22], |
| | | [1, 44, 16], |
| | | |
| | | // 3 |
| | | [1, 70, 55], |
| | | [1, 70, 44], |
| | | [2, 35, 17], |
| | | [2, 35, 13], |
| | | |
| | | // 4 |
| | | [1, 100, 80], |
| | | [2, 50, 32], |
| | | [2, 50, 24], |
| | | [4, 25, 9], |
| | | |
| | | // 5 |
| | | [1, 134, 108], |
| | | [2, 67, 43], |
| | | [2, 33, 15, 2, 34, 16], |
| | | [2, 33, 11, 2, 34, 12], |
| | | |
| | | // 6 |
| | | [2, 86, 68], |
| | | [4, 43, 27], |
| | | [4, 43, 19], |
| | | [4, 43, 15], |
| | | |
| | | // 7 |
| | | [2, 98, 78], |
| | | [4, 49, 31], |
| | | [2, 32, 14, 4, 33, 15], |
| | | [4, 39, 13, 1, 40, 14], |
| | | |
| | | // 8 |
| | | [2, 121, 97], |
| | | [2, 60, 38, 2, 61, 39], |
| | | [4, 40, 18, 2, 41, 19], |
| | | [4, 40, 14, 2, 41, 15], |
| | | |
| | | // 9 |
| | | [2, 146, 116], |
| | | [3, 58, 36, 2, 59, 37], |
| | | [4, 36, 16, 4, 37, 17], |
| | | [4, 36, 12, 4, 37, 13], |
| | | |
| | | // 10 |
| | | [2, 86, 68, 2, 87, 69], |
| | | [4, 69, 43, 1, 70, 44], |
| | | [6, 43, 19, 2, 44, 20], |
| | | [6, 43, 15, 2, 44, 16], |
| | | |
| | | // 11 |
| | | [4, 101, 81], |
| | | [1, 80, 50, 4, 81, 51], |
| | | [4, 50, 22, 4, 51, 23], |
| | | [3, 36, 12, 8, 37, 13], |
| | | |
| | | // 12 |
| | | [2, 116, 92, 2, 117, 93], |
| | | [6, 58, 36, 2, 59, 37], |
| | | [4, 46, 20, 6, 47, 21], |
| | | [7, 42, 14, 4, 43, 15], |
| | | |
| | | // 13 |
| | | [4, 133, 107], |
| | | [8, 59, 37, 1, 60, 38], |
| | | [8, 44, 20, 4, 45, 21], |
| | | [12, 33, 11, 4, 34, 12], |
| | | |
| | | // 14 |
| | | [3, 145, 115, 1, 146, 116], |
| | | [4, 64, 40, 5, 65, 41], |
| | | [11, 36, 16, 5, 37, 17], |
| | | [11, 36, 12, 5, 37, 13], |
| | | |
| | | // 15 |
| | | [5, 109, 87, 1, 110, 88], |
| | | [5, 65, 41, 5, 66, 42], |
| | | [5, 54, 24, 7, 55, 25], |
| | | [11, 36, 12], |
| | | |
| | | // 16 |
| | | [5, 122, 98, 1, 123, 99], |
| | | [7, 73, 45, 3, 74, 46], |
| | | [15, 43, 19, 2, 44, 20], |
| | | [3, 45, 15, 13, 46, 16], |
| | | |
| | | // 17 |
| | | [1, 135, 107, 5, 136, 108], |
| | | [10, 74, 46, 1, 75, 47], |
| | | [1, 50, 22, 15, 51, 23], |
| | | [2, 42, 14, 17, 43, 15], |
| | | |
| | | // 18 |
| | | [5, 150, 120, 1, 151, 121], |
| | | [9, 69, 43, 4, 70, 44], |
| | | [17, 50, 22, 1, 51, 23], |
| | | [2, 42, 14, 19, 43, 15], |
| | | |
| | | // 19 |
| | | [3, 141, 113, 4, 142, 114], |
| | | [3, 70, 44, 11, 71, 45], |
| | | [17, 47, 21, 4, 48, 22], |
| | | [9, 39, 13, 16, 40, 14], |
| | | |
| | | // 20 |
| | | [3, 135, 107, 5, 136, 108], |
| | | [3, 67, 41, 13, 68, 42], |
| | | [15, 54, 24, 5, 55, 25], |
| | | [15, 43, 15, 10, 44, 16], |
| | | |
| | | // 21 |
| | | [4, 144, 116, 4, 145, 117], |
| | | [17, 68, 42], |
| | | [17, 50, 22, 6, 51, 23], |
| | | [19, 46, 16, 6, 47, 17], |
| | | |
| | | // 22 |
| | | [2, 139, 111, 7, 140, 112], |
| | | [17, 74, 46], |
| | | [7, 54, 24, 16, 55, 25], |
| | | [34, 37, 13], |
| | | |
| | | // 23 |
| | | [4, 151, 121, 5, 152, 122], |
| | | [4, 75, 47, 14, 76, 48], |
| | | [11, 54, 24, 14, 55, 25], |
| | | [16, 45, 15, 14, 46, 16], |
| | | |
| | | // 24 |
| | | [6, 147, 117, 4, 148, 118], |
| | | [6, 73, 45, 14, 74, 46], |
| | | [11, 54, 24, 16, 55, 25], |
| | | [30, 46, 16, 2, 47, 17], |
| | | |
| | | // 25 |
| | | [8, 132, 106, 4, 133, 107], |
| | | [8, 75, 47, 13, 76, 48], |
| | | [7, 54, 24, 22, 55, 25], |
| | | [22, 45, 15, 13, 46, 16], |
| | | |
| | | // 26 |
| | | [10, 142, 114, 2, 143, 115], |
| | | [19, 74, 46, 4, 75, 47], |
| | | [28, 50, 22, 6, 51, 23], |
| | | [33, 46, 16, 4, 47, 17], |
| | | |
| | | // 27 |
| | | [8, 152, 122, 4, 153, 123], |
| | | [22, 73, 45, 3, 74, 46], |
| | | [8, 53, 23, 26, 54, 24], |
| | | [12, 45, 15, 28, 46, 16], |
| | | |
| | | // 28 |
| | | [3, 147, 117, 10, 148, 118], |
| | | [3, 73, 45, 23, 74, 46], |
| | | [4, 54, 24, 31, 55, 25], |
| | | [11, 45, 15, 31, 46, 16], |
| | | |
| | | // 29 |
| | | [7, 146, 116, 7, 147, 117], |
| | | [21, 73, 45, 7, 74, 46], |
| | | [1, 53, 23, 37, 54, 24], |
| | | [19, 45, 15, 26, 46, 16], |
| | | |
| | | // 30 |
| | | [5, 145, 115, 10, 146, 116], |
| | | [19, 75, 47, 10, 76, 48], |
| | | [15, 54, 24, 25, 55, 25], |
| | | [23, 45, 15, 25, 46, 16], |
| | | |
| | | // 31 |
| | | [13, 145, 115, 3, 146, 116], |
| | | [2, 74, 46, 29, 75, 47], |
| | | [42, 54, 24, 1, 55, 25], |
| | | [23, 45, 15, 28, 46, 16], |
| | | |
| | | // 32 |
| | | [17, 145, 115], |
| | | [10, 74, 46, 23, 75, 47], |
| | | [10, 54, 24, 35, 55, 25], |
| | | [19, 45, 15, 35, 46, 16], |
| | | |
| | | // 33 |
| | | [17, 145, 115, 1, 146, 116], |
| | | [14, 74, 46, 21, 75, 47], |
| | | [29, 54, 24, 19, 55, 25], |
| | | [11, 45, 15, 46, 46, 16], |
| | | |
| | | // 34 |
| | | [13, 145, 115, 6, 146, 116], |
| | | [14, 74, 46, 23, 75, 47], |
| | | [44, 54, 24, 7, 55, 25], |
| | | [59, 46, 16, 1, 47, 17], |
| | | |
| | | // 35 |
| | | [12, 151, 121, 7, 152, 122], |
| | | [12, 75, 47, 26, 76, 48], |
| | | [39, 54, 24, 14, 55, 25], |
| | | [22, 45, 15, 41, 46, 16], |
| | | |
| | | // 36 |
| | | [6, 151, 121, 14, 152, 122], |
| | | [6, 75, 47, 34, 76, 48], |
| | | [46, 54, 24, 10, 55, 25], |
| | | [2, 45, 15, 64, 46, 16], |
| | | |
| | | // 37 |
| | | [17, 152, 122, 4, 153, 123], |
| | | [29, 74, 46, 14, 75, 47], |
| | | [49, 54, 24, 10, 55, 25], |
| | | [24, 45, 15, 46, 46, 16], |
| | | |
| | | // 38 |
| | | [4, 152, 122, 18, 153, 123], |
| | | [13, 74, 46, 32, 75, 47], |
| | | [48, 54, 24, 14, 55, 25], |
| | | [42, 45, 15, 32, 46, 16], |
| | | |
| | | // 39 |
| | | [20, 147, 117, 4, 148, 118], |
| | | [40, 75, 47, 7, 76, 48], |
| | | [43, 54, 24, 22, 55, 25], |
| | | [10, 45, 15, 67, 46, 16], |
| | | |
| | | // 40 |
| | | [19, 148, 118, 6, 149, 119], |
| | | [18, 75, 47, 31, 76, 48], |
| | | [34, 54, 24, 34, 55, 25], |
| | | [20, 45, 15, 61, 46, 16] |
| | | ]; |
| | | |
| | | QRRSBlock.getRSBlocks = function(typeNumber, errorCorrectLevel) { |
| | | |
| | | var rsBlock = QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel); |
| | | |
| | | if (rsBlock == undefined) { |
| | | throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + |
| | | errorCorrectLevel); |
| | | } |
| | | |
| | | var length = rsBlock.length / 3; |
| | | |
| | | var list = new Array(); |
| | | |
| | | for (var i = 0; i < length; i++) { |
| | | |
| | | var count = rsBlock[i * 3 + 0]; |
| | | var totalCount = rsBlock[i * 3 + 1]; |
| | | var dataCount = rsBlock[i * 3 + 2]; |
| | | |
| | | for (var j = 0; j < count; j++) { |
| | | list.push(new QRRSBlock(totalCount, dataCount)); |
| | | } |
| | | } |
| | | |
| | | return list; |
| | | } |
| | | |
| | | QRRSBlock.getRsBlockTable = function(typeNumber, errorCorrectLevel) { |
| | | |
| | | switch (errorCorrectLevel) { |
| | | case QRErrorCorrectLevel.L: |
| | | return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0]; |
| | | case QRErrorCorrectLevel.M: |
| | | return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1]; |
| | | case QRErrorCorrectLevel.Q: |
| | | return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2]; |
| | | case QRErrorCorrectLevel.H: |
| | | return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3]; |
| | | default: |
| | | return undefined; |
| | | } |
| | | } |
| | | |
| | | //--------------------------------------------------------------------- |
| | | // QRBitBuffer |
| | | //--------------------------------------------------------------------- |
| | | |
| | | function QRBitBuffer() { |
| | | this.buffer = new Array(); |
| | | this.length = 0; |
| | | } |
| | | |
| | | QRBitBuffer.prototype = { |
| | | |
| | | get: function(index) { |
| | | var bufIndex = Math.floor(index / 8); |
| | | return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) == 1; |
| | | }, |
| | | |
| | | put: function(num, length) { |
| | | for (var i = 0; i < length; i++) { |
| | | this.putBit(((num >>> (length - i - 1)) & 1) == 1); |
| | | } |
| | | }, |
| | | |
| | | getLengthInBits: function() { |
| | | return this.length; |
| | | }, |
| | | |
| | | putBit: function(bit) { |
| | | |
| | | var bufIndex = Math.floor(this.length / 8); |
| | | if (this.buffer.length <= bufIndex) { |
| | | this.buffer.push(0); |
| | | } |
| | | |
| | | if (bit) { |
| | | this.buffer[bufIndex] |= (0x80 >>> (this.length % 8)); |
| | | } |
| | | |
| | | this.length++; |
| | | } |
| | | }; |
| | | |
| | | //--------------------------------------------------------------------- |
| | | // Support Chinese |
| | | //--------------------------------------------------------------------- |
| | | function utf16To8(text) { |
| | | var result = ''; |
| | | var c; |
| | | for (var i = 0; i < text.length; i++) { |
| | | c = text.charCodeAt(i); |
| | | if (c >= 0x0001 && c <= 0x007F) { |
| | | result += text.charAt(i); |
| | | } else if (c > 0x07FF) { |
| | | result += String.fromCharCode(0xE0 | c >> 12 & 0x0F); |
| | | result += String.fromCharCode(0x80 | c >> 6 & 0x3F); |
| | | result += String.fromCharCode(0x80 | c >> 0 & 0x3F); |
| | | } else { |
| | | result += String.fromCharCode(0xC0 | c >> 6 & 0x1F); |
| | | result += String.fromCharCode(0x80 | c >> 0 & 0x3F); |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | uQRCode = { |
| | | errorCorrectLevel: QRErrorCorrectLevel, |
| | | |
| | | defaults: { |
| | | size: 354, |
| | | margin: 0, |
| | | backgroundColor: '#ffffff', |
| | | foregroundColor: '#000000', |
| | | fileType: 'png', // 'jpg', 'png' |
| | | errorCorrectLevel: QRErrorCorrectLevel.H, |
| | | typeNumber: -1, |
| | | enableDelay: false // 启用延迟绘制 |
| | | }, |
| | | |
| | | getModules: function(options) { |
| | | options = Object.assign(this.defaults, options); |
| | | var qrcode = new QRCode(options.typeNumber, options.errorCorrectLevel); |
| | | qrcode.addData(utf16To8(options.text)); |
| | | qrcode.make(); |
| | | return qrcode.modules; |
| | | }, |
| | | |
| | | make: function(options, componentInstance) { |
| | | return new Promise((reslove, reject) => { |
| | | options = Object.assign(this.defaults, options); |
| | | if (!options.canvasId) { |
| | | throw new Error('uQRCode: Please set canvasId!'); |
| | | } |
| | | var modules = this.getModules(options); |
| | | var tileW = (options.size - options.margin * 2) / modules.length; |
| | | var tileH = tileW; |
| | | var delay = 0; |
| | | var ctx = uni.createCanvasContext(options.canvasId, componentInstance); |
| | | ctx.setFillStyle(options.backgroundColor); |
| | | ctx.fillRect(0, 0, options.size, options.size); |
| | | for (var row = 0; row < modules.length; row++) { |
| | | for (var col = 0; col < modules.length; col++) { |
| | | delay = options.enableDelay ? row * modules.length + col + 1 : 0; |
| | | setTimeout(function(row, col) { |
| | | // 计算每一个小块的位置 |
| | | var x = Math.round(col * tileW) + options.margin; |
| | | var y = Math.round(row * tileH) + options.margin; |
| | | var w = Math.ceil((col + 1) * tileW) - Math.floor(col * tileW); |
| | | var h = Math.ceil((row + 1) * tileW) - Math.floor(row * tileW); |
| | | var style = modules[row][col] ? options.foregroundColor : |
| | | options.backgroundColor; |
| | | ctx.setFillStyle(style); |
| | | ctx.fillRect(x, y, w, h); |
| | | }, delay, row, col); |
| | | } |
| | | } |
| | | |
| | | // 耗时 |
| | | var time = options.enableDelay ? delay + options.size * 2 + options.margin * 2 + options.text.length : 0; |
| | | setTimeout(function() { |
| | | ctx.draw(false, function() { |
| | | uni.canvasToTempFilePath({ |
| | | canvasId: options.canvasId, |
| | | fileType: options.fileType, |
| | | width: options.size, |
| | | height: options.size, |
| | | destWidth: options.size, |
| | | destHeight: options.size, |
| | | success: function(res) { |
| | | reslove(Object.assign(res, { |
| | | time |
| | | })); |
| | | }, |
| | | fail: function(err) { |
| | | reject(err); |
| | | } |
| | | }, componentInstance); |
| | | }); |
| | | }, time); |
| | | }); |
| | | } |
| | | } |
| | | })(); |
| | | |
| | | export default uQRCode; |
对比新文件 |
| | |
| | | <template> |
| | | <view class="qrcode"> |
| | | <canvas id="qrcode" canvas-id="qrcode" :style="{'width': `${options.size}px`, 'height': `${options.size}px`}" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import qrcode from './qrcode' |
| | | export default { |
| | | name: 'qrcode', |
| | | data() { |
| | | return { |
| | | options: { |
| | | canvasId: 'qrcode', |
| | | size: 354, |
| | | margin: 10, |
| | | text: '' |
| | | } |
| | | } |
| | | }, |
| | | methods: { |
| | | make(options) { |
| | | return qrcode.make(Object.assign(this.options, options), this) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | |
| | | // };
|
| | | // },
|
| | |
|
| | | onLoad() {
|
| | | onLoad(options) { |
| | | // if(options.partnerUserId){ |
| | | // //需要前往注册了 |
| | | // uni.navigateTo({ |
| | | // url: '/pages/login/supplier-login' |
| | | // }) |
| | | // }
|
| | | // console.log('home created')
|
| | | //这里进行一次初始化即可
|
| | | // this.$http.request('get', '/api/school/area/list', {
|
| | |
| | | <button @tap="login()" class="bottom-button">登 录</button>
|
| | |
|
| | | <view class="flex">
|
| | | <view class="topic-font" v-if="loginType=='pwd'&&apitype!=='loginAdmin'" @click="loginType='code'">手机验证码登录</view>
|
| | | <view class="topic-font" v-if="loginType=='code'&&apitype!=='loginAdmin'" @click="loginType='pwd'">账号密码登录</view>
|
| | | <view class="topic-font" v-if="loginType=='pwd'&&apitype!=='loginAdmin'"
|
| | | @click="loginType='code'">手机验证码登录</view>
|
| | | <view class="topic-font" v-if="loginType=='code'&&apitype!=='loginAdmin'"
|
| | | @click="loginType='pwd'">账号密码登录</view>
|
| | |
|
| | | <view class="topic-font m-l-a m-r-0" v-if="apitype!=='loginAdmin'" @click="toReg">前往注册</view>
|
| | |
|
| | |
| | | <!-- #ifdef PUB_PARTNER -->
|
| | | <view class="topic-font m-l-a m-r-0" @click="()=>{
|
| | | if(apitype==='loginPartner'){
|
| | | apitype = 'loginAdmin' |
| | | apitype = 'loginAdmin'
|
| | | loginType = 'pwd'
|
| | | }else{
|
| | | apitype = 'loginPartner'
|
| | |
| | | </view>
|
| | | </template>
|
| | | <script>
|
| | | // import util from '@/utils/util.js'
|
| | | // import gzmzApi from '@/api/gzmzApi.js'
|
| | | // import myCache from '@/utils/myCache.js'
|
| | | export default {
|
| | | // props: {
|
| | | // // apitype: 'loginSupplier',
|
| | | // apitype: {
|
| | | // type: String,
|
| | | // default () {
|
| | | // // #ifdef PUB_SUPPLIER
|
| | | // return 'loginSupplier'
|
| | | // // #endif
|
| | | // // #ifdef PUB_PARTNER
|
| | | // return 'loginPartner'
|
| | | // // #endif
|
| | | // // #ifdef PUB_CUSTOMER
|
| | | // return 'loginCustomer'
|
| | | // // #endif
|
| | | // // return 'loginPartner'
|
| | | // }
|
| | | // },
|
| | | // },
|
| | | onLoad(options) {
|
| | | // #ifdef PUB_CUSTOMER
|
| | | if (options.partnerUserId) {
|
| | | if (this.$storage.getItem('token')) {
|
| | | this.$message.showLoading()
|
| | | //稍微等一会,避免currentInfo还在同步
|
| | | let tmp = this
|
| | | setTimeout(() => {
|
| | | tmp.$message.hideLoading()
|
| | | if (tmp.currentInfo.id || tmp.$storage.getItem('token')) {
|
| | | //这种已经登录的
|
| | | //确定是注册绑定还是重新绑定
|
| | | var t = {
|
| | | title: '提示,您已登录,是否退出并注册绑定合伙人',
|
| | | content: '',
|
| | | showCancel: true,
|
| | | cancelText: '使用当前账号绑定合伙人',
|
| | | cancelColor: '#000000',
|
| | | confirmText: '退出当前账号并注册、绑定',
|
| | | confirmColor: '#20613D'
|
| | | }
|
| | | uni.showModal({
|
| | | ...t,
|
| | | success: (res) => {
|
| | | if (res.confirm) {
|
| | | //清空登录信息,
|
| | | this.$store.commit('updateLogin', false)
|
| | | setTimeout(() => {
|
| | | uni.navigateTo({
|
| | | url: `/sub_pages/customer/customer-info/customer-info?source=step&partnerUserId=${options.partnerUserId}&partnerUserName=${options.partnerUserName}`
|
| | | })
|
| | | }, 200)
|
| | | }
|
| | | if (res.cancel) {
|
| | | if (!tmp.currentInfo.customer) {
|
| | | tmp.$message.showToast('您尚未完善信息无法绑定')
|
| | | return
|
| | | } else {
|
| | | if (tmp.currentInfo.customer.partnerId) {
|
| | | tmp.$message.showToast('您已绑定,请联系客服解除绑定')
|
| | | return
|
| | | } else {
|
| | | //前往绑定页面
|
| | | uni.reLaunch({
|
| | | url: `/pages/user/supplier-user?partnerUserId=${options.partnerUserId}&partnerUserName=${options.partnerUserName}`
|
| | | })
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | | })
|
| | |
|
| | | } else {
|
| | | //退出登录了,或者失效了
|
| | | uni.navigateTo({
|
| | | url: `/sub_pages/customer/customer-info/customer-info?source=step&partnerUserId=${options.partnerUserId}&partnerUserName=${options.partnerUserName}`
|
| | | })
|
| | | }
|
| | | }, 2000)
|
| | |
|
| | | } else {
|
| | | uni.navigateTo({
|
| | | url: `/sub_pages/customer/customer-info/customer-info?source=step&partnerUserId=${options.partnerUserId}&partnerUserName=${options.partnerUserName}`
|
| | | })
|
| | | }
|
| | |
|
| | |
|
| | | }
|
| | | // #endif
|
| | |
|
| | | },
|
| | | data() {
|
| | | return {
|
| | | openId: '-1',
|
| | |
| | | icon: 'none'
|
| | | });
|
| | | return;
|
| | | } |
| | | }
|
| | | that.phoneNumber = ''
|
| | | }
|
| | | if (this.loginType == 'code') {
|
| | |
| | | }, |
| | | onLoad(options) { |
| | | this.source = options.source || '' |
| | | // #ifdef PUB_CUSTOMER |
| | | var tjson = this.$storage.getItem('cache_customer_info') |
| | | if (tjson) { |
| | | var dto = JSON.parse(tjson) |
| | | if (dto.partnerUserId) { |
| | | this.partnerId = dto.partnerUserId || '' |
| | | this.partnerName = dto.partnerUserName || '佚名' |
| | | } |
| | | } |
| | | // #endif |
| | | |
| | | }, |
| | | methods: { |
| | | async scanPartnerCode() { |
| | |
| | | console.log('条码内容:' + res.result); |
| | | var dto = undefined |
| | | try { |
| | | dto = JSON.parse(res.result) |
| | | if (res.result && res.result.startsWith('http://') && res.result.indexOf( |
| | | 'partnerUserId') >= 0) { |
| | | var arr = res.result.split("?")[1].split("&") |
| | | dto = {} |
| | | for (var item of arr) { |
| | | var tarr = item.split("=") |
| | | if (tarr[1]) { |
| | | dto[tarr[0]] = dto[tarr[1]] |
| | | } |
| | | } |
| | | dto['name'] = dto['partnerUserName'] || dto['partnerUserId'] || '佚名' |
| | | dto['userId'] = dto['partnerUserId'] || '' |
| | | |
| | | } else { |
| | | dto = JSON.parse(res.result) |
| | | |
| | | } |
| | | if (!!dto['userId']) { |
| | | that.partnerName = dto['name'] || '' |
| | | that.partnerId = dto['userId'] || '' |
| | |
| | | <view class="right-icon">
|
| | | <uni-icons type="right"></uni-icons>
|
| | | </view>
|
| | | </view> |
| | | <!-- <view class="user-util m-t-12 flex" v-if="selftype==='partner'" |
| | | @click="goto('/sub_pages/partner/partner-info/partner-code-v2',true)"> |
| | | <view class="title">测试二维码</view> |
| | | <view class="right-icon"> |
| | | <uni-icons type="right"></uni-icons> |
| | | </view> |
| | | </view>
|
| | | <!-- <view class="user-util m-t-12 flex" v-if="selftype==='partner'"
|
| | | @click="goto('/sub_pages/partner/partner-info/partner-code-v2',true)">
|
| | | <view class="title">测试二维码</view>
|
| | | <view class="right-icon">
|
| | | <uni-icons type="right"></uni-icons>
|
| | | </view>
|
| | | </view> -->
|
| | | <!-- #endif -->
|
| | | <!-- #ifdef PUB_CUSTOMER -->
|
| | |
| | | onLoad(options) {
|
| | | // const url = options.q ? decodeURIComponent(options.q) : '';
|
| | | // const urlcode = options.url && decodeURIComponent(options.url) || ''
|
| | |
|
| | | // #ifdef PUB_CUSTOMER
|
| | | if (options.partnerUserId) {
|
| | | this.bindPartnerUser(options.partnerUserId, options.partnerUserName)
|
| | | }
|
| | | // #endif
|
| | |
|
| | |
|
| | | },
|
| | |
| | | uni.stopPullDownRefresh()
|
| | | },
|
| | | methods: {
|
| | | async bindPartnerUser(userId, name) {
|
| | | await this.$message.confirm(`确定要绑定${name}合伙人吗?`)
|
| | | //调用接口绑定
|
| | | this.$message.showLoading()
|
| | | const {
|
| | | code,
|
| | | data
|
| | | } = await this.$http.request('post', '/api/customer/bind/partner', {
|
| | | data: {
|
| | | partnerUserId: userId
|
| | | }
|
| | | })
|
| | | this.$message.hideLoading()
|
| | | if (code == 0) {
|
| | | this.$message.showToast(`绑定合伙人${name}成功`)
|
| | | await this.$store.dispatch('getCurrentInfo')
|
| | | }
|
| | | },
|
| | | async scanPartnerCode() {
|
| | | await this.$message.confirm('确定要绑定合伙人吗?')
|
| | | //扫二维码确认
|
| | | let that = this
|
| | | uni.scanCode({
|
| | |
| | | console.log('条码内容:' + res.result);
|
| | | var dto = undefined
|
| | | try {
|
| | | dto = JSON.parse(res.result)
|
| | | if (res.result && res.result.startsWith('http://') && res.result.indexOf(
|
| | | 'partnerUserId') >= 0) {
|
| | | var arr = res.result.split("?")[1].split("&")
|
| | | dto = {}
|
| | | for (var item of arr) {
|
| | | var tarr = item.split("=")
|
| | | if (tarr[1]) {
|
| | | dto[tarr[0]] = dto[tarr[1]]
|
| | | }
|
| | | }
|
| | | dto['name'] = dto['partnerUserName'] || dto['partnerUserId'] || '佚名'
|
| | | dto['userId'] = dto['partnerUserId'] || ''
|
| | |
|
| | | } else {
|
| | | dto = JSON.parse(res.result)
|
| | |
|
| | | }
|
| | | if (!!dto['userId']) {
|
| | | var partnerName = dto['name'] || ''
|
| | | var partnerId = dto['userId'] || ''
|
| | | //调用接口绑定
|
| | | that.$message.showLoading()
|
| | | const {
|
| | | code,
|
| | | data
|
| | | } = await that.$http.request('post', '/api/customer/bind/partner', {
|
| | | data: {
|
| | | partnerUserId: partnerId
|
| | | }
|
| | | })
|
| | | that.$message.hideLoading()
|
| | | if (code == 0) {
|
| | | that.$message.showToast(`绑定合伙人${partnerName}成功`)
|
| | | await that.$store.dispatch('getCurrentInfo')
|
| | | that.bindPartnerUser(partnerId, partnerName)
|
| | |
|
| | | // setTimeout(async () => {
|
| | | // that.$message.showLoading()
|
| | | // that.$message.hideLoading()
|
| | | // }, 1000)
|
| | |
|
| | | }
|
| | | } else {
|
| | | that.$message.showToast('二维码格式不正确扫码失败')
|
| | | }
|
| | |
| | | }
|
| | | });
|
| | | },
|
| | |
|
| | |
|
| | | toInfo() {
|
| | | var url = ''
|
| | | if (this.currentInfo.id) {
|
| | |
| | | console.log('updateLogin', provider) |
| | | state.hasLogin = provider && true || false; |
| | | if (!state.hasLogin) { |
| | | state.currentInfo = {} |
| | | storage.removeItem('token') |
| | | } |
| | | }, |
| | |
| | | state.currentInfo = {} |
| | | storage.removeItem('token') |
| | | message.showToast('退出登录成功') |
| | | // #ifdef APP |
| | | var KeepAliveModule = uni.requireNativePlugin("yh-nl") //保活组件 |
| | | |
| | | let ret = KeepAliveModule.stopLocation(); |
| | | console.log('ret', ret) |
| | | // #endif |
| | | uni.redirectTo({ |
| | | url: '/views/login/login' |
| | | }) |
| | | // uni.redirectTo({ |
| | | // url: '/views/login/login' |
| | | // }) |
| | | }, |
| | | setOpenid(state, openid) { |
| | | state.openid = openid |
| | |
| | | ...JSON.parse(tjson) |
| | | } |
| | | } |
| | | if(options.partnerUserId){ |
| | | this.dto.partnerUserId = options.partnerUserId || '' |
| | | } |
| | | if(options.partnerUserName){ |
| | | this.dto.partnerUserName = options.partnerUserName || '' |
| | | } |
| | | } else { |
| | | this.getCurrentInfo() |
| | | } |
| | |
| | | <template> |
| | | <view class="product-detail-page"> |
| | | <scroll-view enable-back-to-top scroll-y="true" class="product-detail-page__scroll"> |
| | | <view class="product-detail-page__scroll__swiper" v-if="info.ImageUrlList&&info.ImageUrlList.length>0"> |
| | | <swiper @change="onSwiperChange" :current="currentIndex" class="product-detail-page__scroll__swiper__target"> |
| | | <swiper-item class="product-detail-page__scroll__swiper__target__item" v-for="(item,index) in info.ImageUrlList" |
| | | :key="index"> |
| | | <image mode="aspectFit" :src="item" class="product-detail-page__scroll__swiper__target__item__img" lazy-load></image> |
| | | </swiper-item> |
| | | </swiper> |
| | | <view class="product-detail-page__scroll__swiper__page">{{currentIndex+1}}/{{info.ImageUrlList.length}}</view> |
| | | <button v-if="info.Id" @click="shareDetail" class="evan-share"> |
| | | <image src="/static/images/common/share_icon.png" class="evan-share__icon"></image> |
| | | <view class="evan-share__text">分享</view> |
| | | </button> |
| | | </view> |
| | | <image v-else mode="aspectFill" class="product-detail-page__scroll__default-image" src="/static/images/common/default_image_horizontal.png"></image> |
| | | <view class="product-detail-page__scroll__info"> |
| | | <view class="product-detail-page__scroll__info__title">{{info.Name||''}}</view> |
| | | <view class="product-detail-page__scroll__info__desc">{{info.Introduction||''}}</view> |
| | | <!-- <view class="product-detail-page__scroll__info__bulter">管家提成比例:</view> --> |
| | | <view class="product-detail-page__scroll__info__tags"> |
| | | <view class="product-detail-page__scroll__info__tags__item" v-for="(item,index) in tags" :key="index"> |
| | | <image class="product-detail-page__scroll__info__tags__item__icon" :src="item.icon"></image> |
| | | <view class="product-detail-page__scroll__info__tags__item__text">{{item.text}}</view> |
| | | </view> |
| | | <view v-if="!isGroup" class="product-detail-page__scroll__info__tags__count">已售{{info.SaleCount||0}}</view> |
| | | </view> |
| | | </view> |
| | | <view class="product-detail-page__scroll__team" v-if="isGroup"> |
| | | <view class="product-detail-page__scroll__team__title">批购进度及商品价格区间</view> |
| | | <view class="product-detail-page__scroll__team__main"> |
| | | <view v-if="!info.GroupRules||info.GroupRules.length===0" class="product-detail-page__scroll__team__main__progress"></view> |
| | | <view v-else class="product-detail-page__scroll__team__main__progress"> |
| | | <view class="product-detail-page__scroll__team__main__progress__active" :style="{width:getPercent()+'rpx'}"></view> |
| | | </view> |
| | | <!-- <template v-if="info.GroupRules&&info.GroupRules.length>0"> |
| | | <view v-for="(item,index) in info.GroupRules" :key="index" class="product-detail-page__scroll__team__main__price" |
| | | :style="{top:'80rpx',left:`${630 * 0.8 / lastInfo.GroupCountStart * item.GroupCountStart}rpx`}"> |
| | | <view class="product-detail-page__scroll__team__main__price__line"></view> |
| | | <view class="product-detail-page__scroll__team__main__price__target">{{item.GroupCountStart}}件</view> |
| | | <view class="product-detail-page__scroll__team__main__price__target">{{item.Amount}}元</view> |
| | | </view> |
| | | </template> --> |
| | | <view v-if="!$utils.isTrueEmpty(info.GroupCount)" class="product-detail-page__scroll__team__main__price" :style="{bottom:'80rpx',left:getLeftValue()+'rpx'}"> |
| | | <view class="product-detail-page__scroll__team__main__price__current">已批{{info.GroupCount}}件</view> |
| | | <view class="product-detail-page__scroll__team__main__price__line current"></view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view class="product-detail-page__scroll__team-intro" v-if="isGroup"> |
| | | <view class="product-detail-page__scroll__team-intro__target">批购说明:参与购买的人数越多,商品价格越实惠</view> |
| | | <view class="product-detail-page__scroll__team-intro__target">根据批购最终参与购买的人数,来确定你需要支付的最终价格</view> |
| | | </view> |
| | | <view class="product-detail-page__scroll__desc"> |
| | | <view class="product-detail-page__scroll__desc__title">商品详情</view> |
| | | <u-parse :content="info.ProductDesc" /> |
| | | </view> |
| | | </scroll-view> |
| | | <view class="evan-buy-bottom"> |
| | | <view class="evan-buy-bottom__item evan-buy-bottom__item--left"> |
| | | <view class="evan-buy-bottom__item__price"> |
| | | <view v-if="isGroup||info.PayType===1" class="evan-buy-bottom__item__price__unit">¥</view> |
| | | <!-- <view class="evan-buy-bottom__item__price__current">{{showPrice}}</view> --> |
| | | <view v-if="!isGroup&&info.PayType===1&&info.MarketPrice" class="evan-buy-bottom__item__price__old">¥{{info.MarketPrice}}</view> |
| | | </view> |
| | | <view v-if="info.GiveAwayHuidouCount" class="evan-buy-bottom__item__tip">赠送{{info.GiveAwayHuidouCount}}汇豆</view> |
| | | </view> |
| | | <view @tap="buy" class="evan-buy-bottom__item evan-buy-bottom__item--right">立即购买</view> |
| | | <view> |
| | | <view class="button p-t-12 bg-white"> |
| | | <button :disabled="canvasImages == '' ? true : false" type="primary" @click="downloadImg">下载二维码</button> |
| | | <button :disabled="canvasImages != '' ? false : true" @click="previewHandle">预览二维码</button> |
| | | <!-- #ifdef MP-WEIXIN --> |
| | | <!-- <button type="warn" :disabled="canvasImages != '' ? false : true" open-type="share">分享给朋友</button> --> |
| | | <!-- #endif --> |
| | | </view> |
| | | <hjg-spec @confirm="onSpecConfirm" :changeCount="!isNewUserProduct" :specs="info.SpecInfos" ref="spec"></hjg-spec> |
| | | <view @tap="hideBarcode" class="evan-poster__mask" :class="{hide:!showBarcode}" :style="{paddingTop:posterPadding}"> |
| | | <canvas class="evan-poster__mask__canvas" :style="{width:canvasWidth+'px',height:canvasHeight+'px'}" canvas-id="barcode"></canvas> |
| | | <view @tap.stop.prevent="stopPop" class="evan-poster__mask__bottom"> |
| | | <button open-type="share" class="evan-poster__mask__bottom__item"> |
| | | <view class="evan-poster__mask__bottom__item__text">分享好友</view> |
| | | </button> |
| | | <button @tap="saveToAlbum" class="evan-poster__mask__bottom__item"> |
| | | <view class="evan-poster__mask__bottom__item__text">保存海报</view> |
| | | </button> |
| | | </view> |
| | | </view> |
| | | <shareImages ref="canvas" :canvasWidth="canvasWidth" :canvasHeight="canvasHeight" :shareTitle="shareTitle" |
| | | :goodsTitle="goodsTitle" :shareImage="shareImage" :goodsTitle2="goodsTitle2" :qrSize="qrSize" :qrUrl="qrUrl" |
| | | @success="shareSuccess" :canvasID="canvasID"> |
| | | </shareImages> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | |
| | | import { |
| | | mapGetters, |
| | | mapState |
| | | } from 'vuex' |
| | | let ENV = 'prod' |
| | | import shareImages from '@/components/hj-placard/shareImages.vue' |
| | | export default { |
| | | components: { |
| | | |
| | | }, |
| | | computed: { |
| | | |
| | | |
| | | shareImages |
| | | }, |
| | | data() { |
| | | return { |
| | | memberId: '', |
| | | headUrl: '', |
| | | nickName: '', |
| | | id: null, |
| | | info: {}, |
| | | currentIndex: 0, |
| | | tags: [{ |
| | | icon: '/static/images/home/qqzx.png', |
| | | text: '全球精品' |
| | | }, |
| | | { |
| | | icon: '/static/images/home/jyps.png', |
| | | text: '正品保证' |
| | | }, |
| | | { |
| | | icon: '/static/images/home/shwy.png', |
| | | text: '商品包邮' |
| | | } |
| | | ], |
| | | isGroup: false, |
| | | groupId: null, |
| | | canvasWidth: 242, |
| | | canvasHeight: 430, |
| | | showBarcode: false, |
| | | ratio: 430 / 1920, |
| | | posterPadding: 0, |
| | | filePath: '', |
| | | isNewUserProduct: false, |
| | | canBuy: false |
| | | name: '', |
| | | canvasID: "myQrcode", |
| | | canvasImages: '', |
| | | canvasWidth: 375, // 宽度 |
| | | canvasHeight: 650, // 高度 |
| | | shareTitle: '我是这张图片的标题', // 分享标题 |
| | | goodsTitle: '\n', // 商品宣传标题 |
| | | goodsTitle2: '', |
| | | shareImage: 'https://hmy-flower.oss-cn-shanghai.aliyuncs.com/d4/d43cdefc7b8f4c3e91fb451a236a4435WechatIMG2882.jpg', // 背景图片 |
| | | qrSize: 100, // 二维码大小 |
| | | qrUrl: 'http://www.hmyxianhua.com/wx/jump?partnerUserId=1&partnerUserName=', // 生成二维码的链接 |
| | | } |
| | | }, |
| | | onLoad() { |
| | | if (!this.currentInfo.partnerDTO) { |
| | | this.$message.showToast('请先完善合伙人信息') |
| | | return |
| | | } |
| | | this.name = this.currentInfo.partnerDTO.name || '佚名' |
| | | this.qrUrl = |
| | | `http://www.hmyxianhua.com/wx/jump?partnerUserId=${this.currentInfo.id||'-'}&partnerUserName=${this.name||'-'}` |
| | | this.goodsTitle = `${this.name||'-'}的推广二维码` |
| | | this.goodsTitle2 = `扫码注册绑定合伙人` |
| | | this.$message.showLoading() |
| | | setTimeout(() => { |
| | | this.createsShareImage() |
| | | }, 500) |
| | | setTimeout(() => { |
| | | this.$message.hideLoading() |
| | | }, 2000) |
| | | }, |
| | | methods: { |
| | | async getDetail() { |
| | | // const { |
| | | // code, |
| | | // data |
| | | // } = await productService.getDetail(this.id) |
| | | // if (code === 0) { |
| | | // this.info = data |
| | | // this.isNewUserProduct = data.IsNewUserTopic === 1 |
| | | // 生成分享图片 |
| | | createsShareImage() { |
| | | // console.log(this.$refs.canvas) |
| | | this.$refs.canvas.canvasCreate(); |
| | | }, |
| | | // 预览图片 |
| | | previewHandle() { |
| | | uni.previewImage({ |
| | | urls: [this.canvasImages], |
| | | }); |
| | | }, |
| | | // 回调图片地址 |
| | | shareSuccess(e) { |
| | | // console.log('地址',e) |
| | | this.canvasImages = e |
| | | }, |
| | | downloadImg() { |
| | | // this.$refs.canvas.downloadImg(); |
| | | uni.saveImageToPhotosAlbum({ |
| | | filePath: this.canvasImages, |
| | | success: function() { |
| | | console.log('save success'); |
| | | uni.showToast({ |
| | | title: '保存成功' |
| | | }) |
| | | }, |
| | | fail(res) { |
| | | console.error(res) |
| | | uni.showToast({ |
| | | title: '保存失败。', |
| | | icon: 'error' |
| | | }) |
| | | } |
| | | }) |
| | | |
| | | |
| | | }, |
| | | // 分享 |
| | | onShareAppMessage(res) { |
| | | // if (res.from === 'button') { |
| | | // console.log(res.target) |
| | | // } |
| | | }, |
| | | async getGroupDetail() { |
| | | const { |
| | | code, |
| | | data |
| | | } = await assembleService.getAssembleDetail(this.id, this.groupId) |
| | | if (code === 0) { |
| | | this.info = data |
| | | return { |
| | | title: `${this.name||'-'}的推广二维码`, |
| | | path: this.canvasImages |
| | | } |
| | | }, |
| | | onSwiperChange(e) { |
| | | this.currentIndex = e.detail.current |
| | | }, |
| | | async buy() { |
| | | |
| | | }, |
| | | onSpecConfirm(e) { |
| | | let specList = [] |
| | | if (Array.isArray(e.specs)) { |
| | | specList = e.specs.map((item) => { |
| | | return { |
| | | SpecName: item.SpecName, |
| | | SpecValue: item.SpecValue |
| | | } |
| | | }) |
| | | } |
| | | let orderInfo = { |
| | | ProductId: this.info.Id, |
| | | ProductSpecList: specList, |
| | | ProductCount: e.count, |
| | | ProductSaleType: this.isGroup ? 2 : 1, |
| | | ProductPayType: this.isGroup ? 1 : this.info.PayType |
| | | } |
| | | if (this.isGroup) { |
| | | orderInfo.GroupId = this.groupId |
| | | orderInfo.BookAmount = this.info.BookAmount |
| | | } else { |
| | | if (orderInfo.ProductPayType === 1) { |
| | | orderInfo.SaleAmount = this.info.SalePrice |
| | | } else { |
| | | orderInfo.SaleAmount = this.info.HuidouCount |
| | | } |
| | | } |
| | | uni.navigateTo({ |
| | | url: `./order?orderInfo=${JSON.stringify(orderInfo)}` |
| | | }) |
| | | }, |
| | | getPercent() { |
| | | if (!this.info.GroupRules || this.info.GroupRules.length === 0) { |
| | | return 0 |
| | | } |
| | | if (this.info.GroupCount > this.info.GroupRules[this.info.GroupRules.length - 1].GroupCountStart) { |
| | | return 0.85 * 630 |
| | | } else { |
| | | return this.info.GroupCount / this.info.GroupRules[this.info.GroupRules.length - 1].GroupCountStart * |
| | | 0.8 * 630 |
| | | } |
| | | }, |
| | | getLeftValue() { |
| | | if (!this.info.GroupRules || this.info.GroupRules.length === 0) { |
| | | if (this.info.GroupCount === 0) { |
| | | return 0 |
| | | } else { |
| | | return 630 * 0.8 |
| | | } |
| | | } else { |
| | | if (this.info.GroupCount > this.info.GroupRules[this.info.GroupRules.length - 1].GroupCountStart) { |
| | | return 630 * 0.85 |
| | | } else { |
| | | return 630 * 0.8 / Math.max(this.info.GroupRules[this.info.GroupRules.length - 1].GroupCountStart / |
| | | this.info.GroupCount, 1) |
| | | } |
| | | } |
| | | }, |
| | | formatCanvasSize(size) { |
| | | return Math.floor(this.ratio * size) |
| | | }, |
| | | async shareDetail() { |
| | | if (this.memberId) { |
| | | // #ifdef MP-WEIXIN |
| | | let params = `id=${this.info.Id}` |
| | | if (this.isGroup) { |
| | | params += `&groupId=${this.groupId}` |
| | | } |
| | | if (this.memberId) { |
| | | params += `&inviteId=${this.memberId}` |
| | | } |
| | | const { |
| | | code: sceneCode, |
| | | data: sceneData |
| | | } = await commonService.saveScene(encodeURIComponent(params)) |
| | | if (sceneCode === 0) { |
| | | const { |
| | | code, |
| | | data |
| | | } = await commonService.getUnlimitedBarcode('pages/home/product/detail', `posterId=${sceneData}`) |
| | | if (code === 0) { |
| | | const fsm = wx.getFileSystemManager() |
| | | this.filePath = `${wx.env.USER_DATA_PATH}/barcode_tmp_${(new Date).getTime()}.png` |
| | | fsm.writeFile({ |
| | | filePath: this.filePath, |
| | | data: data, |
| | | encoding: 'binary', |
| | | success: async () => { |
| | | const context = uni.createCanvasContext('barcode') |
| | | const headSize = this.formatCanvasSize(105) |
| | | const productSize = this.formatCanvasSize(540) |
| | | const canvasWidth = this.canvasWidth |
| | | const canvasHeight = this.canvasHeight |
| | | const headPath = await this.getImageInfo(this.headUrl) |
| | | const productPath = await this.getImageInfo(this.info.ImageUrlList[0]) |
| | | // 背景 |
| | | context.drawImage('/pages/home/static/images/sharebg.jpg', 0, 0, canvasWidth, |
| | | canvasHeight) |
| | | // 头像 |
| | | context.drawImage(headPath, this.formatCanvasSize(80), this.formatCanvasSize(70), headSize, headSize) |
| | | // 昵称 |
| | | context.font = `bold ${this.formatCanvasSize(40)}px system-ui` |
| | | context.setFillStyle('#000') |
| | | this.fillTextByLength(context, this.nickName, 20, this.formatCanvasSize(198), |
| | | this.formatCanvasSize(110)) |
| | | // 产品图 |
| | | context.drawImage(productPath, this.formatCanvasSize(260), this.formatCanvasSize(440), productSize, |
| | | productSize) |
| | | // 价格 |
| | | const priceWidth = this.formatCanvasSize(150) |
| | | const priceTop = this.formatCanvasSize(1240) |
| | | const priceLeft = this.formatCanvasSize(141) |
| | | // 当前价格 |
| | | if (this.showPrice) { |
| | | const price = (this.isGroup || this.info.PayType === 1) ? `¥${this.showPrice}` : this.showPrice |
| | | context.font = `bold ${this.formatCanvasSize(84)}px system-ui` |
| | | context.setFillStyle('#d92c21') |
| | | context.fillText(price, priceLeft, priceTop, priceWidth) |
| | | } |
| | | // 市场价格 |
| | | if (!this.isGroup && this.info.PayType === 1 && this.info.MarketPrice) { |
| | | context.font = `normal ${this.formatCanvasSize(54)}px system-ui` |
| | | context.setFillStyle('#61605e') |
| | | context.fillText(`¥${this.info.MarketPrice}`, priceLeft + priceWidth + 5, priceTop, priceWidth) |
| | | context.moveTo(priceLeft + priceWidth + 5, priceTop - this.formatCanvasSize(20)) |
| | | context.lineTo(priceLeft + priceWidth + 5 + context.measureText(`¥${this.info.MarketPrice}`).width + 2, |
| | | priceTop - this.formatCanvasSize(20)) |
| | | context.setStrokeStyle('#61605e') |
| | | context.stroke() |
| | | } |
| | | // 赠送汇豆 |
| | | if (this.info.GiveAwayHuidouCount) { |
| | | context.font = `normal ${this.formatCanvasSize(36)}px system-ui` |
| | | context.setFillStyle('#61605e') |
| | | context.fillText(`赠送${this.info.GiveAwayHuidouCount}汇豆`, priceLeft, priceTop + this.formatCanvasSize(36) + |
| | | 5, |
| | | priceWidth * 2) |
| | | } |
| | | // 商品名称 |
| | | let nameLeft = priceLeft + 2 * priceWidth + 10 |
| | | let nameTop = this.formatCanvasSize(1230) |
| | | context.font = `bold ${this.formatCanvasSize(50)}px system-ui` |
| | | context.setFillStyle('#000') |
| | | let nameWidth = 0 |
| | | // 换行次数 |
| | | let breakLineCount = 0 |
| | | for (let i = 0; i < this.info.Name.length; i++) { |
| | | const str = this.info.Name[i] |
| | | nameWidth += context.measureText(str).width |
| | | if (nameWidth > 80 && breakLineCount > 0) { |
| | | context.fillText('...', nameLeft, nameTop) |
| | | break |
| | | } |
| | | if (nameWidth > 90) { |
| | | nameTop += this.formatCanvasSize(74) |
| | | nameLeft = priceLeft + 2 * priceWidth + 10 |
| | | nameWidth = context.measureText(str).width |
| | | breakLineCount++ |
| | | } |
| | | context.fillText(str, nameLeft, nameTop) |
| | | nameLeft += context.measureText(str).width + 2 |
| | | } |
| | | // 二维码 |
| | | const barcodeSize = this.formatCanvasSize(250) |
| | | const barcodeLeft = this.formatCanvasSize(740) |
| | | const barcodeTop = this.formatCanvasSize(1500) |
| | | context.drawImage(this.filePath, barcodeLeft, barcodeTop, |
| | | barcodeSize, |
| | | barcodeSize) |
| | | this.showBarcode = true |
| | | this.$nextTick(() => { |
| | | context.draw(false, () => {}) |
| | | }) |
| | | }, |
| | | fail: (err) => { |
| | | this.$message.showToast('写入文件失败') |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | // #endif |
| | | } else { |
| | | this.$message.confirm('登录后才能分享,是否立即登录?').then(() => { |
| | | uni.navigateTo({ |
| | | url: '/pages/account/login' |
| | | }) |
| | | }).catch(() => {}) |
| | | } |
| | | }, |
| | | fillTextSingleLine(context, text, maxLength, startLeft, startTop) { |
| | | let nameWidth = 0 |
| | | for (let i = 0; i < text.length; i++) { |
| | | const str = text[i] |
| | | nameWidth += context.measureText(str).width |
| | | if (nameWidth > maxLength - 10) { |
| | | context.fillText('...', startLeft, startTop) |
| | | break |
| | | } else { |
| | | context.fillText(str, startLeft, startTop) |
| | | startLeft += context.measureText(str).width + 2 |
| | | } |
| | | } |
| | | }, |
| | | fillTextByLength(context, text, len, startLeft, startTop) { |
| | | if (text.length > len - 3) { |
| | | text = text.substr(0, len - 3) + '...' |
| | | } |
| | | context.fillText(text, startLeft, startTop) |
| | | }, |
| | | getImageInfo(url) { |
| | | if (ENV === 'prod') { |
| | | url = url.replace(/http:\/\//g, 'https://') |
| | | } |
| | | return new Promise((resolve, reject) => { |
| | | uni.getImageInfo({ |
| | | src: url, |
| | | success: (res) => { |
| | | resolve(res.path) |
| | | }, |
| | | fail: (e) => { |
| | | reject(e) |
| | | } |
| | | }) |
| | | }) |
| | | }, |
| | | saveToAlbum() { |
| | | uni.canvasToTempFilePath({ |
| | | x: 0, |
| | | y: 0, |
| | | width: this.canvasWidth, |
| | | height: this.canvasHeight, |
| | | canvasId: 'barcode', |
| | | success: (res) => { |
| | | uni.saveImageToPhotosAlbum({ |
| | | filePath: res.tempFilePath, |
| | | success: () => { |
| | | this.$message.showToast('已为您保存至相册') |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | }, |
| | | hideBarcode() { |
| | | this.showBarcode = false |
| | | if (this.filePath) { |
| | | const fsm = wx.getFileSystemManager() |
| | | fsm.unlink({ |
| | | filePath: this.filePath, |
| | | success: () => { |
| | | this.filePath = '' |
| | | } |
| | | }) |
| | | } |
| | | }, |
| | | stopPop() { |
| | | // do nothing |
| | | }, |
| | | async getScene(id) { |
| | | const { |
| | | code, |
| | | data |
| | | } = await commonService.getScene(id) |
| | | if (code === 0) { |
| | | const productId = this.$utils.getBarcodeQueryString(data, 'id') |
| | | const inviteId = this.$utils.getBarcodeQueryString(data, 'inviteId') |
| | | const groupId = this.$utils.getBarcodeQueryString(data, 'groupId') |
| | | if (productId) { |
| | | this.id = productId |
| | | if (inviteId) { |
| | | this.$store.commit('account/SET_INVITEID', inviteId) |
| | | } |
| | | if (groupId) { |
| | | this.isGroup = true |
| | | this.groupId = groupId |
| | | this.getGroupDetail() |
| | | } else { |
| | | this.getDetail() |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | setPosterPadding() { |
| | | const windowHeight = uni.getSystemInfoSync().windowHeight |
| | | this.posterPadding = (windowHeight - 126 - this.canvasHeight) / 2 + 'px' |
| | | } |
| | | }, |
| | | async onLoad(options) { |
| | | this.setPosterPadding() |
| | | this.id = options.id || '' |
| | | }, |
| | | onUnload() { |
| | | }, |
| | | onShareAppMessage() { |
| | | let params = `id=${this.info.Id}` |
| | | if (this.isGroup) { |
| | | params += `&groupId=${this.groupId}` |
| | | } |
| | | if (this.memberId) { |
| | | params += `&inviteId=${this.memberId}` |
| | | } |
| | | let path = `/pages/home/product/detail?${params}` |
| | | return { |
| | | title: this.info.Name, |
| | | path: path |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .product-detail-page { |
| | | height: 100%; |
| | | <style scoped> |
| | | .button { |
| | | display: flex; |
| | | flex-direction: column; |
| | | |
| | | &__scroll { |
| | | flex: 1; |
| | | overflow: auto; |
| | | |
| | | &__swiper { |
| | | position: relative; |
| | | width: 100%; |
| | | height: 446rpx; |
| | | background-color: #fff; |
| | | |
| | | &__target { |
| | | height: 100%; |
| | | |
| | | &__item { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | |
| | | &__img { |
| | | width: 400rpx; |
| | | height: 400rpx; |
| | | } |
| | | } |
| | | } |
| | | |
| | | &__page { |
| | | position: absolute; |
| | | bottom: 14rpx; |
| | | right: 40rpx; |
| | | height: 40rpx; |
| | | border-radius: 20rpx; |
| | | background-color: rgba(0, 0, 0, 0.6); |
| | | padding: 0 14rpx; |
| | | font-size: 28rpx; |
| | | color: #fff; |
| | | } |
| | | } |
| | | |
| | | &__default-image { |
| | | width: 100%; |
| | | height: 446rpx; |
| | | } |
| | | |
| | | &__info { |
| | | background-color: #fff; |
| | | padding: 18rpx 30rpx 28rpx 30rpx; |
| | | |
| | | &__title { |
| | | font-size: 32rpx; |
| | | color: #000; |
| | | font-weight: 500; |
| | | line-height: 44rpx; |
| | | margin-bottom: 14rpx; |
| | | } |
| | | |
| | | &__desc { |
| | | font-size: 28rpx; |
| | | color: #666; |
| | | line-height: 40rpx; |
| | | margin-bottom: 10rpx; |
| | | } |
| | | |
| | | &__bulter { |
| | | font-size: 28rpx; |
| | | color: #000; |
| | | line-height: 40rpx; |
| | | } |
| | | |
| | | &__tags { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-top: 10rpx; |
| | | |
| | | &__item { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-right: 44rpx; |
| | | |
| | | &__icon { |
| | | width: 28rpx; |
| | | height: 28rpx; |
| | | margin-right: 4rpx; |
| | | } |
| | | |
| | | &__text { |
| | | font-size: 24rpx; |
| | | color: #000; |
| | | } |
| | | } |
| | | |
| | | &__count { |
| | | flex: 1; |
| | | text-align: right; |
| | | font-size: 24rpx; |
| | | color: #666; |
| | | } |
| | | } |
| | | } |
| | | |
| | | &__desc { |
| | | padding: 30rpx; |
| | | background-color: #fff; |
| | | margin-top: 24rpx; |
| | | |
| | | &__title { |
| | | font-size: 36rpx; |
| | | color: #000; |
| | | font-weight: 500; |
| | | line-height: 50rpx; |
| | | margin-bottom: 26rpx; |
| | | } |
| | | } |
| | | |
| | | &__team { |
| | | background-color: #fff; |
| | | padding-bottom: 48rpx; |
| | | |
| | | &__title { |
| | | font-size: 28rpx; |
| | | color: #000; |
| | | padding: 0 30rpx; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | &__main { |
| | | width: 750rpx; |
| | | padding: 60rpx 0; |
| | | position: relative; |
| | | display: flex; |
| | | justify-content: center; |
| | | |
| | | &__progress { |
| | | width: 630rpx; |
| | | height: 20rpx; |
| | | background-color: #d8d8d8; |
| | | border-radius: 16rpx; |
| | | |
| | | &__active { |
| | | height: 100%; |
| | | background-color: #d51d1d; |
| | | border-radius: 16rpx; |
| | | } |
| | | } |
| | | |
| | | &__price { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | position: absolute; |
| | | min-width: 120rpx; |
| | | |
| | | &__line { |
| | | width: 2rpx; |
| | | height: 24rpx; |
| | | background-color: #979797; |
| | | |
| | | &.current { |
| | | background-color: #d51d1d; |
| | | } |
| | | } |
| | | |
| | | &__target { |
| | | font-size: 24rpx; |
| | | color: #000; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | &__current { |
| | | font-size: 20rpx; |
| | | color: #d51d1d; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | &__team-intro { |
| | | padding: 8rpx 30rpx; |
| | | background-color: #EDE0CC; |
| | | margin-top: 24rpx; |
| | | |
| | | &__target { |
| | | font-size: 24rpx; |
| | | color: #9C753B; |
| | | font-weight: bold; |
| | | |
| | | &:not(:first-child) { |
| | | margin-top: 8rpx; |
| | | } |
| | | } |
| | | } |
| | | |
| | | &__team-info { |
| | | padding: 16rpx 30rpx 0 16rpx; |
| | | |
| | | &__line { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | margin-bottom: 8rpx; |
| | | |
| | | &__label { |
| | | font-size: 28rpx; |
| | | color: #000; |
| | | } |
| | | |
| | | &__value { |
| | | font-size: 28rpx; |
| | | color: #000; |
| | | flex: 1; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | | </style> |
| | |
| | | <!-- --> |
| | | <view class="contact-container"> |
| | | <view class="container" @click="saveCode"> |
| | | |
| | | |
| | | <canvas type="2d" id="myQrcode" class="code"></canvas> |
| | | <view class="info"> |
| | | <view class="desc"> |