@@ -78,7 +78,10 @@ var config = { | |||||
* 获取券适用门店List | * 获取券适用门店List | ||||
*/ | */ | ||||
couponMerchant: "/wxCoupon/couponMerchant", | couponMerchant: "/wxCoupon/couponMerchant", | ||||
/** | |||||
* 获取适用门店所在的城市list | |||||
*/ | |||||
couponMerchantCity: "/wxCoupon/couponMerchantCity", | |||||
/** | /** | ||||
* 获取券详情 | * 获取券详情 | ||||
*/ | */ | ||||
@@ -82,8 +82,10 @@ | |||||
<view class="fuwuName f">服务资质</view> | <view class="fuwuName f">服务资质</view> | ||||
</navigator> | </navigator> | ||||
</view> | </view> | ||||
</view> | </view> | ||||
<view class="version">Version 2.8.3</view> | |||||
<phoem showBox="{{showPhoem}}" bind:hiePhoen="setPhone" bind:heiBox="setBox"></phoem> | <phoem showBox="{{showPhoem}}" bind:hiePhoen="setPhone" bind:heiBox="setBox"></phoem> | ||||
</view> | </view> | ||||
<tabbar /> | <tabbar /> |
@@ -1,5 +1,5 @@ | |||||
/* d:\fumaolianke\ttFmC\tt富茂C\pages\user\user.ttss */ | /* d:\fumaolianke\ttFmC\tt富茂C\pages\user\user.ttss */ | ||||
.BoxBg{ | |||||
.BoxBg { | |||||
/* background-image: url("https://formall.oss-accelerate.aliyuncs.com/douyin_ifomall/imgData/userBg.png"); */ | /* background-image: url("https://formall.oss-accelerate.aliyuncs.com/douyin_ifomall/imgData/userBg.png"); */ | ||||
/* background-size: 100% auto; */ | /* background-size: 100% auto; */ | ||||
/* background-repeat: no-repeat; */ | /* background-repeat: no-repeat; */ | ||||
@@ -9,7 +9,8 @@ | |||||
background-color: #e6e6e6; | background-color: #e6e6e6; | ||||
overflow: hidden; | overflow: hidden; | ||||
} | } | ||||
.bgImgTop{ | |||||
.bgImgTop { | |||||
width: 100%; | width: 100%; | ||||
height: 380rpx; | height: 380rpx; | ||||
transform: rotate(16deg); | transform: rotate(16deg); | ||||
@@ -18,32 +19,38 @@ | |||||
left: 0; | left: 0; | ||||
z-index: 1; | z-index: 1; | ||||
} | } | ||||
.userBg{ | |||||
.userBg { | |||||
width: 100%; | width: 100%; | ||||
height: 200rpx; | height: 200rpx; | ||||
/* background:linear-gradient(180deg,rgba(253,131,45,1) 0%,rgba(254,74,22,1) 100%); */ | /* background:linear-gradient(180deg,rgba(253,131,45,1) 0%,rgba(254,74,22,1) 100%); */ | ||||
position: relative; | position: relative; | ||||
} | } | ||||
.userBg1{ | |||||
.userBg1 { | |||||
width: 100%; | width: 100%; | ||||
height: 200rpx; | height: 200rpx; | ||||
/* background-image: url("/assets/imgData/userBg.png"); */ | /* background-image: url("/assets/imgData/userBg.png"); */ | ||||
position: relative; | position: relative; | ||||
z-index: 1000; | z-index: 1000; | ||||
} | } | ||||
button::after { | button::after { | ||||
border: none; | border: none; | ||||
} | |||||
} | |||||
button { | button { | ||||
background-color: transparent; | background-color: transparent; | ||||
padding-left: 0; | padding-left: 0; | ||||
padding-right: 0; | padding-right: 0; | ||||
line-height:inherit; | |||||
line-height: inherit; | |||||
} | } | ||||
button { | button { | ||||
border-radius:0; | |||||
border-radius: 0; | |||||
} | } | ||||
.userLogo{ | |||||
.userLogo { | |||||
position: absolute; | position: absolute; | ||||
top: 40rpx; | top: 40rpx; | ||||
left: 80rpx; | left: 80rpx; | ||||
@@ -53,24 +60,29 @@ button { | |||||
border-radius: 50%; | border-radius: 50%; | ||||
border: 2rpx solid #A2B9BE; | border: 2rpx solid #A2B9BE; | ||||
} | } | ||||
.userLogo open-data{ | |||||
.userLogo open-data { | |||||
display: block; | display: block; | ||||
width: 100%; | width: 100%; | ||||
height: 100%; | height: 100%; | ||||
} | } | ||||
.userLogo img{ | |||||
.userLogo img { | |||||
border-radius: 50% !important; | border-radius: 50% !important; | ||||
} | } | ||||
.open{ | |||||
.open { | |||||
width: 100% !important; | width: 100% !important; | ||||
height:100% !important; | |||||
height: 100% !important; | |||||
border-radius: 50% !important; | border-radius: 50% !important; | ||||
overflow: hidden; | overflow: hidden; | ||||
} | } | ||||
.open img{ | |||||
.open img { | |||||
border-radius: 50% !important; | border-radius: 50% !important; | ||||
} | } | ||||
.userData{ | |||||
.userData { | |||||
position: absolute; | position: absolute; | ||||
top: 40rpx; | top: 40rpx; | ||||
left: 180rpx; | left: 180rpx; | ||||
@@ -79,23 +91,24 @@ button { | |||||
/* color: #ffffff; */ | /* color: #ffffff; */ | ||||
} | } | ||||
.noInfo{ | |||||
.noInfo { | |||||
width: 220rpx; | width: 220rpx; | ||||
margin-left: 20rpx; | margin-left: 20rpx; | ||||
font-size: 32rpx; | font-size: 32rpx; | ||||
text-overflow: -o-ellipsis-lastline; | text-overflow: -o-ellipsis-lastline; | ||||
overflow:hidden; | |||||
text-overflow:ellipsis; | |||||
display:-webkit-box; | |||||
-webkit-box-orient:vertical; | |||||
-webkit-line-clamp:1; | |||||
overflow: hidden; | |||||
text-overflow: ellipsis; | |||||
display: -webkit-box; | |||||
-webkit-box-orient: vertical; | |||||
-webkit-line-clamp: 1; | |||||
color: #02201c; | color: #02201c; | ||||
font-family: "PingFangSC-Medium"; | font-family: "PingFangSC-Medium"; | ||||
font-size: 36rpx; | font-size: 36rpx; | ||||
font-weight: 400; | font-weight: 400; | ||||
text-transform: uppercase; | text-transform: uppercase; | ||||
} | } | ||||
.info{ | |||||
.info { | |||||
border: 1rpx #ffffff solid; | border: 1rpx #ffffff solid; | ||||
border-radius: 50rpx; | border-radius: 50rpx; | ||||
padding: 0 10rpx; | padding: 0 10rpx; | ||||
@@ -104,7 +117,8 @@ button { | |||||
text-align: center; | text-align: center; | ||||
/* width: 130rpx; */ | /* width: 130rpx; */ | ||||
} | } | ||||
.infoX{ | |||||
.infoX { | |||||
/* border: 1rpx #ffffff solid; */ | /* border: 1rpx #ffffff solid; */ | ||||
border-radius: 50rpx; | border-radius: 50rpx; | ||||
padding: 0 10rpx; | padding: 0 10rpx; | ||||
@@ -117,19 +131,22 @@ button { | |||||
text-transform: uppercase; | text-transform: uppercase; | ||||
/* text-align: center; */ | /* text-align: center; */ | ||||
} | } | ||||
.userName{ | |||||
.userName { | |||||
position: absolute; | position: absolute; | ||||
top: 60rpx; | top: 60rpx; | ||||
left: 180rpx; | left: 180rpx; | ||||
font-size: 26rpx; | font-size: 26rpx; | ||||
color: #ffffff; | color: #ffffff; | ||||
} | } | ||||
.tempBpx{ | |||||
.tempBpx { | |||||
position: relative; | position: relative; | ||||
width: 680rpx; | width: 680rpx; | ||||
height: 160rpx; | height: 160rpx; | ||||
} | } | ||||
.functionBox{ | |||||
.functionBox { | |||||
position: absolute; | position: absolute; | ||||
width: 680rpx; | width: 680rpx; | ||||
height: 160rpx; | height: 160rpx; | ||||
@@ -139,30 +156,35 @@ button { | |||||
/* background-color: #ffffff; */ | /* background-color: #ffffff; */ | ||||
border-radius: 10rpx; | border-radius: 10rpx; | ||||
display: flex; | display: flex; | ||||
justify-content:space-around; | |||||
justify-content: space-around; | |||||
/* overflow: hidden; */ | /* overflow: hidden; */ | ||||
z-index: 100; | z-index: 100; | ||||
} | } | ||||
.itemBox{ | |||||
width:30% ; | |||||
.itemBox { | |||||
width: 30%; | |||||
/* text-align: center; */ | /* text-align: center; */ | ||||
} | } | ||||
.itemLogoBox{ | |||||
.itemLogoBox { | |||||
width: 60rpx; | width: 60rpx; | ||||
height: 60rpx; | height: 60rpx; | ||||
/* background-color: #cacaca; */ | /* background-color: #cacaca; */ | ||||
margin: 20rpx auto 0 auto; | margin: 20rpx auto 0 auto; | ||||
} | } | ||||
.itemLogo{ | |||||
.itemLogo { | |||||
width: 100%; | width: 100%; | ||||
height: 100%; | height: 100%; | ||||
} | } | ||||
.itemNAme{ | |||||
.itemNAme { | |||||
text-align: center; | text-align: center; | ||||
font-size: 26rpx; | font-size: 26rpx; | ||||
margin-top: 10rpx; | margin-top: 10rpx; | ||||
} | } | ||||
.moreBox{ | |||||
.moreBox { | |||||
width: 680rpx; | width: 680rpx; | ||||
margin: 20rpx auto 0 auto; | margin: 20rpx auto 0 auto; | ||||
background-color: #ffffff; | background-color: #ffffff; | ||||
@@ -172,26 +194,31 @@ button { | |||||
position: absolute; | position: absolute; | ||||
z-index: 1000; | z-index: 1000; | ||||
} | } | ||||
.fuwu{ | |||||
.fuwu { | |||||
/* font-size: 28rpx; */ | /* font-size: 28rpx; */ | ||||
margin: 20rpx 0 20rpx 40rpx ; | |||||
margin: 20rpx 0 20rpx 40rpx; | |||||
color: #5d3a19; | color: #5d3a19; | ||||
font-family: "PingFangSC-Medium"; | font-family: "PingFangSC-Medium"; | ||||
font-size: 32rpx; | font-size: 32rpx; | ||||
font-weight: 400; | font-weight: 400; | ||||
} | } | ||||
.fuwuItemBox{ | |||||
.fuwuItemBox { | |||||
/* display: flex; */ | /* display: flex; */ | ||||
overflow: hidden; | overflow: hidden; | ||||
} | } | ||||
.f{ | |||||
.f { | |||||
float: left; | float: left; | ||||
} | } | ||||
.r{ | |||||
.r { | |||||
float: right; | float: right; | ||||
} | } | ||||
.fuwuItem{ | |||||
.fuwuItem { | |||||
/* width: 25%; */ | /* width: 25%; */ | ||||
/* background-color: aquamarine; */ | /* background-color: aquamarine; */ | ||||
border-bottom: 1rpx #f6f6f6 solid; | border-bottom: 1rpx #f6f6f6 solid; | ||||
@@ -201,14 +228,23 @@ button { | |||||
margin: 0 auto; | margin: 0 auto; | ||||
} | } | ||||
.fuwuLogoBox{ | |||||
.fuwuLogoBox { | |||||
width: 50rpx; | width: 50rpx; | ||||
height: 50rpx; | height: 50rpx; | ||||
/* background-color: #fb3e5c; */ | /* background-color: #fb3e5c; */ | ||||
} | } | ||||
.fuwuName{ | |||||
.fuwuName { | |||||
text-align: center; | text-align: center; | ||||
font-size: 24rpx; | font-size: 24rpx; | ||||
margin-top: 10rpx; | margin-top: 10rpx; | ||||
margin-left: 10rpx; | margin-left: 10rpx; | ||||
} | |||||
.version { | |||||
position: absolute; | |||||
bottom: 0; | |||||
right: 5%; | |||||
color: #ffffffb9; | |||||
} | } |
@@ -182,6 +182,7 @@ Page({ | |||||
mallLocationArr.forEach((item, index) => { | mallLocationArr.forEach((item, index) => { | ||||
const distanceData = that.getDistances(latitudeNow, longitudeNow, item.latitude, item.longitude) | const distanceData = that.getDistances(latitudeNow, longitudeNow, item.latitude, item.longitude) | ||||
tempArr[index].distance_str = distanceData.distance_str | tempArr[index].distance_str = distanceData.distance_str | ||||
tempArr[index].distance_str = distanceData.distance_str | |||||
tempArr[index].distanceName = tempArr[index].merchantName + ' ' + distanceData.distance_str | tempArr[index].distanceName = tempArr[index].merchantName + ' ' + distanceData.distance_str | ||||
tempArr[index].distance = distanceData.distance | tempArr[index].distance = distanceData.distance | ||||
bloobArr.push(tempArr[index]) | bloobArr.push(tempArr[index]) | ||||
@@ -207,7 +208,19 @@ Page({ | |||||
}, | }, | ||||
complete: finish => { | complete: finish => { | ||||
let isSuccess = 0 | |||||
const mallList = that.data.mallList | |||||
mallList.forEach(item => { | |||||
if (item.distance_str) { | |||||
isSuccess = 1 | |||||
} | |||||
}) | |||||
if (!isSuccess) { | |||||
tt.showToast({ | |||||
title: '定位失败!', | |||||
icon: "fail" | |||||
}); | |||||
} | |||||
} | } | ||||
}) | }) | ||||
}, | }, | ||||
@@ -639,7 +652,7 @@ Page({ | |||||
*/ | */ | ||||
orderFunc(discount) { | orderFunc(discount) { | ||||
if (this.data.showbutton) return; | if (this.data.showbutton) return; | ||||
if (!this.data.merchantId) { | |||||
if (!this.data.merchantId && this.data.data.type == 69) { | |||||
tt.showToast({ | tt.showToast({ | ||||
title: '请选择可用商户!', | title: '请选择可用商户!', | ||||
icon: 'fail' | icon: 'fail' | ||||
@@ -38,7 +38,8 @@ | |||||
<view tt:if="{{ !merchantId }}" class="addressPickerFlex"> | <view tt:if="{{ !merchantId }}" class="addressPickerFlex"> | ||||
<text>选择可用商户:</text> | <text>选择可用商户:</text> | ||||
<picker style="display: inline-block;" mode="selector" value="{{index}}" range="{{mallList}}" | <picker style="display: inline-block;" mode="selector" value="{{index}}" range="{{mallList}}" | ||||
range-key="distanceName" disabled="{{false}}" bindchange="setMerchant"> | |||||
range-key="{{mallList[0].distanceName ? 'distanceName' : 'merchantName'}}" disabled="{{false}}" | |||||
bindchange="setMerchant"> | |||||
<view class="pickerInside"> | <view class="pickerInside"> | ||||
请选择 | 请选择 | ||||
</view> | </view> | ||||
@@ -46,10 +47,12 @@ | |||||
</view> | </view> | ||||
<view tt:if="{{ merchantId }}" class="addressPicker"> | <view tt:if="{{ merchantId }}" class="addressPicker"> | ||||
<picker style="display: inline;" mode="selector" value="{{index}}" range="{{mallList}}" range-key="distanceName" | |||||
disabled="{{false}}" bindchange="setMerchant"> | |||||
<picker style="display: inline;" mode="selector" value="{{index}}" range="{{mallList}}" | |||||
rrange-key="{{mallList[0].distanceName ? 'distanceName' : 'merchantName'}}" disabled="{{false}}" | |||||
bindchange="setMerchant"> | |||||
<text> 选择可用商户:<text class="pickerInside">{{ | <text> 选择可用商户:<text class="pickerInside">{{ | ||||
mallList[currentIndex].merchantName }} <text class="distanceFoot">{{ | |||||
mallList[currentIndex].merchantName }} <text tt:if="{{ mallList[currentIndex].distance_str }}" | |||||
class="distanceFoot">{{ | |||||
mallList[currentIndex].distance_str }}</text></text></text> | mallList[currentIndex].distance_str }}</text></text></text> | ||||
</picker> | </picker> | ||||
</view> | </view> |
@@ -26,7 +26,8 @@ Page({ | |||||
status: "", | status: "", | ||||
isShowBtns: false, | isShowBtns: false, | ||||
latitude: "", | latitude: "", | ||||
longitude: "" | |||||
longitude: "", | |||||
shopItem: null | |||||
}, | }, | ||||
onLoad(options) { | onLoad(options) { | ||||
console.log(options, 'options') | console.log(options, 'options') | ||||
@@ -76,7 +77,7 @@ Page({ | |||||
endTime: options.endTime || '', | endTime: options.endTime || '', | ||||
}) | }) | ||||
this.getCouponMerchant(options.orderId) | |||||
// this.getCouponMerchant() | |||||
if (this.data.id) { | if (this.data.id) { | ||||
this.getDetail(this.data.id) | this.getDetail(this.data.id) | ||||
@@ -87,6 +88,19 @@ Page({ | |||||
} | } | ||||
}, | }, | ||||
goSelectShop() { | |||||
const data = this.data | |||||
const id = data.id | |||||
const orderId = data.orderId | |||||
const merOrderId = data.merOrderId | |||||
const startTime = data.startTime | |||||
const endTime = data.endTime | |||||
tt.navigateTo({ | |||||
url: `/pages2/shopSelect/shopSelect?id=${id}&orderId=${orderId}&merOrderId=${merOrderId}&startTime=${startTime}&endTime=${endTime}`, | |||||
}); | |||||
}, | |||||
setMerchant(e) { | setMerchant(e) { | ||||
console.log(e.detail.value, 'e'); | console.log(e.detail.value, 'e'); | ||||
const index = e.detail.value | const index = e.detail.value | ||||
@@ -160,7 +174,19 @@ Page({ | |||||
}, | }, | ||||
complete: finish => { | complete: finish => { | ||||
let isSuccess = 0 | |||||
const mallList = that.data.mallList | |||||
mallList.forEach(item => { | |||||
if (item.distance_str) { | |||||
isSuccess = 1 | |||||
} | |||||
}) | |||||
if (!isSuccess) { | |||||
tt.showToast({ | |||||
title: '定位失败!', | |||||
icon: "fail" | |||||
}); | |||||
} | |||||
} | } | ||||
}) | }) | ||||
}, | }, | ||||
@@ -211,12 +237,6 @@ Page({ | |||||
}) | }) | ||||
}, | }, | ||||
goSelectShop() { | |||||
tt.navigateTo({ | |||||
url: `/pages2/shopSelect/shopSelect` | |||||
}); | |||||
}, | |||||
chooseAddress() { | chooseAddress() { | ||||
if (!this.data.isShowBtns) return | if (!this.data.isShowBtns) return | ||||
let that = this; | let that = this; | ||||
@@ -505,6 +525,16 @@ Page({ | |||||
}, | }, | ||||
onShow() { | onShow() { | ||||
const shopItem = app.globalData.shopItem | |||||
if (shopItem) { | |||||
console.log('Yes!!!'); | |||||
this.setData({ | |||||
shopItem, | |||||
merchantId: shopItem.id, | |||||
reservationMerchantName: "" | |||||
}) | |||||
console.log(this.data.shopItem, 'shopItem'); | |||||
app.globalData.shopItem = null | |||||
} | |||||
} | } | ||||
}) | }) |
@@ -37,33 +37,44 @@ | |||||
</picker> | </picker> | ||||
</view> | </view> | ||||
<view tt:if="{{ !merchantId }}" class="addressPickerFlex"> | |||||
<!-- <view tt:if="{{ !merchantId }}" class="addressPickerFlex"> | |||||
<text>选择可用商户:</text> | <text>选择可用商户:</text> | ||||
<picker style="display: inline-block;" mode="selector" value="{{index}}" range="{{mallList}}" | <picker style="display: inline-block;" mode="selector" value="{{index}}" range="{{mallList}}" | ||||
range-key="distanceName" disabled="{{false}}" bindchange="setMerchant"> | |||||
range-key="{{mallList[0].distanceName ? 'distanceName' : 'merchantName'}}" disabled="{{false}}" | |||||
bindchange="setMerchant"> | |||||
<view class="pickerInside"></view> | <view class="pickerInside"></view> | ||||
请选择 | 请选择 | ||||
</picker> | </picker> | ||||
</view> | </view> | ||||
<view tt:if="{{ merchantId }}" class="addressPicker"> | <view tt:if="{{ merchantId }}" class="addressPicker"> | ||||
<picker style="display: inline;" mode="selector" value="{{index}}" range="{{mallList}}" range-key="distanceName" | |||||
disabled="{{false}}" bindchange="setMerchant"> | |||||
<picker style="display: inline;" mode="selector" value="{{index}}" range="{{mallList}}" | |||||
range-key="{{mallList[0].distanceName ? 'distanceName' : 'merchantName'}}" disabled="{{false}}" | |||||
bindchange="setMerchant"> | |||||
<text tt:if="{{ !reservationMerchantName }}"> 选择可用商户:<text class="pickerInside">{{ | <text tt:if="{{ !reservationMerchantName }}"> 选择可用商户:<text class="pickerInside">{{ | ||||
mallList[currentIndex].merchantName }} <text class="distanceFoot">{{ | |||||
mallList[currentIndex].merchantName }} <text tt:if="{{ mallList[currentIndex].distance_str }}" | |||||
class="distanceFoot">{{ | |||||
mallList[currentIndex].distance_str }}</text></text></text> | mallList[currentIndex].distance_str }}</text></text></text> | ||||
<text tt:if="{{ reservationMerchantName }}"> 选择可用商户:<text class="pickerInside">{{ reservationMerchantName | <text tt:if="{{ reservationMerchantName }}"> 选择可用商户:<text class="pickerInside">{{ reservationMerchantName | ||||
}}</text></text> | }}</text></text> | ||||
</picker> | </picker> | ||||
</view> | |||||
</view> --> | |||||
<view class="addressPickerFlex" bindtap="goSelectShop"> | |||||
<text>选择可用商户(BETA):</text> | |||||
<view tt:if="{{ !shopItem && !reservationMerchantName }}" class="addressPickerFlex" bindtap="goSelectShop"> | |||||
<text>选择可用商户(Beta):</text> | |||||
<view class="pickerInside"> | <view class="pickerInside"> | ||||
请选择 | 请选择 | ||||
</view> | </view> | ||||
</view> | |||||
<view tt:if="{{ shopItem || reservationMerchantName }}" class="addressPicker" bindtap="goSelectShop"> | |||||
<text tt:if="{{ reservationMerchantName }}"> 选择可用商户(Beta):<text class="pickerInside">{{ reservationMerchantName | |||||
}}</text></text> | |||||
<text tt:else> 选择可用商户:<text class="pickerInside">{{ | |||||
shopItem.merchantName }} <text tt:if="{{ shopItem.distance_str }}" | |||||
class="distanceFoot">{{shopItem.distance_str }}</text></text></text> | |||||
</view> | </view> | ||||
<view class="describeTextarea"> | <view class="describeTextarea"> | ||||
@@ -1,16 +1,270 @@ | |||||
// c:\Users\56817\Desktop\Working Space\3,TikTok-MiniPro\ttc\pages2\shopSelect\shopSelect.js | // c:\Users\56817\Desktop\Working Space\3,TikTok-MiniPro\ttc\pages2\shopSelect\shopSelect.js | ||||
let config = require("../../config/config.js"); | |||||
let util = require("../../utils/util"); | |||||
let Http = require("../../utils/HttpBasics"); | |||||
let app = getApp(); | |||||
const imgurl = require("../../utils/imgurl"); | |||||
Page({ | Page({ | ||||
data: { | data: { | ||||
isShop: true, | isShop: true, | ||||
position: 0, | position: 0, | ||||
tagArr: [], | tagArr: [], | ||||
currentTag: "" | |||||
mallList: [], | |||||
currentTag: "", | |||||
currentCity: "", | |||||
id: "", | |||||
orderId: "", | |||||
merOrderId: "", | |||||
startTime: "", | |||||
endTime: "", | |||||
latitude: "", | |||||
longitude: "", | |||||
toView: "A" | |||||
}, | }, | ||||
onLoad: function (options) { | onLoad: function (options) { | ||||
tt.showLoading({ | |||||
title: '加载中...', | |||||
}) | |||||
console.log(options, 'options') | |||||
const mallTenantId = tt.getStorageSync('mallTenantId'); | |||||
if (mallTenantId) { | |||||
this.setData({ | |||||
mallTenantId | |||||
}) | |||||
} | |||||
const tagArr = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'] | const tagArr = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'] | ||||
this.setData({ | this.setData({ | ||||
tagArr | tagArr | ||||
}) | }) | ||||
this.setData({ | |||||
id: options.id || '', | |||||
orderId: options.orderId || '', | |||||
merOrderId: options.merOrderId || '', | |||||
startTime: options.startTime || '', | |||||
endTime: options.endTime || '', | |||||
}) | |||||
this.getLocation() | |||||
}, | |||||
getCouponChannelId(flag) { | |||||
const that = this | |||||
Http.get({ | |||||
url: config.api.orderDetail, | |||||
data: { | |||||
orderId: that.data.merOrderId, | |||||
mallTenantId: that.data.mallTenantId || '' | |||||
} | |||||
}).then(res => { | |||||
const couponChannelId = res.data.orders[0].couponChannelId | |||||
that.getCouponMerchant(couponChannelId, flag) | |||||
that.getCityList(couponChannelId) | |||||
}).catch(err => { | |||||
}) | |||||
}, | |||||
//获取适用门店 | |||||
getCouponMerchant(couponChannelId, flag) { | |||||
const that = this | |||||
Http.get({ | |||||
url: config.api.couponMerchant, | |||||
data: { | |||||
couponChannelId, | |||||
city: that.data.currentCity, | |||||
mallTenantId: that.data.mallTenantId || '' | |||||
} | |||||
}).then(res => { | |||||
const keys = Object.keys(res.data) | |||||
if (keys.length > 0) { | |||||
const mallList = [] | |||||
let i = 0 | |||||
keys.forEach(item => { | |||||
const arr = item.split('|') | |||||
const obj = { | |||||
tenantId: arr[0], | |||||
mallName: arr[1], | |||||
merchantVoList: res.data[item], | |||||
expand: false | |||||
} | |||||
if (i == 0) { | |||||
obj.expand = true | |||||
} | |||||
mallList.push(obj) | |||||
i++ | |||||
}) | |||||
that.setData({ | |||||
mallList: mallList[0].merchantVoList | |||||
}) | |||||
console.log(that.data.mallList, 'mallList'); | |||||
} else { | |||||
that.setData({ | |||||
mallList: [] | |||||
}) | |||||
console.log(that.data.mallList, 'mallList'); | |||||
} | |||||
if (flag) { | |||||
that.dealMallList() | |||||
} | |||||
tt.hideLoading(); | |||||
}) | |||||
}, | |||||
// 获取适用门店所在的城市list | |||||
getCityList(couponChannelId) { | |||||
Http.get({ | |||||
url: config.api.couponMerchantCity, | |||||
data: { | |||||
couponChannelId | |||||
} | |||||
}).then(res => { | |||||
console.log(res, 'res'); | |||||
}).catch(err => { | |||||
console.log(err, 'err'); | |||||
}) | |||||
}, | |||||
/** | |||||
* 获得经纬度 | |||||
*/ | |||||
getLocation() { | |||||
console.log('getLocation'); | |||||
const that = this; | |||||
tt.getLocation({ | |||||
type: "wgs84", | |||||
// isHighAccuracy: true, | |||||
success: function (res) { | |||||
console.log(res, 'getLocation') | |||||
that.setData({ | |||||
latitude: res.latitude, | |||||
longitude: res.longitude, | |||||
currentCity: res.city | |||||
}) | |||||
that.getCouponChannelId(true) | |||||
}, | |||||
// 拒绝提供定位权限 | |||||
fail: error => { | |||||
// that.getCouponChannelId(false) | |||||
that.setData({ | |||||
isShop: false, | |||||
mallList: [] | |||||
}) | |||||
tt.hideLoading(); | |||||
}, | |||||
complete: finish => { | |||||
const city = that.data.currentCity | |||||
if (!city) { | |||||
tt.showToast({ | |||||
title: "定位失败!", | |||||
icon: "fail" | |||||
}); | |||||
} | |||||
} | |||||
}) | |||||
}, | |||||
dealMallList() { | |||||
const that = this | |||||
const latitudeNow = that.data.latitude | |||||
const longitudeNow = that.data.longitude | |||||
const mallLocationArr = [] | |||||
const mallList = that.data.mallList | |||||
mallList.forEach((item, index) => { | |||||
const obj = { | |||||
latitude: item.latitude || false, | |||||
longitude: item.longitude || false, | |||||
id: item.id, | |||||
index: index | |||||
} | |||||
mallLocationArr.push(obj) | |||||
}) | |||||
console.log(mallLocationArr, 'mallLocationArr'); | |||||
const tempArr = mallList | |||||
const bloobArr = [] | |||||
mallLocationArr.forEach((item, index) => { | |||||
const distanceData = that.getDistances(latitudeNow, longitudeNow, item.latitude, item.longitude) | |||||
tempArr[index].distance_str = distanceData.distance_str | |||||
tempArr[index].distanceName = tempArr[index].merchantName + ' ' + distanceData.distance_str | |||||
tempArr[index].distance = distanceData.distance | |||||
bloobArr.push(tempArr[index]) | |||||
}) | |||||
const finalSortMallList = that.bloob(bloobArr) | |||||
console.log(finalSortMallList, 'finalSortMallList'); | |||||
that.setData({ | |||||
mallList: finalSortMallList | |||||
}) | |||||
}, | |||||
/** | |||||
* @description:根据经纬度计算距离 | |||||
* @param {*} locationInfo (lat1, lng1, lat2, lng2) | |||||
* @return: distanceObj: { distance , distance_str } | |||||
*/ | |||||
getDistances(lat1, lng1, lat2, lng2) { | |||||
if (lat2 || lng2) { | |||||
function rad(num) { | |||||
return num * Math.PI / 180.0; | |||||
} | |||||
var radLat1 = rad(lat1); | |||||
var radLat2 = rad(lat2); | |||||
var a = radLat1 - radLat2; | |||||
var b = rad(lng1) - rad(lng2); | |||||
var s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + | |||||
Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2))); | |||||
s = s * 6378.137; | |||||
s = Math.round(s * 10000) / 10000; | |||||
var distance = s; | |||||
var distance_str = ""; | |||||
if (parseInt(distance) >= 1) { | |||||
distance_str = distance.toFixed(2) + "km"; | |||||
} else if (!arseInt(distance)) { | |||||
return false | |||||
} else { | |||||
distance_str = (distance * 1000).toFixed(2) + "m"; | |||||
} | |||||
let objData = { | |||||
distance: distance, | |||||
distance_str: distance_str | |||||
} | |||||
return objData | |||||
} else { | |||||
let objData = { | |||||
distance: Infinity, | |||||
distance_str: '' | |||||
} | |||||
return objData | |||||
} | |||||
}, | |||||
bloob(arr) { | |||||
const tempArr = arr | |||||
for (let i = 0; i < tempArr.length - 1; i++) { | |||||
for (let j = 0; j < tempArr.length - 1 - i; j++) { | |||||
if (tempArr[j].distance > tempArr[j + 1].distance) { | |||||
let temp = tempArr[j]; | |||||
tempArr[j] = tempArr[j + 1]; | |||||
tempArr[j + 1] = temp; | |||||
} | |||||
} | |||||
} | |||||
return tempArr | |||||
}, | }, | ||||
selectCity() { | selectCity() { | ||||
@@ -31,19 +285,32 @@ Page({ | |||||
tagBind(e) { | tagBind(e) { | ||||
const that = this | const that = this | ||||
tt.hideToast({ | |||||
success: (res) => { | |||||
const id = e.target.id | |||||
that.setData({ | |||||
currentTag: id | |||||
}) | |||||
tt.showToast({ | |||||
title: id, | |||||
icon: "none", | |||||
duration: 1000 | |||||
}); | |||||
}, | |||||
}); | |||||
const id = e.target.id | |||||
that.setData({ | |||||
currentTag: id, | |||||
toView: id | |||||
}) | |||||
}, | }, | ||||
goSetShop(e) { | |||||
const item = e.currentTarget.dataset.item | |||||
console.log(item, 'item'); | |||||
app.globalData.shopItem = item | |||||
tt.navigateBack(); | |||||
}, | |||||
goFindShop(e) { | |||||
const name = e.currentTarget.dataset.name | |||||
this.setData({ | |||||
currentCity: name, | |||||
mallList: [], | |||||
isShop: true | |||||
}) | |||||
tt.showLoading({ | |||||
title: '加载中...', | |||||
}); | |||||
this.getCouponChannelId(false) | |||||
}, | |||||
}) | }) |
@@ -1,3 +1,6 @@ | |||||
{ | { | ||||
"navigationBarTitleText": "门店选择", | |||||
"navigationBarBackgroundColor": "#fff", | |||||
"navigationBarTextStyle": "black", | |||||
"usingComponents": {} | "usingComponents": {} | ||||
} | } |
@@ -3,6 +3,7 @@ page { | |||||
font-size: 30rpx; | font-size: 30rpx; | ||||
box-sizing: border-box !important; | box-sizing: border-box !important; | ||||
background-color: #fff; | background-color: #fff; | ||||
padding-bottom: 0; | |||||
.continer { | .continer { | ||||
width: 95%; | width: 95%; | ||||
@@ -47,6 +48,13 @@ page { | |||||
.img { | .img { | ||||
width: 30%; | width: 30%; | ||||
height: 170rpx; | height: 170rpx; | ||||
border-radius: 15rpx; | |||||
overflow: hidden; | |||||
image { | |||||
width: 100%; | |||||
height: 100%; | |||||
} | |||||
} | } | ||||
.infoBox { | .infoBox { | ||||
@@ -64,6 +72,33 @@ page { | |||||
text-overflow: ellipsis; | text-overflow: ellipsis; | ||||
} | } | ||||
} | } | ||||
.infoBox2 { | |||||
display: flex; | |||||
justify-content: space-between; | |||||
flex-direction: column; | |||||
width: 65%; | |||||
margin-left: 20rpx; | |||||
padding: 30rpx 0; | |||||
.infoItem { | |||||
width: 100%; | |||||
white-space: nowrap; | |||||
overflow: hidden; | |||||
text-overflow: ellipsis; | |||||
} | |||||
} | |||||
} | |||||
.takeingPlace { | |||||
text-align: center; | |||||
margin-top: 30rpx; | |||||
.title { | |||||
font-size: 45rpx; | |||||
color: #00000075; | |||||
margin-bottom: 40rpx; | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -82,11 +117,34 @@ page { | |||||
border-radius: 15rpx; | border-radius: 15rpx; | ||||
} | } | ||||
} | } | ||||
.notice { | |||||
font-size: 40rpx; | |||||
padding: 0 15rpx; | |||||
margin-bottom: 30rpx; | |||||
} | |||||
.indexList { | |||||
padding: 0 15rpx; | |||||
box-sizing: border-box; | |||||
margin-bottom: 25rpx; | |||||
.title { | |||||
font-size: 40rpx; | |||||
} | |||||
.item { | |||||
font-size: 36rpx; | |||||
height: 80rpx; | |||||
line-height: 80rpx; | |||||
border-bottom: 1px solid #0000003b; | |||||
} | |||||
} | |||||
} | } | ||||
.indexBar { | .indexBar { | ||||
position: fixed; | position: fixed; | ||||
top: 10%; | |||||
top: 5%; | |||||
right: 3%; | right: 3%; | ||||
font-size: 25rpx; | font-size: 25rpx; | ||||
text-align: center; | text-align: center; | ||||
@@ -96,14 +154,48 @@ page { | |||||
border-radius: 30rpx; | border-radius: 30rpx; | ||||
.indexBarItem { | .indexBarItem { | ||||
position: relative; | |||||
width: 50rpx; | width: 50rpx; | ||||
height: 42rpx; | |||||
color: #ffffff; | color: #ffffff; | ||||
margin-bottom: 10rpx; | |||||
transition: all 0.3s; | transition: all 0.3s; | ||||
&.active { | &.active { | ||||
color: #f92672; | color: #f92672; | ||||
} | } | ||||
.tag { | |||||
position: absolute; | |||||
left: -210%; | |||||
top: 0; | |||||
width: 110rpx; | |||||
height: 60rpx; | |||||
text-align: center; | |||||
transform: scale(1.3); | |||||
} | |||||
.name { | |||||
position: relative; | |||||
top: -11rpx; | |||||
left: 10rpx; | |||||
display: inline-block; | |||||
height: 50rpx; | |||||
line-height: 50rpx; | |||||
color: #ffffff; | |||||
background-color: #8a8a8a; | |||||
border-radius: 15rpx; | |||||
padding: 0 20rpx; | |||||
} | |||||
.tran { | |||||
display: inline-block; | |||||
width: 0; | |||||
height: 0; | |||||
border-top: 20rpx solid #ffffff00; | |||||
border-bottom: 20rpx solid #ffffff00; | |||||
border-left: 20rpx solid #8a8a8a; | |||||
border-right: 20rpx solid #ffffff00; | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -2,17 +2,32 @@ | |||||
<view class="continer"> | <view class="continer"> | ||||
<view tt:if="{{ isShop }}" class="selectShop"> | <view tt:if="{{ isShop }}" class="selectShop"> | ||||
<view class="nav"> | <view class="nav"> | ||||
<view class="item">当前城市:武汉</view> | |||||
<view tt:if="{{ currentCity }}" class="item">当前城市:{{ currentCity }}</view> | |||||
<view tt:if="{{ !currentCity }}" class="item">定位失败</view> | |||||
<view class="item" bindtap="selectCity">切换城市</view> | <view class="item" bindtap="selectCity">切换城市</view> | ||||
</view> | </view> | ||||
<view class="shopList"> | |||||
<view class="item" tt:for="{{ tagArr }}"> | |||||
<image class="img" src="../../assets/itemImg/Audi-RS7.png"></image> | |||||
<view class="infoBox"> | |||||
<view class="infoItem">家帮汇沧州店</view> | |||||
<view class="infoItem">地址:湖北省汉川市仙女山街道办事处仙女大道100号1栋城北建筑公司1单元501室</view> | |||||
<view class="infoItem">距您0.2km</view> | |||||
<view tt:if="{{ mallList.length > 0 }}" class="shopList"> | |||||
<view class="item" tt:for="{{ mallList }}" tt:key="index" bindtap="goSetShop" data-item="{{ item }}"> | |||||
<view class="img"> | |||||
<image src="{{ item.merchantImgUrl }}"></image> | |||||
</view> | </view> | ||||
<view tt:if="{{ item.distance_str }}" class="infoBox"> | |||||
<view class="infoItem">{{ item.merchantName }}</view> | |||||
<view class="infoItem">地址:{{ item.addr }}</view> | |||||
<view class="infoItem">距您 {{ item.distance_str }}</view> | |||||
</view> | |||||
<view tt:if="{{ !item.distance_str }}" class="infoBox2"> | |||||
<view class="infoItem">{{ item.merchantName }}</view> | |||||
<view class="infoItem">地址:{{ item.addr }}</view> | |||||
</view> | |||||
</view> | |||||
</view> | |||||
<view tt:if="{{ mallList.length <= 0 }}" class="shopList"> | |||||
<view class="takeingPlace"> | |||||
<view class="title">该城市暂无可用门店哦</view> | |||||
<image src="../../assets/itemImg/place.png"></image> | |||||
</view> | </view> | ||||
</view> | </view> | ||||
</view> | </view> | ||||
@@ -21,10 +36,30 @@ | |||||
<view class="nav"> | <view class="nav"> | ||||
<view class="item" bindtap="selectShop">返回</view> | <view class="item" bindtap="selectShop">返回</view> | ||||
</view> | </view> | ||||
<view class="notice">请选择您所在城市</view> | |||||
<scroll-view scroll-y="{{true}}" style="height:1400rpx;" scroll-with-animation="{{true}}" | |||||
upper-threshold="{{50}}" lower-threshold="{{50}}" scroll-into-view="{{toView}}"> | |||||
<view tt:for="{{ tagArr }}" tt:key="index" class="indexList" id="{{ item }}"> | |||||
<view class="title">{{ item }}</view> | |||||
<view class="item" bindtap="goFindShop" data-name="北京市">北京市</view> | |||||
<view class="item" bindtap="goFindShop" data-name="武汉市">武汉市</view> | |||||
<view class="item" bindtap="goFindShop" data-name="天津市">天津市</view> | |||||
<view class="item" bindtap="goFindShop" data-name="石家庄市">石家庄市</view> | |||||
<view class="item" bindtap="goFindShop" data-name="济南市">济南市</view> | |||||
<view class="item" bindtap="goFindShop" data-name="长沙市">长沙市</view> | |||||
</view> | |||||
</scroll-view> | |||||
</view> | </view> | ||||
<view tt:if="{{ !isShop }}" class="indexBar" catchtouchmove="indexBarMove"> | <view tt:if="{{ !isShop }}" class="indexBar" catchtouchmove="indexBarMove"> | ||||
<view class="{{ currentTag == item ? 'indexBarItem active' : 'indexBarItem' }}" tt:for="{{ tagArr }}" | <view class="{{ currentTag == item ? 'indexBarItem active' : 'indexBarItem' }}" tt:for="{{ tagArr }}" | ||||
tt:key="index" id="{{ item }}" bindtap="tagBind">{{ | |||||
item }}</view> | |||||
tt:key="index" id="{{ item }}" bindtap="tagBind">{{ item }} | |||||
<view tt:if="{{ currentTag==item }}" class="tag"> | |||||
<view class="name">{{ item }}</view> | |||||
<view class="tran"></view> | |||||
</view> | |||||
</view> | |||||
</view> | </view> | ||||
</view> | </view> |
@@ -3,6 +3,7 @@ page { | |||||
font-size: 30rpx; | font-size: 30rpx; | ||||
box-sizing: border-box !important; | box-sizing: border-box !important; | ||||
background-color: #fff; | background-color: #fff; | ||||
padding-bottom: 0; | |||||
} | } | ||||
page .continer { | page .continer { | ||||
width: 95%; | width: 95%; | ||||
@@ -44,6 +45,12 @@ page .continer .selectShop .shopList .item { | |||||
page .continer .selectShop .shopList .item .img { | page .continer .selectShop .shopList .item .img { | ||||
width: 30%; | width: 30%; | ||||
height: 170rpx; | height: 170rpx; | ||||
border-radius: 15rpx; | |||||
overflow: hidden; | |||||
} | |||||
page .continer .selectShop .shopList .item .img image { | |||||
width: 100%; | |||||
height: 100%; | |||||
} | } | ||||
page .continer .selectShop .shopList .item .infoBox { | page .continer .selectShop .shopList .item .infoBox { | ||||
display: flex; | display: flex; | ||||
@@ -59,6 +66,29 @@ page .continer .selectShop .shopList .item .infoBox .infoItem { | |||||
overflow: hidden; | overflow: hidden; | ||||
text-overflow: ellipsis; | text-overflow: ellipsis; | ||||
} | } | ||||
page .continer .selectShop .shopList .item .infoBox2 { | |||||
display: flex; | |||||
justify-content: space-between; | |||||
flex-direction: column; | |||||
width: 65%; | |||||
margin-left: 20rpx; | |||||
padding: 30rpx 0; | |||||
} | |||||
page .continer .selectShop .shopList .item .infoBox2 .infoItem { | |||||
width: 100%; | |||||
white-space: nowrap; | |||||
overflow: hidden; | |||||
text-overflow: ellipsis; | |||||
} | |||||
page .continer .selectShop .shopList .takeingPlace { | |||||
text-align: center; | |||||
margin-top: 30rpx; | |||||
} | |||||
page .continer .selectShop .shopList .takeingPlace .title { | |||||
font-size: 45rpx; | |||||
color: #00000075; | |||||
margin-bottom: 40rpx; | |||||
} | |||||
page .continer .selectCity .nav { | page .continer .selectCity .nav { | ||||
margin-bottom: 20rpx; | margin-bottom: 20rpx; | ||||
padding: 0 20rpx; | padding: 0 20rpx; | ||||
@@ -71,9 +101,28 @@ page .continer .selectCity .nav .item { | |||||
background-image: linear-gradient(to top, #48c6ef 0%, #6f86d6 100%); | background-image: linear-gradient(to top, #48c6ef 0%, #6f86d6 100%); | ||||
border-radius: 15rpx; | border-radius: 15rpx; | ||||
} | } | ||||
page .continer .selectCity .notice { | |||||
font-size: 40rpx; | |||||
padding: 0 15rpx; | |||||
margin-bottom: 30rpx; | |||||
} | |||||
page .continer .selectCity .indexList { | |||||
padding: 0 15rpx; | |||||
box-sizing: border-box; | |||||
margin-bottom: 25rpx; | |||||
} | |||||
page .continer .selectCity .indexList .title { | |||||
font-size: 40rpx; | |||||
} | |||||
page .continer .selectCity .indexList .item { | |||||
font-size: 36rpx; | |||||
height: 80rpx; | |||||
line-height: 80rpx; | |||||
border-bottom: 1px solid #0000003b; | |||||
} | |||||
page .continer .indexBar { | page .continer .indexBar { | ||||
position: fixed; | position: fixed; | ||||
top: 10%; | |||||
top: 5%; | |||||
right: 3%; | right: 3%; | ||||
font-size: 25rpx; | font-size: 25rpx; | ||||
text-align: center; | text-align: center; | ||||
@@ -83,11 +132,42 @@ page .continer .indexBar { | |||||
border-radius: 30rpx; | border-radius: 30rpx; | ||||
} | } | ||||
page .continer .indexBar .indexBarItem { | page .continer .indexBar .indexBarItem { | ||||
position: relative; | |||||
width: 50rpx; | width: 50rpx; | ||||
height: 42rpx; | |||||
color: #ffffff; | color: #ffffff; | ||||
margin-bottom: 10rpx; | |||||
transition: all 0.3s; | transition: all 0.3s; | ||||
} | } | ||||
page .continer .indexBar .indexBarItem.active { | page .continer .indexBar .indexBarItem.active { | ||||
color: #f92672; | color: #f92672; | ||||
} | } | ||||
page .continer .indexBar .indexBarItem .tag { | |||||
position: absolute; | |||||
left: -210%; | |||||
top: 0; | |||||
width: 110rpx; | |||||
height: 60rpx; | |||||
text-align: center; | |||||
transform: scale(1.3); | |||||
} | |||||
page .continer .indexBar .indexBarItem .name { | |||||
position: relative; | |||||
top: -11rpx; | |||||
left: 10rpx; | |||||
display: inline-block; | |||||
height: 50rpx; | |||||
line-height: 50rpx; | |||||
color: #ffffff; | |||||
background-color: #8a8a8a; | |||||
border-radius: 15rpx; | |||||
padding: 0 20rpx; | |||||
} | |||||
page .continer .indexBar .indexBarItem .tran { | |||||
display: inline-block; | |||||
width: 0; | |||||
height: 0; | |||||
border-top: 20rpx solid #ffffff00; | |||||
border-bottom: 20rpx solid #ffffff00; | |||||
border-left: 20rpx solid #8a8a8a; | |||||
border-right: 20rpx solid #ffffff00; | |||||
} |
@@ -1,7 +1,7 @@ | |||||
{ | { | ||||
"condition": { | "condition": { | ||||
"miniprogram": { | "miniprogram": { | ||||
"current": 1688192851587, | |||||
"current": -1, | |||||
"list": [ | "list": [ | ||||
{ | { | ||||
"id": 1678508631604, | "id": 1678508631604, | ||||
@@ -58,10 +58,10 @@ | |||||
"location": "audit" | "location": "audit" | ||||
}, | }, | ||||
{ | { | ||||
"id": 1688192851587, | |||||
"id": 1688290922168, | |||||
"name": "pages2/shopSelect/shopSelect", | "name": "pages2/shopSelect/shopSelect", | ||||
"pathName": "pages2/shopSelect/shopSelect", | "pathName": "pages2/shopSelect/shopSelect", | ||||
"query": "", | |||||
"query": "id=835370938545004544&orderId=835370938545004544&merOrderId=835370895208669184&startTime=2023-07-02&endTime=2023-08-30", | |||||
"scene": "990001", | "scene": "990001", | ||||
"launchFrom": "scan", | "launchFrom": "scan", | ||||
"location": "qr_code" | "location": "qr_code" | ||||