149 lines
4.0 KiB
TypeScript
149 lines
4.0 KiB
TypeScript
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<typeof authorize> | 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<Taro.getLocation.SuccessCallbackResult | null> {
|
|
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<LocationInfo>(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<CityOperatorListItem[]>(API.GET_ALL_CITY_OPERATOR);
|
|
store.dispatch(
|
|
setCityOperators(
|
|
(list || []).map(it => ({
|
|
cityCode: it.cityCode,
|
|
groupLink: it.groupLink,
|
|
}))
|
|
)
|
|
);
|
|
}
|