import Taro from '@tarojs/taro'; import { isNaN } from 'lodash-es'; import { CITY_CODE_TO_NAME_MAP, COUNTY_CODE_TO_NAME_MAP, PROVINCE_CODE_TO_NAME_MAP } from '@/constants/city'; import http from '@/http'; import { API } from '@/http/api'; import store from '@/store'; import { setLocationInfo, setCityOperators } from '@/store/actions'; import { selectLocation } from '@/store/selector'; import { CityOperatorListItem, GetCityCodeRequest, LocationInfo } from '@/types/location'; import { authorize, getWxSetting } from './wx'; let locationInfo: Taro.getLocation.SuccessCallbackResult | null = null; let waitAuthorizeLocationPromise: ReturnType | null = null; const VALID_DISTANCE_KM = 999; export const isValidLocation = (location: LocationInfo) => { if (!location) { return false; } return !isNaN(Number(location.latitude)) && !isNaN(Number(location.longitude)); }; export const isValidDistance = (distance: number) => distance < 1000 * VALID_DISTANCE_KM; export const isNotNeedAuthorizeLocation = () => getWxSetting('scope.userLocation'); export const calcDistance = (distance: number, fractionDigits = 2) => { if (isValidDistance(distance)) { return `${(distance / 1000).toFixed(fractionDigits)}km`; } return '999km'; }; export const getCurrentCityCode = () => { return selectLocation(store.getState()).cityCode; }; export const getCurrentCity = () => { const cityCode = getCurrentCityCode(); return CITY_CODE_TO_NAME_MAP.get(cityCode) || ''; }; export const getCityValues = (codes: string[] = [], separator: string = '') => { const [province, city, county] = codes; const values: string[] = []; if (province) { const v = PROVINCE_CODE_TO_NAME_MAP.get(province); v && values.push(v); } if (city) { const v = CITY_CODE_TO_NAME_MAP.get(city); v && values.push(v); } if (county) { const v = COUNTY_CODE_TO_NAME_MAP.get(county); v && values.push(v); } return values.join(separator); }; export async function waitLocationAuthorizeHidden() { if (!waitAuthorizeLocationPromise) { return; } await waitAuthorizeLocationPromise; } /** * 获取经纬度信息 * @param opts * @returns */ export async function getWxLocation( opts?: Taro.getLocation.Option, force = true ): Promise { if (locationInfo?.latitude) return Promise.resolve(locationInfo); const notNeedAuthorize = await isNotNeedAuthorizeLocation(); if (!notNeedAuthorize) { waitAuthorizeLocationPromise = authorize('scope.userLocation', '请授权获取位置权限', force); if (!(await waitAuthorizeLocationPromise)) { return null; } } // 重新获取位置信息 return new Promise(resolve => { try { Taro.getLocation({ type: 'wgs84', ...opts, success: res => { setTimeout(() => { locationInfo = null; }, 31000); if (res?.latitude) { locationInfo = res; return resolve(res); } resolve(null); }, fail: () => resolve(null), }); } catch (e) { console.error(e); } }); } export async function requestLocation(force: boolean = false) { const data = {} as GetCityCodeRequest; const lgInfo = await getWxLocation({}, force); if (!lgInfo) { return; } if (lgInfo?.latitude && lgInfo?.longitude) { data.latitude = lgInfo.latitude; data.longitude = lgInfo.longitude; } const location = await http.post(API.LOCATION, { data, contentType: 'application/x-www-form-urlencoded', }); if (!location.latitude) { location.latitude = data.latitude; } if (!location.longitude) { location.longitude = data.longitude; } store.dispatch(setLocationInfo(location)); return location; } export async function requestCityOperators() { const list = await http.get(API.GET_ALL_CITY_OPERATOR); store.dispatch( setCityOperators( (list || []).map(it => ({ cityCode: it.cityCode, groupLink: it.groupLink, })) ) ); }