Files
timeline-frontend/src/pages/gallery/components/GridView.tsx

106 lines
3.0 KiB
TypeScript
Raw Normal View History

// src/pages/gallery\components\GridView.tsx
2025-08-04 16:56:39 +08:00
import { ImageItem } from '@/pages/gallery/typings';
import { Spin } from 'antd';
import React, { FC, useCallback, useEffect, useState } from 'react';
import { useIsMobile } from '@/hooks/useIsMobile';
import PhotoCard from './PhotoCard';
2025-08-04 16:56:39 +08:00
import '../index.css';
interface GridViewProps {
imageList: ImageItem[];
viewMode: 'small' | 'large' | 'list' | 'table';
batchMode: boolean;
selectedRowKeys: string[];
onPreview: (index: number) => void;
onSelect: (instanceId: string, checked: boolean) => void;
onDownload: (instanceId: string, imageName: string) => void;
onDelete: (instanceId: string, imageName: string) => void;
loadingMore?: boolean;
onScroll: (e: React.UIEvent<HTMLDivElement>) => void;
}
const GridView: FC<GridViewProps> = ({
imageList,
viewMode,
batchMode,
selectedRowKeys,
onPreview,
onSelect,
onDownload,
onDelete,
loadingMore,
onScroll,
}) => {
const isMobile = useIsMobile();
const [windowWidth, setWindowWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWindowWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
2025-08-04 16:56:39 +08:00
const getImageSize = useCallback(() => {
if (isMobile) {
// Mobile: 3 columns for small, 2 columns for large
const padding = 16; // page padding
const gap = 8; // grid gap
if (viewMode === 'large') {
const size = (windowWidth - padding * 2 - gap) / 2;
return { width: size, height: size };
}
// default small
const size = (windowWidth - padding * 2 - gap * 2) / 3;
return { width: size, height: size };
}
2025-08-04 16:56:39 +08:00
switch (viewMode) {
case 'small':
return { width: 150, height: 150 };
case 'large':
return { width: 300, height: 300 };
default:
return { width: 150, height: 150 };
}
}, [viewMode, isMobile, windowWidth]);
2025-08-04 16:56:39 +08:00
const imageSize = getImageSize();
return (
<div
className={viewMode === 'small' ? 'small-grid-view' : 'large-grid-view'}
onScroll={onScroll}
style={isMobile ? {
display: 'grid',
gridTemplateColumns: viewMode === 'large' ? 'repeat(2, 1fr)' : 'repeat(3, 1fr)',
gap: '8px',
paddingBottom: '20px'
} : {}}
2025-08-04 16:56:39 +08:00
>
{imageList.map((item: ImageItem, index: number) => (
<PhotoCard
key={item.instanceId}
item={item}
index={index}
viewMode={viewMode}
batchMode={batchMode}
isSelected={selectedRowKeys.includes(item.instanceId)}
imageSize={imageSize}
isMobile={isMobile}
onPreview={onPreview}
onSelect={onSelect}
onDownload={onDownload}
onDelete={onDelete}
/>
2025-08-04 16:56:39 +08:00
))}
{loadingMore && (
<div style={{ gridColumn: '1 / -1', textAlign: 'center', padding: '20px' }}>
<Spin />
</div>
)}
</div>
);
};
export default GridView;