// 地理位置逆编码 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 { Alert, 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(`/area/gecoding?latitude=${latitude}&longitude=${longitude}`); console.log('地址:', addressResults); for (let address of addressResults) { console.log('地址:', address); if (Platform.OS === 'web') { localStorage.setItem('location', JSON.stringify(address)); } else { SecureStore.setItemAsync('location', JSON.stringify(address)); } return address; } } 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 openSettings = await new Promise(resolve => { Alert.alert( '需要位置权限', '您之前拒绝了位置权限。要使用此功能,请在设置中启用位置权限。', [ { text: '取消', style: 'cancel', onPress: () => resolve(false) }, { text: '去设置', onPress: () => resolve(true) } ] ); }); if (openSettings) { // 打开应用设置 await Linking.openSettings(); } return false; } // 4. 如果是第一次请求或可以再次询问,则请求权限 console.log('请求位置权限...'); const { status: newStatus } = await Location.requestForegroundPermissionsAsync(); console.log('新权限状态:', newStatus); if (newStatus !== 'granted') { Alert.alert('需要位置权限', '请允许访问位置以使用此功能'); return false; } return true; } catch (error) { console.error('请求位置权限时出错:', error); Alert.alert('错误', '请求位置权限时出错'); return false; } }; // 获取媒体库权限 export const getPermissions = async () => { if (Platform.OS !== 'web') { const { status: mediaStatus } = await ImagePicker.getMediaLibraryPermissionsAsync(); if (mediaStatus !== 'granted') { // Alert.alert('需要媒体库权限', '请允许访问媒体库以继续'); return false; } return true; } return true; }; // 请求媒体库权限 export const requestPermissions = async () => { if (Platform.OS !== 'web') { const mediaStatus = await ImagePicker.requestMediaLibraryPermissionsAsync(); if (!mediaStatus.granted) { // Alert.alert('需要媒体库权限', '请允许访问媒体库以继续'); 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 => { 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) { const openSettings = await new Promise(resolve => { Alert.alert( '需要媒体库权限', '您之前拒绝了媒体库访问权限。要选择照片,请在设置中启用媒体库权限。', [ { text: '取消', style: 'cancel', onPress: () => resolve(false) }, { text: '去设置', onPress: () => resolve(true) } ] ); }); if (openSettings) { await Linking.openSettings(); } } return false; } // 4. 请求权限 const { status: newStatus } = await ImagePicker.requestMediaLibraryPermissionsAsync(); if (newStatus !== 'granted' && showAlert) { Alert.alert('需要媒体库权限', '请允许访问媒体库以方便后续操作'); } return newStatus === 'granted'; } catch (error) { console.error('请求媒体库权限时出错:', error); if (showAlert) { Alert.alert('错误', '请求媒体库权限时出错'); } 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) { // 显示提示,引导用户去设置 const openSettings = await new Promise(resolve => { Alert.alert( '需要通知权限', '您之前拒绝了通知权限。要使用此功能,请在设置中启用通知权限。', [ { text: '取消', style: 'cancel', onPress: () => resolve(false) }, { text: '去设置', onPress: () => resolve(true) } ] ); }); if (openSettings) { // 打开应用设置 await Linking.openSettings(); } return false; } // 4. 如果是第一次请求或可以再次询问,则请求权限 console.log('请求通知权限...'); const { status: newStatus } = await Notifications.requestPermissionsAsync(); console.log('新通知权限状态:', newStatus); if (newStatus !== 'granted') { Alert.alert('需要通知权限', '请允许通知以使用此功能'); return false; } return true; } catch (error) { console.error('请求通知权限时出错:', error); Alert.alert('错误', '请求通知权限时出错'); return false; } }; // 发送本地通知的辅助函数 export const sendLocalNotification = async (title: string, body: string, data: Record = {}) => { 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; }