feat: 优化图片加载和展示功能
- 新增 SmartImage 组件优化图片加载体验 - 新增 ImageGrid 组件支持多图布局展示 - 新增 imageHelper 工具函数 - 优化 PostCard 帖子卡片图片展示 - 优化消息页面 SegmentRenderer - 优化日程页面 ScheduleScreen - 优化上传服务 uploadService
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
* 基于 expo-image 封装,原生支持 GIF/WebP 动图
|
||||
*/
|
||||
|
||||
import React, { useState, useCallback, useRef } from 'react';
|
||||
import React, { useState, useCallback, useRef, useEffect } from 'react';
|
||||
import {
|
||||
View,
|
||||
StyleSheet,
|
||||
@@ -55,6 +55,14 @@ export interface SmartImageProps {
|
||||
onError?: (error: any) => void;
|
||||
/** 测试ID */
|
||||
testID?: string;
|
||||
/** 预览图 URL */
|
||||
previewUrl?: string;
|
||||
/** 是否使用预览图(优先加载预览图) */
|
||||
usePreview?: boolean;
|
||||
/** 是否懒加载 */
|
||||
lazyLoad?: boolean;
|
||||
/** 缓存策略 */
|
||||
cachePolicy?: 'memory' | 'disk' | 'memory-disk' | 'none';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,14 +82,33 @@ export const SmartImage: React.FC<SmartImageProps> = ({
|
||||
onLoad,
|
||||
onError,
|
||||
testID,
|
||||
previewUrl,
|
||||
usePreview = false,
|
||||
lazyLoad = false,
|
||||
cachePolicy = 'memory-disk',
|
||||
}) => {
|
||||
const [loadState, setLoadState] = useState<ImageLoadState>('loading');
|
||||
const [isVisible, setIsVisible] = useState(!lazyLoad);
|
||||
const [shouldLoadOriginal, setShouldLoadOriginal] = useState(false);
|
||||
|
||||
// 解析图片源 - 支持 uri 或 url 字段
|
||||
const imageUri = typeof source === 'string'
|
||||
? source
|
||||
const imageUri = typeof source === 'string'
|
||||
? source
|
||||
: (source.uri || source.url || '');
|
||||
|
||||
// 解析预览图 URL
|
||||
const previewUri = typeof previewUrl === 'string' ? previewUrl : '';
|
||||
|
||||
// 智能选择图片 URL
|
||||
const getImageUrl = useCallback((): string => {
|
||||
// 如果应该加载原图(预览图已加载完成或没有预览图)
|
||||
if (shouldLoadOriginal || !usePreview || !previewUri) {
|
||||
return imageUri;
|
||||
}
|
||||
// 否则使用预览图
|
||||
return previewUri;
|
||||
}, [imageUri, previewUri, usePreview, shouldLoadOriginal]);
|
||||
|
||||
// 处理加载开始
|
||||
const handleLoadStart = useCallback(() => {
|
||||
setLoadState('loading');
|
||||
@@ -90,16 +117,25 @@ export const SmartImage: React.FC<SmartImageProps> = ({
|
||||
// 处理加载完成
|
||||
const handleLoad = useCallback(() => {
|
||||
setLoadState('success');
|
||||
// 如果正在加载预览图,切换到原图
|
||||
if (usePreview && !shouldLoadOriginal && previewUri && getImageUrl() === previewUri) {
|
||||
setShouldLoadOriginal(true);
|
||||
}
|
||||
onLoad?.();
|
||||
}, [onLoad]);
|
||||
}, [onLoad, usePreview, shouldLoadOriginal, previewUri, getImageUrl]);
|
||||
|
||||
// 处理加载错误
|
||||
const handleError = useCallback(
|
||||
(error: any) => {
|
||||
// 如果预览图加载失败,尝试加载原图
|
||||
if (usePreview && !shouldLoadOriginal && getImageUrl() === previewUri && imageUri) {
|
||||
setShouldLoadOriginal(true);
|
||||
return;
|
||||
}
|
||||
setLoadState('error');
|
||||
onError?.(error);
|
||||
},
|
||||
[onError]
|
||||
[onError, usePreview, shouldLoadOriginal, getImageUrl, previewUri, imageUri]
|
||||
);
|
||||
|
||||
// 重试加载
|
||||
@@ -144,7 +180,7 @@ export const SmartImage: React.FC<SmartImageProps> = ({
|
||||
};
|
||||
|
||||
// 图片源配置
|
||||
const imageSource = imageUri && imageUri.trim() !== '' ? { uri: imageUri } : undefined;
|
||||
const imageSource = imageUri && imageUri.trim() !== '' ? { uri: getImageUrl() } : undefined;
|
||||
|
||||
// 如果没有有效的图片源,显示错误占位
|
||||
if (!imageSource) {
|
||||
@@ -164,6 +200,16 @@ export const SmartImage: React.FC<SmartImageProps> = ({
|
||||
);
|
||||
}
|
||||
|
||||
// 如果是懒加载且不可见,显示占位
|
||||
if (lazyLoad && !isVisible) {
|
||||
return (
|
||||
<View
|
||||
style={[containerStyle, style as ViewStyle, { backgroundColor: '#F5F5F5' }]}
|
||||
testID={testID}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
style={[containerStyle, style as ViewStyle]}
|
||||
@@ -181,7 +227,7 @@ export const SmartImage: React.FC<SmartImageProps> = ({
|
||||
resizeMode === 'center' ? 'scale-down' :
|
||||
resizeMode
|
||||
}
|
||||
cachePolicy="memory-disk"
|
||||
cachePolicy={cachePolicy}
|
||||
onLoadStart={handleLoadStart}
|
||||
onLoad={handleLoad}
|
||||
onError={handleError}
|
||||
|
||||
Reference in New Issue
Block a user