diff --git a/app.json b/app.json index e8efb01..8b7028c 100644 --- a/app.json +++ b/app.json @@ -65,14 +65,15 @@ "locationWhenInUsePermission": "允许 $(PRODUCT_NAME) 访问您的位置" } ], - [ - "expo-notifications", - { - "color": "#ffffff", - "defaultChannel": "default", - "enableBackgroundRemoteNotifications": false - } - ], + // [ + // "expo-notifications", + // { + // "color": "#ffffff", + // "defaultChannel": "default", + // "enableBackgroundRemoteNotifications": false, + // "mode": "client" + // } + // ], [ "expo-audio", { diff --git a/app/(tabs)/index.tsx b/app/(tabs)/index.tsx index 2b25540..99079a6 100644 --- a/app/(tabs)/index.tsx +++ b/app/(tabs)/index.tsx @@ -49,7 +49,7 @@ export default function HomeScreen() { } console.log("token111111111", token); if (token) { - router.push('/ask') + router.push('/user-message') } else { router.push('/login') } diff --git a/babel.config.js b/babel.config.js index 688c720..3239fbd 100644 --- a/babel.config.js +++ b/babel.config.js @@ -6,7 +6,6 @@ module.exports = function (api) { "nativewind/babel", ], plugins: [ - 'expo-router/babel', 'react-native-reanimated/plugin', ], }; diff --git a/components/file-upload/backgroundUploader.ts b/components/file-upload/backgroundUploader.ts index 11097b0..2c8e204 100644 --- a/components/file-upload/backgroundUploader.ts +++ b/components/file-upload/backgroundUploader.ts @@ -8,28 +8,50 @@ import { Alert } from 'react-native'; const BACKGROUND_UPLOAD_TASK = 'background-upload-task'; // 设置最大并发数 -const CONCURRENCY_LIMIT = 3; // 同时最多上传3个文件 -// 获取指定时间范围内的媒体文件 +const CONCURRENCY_LIMIT = 10; // 同时最多上传10个文件 + +// 获取指定时间范围内的媒体文件(包含 EXIF 信息) export const getMediaByDateRange = async (startDate: Date, endDate: Date) => { + console.log("getMediaByDateRange", startDate.getTime(), endDate.getTime()); + try { const { status } = await MediaLibrary.requestPermissionsAsync(); if (status !== 'granted') { - console.log('Media library permission not granted'); return []; } // 获取媒体资源 const media = await MediaLibrary.getAssetsAsync({ mediaType: ['photo', 'video'], - first: 100, // 每次最多获取100个 + first: 10, // 每次最多获取100个 sortBy: [MediaLibrary.SortBy.creationTime], createdAfter: startDate.getTime(), createdBefore: endDate.getTime(), }); - return media.assets; + console.log("media1111111111", media); + + // 为每个资源获取完整的 EXIF 信息 + const assetsWithExif = await Promise.all( + media.assets.map(async (asset) => { + try { + if (asset.mediaType === 'photo') { + const assetInfo = await MediaLibrary.getAssetInfoAsync(asset.id); + return { + ...asset, + exif: assetInfo.exif || null, + location: assetInfo.location || null + }; + } + return asset; // 视频不处理 EXIF + } catch (error) { + return asset; // 如果获取 EXIF 失败,返回原始资源 + } + }) + ); + + return assetsWithExif; } catch (error) { - console.error('Error getting media by date range:', error); return []; } }; @@ -61,13 +83,13 @@ const compressImage = async (uri: string): Promise<{ uri: string; file: File }> return { uri: manipResult.uri, file }; } catch (error) { - console.error('Error compressing image:', error); throw error; } }; // 获取上传URL const getUploadUrl = async (file: File, metadata: Record = {}): Promise<{ upload_url: string; file_id: string }> => { + const body = { filename: file.name, content_type: file.type, @@ -103,65 +125,38 @@ const addMaterial = async (file: string, compressFile: string) => { "preview_file_id": compressFile }]) }).catch((error) => { - // console.log(error); }) } // 上传文件到URL const uploadFile = async (file: File, uploadUrl: string): Promise => { - console.log('=== Starting file upload ==='); - console.log('File info:', { - name: file.name, - type: file.type, - size: file.size, - lastModified: file.lastModified + return new Promise((resolve, reject) => { + const xhr = new XMLHttpRequest(); + + xhr.open('PUT', uploadUrl); + xhr.setRequestHeader('Content-Type', file.type); + + // 进度监听 + xhr.upload.onprogress = (event) => { + if (event.lengthComputable) { + const progress = Math.round((event.loaded / event.total) * 100); + } + }; + + xhr.onload = () => { + if (xhr.status >= 200 && xhr.status < 300) { + resolve(); + } else { + reject(new Error(`Upload failed with status ${xhr.status}`)); + } + }; + + xhr.onerror = () => { + reject(new Error('Network error during upload')); + }; + + xhr.send(file); }); - console.log('Upload URL:', uploadUrl); - - try { - const controller = new AbortController(); - const timeoutId = setTimeout(() => { - console.log('Upload timeout triggered'); - controller.abort(); - }, 30000); - - console.log('Sending upload request...'); - const startTime = Date.now(); - - const response = await fetch(uploadUrl, { - method: 'PUT', - headers: { - 'Content-Type': file.type, - 'x-oss-forbid-overwrite': 'true' - }, - body: file, - signal: controller.signal - }); - - clearTimeout(timeoutId); - const endTime = Date.now(); - - console.log(`Upload completed in ${endTime - startTime}ms`, { - status: response.status, - statusText: response.statusText, - headers: Object.fromEntries(response.headers.entries()) - }); - - if (!response.ok) { - const errorText = await response.text().catch(() => ''); - console.error('Upload failed with response:', errorText); - throw new Error(`Upload failed: ${response.status} ${response.statusText}\n${errorText}`); - } - - console.log('Upload successful'); - } catch (error: any) { - console.error('Upload error details:', { - name: error.name, - message: error.message, - stack: error.stack - }); - throw error; - } }; // 检查并请求媒体库权限 @@ -187,7 +182,6 @@ const checkMediaLibraryPermission = async (): Promise<{ hasPermission: boolean, status: newStatus }; } catch (error) { - console.error('Error checking media library permission:', error); return { hasPermission: false }; } }; @@ -213,19 +207,19 @@ const processMediaUpload = async (asset: MediaLibrary.Asset) => { const mimeType = isVideo ? 'video/mp4' : 'image/jpeg'; const file = new File([blob], filename, { type: mimeType }); - console.log("Original file prepared for upload:", file); - // 获取上传URL并上传原始文件 const { upload_url, file_id } = await getUploadUrl(file, { originalUri: asset.uri, creationTime: asset.creationTime, mediaType: isVideo ? 'video' : 'image', - isCompressed: false + isCompressed: false, + ...asset?.exif, + GPSVersionID: undefined }); await uploadFile(file, upload_url); await confirmUpload(file_id); - console.log(`Successfully uploaded original: ${filename}`); + return { success: true, file_id }; }; @@ -239,13 +233,6 @@ const processMediaUpload = async (asset: MediaLibrary.Asset) => { `compressed_${asset.filename}` : `image_${Date.now()}_compressed.jpg`; - console.log("Compressed file prepared for upload:", { - name: filename, - size: compressedFile.size, - type: compressedFile.type - }); - console.log("compressedFile", compressedFile); - // 获取上传URL并上传压缩文件 const { upload_url, file_id } = await getUploadUrl(compressedFile, { originalUri: asset.uri, @@ -256,23 +243,20 @@ const processMediaUpload = async (asset: MediaLibrary.Asset) => { await uploadFile(compressedFile, upload_url); await confirmUpload(file_id); - console.log(`Successfully uploaded compressed: ${filename}`); return { success: true, file_id }; } catch (error) { - console.error('Error uploading compressed file:', error); return { success: false, error }; } }; // 同时上传原始文件和压缩文件 - console.log("Asset info:", asset); const [originalResult, compressedResult] = await Promise.all([ uploadOriginalFile(), uploadCompressedFile() ]); - console.log("originalResult", originalResult); - console.log("compressedResult", compressedResult); - addMaterial(originalResult.file_id, compressedResult.file_id) + + // 添加素材 + addMaterial(originalResult.file_id, compressedResult?.file_id || '') return { originalSuccess: originalResult.success, compressedSuccess: compressedResult.success, @@ -282,7 +266,6 @@ const processMediaUpload = async (asset: MediaLibrary.Asset) => { } }; } catch (error: any) { - console.error('Error in processMediaUpload:', error); if (error.message === 'No media library permission') { throw error; } @@ -310,10 +293,8 @@ export const registerBackgroundUploadTask = async () => { startOnBoot: true, // 系统启动后自动运行 }); - console.log('Background upload task registered'); return true; } catch (error) { - console.error('Error registering background task:', error); return false; } }; @@ -321,12 +302,9 @@ export const registerBackgroundUploadTask = async () => { // 定义后台任务 TaskManager.defineTask(BACKGROUND_UPLOAD_TASK, async () => { try { - console.log('Background upload task started'); - // 检查并请求媒体库权限 const { hasPermission } = await checkMediaLibraryPermission(); if (!hasPermission) { - console.log('Media library permission not granted'); return BackgroundFetch.BackgroundFetchResult.NoData; } @@ -335,15 +313,11 @@ TaskManager.defineTask(BACKGROUND_UPLOAD_TASK, async () => { const yesterday = new Date(now.getTime() - 24 * 60 * 60 * 1000); const media = await getMediaByDateRange(yesterday, now); - console.log("media", media); if (media.length === 0) { - console.log('No media found in the specified time range'); return BackgroundFetch.BackgroundFetchResult.NoData; } - console.log(`Found ${media.length} media items to process`); - // 创建并发限制器 const limit = pLimit(CONCURRENCY_LIMIT); @@ -354,7 +328,6 @@ TaskManager.defineTask(BACKGROUND_UPLOAD_TASK, async () => { await processMediaUpload(item); return { success: true, id: item.id }; } catch (error: any) { - console.error(`Error processing media ${item.id}:`, error); if (error.message === 'No media library permission') { throw error; // 权限错误直接抛出 } @@ -372,8 +345,6 @@ TaskManager.defineTask(BACKGROUND_UPLOAD_TASK, async () => { ).length; const failed = results.length - succeeded; - console.log(`Background upload task completed. Success: ${succeeded}, Failed: ${failed}`); - // 如果有权限错误,返回失败 const hasPermissionError = results.some(r => r.status === 'rejected' || @@ -388,7 +359,6 @@ TaskManager.defineTask(BACKGROUND_UPLOAD_TASK, async () => { BackgroundFetch.BackgroundFetchResult.NewData : BackgroundFetch.BackgroundFetchResult.NoData; } catch (error) { - console.error('Error in background upload task:', error); return BackgroundFetch.BackgroundFetchResult.Failed; } }); @@ -396,12 +366,7 @@ TaskManager.defineTask(BACKGROUND_UPLOAD_TASK, async () => { // 手动触发上传 export const triggerManualUpload = async (startDate: Date, endDate: Date) => { try { - console.log('Starting manual upload...'); - console.log("startDate", startDate); - console.log("endDate", endDate); - const media = await getMediaByDateRange(startDate, endDate); - console.log("media", media); if (media.length === 0) { Alert.alert('提示', '在指定时间范围内未找到媒体文件'); return []; @@ -419,7 +384,6 @@ export const triggerManualUpload = async (startDate: Date, endDate: Date) => { fileIds: result.fileIds, }); } catch (error) { - console.error(`Error uploading ${item.filename}:`, error); results.push({ id: item.id, originalSuccess: false, @@ -435,7 +399,6 @@ export const triggerManualUpload = async (startDate: Date, endDate: Date) => { return results; } catch (error) { - console.error('Error in manual upload:', error); Alert.alert('错误', '上传过程中出现错误'); throw error; } diff --git a/components/file-upload/files-uploader.tsx b/components/file-upload/files-uploader.tsx index b328f39..ed720cb 100644 --- a/components/file-upload/files-uploader.tsx +++ b/components/file-upload/files-uploader.tsx @@ -191,6 +191,7 @@ export const ImagesUploader: React.FC = ({ }; const uploadWithProgress = async (file: File, metadata: any): Promise => { let timeoutId: number + console.log("uploadWithProgress", metadata); try { console.log("Starting upload for file:", file.name, "size:", file.size, "type:", file.type); @@ -201,7 +202,7 @@ export const ImagesUploader: React.FC = ({ throw new Error(`文件大小超过限制 (${(MAX_FILE_SIZE / 1024 / 1024).toFixed(1)}MB)`); } - const uploadUrlData = await getUploadUrl(file, {}); + const uploadUrlData = await getUploadUrl(file, { ...metadata, GPSVersionID: undefined }); console.log("Got upload URL for:", file.name); return new Promise((resolve, reject) => { @@ -267,6 +268,8 @@ export const ImagesUploader: React.FC = ({ // 处理单个资源 const processSingleAsset = async (asset: ImagePicker.ImagePickerAsset): Promise => { + console.log("asset111111", asset); + const fileId = `file_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; const isVideo = asset.type === 'video'; const uploadResults: UploadResult = {