import UIButton from "@/components/ui/UIButton"; import { Colors } from "@/constants/theme"; import { ActionSheet, ActivityIndicator, Icon, Modal, Toast } from "@ant-design/react-native"; import { Ionicons } from '@expo/vector-icons'; import { Platform, Pressable, Text, View } from "react-native"; import api from "@/utils/api"; import { openSystemSettings } from "@/utils/os"; import clsx from "clsx"; import { DocumentPickerAsset, getDocumentAsync } from 'expo-document-picker'; import { File } from 'expo-file-system'; import { ImagePickerAsset, launchCameraAsync, launchImageLibraryAsync, requestCameraPermissionsAsync, requestMediaLibraryPermissionsAsync } from 'expo-image-picker'; import { Link } from "expo-router"; import { useCallback, useEffect, useState } from "react"; const takePhoto = async (upload: (assets: ImagePickerAsset[] | DocumentPickerAsset[]) => void) => { const permission = await requestCameraPermissionsAsync(); if (!permission.granted) { Modal.alert("请允许相册权限", "如果点击“确认“按钮后没有跳转,请自己前往系统设置开启相关权限", [ { text: "确认", onPress: openSystemSettings, } ]); // 跳转到 ios/android 相关设置页面 return; } const l = Toast.loading('正在打开相机...'); try { const result = await launchCameraAsync({ allowsEditing: false, // 是否允许裁剪 quality: 0.9, // 照片质量 }); if (!result.canceled) { upload(result.assets); } } catch (err) { console.warn(err); Toast.fail('打开相机失败,请重试'); } finally { Toast.remove(l); } } const picImg = async (upload: (assets: ImagePickerAsset[] | DocumentPickerAsset[]) => void) => { const permission = await requestMediaLibraryPermissionsAsync(); if (!permission.granted) { Modal.alert("请允许相册权限", "如果点击“确认“按钮后没有跳转,请自己前往系统设置开启相关权限", [ { text: "确认", onPress: openSystemSettings, } ]); // 跳转到 ios/android 相关设置页面 return; } const l = Toast.loading('正在打开相册...'); try { let result = await launchImageLibraryAsync({ mediaTypes: ['images'], // 只选图片 allowsEditing: false, quality: .9, // 质量 0~1 }); if (!result.canceled) { upload(result.assets); } } catch (err) { console.warn(err); Toast.fail('打开相册失败,请重试'); } finally { Toast.remove(l); } } const pickDoc = async (upload: (assets: ImagePickerAsset[] | DocumentPickerAsset[]) => void) => { const l = Toast.loading('正在打开相册...'); try { let result = await getDocumentAsync({ type: [ // PDF 'application/pdf', // Word 文档 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // Excel 表格 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // WPS 文字 / WPS 表格 'application/wps-office.doc', 'application/wps-office.docx', 'application/wps-office.xls', 'application/wps-office.xlsx', 'application/wps-office.et', 'application/wps-office.wps', // 纯文本 'text/plain', // HTML 'text/html', // 全部图片(jpg/png/gif/webp 等) 'image/*' ], copyToCacheDirectory: true, // 复制到应用缓存目录 }); if (!result.canceled) { upload(result.assets); } } catch (err) { console.warn(err); Toast.fail('打开文件失败,请重试'); } finally { Toast.remove(l); } }; export function UploadScreen({ visible, onClose }: { visible: boolean, onClose: () => void }) { useEffect(() => { if (!visible) { setState(0); } }, [visible]); const [state, setState] = useState(0); const upload = useCallback(async (assets: ImagePickerAsset[] | DocumentPickerAsset[]) => { setState(1); let att: { url: string, fullurl: string, attid: any } = null!; try { const file = new File(assets[0].uri); // file.type = item.mimeType || 'application/octet-stream'; const formData = new FormData(); formData.append('file', file); att = await api.uploadFile<{ url: string, fullurl: string, attid: any }>('common/upload', { body: formData }); } catch (err) { setState(0); console.warn(err); Toast.fail('上传失败,请重试'); return; } try { await api.post('/credit/create', { att: JSON.stringify(att), }); setState(2); // eslint-disable-next-line @typescript-eslint/no-unused-vars } catch (err) { setState(0); Toast.fail('添加分析到队列失败,请重试'); } }, []); return ( 征信分析 {state === 0 && ( 请选择征信上传方式 pickDoc(upload)} className="mt-8" /> {Platform.OS === 'ios' && picImg(upload)} className="mt-4" />} takePhoto(upload)} className="mt-4" /> )} { state === 1 && ( ) } { state === 2 && ( <> AI 正在分析 分析页 查看状态和结果 ) } {state != 1 && { onClose(); }}> } ); } export function UploadComponent({ customerId, onCompolete }: { customerId?: number, onCompolete: () => void }) { const [state, setState] = useState(0); const upload = useCallback(async (assets: ImagePickerAsset[] | DocumentPickerAsset[]) => { setState(1); let att: { url: string, fullurl: string, attid: any } = null!; try { const file = new File(assets[0].uri); // file.type = item.mimeType || 'application/octet-stream'; const formData = new FormData(); formData.append('file', file); att = await api.uploadFile<{ url: string, fullurl: string, attid: any }>('common/upload', { body: formData }); } catch (err) { setState(0); console.warn(err); Toast.fail('上传失败,请重试'); return; } try { await api.post('/credit/create', { att: JSON.stringify(att), }); setState(0); onCompolete?.(); // eslint-disable-next-line @typescript-eslint/no-unused-vars } catch (err) { setState(0); Toast.fail('添加分析到队列失败,请重试'); } }, [onCompolete]); const onSelect = useCallback((index: number) => { if (Platform.OS == 'android' && index == 2) { return; } if (Platform.OS == 'ios' && index == 3) { return; } if (index == 0) { pickDoc(upload); } if (index == 1) { if (Platform.OS == 'ios') { picImg(upload); } else { takePhoto(upload); } } if (index == 2) { takePhoto(upload); } }, []); const selectFile = useCallback(() => { ActionSheet.showActionSheetWithOptions({ title: "请选择征信上传方式", cancelButtonIndex: 3, options: Platform.OS == 'ios' ? ['从本机文件', '从手机相册', '拍照上传', '取消'] : ['从本机文件', '拍照上传', '取消'] }, onSelect); }, []); return ( <> 上传征信文件 {state == 1 ? : 点击上传征信报告} 支持 PDF、图片格式,最大 20MB ); }