enhance: 类型问题

This commit is contained in:
Junhui Chen 2025-07-16 19:30:03 +08:00
parent 2505df0182
commit f63497f3a1
4 changed files with 97 additions and 227 deletions

View File

@ -1,8 +1,7 @@
import { addMaterial, confirmUpload, getUploadUrl } from '@/lib/background-uploader/api'; import { addMaterial, confirmUpload, getUploadUrl } from '@/lib/background-uploader/api';
import { ConfirmUpload, FileUploadItem, UploadResult, UploadTask } from '@/lib/background-uploader/types'; import { ConfirmUpload, FileUploadItem, UploadResult, UploadTask, ImagesuploaderProps, ExifData, defaultExifData } from '@/lib/background-uploader/types';
import { uploadFileWithProgress } from '@/lib/background-uploader/uploader'; import { uploadFileWithProgress } from '@/lib/background-uploader/uploader';
import { compressImage } from '@/lib/image-process/imageCompress'; import { compressImage } from '@/lib/image-process/imageCompress';
import { defaultExifData, ExifData, ImagesuploaderProps } from '@/types/upload';
import * as ImageManipulator from 'expo-image-manipulator'; import * as ImageManipulator from 'expo-image-manipulator';
import * as ImagePicker from 'expo-image-picker'; import * as ImagePicker from 'expo-image-picker';
import * as Location from 'expo-location'; import * as Location from 'expo-location';
@ -24,7 +23,7 @@ export const ImagesUploader: React.FC<ImagesuploaderProps> = ({
fileType = ['images'], fileType = ['images'],
}) => { }) => {
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [files, setFiles] = useState<FileUploadItem[]>([]);
const [uploadQueue, setUploadQueue] = useState<FileUploadItem[]>([]); const [uploadQueue, setUploadQueue] = useState<FileUploadItem[]>([]);
// 请求权限 // 请求权限
@ -63,12 +62,14 @@ export const ImagesUploader: React.FC<ImagesuploaderProps> = ({
// 创建上传项 // 创建上传项
const newFileItem: FileUploadItem = { const newFileItem: FileUploadItem = {
id: fileId, id: fileId,
uri: asset.uri,
previewUrl: asset.uri, // 使用 asset.uri 作为初始预览
name: asset.fileName || 'file', name: asset.fileName || 'file',
progress: 0, progress: 0,
status: 'uploading' as const, status: 'uploading',
error: null, error: undefined,
type: isVideo ? 'video' : 'image', type: isVideo ? 'video' : 'image',
thumbnail: null, thumbnail: undefined,
}; };
setUploadQueue(prev => [...prev, newFileItem]); setUploadQueue(prev => [...prev, newFileItem]);
@ -190,7 +191,7 @@ export const ImagesUploader: React.FC<ImagesuploaderProps> = ({
item.id === fileId item.id === fileId
? { ? {
...item, ...item,
status: 'done' as const, status: 'success' as const,
progress: 100, progress: 100,
thumbnail: uploadResults.thumbnail thumbnail: uploadResults.thumbnail
} }

View File

@ -159,7 +159,7 @@ export const processMediaUpload = async (asset: ExtendedAsset) => {
const originalResult = await uploadOriginalFile(); const originalResult = await uploadOriginalFile();
// 如果是图片,再上传压缩文件 // 如果是图片,再上传压缩文件
let compressedResult = { success: true, file_id: null }; let compressedResult: { success: boolean; file_id?: string | null; error?: any } = { success: true, file_id: null };
if (!isVideo) { if (!isVideo) {
compressedResult = await uploadCompressedFile(); compressedResult = await uploadCompressedFile();
// 添加素材 // 添加素材

View File

@ -15,16 +15,95 @@ export type UploadTask = {
}; };
}; };
// 上传队列项 // 文件元数据信息
export type FileUploadItem = { interface FileSize {
value: number;
unit: string;
}
interface FileMetadata {
originalName: string;
type: string;
isCompressed: string;
fileType: string;
}
// 后端返回的文件信息
interface FileInfo {
file_id: number;
name: string;
size: FileSize;
content_type: string; // 这里与 ConfirmUpload 的 content_type 定义不同,需要注意
upload_time: string;
storage_medium: string;
file_path: string; // 这里与 ConfirmUpload 的 file_path 定义不同
uploader_id: number;
upload_status: string;
deletion_status: string;
metadata: FileMetadata;
}
// 上传队列项 - 作为唯一的类型定义
// 定义 EXIF 数据类型
export type ExifData = {
GPSLatitude?: number | undefined;
GPSLongitude?: number | undefined;
GPSAltitude?: number | undefined;
DateTimeOriginal?: string | undefined;
Make?: string | undefined;
Model?: string | undefined;
ExposureTime?: number | undefined;
FNumber?: number | undefined;
ISOSpeedRatings?: number | undefined;
FocalLength?: number | undefined;
[key: string]: any;
};
// 默认的 EXIF 数据结构
export const defaultExifData: ExifData = {
GPSLatitude: undefined,
GPSLongitude: undefined,
GPSAltitude: undefined,
DateTimeOriginal: undefined,
Make: undefined,
Model: undefined,
ExposureTime: undefined,
FNumber: undefined,
ISOSpeedRatings: undefined,
FocalLength: undefined,
};
// 压缩图片可配置参数
export interface ImagesuploaderProps {
children?: React.ReactNode;
style?: import('react-native').StyleProp<import('react-native').ViewStyle>;
onPickImage?: (file: File, exifData: ExifData) => void;
compressQuality?: number;
maxWidth?: number;
maxHeight?: number;
preserveExif?: boolean;
uploadOriginal?: boolean;
onUploadComplete?: (result: FileUploadItem[]) => void;
onProgress?: (progress: any) => void; // TODO: Define a proper type for progress
multipleChoice?: boolean;
fileType?: any[]; // TODO: Use MediaType from expo-image-picker
showPreview?: boolean;
}
export interface FileUploadItem {
id: string; id: string;
uri: string; // 用于本地展示的资源URI
name: string; name: string;
progress: number; progress: number;
status: 'pending' | 'uploading' | 'done' | 'error'; status: 'pending' | 'uploading' | 'success' | 'error'; // 统一状态
error: string | null; error?: string | null;
previewUrl: string; // 预览URL
file?: File;
type: 'image' | 'video'; type: 'image' | 'video';
thumbnail: string | null; thumbnail?: string; // 缩略图URL
}; thumbnailFile?: File; // 缩略图文件对象
originalFile?: FileInfo // 上传后返回的文件信息
}
// 确认上传返回 // 确认上传返回
export type ConfirmUpload = { export type ConfirmUpload = {

View File

@ -1,210 +0,0 @@
import { MediaType } from "expo-image-picker";
import { ReactNode } from "react";
import { StyleProp, ViewStyle } from "react-native";
export interface FileStatus {
file: File;
status: 'pending' | 'uploading' | 'success' | 'error';
progress: number;
error?: string;
}
export interface MaterialFile {
id: string;
file_name: string;
url: string;
}
export interface OutputVideoFile {
id: string;
file_name: string;
url: string;
}
export interface ManualTask {
task_id: string;
user_id: string;
status: 'Created' | 'Processing' | 'Completed' | 'Failed';
created_at: string;
started_at: string;
completed_at: string;
failure_reason: string | null;
template_id: number;
source_files: MaterialFile[];
output_video_file?: OutputVideoFile;
}
export interface Size {
value: number;
unit: 'B' | 'KB' | 'MB' | 'GB' | 'TB';
}
export interface ContentType {
value: string;
}
export interface FilePath {
value: string;
}
export interface Metadata {
[key: string]: any;
}
export type UploadStatus = 'Pending' | 'Uploading' | 'Completed' | 'Failed';
export type DeletionStatus = 'Active' | 'PendingDeletion' | 'Deleted';
export interface ConfirmUpload {
file_id: string;
upload_url: string
name: string;
size: Size;
content_type: ContentType;
upload_time: string; // ISO date string
storage_medium: string;
file_path: FilePath;
uploader_id: number;
upload_status: UploadStatus;
deletion_status: DeletionStatus;
metadata: Metadata;
}
// 定义 EXIF 数据类型
export type ExifData = {
GPSLatitude?: number | undefined;
GPSLongitude?: number | undefined;
GPSAltitude?: number | undefined;
DateTimeOriginal?: string | undefined;
Make?: string | undefined;
Model?: string | undefined;
ExposureTime?: number | undefined;
FNumber?: number | undefined;
ISOSpeedRatings?: number | undefined;
FocalLength?: number | undefined;
[key: string]: any;
};
// 默认的 EXIF 数据结构
export const defaultExifData: ExifData = {
GPSLatitude: undefined,
GPSLongitude: undefined,
GPSAltitude: undefined,
DateTimeOriginal: undefined,
Make: undefined,
Model: undefined,
ExposureTime: undefined,
FNumber: undefined,
ISOSpeedRatings: undefined,
FocalLength: undefined,
};
// 压缩图片可配置参数
export interface ImagesuploaderProps {
children?: ReactNode;
style?: StyleProp<ViewStyle>;
onPickImage?: (file: File, exifData: ExifData) => void;
/** 压缩质量0-1 之间的数字,默认为 0.8 */
compressQuality?: number;
/** 最大宽度,图片会被等比例缩放 */
maxWidth?: number;
/** 最大高度,图片会被等比例缩放 */
maxHeight?: number;
/** 是否保留 EXIF 数据,默认为 true */
preserveExif?: boolean;
/** 是否上传原图,默认为 false */
uploadOriginal?: boolean;
/** 上传完成回调 */
onUploadComplete?: UploadCompleteCallback;
/** 进度 */
onProgress?: (progress: FileStatus) => void;
/** 多选单选 默认单选*/
multipleChoice?: boolean;
/** 文件类型 默认图片*/
fileType?: MediaType[];
/** 是否展示预览 默认展示*/
showPreview?: boolean;
}
// 定义上传结果类型
export interface UploadResult {
originalUrl?: string;
compressedUrl: string;
file: File;
exifData: ExifData;
originalFile: ConfirmUpload;
compressedFile: ConfirmUpload;
thumbnail: string;
thumbnailFile: File;
}
// 定义上传完成回调类型
export type UploadCompleteCallback = (result: FileUploadItem[]) => void;
// 单张图片上传完成回调类型
export type UploadSingleCompleteCallback = (result: FileUploadItem) => void;
// 定义上传 URL 响应类型
export interface UploadUrlResponse {
expires_in: number;
file_id: string;
file_path: string;
upload_url: string;
}
interface FileSize {
value: number;
unit: string;
}
interface FileMetadata {
originalName: string;
type: string;
isCompressed: string;
fileType: string;
}
interface FileInfo {
file_id: number;
name: string;
size: FileSize;
content_type: ContentType;
upload_time: string;
storage_medium: string;
file_path: FilePath;
uploader_id: number;
upload_status: string;
deletion_status: string;
metadata: FileMetadata;
}
export interface FileUploadItem {
id: string;
uri: string;
name: string;
progress: number;
status: 'pending' | 'uploading' | 'success' | 'error';
error?: string;
previewUrl: string;
file?: File;
type: 'image' | 'video';
thumbnail?: string; // 缩略图URL
thumbnailFile?: File; // 缩略图文件对象
originalFile?: FileInfo
}
// 压缩图片可配置参数
export interface ImagesPickerProps {
children?: ReactNode;
style?: StyleProp<ViewStyle>;
onPickImage?: (file: File, exifData: ExifData) => void;
/** 压缩质量0-1 之间的数字,默认为 0.8 */
compressQuality?: number;
/** 最大宽度,图片会被等比例缩放 */
maxWidth?: number;
/** 最大高度,图片会被等比例缩放 */
maxHeight?: number;
/** 是否保留 EXIF 数据,默认为 true */
preserveExif?: boolean;
/** 是否上传原图,默认为 false */
uploadOriginal?: boolean;
/** 上传完成回调 */
onUploadComplete?: UploadSingleCompleteCallback;
/** 进度 */
onProgress?: (progress: FileStatus) => void;
}