diff --git a/App.vue b/App.vue
index ed1993c..4a362c5 100644
--- a/App.vue
+++ b/App.vue
@@ -25,6 +25,16 @@ export default {
});
let uuid = plus.device.uuid;
// #endif
+ // #ifdef H5
+ if (typeof window !== "undefined" && window.location) {
+ const pathname = window.location.pathname || "";
+ if (pathname && pathname !== "/" && pathname.includes("pages/")) {
+ const cleanPath = pathname.startsWith("/") ? pathname.slice(1) : pathname;
+ const search = window.location.search || "";
+ window.location.replace(`${window.location.origin}/#/${cleanPath}${search}`);
+ }
+ }
+ // #endif
},
onShow: function () {
console.log("App Show");
diff --git a/api/cart.js b/api/cart.js
index 67de22f..b9013a7 100644
--- a/api/cart.js
+++ b/api/cart.js
@@ -42,23 +42,23 @@ export function updateGoodsNum(data) {
// 查询结算列表
-export function getSettleList(data) {
+export function getSettleList(data) {
// return request.post('/common/getSmsCode',qs.stringify(params));
return request({
url: "/cart/getSettleList",
method: "post",
data,
});
-}
-
-// 立即购买预结算(含优惠券可用性和抵扣后金额)
-export function getDirectSettleList(data) {
- return request({
- url: "/cart/getDirectSettleList",
- method: "post",
- data,
- });
-}
+}
+
+// 立即购买预结算(含优惠券可用性和抵扣后金额)
+export function getDirectSettleList(data) {
+ return request({
+ url: "/cart/getDirectSettleList",
+ method: "post",
+ data,
+ });
+}
// 结算下单
export function settle(data) {
@@ -82,13 +82,20 @@ export function setSeckillOrder(data) {
url: "/seckill/order",
method: "post",
data,
- // cha:1
- // headers: {
- // "Content-Type": "application/x-www-form-urlencoded"
- // }
});
}
+// 秒杀下单
+export function setGroupBuyOrder(data) {
+ return request({
+ url: "/groupBuy/order/0910",
+ method: "post",
+ data,
+ });
+}
+
+setGroupBuyOrder
+
// 查询运费
export function getPostageQuery(data) {
diff --git a/api/order.js b/api/order.js
index f07bc52..9fcafa2 100644
--- a/api/order.js
+++ b/api/order.js
@@ -191,4 +191,13 @@ export function applyUpdateAddress(data) {
method: "post",
data,
});
+}
+
+// 团长取消尚无其他成员参加的拼团
+export function cancelTeam(data) {
+ return request({
+ url: "/groupBuy/cancelTeam/0910",
+ method: "post",
+ data,
+ });
}
\ No newline at end of file
diff --git a/api/product.js b/api/product.js
index 0f3e70b..73448d3 100644
--- a/api/product.js
+++ b/api/product.js
@@ -145,3 +145,42 @@ export function getSearchGoodsList(params) {
});
}
+// 拼团商品列表
+export function getGroupBuyList(params) {
+ return request({
+ url: "/groupBuy/getList/0910",
+ method: "get",
+ data: params,
+ });
+}
+
+// 可直接参加的拼团列表
+export function getGroupBuyJoinableList(params) {
+ return request({
+ url: "/groupBuy/getJoinableList/0910",
+ method: "get",
+ data: params,
+ });
+}
+
+// 当前拼团活动信息 (倒计时、startTime, endTime等)
+export function getGroupBuyCurrent(params) {
+ return request({
+ url: "/groupBuy/current/0910",
+ method: "get",
+ data: params,
+ });
+}
+
+// 获取拼团详情
+export function getTeamDetail(params) {
+ return request({
+ url: "/groupBuy/getTeamDetail/0910",
+ method: "get",
+ data: params,
+ });
+}
+
+
+
+
diff --git a/components/common/product-group-card.vue b/components/common/product-group-card.vue
new file mode 100644
index 0000000..dc317a3
--- /dev/null
+++ b/components/common/product-group-card.vue
@@ -0,0 +1,344 @@
+
+
+
+
+
+
+
+
+
+
+ {{ item.goodsName || item.title || item.name || '商品名称' }}
+
+
+
+
+
+ {{ item.groupSize || item.groupNum || item.groupCount ||
+ item.groupPersonCount || 2 }}人团
+ |
+ 已拼{{ item.soldNum !== undefined ? item.soldNum : (item.groupSales ||
+ item.groupSalesCount || item.sales || item.salesVolume || 12) }}份
+
+
+
+ {{ countdownDisplay }}
+
+
+
+
+
+
+ ⚡
+ 立省¥{{ discountAmount }}
+
+
+
+
+
+
+ ¥
+ {{ item.groupPrice !== undefined ? item.groupPrice : (item.price ||
+ '88.88') }}
+
+ ¥{{ originalPriceDisplay }}
+
+
+
+
+
+ 去拼团
+
+
+
+
+
+
+
+
+
+
diff --git a/components/common/product-seckill-card.vue b/components/common/product-seckill-card.vue
index a1be351..fdf6bdf 100644
--- a/components/common/product-seckill-card.vue
+++ b/components/common/product-seckill-card.vue
@@ -32,6 +32,10 @@
⚡
加倍补{{ item.subsidy }}积分
+
+ ⚡
+ 立省{{ item.secDiscount || item.subsidy || item.discount || 100 }}元
+
@@ -121,6 +125,8 @@ export default {
let url = "/pages/other_package/productInfo/productInfo?id=" + item.id;
if (this.activedType === 'seckill') {
url = "/pages/other_package/productInfo/productInfo?id=" + item.id + "&activedType=" + this.activedType + "&activityId=" + item.activityId;
+ } else if (this.activedType === 'group') {
+ url = "/pages/other_package/productInfo/productInfo?id=" + item.id + "&activedType=" + this.activedType;
}
uni.navigateTo({
url: url,
diff --git a/components/header.vue b/components/header.vue
index dc1c2e3..96c3c1a 100644
--- a/components/header.vue
+++ b/components/header.vue
@@ -48,11 +48,33 @@
const leftPath = this.leftPath;
const leftPathType = this.leftPathType;
if(leftPathType === "navigateTo"){
- uni.navigateBack();
+ const pages = getCurrentPages();
+ if (pages && pages.length > 1) {
+ const prevPage = pages[pages.length - 2];
+ const route = prevPage ? (prevPage.route || (prevPage.$page && prevPage.$page.route)) : '';
+ if (!leftPath || (route && leftPath.includes(route))) {
+ uni.navigateBack();
+ return;
+ }
+ }
+ if (leftPath) {
+ uni.redirectTo({
+ url: leftPath,
+ fail: () => {
+ uni.navigateTo({ url: leftPath });
+ }
+ });
+ } else {
+ uni.navigateBack();
+ }
}else if(leftPathType === "switchTab" && leftPath){
uni.switchTab({
url: leftPath,
});
+ }else if(leftPathType === "redirectTo" && leftPath){
+ uni.redirectTo({
+ url: leftPath,
+ });
}
},
rightJump() {
diff --git a/pages.json b/pages.json
index d0e56ed..5323d4d 100644
--- a/pages.json
+++ b/pages.json
@@ -698,6 +698,18 @@
"style": {
"navigationStyle": "custom"
}
+ },
+ {
+ "path": "group-buying/group-buying",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "group-detail/group-detail",
+ "style": {
+ "navigationStyle": "custom"
+ }
}
]
}
diff --git a/pages/active/components/share-popup.vue b/pages/active/components/share-popup.vue
new file mode 100644
index 0000000..d6f98ac
--- /dev/null
+++ b/pages/active/components/share-popup.vue
@@ -0,0 +1,1092 @@
+
+
+
+
+
+
+
+
+
diff --git a/pages/active/components/tki-qrcode/qrcode.js b/pages/active/components/tki-qrcode/qrcode.js
new file mode 100644
index 0000000..6ea6553
--- /dev/null
+++ b/pages/active/components/tki-qrcode/qrcode.js
@@ -0,0 +1,1201 @@
+let QRCode = {};
+(function () {
+ /**
+ * 获取单个字符的utf8编码
+ * unicode BMP平面约65535个字符
+ * @param {num} code
+ * return {array}
+ */
+ function unicodeFormat8(code) {
+ // 1 byte
+ var c0, c1, c2;
+ if (code < 128) {
+ return [code];
+ // 2 bytes
+ } else if (code < 2048) {
+ c0 = 192 + (code >> 6);
+ c1 = 128 + (code & 63);
+ return [c0, c1];
+ // 3 bytes
+ } else {
+ c0 = 224 + (code >> 12);
+ c1 = 128 + (code >> 6 & 63);
+ c2 = 128 + (code & 63);
+ return [c0, c1, c2];
+ }
+ }
+ /**
+ * 获取字符串的utf8编码字节串
+ * @param {string} string
+ * @return {array}
+ */
+ function getUTF8Bytes(string) {
+ var utf8codes = [];
+ for (var i = 0; i < string.length; i++) {
+ var code = string.charCodeAt(i);
+ var utf8 = unicodeFormat8(code);
+ for (var j = 0; j < utf8.length; j++) {
+ utf8codes.push(utf8[j]);
+ }
+ }
+ return utf8codes;
+ }
+ /**
+ * 二维码算法实现
+ * @param {string} data 要编码的信息字符串
+ * @param {num} errorCorrectLevel 纠错等级
+ */
+ function QRCodeAlg(data, errorCorrectLevel) {
+ this.typeNumber = -1; //版本
+ this.errorCorrectLevel = errorCorrectLevel;
+ this.modules = null; //二维矩阵,存放最终结果
+ this.moduleCount = 0; //矩阵大小
+ this.dataCache = null; //数据缓存
+ this.rsBlocks = null; //版本数据信息
+ this.totalDataCount = -1; //可使用的数据量
+ this.data = data;
+ this.utf8bytes = getUTF8Bytes(data);
+ this.make();
+ }
+ QRCodeAlg.prototype = {
+ constructor: QRCodeAlg,
+ /**
+ * 获取二维码矩阵大小
+ * @return {num} 矩阵大小
+ */
+ getModuleCount: function () {
+ return this.moduleCount;
+ },
+ /**
+ * 编码
+ */
+ make: function () {
+ this.getRightType();
+ this.dataCache = this.createData();
+ this.createQrcode();
+ },
+ /**
+ * 设置二位矩阵功能图形
+ * @param {bool} test 表示是否在寻找最好掩膜阶段
+ * @param {num} maskPattern 掩膜的版本
+ */
+ makeImpl: function (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);
+ }
+ this.setupPositionProbePattern(0, 0);
+ this.setupPositionProbePattern(this.moduleCount - 7, 0);
+ this.setupPositionProbePattern(0, this.moduleCount - 7);
+ this.setupPositionAdjustPattern();
+ this.setupTimingPattern();
+ this.setupTypeInfo(true, maskPattern);
+ if (this.typeNumber >= 7) {
+ this.setupTypeNumber(true);
+ }
+ this.mapData(this.dataCache, maskPattern);
+ },
+ /**
+ * 设置二维码的位置探测图形
+ * @param {num} row 探测图形的中心横坐标
+ * @param {num} col 探测图形的中心纵坐标
+ */
+ 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;
+ }
+ }
+ }
+ },
+ /**
+ * 创建二维码
+ * @return {[type]} [description]
+ */
+ createQrcode: function () {
+ var minLostPoint = 0;
+ var pattern = 0;
+ var bestModules = null;
+ for (var i = 0; i < 8; i++) {
+ this.makeImpl(i);
+ var lostPoint = QRUtil.getLostPoint(this);
+ if (i == 0 || minLostPoint > lostPoint) {
+ minLostPoint = lostPoint;
+ pattern = i;
+ bestModules = this.modules;
+ }
+ }
+ this.modules = bestModules;
+ this.setupTypeInfo(false, pattern);
+ if (this.typeNumber >= 7) {
+ this.setupTypeNumber(false);
+ }
+ },
+ /**
+ * 设置定位图形
+ * @return {[type]} [description]
+ */
+ 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);
+ if (this.modules[6][r] != null) {
+ continue;
+ }
+ this.modules[6][r] = (r % 2 == 0);
+ }
+ },
+ /**
+ * 设置矫正图形
+ * @return {[type]} [description]
+ */
+ 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;
+ }
+ }
+ }
+ }
+ }
+ },
+ /**
+ * 设置版本信息(7以上版本才有)
+ * @param {bool} test 是否处于判断最佳掩膜阶段
+ * @return {[type]} [description]
+ */
+ 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;
+ this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
+ }
+ },
+ /**
+ * 设置格式信息(纠错等级和掩膜版本)
+ * @param {bool} test
+ * @param {num} maskPattern 掩膜版本
+ * @return {}
+ */
+ setupTypeInfo: function (test, maskPattern) {
+ var data = (QRErrorCorrectLevel[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
+ 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);
+ },
+ /**
+ * 数据编码
+ * @return {[type]} [description]
+ */
+ createData: function () {
+ var buffer = new QRBitBuffer();
+ var lengthBits = this.typeNumber > 9 ? 16 : 8;
+ buffer.put(4, 4); //添加模式
+ buffer.put(this.utf8bytes.length, lengthBits);
+ for (var i = 0, l = this.utf8bytes.length; i < l; i++) {
+ buffer.put(this.utf8bytes[i], 8);
+ }
+ if (buffer.length + 4 <= this.totalDataCount * 8) {
+ buffer.put(0, 4);
+ }
+ // padding
+ while (buffer.length % 8 != 0) {
+ buffer.putBit(false);
+ }
+ // padding
+ while (true) {
+ if (buffer.length >= this.totalDataCount * 8) {
+ break;
+ }
+ buffer.put(QRCodeAlg.PAD0, 8);
+ if (buffer.length >= this.totalDataCount * 8) {
+ break;
+ }
+ buffer.put(QRCodeAlg.PAD1, 8);
+ }
+ return this.createBytes(buffer);
+ },
+ /**
+ * 纠错码编码
+ * @param {buffer} buffer 数据编码
+ * @return {[type]}
+ */
+ createBytes: function (buffer) {
+ var offset = 0;
+ var maxDcCount = 0;
+ var maxEcCount = 0;
+ var length = this.rsBlock.length / 3;
+ var rsBlocks = new Array();
+ for (var i = 0; i < length; i++) {
+ var count = this.rsBlock[i * 3 + 0];
+ var totalCount = this.rsBlock[i * 3 + 1];
+ var dataCount = this.rsBlock[i * 3 + 2];
+ for (var j = 0; j < count; j++) {
+ rsBlocks.push([dataCount, totalCount]);
+ }
+ }
+ var dcdata = new Array(rsBlocks.length);
+ var ecdata = new Array(rsBlocks.length);
+ for (var r = 0; r < rsBlocks.length; r++) {
+ var dcCount = rsBlocks[r][0];
+ var ecCount = rsBlocks[r][1] - 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 data = new Array(this.totalDataCount);
+ 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;
+
+ },
+ /**
+ * 布置模块,构建最终信息
+ * @param {} data
+ * @param {} maskPattern
+ * @return {}
+ */
+ 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;
+ }
+ }
+ }
+ }
+ };
+ /**
+ * 填充字段
+ */
+ QRCodeAlg.PAD0 = 0xEC;
+ QRCodeAlg.PAD1 = 0x11;
+ //---------------------------------------------------------------------
+ // 纠错等级对应的编码
+ //---------------------------------------------------------------------
+ var QRErrorCorrectLevel = [1, 0, 3, 2];
+ //---------------------------------------------------------------------
+ // 掩膜版本
+ //---------------------------------------------------------------------
+ var QRMaskPattern = {
+ PATTERN000: 0,
+ PATTERN001: 1,
+ PATTERN010: 2,
+ PATTERN011: 3,
+ PATTERN100: 4,
+ PATTERN101: 5,
+ PATTERN110: 6,
+ PATTERN111: 7
+ };
+ //---------------------------------------------------------------------
+ // 工具类
+ //---------------------------------------------------------------------
+ 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),
+ /*
+ BCH编码格式信息
+ */
+ 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;
+ },
+ /*
+ BCH编码版本信息
+ */
+ 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;
+ },
+ /*
+ 获取BCH位信息
+ */
+ 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);
+ }
+ },
+ /*
+ 获取RS的纠错多项式
+ */
+ 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;
+ },
+ /*
+ 获取评价
+ */
+ getLostPoint: function (qrCode) {
+ var moduleCount = qrCode.getModuleCount(),
+ lostPoint = 0,
+ darkCount = 0;
+ for (var row = 0; row < moduleCount; row++) {
+ var sameCount = 0;
+ var head = qrCode.modules[row][0];
+ for (var col = 0; col < moduleCount; col++) {
+ var current = qrCode.modules[row][col];
+ //level 3 评价
+ if (col < moduleCount - 6) {
+ if (current && !qrCode.modules[row][col + 1] && qrCode.modules[row][col + 2] && qrCode.modules[row][col + 3] && qrCode.modules[row][col + 4] && !qrCode.modules[row][col + 5] && qrCode.modules[row][col + 6]) {
+ if (col < moduleCount - 10) {
+ if (qrCode.modules[row][col + 7] && qrCode.modules[row][col + 8] && qrCode.modules[row][col + 9] && qrCode.modules[row][col + 10]) {
+ lostPoint += 40;
+ }
+ } else if (col > 3) {
+ if (qrCode.modules[row][col - 1] && qrCode.modules[row][col - 2] && qrCode.modules[row][col - 3] && qrCode.modules[row][col - 4]) {
+ lostPoint += 40;
+ }
+ }
+ }
+ }
+ //level 2 评价
+ if ((row < moduleCount - 1) && (col < moduleCount - 1)) {
+ var count = 0;
+ if (current) count++;
+ if (qrCode.modules[row + 1][col]) count++;
+ if (qrCode.modules[row][col + 1]) count++;
+ if (qrCode.modules[row + 1][col + 1]) count++;
+ if (count == 0 || count == 4) {
+ lostPoint += 3;
+ }
+ }
+ //level 1 评价
+ if (head ^ current) {
+ sameCount++;
+ } else {
+ head = current;
+ if (sameCount >= 5) {
+ lostPoint += (3 + sameCount - 5);
+ }
+ sameCount = 1;
+ }
+ //level 4 评价
+ if (current) {
+ darkCount++;
+ }
+ }
+ }
+ for (var col = 0; col < moduleCount; col++) {
+ var sameCount = 0;
+ var head = qrCode.modules[0][col];
+ for (var row = 0; row < moduleCount; row++) {
+ var current = qrCode.modules[row][col];
+ //level 3 评价
+ if (row < moduleCount - 6) {
+ if (current && !qrCode.modules[row + 1][col] && qrCode.modules[row + 2][col] && qrCode.modules[row + 3][col] && qrCode.modules[row + 4][col] && !qrCode.modules[row + 5][col] && qrCode.modules[row + 6][col]) {
+ if (row < moduleCount - 10) {
+ if (qrCode.modules[row + 7][col] && qrCode.modules[row + 8][col] && qrCode.modules[row + 9][col] && qrCode.modules[row + 10][col]) {
+ lostPoint += 40;
+ }
+ } else if (row > 3) {
+ if (qrCode.modules[row - 1][col] && qrCode.modules[row - 2][col] && qrCode.modules[row - 3][col] && qrCode.modules[row - 4][col]) {
+ lostPoint += 40;
+ }
+ }
+ }
+ }
+ //level 1 评价
+ if (head ^ current) {
+ sameCount++;
+ } else {
+ head = current;
+ if (sameCount >= 5) {
+ lostPoint += (3 + sameCount - 5);
+ }
+ sameCount = 1;
+ }
+ }
+ }
+ // LEVEL4
+ var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
+ lostPoint += ratio * 10;
+ return lostPoint;
+ }
+
+ };
+ //---------------------------------------------------------------------
+ // QRMath使用的数学工具
+ //---------------------------------------------------------------------
+ var QRMath = {
+ /*
+ 将n转化为a^m
+ */
+ glog: function (n) {
+ if (n < 1) {
+ throw new Error("glog(" + n + ")");
+ }
+ return QRMath.LOG_TABLE[n];
+ },
+ /*
+ 将a^m转化为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 多项式
+ //---------------------------------------------------------------------
+ /**
+ * 多项式类
+ * @param {Array} num 系数
+ * @param {num} shift a^shift
+ */
+ 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;
+ },
+ /**
+ * 多项式乘法
+ * @param {QRPolynomial} e 被乘多项式
+ * @return {[type]} [description]
+ */
+ 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);
+ },
+ /**
+ * 多项式模运算
+ * @param {QRPolynomial} e 模多项式
+ * @return {}
+ */
+ mod: function (e) {
+ var tl = this.getLength(),
+ el = e.getLength();
+ if (tl - el < 0) {
+ return this;
+ }
+ var num = new Array(tl);
+ for (var i = 0; i < tl; i++) {
+ num[i] = this.get(i);
+ }
+ while (num.length >= el) {
+ var ratio = QRMath.glog(num[0]) - QRMath.glog(e.get(0));
+
+ for (var i = 0; i < e.getLength(); i++) {
+ num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio);
+ }
+ while (num[0] == 0) {
+ num.shift();
+ }
+ }
+ return new QRPolynomial(num, 0);
+ }
+ };
+
+ //---------------------------------------------------------------------
+ // RS_BLOCK_TABLE
+ //---------------------------------------------------------------------
+ /*
+ 二维码各个版本信息[块数, 每块中的数据块数, 每块中的信息块数]
+ */
+ var 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]
+ ];
+
+ /**
+ * 根据数据获取对应版本
+ * @return {[type]} [description]
+ */
+ QRCodeAlg.prototype.getRightType = function () {
+ for (var typeNumber = 1; typeNumber < 41; typeNumber++) {
+ var rsBlock = RS_BLOCK_TABLE[(typeNumber - 1) * 4 + this.errorCorrectLevel];
+ if (rsBlock == undefined) {
+ throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + this.errorCorrectLevel);
+ }
+ var length = rsBlock.length / 3;
+ var totalDataCount = 0;
+ for (var i = 0; i < length; i++) {
+ var count = rsBlock[i * 3 + 0];
+ var dataCount = rsBlock[i * 3 + 2];
+ totalDataCount += dataCount * count;
+ }
+ var lengthBytes = typeNumber > 9 ? 2 : 1;
+ if (this.utf8bytes.length + lengthBytes < totalDataCount || typeNumber == 40) {
+ this.typeNumber = typeNumber;
+ this.rsBlock = rsBlock;
+ this.totalDataCount = totalDataCount;
+ break;
+ }
+ }
+ };
+
+ //---------------------------------------------------------------------
+ // 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);
+ },
+ put: function (num, length) {
+ for (var i = 0; i < length; i++) {
+ this.putBit(((num >>> (length - i - 1)) & 1));
+ }
+ },
+ 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++;
+ }
+ };
+
+
+
+ // xzedit
+ let qrcodeAlgObjCache = [];
+ /**
+ * 二维码构造函数,主要用于绘制
+ * @param {参数列表} opt 传递参数
+ * @return {}
+ */
+ QRCode = function (opt) {
+ //设置默认参数
+ this.options = {
+ text: '',
+ size: 256,
+ correctLevel: 3,
+ background: '#ffffff',
+ foreground: '#000000',
+ pdground: '#000000',
+ image: '',
+ imageSize: 30,
+ canvasId: opt.canvasId,
+ context: opt.context,
+ usingComponents: opt.usingComponents,
+ showLoading: opt.showLoading,
+ loadingText: opt.loadingText,
+ };
+ if (typeof opt === 'string') { // 只编码ASCII字符串
+ opt = {
+ text: opt
+ };
+ }
+ if (opt) {
+ for (var i in opt) {
+ this.options[i] = opt[i];
+ }
+ }
+ //使用QRCodeAlg创建二维码结构
+ var qrCodeAlg = null;
+ for (var i = 0, l = qrcodeAlgObjCache.length; i < l; i++) {
+ if (qrcodeAlgObjCache[i].text == this.options.text && qrcodeAlgObjCache[i].text.correctLevel == this.options.correctLevel) {
+ qrCodeAlg = qrcodeAlgObjCache[i].obj;
+ break;
+ }
+ }
+ if (i == l) {
+ qrCodeAlg = new QRCodeAlg(this.options.text, this.options.correctLevel);
+ qrcodeAlgObjCache.push({
+ text: this.options.text,
+ correctLevel: this.options.correctLevel,
+ obj: qrCodeAlg
+ });
+ }
+ /**
+ * 计算矩阵点的前景色
+ * @param {Obj} config
+ * @param {Number} config.row 点x坐标
+ * @param {Number} config.col 点y坐标
+ * @param {Number} config.count 矩阵大小
+ * @param {Number} config.options 组件的options
+ * @return {String}
+ */
+ let getForeGround = function (config) {
+ var options = config.options;
+ if (options.pdground && (
+ (config.row > 1 && config.row < 5 && config.col > 1 && config.col < 5) ||
+ (config.row > (config.count - 6) && config.row < (config.count - 2) && config.col > 1 && config.col < 5) ||
+ (config.row > 1 && config.row < 5 && config.col > (config.count - 6) && config.col < (config.count - 2))
+ )) {
+ return options.pdground;
+ }
+ return options.foreground;
+ }
+ // 创建canvas
+ let createCanvas = function (options) {
+ if (options.showLoading) {
+ uni.showLoading({
+ title: options.loadingText,
+ mask: true
+ });
+ }
+ var ctx = uni.createCanvasContext(options.canvasId, options.context);
+ var count = qrCodeAlg.getModuleCount();
+ var ratioSize = options.size;
+ var ratioImgSize = options.imageSize;
+ //计算每个点的长宽
+ var tileW = (ratioSize / count).toPrecision(4);
+ var tileH = (ratioSize / count).toPrecision(4);
+ //绘制
+ for (var row = 0; row < count; row++) {
+ for (var col = 0; col < count; col++) {
+ var w = (Math.ceil((col + 1) * tileW) - Math.floor(col * tileW));
+ var h = (Math.ceil((row + 1) * tileW) - Math.floor(row * tileW));
+ var foreground = getForeGround({
+ row: row,
+ col: col,
+ count: count,
+ options: options
+ });
+ ctx.setFillStyle(qrCodeAlg.modules[row][col] ? foreground : options.background);
+ ctx.fillRect(Math.round(col * tileW), Math.round(row * tileH), w, h);
+ }
+ }
+ if (options.image) {
+ var x = Number(((ratioSize - ratioImgSize) / 2).toFixed(2));
+ var y = Number(((ratioSize - ratioImgSize) / 2).toFixed(2));
+ drawRoundedRect(ctx, x, y, ratioImgSize, ratioImgSize, 2, 6, true, true)
+ ctx.drawImage(options.image, x, y, ratioImgSize, ratioImgSize);
+ // 画圆角矩形
+ function drawRoundedRect(ctxi, x, y, width, height, r, lineWidth, fill, stroke) {
+ ctxi.setLineWidth(lineWidth);
+ ctxi.setFillStyle(options.background);
+ ctxi.setStrokeStyle(options.background);
+ ctxi.beginPath(); // draw top and top right corner
+ ctxi.moveTo(x + r, y);
+ ctxi.arcTo(x + width, y, x + width, y + r, r); // draw right side and bottom right corner
+ ctxi.arcTo(x + width, y + height, x + width - r, y + height, r); // draw bottom and bottom left corner
+ ctxi.arcTo(x, y + height, x, y + height - r, r); // draw left and top left corner
+ ctxi.arcTo(x, y, x + r, y, r);
+ ctxi.closePath();
+ if (fill) {
+ ctxi.fill();
+ }
+ if (stroke) {
+ ctxi.stroke();
+ }
+ }
+ }
+ setTimeout(() => {
+ ctx.draw(true, () => {
+ // 保存到临时区域
+ setTimeout(() => {
+ uni.canvasToTempFilePath({
+ width: options.width,
+ height: options.height,
+ destWidth: options.width,
+ destHeight: options.height,
+ canvasId: options.canvasId,
+ quality: Number(1),
+ success: function (res) {
+ if (options.cbResult) {
+ options.cbResult(res.tempFilePath)
+ }
+ },
+ fail: function (res) {
+ if (options.cbResult) {
+ options.cbResult(res)
+ }
+ },
+ complete: function () {
+ if (options.showLoading){
+ uni.hideLoading();
+ }
+ },
+ }, options.context);
+ }, options.text.length + 100);
+ });
+ }, options.usingComponents ? 0 : 150);
+ }
+ createCanvas(this.options);
+ // 空判定
+ let empty = function (v) {
+ let tp = typeof v,
+ rt = false;
+ if (tp == "number" && String(v) == "") {
+ rt = true
+ } else if (tp == "undefined") {
+ rt = true
+ } else if (tp == "object") {
+ if (JSON.stringify(v) == "{}" || JSON.stringify(v) == "[]" || v == null) rt = true
+ } else if (tp == "string") {
+ if (v == "" || v == "undefined" || v == "null" || v == "{}" || v == "[]") rt = true
+ } else if (tp == "function") {
+ rt = false
+ }
+ return rt
+ }
+ };
+ QRCode.prototype.clear = function (fn) {
+ var ctx = uni.createCanvasContext(this.options.canvasId, this.options.context)
+ ctx.clearRect(0, 0, this.options.size, this.options.size)
+ ctx.draw(false, () => {
+ if (fn) {
+ fn()
+ }
+ })
+ };
+})()
+
+export default QRCode
\ No newline at end of file
diff --git a/pages/active/components/tki-qrcode/tki-qrcode.vue b/pages/active/components/tki-qrcode/tki-qrcode.vue
new file mode 100644
index 0000000..2eee5fc
--- /dev/null
+++ b/pages/active/components/tki-qrcode/tki-qrcode.vue
@@ -0,0 +1,211 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/active/group-buying/group-buying.vue b/pages/active/group-buying/group-buying.vue
new file mode 100644
index 0000000..2bb21b4
--- /dev/null
+++ b/pages/active/group-buying/group-buying.vue
@@ -0,0 +1,274 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/active/group-detail/group-detail.vue b/pages/active/group-detail/group-detail.vue
new file mode 100644
index 0000000..16f05e9
--- /dev/null
+++ b/pages/active/group-detail/group-detail.vue
@@ -0,0 +1,1229 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ navTitle }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ teamDetail.goodsName }}
+
+ {{ teamDetail.requiredNum }}人成团
+
+
+
+ 拼团价
+ ¥
+ {{ teamDetail.groupPrice }}
+
+
+ ¥{{ teamDetail.salePrice }}
+
+
+
+
+
+
+
+
+
+
+
+ 拼团剩余时间 {{ countdownText }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 团长
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 邀请好友参团
+
+
+
+
+ 单独购买
+
+
+
+
+
+
+ 参加这个团
+
+
+
+
+
+
+ 查看订单
+
+
+
+
+
+
+
+ 拼团玩法
+
+
+
+
+
+ 开团/参加
+
+
+
+ 邀请好友参团
+
+
+
+ 成团发货
+
+
+
+
+
+ 购买须知:付款后等待成团,成团后 1-3 天发货。未成团且不支持自动成团时全额退款。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/active/static/group_banner_cart.jpg b/pages/active/static/group_banner_cart.jpg
new file mode 100644
index 0000000..4344a73
Binary files /dev/null and b/pages/active/static/group_banner_cart.jpg differ
diff --git a/pages/home/home.vue b/pages/home/home.vue
index 6da519f..dd4171e 100644
--- a/pages/home/home.vue
+++ b/pages/home/home.vue
@@ -379,9 +379,9 @@ export default {
// #ifdef MP
const hasSeenGuide = uni.getStorageSync("has_seen_home_guide");
if (hasSeenGuide) {
- uni.showTabBar({ animation: false, fail: () => {} });
+ uni.showTabBar({ animation: false, fail: () => { } });
} else {
- uni.hideTabBar({ animation: false, fail: () => {} });
+ uni.hideTabBar({ animation: false, fail: () => { } });
}
// #endif
this.refreshKefuUnread();
@@ -720,21 +720,39 @@ export default {
let _this = this;
uni.getClipboardData({
success: function (res) {
- // http://localhost:5173/#/pages/other_package/productInfo/productInfo?id=1038
- console.log(res.data); // 剪贴板内容
- if (
- res.data.indexOf(
- `${SHARE_URL}/#/pages/other_package/productInfo/productInfo?id=`,
- ) != -1
- ) {
+ const text = res.data || "";
+ console.log('剪贴板内容', text);
+ const isGroupDetail = text.indexOf("pages/active/group-detail/group-detail") !== -1;
+ const isProductInfo = text.indexOf("pages/other_package/productInfo/productInfo") !== -1;
+ const hasShareUrl = (SHARE_URL && text.indexOf(SHARE_URL) !== -1) ||
+ text.indexOf("https://h.tbmall.xin") !== -1 ||
+ text.indexOf("https://h.o.tbmall.xin") !== -1;
+
+ if (isGroupDetail || isProductInfo || hasShareUrl) {
uni.showModal({
title: "",
content: "当前APP想要粘贴商品详情,是否继续?",
success: (res1) => {
if (res1.confirm) {
- let id = res.data.match(/=(.*?)\s/);
- _this.curId = Number(id[1]);
- _this.getShop();
+ const teamMatch = text.match(/[?&]teamId=([^& \s]+)/);
+ const teamId = teamMatch ? teamMatch[1] : "";
+ const match = text.match(/[?&]id=([^& \s]+)/);
+ const id = match ? match[1] : "";
+ console.log("获取id", id, "teamId", teamId);
+
+ // 识别到了有 teamId,跳转到拼团详情页(展示“参加这个团”场景)
+ if (teamId) {
+ uni.navigateTo({
+ url: `/pages/active/group-detail/group-detail?teamId=${teamId}&id=${id}`,
+ });
+ } else if (text.indexOf('activedType=groupBuy&activityId=1') !== -1) {
+ uni.navigateTo({
+ url: `/pages/other_package/productInfo/productInfo?id=${id}&activedType=groupBuy&activityId=1`,
+ });
+ } else {
+ _this.curId = Number(id);
+ _this.getShop();
+ }
uni.setClipboardData({
data: "",
});
diff --git a/pages/login_package/login/login.vue b/pages/login_package/login/login.vue
index 8ecb993..b98db9b 100644
--- a/pages/login_package/login/login.vue
+++ b/pages/login_package/login/login.vue
@@ -167,7 +167,24 @@ export default {
});
// #endif
},
- onLoad() {
+ onLoad(options) {
+ let redirect = (options && options.redirect) || "";
+ // #ifdef H5
+ if (!redirect && this.$route && this.$route.query && this.$route.query.redirect) {
+ redirect = this.$route.query.redirect;
+ }
+ // #endif
+ if (!redirect) {
+ redirect = uni.getStorageSync("login_redirect_url") || "";
+ }
+ if (redirect) {
+ try {
+ this.redirect = decodeURIComponent(redirect);
+ } catch (e) {
+ this.redirect = redirect;
+ }
+ console.log("登录后重定向目标页面:", this.redirect);
+ }
// #ifdef APP-PLUS
// 判断微信是否安装 (iOS 的 scheme 为 weixin://)
this.isWechatInstalled = plus.runtime.isApplicationExist({
@@ -201,18 +218,57 @@ export default {
loading: false,
showPolicyModal: false,
isWechatInstalled: false,
+ redirect: "",
};
},
methods: {
onBack() {
- console.log('onBack',)
- uni.switchTab({
- url: '/pages/home/home'
- })
+ console.log('onBack')
+ const pages = getCurrentPages();
+ if (pages && pages.length > 1) {
+ uni.navigateBack();
+ } else {
+ uni.switchTab({
+ url: '/pages/home/home'
+ });
+ }
+ },
+
+ jumpAfterLogin() {
+ let target = this.redirect || uni.getStorageSync("login_redirect_url") || "";
+ uni.removeStorageSync("login_redirect_url");
+ if (target) {
+ try {
+ if (target.includes("%")) {
+ target = decodeURIComponent(target);
+ }
+ } catch (e) {}
+ console.log("登录成功,重定向回页面:", target);
+ uni.redirectTo({
+ url: target,
+ fail: (err) => {
+ console.warn("redirectTo 失败,尝试 switchTab:", err);
+ uni.switchTab({
+ url: target,
+ fail: () => {
+ uni.switchTab({ url: "/pages/home/home" });
+ },
+ });
+ },
+ });
+ } else {
+ const pages = getCurrentPages();
+ if (pages && pages.length > 1) {
+ uni.navigateBack();
+ } else {
+ uni.switchTab({
+ url: "/pages/home/home",
+ });
+ }
+ }
},
jumpHome() {
-
uni.switchTab({
url: "/pages/home/home",
});
@@ -271,8 +327,8 @@ export default {
});
setTimeout(() => {
- then.jumpHome();
- }, 2000);
+ then.jumpAfterLogin();
+ }, 1500);
},
checkNameParam(val) {
// console.log("val",val);
@@ -647,9 +703,7 @@ export default {
message: response.msg,
});
setTimeout(() => {
- uni.switchTab({
- url: "/pages/home/home",
- });
+ this.jumpAfterLogin();
}, 1200);
} else if (response && response.msg) {
this.$refs.uToastRef.show({
diff --git a/pages/mine_package/apply_refund/apply_refund.vue b/pages/mine_package/apply_refund/apply_refund.vue
index bdfc654..69da4de 100644
--- a/pages/mine_package/apply_refund/apply_refund.vue
+++ b/pages/mine_package/apply_refund/apply_refund.vue
@@ -143,7 +143,7 @@
diff --git a/pages/other_package/productInfo/components/product-contribution-dialog.vue b/pages/other_package/productInfo/components/product-contribution-dialog.vue
new file mode 100644
index 0000000..85ed63d
--- /dev/null
+++ b/pages/other_package/productInfo/components/product-contribution-dialog.vue
@@ -0,0 +1,151 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/other_package/productInfo/components/product-coupon-popup.vue b/pages/other_package/productInfo/components/product-coupon-popup.vue
new file mode 100644
index 0000000..791597f
--- /dev/null
+++ b/pages/other_package/productInfo/components/product-coupon-popup.vue
@@ -0,0 +1,420 @@
+
+
+
+
+
+
+
+
+
diff --git a/pages/other_package/productInfo/components/product-group-rules.vue b/pages/other_package/productInfo/components/product-group-rules.vue
new file mode 100644
index 0000000..e162d3f
--- /dev/null
+++ b/pages/other_package/productInfo/components/product-group-rules.vue
@@ -0,0 +1,247 @@
+
+
+
+
+
+ 拼团玩法
+
+
+
+
+
+ 开团/参加
+
+
+
+
+
+
+ 邀请好友参团
+
+
+
+
+
+
+ 成团发货
+
+
+
+ 购买须知:付款后等待成团,成团后 1-3 天发货。未成团且不支持自动成团时全额退款。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ team.nickname }}
+
+
+ {{ team.countdownText }}
+
+ 去拼团
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/other_package/productInfo/components/product-joinable-popup.vue b/pages/other_package/productInfo/components/product-joinable-popup.vue
new file mode 100644
index 0000000..5d73794
--- /dev/null
+++ b/pages/other_package/productInfo/components/product-joinable-popup.vue
@@ -0,0 +1,199 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/other_package/productInfo/productInfo.vue b/pages/other_package/productInfo/productInfo.vue
index db41799..8fcd00e 100644
--- a/pages/other_package/productInfo/productInfo.vue
+++ b/pages/other_package/productInfo/productInfo.vue
@@ -15,21 +15,54 @@
-
-
-
-
+
+
-
+
+
+
+
+
+
+
+
+ 拼团价
+ ¥
+ {{ orderInfo.groupPrice }}
+ ¥{{ groupOriginPrice }}
+
+
+ 只剩 {{ groupCountdownText }}
+
+
+
+
+
+
+ {{ orderInfo.name }}
+
+
+
+
+
+ 下单送{{ orderInfo.contribution }}贡献值
+
+
+
+ 全网销量{{ limit999(orderInfo.sales) }}
+
+
-
-
-
+
+
+
-->
+
+
+
+
退货提示
@@ -201,15 +239,28 @@
购物车
-
-
- 加入购物车
-
-
-
- 立即购买
-
+
+
+
+
+ 单独购买
+
+
+ {{ activedType === 'joinGroup' ? '参与拼团' : '发起拼团' }}
+
+
+
+
+
+ 加入购物车
+
+
+
+ 立即购买
+
+
@@ -263,6 +314,21 @@
+{{ orderInfo.minPrice }}元
+
+
+ 拼团价¥
+
+ {{ (selectSpecificationTempl && selectSpecificationTempl.groupPrice) ?
+ selectSpecificationTempl.groupPrice
+ : orderInfo.groupPrice }}
+
+
+ {{ orderInfo.groupSize || 2 }}人团
+
+
+
¥
@@ -298,8 +364,6 @@
{{ skuBySpecInfo.stock || 0 }}件 -->
已选规格: {{ skuBySpecInfo.skuName }}
-
-
@@ -330,7 +394,12 @@
+
- 去支付
+
+
+ 去支付
+
加入购物车
@@ -399,121 +468,25 @@
+ :id="id" :text="orderInfo.name ? orderInfo.name : ''" :tu="swiperList.length && swiperList[0]"
+ :price="isGroupProduct ? String(groupActivityInfo?.groupPrice || orderInfo.price) : String(orderInfo.price || '')"
+ :groupPrice="groupActivityInfo?.groupPrice ? String(groupActivityInfo.groupPrice) : ''"
+ :requiredNum="groupActivityInfo?.requiredNum || 2"
+ :sharePath="isGroupProduct ? `pages/other_package/productInfo/productInfo?id=${id}&activedType=groupBuy&activityId=1` : ''">
+
-
-
-
-
-
-
-
+
+
+