311 lines
9.7 KiB
TypeScript
311 lines
9.7 KiB
TypeScript
// 地理位置逆编码
|
|
import i18n from '@/i18n';
|
|
import { PermissionService } from '@/lib/PermissionService';
|
|
import { fetchApi } from '@/lib/server-api-util';
|
|
import * as ImagePicker from 'expo-image-picker';
|
|
import * as Location from 'expo-location';
|
|
import * as Notifications from 'expo-notifications';
|
|
import * as SecureStore from 'expo-secure-store';
|
|
import { Linking, Platform } from 'react-native';
|
|
|
|
interface Address {
|
|
id: number;
|
|
name: string;
|
|
// Add other address properties as needed
|
|
}
|
|
|
|
// 配置通知处理器
|
|
Notifications.setNotificationHandler({
|
|
handleNotification: async () => ({
|
|
shouldShowAlert: true,
|
|
shouldPlaySound: true,
|
|
shouldSetBadge: false,
|
|
shouldShowBanner: true,
|
|
shouldShowList: true,
|
|
}),
|
|
});
|
|
|
|
// 逆编码
|
|
export const reverseGeocode = async (latitude: number, longitude: number) => {
|
|
try {
|
|
const addressResults = await fetchApi<Address[]>(`/area/gecoding?latitude=${latitude}&longitude=${longitude}`);
|
|
if (Object.keys(addressResults).length === 0) {
|
|
return null;
|
|
}
|
|
console.log('地址1:', addressResults);
|
|
|
|
if (Platform.OS === 'web') {
|
|
localStorage.setItem('location', JSON.stringify(addressResults));
|
|
} else {
|
|
SecureStore.setItemAsync('location', JSON.stringify(addressResults));
|
|
}
|
|
return addressResults
|
|
} catch (error) {
|
|
console.log('逆地理编码失败:', error);
|
|
}
|
|
};
|
|
|
|
// 获取位置权限
|
|
export const getLocationPermission = async () => {
|
|
const { status } = await Location.getForegroundPermissionsAsync();
|
|
if (status !== 'granted') {
|
|
// Alert.alert('需要位置权限', '请允许访问位置以继续');
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
// 请求位置权限
|
|
export const requestLocationPermission = async () => {
|
|
try {
|
|
// 1. 先检查当前权限状态
|
|
const { status, canAskAgain } = await Location.getForegroundPermissionsAsync();
|
|
console.log('当前权限状态:', { status, canAskAgain });
|
|
console.log("canAskAgain", canAskAgain);
|
|
|
|
// 2. 如果已经有权限,直接返回
|
|
if (status === 'granted') {
|
|
return true;
|
|
}
|
|
|
|
// 3. 如果用户之前选择了"拒绝且不再询问"
|
|
if (status === 'denied' && !canAskAgain) {
|
|
// 显示提示,引导用户去设置
|
|
const confirmed = await PermissionService.show({
|
|
title: i18n.t('permission:title.locationPermissionRequired'),
|
|
message: i18n.t('permission:message.locationPreviouslyDenied'),
|
|
});
|
|
|
|
if (confirmed) {
|
|
openAppSettings();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// 4. 如果是第一次请求或可以再次询问,则请求权限
|
|
console.log('请求位置权限...');
|
|
const { status: newStatus } = await Location.requestForegroundPermissionsAsync();
|
|
console.log('新权限状态:', newStatus);
|
|
|
|
if (newStatus !== 'granted') {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
} catch (error) {
|
|
console.error('请求位置权限时出错:', error);
|
|
return false;
|
|
}
|
|
};
|
|
|
|
export const openAppSettings = () => {
|
|
Linking.openSettings();
|
|
};
|
|
|
|
// 获取媒体库权限
|
|
export const getPermissions = async () => {
|
|
if (Platform.OS !== 'web') {
|
|
const { status: mediaStatus } = await ImagePicker.getMediaLibraryPermissionsAsync();
|
|
if (mediaStatus !== 'granted') {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
// 请求媒体库权限
|
|
export const requestPermissions = async () => {
|
|
if (Platform.OS !== 'web') {
|
|
const mediaStatus = await ImagePicker.requestMediaLibraryPermissionsAsync();
|
|
if (!mediaStatus.granted) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* 检查相册/媒体库权限
|
|
* @returns 返回权限状态对象
|
|
*/
|
|
export const checkMediaLibraryPermission = async (): Promise<{
|
|
hasPermission: boolean;
|
|
canAskAgain: boolean;
|
|
status: ImagePicker.PermissionStatus;
|
|
}> => {
|
|
if (Platform.OS === 'web') {
|
|
return { hasPermission: true, canAskAgain: true, status: 'granted' };
|
|
}
|
|
|
|
const { status, canAskAgain } = await ImagePicker.getMediaLibraryPermissionsAsync();
|
|
|
|
return {
|
|
hasPermission: status === 'granted',
|
|
canAskAgain,
|
|
status
|
|
};
|
|
};
|
|
|
|
/**
|
|
* 请求相册/媒体库权限
|
|
* @param showAlert 是否在无权限时显示提示
|
|
* @returns 返回是否已授权
|
|
*/
|
|
export const requestMediaLibraryPermission = async (showAlert: boolean = true): Promise<boolean> => {
|
|
if (Platform.OS === 'web') {
|
|
return true;
|
|
}
|
|
|
|
try {
|
|
// 1. 检查当前权限状态
|
|
const { status: existingStatus, canAskAgain } = await checkMediaLibraryPermission();
|
|
|
|
// 2. 如果已经有权限,直接返回
|
|
if (existingStatus === 'granted') {
|
|
return true;
|
|
}
|
|
|
|
// 3. 如果之前被拒绝且不能再次询问
|
|
if (existingStatus === 'denied' && !canAskAgain) {
|
|
if (showAlert) {
|
|
await PermissionService.show({
|
|
title: i18n.t('permission:title.mediaLibraryPermissionRequired'),
|
|
message: i18n.t('permission:message.mediaLibraryPreviouslyDenied'),
|
|
});
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// 4. 请求权限
|
|
const { status: newStatus } = await ImagePicker.requestMediaLibraryPermissionsAsync();
|
|
|
|
if (newStatus !== 'granted' && showAlert) {
|
|
await PermissionService.show({
|
|
title: i18n.t('permission:title.mediaLibraryPermissionRequired'),
|
|
message: i18n.t('permission:message.mediaLibraryPermissionRequired'),
|
|
});
|
|
}
|
|
|
|
return newStatus === 'granted';
|
|
} catch (error) {
|
|
console.error('请求媒体库权限时出错:', error);
|
|
if (showAlert) {
|
|
await PermissionService.show({
|
|
title: i18n.t('permission:title.error'),
|
|
message: i18n.t('permission:message.requestPermissionError'),
|
|
});
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
|
|
// 检查通知权限
|
|
export const checkNotificationPermission = async () => {
|
|
const { status } = await Notifications.getPermissionsAsync();
|
|
console.log('当前通知权限状态:', status);
|
|
|
|
return status === 'granted';
|
|
};
|
|
|
|
// 请求通知权限
|
|
export const requestNotificationPermission = async () => {
|
|
try {
|
|
// 1. 先检查当前权限状态
|
|
const { status, canAskAgain } = await Notifications.getPermissionsAsync();
|
|
console.log('当前通知权限状态:', { status, canAskAgain });
|
|
|
|
// 2. 如果已经有权限,直接返回
|
|
if (status === 'granted') {
|
|
return true;
|
|
}
|
|
|
|
// 3. 如果用户之前选择了"拒绝且不再询问"
|
|
if (status === 'denied' && !canAskAgain) {
|
|
// 显示提示,引导用户去设置
|
|
await PermissionService.show({
|
|
title: i18n.t('permission:title.notificationPermissionRequired'),
|
|
message: i18n.t('permission:message.notificationPreviouslyDenied'),
|
|
});
|
|
return false;
|
|
}
|
|
|
|
// 4. 如果是第一次请求或可以再次询问,则请求权限
|
|
console.log('请求通知权限...');
|
|
const { status: newStatus } = await Notifications.requestPermissionsAsync();
|
|
console.log('新通知权限状态:', newStatus);
|
|
|
|
if (newStatus !== 'granted') {
|
|
PermissionService.show({
|
|
title: '需要通知权限',
|
|
message: '请允许通知以使用此功能',
|
|
});
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
} catch (error) {
|
|
console.error('请求通知权限时出错:', error);
|
|
PermissionService.show({ title: '错误', message: '请求通知权限时出错' });
|
|
return false;
|
|
}
|
|
};
|
|
|
|
// 发送本地通知的辅助函数
|
|
export const sendLocalNotification = async (title: string, body: string, data: Record<string, any> = {}) => {
|
|
try {
|
|
const hasPermission = await checkNotificationPermission();
|
|
if (!hasPermission) {
|
|
const granted = await requestNotificationPermission();
|
|
if (!granted) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
await Notifications.scheduleNotificationAsync({
|
|
content: {
|
|
title,
|
|
body,
|
|
data,
|
|
priority: 'high',
|
|
},
|
|
trigger: null, // 立即触发
|
|
});
|
|
|
|
return true;
|
|
} catch (error) {
|
|
console.error('发送通知时出错:', error);
|
|
return false;
|
|
}
|
|
};
|
|
|
|
|
|
// 获取定位信息 -- 最子集元素
|
|
export function findInnermostElement(data: any[], targetName: string): { name: string; value: any } | null {
|
|
let result: { name: string; value: any } | null = null;
|
|
|
|
function search(nodes: any[]): boolean {
|
|
for (const node of nodes) {
|
|
if (node.name === targetName) {
|
|
result = { name: node.name, value: node.value };
|
|
// Keep searching to see if there's a deeper match
|
|
let foundDeeper = false;
|
|
if (node.children && node.children.length > 0) {
|
|
foundDeeper = search(node.children);
|
|
}
|
|
// If no deeper match was found, this is the innermost one
|
|
if (!foundDeeper) {
|
|
return true;
|
|
}
|
|
} else if (node.children && node.children.length > 0) {
|
|
const found = search(node.children);
|
|
if (found) return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
search(data);
|
|
return result;
|
|
} |