ソースを参照

修复头像上传

zbb 3 ヶ月 前
コミット
28b5474fbe
2 ファイル変更77 行追加3 行削除
  1. 18 3
      app/profile/index.tsx
  2. 59 0
      services/base.ts

+ 18 - 3
app/profile/index.tsx

@@ -17,7 +17,8 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context';
 
 import { Images } from '@/constants/images';
 import { useAuth } from '@/contexts/AuthContext';
-import { getUserInfo, updateNickname, updateUserInfo } from '@/services/user';
+import { uploadFile } from '@/services/base';
+import { getUserInfo, updateAvatar, updateNickname, updateUserInfo } from '@/services/user';
 
 interface FormData {
   nickname: string;
@@ -69,7 +70,7 @@ export default function ProfileScreen() {
       }
 
       const result = await ImagePicker.launchImageLibraryAsync({
-        mediaTypes: ImagePicker.MediaTypeOptions.Images,
+        mediaTypes: ['images'],
         allowsEditing: true,
         aspect: [1, 1],
         quality: 0.8,
@@ -78,7 +79,6 @@ export default function ProfileScreen() {
       if (!result.canceled && result.assets[0]) {
         const imageUri = result.assets[0].uri;
         setFormData(prev => ({ ...prev, avatar: imageUri }));
-        Alert.alert('提示', '头像选择成功,保存时将更新');
       }
     } catch (error) {
       console.error('选择头像失败:', error);
@@ -99,6 +99,21 @@ export default function ProfileScreen() {
     try {
       setLoading(true);
       
+      // 如果头像是本地文件(file://开头),需要先上传
+      let avatarUrl = formData.avatar;
+      if (formData.avatar && formData.avatar.startsWith('file://')) {
+        const uploadedUrl = await uploadFile(formData.avatar, 'avatar');
+        if (uploadedUrl) {
+          avatarUrl = uploadedUrl;
+          // 更新头像
+          await updateAvatar(avatarUrl);
+        } else {
+          Alert.alert('提示', '头像上传失败');
+          setLoading(false);
+          return;
+        }
+      }
+      
       // 更新昵称
       const nicknameRes = await updateNickname(formData.nickname);
       

+ 59 - 0
services/base.ts

@@ -67,6 +67,64 @@ export const track = async () => {
   return res.data;
 };
 
+// 上传文件
+export const uploadFile = async (fileUri: string, folder = 'avatar'): Promise<string | null> => {
+  try {
+    const formData = new FormData();
+    
+    // 获取文件名
+    const fileName = fileUri.split('/').pop() || 'image.jpg';
+    
+    // 创建文件对象 (React Native 格式)
+    const fileObj = {
+      uri: fileUri,
+      type: 'image/jpeg',
+      name: fileName,
+    } as any;
+    
+    formData.append('file', fileObj);
+    formData.append('appId', 'supermart-acetoys');
+    formData.append('folder', folder);
+    
+    // 使用http.ts中的getToken获取token
+    const { getToken } = require('./http');
+    const token = getToken();
+    
+    const response = await fetch('https://mm.acetoys.cn/api/oss/file/upload', {
+      method: 'POST',
+      headers: {
+        // 不设置 Content-Type,让 fetch 自动处理 multipart/form-data 边界
+        'Authentication': token || '',
+      },
+      body: formData,
+    });
+    
+    // 检查响应状态
+    if (!response.ok) {
+      const errorText = await response.text();
+      console.error('上传响应状态:', response.status, '响应内容:', errorText);
+      return null;
+    }
+    
+    const text = await response.text();
+    if (!text) {
+      console.error('上传响应为空');
+      return null;
+    }
+    
+    const result = JSON.parse(text);
+    // code 可能是数字或字符串
+    if ((result.code === 0 || result.code === '0') && result.data?.url) {
+      return result.data.url;
+    }
+    console.error('上传返回错误:', result);
+    return null;
+  } catch (error) {
+    console.error('上传文件失败:', error);
+    return null;
+  }
+};
+
 export default {
   getPageConfig,
   getMessages,
@@ -74,4 +132,5 @@ export default {
   getParamConfig,
   submitFeedback,
   track,
+  uploadFile,
 };