From 802290838fd05c7236dae780900b4bacb20c82df Mon Sep 17 00:00:00 2001
From: xuxueyang <xuxy@fengyuntec.com>
Date: 星期五, 02 八月 2024 16:27:26 +0800
Subject: [PATCH] add 二维码格式
---
pages/login/supplier-login.vue | 102 +
pages/home/home.vue | 8
components/qr_code/qrcode.vue | 27
sub_pages/partner/partner-info/partner-code.vue | 2
pages/login/supplier-reg.vue | 29
sub_pages/partner/partner-info/partner-code-v2.vue | 754 +--------------
components/qr_code/qrcode.js | 1362 ++++++++++++++++++++++++++++++
App.vue | 16
components/hj-placard/shareImages.vue | 292 ++++++
sub_pages/customer/customer-info/customer-info.vue | 6
pages/user/supplier-user.vue | 80 +
store/index.js | 13
12 files changed, 1,955 insertions(+), 736 deletions(-)
diff --git a/App.vue b/App.vue
index d8ad526..f423ad2 100644
--- a/App.vue
+++ b/App.vue
@@ -51,10 +51,18 @@
// #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
},
diff --git a/components/hj-placard/shareImages.vue b/components/hj-placard/shareImages.vue
new file mode 100644
index 0000000..6f84159
--- /dev/null
+++ b/components/hj-placard/shareImages.vue
@@ -0,0 +1,292 @@
+<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>
\ No newline at end of file
diff --git a/components/qr_code/qrcode.js b/components/qr_code/qrcode.js
new file mode 100644
index 0000000..44e5715
--- /dev/null
+++ b/components/qr_code/qrcode.js
@@ -0,0 +1,1362 @@
+//---------------------------------------------------------------------
+// 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;
diff --git a/components/qr_code/qrcode.vue b/components/qr_code/qrcode.vue
new file mode 100644
index 0000000..621582c
--- /dev/null
+++ b/components/qr_code/qrcode.vue
@@ -0,0 +1,27 @@
+<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>
\ No newline at end of file
diff --git a/pages/home/home.vue b/pages/home/home.vue
index c8e1246..7e40797 100644
--- a/pages/home/home.vue
+++ b/pages/home/home.vue
@@ -184,7 +184,13 @@
// };
// },
- 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', {
diff --git a/pages/login/supplier-login.vue b/pages/login/supplier-login.vue
index b49218b..6e36103 100644
--- a/pages/login/supplier-login.vue
+++ b/pages/login/supplier-login.vue
@@ -50,8 +50,10 @@
<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>
@@ -61,7 +63,7 @@
<!-- #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'
@@ -78,28 +80,78 @@
</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',
@@ -243,7 +295,7 @@
icon: 'none'
});
return;
- }
+ }
that.phoneNumber = ''
}
if (this.loginType == 'code') {
diff --git a/pages/login/supplier-reg.vue b/pages/login/supplier-reg.vue
index 85e6a25..4ea03aa 100644
--- a/pages/login/supplier-reg.vue
+++ b/pages/login/supplier-reg.vue
@@ -142,6 +142,17 @@
},
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() {
@@ -153,7 +164,23 @@
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'] || ''
diff --git a/pages/user/supplier-user.vue b/pages/user/supplier-user.vue
index 1f9cdfa..c9da5b7 100644
--- a/pages/user/supplier-user.vue
+++ b/pages/user/supplier-user.vue
@@ -179,13 +179,13 @@
<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 -->
@@ -343,7 +343,11 @@
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
},
@@ -355,8 +359,25 @@
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({
@@ -364,31 +385,28 @@
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('二维码格式不正确扫码失败')
}
@@ -402,6 +420,8 @@
}
});
},
+
+
toInfo() {
var url = ''
if (this.currentInfo.id) {
diff --git a/store/index.js b/store/index.js
index 528e0f9..69d8cd8 100644
--- a/store/index.js
+++ b/store/index.js
@@ -40,6 +40,7 @@
console.log('updateLogin', provider)
state.hasLogin = provider && true || false;
if (!state.hasLogin) {
+ state.currentInfo = {}
storage.removeItem('token')
}
},
@@ -53,15 +54,9 @@
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
diff --git a/sub_pages/customer/customer-info/customer-info.vue b/sub_pages/customer/customer-info/customer-info.vue
index 8d30ff2..5e4c1e3 100644
--- a/sub_pages/customer/customer-info/customer-info.vue
+++ b/sub_pages/customer/customer-info/customer-info.vue
@@ -138,6 +138,12 @@
...JSON.parse(tjson)
}
}
+ if(options.partnerUserId){
+ this.dto.partnerUserId = options.partnerUserId || ''
+ }
+ if(options.partnerUserName){
+ this.dto.partnerUserName = options.partnerUserName || ''
+ }
} else {
this.getCurrentInfo()
}
diff --git a/sub_pages/partner/partner-info/partner-code-v2.vue b/sub_pages/partner/partner-info/partner-code-v2.vue
index 9746ae6..c6d015e 100644
--- a/sub_pages/partner/partner-info/partner-code-v2.vue
+++ b/sub_pages/partner/partner-info/partner-code-v2.vue
@@ -1,688 +1,112 @@
<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>
\ No newline at end of file
diff --git a/sub_pages/partner/partner-info/partner-code.vue b/sub_pages/partner/partner-info/partner-code.vue
index 4041000..97cea11 100644
--- a/sub_pages/partner/partner-info/partner-code.vue
+++ b/sub_pages/partner/partner-info/partner-code.vue
@@ -3,7 +3,7 @@
<!-- -->
<view class="contact-container">
<view class="container" @click="saveCode">
-
+
<canvas type="2d" id="myQrcode" class="code"></canvas>
<view class="info">
<view class="desc">
--
Gitblit v1.9.3