fix: 修复布局问题
This commit is contained in:
@@ -210,5 +210,5 @@ export async function recordTokenUsage(
|
||||
* 跳转到充值页面
|
||||
*/
|
||||
export function redirectToPricePage() {
|
||||
router.push('/exchange' as any);
|
||||
router.push('/exchange');
|
||||
}
|
||||
|
||||
5
lib/api/todo.md
Normal file
5
lib/api/todo.md
Normal file
@@ -0,0 +1,5 @@
|
||||
页面:/profile
|
||||
|
||||
点击顶部 月付 应该跳转到 app\recharge.tsx
|
||||
|
||||
点击顶部的 余额 应该跳转到 app\exchange.tsx
|
||||
@@ -1,4 +1,4 @@
|
||||
import { apiClient } from './client';
|
||||
import { storage } from '../storage';
|
||||
|
||||
export interface UploadResponse {
|
||||
success: boolean;
|
||||
@@ -11,6 +11,10 @@ export interface UploadResponse {
|
||||
message?: string;
|
||||
}
|
||||
|
||||
async function getAuthToken(): Promise<string> {
|
||||
return (await storage.getItem(`bestaibest.better-auth.session_token`)) || '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件到服务器
|
||||
* @param uri 本地文件 URI(可以是 blob: 或 file:// 格式)
|
||||
@@ -31,43 +35,100 @@ export async function uploadFile(uri: string, type: 'image' | 'video'): Promise<
|
||||
};
|
||||
}
|
||||
|
||||
// 先获取 blob 以确定实际的 MIME 类型
|
||||
const response = await fetch(uri);
|
||||
const blob = await response.blob();
|
||||
|
||||
// 从 blob 获取实际的 MIME 类型
|
||||
let mimeType = blob.type;
|
||||
|
||||
// 如果 blob 没有 type,则根据参数推断
|
||||
if (!mimeType || mimeType === 'application/octet-stream') {
|
||||
mimeType = type === 'image' ? 'image/jpeg' : 'video/mp4';
|
||||
}
|
||||
|
||||
// 根据 MIME 类型确定文件扩展名
|
||||
let extension: string;
|
||||
if (mimeType.startsWith('image/')) {
|
||||
const imageExtensions: Record<string, string> = {
|
||||
'image/jpeg': 'jpg',
|
||||
'image/png': 'png',
|
||||
'image/gif': 'gif',
|
||||
'image/webp': 'webp',
|
||||
};
|
||||
extension = imageExtensions[mimeType] || 'jpg';
|
||||
} else {
|
||||
const videoExtensions: Record<string, string> = {
|
||||
'video/mp4': 'mp4',
|
||||
'video/webm': 'webm',
|
||||
'video/avi': 'avi',
|
||||
'video/quicktime': 'mov',
|
||||
};
|
||||
extension = videoExtensions[mimeType] || 'mp4';
|
||||
}
|
||||
|
||||
// 生成文件名
|
||||
const filename = `${type}_${Date.now()}.${extension}`;
|
||||
|
||||
// 创建 File 对象
|
||||
const file = new File([blob], filename, { type: mimeType });
|
||||
|
||||
// 创建 FormData
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
|
||||
// 从 URI 中提取文件信息
|
||||
const filename = uri.split('/').pop() || `${type}_${Date.now()}`;
|
||||
const match = /\.(\w+)$/.exec(filename);
|
||||
const fileType = match ? match[1] : (type === 'image' ? 'jpg' : 'mp4');
|
||||
// 获取认证 token
|
||||
const token = await getAuthToken();
|
||||
|
||||
// 添加文件到 FormData
|
||||
formData.append('file', {
|
||||
uri,
|
||||
type: type === 'image' ? `image/${fileType}` : `video/${fileType}`,
|
||||
name: filename,
|
||||
} as any);
|
||||
|
||||
formData.append('type', type);
|
||||
|
||||
// 上传文件
|
||||
const response = await fetch(`${process.env.EXPO_PUBLIC_API_URL || 'https://api.mixvideo.bowong.cc'}/api/upload`, {
|
||||
// 上传文件(不要手动设置 Content-Type,让浏览器自动添加 boundary)
|
||||
const uploadResponse = await fetch(`https://api.mixvideo.bowong.cc/api/file/upload/s3`, {
|
||||
method: 'POST',
|
||||
headers: token ? {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
} : {},
|
||||
body: formData,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Upload failed: ${response.statusText}`);
|
||||
if (!uploadResponse.ok) {
|
||||
const errorData = await uploadResponse.json();
|
||||
const errorMessage = errorData?.error?.message || errorData?.message || uploadResponse.statusText;
|
||||
throw new Error(`Upload failed: ${errorMessage}`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
const result = await uploadResponse.json();
|
||||
|
||||
if (!result.success) {
|
||||
throw new Error(result.message || 'Upload failed');
|
||||
// 支持多种返回格式:
|
||||
// 1. { status: true, msg: "...", data: "url" } - 实际 S3 上传格式
|
||||
// 2. { success: true, data: { url, ... } }
|
||||
// 3. { data: { status: true, data: "url" } }
|
||||
if (result.status === true && result.data) {
|
||||
// 格式 1(实际 S3 格式)
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
url: result.data,
|
||||
filename: filename,
|
||||
size: file.size,
|
||||
mimeType: mimeType,
|
||||
},
|
||||
};
|
||||
} else if (result.data?.status && result.data?.data) {
|
||||
// 格式 3
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
url: result.data.data,
|
||||
filename: filename,
|
||||
size: file.size,
|
||||
mimeType: mimeType,
|
||||
},
|
||||
};
|
||||
} else if (result.success && result.data) {
|
||||
// 格式 2
|
||||
return result;
|
||||
} else {
|
||||
throw new Error(result.error?.message || result.msg || result.message || 'Upload failed');
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error('Failed to upload file:', error);
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user