457 lines
12 KiB
Vue
457 lines
12 KiB
Vue
<template>
|
||
<view class="container" :class="[`${themeInfo.theme}-theme`, `${themeInfo.language}`]">
|
||
<view class="header-wrap">
|
||
<wxNavbar :title="$t('tabbar.book')"></wxNavbar>
|
||
<!-- 头部的筛选 -->
|
||
<view class="header">
|
||
<view class="header-text" @click="open">
|
||
<uv-icon name="dropdown" custom-prefix="custom-icon" size="16" :color="themeInfo.iconColor"></uv-icon>
|
||
{{ $t("book.location") }}: {{ popupData.selectCity }}
|
||
</view>
|
||
<view class="header-text" @click="tomapMode">
|
||
{{ $t("book.map") }}
|
||
<uv-icon name="setting1" custom-prefix="custom-icon" size="16" :color="themeInfo.iconColor"></uv-icon>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<!-- location窗口 -->
|
||
<uv-overlay :show="popupData.show" @click="open" z-index="99" >
|
||
<view class="location-popup">
|
||
<view class="select-area-wrap" :style="{ 'margin-top': `${state.navHeight}px` }" @click.stop.prevent>
|
||
<view class="city inner-wrap">
|
||
<view class="top-wrap">
|
||
<uv-icon name="halfArrow" custom-prefix="custom-icon" size="16" color="#0F2232"></uv-icon>
|
||
<text class="text">{{ $t("book.city") }}</text>
|
||
</view>
|
||
<view class="select-wrap">
|
||
<view
|
||
class="select-item"
|
||
v-for="(item, index) in popupData.cityData"
|
||
:key="index"
|
||
:class="{ select: item === popupData.selectCity }"
|
||
@click="handleCity(item)">
|
||
<view class="circle"></view>
|
||
<view class="name">{{ item }}</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="border"></view>
|
||
<view class="area inner-wrap">
|
||
<view class="top-wrap">
|
||
<uv-icon name="halfArrow" custom-prefix="custom-icon" size="16" color="#0F2232"></uv-icon>
|
||
<text class="text">{{ $t("book.area") }}</text>
|
||
</view>
|
||
<view class="select-wrap">
|
||
<view
|
||
class="select-item"
|
||
v-for="(item, index) in popupData.areaData"
|
||
:key="index"
|
||
:class="{ select: item === popupData.selectDistrict }"
|
||
@click="handleDistrict(item)">
|
||
<view class="circle"></view>
|
||
<view class="name">{{ item }}</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</uv-overlay>
|
||
|
||
<!-- 热推门店详情 -->
|
||
<view class="get-location-wrap" @click="handleAuthorize" v-if="locationState.showGetLocation">
|
||
{{ $t("book.get") }}
|
||
</view>
|
||
<view :style="{ 'margin-top': `${state.navHeight}px` }" class="shopDetail" v-if="siteData.list?.length">
|
||
<siteDetail v-for="item in siteData.list" :key="item.id" :siteItem="item" @showCode="handleShowCode"></siteDetail>
|
||
</view>
|
||
<view class="footer">
|
||
<myCustomtTabBar direction="horizontal" :show-icon="true" :selected="2" @onTabItemTap="onTabItemTap" />
|
||
</view>
|
||
<!-- 门禁二维码 -->
|
||
<myPopup v-model="state.showQrcode" bgColor="transparent">
|
||
<view class="qrcode-wrap">
|
||
<view class="get-code-btn" v-show="!state.qrcodeUrl">
|
||
<uv-button @click="GetQRCode">
|
||
{{ $t("book.getCode") }}
|
||
</uv-button>
|
||
</view>
|
||
<image class="qrcodeImg" :src="state.qrcodeUrl"></image>
|
||
</view>
|
||
<view class="btn-wrap">
|
||
<uv-button @click="RemoteOpenDoor" :loading="state.openDoorLoading" :loadingText="t('unlock.remoteOpenLoading')">{{ state.openDoorText }}</uv-button>
|
||
</view>
|
||
</myPopup>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, reactive } from "vue";
|
||
import { onLoad, onShow, onHide, onShareAppMessage} from "@dcloudio/uni-app";
|
||
import { onTabItemTap, getDistance, navbarHeightAndStatusBarHeight,shareParam,mergeFiveGoatStores } from "@/utils/common.js";
|
||
import { ClientSite } from "@/Apis/book.js";
|
||
import wxNavbar from "@/components/wxNavbar.vue";
|
||
import myCustomtTabBar from "@/components/myCustomtTabBar.vue";
|
||
import siteDetail from '@/components/siteDetail.vue';
|
||
import myPopup from '@/components/myPopup.vue';
|
||
import { useLockApi } from '@/Apis/lock.js';
|
||
import { AppId } from '@/config/index.js'
|
||
|
||
// 主题色配置
|
||
import { useMainStore } from "@/store/index.js";
|
||
const { themeInfo, storeState } = useMainStore();
|
||
import { useI18n } from 'vue-i18n';
|
||
const { t } = useI18n();
|
||
import { useLocation } from "@/hooks/useLocation";
|
||
const { locationState, openLocationAuthorize, getLocation } = useLocation();
|
||
const getLockApi = useLockApi();
|
||
const getApi = ClientSite();
|
||
const state = reactive({
|
||
navHeight: 0,
|
||
showQrcode: false,
|
||
qrcodeUrl: '',
|
||
firstLoad: false,
|
||
openDoorLoading: false,
|
||
clickItem: {},
|
||
openDoorText: t('unlock.remoteOpen'),
|
||
});
|
||
onShareAppMessage((res) => {
|
||
if (res.from === "button") {
|
||
// 来自页面内分享按钮
|
||
console.log(res.target);
|
||
}
|
||
return shareParam;
|
||
});
|
||
onLoad(() => {
|
||
uni.hideTabBar();
|
||
state.navHeight = Number(navbarHeightAndStatusBarHeight().navbarHeight) + 50;
|
||
// 获取城市数据
|
||
getCityData();
|
||
state.firstLoad = true;
|
||
// 小红书onshow第一次 不会触发
|
||
// #ifdef MP-XHS
|
||
getLocation().finally(() => {
|
||
getSiteDetail();
|
||
// #ifndef MP-WEIXIN
|
||
locationState.showGetLocation = false;
|
||
// #endif
|
||
});
|
||
// #endif
|
||
});
|
||
onShow(() => {
|
||
getLocation().finally(() => {
|
||
getSiteDetail();
|
||
// #ifndef MP-WEIXIN
|
||
locationState.showGetLocation = false;
|
||
// #endif
|
||
});
|
||
});
|
||
onHide(() => {
|
||
state.firstLoad = false;
|
||
});
|
||
|
||
/**
|
||
* 开门功能相关
|
||
*/
|
||
const handleShowCode = (item) => {
|
||
state.clickItem = item;
|
||
state.showQrcode = true;
|
||
state.qrcodeUrl = '';
|
||
}
|
||
|
||
// 远程开门
|
||
const RemoteOpenDoor = () => {
|
||
if (!state.clickItem?.id || state.openDoorLoading) return;
|
||
state.openDoorLoading = true;
|
||
getLockApi.RemoteOpenDoor({ siteId: state.clickItem.id }).then(res => {
|
||
state.openDoorLoading = false;
|
||
if (res.code === 200) {
|
||
uni.showToast({
|
||
title: t('unlock.remoteOpenSuccess'),
|
||
icon: 'none'
|
||
});
|
||
state.openDoorText = t('unlock.remoteOpenSuccess');
|
||
setTimeout(() => {
|
||
state.openDoorText = t('unlock.remoteOpen');
|
||
}, 3000);
|
||
} else {
|
||
uni.showToast({
|
||
title: t('unlock.remoteOpenFail'),
|
||
icon: 'none'
|
||
});
|
||
}
|
||
});
|
||
}
|
||
|
||
// 获取二维码
|
||
const GetQRCode = () => {
|
||
if (!state.clickItem?.id) return;
|
||
uni.showLoading();
|
||
getLockApi.GetAccesscontrolQRCodeBySite({ siteId: state.clickItem.id }).then(res => {
|
||
if (res.code === 200) {
|
||
state.qrcodeUrl = res.data;
|
||
}
|
||
uni.hideLoading();
|
||
});
|
||
}
|
||
|
||
// 跳转到地图页
|
||
const tomapMode = ()=>{
|
||
uni.navigateTo({
|
||
url: "/pages/book/mapmode"
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 顶部popup 相关功能
|
||
*/
|
||
const popupData = reactive({
|
||
show: false,
|
||
selectCity: "",
|
||
selectDistrict: "",
|
||
cityData: [],
|
||
areaData: [],
|
||
});
|
||
const open = () => {
|
||
popupData.show = !popupData.show;
|
||
}
|
||
const getCityData = () => {
|
||
getApi.GetCityAll().then(res => {
|
||
if(res.code === 200) {
|
||
popupData.cityData = res.data;
|
||
popupData.cityData.unshift("全部");
|
||
// 首次直接选择全部
|
||
popupData.selectCity = popupData.cityData[0];
|
||
}
|
||
})
|
||
}
|
||
const handleCity = (city) => {
|
||
popupData.selectCity = city;
|
||
if (city === "全部") {
|
||
popupData.areaData = ["全部"];
|
||
popupData.selectDistrict = "全部";
|
||
getSiteDetail();
|
||
} else {
|
||
getApi.GetDistrictByCity(city).then(res => {
|
||
if (res.code === 200) {
|
||
popupData.areaData = res.data;
|
||
popupData.areaData.unshift("全部");
|
||
popupData.selectDistrict = popupData.areaData[0];
|
||
}
|
||
|
||
let currentCity = city === "全部" ? "" : city;
|
||
getSiteDetail(currentCity, "");
|
||
});
|
||
}
|
||
}
|
||
const handleDistrict = (item) => {
|
||
popupData.selectDistrict = item;
|
||
let currentCity = popupData.selectCity === "全部" ? "" : popupData.selectCity;
|
||
let district = item === "全部" ? "" : item;
|
||
getSiteDetail(currentCity, district);
|
||
}
|
||
let siteData = reactive({
|
||
list: [],
|
||
isLoading: false,
|
||
});
|
||
// 获取门店信息
|
||
const getSiteDetail = (city, district,isAll) => {
|
||
if (siteData.isLoading) return;
|
||
// #ifdef MP-WEIXIN
|
||
// if (locationState.showGetLocation) {
|
||
// uni.showToast({
|
||
// title: t("book.getSite"),
|
||
// icon: "none",
|
||
// duration: 2000
|
||
// });
|
||
// return;
|
||
// }
|
||
// #endif
|
||
uni.showLoading();
|
||
siteData.isLoading = true;
|
||
let getCity = city || "";
|
||
let getDistrict = district || "";
|
||
if (!city) {
|
||
getCity = popupData.selectCity == "全部" ? "" : popupData.selectCity;
|
||
getDistrict = popupData.selectDistrict == "全部" ? "" : popupData.selectDistrict;
|
||
}
|
||
if(isAll){
|
||
getCity = "";
|
||
getDistrict = "";
|
||
}
|
||
getApi.getSiteDetailsAll({
|
||
city: getCity,
|
||
district: getDistrict
|
||
}).then(res => {
|
||
if (res.code === 200) {
|
||
siteData.list = mergeFiveGoatStores(res.data);
|
||
if (locationState?.latitude && locationState?.longitude) {
|
||
const { latitude, longitude } = locationState;
|
||
siteData.list.forEach(item => {
|
||
const { distance, number } = getDistance(latitude, longitude, item.latitude, item.longitude);
|
||
item.distance = distance;
|
||
item.distanceNumber = number;
|
||
});
|
||
siteData.list.sort((a, b) => a.distanceNumber - b.distanceNumber);
|
||
if (state.firstLoad) filterSiteData();
|
||
}else {
|
||
// 如果是金刚就不是显示全部
|
||
if(AppId === 'wxb20921dfdd0b94f4' || AppId === 'wx3c4ab696101d77d1') {
|
||
if (state.firstLoad) filterSiteData(true);
|
||
}
|
||
}
|
||
}
|
||
uni.hideLoading();
|
||
siteData.isLoading = false;
|
||
}).catch(err => {
|
||
uni.hideLoading();
|
||
siteData.isLoading = false;
|
||
});
|
||
}
|
||
const handleAuthorize = () => {
|
||
openLocationAuthorize().then(res => {
|
||
state.firstLoad = true;
|
||
if (res) getSiteDetail('全部','全部',true);
|
||
});
|
||
}
|
||
// 首次只显示距离最近的城市 noLocation 沒有定位的情况下顯示深圳
|
||
const filterSiteData = (noLocation) => {
|
||
state.firstLoad = false;
|
||
if (!siteData.list.length) return;
|
||
let city = siteData.list[0]['city'];
|
||
// 如果是金刚的appid,默认显示深圳的门店
|
||
if(noLocation){
|
||
if(AppId === 'wxb20921dfdd0b94f4' || AppId === 'wx3c4ab696101d77d1') {
|
||
city = siteData.list.find(item => item.city.indexOf("深圳") !== -1)?.city;
|
||
}
|
||
}
|
||
siteData.list = siteData.list.filter((item) => item.city.indexOf(city) !== -1);
|
||
popupData.selectCity = city;
|
||
getApi.GetDistrictByCity(city).then(res => {
|
||
if (res.code === 200) {
|
||
popupData.areaData = res.data;
|
||
popupData.areaData.unshift("全部");
|
||
popupData.selectDistrict = popupData.areaData[0];
|
||
}
|
||
});
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
@import '@/static/style/theme.scss';
|
||
.container {
|
||
width: 100%;
|
||
margin: 0;
|
||
padding: 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
|
||
.qrcode-wrap {
|
||
position: relative;
|
||
width: 100%;
|
||
text-align: center;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border-radius: 18rpx;
|
||
|
||
.get-code-btn {
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
}
|
||
|
||
.qrcodeImg {
|
||
background-color: #FFFFFF;
|
||
height: 600rpx;
|
||
width: 600rpx;
|
||
}
|
||
}
|
||
|
||
.btn-wrap {
|
||
width: 600rpx;
|
||
margin: 0 auto;
|
||
margin-top: 40rpx;
|
||
}
|
||
|
||
.qrcode-wrap,
|
||
.btn-wrap {
|
||
::v-deep .uv-button {
|
||
color: var(--text-color);
|
||
background-color: var(--btn-color1);
|
||
border: none;
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
text-justify: 20rpx;
|
||
|
||
.uv-button__loading-text {
|
||
font-size: 32rpx!important;
|
||
font-weight: bold;
|
||
text-justify: 20rpx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.header-wrap {
|
||
position: fixed;
|
||
width: 100%;
|
||
background: linear-gradient(to bottom, var(--left-linear), var(--right-linear));
|
||
z-index: 999;
|
||
|
||
::v-deep .wxNavbar {
|
||
background: transparent !important;
|
||
}
|
||
}
|
||
// 头部的筛选
|
||
.header {
|
||
height: 50px;
|
||
width: 100%;
|
||
padding: 0 40rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
|
||
.header-text {
|
||
font-size: 28rpx;
|
||
font-weight: bold;
|
||
display: flex;
|
||
align-items: center;
|
||
color: var(--whiteOrBlack);
|
||
|
||
& > .header-icon {
|
||
width: 28rpx;
|
||
height: 28rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 门店列表
|
||
.shopDetail {
|
||
width: 100%;
|
||
margin-bottom: 300rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
}
|
||
|
||
.get-location-wrap {
|
||
position: fixed;
|
||
height: 74rpx;
|
||
background-color: var(--main-color);
|
||
border-radius: 45rpx 0rpx 0rpx 45rpx;
|
||
border: 4rpx solid var(--stress-text);
|
||
box-shadow: 0rpx 4rpx 10rpx 0rpx rgba(0, 0, 0, 0.1);
|
||
right: -4px;
|
||
top: 75%;
|
||
padding: 0 20rpx 0 30rpx;
|
||
z-index: 9;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
color: var(--stress-text);
|
||
font-size: 28rpx;
|
||
font-weight: 700;
|
||
}
|
||
</style>
|