feat: 更新应用图标和启动画面
- 将应用图标更改为 logo.jpeg,更新相关配置文件 - 删除旧的图标文件,确保资源整洁 - 更新启动画面使用新的 logo 图片,提升视觉一致性 - 在训练计划相关功能中集成新的 API 接口,支持训练计划的创建和管理 - 优化 Redux 状态管理,支持训练计划的加载和删除功能 - 更新样式以适应新图标和功能的展示
This commit is contained in:
@@ -4,6 +4,7 @@ import * as ImagePicker from 'expo-image-picker';
|
||||
import { useRouter } from 'expo-router';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import {
|
||||
ActivityIndicator,
|
||||
Alert,
|
||||
Image,
|
||||
Linking,
|
||||
@@ -12,13 +13,14 @@ import {
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
View
|
||||
} from 'react-native';
|
||||
import ImageViewing from 'react-native-image-viewing';
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
|
||||
import { HeaderBar } from '@/components/ui/HeaderBar';
|
||||
import { Colors } from '@/constants/Colors';
|
||||
import { useCosUpload } from '@/hooks/useCosUpload';
|
||||
|
||||
type PoseView = 'front' | 'side' | 'back';
|
||||
|
||||
@@ -59,6 +61,9 @@ export default function AIPostureAssessmentScreen() {
|
||||
[uploadState]
|
||||
);
|
||||
|
||||
const { upload, uploading } = useCosUpload();
|
||||
const [uploadingKey, setUploadingKey] = useState<PoseView | null>(null);
|
||||
|
||||
const [cameraPerm, setCameraPerm] = useState<ImagePicker.PermissionStatus | null>(null);
|
||||
const [libraryPerm, setLibraryPerm] = useState<ImagePicker.PermissionStatus | null>(null);
|
||||
const [libraryAccess, setLibraryAccess] = useState<'all' | 'limited' | 'none' | null>(null);
|
||||
@@ -129,7 +134,25 @@ export default function AIPostureAssessmentScreen() {
|
||||
aspect: [3, 4],
|
||||
});
|
||||
if (!result.canceled) {
|
||||
setUploadState((s) => ({ ...s, [key]: result.assets[0]?.uri ?? null }));
|
||||
// 设置正在上传状态
|
||||
setUploadingKey(key);
|
||||
try {
|
||||
// 上传到 COS
|
||||
const { url } = await upload(
|
||||
{ uri: result.assets[0]?.uri ?? '', name: `posture-${key}.jpg`, type: 'image/jpeg' },
|
||||
{ prefix: 'posture-assessment/' }
|
||||
);
|
||||
// 上传成功,更新状态
|
||||
setUploadState((s) => ({ ...s, [key]: url }));
|
||||
} catch (uploadError) {
|
||||
console.warn('上传图片失败', uploadError);
|
||||
Alert.alert('上传失败', '图片上传失败,请重试');
|
||||
// 上传失败,清除状态
|
||||
setUploadState((s) => ({ ...s, [key]: null }));
|
||||
} finally {
|
||||
// 清除上传状态
|
||||
setUploadingKey(null);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const resp = await ImagePicker.requestMediaLibraryPermissionsAsync();
|
||||
@@ -158,7 +181,25 @@ export default function AIPostureAssessmentScreen() {
|
||||
aspect: [3, 4],
|
||||
});
|
||||
if (!result.canceled) {
|
||||
setUploadState((s) => ({ ...s, [key]: result.assets[0]?.uri ?? null }));
|
||||
// 设置正在上传状态
|
||||
setUploadingKey(key);
|
||||
try {
|
||||
// 上传到 COS
|
||||
const { url } = await upload(
|
||||
{ uri: result.assets[0]?.uri ?? '', name: `posture-${key}.jpg`, type: 'image/jpeg' },
|
||||
{ prefix: 'posture-assessment/' }
|
||||
);
|
||||
// 上传成功,更新状态
|
||||
setUploadState((s) => ({ ...s, [key]: url }));
|
||||
} catch (uploadError) {
|
||||
console.warn('上传图片失败', uploadError);
|
||||
Alert.alert('上传失败', '图片上传失败,请重试');
|
||||
// 上传失败,清除状态
|
||||
setUploadState((s) => ({ ...s, [key]: null }));
|
||||
} finally {
|
||||
// 清除上传状态
|
||||
setUploadingKey(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -219,6 +260,7 @@ export default function AIPostureAssessmentScreen() {
|
||||
onPickCamera={() => requestPermissionAndPick('camera', 'front')}
|
||||
onPickLibrary={() => requestPermissionAndPick('library', 'front')}
|
||||
samples={SAMPLES.front}
|
||||
uploading={uploading && uploadingKey === 'front'}
|
||||
/>
|
||||
|
||||
<UploadTile
|
||||
@@ -227,6 +269,7 @@ export default function AIPostureAssessmentScreen() {
|
||||
onPickCamera={() => requestPermissionAndPick('camera', 'side')}
|
||||
onPickLibrary={() => requestPermissionAndPick('library', 'side')}
|
||||
samples={SAMPLES.side}
|
||||
uploading={uploading && uploadingKey === 'side'}
|
||||
/>
|
||||
|
||||
<UploadTile
|
||||
@@ -235,6 +278,7 @@ export default function AIPostureAssessmentScreen() {
|
||||
onPickCamera={() => requestPermissionAndPick('camera', 'back')}
|
||||
onPickLibrary={() => requestPermissionAndPick('library', 'back')}
|
||||
samples={SAMPLES.back}
|
||||
uploading={uploading && uploadingKey === 'back'}
|
||||
/>
|
||||
</ScrollView>
|
||||
|
||||
@@ -264,12 +308,14 @@ function UploadTile({
|
||||
onPickCamera,
|
||||
onPickLibrary,
|
||||
samples,
|
||||
uploading,
|
||||
}: {
|
||||
label: string;
|
||||
value?: string | null;
|
||||
onPickCamera: () => void;
|
||||
onPickLibrary: () => void;
|
||||
samples: Sample[];
|
||||
uploading?: boolean;
|
||||
}) {
|
||||
const [viewerVisible, setViewerVisible] = React.useState(false);
|
||||
const [viewerIndex, setViewerIndex] = React.useState(0);
|
||||
@@ -291,8 +337,14 @@ function UploadTile({
|
||||
onLongPress={onPickLibrary}
|
||||
onPress={onPickCamera}
|
||||
style={styles.uploader}
|
||||
disabled={uploading}
|
||||
>
|
||||
{value ? (
|
||||
{uploading ? (
|
||||
<View style={[styles.placeholder, { backgroundColor: '#f5f5f5' }]}>
|
||||
<ActivityIndicator size="large" color="#BBF246" />
|
||||
<Text style={styles.placeholderTitle}>上传中...</Text>
|
||||
</View>
|
||||
) : value ? (
|
||||
<Image source={{ uri: value }} style={styles.preview} />
|
||||
) : (
|
||||
<View style={styles.placeholder}>
|
||||
|
||||
Reference in New Issue
Block a user