Browse Source

Merge branch 'master' of http://47.114.134.244:3000/chenkainan/yandu_WeChat

# Conflicts:
#	static/js/request.js
master
chenkainan 1 year ago
parent
commit
17d9f78776
  1. 46
      pages.json
  2. 2
      pages/index/index.vue
  3. 1
      pages/user/user.vue
  4. 9
      static/js/CommonFunction.js
  5. 426
      static/js/weapp-qrcode.js
  6. 214
      subPackages/eventCalendar/detail.vue
  7. 7
      subPackages/eventCalendar/eventCalendar.vue
  8. 2
      subPackages/food/foodDetail.vue
  9. 769
      subPackages/hotelHomestay/detail.vue
  10. 53
      subPackages/hotelHomestay/hotelHomestay.vue
  11. 601
      subPackages/hotelHomestay/order.vue
  12. 110
      subPackages/hotelHomestay/policy.vue
  13. 184
      subPackages/line/detail.vue
  14. 7
      subPackages/line/lineList.vue
  15. 387
      subPackages/order/detail.vue
  16. 2
      subPackages/order/orderCoupon.vue
  17. 5
      subPackages/order/trades.vue
  18. 30
      subPackages/techan/detail.vue
  19. 52
      subPackages/techan/order.vue
  20. 20
      subPackages/ticketBooking/detail.vue
  21. 248
      subPackages/ticketBooking/order.vue
  22. 17
      subPackages/ticketBooking/ticketBooking.vue
  23. 200
      subPackages/travelGuide/detail.vue
  24. 234
      subPackages/travelGuide/travelGuide.vue

46
pages.json

@ -93,6 +93,12 @@
"navigationStyle": "custom" "navigationStyle": "custom"
} }
}, },
{
"path": "line/detail",
"style": {
"navigationBarTitleText": "线路详情"
}
},
{ {
"path": "eventCalendar/eventCalendar", "path": "eventCalendar/eventCalendar",
"style": { "style": {
@ -100,6 +106,12 @@
"navigationStyle": "custom" "navigationStyle": "custom"
} }
}, },
{
"path": "eventCalendar/detail",
"style": {
"navigationBarTitleText": "活动详情"
}
},
{ {
"path": "service/service", "path": "service/service",
"style": { "style": {
@ -144,6 +156,39 @@
"navigationStyle": "custom" "navigationStyle": "custom"
} }
}, },
{
"path": "hotelHomestay/detail",
"style": {
"navigationBarTitleText": "酒店详情"
}
},
{
"path": "hotelHomestay/policy",
"style": {
"navigationBarTitleText": "设施/政策"
}
},
{
"path": "hotelHomestay/order",
"style": {
"navigationBarTitleText": "酒店民宿"
}
},
{
"path" : "travelGuide/travelGuide",
"style" :
{
"navigationBarTitleText": "游记攻略",
"navigationStyle": "custom"
}
},
{
"path" : "travelGuide/detail",
"style" :
{
"navigationBarTitleText": "攻略详情"
}
},
{ {
"path": "food/taocanDetail", "path": "food/taocanDetail",
"style": { "style": {
@ -205,6 +250,7 @@
"navigationStyle": "custom" "navigationStyle": "custom"
} }
} }
] ]
}], }],
"tabBar": { "tabBar": {

2
pages/index/index.vue

@ -186,7 +186,7 @@
{ {
img: 'https://static.ticket.sz-trip.com/yandu/images/index/jdmp.png', img: 'https://static.ticket.sz-trip.com/yandu/images/index/jdmp.png',
text: '游记攻略', text: '游记攻略',
path: '' path: '/subPackages/travelGuide/travelGuide'
}, },
{ {
img: 'https://static.ticket.sz-trip.com/yandu/images/index/jdmp.png', img: 'https://static.ticket.sz-trip.com/yandu/images/index/jdmp.png',

1
pages/user/user.vue

@ -137,6 +137,7 @@
} }
}, },
onShow() { onShow() {
this.userInfo = this.$store.state.user.userInfo || {}
// this.dfkList = [] // this.dfkList = []
// this.nowDateTime = parseInt(new Date().getTime() / 1000) // this.nowDateTime = parseInt(new Date().getTime() / 1000)
// this.Post({}, "/api/user/userInfo").then((res) => { // this.Post({}, "/api/user/userInfo").then((res) => {

9
static/js/CommonFunction.js

@ -221,3 +221,12 @@ Date.prototype.Format = function(fmt)
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length))); fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));
return fmt; return fmt;
} }
// 获取最大优惠券 params:{money:100,sku_ids:1,2}
Vue.prototype.getMaxCoupon = async function (param) {
let res = await this.Post(param, "/api/coupon/use_max_coupon_list")
if (res.code == 1 && res.data.id) {
this.$store.commit("choseCoupon",res.data);
}
return res.data
}

426
static/js/weapp-qrcode.js

@ -0,0 +1,426 @@
// Core code comes from https://github.com/davidshimjs/qrcodejs
var QRCode;
(function () {
/**
* Get the type by string length
*
* @private
* @param {String} sText
* @param {Number} nCorrectLevel
* @return {Number} type
*/
function _getTypeNumber(sText, nCorrectLevel) {
var nType = 1;
var length = _getUTF8Length(sText);
for (var i = 0, len = QRCodeLimitLength.length; i <= len; i++) {
var nLimit = 0;
switch (nCorrectLevel) {
case QRErrorCorrectLevel.L:
nLimit = QRCodeLimitLength[i][0];
break;
case QRErrorCorrectLevel.M:
nLimit = QRCodeLimitLength[i][1];
break;
case QRErrorCorrectLevel.Q:
nLimit = QRCodeLimitLength[i][2];
break;
case QRErrorCorrectLevel.H:
nLimit = QRCodeLimitLength[i][3];
break;
}
if (length <= nLimit) {
break;
} else {
nType++;
}
}
if (nType > QRCodeLimitLength.length) {
throw new Error("Too long data");
}
return nType;
}
function _getUTF8Length(sText) {
var replacedText = encodeURI(sText).toString().replace(/\%[0-9a-fA-F]{2}/g, 'a');
return replacedText.length + (replacedText.length != sText ? 3 : 0);
}
function QR8bitByte(data) {
this.mode = QRMode.MODE_8BIT_BYTE;
this.data = data;
this.parsedData = [];
// Added to support UTF-8 Characters
for (var i = 0, l = this.data.length; i < l; i++) {
var byteArray = [];
var code = this.data.charCodeAt(i);
if (code > 0x10000) {
byteArray[0] = 0xF0 | ((code & 0x1C0000) >>> 18);
byteArray[1] = 0x80 | ((code & 0x3F000) >>> 12);
byteArray[2] = 0x80 | ((code & 0xFC0) >>> 6);
byteArray[3] = 0x80 | (code & 0x3F);
} else if (code > 0x800) {
byteArray[0] = 0xE0 | ((code & 0xF000) >>> 12);
byteArray[1] = 0x80 | ((code & 0xFC0) >>> 6);
byteArray[2] = 0x80 | (code & 0x3F);
} else if (code > 0x80) {
byteArray[0] = 0xC0 | ((code & 0x7C0) >>> 6);
byteArray[1] = 0x80 | (code & 0x3F);
} else {
byteArray[0] = code;
}
this.parsedData.push(byteArray);
}
this.parsedData = Array.prototype.concat.apply([], this.parsedData);
if (this.parsedData.length != this.data.length) {
this.parsedData.unshift(191);
this.parsedData.unshift(187);
this.parsedData.unshift(239);
}
}
QR8bitByte.prototype = {
getLength: function (buffer) {
return this.parsedData.length;
},
write: function (buffer) {
for (var i = 0, l = this.parsedData.length; i < l; i++) {
buffer.put(this.parsedData[i], 8);
}
}
};
// QRCodeModel
function QRCodeModel(typeNumber, errorCorrectLevel) {
this.typeNumber = typeNumber;
this.errorCorrectLevel = errorCorrectLevel;
this.modules = null;
this.moduleCount = 0;
this.dataCache = null;
this.dataList = [];
}
QRCodeModel.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 () { 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; } }
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 = QRCodeModel.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); 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; } }
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; } }
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; }
}
}
}
};
QRCodeModel.PAD0 = 0xEC;
QRCodeModel.PAD1 = 0x11;
QRCodeModel.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); }
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
+ ")");
}
if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) { buffer.put(0, 4); }
while (buffer.getLengthInBits() % 8 != 0) { buffer.putBit(false); }
while (true) {
if (buffer.getLengthInBits() >= totalDataCount * 8) { break; }
buffer.put(QRCodeModel.PAD0, 8); if (buffer.getLengthInBits() >= totalDataCount * 8) { break; }
buffer.put(QRCodeModel.PAD1, 8);
}
return QRCodeModel.createBytes(buffer, rsBlocks);
};
QRCodeModel.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;
};
var QRMode = { MODE_NUMBER: 1 << 0, MODE_ALPHA_NUM: 1 << 1, MODE_8BIT_BYTE: 1 << 2, MODE_KANJI: 1 << 3 };
var QRErrorCorrectLevel = { L: 1, M: 0, Q: 3, H: 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), 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) { 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) { 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) { 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; 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); }
}
}
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; } } }
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; } } }
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;
}
};
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; }
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); }
return new QRPolynomial(num, 0).mod(e);
}
};
function QRRSBlock(totalCount, dataCount) { this.totalCount = totalCount; this.dataCount = dataCount; }
QRRSBlock.RS_BLOCK_TABLE = [[1, 26, 19], [1, 26, 16], [1, 26, 13], [1, 26, 9], [1, 44, 34], [1, 44, 28], [1, 44, 22], [1, 44, 16], [1, 70, 55], [1, 70, 44], [2, 35, 17], [2, 35, 13], [1, 100, 80], [2, 50, 32], [2, 50, 24], [4, 25, 9], [1, 134, 108], [2, 67, 43], [2, 33, 15, 2, 34, 16], [2, 33, 11, 2, 34, 12], [2, 86, 68], [4, 43, 27], [4, 43, 19], [4, 43, 15], [2, 98, 78], [4, 49, 31], [2, 32, 14, 4, 33, 15], [4, 39, 13, 1, 40, 14], [2, 121, 97], [2, 60, 38, 2, 61, 39], [4, 40, 18, 2, 41, 19], [4, 40, 14, 2, 41, 15], [2, 146, 116], [3, 58, 36, 2, 59, 37], [4, 36, 16, 4, 37, 17], [4, 36, 12, 4, 37, 13], [2, 86, 68, 2, 87, 69], [4, 69, 43, 1, 70, 44], [6, 43, 19, 2, 44, 20], [6, 43, 15, 2, 44, 16], [4, 101, 81], [1, 80, 50, 4, 81, 51], [4, 50, 22, 4, 51, 23], [3, 36, 12, 8, 37, 13], [2, 116, 92, 2, 117, 93], [6, 58, 36, 2, 59, 37], [4, 46, 20, 6, 47, 21], [7, 42, 14, 4, 43, 15], [4, 133, 107], [8, 59, 37, 1, 60, 38], [8, 44, 20, 4, 45, 21], [12, 33, 11, 4, 34, 12], [3, 145, 115, 1, 146, 116], [4, 64, 40, 5, 65, 41], [11, 36, 16, 5, 37, 17], [11, 36, 12, 5, 37, 13], [5, 109, 87, 1, 110, 88], [5, 65, 41, 5, 66, 42], [5, 54, 24, 7, 55, 25], [11, 36, 12], [5, 122, 98, 1, 123, 99], [7, 73, 45, 3, 74, 46], [15, 43, 19, 2, 44, 20], [3, 45, 15, 13, 46, 16], [1, 135, 107, 5, 136, 108], [10, 74, 46, 1, 75, 47], [1, 50, 22, 15, 51, 23], [2, 42, 14, 17, 43, 15], [5, 150, 120, 1, 151, 121], [9, 69, 43, 4, 70, 44], [17, 50, 22, 1, 51, 23], [2, 42, 14, 19, 43, 15], [3, 141, 113, 4, 142, 114], [3, 70, 44, 11, 71, 45], [17, 47, 21, 4, 48, 22], [9, 39, 13, 16, 40, 14], [3, 135, 107, 5, 136, 108], [3, 67, 41, 13, 68, 42], [15, 54, 24, 5, 55, 25], [15, 43, 15, 10, 44, 16], [4, 144, 116, 4, 145, 117], [17, 68, 42], [17, 50, 22, 6, 51, 23], [19, 46, 16, 6, 47, 17], [2, 139, 111, 7, 140, 112], [17, 74, 46], [7, 54, 24, 16, 55, 25], [34, 37, 13], [4, 151, 121, 5, 152, 122], [4, 75, 47, 14, 76, 48], [11, 54, 24, 14, 55, 25], [16, 45, 15, 14, 46, 16], [6, 147, 117, 4, 148, 118], [6, 73, 45, 14, 74, 46], [11, 54, 24, 16, 55, 25], [30, 46, 16, 2, 47, 17], [8, 132, 106, 4, 133, 107], [8, 75, 47, 13, 76, 48], [7, 54, 24, 22, 55, 25], [22, 45, 15, 13, 46, 16], [10, 142, 114, 2, 143, 115], [19, 74, 46, 4, 75, 47], [28, 50, 22, 6, 51, 23], [33, 46, 16, 4, 47, 17], [8, 152, 122, 4, 153, 123], [22, 73, 45, 3, 74, 46], [8, 53, 23, 26, 54, 24], [12, 45, 15, 28, 46, 16], [3, 147, 117, 10, 148, 118], [3, 73, 45, 23, 74, 46], [4, 54, 24, 31, 55, 25], [11, 45, 15, 31, 46, 16], [7, 146, 116, 7, 147, 117], [21, 73, 45, 7, 74, 46], [1, 53, 23, 37, 54, 24], [19, 45, 15, 26, 46, 16], [5, 145, 115, 10, 146, 116], [19, 75, 47, 10, 76, 48], [15, 54, 24, 25, 55, 25], [23, 45, 15, 25, 46, 16], [13, 145, 115, 3, 146, 116], [2, 74, 46, 29, 75, 47], [42, 54, 24, 1, 55, 25], [23, 45, 15, 28, 46, 16], [17, 145, 115], [10, 74, 46, 23, 75, 47], [10, 54, 24, 35, 55, 25], [19, 45, 15, 35, 46, 16], [17, 145, 115, 1, 146, 116], [14, 74, 46, 21, 75, 47], [29, 54, 24, 19, 55, 25], [11, 45, 15, 46, 46, 16], [13, 145, 115, 6, 146, 116], [14, 74, 46, 23, 75, 47], [44, 54, 24, 7, 55, 25], [59, 46, 16, 1, 47, 17], [12, 151, 121, 7, 152, 122], [12, 75, 47, 26, 76, 48], [39, 54, 24, 14, 55, 25], [22, 45, 15, 41, 46, 16], [6, 151, 121, 14, 152, 122], [6, 75, 47, 34, 76, 48], [46, 54, 24, 10, 55, 25], [2, 45, 15, 64, 46, 16], [17, 152, 122, 4, 153, 123], [29, 74, 46, 14, 75, 47], [49, 54, 24, 10, 55, 25], [24, 45, 15, 46, 46, 16], [4, 152, 122, 18, 153, 123], [13, 74, 46, 32, 75, 47], [48, 54, 24, 14, 55, 25], [42, 45, 15, 32, 46, 16], [20, 147, 117, 4, 148, 118], [40, 75, 47, 7, 76, 48], [43, 54, 24, 22, 55, 25], [10, 45, 15, 67, 46, 16], [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 = []; 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; } };
function QRBitBuffer() { this.buffer = []; 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++;
}
};
var QRCodeLimitLength = [[17, 14, 11, 7], [32, 26, 20, 14], [53, 42, 32, 24], [78, 62, 46, 34], [106, 84, 60, 44], [134, 106, 74, 58], [154, 122, 86, 64], [192, 152, 108, 84], [230, 180, 130, 98], [271, 213, 151, 119], [321, 251, 177, 137], [367, 287, 203, 155], [425, 331, 241, 177], [458, 362, 258, 194], [520, 412, 292, 220], [586, 450, 322, 250], [644, 504, 364, 280], [718, 560, 394, 310], [792, 624, 442, 338], [858, 666, 482, 382], [929, 711, 509, 403], [1003, 779, 565, 439], [1091, 857, 611, 461], [1171, 911, 661, 511], [1273, 997, 715, 535], [1367, 1059, 751, 593], [1465, 1125, 805, 625], [1528, 1190, 868, 658], [1628, 1264, 908, 698], [1732, 1370, 982, 742], [1840, 1452, 1030, 790], [1952, 1538, 1112, 842], [2068, 1628, 1168, 898], [2188, 1722, 1228, 958], [2303, 1809, 1283, 983], [2431, 1911, 1351, 1051], [2563, 1989, 1423, 1093], [2699, 2099, 1499, 1139], [2809, 2213, 1579, 1219], [2953, 2331, 1663, 1273]];
// QRCode object
QRCode = function (canvasId, vOption) {
this._htOption = {
width: 256,
height: 256,
typeNumber: 4,
colorDark: "#000000",
colorLight: "#ffffff",
correctLevel: QRErrorCorrectLevel.H
};
if (typeof vOption === 'string') {
vOption = {
text: vOption
};
}
// Overwrites options
if (vOption) {
for (var i in vOption) {
this._htOption[i] = vOption[i];
}
}
this._oQRCode = null;
this.canvasId = canvasId
if (this._htOption.text && this.canvasId) {
this.makeCode(this._htOption.text);
}
};
QRCode.prototype.makeCode = function (sText) {
this._oQRCode = new QRCodeModel(_getTypeNumber(sText, this._htOption.correctLevel), this._htOption.correctLevel);
this._oQRCode.addData(sText);
this._oQRCode.make();
this.makeImage();
};
QRCode.prototype.makeImage = function () {
var _oContext
if (this._htOption.usingIn) {
_oContext = wx.createCanvasContext(this.canvasId, this._htOption.usingIn)
}
else {
_oContext = wx.createCanvasContext(this.canvasId)
}
var _htOption = this._htOption;
var oQRCode = this._oQRCode
var nCount = oQRCode.getModuleCount();
var nWidth = _htOption.padding ? (_htOption.width - 2 * _htOption.padding) / nCount : _htOption.width / nCount;
var nHeight = _htOption.padding ? (_htOption.height - 2 * _htOption.padding) / nCount : _htOption.height / nCount;
var nRoundedHeight = Math.round(nHeight);
var nRoundedWidth = Math.round(nWidth);
if (_htOption.image && _htOption.image != '') {
_oContext.drawImage(_htOption.image, 0, 0, _htOption.width, _htOption.height)
}
_oContext.setFillStyle('#fff')
_oContext.fillRect(0, 0, _htOption.width, _htOption.height)
_oContext.save()
for (var row = 0; row < nCount; row++) {
for (var col = 0; col < nCount; col++) {
var bIsDark = oQRCode.isDark(row, col);
var nLeft = _htOption.padding ? col * nWidth + _htOption.padding : col * nWidth;
var nTop = _htOption.padding ? row * nHeight + _htOption.padding : row * nHeight;
_oContext.setStrokeStyle(bIsDark ? _htOption.colorDark : _htOption.colorLight)
// _oContext.setStrokeStyle('red')
_oContext.setLineWidth(1)
_oContext.setFillStyle(bIsDark ? _htOption.colorDark : _htOption.colorLight)
// _oContext.setFillStyle('red')
// if (bIsDark) {
_oContext.fillRect(nLeft, nTop, nWidth, nHeight);
// }
// 안티 앨리어싱 방지 처리
// if (bIsDark) {
_oContext.strokeRect(
Math.floor(nLeft) + 0.5,
Math.floor(nTop) + 0.5,
nRoundedHeight
);
_oContext.strokeRect(
Math.ceil(nLeft) - 0.5,
Math.ceil(nTop) - 0.5,
nRoundedWidth,
nRoundedHeight
);
// }
// _oContext.fillRect(
// Math.floor(nLeft) + 0.5,
// Math.floor(nTop) + 0.5,
// nRoundedWidth,
// nRoundedHeight
// );
// _oContext.fillRect(
// Math.ceil(nLeft) - 0.5,
// Math.ceil(nTop) - 0.5,
// nRoundedWidth,
// nRoundedHeight
// );
// _oContext.clearRect(
// Math.floor(nLeft) + 0.5,
// Math.floor(nTop) + 0.5,
// nRoundedWidth,
// nRoundedHeight
// );
// _oContext.clearRect(
// Math.ceil(nLeft) - 0.5,
// Math.ceil(nTop) - 0.5,
// nRoundedWidth,
// nRoundedHeight
// );
}
}
_oContext.draw(false, () => {
setTimeout(() => {
this.exportImage()
}, 800)
})
};
// 保存为图片,将临时路径传给回调
QRCode.prototype.exportImage = function (callback) {
if (this._htOption.callback && typeof this._htOption.callback === 'function') {
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: this._htOption.width,
height: this._htOption.height,
destWidth: this._htOption.width,
destHeight: this._htOption.height,
canvasId: this.canvasId,
success: (res) => {
this._htOption.callback({path: res.tempFilePath})
}
})
}
}
QRCode.CorrectLevel = QRErrorCorrectLevel;
})();
module.exports = QRCode

214
subPackages/eventCalendar/detail.vue

@ -0,0 +1,214 @@
<template>
<view class="bg">
<view class="swipe-box" v-if="info.images">
<swiper class="swiper" :autoplay="true" :interval="3000" :duration="1000" circular indicator-dots indicator-color="rgba(255,255,255,.5)"
indicator-active-color="#fff" @change="swiperChange">
<swiper-item v-for="(item, index) in info.images.split(',')" :key="item.id">
<view class="swiper-item">
<image class="item-img" :src="showImg(item)" mode="aspectFill"></image>
</view>
</swiper-item>
</swiper>
<view class="swiper-pointer">
{{swiperCurrent}}/{{info.images.split(',').length}}
</view>
<view class="collect" style="right: 100rpx;" @click.stop="collect()">
<image src="https://tongli.sz-trip.com/uploads/20240829/9dbb80cafe8375bd6d5c96fccb617962.png" v-if="info.is_collect"></image>
<image src="https://tongli.sz-trip.com/uploads/20240826/564af778708591f5de29174d3b14bbff.png" v-else></image>
</view>
<view class="collect" @click.stop="share()">
<image src="https://tongli.sz-trip.com/uploads/20240902/8eb614e4ea41db655a4e6da2cc0ca954.png"></image>
</view>
</view>
<view class="common-container info-container">
<view class="info-title text-overflowRows">{{info.title}}</view>
<view class="text-overflow" style="padding: 40rpx 0 16rpx;">{{info.address}}</view>
<view class="text-overflow" v-if="info.start_time && info.end_time">时间{{info.start_time}} - {{info.end_time}}</view>
</view>
<view class="common-container detail-container">
<view class="" id="cpts" v-html="formateRichText(info.detail)"></view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
id: null,
swiperCurrent: 1,
info: {},
}
},
onShow(options) {
},
onLoad(options) {
this.id = options.id;
this.getInfo();
},
methods: {
swiperChange (e) {
this.swiperCurrent = e.detail.current+1
},
//
getInfo() {
this.Post({id: this.id},'/api/activity/getActivityCalendarDetail').then(res => {
if (res.data.flag == 0) {
uni.showToast({title: '商品不存在或已下架',icon: 'none'})
setTimeout(() => {this.goBack()}, 2000)
}
this.info = res.data;
});
},
//
collect() {
this.Post({type: 7,id: this.id},'/api/scenic/collect').then(res => {
if (res) {
uni.showToast({title: res.msg,icon: 'none'});
this.info.is_collect = !this.info.is_collect
}
});
},
share () {
var pages = getCurrentPages() //
var view = pages[pages.length - 1] //
uni.share({
provider: "weixin",
scene: "WXSceneSession",
type: 0,
href: `${view.route}`,
title: this.info.title,
imageUrl: this.showImg(this.info.image),
success: function (res) {
console.log("success:" + JSON.stringify(res));
},
fail: function (err) {
console.log("fail:" + JSON.stringify(err));
}
});
}
}
}
</script>
<style scoped lang="scss">
*{
box-sizing: border-box;
}
.bg{
min-height: 100vh;
background: #F8F8F8;
}
.swipe-box {
height: 867rpx;
position: relative;
.swiper-item-num {
width: 90rpx;
height: 40rpx;
background: rgba(0, 0, 0, 0.5);
border-radius: 20rpx;
font-size: 24rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ffffff;
text-align: center;
line-height: 40rpx;
position: absolute;
right: 30rpx;
bottom: 50rpx;
}
.collect{
position: absolute;
width: 51rpx;
height: 51rpx;
right: 20rpx;
top: 20rpx;
font-size: 23rpx;
background: rgba(0, 0, 0, 0.5);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
image{
width: 36rpx;
height: 36rpx;
}
}
.swiper-pointer{
position: absolute;
right: 20rpx;
bottom: 20rpx;
background: rgba(22,22,22,0.5);
border-radius: 23rpx;
font-family: PingFang SC;
font-weight: 500;
font-size: 24rpx;
color: #FFFFFF;
padding: 6rpx 14rpx;
}
}
.swiper {
height: 867rpx;
position: relative;
.swiper-item {
width: 100%;
height: 867rpx;
.item-img {
width: 750rpx;
height: 867rpx;
}
.item-img.pop-swiper-image{
height: 347rpx;
border-radius: 13rpx;
}
}
}
.common-container{
background: white;
width: 100%;
}
.info-container{
padding: 34rpx 25rpx;
width: 100%;
margin-bottom: 21rpx;
font-family: PingFang SC;
font-weight: 500;
font-size: 25rpx;
color: #666666;
.info-title{
font-weight: bold;
font-size: 35rpx;
color: #000000;
}
}
.detail-container{
width: 100%;
padding: 28rpx;
font-family: PingFang SC;
font-weight: 500;
font-size: 28rpx;
color: #333333;
}
</style>

7
subPackages/eventCalendar/eventCalendar.vue

@ -52,7 +52,7 @@
</view> </view>
</view> </view>
<view class="item" v-for="(item,index) in list" :key="index"> <view class="item" v-for="(item,index) in list" :key="index" @click="viewDetail(item)">
<image :src="showImg(item.image)" mode="aspectFill" class="item-img"></image> <image :src="showImg(item.image)" mode="aspectFill" class="item-img"></image>
<view class="content flex-column"> <view class="content flex-column">
<view class="title text-overflowRows">{{item.title}}</view> <view class="title text-overflowRows">{{item.title}}</view>
@ -356,6 +356,11 @@
this.getList() this.getList()
} }
}, },
viewDetail (item) {
uni.navigateTo({
url:'/subPackages/eventCalendar/detail?id='+item.id
})
},
} }
} }
</script> </script>

2
subPackages/food/foodDetail.vue

@ -65,7 +65,7 @@
</view> </view>
<image class="right" :src="showImg('/uploads/20240827/0e777c1006a15612a0d449178472fd13.png')" mode=""></image> <image class="right" :src="showImg('/uploads/20240827/0e777c1006a15612a0d449178472fd13.png')" mode=""></image>
</view> </view>
<view class="price">{{skuItem.price/100}}</view> <view class="price">{{skuItem.money/100}}</view>
</view> </view>
<view class="content-bottom flex-between"> <view class="content-bottom flex-between">
<view class="tags"> <view class="tags">

769
subPackages/hotelHomestay/detail.vue

@ -0,0 +1,769 @@
<template>
<view class="bg">
<view class="swipe-box">
<swiper class="swiper" :autoplay="true" :interval="3000" :duration="1000" circular indicator-dots indicator-color="rgba(255,255,255,.5)"
indicator-active-color="#fff" @change="swiperChange">
<swiper-item v-for="(item, index) in info.list_images.split(',')" :key="item.id">
<view class="swiper-item">
<image class="item-img" :src="showImg(item)" mode="aspectFill"></image>
</view>
</swiper-item>
</swiper>
<view class="swiper-pointer">
{{swiperCurrent}}/{{info.list_images.split(',').length}}
</view>
<view class="collect" @click.stop="collect()">
<image src="https://tongli.sz-trip.com/uploads/20240829/9dbb80cafe8375bd6d5c96fccb617962.png" v-if="info.is_collect"></image>
<image src="https://tongli.sz-trip.com/uploads/20240826/564af778708591f5de29174d3b14bbff.png" v-else></image>
</view>
</view>
<view class="detail-container">
<view class="common-container info-container">
<view>
<view class="info-title text-overflowRows">{{info.title}}</view>
</view>
<view class="flex-between time-container">
<view class="flex-1 w-1rpx">
<view class="tag-container no-scrollbar" v-if="info.label">
<view class="tag" v-for="(tag,tagIndex) in info.label.split(',')" :key="tagIndex">{{tag}}</view>
</view>
</view>
<view class="policy-btn flex-shrink-0 flex flex-items-center" style="justify-content: flex-end;" @click="goPolicy">
设施/政策
<uni-icons color="#71B580" style="height: 35rpx;" type="right" size="12"></uni-icons>
</view>
</view>
<view class="flex-between">
<view class="address-container flex flex-shrink-0 flex-between" @click="goMap">
<view class="address-title text-overflowRows">
{{info.address}}
</view>
<view class="flex-column flex-center">
<image :src="showImg('/uploads/20240827/5b19517f2a630f3a766ea03ac621a3be.png')">
<view class="tip" style="padding-top: 11rpx;">地图</view>
</view>
</view>
<view class="phone-container flex-column flex-center" @click="callPhone">
<image :src="showImg('/uploads/20240829/b38a84c91eef12d3040deaef50eaf697.png')">
<view class="tip" style="padding-top: 11rpx;">电话</view>
</view>
</view>
</view>
<view class="common-container hotel-container" style="padding: 0;background: none;">
<view class="order-time flex-between" style="justify-content: space-around;"
@click="openCalendar()">
<view class="time">
<view style="font-size: 35rpx;font-weight: bold;">{{new Date(selectDate.startDay).Format('MM-dd')}}</view>
<view style="padding:0 14rpx">{{ ShowDateDay(new Date(selectDate.startDay).getDay()) }}</view>
<view style="color: #71B580;">入住</view>
</view>
<view class="cal-day">
{{selectDate.differDays}}
</view>
<view class="time">
<view style="font-size: 35rpx;font-weight: bold;">{{new Date(selectDate.endDay).Format('MM-dd')}}</view>
<view style="padding:0 14rpx">{{ShowDateDay(new Date(selectDate.endDay).getDay()) }}</view>
<view style="color: #71B580;">离店</view>
</view>
</view>
<view style="padding:0 34rpx;">
<view v-for="(item, index) in sku" :key="index">
<view class="scenic-item flex" v-if="(!showMore&&index<=2)||showMore">
<view class="scenic-image flex-shrink-0">
<image style="width: 100%;height: 100%;" :src="showImg(item.image)"></image>
</view>
<view class="flex-1 w-1rpx flex-column" style="padding: 14rpx;justify-content: space-between;">
<view class="flex flex-items-center" @click="viewDetail(item)">
<view class="scenic-title text-overflow">{{item.title}}</view>
<uni-icons style="height: 40rpx;font-weight: bold;" type="right" size="15"></uni-icons>
</view>
<view>
<view class="scenic-content text-overflowRows">
<text>{{item.showTag}}</text>
<text>{{item.lastShowTag}}</text>
</view>
</view>
<view class="price-container">
<view class="price">{{item.price/100}}</view>
<view class="btn" @click="goOrder(item)">预订</view>
</view>
</view>
</view>
</view>
<view class="showMore" v-if="!showMore&&sku.length>3" @click="changeShowMore">
查看剩余房型
</view>
</view>
</view>
<view style="padding: 0rpx 29rpx;">
<view class="box-title">酒店介绍</view>
<view class="common-container" style="padding: 30rpx 40rpx;">
<view class="" id="cpts" v-html="formateRichText(info.feature_content)"></view>
</view>
<view class="box-title">设施与政策</view>
<view class="common-container policy-container" style="padding: 30rpx 40rpx;">
<view class="common-container1">
<view class="info-title1 box-title1 text-overflowRows">{{info.title}}</view>
<view class="flex-between phone-container1">
<view>
联系电话{{info.tel}}
</view>
<view @click="callPhone">
<image :src="showImg('/uploads/20240830/8b5750ff23837fe4a187e13775f9424c.png')">
</view>
</view>
</view>
<view class="common-container1">
<view class="box-title1">服务设施</view>
<view style="padding-top: 34rpx;" v-html="formateRichText(info.cost_content)"></view>
</view>
<view class="common-container1">
<view class="box-title1">入住须知</view>
<view style="padding-top: 34rpx;" v-html="formateRichText(info.describe_content)"></view>
</view>
</view>
</view>
</view>
<!-- 酒店详情弹窗 -->
<uni-popup ref="popupRule" type="bottom" :safe-area="false" background-color="#F7F7F7">
<view class="popup-content-date" >
<view class="popup-content-title flex">
<view class="flex-1 w-1rpx text-overflow">
{{skuInfo.title}}
</view>
<img src="https://static.ticket.sz-trip.com/taizhou/images/cha.png" @click="closePopupRule"
style="width: 31rpx;height: 31rpx;" class="flex-shrink-0">
</view>
<view class="content">
<view class="swipe-box" style="height: 347rpx;" v-if="skuInfo.list_images">
<swiper class="swiper" :autoplay="true" :interval="3000" :duration="1000" circular indicator-dots indicator-color="rgba(255,255,255,.5)"
indicator-active-color="#fff" @change="popSwiperChange" :current="0">
<swiper-item v-for="(item, index) in skuInfo.list_images.split(',')" :key="item.id">
<view class="swiper-item" style="height: 347rpx;">
<image class="item-img pop-swiper-image" :src="showImg(item)" mode="aspectFill"></image>
</view>
</swiper-item>
</swiper>
<view class="swiper-pointer" style="right:30rpx;bottom: 20rpx;">
{{popSwiperCurrent}}/{{skuInfo.list_images.split(',').length}}
</view>
</view>
<view class="pop-detail-container">
<view class="pop-detail-title">房型信息</view>
<view v-html="formateRichText(skuInfo.use_explain)"></view>
</view>
</view>
</view>
</uni-popup>
<uni-calendar ref="calendar" class="uni-calendar--hook" :clear-date="false"
:insert="false" :range="true" :startDate="calendarParam.startDate"
:endDate="calendarParam.endDate" @confirm="confirmCalendar"/>
</view>
</template>
<script>
export default {
data() {
return {
headImg: "https://tongli.sz-trip.com/uploads/20240826/8653c32761e01ee683505eddba1ae22b.png",
id: null,
swiperCurrent: 1,
popSwiperCurrent: 1,
info: {list_images:''},
sku: [],
showMore: false,
skuInfo: {}, //
selectDate: {
startDay:new Date().Format('yyyy-MM-dd'),
endDay:new Date((new Date()).getFullYear(), (new Date()).getMonth(), new Date().getDate()+1).Format('yyyy-MM-dd'),
differDays: 1
},
minSeldDate: new Date().Format('yyyy-MM-dd'),
maxSeldDate: new Date((new Date()).getFullYear(), (new Date()).getMonth() + 3, 0).Format('yyyy-MM-dd'),
calendarParam: {
stratDate:'',endDate: '', selected: []
},
}
},
onShow(options) {
},
onLoad(options) {
this.id = options.id;
this.getInfo();
this.getGoodsList()
},
methods: {
swiperChange (e) {
this.swiperCurrent = e.detail.current+1
},
popSwiperChange (e) {
this.popSwiperCurrent = e.detail.current+1
},
changeShowMore () {
this.showMore = !this.showMore
},
goPolicy () {
uni.navigateTo({
url:`/subPackages/hotelHomestay/policy?id=${this.id}`
})
},
callPhone () {
let _this = this
uni.showActionSheet({
itemList: [this.info.tel,'呼叫'],
success: function (res) {
_this.clickPhone(_this.info.tel)
}
});
// this.clickPhone(this.info.tel)
},
goMap () {
uni.openLocation({
latitude: Number(this.info.lat),
longitude: Number(this.info.lon),
name: this.info.title,
address: this.info.address,
success: function () {
console.log('success');
}
});
},
//
getInfo() {
this.Post({id: this.id},'/api/scenic/getScenicById').then(res => {
if (res.data.flag == 0) {
uni.showToast({title: '商品不存在或已下架',icon: 'none'})
setTimeout(() => {this.goBack()}, 2000)
}
let info = res.data;
try {
info.times_list_info = JSON.parse(info.times_list)[0]
} catch(e) {
console.log(e)
info.times_list_info = {start:'',end:''}
}
this.info = info
console.log(info)
});
},
// id
getGoodsList(){
this.Post({
scenic_id: this.id
},'/api/scenic/getGoodsByScenicId').then(res => {
let result = res.data || []
let data = []
result.forEach(item=>{
item.specifications.forEach(v=>{
let showTag = ''
let lastShowTag = ''
if (v.specifications_new_tag) {
let tags = v.specifications_new_tag.split(',')
showTag = (tags.slice(0,-1)||[]).join(' | ')
if (tags.length>1) {
showTag += ' | '
}
lastShowTag = tags[tags.length-1]||''
}
v.showTag = showTag
v.lastShowTag = lastShowTag
data.push(v)
})
})
this.sku = data
// this.sku = [...data,...data,...data,...data]
})
},
//
collect() {
this.Post({type: 4,id: this.id},'/api/scenic/collect').then(res => {
if (res) {
uni.showToast({title: res.msg,icon: 'none'});
this.info.is_collect = !this.info.is_collect
}
});
},
calDate (startDate, endDate) {
var start = new Date(startDate);
var end = new Date(endDate);
var diff = end - start;
var days = Math.floor(diff / (1000 * 60 * 60 * 24)); //
return days;
},
openCalendar () {
this.calendarParam = {
startDate: this.minSeldDate,
endDate: this.maxSeldDate,
// selected: this.allSeldDate.filter(v=>v.store>0).map(v=>{
// return {
// date: v.date,
// info: ''+this.showNoPriceNew(v.money),
// notNeedDot:true,
// }
// })
}
this.$refs.calendar.open();
},
confirmCalendar (val) {
if (val.range.data.length<2) {
uni.showToast({
title:'请选择日期',
icon:'none'
})
return
}
this.selectDate.startDay = val.range.before
this.selectDate.endDay = val.range.after
this.selectDate.differDays = this.calDate(this.selectDate.startDay,this.selectDate.endDay)
},
//
viewDetail (item) {
this.skuInfo = item
this.popSwiperCurrent = 1
this.openPopRule()
},
//
goOrder (item) {
// if (item.xx) {
// return
// }
let param = {
skuInfo: item,
selectDate: this.selectDate
}
uni.setStorageSync('hotelOrderInfo', JSON.stringify(param))
uni.navigateTo({
url:`/subPackages/hotelHomestay/order`
})
},
closePopupRule() {
this.$refs.popupRule.close()
},
openPopRule(){
this.$refs.popupRule.open()
},
//
showNoPriceNew(price) {
if (price && price > 0) {
return (price / 100)
} else {
return '0'
}
},
}
}
</script>
<style scoped lang="scss">
*{
box-sizing: border-box;
}
.bg{
min-height: 100vh;
background: #F8F8F8;
}
.swipe-box {
height: 484rpx;
position: relative;
.swiper-item-num {
width: 90rpx;
height: 40rpx;
background: rgba(0, 0, 0, 0.5);
border-radius: 20rpx;
font-size: 24rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ffffff;
text-align: center;
line-height: 40rpx;
position: absolute;
right: 30rpx;
bottom: 50rpx;
}
.collect{
position: absolute;
width: 51rpx;
height: 51rpx;
right: 36rpx;
top: 36rpx;
font-size: 23rpx;
background: rgba(0, 0, 0, 0.5);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
image{
width: 36rpx;
height: 36rpx;
}
}
.swiper-pointer{
position: absolute;
right: 36rpx;
bottom: 80rpx;
background: rgba(22,22,22,0.5);
border-radius: 23rpx;
font-family: PingFang SC;
font-weight: 500;
font-size: 24rpx;
color: #FFFFFF;
padding: 6rpx 14rpx;
}
}
.swiper {
height: 484rpx;
position: relative;
.swiper-item {
width: 100%;
height: 484rpx;
.item-img {
width: 750rpx;
height: 484rpx;
}
.item-img.pop-swiper-image{
height: 347rpx;
border-radius: 13rpx;
}
}
}
.detail-container{
width: 100%;
z-index: 2;
position: relative;
top: -52rpx;
}
.common-container{
background: white;
border-radius: 20rpx;
margin-bottom: 20rpx;
padding: 22rpx 26rpx;
}
.info-container{
font-family: PingFang;
font-weight: 500;
font-size: 27rpx;
color: #000000;
padding: 36rpx 29rpx;
.time-container{
padding: 22rpx 0;
.tag-container{
display: flex;
flex-wrap: nowrap;
overflow-x: auto;
.tag{
border-radius: 5rpx;
border: 1px solid #71B580;
padding: 7rpx 14rpx;
font-family: PingFang SC;
font-weight: 500;
font-size: 25rpx;
color: #71B580;
text-align: center;
margin-right: 15rpx;
flex-shrink: 0;
}
}
.policy-btn{
width: 160rpx;
height: 35rpx;
font-family: PingFang SC;
font-weight: 500;
font-size: 27rpx;
text-align: right;
color: #71B580;
}
}
.info-title{
width: 100%;
height: 85rpx;
font-family: PingFang SC;
font-weight: bold;
font-size: 35rpx;
color: #000000;
}
.address-container{
width: 587rpx;
height: 107rpx;
border-radius: 20rpx;
padding: 25rpx 20rpx 25rpx 33rpx;
font-family: PingFang SC;
font-weight: 500;
font-size: 27rpx;
color: #000000;
background-color: #E8F6EB;
background-image: url('https://tongli.sz-trip.com/uploads/20240830/e8089886a03786e925bd4d4bbc441320.png');
background-repeat: no-repeat;
background-size: 100% 100%;
image{
width: 30rpx;
height: 30rpx;
}
.tip{
font-family: PingFang SC;
font-weight: 500;
font-size: 24rpx;
color: #333333;
}
}
.phone-container{
width: 93rpx;
height: 107rpx;
background: #E8F6EB;
border-radius: 20rpx;
font-family: PingFang SC;
font-weight: 500;
font-size: 24rpx;
color: #333333;
image{
width: 30rpx;
height: 30rpx;
}
.tip{
font-family: PingFang SC;
font-weight: 500;
font-size: 24rpx;
color: #333333;
}
}
}
.hotel-container{
.order-time{
height: 107rpx;
background: linear-gradient(180deg, #FFFFFF, #F7F7F7);
.time{
display: flex;
font-family: PingFang SC;
font-size: 24rpx;
color: #000000;
align-items: center;
}
}
.cal-day{
background: #E8F6EB;
border-radius: 17rpx;
padding: 5rpx 16rpx;
font-family: PingFang SC;
font-weight: 500;
font-size: 24rpx;
color: #000000;
}
.showMore{
width: 100%;
height: 67rpx;
background: #FFFFFF;
border-radius: 20rpx;
font-family: PingFang SC;
font-weight: 500;
font-size: 27rpx;
color: #666666;
line-height: 67rpx;
text-align: center;
}
}
.box-title {
margin: 52rpx 0 26rpx 12rpx;
font-family: PingFang;
font-weight: bold;
font-size: 37rpx;
color: #000000;
}
.address-icon{
margin-right: 9rpx;
width: 26rpx;
height: 26rpx;
}
.scenic-item{
display: flex;
width: 100%;
height: 213rpx;
background: #FFFFFF;
border-radius: 20rpx;
padding: 7rpx;
margin-bottom: 20rpx;
.scenic-image{
width: 173rpx;
height: 100%;
flex-shrink: 0;
image{
border-radius: 20rpx;
}
}
.scenic-title {
font-family: PingFang SC;
font-weight: bold;
font-size: 31rpx;
color: #000000;
flex-shrink: 0;
max-width: 90%;
}
.scenic-content{
width: 100%;
height: 66rpx;
font-family: PingFang SC;
font-weight: 500;
font-size: 24rpx;
color: #666666;
line-height: 33rpx;
text:last-of-type{
color: #71B580;
}
}
.price-container{
width: 100%;
display: flex;
align-items: center;
justify-content: flex-end;
.price{
font-family: PingFang SC;
font-weight: bold;
font-size: 37rpx;
color: #D60000;
padding-right: 20rpx;
}
.price::before{
content: "¥";
font-size: 24rpx;
}
.btn{
width: 120rpx;
height: 47rpx;
background: linear-gradient(90deg, #FD6F34, #F4A61F);
border-radius: 23rpx;
font-family: PingFang SC;
font-weight: bold;
font-size: 29rpx;
color: #FFFFFF;
display: flex;
align-items: center;
justify-content: center;
}
}
}
.bottom {
.notice {
font-weight: 400;
color: #0B898E;
}
}
.popup-content-date{
position: relative;
background: #F7F7F7;
top: -33rpx;
padding: 25rpx 44rpx;
border-radius: 33rpx;
.popup-content-title{
font-family: PingFang SC;
font-weight: 500;
font-size: 35rpx;
color: #000000;
text-align: center;
padding-bottom: 26rpx;
}
.pop-detail-container{
background: #FFFFFF;
border-radius: 13rpx;
padding: 20rpx;
margin-top: 26rpx;
max-height: 800rpx;
overflow-y: auto;
.pop-detail-title{
font-family: PingFang SC;
font-weight: 500;
font-size: 32rpx;
color: #000000;
}
}
}
.policy-container{
.common-container1{
width: 100%;
background: white;
border-radius: 13rpx;
margin-bottom: 20rpx;
padding: 20rpx 18rpx;
}
.box-title1 {
font-family: PingFang SC;
font-weight: bold;
font-size: 35rpx;
color: #000000;
}
.info-title1{
height: 88rpx;
}
.phone-container1{
padding-top: 20rpx;
font-family: PingFang SC;
font-weight: 400;
font-size: 28rpx;
color: #000000;
image{
width: 33.33rpx;
height: 33.33rpx;
}
}
}
</style>

53
subPackages/hotelHomestay/hotelHomestay.vue

@ -9,11 +9,11 @@
<view class="goodBox"> <view class="goodBox">
<navigator :url="'/subPackages/ticketBooking/detail?id='+item.id" class="goodItem flex-column" v-for="(item,index) in list" :key="index"> <navigator :url="'/subPackages/hotelHomestay/detail?id='+item.id" class="goodItem flex-column" v-for="(item,index) in list" :key="index">
<view class="left-image flex-shrink-0 relative"> <view class="left-image flex-shrink-0 relative">
<image class="left-image " :src="showImg(item.image)" mode="aspectFill"></image> <image class="left-image " :src="showImg(item.image)" mode="aspectFill"></image>
<view class="collect" @click="like(item)"> <view class="collect" @click.stop="like(item)">
<image src="https://tongli.sz-trip.com/uploads/20240826/81b1f86ff8534db09472853b4c0b6748.png" v-if="item.is_collect"></image> <image src="https://tongli.sz-trip.com/uploads/20240829/9dbb80cafe8375bd6d5c96fccb617962.png" v-if="item.is_collect"></image>
<image src="https://tongli.sz-trip.com/uploads/20240826/564af778708591f5de29174d3b14bbff.png" v-else></image> <image src="https://tongli.sz-trip.com/uploads/20240826/564af778708591f5de29174d3b14bbff.png" v-else></image>
</view> </view>
@ -22,24 +22,25 @@
<view class="contentBox flex-column flex-1 h-1rpx"> <view class="contentBox flex-column flex-1 h-1rpx">
<view class="title text-overflow">{{item.title}}</view> <view class="title text-overflow">{{item.title}}</view>
<view class="flex-between"> <view class="flex-between">
<view class="tag-container"> <view class="flex-1 w-1rpx">
<view class="tag">盐都精选</view> <view class="tag-container no-scrollbar" v-if="item.label">
<view class="tag">盐都精选</view> <view class="tag" v-for="(tag,tagIndex) in item.label.split(',')" :key="tagIndex">{{tag}}</view>
</view> </view>
<view class="priceBox">
<view class="price">{{showPrice(item.price)}}</view>
</view> </view>
</view> </view>
<view class="flex-between"> <view class="flex-between">
<view class="distance">距您约602m</view> <view class="distance">距您约602m</view>
<view class="order-btn">立即预定</view> <view class="priceBox flex-shrink-0">
<view class="price">{{showPrice(item.price)}}</view>
</view>
</view> </view>
</view> </view>
</navigator> </navigator>
</view> </view>
<view class="finished-text" v-if="finished">没有更多数据了</view> <!-- <view class="finished-text" v-if="finished">没有更多数据了</view> -->
</view> </view>
</template> </template>
@ -59,20 +60,17 @@
headImg:null, headImg:null,
navList: [], navList: [],
actNavIndex: 0, actNavIndex: 0,
type_id: 9,//id type_id: 11,//id
} }
}, },
onShow() { onShow() {
this.headImg = 'https://tongli.sz-trip.com/uploads/20240826/8653c32761e01ee683505eddba1ae22b.png' this.headImg = 'https://tongli.sz-trip.com/uploads/20240826/8653c32761e01ee683505eddba1ae22b.png'
this.finished = false this.finished = false
this.list = [
{id:1, title:'景点名称景点名称景点名称 景点名称',
address:'景点名称景点名称景点名称 景点名称景点名称景点名称景点名称 景点名称',price:10000,
image:'https://tongli.sz-trip.com/uploads/20240826/a87488f6225789aa19dbb437671d388d.png',
}
]
// this.getHeadImg('piaowu') // this.getHeadImg('piaowu')
}, },
onReady() {
this.getList()
},
onLoad(options) { onLoad(options) {
let that = this let that = this
uni.getSystemInfo({ uni.getSystemInfo({
@ -107,10 +105,11 @@
// //
getList(){ getList(){
this.Post({ this.Post({
tag_id: this.navList[this.actNavIndex].id, scenic_type_id: this.type_id,offset: this.list.length,limit: 10,
offset: this.list.length, lon: uni.getStorageSync('location').lon || '120',
limit: 10 lat: uni.getStorageSync('location').lat || '30',
},'https://yjdtadmin.sz-trip.com/api/scenic/getScenicByTagId').then(res => { },
'/api/Scenic/getScenicByType').then(res => {
this.list = [...this.list, ...res.data]; this.list = [...this.list, ...res.data];
if (res.data.length < 10) { if (res.data.length < 10) {
this.finished = true this.finished = true
@ -123,9 +122,9 @@
this.Post({ this.Post({
type: 4, type: 4,
id: item.id id: item.id
}, 'https://yjdtadmin.sz-trip.com/api/scenic/collect').then(res => { }, '/api/scenic/collect').then(res => {
if (res.code == 200) { if (res.code == 1) {
uni.showToast({title: res.msg}) uni.showToast({title: res.msg,icon:'none'})
if (item.is_collect == 1) { if (item.is_collect == 1) {
item.is_collect = 0 item.is_collect = 0
} else { } else {
@ -213,6 +212,8 @@
.tag-container{ .tag-container{
display: flex; display: flex;
flex-wrap: nowrap;
overflow-x: auto;
.tag{ .tag{
background: rgba(205,233,209,0.3); background: rgba(205,233,209,0.3);
border-radius: 7rpx 5rpx 5rpx 7rpx; border-radius: 7rpx 5rpx 5rpx 7rpx;
@ -221,14 +222,16 @@
padding: 4rpx 14rpx; padding: 4rpx 14rpx;
font-weight: 500; font-weight: 500;
font-size: 25rpx; font-size: 25rpx;
color: #4E7956; color: #5BA06A;
text-align: center; text-align: center;
margin-right: 12rpx; margin-right: 12rpx;
flex-shrink: 0;
} }
} }
.priceBox{ .priceBox{
width: 120rpx;
.price{ .price{
font-family: PingFang SC; font-family: PingFang SC;
font-weight: bold; font-weight: bold;

601
subPackages/hotelHomestay/order.vue

@ -0,0 +1,601 @@
<template>
<view class="bg">
<view class="detail-container">
<view class="common-container info-container">
<view class="flex-between" style="align-items: flex-start;">
<view class="info-title text-overflowRows">{{skuInfo.title}}</view>
<view class="policy-btn flex-shrink-0 flex flex-items-center" @click="openPopRule">
房型信息
<uni-icons color="#71B580" style="height: 32rpx;" type="right" size="12"></uni-icons>
</view>
</view>
<view class="tag-container text-overflow">
<text>{{skuInfo.showTag}}</text>
<text>{{skuInfo.lastShowTag}}</text>
</view>
<view class="order-time flex-between" style="justify-content: space-around;">
<view class="time">
<view style="font-size: 35rpx;font-weight: bold;">{{new Date(selectDate.startDay).Format('MM-dd')}}</view>
<view style="padding-left:14rpx">{{ ShowDateDay(new Date(selectDate.startDay).getDay()) }}</view>
<view>入住</view>
</view>
<view class="cal-day">
{{selectDate.differDays}}
</view>
<view class="time">
<view style="font-size: 35rpx;font-weight: bold;">{{new Date(selectDate.endDay).Format('MM-dd')}}</view>
<view style="padding-left:14rpx">{{ShowDateDay(new Date(selectDate.endDay).getDay()) }}</view>
<view>离店</view>
</view>
</view>
<view class="notice-container">
<view class="flex">
<view class="flex-shrink-0" style="padding-top: 4rpx;">
<image :src="showImg('/uploads/20240830/aa84c8b1de80651f645fed67a1997ced.png')"></image>
</view>
<view class="flex-1 w-1rpx" style="padding-left: 14rpx;">
<view>订单确认后您在{{new Date(selectDate.startDay).Format('yyyy年MM月dd日')}}20:00前之免费取消或 变更订单20:00后将收取30%房费作为违约费用</view>
<view style="color: #F84A56;">预期不可取消或/修改扣取全额房费</view>
</view>
</view>
<view class="flex" style="padding-top: 22rpx;">
<view class="flex-shrink-0" style="padding-top: 4rpx;">
<image :src="showImg('/uploads/20240830/59d2f01f0391f72a537cc9004bc2071d.png')"></image>
</view>
<view class="flex-1 w-1rpx" style="padding-left: 14rpx;">
<view>证件要求大陆居民身份证登记入住</view>
</view>
</view>
</view>
</view>
<view class="common-container form-container">
<view class="form-title">
<text style="font-weight: bold;font-size: 35rpx;padding-right: 28rpx;">预订信息</text>
<text>姓名需与证件一致</text>
</view>
<view class="btn-box flex-column">
<view class="line w-full" style="border-top: none;">
<view class="left">房间数</view>
<view class="input flex" style="justify-content: flex-end;">
<view class="num-box">
<view :class="['ctrl',buyNum>1?'':'disabled']" @click="reduce()">-</view>
<input class="num" type="text" v-model="buyNum" :disabled='true' />
<view :class="['ctrl']" @click="plus()">+</view>
</view>
</view>
</view>
<view class="line w-full" v-for="(user,index) in roomUser" :key="index">
<view class="left">房间{{index+1}}</view>
<input class="input" type="text" placeholder="请输入住客姓名" v-model="user.name" />
</view>
<view class="line w-full">
<view class="left">联系电话</view>
<view class="flex flex-items-center input">
<input class="input" type="text" placeholder="请输入联系手机号" v-model="phone" />
<uni-icons v-if="phone.length>0" style="margin-left: 30rpx;"
type="closeempty" size="14" @click="phone = ''"></uni-icons>
</view>
</view>
</view>
</view>
</view>
<view class="btn-list">
<view class="price-box">
<view class="text">合计:</view>
<view class="price">{{ total() }}</view>
<!-- <view class="post-text" v-if="sendType==1&&post">含邮费:¥{{ post / 100 }}</view> -->
</view>
<view class="btn" @click="order()">立即预订</view>
</view>
<!-- 酒店详情弹窗 -->
<uni-popup ref="popupRule" type="bottom" :safe-area="false" background-color="#F7F7F7">
<view class="popup-content-date" >
<view class="popup-content-title flex">
<view class="flex-1 w-1rpx text-overflow">
{{skuInfo.title}}
</view>
<img src="https://static.ticket.sz-trip.com/taizhou/images/cha.png" @click="closePopupRule"
style="width: 31rpx;height: 31rpx;" class="flex-shrink-0">
</view>
<view class="content">
<view class="swipe-box" style="height: 347rpx;" v-if="skuInfo.list_images">
<swiper class="swiper" :autoplay="true" :interval="3000" :duration="1000" circular indicator-dots indicator-color="rgba(255,255,255,.5)"
indicator-active-color="#fff" @change="popSwiperChange" :current="0">
<swiper-item v-for="(item, index) in skuInfo.list_images.split(',')" :key="item.id">
<view class="swiper-item" style="height: 347rpx;">
<image class="item-img pop-swiper-image" :src="showImg(item)" mode="aspectFill"></image>
</view>
</swiper-item>
</swiper>
<view class="swiper-pointer" style="right:30rpx;bottom: 20rpx;">
{{popSwiperCurrent}}/{{skuInfo.list_images.split(',').length}}
</view>
</view>
<view class="pop-detail-container">
<view class="pop-detail-title">房型信息</view>
<view v-html="formateRichText(skuInfo.use_explain)"></view>
</view>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
export default {
data() {
return {
id: null,
popSwiperCurrent: 1,
skuInfo: {}, //
selectDate: {
startDay:new Date().Format('yyyy-MM-dd'),
endDay:new Date((new Date()).getFullYear(), (new Date()).getMonth(), new Date().getDate()+1).Format('yyyy-MM-dd'),
differDays: 1
},
phone: '',
buyNum: 1,
roomUser: [{
name: ''
}]
}
},
onShow(options) {
},
onLoad(options) {
this.initOrderDate()
},
methods: {
popSwiperChange (e) {
this.popSwiperCurrent = e.detail.current+1
},
//
initOrderDate () {
let data = {}
try {
data = JSON.parse(uni.getStorageSync('hotelOrderInfo'));
} catch (e) {
data = {}
setTimeout(()=>{
uni.navigateBack()
},1000)
}
this.skuInfo = data.skuInfo
this.selectDate = data.selectDate
this.buyNum = 1
this.roomUser = [{name: ''}]
},
//
viewDetail () {
this.popSwiperCurrent = 1
this.openPopRule()
},
plus() {
this.buyNum += 1;
this.roomUser.push({name: ''})
},
reduce() {
if (this.buyNum > 1) {
this.buyNum -= 1;
this.roomUser.pop()
}
},
total () {
return this.skuInfo.price/100 * this.buyNum || 0
},
order () {
//
if (!this.isTel(this.phone)){
uni.showToast({
title: '请输入自提人手机号',
icon: 'none'
});
return;
}
if (this.roomUser.some(v=>v.trim().length<0)) {
uni.showToast({
title: '请输入住客姓名',
icon: 'none'
});
return;
}
let goods = []
let goodsItem = {
num:this.buyNum,
specifications_id: this.skuInfo.id,
start_date: this.selectDate.startDay,
end_date: this.selectDate.endDay,
customer_name: this.roomUser.map(v=>v.name).join('、'),
reserve_mobile: this.phone,
}
goods.push(goodsItem)
let data = {
goods: goods,
reserve_phone: this.phone,
}
return
this.Post({
method: 'POST',
data: JSON.stringify(data)
},'/api/order/place').then(res => {
console.log('成功');
if(res.code == 200){
uni.removeStorageSync('hotelOrderInfo')
this.Post({
order_id: res.data.order_id,
type: "miniprogram",
platform: 'miniprogram'
},'/api/pay/unify').then(res => {
if(res.data){
uni.requestPayment({
nonceStr: res.data.nonceStr,
package: res.data.package,
paySign: res.data.paySign,
signType: res.data.signType,
timeStamp: res.data.timeStamp,
complete() {
uni.navigateTo({
url: '/subPackages/order/trades'
})
}
})
}
})
}
})
},
closePopupRule() {
this.$refs.popupRule.close()
},
openPopRule(){
this.$refs.popupRule.open()
},
}
}
</script>
<style scoped lang="scss">
*{
box-sizing: border-box;
}
.bg{
min-height: 100vh;
background: #F8F8F8;
}
.swipe-box {
height: 484rpx;
position: relative;
.swiper-item-num {
width: 90rpx;
height: 40rpx;
background: rgba(0, 0, 0, 0.5);
border-radius: 20rpx;
font-size: 24rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ffffff;
text-align: center;
line-height: 40rpx;
position: absolute;
right: 30rpx;
bottom: 50rpx;
}
.collect{
position: absolute;
right: 36rpx;
top: 36rpx;
font-size: 23rpx;
image{
width: 36rpx;
height: 36rpx;
}
}
.swiper-pointer{
position: absolute;
right: 36rpx;
bottom: 80rpx;
background: rgba(22,22,22,0.5);
border-radius: 23rpx;
font-family: PingFang SC;
font-weight: 500;
font-size: 24rpx;
color: #FFFFFF;
padding: 6rpx 14rpx;
}
}
.swiper {
height: 484rpx;
position: relative;
.swiper-item {
width: 100%;
height: 484rpx;
.item-img {
width: 750rpx;
height: 484rpx;
}
.item-img.pop-swiper-image{
height: 347rpx;
border-radius: 13rpx;
}
}
}
.detail-container{
width: 100%;
padding: 26rpx;
padding-bottom: 200rpx;
}
.common-container{
background: white;
border-radius: 20rpx;
margin-bottom: 20rpx;
padding: 22rpx 26rpx;
}
.info-container{
font-family: PingFang SC;
font-weight: 500;
font-size: 24rpx;
color: #666666;
.info-title{
width: 100%;
font-family: PingFang SC;
font-weight: bold;
font-size: 35rpx;
color: #000000;
}
.policy-btn{
width: 160rpx;
height: 35rpx;
font-family: PingFang SC;
font-weight: 500;
font-size: 24rpx;
color: #666666;
text-align: right;
display: flex;
align-items: center;
justify-content: flex-end;
}
.tag-container{
width: 100%;
padding: 35rpx 0;
}
.time-container{
padding: 22rpx 0;
}
.notice-container{
background:rgba(232, 246, 235, 0.7);
border-radius: 13rpx;
font-family: PingFang SC;
font-weight: 500;
font-size: 23rpx;
color: #000000;
padding: 22rpx 16rpx;
margin-top: 28rpx;
image{
width: 25rpx;
height: 25rpx;
}
}
}
.order-time{
.time{
display: flex;
font-family: PingFang SC;
font-size: 24rpx;
color: #000000;
align-items: center;
}
}
.cal-day{
background: #E8F6EB;
border-radius: 17rpx;
padding: 5rpx 16rpx;
font-family: PingFang SC;
font-weight: 500;
font-size: 24rpx;
color: #000000;
}
.popup-content-date{
position: relative;
background: #F7F7F7;
top: -33rpx;
padding: 25rpx 44rpx;
border-radius: 33rpx;
.popup-content-title{
font-family: PingFang SC;
font-weight: 500;
font-size: 35rpx;
color: #000000;
text-align: center;
padding-bottom: 26rpx;
}
.pop-detail-container{
background: #FFFFFF;
border-radius: 13rpx;
padding: 20rpx;
margin-top: 26rpx;
max-height: 800rpx;
overflow-y: auto;
.pop-detail-title{
font-family: PingFang SC;
font-weight: 500;
font-size: 32rpx;
color: #000000;
}
}
}
.btn-list {
width: 100%;
height: 166rpx;
background: #ffffff;
box-shadow: 0rpx -3rpx 9rpx 1rpx rgba(227, 229, 232, 0.5);
display: flex;
position: fixed;
bottom: 0;
padding: 20rpx 20rpx;
align-items: center;
justify-content: space-between;
.btn {
width: 294rpx;
height: 88rpx;
background: #F84A56;
border-radius: 43rpx;
text-align: center;
line-height: 88rpx;
font-size: 36rpx;
font-family: PingFang SC;
font-weight: 500;
color: #FFFFFF;
}
.price-box {
display: flex;
align-items: center;
.text {
font-size: 29rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 500;
color: #333;
}
.price {
margin-left: 15rpx;
font-size: 36rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #fc5109;
&:before {
content: '¥';
display: inline-block;
color: #fc5109;
font-size: 36rpx;
}
}
.post-text {
margin-left: 15rpx;
color: #fc5109;
font-size: 24rpx;
}
}
}
.form-container{
.form-title{
font-family: PingFang SC;
color: #000000;
font-weight: 500;
font-size: 23rpx;
display: flex;
align-items: baseline;
}
.left{
width: 160rpx;
font-family: PingFang SC;
font-weight: bold;
font-size: 29rpx;
color: #000000;
flex-shrink: 0;
}
.line{
display: flex;
align-items: center;
border-top:1rpx solid #D8D8D8;
height: 92rpx;
}
.input{
flex: 1;
}
input{
font-family: PingFang SC;
font-weight: 500;
font-size: 29rpx;
color: #000000;
}
}
.num-box {
display: flex;
align-items: center;
margin-left: 20rpx;
width: 160rpx;
justify-content: space-between;
.num {
text-align: center;
width: 50rpx;
}
.ctrl {
width: 47rpx;
height: 47rpx;
background: #71B580;
border-radius: 50%;
font-family: PingFang SC;
font-weight: 400;
font-size: 34rpx;
color: #FFFFFF;
line-height: 42rpx;
text-align: center;
}
.ctrl.disabled{
background: #E8E8E8;
color: #999999;
}
}
</style>

110
subPackages/hotelHomestay/policy.vue

@ -0,0 +1,110 @@
<template>
<view class="bg">
<view class="common-container">
<view class="info-title box-title text-overflowRows">{{info.title}}</view>
<view class="flex-between phone-container">
<view>
联系电话{{info.tel}}
</view>
<view @click="callPhone">
<image :src="showImg('/uploads/20240830/8b5750ff23837fe4a187e13775f9424c.png')">
</view>
</view>
</view>
<view class="common-container">
<view class="box-title">服务设施</view>
<view style="padding-top: 34rpx;" v-html="formateRichText(info.cost_content)"></view>
</view>
<view class="common-container">
<view class="box-title">入住须知</view>
<view style="padding-top: 34rpx;" v-html="formateRichText(info.describe_content)"></view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
id: null,
info: {},
}
},
onShow(options) {
},
onLoad(options) {
this.id = options.id;
this.getInfo();
},
methods: {
callPhone () {
let _this = this
uni.showActionSheet({
itemList: [this.info.tel,'呼叫'],
success: function (res) {
_this.clickPhone(_this.info.tel)
}
});
// this.clickPhone(this.info.tel)
},
//
getInfo() {
this.Post({id: this.id},'/api/scenic/getScenicById').then(res => {
if (res.data.flag == 0) {
uni.showToast({title: '商品不存在或已下架',icon: 'none'})
setTimeout(() => {this.goBack()}, 2000)
}
this.info = res.data
});
},
}
}
</script>
<style scoped lang="scss">
*{
box-sizing: border-box;
}
.bg{
min-height: 100vh;
background: #F7F7F7;
padding: 20rpx;
}
.common-container{
width: 100%;
background: white;
border-radius: 13rpx;
margin-bottom: 20rpx;
padding: 20rpx 18rpx;
}
.box-title {
font-family: PingFang SC;
font-weight: bold;
font-size: 35rpx;
color: #000000;
}
.info-title{
height: 88rpx;
}
.phone-container{
padding-top: 20rpx;
font-family: PingFang SC;
font-weight: 400;
font-size: 28rpx;
color: #000000;
image{
width: 33.33rpx;
height: 33.33rpx;
}
}
</style>

184
subPackages/line/detail.vue

@ -0,0 +1,184 @@
<template>
<view class="bg">
<view class="swipe-box">
<swiper class="swiper" :autoplay="true" :interval="3000" :duration="1000" circular indicator-dots indicator-color="rgba(255,255,255,.5)"
indicator-active-color="#fff" @change="swiperChange">
<swiper-item v-for="(item, index) in info.list_images.split(',')" :key="item.id">
<view class="swiper-item">
<image class="item-img" :src="showImg(item)" ></image>
</view>
</swiper-item>
</swiper>
<view class="swiper-pointer">
{{swiperCurrent}}/{{info.list_images.split(',').length}}
</view>
<view class="collect" @click.stop="collect()">
<image src="https://tongli.sz-trip.com/uploads/20240829/9dbb80cafe8375bd6d5c96fccb617962.png" v-if="info.is_collect"></image>
<image src="https://tongli.sz-trip.com/uploads/20240826/564af778708591f5de29174d3b14bbff.png" v-else></image>
</view>
</view>
<view class="common-container info-container">
<view class="info-title text-overflowRows">{{info.title}}</view>
</view>
<view class="common-container detail-container">
<view class="" id="cpts" v-html="formateRichText(info.feature_content)"></view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
id: null,
swiperCurrent: 1,
info: {list_images:''},
}
},
onShow(options) {
},
onLoad(options) {
this.id = options.id;
this.getInfo();
},
methods: {
swiperChange (e) {
this.swiperCurrent = e.detail.current+1
},
//
getInfo() {
this.Post({goods_id: this.id},'/api/goods/getGoodDetail').then(res => {
if (res.data.flag == 0) {
uni.showToast({title: '商品不存在或已下架',icon: 'none'})
setTimeout(() => {this.goBack()}, 2000)
}
this.info = res.data;
});
},
//
collect() {
this.Post({type: 6,id: this.id},'/api/scenic/collect').then(res => {
if (res) {
uni.showToast({title: res.msg,icon: 'none'});
this.info.is_collect = !this.info.is_collect
}
});
},
}
}
</script>
<style scoped lang="scss">
*{
box-sizing: border-box;
}
.bg{
min-height: 100vh;
background: #F8F8F8;
}
.swipe-box {
height: 867rpx;
position: relative;
.swiper-item-num {
width: 90rpx;
height: 40rpx;
background: rgba(0, 0, 0, 0.5);
border-radius: 20rpx;
font-size: 24rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ffffff;
text-align: center;
line-height: 40rpx;
position: absolute;
right: 30rpx;
bottom: 50rpx;
}
.collect{
position: absolute;
width: 51rpx;
height: 51rpx;
right: 36rpx;
top: 36rpx;
font-size: 23rpx;
background: rgba(0, 0, 0, 0.5);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
image{
width: 36rpx;
height: 36rpx;
}
}
.swiper-pointer{
position: absolute;
right: 36rpx;
bottom: 80rpx;
background: rgba(22,22,22,0.5);
border-radius: 23rpx;
font-family: PingFang SC;
font-weight: 500;
font-size: 24rpx;
color: #FFFFFF;
padding: 6rpx 14rpx;
}
}
.swiper {
height: 867rpx;
position: relative;
.swiper-item {
width: 100%;
height: 867rpx;
.item-img {
width: 750rpx;
height: 867rpx;
}
.item-img.pop-swiper-image{
height: 347rpx;
border-radius: 13rpx;
}
}
}
.common-container{
background: white;
width: 100%;
}
.info-container{
padding: 34rpx 25rpx;
width: 100%;
font-family: PingFang SC;
font-weight: bold;
font-size: 35rpx;
color: #000000;
margin-bottom: 21rpx;
}
.detail-container{
width: 100%;
padding: 28rpx;
font-family: PingFang SC;
font-weight: 500;
font-size: 28rpx;
color: #333333;
}
</style>

7
subPackages/line/lineList.vue

@ -2,7 +2,7 @@
<view class="bg"> <view class="bg">
<span class="iconfont topLeft" @click="goBack">&#xe660;</span> <span class="iconfont topLeft" @click="goBack">&#xe660;</span>
<img :src="showImg('/uploads/20240826/97282395bdd31e0b1fe20e5356cc4fc4.png')" class="topImg" /> <img :src="showImg('/uploads/20240826/97282395bdd31e0b1fe20e5356cc4fc4.png')" class="topImg" />
<view class="item" v-for="item in list" :key="item.id"> <view class="item" v-for="item in list" :key="item.id" @click="viewDetail(item)">
<image class="img" :src="showImg(item.image)" mode=""></image> <image class="img" :src="showImg(item.image)" mode=""></image>
<view class="content"> <view class="content">
<view class="title text-overflowRows"> <view class="title text-overflowRows">
@ -45,6 +45,11 @@
} }
}) })
}, },
viewDetail (item) {
uni.navigateTo({
url:'/subPackages/line/detail?id='+item.id
})
},
}, },
onReachBottom() { onReachBottom() {
setTimeout(() => { setTimeout(() => {

387
subPackages/order/detail.vue

@ -11,8 +11,44 @@
<view v-if="info.status=='WAIT_PAYMENT'" class="close-time">订单将在{{info.close_time.slice(-8)}}自动取消</view> <view v-if="info.status=='WAIT_PAYMENT'" class="close-time">订单将在{{info.close_time.slice(-8)}}自动取消</view>
</view> </view>
<!-- 景点美食二维码 -->
<view v-if="isQrcode" style="margin-top: -66rpx;">
<view class="qrcode-remain">还剩<span>{{remainNum}}</span>张未核销</view>
<swiper class="qrcode-box" :circular="false" previous-margin="120rpx" next-margin="120rpx"
:duration="800" :current="current" @change="swiperChange">
<swiper-item v-for="(item, index) in info.order_child" :key="index" class="flex-center">
<view class="qrcode-item flex-column">
<view class="qrcode-title">{{item.specifications_name}}</view>
<image :src="showImg(item.qrcodeimg)" mode="aspectFill"></image>
<canvas :id="'qrcodeT'+index" :canvas-id="'qrcodeT'+index"
style="width:150px;height:150px;z-index: -20;bottom: -500px;position: absolute;"></canvas>
<view class="qrcode-subtitle">核销码:{{item.child_id}}</view>
<view class="complete-text flex-center" v-if="['WAIT_REFUND','REFUND_SUCCESS','WAIT_COMMENT','COMPLETE'].includes(item.status)">
<view class="flex-center" v-if="item.status == 'WAIT_COMMENT'">
已核销
</view>
<view class="flex-center" v-else>
已失效
</view>
</view>
</view>
</swiper-item>
</swiper>
<!-- 指示点 -->
<view class="swiper-point flex-center">
<view v-for="(item,index) in info.order_child" :key="index" :class="[{'swiper-points': index == current}]"></view>
</view>
<!-- 提示语 -->
<view class="swiper-prompt">左右滑动核销其他二维码</view>
</view>
<!-- 子订单里info.order_child[0].goods_genre景点ticket酒店hotel美食food邮寄自提pgoods --> <!-- 子订单里info.order_child[0].goods_genre景点ticket酒店hotel美食food邮寄自提pgoods -->
<view :style="{marginTop: isQrcode ? '0' : '-66rpx', margin: 'auto'}" v-if="info.order_child">
<!-- 景点订单 --> <!-- 景点订单 -->
<view v-if="info.order_child[0].goods_genre == 'ticket'"> <view v-if="info.order_child[0].goods_genre == 'ticket'">
<!-- 景点详情 --> <!-- 景点详情 -->
@ -56,7 +92,7 @@
</view> </view>
<!-- 出行人 --> <!-- 出行人 -->
<view class="novice-box"> <view class="novice-box" v-if="item.contact_name">
出行人 出行人
<view v-for="(item,index) in info.order_child" :key="index" class="novice-item"> <view v-for="(item,index) in info.order_child" :key="index" class="novice-item">
<view class="novice-title">{{item.specifications_name}}</view> <view class="novice-title">{{item.specifications_name}}</view>
@ -79,7 +115,7 @@
</view> </view>
<!-- 产品详情 --> <!-- 产品详情 -->
<view class="pgoods-detail" :style="{marginTop: info.order_child[0].consignee_id ? '20rpx' : '-66rpx'}"> <view class="pgoods-detail">
商家名称 商家名称
<view class="pgoods-product" v-for="(item,index) in info.order_child" :key="index"> <view class="pgoods-product" v-for="(item,index) in info.order_child" :key="index">
<image :src="showImg(item.specifications_image)" mode="aspectFill" class="product-img"></image> <image :src="showImg(item.specifications_image)" mode="aspectFill" class="product-img"></image>
@ -110,12 +146,94 @@
<view class="pickup-box" v-if="info.order_child[0].contact_id && info.order_child[0].extract_id"> <view class="pickup-box" v-if="info.order_child[0].contact_id && info.order_child[0].extract_id">
自提信息 自提信息
<view class="pickup-user"> <view class="pickup-user">
<image src="https://static.ticket.sz-trip.com/yandu/images/order/user.png" class="picker-userImg"></image> <image src="https://static.ticket.sz-trip.com/yandu/images/order/user.png" class="picker-img"></image>
<view>{{info.order_child[0].contact.name}}</view> <view>{{info.order_child[0].contact.name}}</view>
<view>{{info.order_child[0].contact.tel}}</view> <view>{{info.order_child[0].contact.tel}}</view>
</view> </view>
<view class="pickup-address"> <view class="pickup-address">
<image></image> <image src="https://static.ticket.sz-trip.com/yandu/images/order/location.png" class="picker-img" style="margin-top: 6rpx;"></image>
<view>
<view class="picker-shopName">{{info.order_child[0].extract.extract_name}}</view>
<view class="picker-shopAddress">{{info.order_child[0].extract.detail_addr}}</view>
</view>
<view class="pickup-icon flex-center">
<view @click="clickPhone(info.order_child[0].extract.mobile)">
<image src="https://static.ticket.sz-trip.com/yandu/images/order/phone.png" mode=""></image>
电话
</view>
<view @click="openLocation(info.order_child[0].extract.lat,info.order_child[0].extract.lon)">
<image src="https://static.ticket.sz-trip.com/yandu/images/order/navigation.png" mode=""></image>
导航
</view>
</view>
</view>
</view>
</view>
<!-- 美食 -->
<view v-if="info.order_child[0].goods_genre == 'food'">
<view class="pgoods-detail">
购买信息
<view class="pgoods-product">
<image :src="showImg(foodInfo.image)" mode="aspectFill" class="product-img"></image>
<view class="product-content flex-column">
<view class="product-title">{{foodInfo.title}}</view>
<view class="product-subtitle flex-between">
<view class="product-tags" v-if="foodInfo.specifications_new_tag">
<view v-for="(item,index) in foodInfo.specifications_new_tag.split(',').slice(0,3)" :key="index">{{item}}</view>
</view>
<span>x{{info.order_child[0].num}}</span>
</view>
</view>
</view>
<!-- 商品价格 -->
<view class="public-price">
<view class="flex-between">
商品总额<span>{{info.money / 100}}</span>
</view>
<view class="flex-between" v-if="info.discounts">
优惠券<span>-{{info.discounts / 100}}</span>
</view>
<view class="flex-between">
实付金额<span style="font-size: 35rpx;color: #EE3E3B;">{{info.pay_money / 100}}</span>
</view>
</view>
</view>
<view class="shop-detail" v-if="merchantInfo">
商家信息
<view class="shop-name">店铺名称</view>
<view class="shop-info">
<view>
<view style="margin-top: 23rpx; display: flex;">
<image src="https://static.ticket.sz-trip.com/yandu/images/order/time.png" class="shop-time"></image>
<view>
<view class="shop-title">营业时间</view>
<view class="shop-subtitle">全年周一至周日 10:00-21:00</view>
</view>
</view>
</view>
<view>
<view class="flex-center" style="margin-top: 23rpx;">
<view style="display: flex;">
<image src="https://static.ticket.sz-trip.com/yandu/images/order/location.png" class="shop-time"></image>
<view style="width: 420rpx;">
<view class="shop-title">{{merchantInfo.province_name}}{{merchantInfo.city_name}}{{merchantInfo.district_name}}{{merchantInfo.detail_addr}}</view>
<view class="shop-subtitle" v-if="merchantInfo.juli">距您约{{merchantInfo.juli}}</view>
</view>
</view>
<view class="shop-icon">
<image src="https://static.ticket.sz-trip.com/yandu/images/order/phone.png" @click="clickPhone(merchantInfo.mobile)"></image>
<image src="https://static.ticket.sz-trip.com/yandu/images/order/navigation.png" @click="openLocation(merchantInfo.lat,merchantInfo.lon)"></image>
</view>
</view>
</view>
</view>
</view> </view>
</view> </view>
</view> </view>
@ -168,12 +286,17 @@
</template> </template>
<script> <script>
import QRCode from '@/static/js/weapp-qrcode.js'
export default { export default {
data() { data() {
return { return {
order_id: '', order_id: '',
info: {}, info: {},
foodInfo: {},
current: 0,
isQrcode: false,
remainNum: 0,
merchantInfo: {}
} }
}, },
onLoad(option) { onLoad(option) {
@ -190,7 +313,79 @@
order_id: this.order_id order_id: this.order_id
},'/api/order/orderDetail').then(res => { },'/api/order/orderDetail').then(res => {
this.info = res.data; this.info = res.data;
if(this.info.order_child[0].goods_genre == 'food') {
//
this.Post({
goods_id: this.info.order_child[0].goods_id
},'/api/goods/getSpecificationsByGoodsId').then(res => {
res.data.forEach(item => {
if(item.id == this.info.order_child[0].specifications_id) this.foodInfo = item
}) })
})
//
this.Post({
lon: uni.getStorageSync('location').lon || '110.43785794300781',
lat: uni.getStorageSync('location').lat || '36.95286642085422',
specifications_id: this.info.order_child[0].specifications_id
},'/api/extract/getMerchantExtractStoreList').then(res => {
this.merchantInfo = res.data[0]
})
}
//
if(['ticket','food'].includes(this.info.order_child[0].goods_genre)) {
if (['PAYMENT_SUCCESSFULLY','WAIT_REFUND','REFUND_SUCCESS','WAIT_COMMENT','COMPLETED'].includes(this.info.status)) {
this.isQrcode = true
for (let i = 0; i < this.info.order_child.length; i++) {
this.getCodeImg(this.info.order_child[i].child_id, i);
//
if(this.info.order_child[i].status == 'SUCCESS') this.remainNum += 1
}
} else if (!['WAIT_PAYMENT','CLOSED'].includes(this.info.status)) {
for (let i = 0; i < this.info.order_child.length; i++) {
if (this.info.order_child[i].is_display_order_qrcode) {
this.isQrcode = true
this.getCodeImg(this.info.order_child[i].child_id, i);
//
if(this.info.order_child[i].status == 'SUCCESS') this.remainNum += 1
}
}
}
}
setTimeout(() => {
console.log(this.info.order_child)
},1000)
})
},
//
getCodeImg(code, index) {
console.log(code)
new QRCode('qrcodeT' + index, {
text: code,
width: 150,
height: 150,
padding: 2,
colorDark: 'rgb(0,0,0)',
colorLight: 'rgb(255,255,255)',
correctLevel: QRCode.CorrectLevel.H, //
callback: res => {
console.log(res)
this.$set(this.info.order_child[index], 'qrcodeimg', res.path);
this.$forceUpdate();
}
});
},
//
swiperChange(e) {
let { current, source } = e.detail;
//current
if (source === 'autoplay' || source === 'touch') {
this.current = current;
}
}, },
// //
clickCopy() { clickCopy() {
@ -214,7 +409,7 @@
let that = this; let that = this;
uni.showModal({ uni.showModal({
title: '提示', title: '提示',
content: '是否关闭订单?', content: '确认取消订单?',
success: successRes => { success: successRes => {
if (successRes.confirm) { if (successRes.confirm) {
that.Post({ that.Post({
@ -241,14 +436,14 @@
type: "miniprogram", type: "miniprogram",
platform: 'miniprogram' platform: 'miniprogram'
},'/api/pay/unify').then(res => { },'/api/pay/unify').then(res => {
if (res.data) { if (res.code == 1) {
uni.requestPayment({ uni.requestPayment({
nonceStr: res.data.nonceStr, nonceStr: res.data.nonceStr,
package: res.data.package, package: res.data.package,
paySign: res.data.paySign, paySign: res.data.paySign,
signType: res.data.signType, signType: res.data.signType,
timeStamp: res.data.timeStamp, timeStamp: res.data.timeStamp,
success:()=>{ complete:()=>{
that.getDetail(); that.getDetail();
} }
}); });
@ -261,6 +456,7 @@
<style lang="scss" scoped> <style lang="scss" scoped>
.bg { .bg {
width: 750rpx;
overflow-x: hidden; overflow-x: hidden;
min-height: 100vh; min-height: 100vh;
background-color: #F7F7F7; background-color: #F7F7F7;
@ -302,6 +498,103 @@
} }
} }
//
.qrcode-remain {
font-weight: bold;
font-size: 29rpx;
color: #000000;
text-align: center;
span {
width: 60rpx;
text-align: center;
color: rgba(238, 62, 59, 1);
display: inline-block;
}
}
.qrcode-box {
height: 456rpx;
display: flex;
align-items: center;
margin-top: 32rpx;
.qrcode-item {
width: 467rpx !important;
height: 456rpx !important;
background: #FFFFFF;
box-shadow: 0rpx 0rpx 33rpx 0rpx rgba(102,102,102,0.2);
border-radius: 20rpx;
padding: 25rpx 0;
justify-content: space-between;
align-items: center;
position: relative;
image {
width: 300rpx;
height: 300rpx;
border-radius: 10rpx;
}
.qrcode-title {
font-weight: bold;
font-size: 32rpx;
color: #000000;
}
.qrcode-subtitle {
font-weight: 500;
font-size: 27rpx;
color: #888888;
}
.complete-text {
position: absolute;
width: 300rpx;
height: 300rpx;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
background: rgba(0, 0, 0, .5);
view {
width: 200rpx;
height: 200rpx;
background: #FFFFFF;
border-radius: 100rpx;
font-weight: bold;
font-size: 36rpx;
color: #000000;
}
}
}
}
.swiper-point {
height: 63rpx;
view {
width: 11rpx;
height: 11rpx;
background: #CCCCCC;
border-radius: 50%;
}
view:not(:first-child) {
margin-left: 13rpx;
}
.swiper-points {
background: #71B580;
}
}
.swiper-prompt {
font-weight: 500;
font-size: 29rpx;
color: #EE3E3B;
text-align: center;
margin-bottom: 45rpx;
}
// //
.scenic-detail { .scenic-detail {
width: 697rpx; width: 697rpx;
@ -309,7 +602,7 @@
background: #FFFFFF; background: #FFFFFF;
border-radius: 20rpx; border-radius: 20rpx;
padding: 26rpx; padding: 26rpx;
margin: -66rpx auto 0; margin: auto;
&>view:nth-child(2) { &>view:nth-child(2) {
margin: 30rpx 0; margin: 30rpx 0;
@ -395,10 +688,10 @@
background: #FFFFFF; background: #FFFFFF;
border-radius: 20rpx; border-radius: 20rpx;
padding: 26rpx; padding: 26rpx;
margin: -66rpx auto 0;
font-weight: bold; font-weight: bold;
font-size: 36rpx; font-size: 36rpx;
color: #000000; color: #000000;
margin: auto;
&>view { &>view {
margin-top: 25rpx; margin-top: 25rpx;
@ -458,6 +751,17 @@
font-weight: 500; font-weight: 500;
font-size: 24rpx; font-size: 24rpx;
color: #666666; color: #666666;
.product-tags {
display: flex;
&>view:not(:last-child)::after {
content: '丨';
width: 1rpx;
height: 26rpx;
color: #666666;
}
}
} }
} }
} }
@ -479,6 +783,11 @@
margin-top: 40rpx; margin-top: 40rpx;
} }
.picker-img {
width: 33.33rpx;
height: 33.33rpx;
}
.pickup-user { .pickup-user {
display: flex; display: flex;
align-items: center; align-items: center;
@ -486,11 +795,6 @@
font-size: 31rpx; font-size: 31rpx;
color: #000000; color: #000000;
.picker-userImg {
width: 33.33rpx;
height: 33.33rpx;
}
&>view:first-of-type { &>view:first-of-type {
margin: 0 63rpx 0 19rpx; margin: 0 63rpx 0 19rpx;
} }
@ -538,12 +842,65 @@
image { image {
width: 56rpx; width: 56rpx;
height: 56rpx; height: 56rpx;
display: block;
margin-bottom: 5rpx; margin-bottom: 5rpx;
} }
} }
} }
} }
//
.shop-detail {
width: 697rpx;
height: auto;
background: #FFFFFF;
border-radius: 20rpx;
margin: 20rpx auto 0;
padding: 33rpx 26rpx;
font-weight: bold;
font-size: 36rpx;
color: #000000;
.shop-name {
font-weight: bold;
font-size: 30rpx;
color: #000000;
margin-top: 30rpx;
}
.shop-info {
.shop-time {
width: 28rpx;
height: 28rpx;
margin: 5rpx 8rpx 0 0;
}
.shop-title {
font-weight: 500;
font-size: 26rpx;
color: #000000;
}
.shop-subtitle {
font-weight: 500;
font-size: 24rpx;
color: #666666;
margin-top: 23rpx;
}
.shop-icon {
margin-left: auto;
image{
width: 56rpx;
height: 56rpx;
}
image:first-child {
margin-right: 40rpx;
}
}
}
}
// //
.public-price { .public-price {

2
subPackages/order/orderCoupon.vue

@ -46,7 +46,7 @@
</view> </view>
<view v-else class="noCoupon"> <view v-else class="noCoupon">
<img src="https://static.ticket.sz-trip.com/dongtai/images/user/noCoupon.png" class="no-couPon"> <img :src="showImg('/uploads/20240902/376de17481e3010f50305be570009745.png')" class="no-couPon">
<view>暂无优惠券</view> <view>暂无优惠券</view>
</view> </view>

5
subPackages/order/trades.vue

@ -182,7 +182,10 @@ export default {
package: res.data.package, package: res.data.package,
paySign: res.data.paySign, paySign: res.data.paySign,
signType: res.data.signType, signType: res.data.signType,
timeStamp: res.data.timeStamp timeStamp: res.data.timeStamp,
complete:()=>{
that.getDetail();
}
}); });
} }
}); });

30
subPackages/techan/detail.vue

@ -1,7 +1,19 @@
<template> <template>
<view class="bg" id="bg" v-if="info"> <view class="bg" id="bg" v-if="info">
<view class="swipe-box"> <view class="swipe-box">
<swiper class="swiper" :indicator-dots="false" :autoplay="true" :interval="3000" :duration="1000" circular> <swiper class="swiper" :indicator-dots="false" :autoplay="false" :interval="3000" :duration="1000" circular>
<swiper-item v-if="info && info.videourl">
<video
:src="showImg(info.videourl)"
id="detailVideo"
:poster="showImg(info.image)"
@play="play"
@error="videoErrorCallback"
controls
style="width: 100%;height: 100%;"
object-fit="cover"
></video>
</swiper-item>
<swiper-item v-for="(item, index) in info.list_images.split(',')" :key="item.id"> <swiper-item v-for="(item, index) in info.list_images.split(',')" :key="item.id">
<view class="swiper-item"> <view class="swiper-item">
<image class="item-img" :src="showImg(item)" mode="aspectFill"></image> <image class="item-img" :src="showImg(item)" mode="aspectFill"></image>
@ -31,7 +43,7 @@
选择 选择
</view> </view>
<view class="flex-1"> <view class="flex-1">
{{sku[productIndex].title}} {{sku[productIndex].title || '暂无可选规格'}}
</view> </view>
</view> </view>
<uni-icons class="flex-shrink-0" style="height: 36rpx;margin-right: 20rpx;" type="right" size="18"></uni-icons> <uni-icons class="flex-shrink-0" style="height: 36rpx;margin-right: 20rpx;" type="right" size="18"></uni-icons>
@ -181,7 +193,7 @@
'/api/goods/getSpecificationsByGoodsId' '/api/goods/getSpecificationsByGoodsId'
).then(res => { ).then(res => {
if (res) { if (res) {
this.sku = res.data; this.sku = res.data || [];
} }
}); });
}, },
@ -218,6 +230,14 @@
this.$refs.popup.close() this.$refs.popup.close()
}, },
openPop() { openPop() {
if (!this.sku||this.sku.length<=0) {
uni.showToast({
title:'暂无可选规格',
icon:'none'
})
return
}
if (!this.popShow) { if (!this.popShow) {
this.$refs.popup.open() this.$refs.popup.open()
} else { } else {
@ -227,8 +247,8 @@
order(item) { order(item) {
let goods = this.sku[this.productIndex] let goods = this.sku[this.productIndex]
goods.buyNum = this.buyNum goods.buyNum = this.buyNum
uni.setStorageSync('order', JSON.stringify(goods)); // uni.setStorageSync('teChanOrder', JSON.stringify(goods)); //
uni.setStorageSync('info', JSON.stringify(this.info)); // uni.setStorageSync('teChanInfo', JSON.stringify(this.info)); //
uni.navigateTo({ uni.navigateTo({
url: '/subPackages/techan/order' url: '/subPackages/techan/order'
}); });

52
subPackages/techan/order.vue

@ -117,7 +117,7 @@
</view> </view>
</view> </view>
<!-- 优惠券 --> <!-- 优惠券 -->
<navigator :url="'/subPackages/order/orderCoupon?needDefault=1&allprice='+ allprice + '&sku_ids='+ info.id" class="tickets-box flex-between top-line"> <navigator :url="'/subPackages/order/orderCoupon?allprice='+ allprice + '&sku_ids='+ info.id" class="tickets-box flex-between top-line">
<view class="order-title">优惠券</view> <view class="order-title">优惠券</view>
<view class="coupon-btn" v-if="coupon==''"> <view class="coupon-btn" v-if="coupon==''">
<view class="select">请选择</view> <view class="select">请选择</view>
@ -233,8 +233,8 @@ export default {
}, },
onLoad() { onLoad() {
this.$store.commit("choseCoupon", ""); this.$store.commit("choseCoupon", "");
this.info = JSON.parse(uni.getStorageSync('order')); this.info = JSON.parse(uni.getStorageSync('teChanOrder'));
this.detail = JSON.parse(uni.getStorageSync('info')); this.detail = JSON.parse(uni.getStorageSync('teChanInfo'));
if (!this.info) { if (!this.info) {
uni.navigateBack(); uni.navigateBack();
return return
@ -257,6 +257,15 @@ export default {
}, },
onUnload(){ onUnload(){
uni.$off("updateDataByConnect",this.getDataByConnect) uni.$off("updateDataByConnect",this.getDataByConnect)
},
onReady () {
this.$nextTick(()=>{
setTimeout(()=>{
this.getMaxCouponData()
},1000)
})
}, },
methods: { methods: {
getContacts() { getContacts() {
@ -409,7 +418,7 @@ export default {
} }
} else{ } else{
price = ((this.info.money) * this.info.buyNum + postPrice) - (((this.info.money) * this.info.buyNum + postPrice) * this.coupon.percent) price = ((this.info.money) * this.info.buyNum + postPrice) - (((this.info.money) * this.info.buyNum + postPrice) * this.coupon.percent/100)
} }
} else { } else {
price = (this.info.money) * this.info.buyNum + postPrice price = (this.info.money) * this.info.buyNum + postPrice
@ -441,7 +450,7 @@ export default {
}); });
return; return;
} }
if (!this.IsTel(this.pickupPerson)) { if (!this.IsTel(this.pickupPerson.phone)) {
uni.showToast({ uni.showToast({
title: '请输入自提人手机号', title: '请输入自提人手机号',
icon: 'none' icon: 'none'
@ -462,7 +471,6 @@ export default {
if (this.sendType == 2) { if (this.sendType == 2) {
goodsItem.extract_id = this.pickupAddress.id; goodsItem.extract_id = this.pickupAddress.id;
goodsItem.contact_id = this.pickupPerson.id;
} else if (this.sendType == 1){ } else if (this.sendType == 1){
goodsItem.consignee_id = this.contacts.id goodsItem.consignee_id = this.contacts.id
} }
@ -473,9 +481,8 @@ export default {
coupon: this.coupon ? this.coupon.id : "", coupon: this.coupon ? this.coupon.id : "",
remark: this.remark, remark: this.remark,
is_post: this.info.is_post, is_post: this.info.is_post,
reserve_name: this.reserve_name, reserve_name: this.pickupPerson.name,
reserve_phone: this.reserve_phone, reserve_phone: this.pickupPerson.phone,
reserve_idcard: this.reserve_idcard
}; };
this.Post( this.Post(
{ {
@ -484,6 +491,8 @@ export default {
}, },
'/api/order/place' '/api/order/place'
).then(res => { ).then(res => {
uni.removeStorageSync('teChanOrder')
uni.removeStorageSync('teChanInfo')
if (res.code == 1) { if (res.code == 1) {
this.Post( this.Post(
{ {
@ -523,6 +532,15 @@ export default {
} }
}, },
//
async getMaxCouponData () {
let param = {money:this.allprice,sku_ids:this.info.id}
let res = await this.getMaxCoupon(param)
if (res.id) {
this.coupon = res
}
}
} }
@ -801,20 +819,20 @@ view {
} }
} }
.btn-list { .btn-list {
width: 750rpx; width: 100%;
height: 166rpx; height: 166rpx;
background: #ffffff; background: #ffffff;
box-shadow: 0rpx -3rpx 9rpx 1rpx rgba(227, 229, 232, 0.5); box-shadow: 0rpx -3rpx 9rpx 1rpx rgba(227, 229, 232, 0.5);
display: flex; display: flex;
position: fixed; position: fixed;
bottom: 0; bottom: 0;
padding: 20rpx 50rpx; padding: 20rpx 20rpx;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
.btn { .btn {
width: 294rpx; width: 294rpx;
height: 88rpx; height: 88rpx;
background: linear-gradient(90deg, #F84A56, #FF9834); background: #F84A56;
border-radius: 43rpx; border-radius: 43rpx;
text-align: center; text-align: center;
line-height: 88rpx; line-height: 88rpx;
@ -829,14 +847,14 @@ view {
display: flex; display: flex;
align-items: center; align-items: center;
.text { .text {
font-size: 28rpx; font-size: 29rpx;
font-family: PingFangSC-Regular, PingFang SC; font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400; font-weight: 500;
color: #393b3e; color: #333;
} }
.price { .price {
margin-left: 15rpx; margin-left: 15rpx;
font-size: 48rpx; font-size: 36rpx;
font-family: PingFangSC-Regular, PingFang SC; font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400; font-weight: 400;
color: #fc5109; color: #fc5109;
@ -844,7 +862,7 @@ view {
content: '¥'; content: '¥';
display: inline-block; display: inline-block;
color: #fc5109; color: #fc5109;
font-size: 24rpx; font-size: 36rpx;
} }
} }
.post-text { .post-text {

20
subPackages/ticketBooking/detail.vue

@ -25,7 +25,7 @@
<image class="address-icon flex-shrink-0" :src="showImg('/uploads/20240827/3d357e6e562de9395f373dc380a790a7.png')" mode=""></image> <image class="address-icon flex-shrink-0" :src="showImg('/uploads/20240827/3d357e6e562de9395f373dc380a790a7.png')" mode=""></image>
<view class="title text-overflowRows"> <view class="title text-overflowRows">
<text style="margin-right: 28rpx;">营业时间</text> <text style="margin-right: 28rpx;">营业时间</text>
{{info.times_list_info.start}}-{{info.times_list_info.end}} {{info.open_description}}
</view> </view>
</view> </view>
<view></view> <view></view>
@ -44,8 +44,8 @@
</view> </view>
</view> </view>
<view class="box-title">门票预定</view> <view class="box-title" v-if="sku.length>0">门票预定</view>
<view class="common-container"> <view class="common-container" v-if="sku.length>0">
<view class="scenic-list" v-for="(item, index) in sku" :key="index"> <view class="scenic-list" v-for="(item, index) in sku" :key="index">
<view class="list-title text-overflow">{{ item.title }}</view> <view class="list-title text-overflow">{{ item.title }}</view>
<view class="scenic-item com-flex-tao" v-for="(itemSku, indexSku) in item.specifications" :key="indexSku"> <view class="scenic-item com-flex-tao" v-for="(itemSku, indexSku) in item.specifications" :key="indexSku">
@ -76,7 +76,7 @@
</view> </view>
</view> </view>
<view class="box-title">景点简</view> <view class="box-title"></view>
<view class="common-container"> <view class="common-container">
<view class="" id="cpts" v-html="formateRichText(info.feature_content)"></view> <view class="" id="cpts" v-html="formateRichText(info.feature_content)"></view>
</view> </view>
@ -321,7 +321,12 @@
let orderSkuIndex = this.selectGoods.specifications.findIndex(v=>v.id == that.skuInfo.id) let orderSkuIndex = this.selectGoods.specifications.findIndex(v=>v.id == that.skuInfo.id)
let item = this.selectGoods.specifications.splice(orderSkuIndex, 1)[0]; // let item = this.selectGoods.specifications.splice(orderSkuIndex, 1)[0]; //
item.buyNum = 1 item.buyNum = 1
item.selPeople = [{}] item.selPeople = [
{
id:null,id_number:null,name:null,
tel:null,user_id:null,age:null,
},
]
this.selectGoods.specifications.unshift(item); this.selectGoods.specifications.unshift(item);
let param = { let param = {
@ -335,13 +340,10 @@
timesArr: this.timesArr, timesArr: this.timesArr,
seldTimeIndex: this.seldTimeIndex, seldTimeIndex: this.seldTimeIndex,
} }
uni.setStorageSync('ticketOrder', JSON.stringify(param));
// that.gotoBuy(pInfo, sInfo); // that.gotoBuy(pInfo, sInfo);
uni.navigateTo({ uni.navigateTo({
url:'/subPackages/ticketBooking/order', url:'/subPackages/ticketBooking/order',
success() {
uni.$emit("updateDataByConnect", {msgType:'updateTicketBookingOrder',data:param})
}
}) })
}, },

248
subPackages/ticketBooking/order.vue

@ -28,17 +28,30 @@
</view> </view>
<view class="people-box" > <view class="people-box" >
<view class="people-box-sku" v-for="(skuItem,skuIndex) in pInfo.specifications.filter(v=>v.buyNum>=1)" :key="skuIndex"> <!-- 按地址引用 不能用filter -->
<!-- <view class="people-box-sku" v-for="(skuItem,skuIndex) in pInfo.specifications.filter(v=>v.buyNum>=1)" :key="skuIndex"> -->
<view v-for="(skuItem,skuIndex) in pInfo.specifications" :key="skuIndex">
<view class="people-box-sku" v-if="skuItem.buyNum>=1">
<view>{{skuItem.title}}</view> <view>{{skuItem.title}}</view>
<view v-for="(person,personIndex) in skuItem.selPeople" :key="personIndex" @click="person.id=1;showAddressPopUp(person)"> <view v-for="(person,personIndex) in skuItem.selPeople" :key="personIndex" @click="showAddressPopUp(person,skuItem.selPeople)">
<view v-if="person.id">123</view> <view v-if="person.id" class="flex">
<view>出行人1</view>
<view>{{person.name}}</view>
</view>
<view v-else>点击添加出行人信息</view> <view v-else>点击添加出行人信息</view>
</view> </view>
</view>
</view> </view>
</view> </view>
<view class="btn-list">
<view class="price-box">
<view class="text">合计:</view>
<view class="price">{{ 10 }}</view>
<!-- <view class="post-text" v-if="sendType==1&&post">含邮费:¥{{ post / 100 }}</view> -->
</view>
<view class="btn" @click="order()">立即购买</view>
</view>
<!-- 选择出行人 --> <!-- 选择出行人 -->
<uni-popup ref="addressPopup" type="bottom" backgroundColor="#F4F4F4" > <uni-popup ref="addressPopup" type="bottom" backgroundColor="#F4F4F4" >
<view class="people-popup"> <view class="people-popup">
@ -50,7 +63,8 @@
</view> </view>
<view class="button">添加出行人</view> <view class="button">添加出行人</view>
<view class="popup-list" v-if="addressList.length > 0"> <view class="popup-list" v-if="addressList.length > 0">
<view :class="['popup-item',addressSelect.id==item.id?'active':'']" v-for="(item, index) in addressList" :key="index" @click="seldThisAddress(item)"> <view :class="['popup-item',addressSelect.id==item.id?'active':'',currentPerson.id!=item.id&&currentPersonIds.includes(item.id)?'disabled':'']"
v-for="(item, index) in addressList" :key="index" @click="seldThisAddress(item)">
<view class="item-top flex-between"> <view class="item-top flex-between">
<view style="padding-right: 71rpx;"> <view style="padding-right: 71rpx;">
<view class="name flex-start"> <view class="name flex-start">
@ -91,47 +105,54 @@
buyNum: 0, buyNum: 0,
addressList: [], addressList: [], //
currentPerson: {}, currentPerson: {}, //
addressSelect: {}, currentPersonIds: [], //
addressSelect: {}, //
} }
}, },
onLoad(options) { onLoad(options) {
// this.getList(); // this.getList();
this.initPageData()
uni.$on("updateDataByConnect",this.getDataByConnect)
}, },
onShow() { onShow() {
this.getAddressList() this.getAddressList()
this.handlePageData()
}, },
onUnload () { onUnload () {
uni.$off("updateDataByConnect",this.getDataByConnect)
}, },
methods: { methods: {
getDataByConnect(data) { initPageData () {
if (data.msgType == "updateTicketBookingOrder") { let data = uni.getStorageSync('ticketOrder');
uni.setStorageSync('tempData', JSON.stringify(data.data)); try{
data = JSON.parse(data)
// this.pInfo = data.data.pInfo this.pInfo = data.pInfo
// this.sInfo = data.data.sInfo this.sInfo = data.sInfo
// this.minSeldDate=data.data.minSeldDate this.minSeldDate=data.minSeldDate
// this.maxSeldDate = data.data.maxSeldDate this.maxSeldDate = data.maxSeldDate
// this.calendarParam = data.data.calendarParam this.calendarParam = data.calendarParam
// this.allSeldDate = data.data.allSeldDate this.allSeldDate = data.allSeldDate
// this.seldDateIndex = data.data.seldDateIndex this.seldDateIndex = data.seldDateIndex
// this.timesArr = data.data.timesArr this.timesArr = data.timesArr
// this.seldTimeIndex = data.data.seldTimeIndex this.seldTimeIndex = data.seldTimeIndex
} catch(e){
console.log(e)
} }
}, },
// //
showAddressPopUp (person) { showAddressPopUp (person,personList) {
person.id = 1
this.currentPerson = person this.currentPerson = person
this.currentPersonIds = []
personList.forEach(v=>{
if (v.id) {
this.currentPersonIds.push(v.id)
}
})
if (person.id) { if (person.id) {
this.addressSelect = person this.addressSelect = person
} else { } else {
@ -151,6 +172,7 @@
if (confirm) { if (confirm) {
// //
this.currentPerson.id = this.addressSelect.id this.currentPerson.id = this.addressSelect.id
this.currentPerson.name = this.addressSelect.name
this.currentPerson.id_number = this.addressSelect.id_number this.currentPerson.id_number = this.addressSelect.id_number
this.currentPerson.tel = this.addressSelect.tel this.currentPerson.tel = this.addressSelect.tel
this.currentPerson.user_id = this.addressSelect.user_id this.currentPerson.user_id = this.addressSelect.user_id
@ -164,28 +186,20 @@
this.$forceUpdate(); this.$forceUpdate();
}, },
seldThisAddress(item){ seldThisAddress(item){
if (this.addressSelect.id == item.id) {
this.addressSelect = {}
} else {
if (this.currentPersonIds.includes(item.id)&&item.id!=this.currentPerson.id) {
return
} else {
this.addressSelect = item this.addressSelect = item
}
}
}, },
handlePageData () {
let data = uni.getStorageSync('tempData');
try{
data = JSON.parse(data)
this.pInfo = data.pInfo
this.sInfo = data.sInfo
this.minSeldDate=data.minSeldDate
this.maxSeldDate = data.maxSeldDate
this.calendarParam = data.calendarParam
this.allSeldDate = data.allSeldDate
this.seldDateIndex = data.seldDateIndex
this.timesArr = data.timesArr
this.seldTimeIndex = data.seldTimeIndex
} catch(e){
console.log(e)
}
},
// //
@ -214,9 +228,15 @@
// this.$toast(""+this.max_num+"") // this.$toast(""+this.max_num+"")
// } // }
if (Array.isArray(skuItem.selPeople)) { if (Array.isArray(skuItem.selPeople)) {
skuItem.selPeople.push({}) skuItem.selPeople.push({
id:null,id_number:null,name:null,
tel:null,user_id:null,age:null,
})
} else { } else {
skuItem.selPeople = [{}] skuItem.selPeople = [{
id:null,id_number:null,name:null,
tel:null,user_id:null,age:null,
}]
} }
}, },
@ -290,6 +310,79 @@
}) })
}, },
order() {
let use_date = this.allSeldDate[this.seldDateIndex].date
let start_time =this.timesArr[this.seldTimeIndex].start_time
let end_time = this.timesArr[this.seldTimeIndex].end_time
let goods = []
//
console.log(this.pInfo)
this.pInfo.specifications.forEach(sku=>{
if (sku.buyNum != sku.selPeople.length) {
uni.showToast({
title:'请选择出行人',
icon:'none'
})
}
if (sku.buyNum>=1) {
let param = {
specifications_id: sku.id,
num: sku.buyNum,
contact_id: sku.selPeople.filter(v=>v.id).map(v=>v.id),
date: use_date,
start_time: start_time,
end_time: end_time,
}
goods.push(param)
}
})
console.log(goods)
let data = {
goods: goods,
coupon: this.coupon ? this.coupon.id : "",
// reserve_name: this.reserve_name,
// reserve_phone: this.reserve_phone
// remark: this.remark
}
console.log('data数据',data);
this.Post({
method: 'POST',
data: JSON.stringify(data)
}, '/api/order/place').then(res => {
if (res.code == 200) {
console.log(res.data.order_id);
let order_id = res.data.order_id
this.$store.commit("changeOrderInfo", null);
this.$store.commit("choseCoupon", "");
this.Post({
order_id: order_id,
type: "miniprogram",
platform: 'miniprogram'
}, '/api/pay/unify').then(res => {
if (res.data) {
uni.requestPayment({
nonceStr: res.data.nonceStr,
package: res.data.package,
paySign: res.data.paySign,
signType: res.data.signType,
timeStamp: res.data.timeStamp,
complete() {
uni.navigateTo({
url: '/subPackages/order/trades'
})
}
})
}
})
}
})
}
} }
} }
</script> </script>
@ -574,6 +667,11 @@
.popup-item.active{ .popup-item.active{
background-image: linear-gradient(135deg, #9EE4FE, #7FD491); background-image: linear-gradient(135deg, #9EE4FE, #7FD491);
} }
.popup-item.disabled{
.item-top {
background-color: #999;
}
}
} }
.button { .button {
@ -592,4 +690,60 @@
} }
} }
.btn-list {
width: 750rpx;
height: 166rpx;
background: #ffffff;
box-shadow: 0rpx -3rpx 9rpx 1rpx rgba(227, 229, 232, 0.5);
display: flex;
position: fixed;
bottom: 0;
padding: 20rpx 50rpx;
align-items: center;
justify-content: space-between;
.btn {
width: 294rpx;
height: 88rpx;
background: linear-gradient(90deg, #F84A56, #FF9834);
border-radius: 43rpx;
text-align: center;
line-height: 88rpx;
font-size: 36rpx;
font-family: PingFang SC;
font-weight: 500;
color: #FFFFFF;
}
.price-box {
display: flex;
align-items: center;
.text {
font-size: 28rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #393b3e;
}
.price {
margin-left: 15rpx;
font-size: 48rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #fc5109;
&:before {
content: '¥';
display: inline-block;
color: #fc5109;
font-size: 24rpx;
}
}
.post-text {
margin-left: 15rpx;
color: #fc5109;
font-size: 24rpx;
}
}
}
</style> </style>

17
subPackages/ticketBooking/ticketBooking.vue

@ -18,7 +18,12 @@
<view class="text-overflow">{{item.address}}</view> <view class="text-overflow">{{item.address}}</view>
</view> </view>
<view class="priceBox"> <view class="priceBox">
<view class="price">{{showPrice(item.price)}}</view> <!-- <view :class="['price',item.price>0?'price-money':'']">
{{item.price>0?showPrice(item.price):'免费'}}
</view> -->
<view class="price price-money">
{{showPrice(item.price)}}
</view>
</view> </view>
</view> </view>
</navigator> </navigator>
@ -42,15 +47,17 @@
finished: false, finished: false,
headImg:null, headImg:null,
type_id: 10,//id type_id: 10,//id
} }
}, },
onShow() { onShow() {
this.headImg = 'https://tongli.sz-trip.com/uploads/20240826/a87488f6225789aa19dbb437671d388d.png' this.headImg = 'https://tongli.sz-trip.com/uploads/20240826/a87488f6225789aa19dbb437671d388d.png'
this.finished = false this.finished = false
this.getList()
// this.getHeadImg('piaowu') // this.getHeadImg('piaowu')
}, },
onReady() {
this.getList()
},
onLoad(options) { onLoad(options) {
let that = this let that = this
uni.getSystemInfo({ uni.getSystemInfo({
@ -173,12 +180,12 @@
color: #F02A2A; color: #F02A2A;
text-align: right; text-align: right;
} }
.price::before{ .price-money::before{
content: '¥'; content: '¥';
color: #F02A2A; color: #F02A2A;
font-size: 24rpx; font-size: 24rpx;
} }
.price::after{ .price-money::after{
content: '起'; content: '起';
color: #999; color: #999;
font-size: 24rpx; font-size: 24rpx;

200
subPackages/travelGuide/detail.vue

@ -0,0 +1,200 @@
<template>
<view class="bg">
<view class="swipe-box" v-if="info.images">
<swiper class="swiper" :autoplay="true" :interval="3000" :duration="1000" circular indicator-dots indicator-color="rgba(255,255,255,.5)"
indicator-active-color="#fff" @change="swiperChange">
<swiper-item v-for="(item, index) in info.images.split(',')" :key="item.id">
<view class="swiper-item">
<image class="item-img" :src="showImg(item)" mode="aspectFill"></image>
</view>
</swiper-item>
</swiper>
<view class="swiper-pointer">
{{swiperCurrent}}/{{info.images.split(',').length}}
</view>
<view class="collect" @click.stop="collect()">
<image src="https://tongli.sz-trip.com/uploads/20240829/9dbb80cafe8375bd6d5c96fccb617962.png" v-if="info.is_collect"></image>
<image src="https://tongli.sz-trip.com/uploads/20240826/564af778708591f5de29174d3b14bbff.png" v-else></image>
</view>
<!-- <view class="collect" @click.stop="share()">
<image src="https://tongli.sz-trip.com/uploads/20240902/8eb614e4ea41db655a4e6da2cc0ca954.png"></image>
</view> -->
</view>
<view class="common-container info-container">
<view class="info-title text-overflowRows">{{info.title}}</view>
<view class="flex-between" style="padding: 40rpx 0 0;">
<view>浏览 {{info.view}}</view>
<view>发布时间{{info.create_time}}</view>
</view>
<!-- <view class="text-overflow" v-if="info.start_time && info.end_time">时间{{info.start_time}} - {{info.end_time}}</view> -->
</view>
<view class="common-container detail-container">
<view class="" id="cpts" v-html="formateRichText(info.detail)"></view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
id: null,
swiperCurrent: 1,
info: {},
}
},
onShow(options) {
},
onLoad(options) {
this.id = options.id;
this.getInfo();
},
methods: {
swiperChange (e) {
this.swiperCurrent = e.detail.current+1
},
//
getInfo() {
this.Post({id: this.id},'/api/article/getArticleById').then(res => {
if (res.data.flag == 0) {
uni.showToast({title: '文章不存在或已下架',icon: 'none'})
setTimeout(() => {this.goBack()}, 2000)
}
this.info = res.data;
});
},
//
collect() {
this.Post({type: 1,id: this.id},'/api/scenic/collect').then(res => {
if (res) {
uni.showToast({title: res.msg,icon: 'none'});
this.info.is_collect = !this.info.is_collect
}
});
},
}
}
</script>
<style scoped lang="scss">
*{
box-sizing: border-box;
}
.bg{
min-height: 100vh;
background: #F8F8F8;
}
.swipe-box {
height: 867rpx;
position: relative;
.swiper-item-num {
width: 90rpx;
height: 40rpx;
background: rgba(0, 0, 0, 0.5);
border-radius: 20rpx;
font-size: 24rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ffffff;
text-align: center;
line-height: 40rpx;
position: absolute;
right: 30rpx;
bottom: 50rpx;
}
.collect{
position: absolute;
width: 51rpx;
height: 51rpx;
right: 20rpx;
top: 20rpx;
font-size: 23rpx;
background: rgba(0, 0, 0, 0.5);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
image{
width: 36rpx;
height: 36rpx;
}
}
.swiper-pointer{
position: absolute;
right: 20rpx;
bottom: 20rpx;
background: rgba(22,22,22,0.5);
border-radius: 23rpx;
font-family: PingFang SC;
font-weight: 500;
font-size: 24rpx;
color: #FFFFFF;
padding: 6rpx 14rpx;
}
}
.swiper {
height: 867rpx;
position: relative;
.swiper-item {
width: 100%;
height: 867rpx;
.item-img {
width: 750rpx;
height: 867rpx;
}
.item-img.pop-swiper-image{
height: 347rpx;
border-radius: 13rpx;
}
}
}
.common-container{
background: white;
width: 100%;
}
.info-container{
padding: 34rpx 25rpx;
width: 100%;
margin-bottom: 21rpx;
font-family: PingFang SC;
font-weight: 500;
font-size: 25rpx;
color: #666666;
.info-title{
font-weight: bold;
font-size: 35rpx;
color: #000000;
}
}
.detail-container{
width: 100%;
padding: 28rpx;
font-family: PingFang SC;
font-weight: 500;
font-size: 28rpx;
color: #333333;
}
</style>

234
subPackages/travelGuide/travelGuide.vue

@ -0,0 +1,234 @@
<template>
<view class="bg">
<view class="topImg relative">
<img v-if="headImg" :src="showImg(headImg)" class="topImg" mode="aspectFill">
<view class="icon-back" :style="{top:systemInfo.textTop,left:'19rpx'}" @click="goBack()" >
<uni-icons type="left" size="24" color="#242424"></uni-icons>
</view>
</view>
<view class="tag-container no-scrollbar">
<view :class="['tag', type_id==0?'active':'']" @click="setTag(0)">全部</view>
<view :class="['tag', type_id==1?'active':'']" v-for="(item,i) in 10" :key="i" @click="setTag(i)">景点</view>
</view>
<view class="strategy-box box">
<view v-for="(num,nums) in 2" :key="nums">
<view v-for="(item,index) in list" :key="index" class="strategy-item" v-if="index % 2 === nums" @click="viewDetail(item)">
<!-- <view class="title-tag" v-if="item.image_tag">{{item.image_tag}}</view> -->
<image class="strategy-image" :src="showImg(item.image)" mode="widthFix"></image>
<view class="strategy-content">
<view class="strategy-title">{{item.title}}</view>
<view class="flex-between">
<view class="text-overflow" style="display: flex;align-items: center;width: 200rpx;">
<image :src="showImg(item.author_img)" mode="" class="author-img"></image>
{{item.author}}
</view>
<view style="display: flex;align-items: center;">
<image src="https://static.ticket.sz-trip.com/yandu/images/index/eye.png" mode="" class="eye-img"></image>
{{item.view}}
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default{
data(){
return {
systemInfo: {
height:"0px",
textHeight:"0px",
textTop:"0px",
contentTop: '0px',
},
list: [],
showMore: true,
headImg:"https://tongli.sz-trip.com/uploads/20240902/55c5cbe137790323cc719b5c83d5e2e9.png",
type_id: 0,//id
}
},
onShow() {
this.showMore = true
},
onReady() {
this.getArticleByType()
},
onLoad(options) {
let that = this
uni.getSystemInfo({
success(res) {
console.log(res)
that.systemInfo.height =res.windowHeight+'px'
const menu=uni.getMenuButtonBoundingClientRect()
that.systemInfo.textHeight=menu.height+"px"
that.systemInfo.textTop=menu.top+"px"
that.systemInfo.contentTop = (menu.height + menu.top)+"px"
console.log(that.systemInfo)
}
})
},
methods: {
setTag (item) {
this.type_id = item
// this.getArticleByType()
},
//
getArticleByType() {
this.Post({
type_id: 41,
offset: this.list.length,
limit: 10
},'/api/Article/getArticleByType').then(res => {
this.list = [...this.list, ...res.data]
if(res.data.length < 10) this.showMore = false
})
},
//
strategyMore() {
this.getArticleByType()
},
viewDetail (item) {
uni.navigateTo({
url:'/subPackages/travelGuide/detail?id='+item.id
})
},
},
onReachBottom() {
setTimeout(() => {
if (!this.showMore) this.getList()
},1000)
}
}
</script>
<style scoped lang="scss">
*{
box-sizing: border-box;
font-family: PingFangSC;
}
.bg{
min-height: 100vh;
background: #FFFFFF;
}
.topImg{
width: 100%;
height: 440rpx;
.icon-back{
position: absolute;
display: flex;
align-items: center;
z-index: 50;
}
}
.tag-container{
margin: 42rpx 26rpx;
display: flex;
flex-wrap: nowrap;
overflow-y: auto;
.tag{
flex-shrink: 0;
border-radius: 13rpx;
border: 1px solid #999999;
font-family: PingFang SC;
font-weight: 500;
font-size: 28rpx;
color: #666666;
padding: 13rpx 29rpx;
margin-right: 20rpx;
}
.tag.active{
background: linear-gradient(90deg, #9EE4FE, #7FD491);
border: none;
font-weight: bold;
color: #000000;
}
}
.strategy-box {
padding: 0 26rpx;
padding-bottom: 50rpx;
box-sizing: border-box;
display: flex;
justify-content: space-between;
.strategy-item {
width: 339rpx;
border-radius: 13rpx;
overflow: hidden;
margin-bottom: 28rpx;
position: relative;
box-shadow: 0rpx 0rpx 20rpx 0rpx rgba(153,153,153,0.38);
.title-tag {
position: absolute;
top: 0;
left: 0;
width: 153rpx;
line-height: 47rpx;
background: #71B580;
border-radius: 20rpx 0rpx 20rpx 0rpx;
text-align: center;
font-weight: 500;
font-size: 27rpx;
color: #FFFFFF;
overflow-x: auto;
white-space: nowrap;
}
.title-tag::-webkit-scrollbar {
display: none;
}
.strategy-image {
width: 337rpx;
display: block;
}
.strategy-content {
background: #FFFFFF;
padding: 20rpx;
.strategy-title {
font-family: PingFang SC;
font-weight: bold;
font-size: 31rpx;
color: #2C2C2C;
}
.flex-between {
font-weight: 500;
font-family: PingFang SC;
font-size: 24rpx;
color: #000000;
margin-top: 14rpx;
.author-img {
width: 37rpx;
height: 37rpx;
margin-right: 6rpx;
}
.eye-img {
width: 26.67rpx;
height: 18.67rpx;
margin-right: 6rpx;
}
}
}
}
}
</style>
Loading…
Cancel
Save