- ImageStrategyGroup/ImageLightbox/RegenControls/ImportTextModal/ RejectReasonBanner 新建组件 - tasks images/text/new + history + 配置/布局/SSE hooks 存量改动 - 总核销表进度更新 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
58 lines
1.7 KiB
TypeScript
58 lines
1.7 KiB
TypeScript
'use client';
|
||
// ImageLightbox — 点击挑图卡片放大看全图(解决"只看半截"),ESC/点遮罩关闭
|
||
import { useEffect } from 'react';
|
||
|
||
interface ImageLightboxProps {
|
||
url: string | null;
|
||
caption?: string;
|
||
onClose: () => void;
|
||
}
|
||
|
||
export function ImageLightbox({ url, caption, onClose }: ImageLightboxProps) {
|
||
useEffect(() => {
|
||
if (!url) return;
|
||
const onKey = (e: KeyboardEvent) => {
|
||
if (e.key === 'Escape') onClose();
|
||
};
|
||
window.addEventListener('keydown', onKey);
|
||
// 打开时锁滚动,关闭时恢复
|
||
const prev = document.body.style.overflow;
|
||
document.body.style.overflow = 'hidden';
|
||
return () => {
|
||
window.removeEventListener('keydown', onKey);
|
||
document.body.style.overflow = prev;
|
||
};
|
||
}, [url, onClose]);
|
||
|
||
if (!url) return null;
|
||
|
||
return (
|
||
<div
|
||
role="dialog"
|
||
aria-modal="true"
|
||
aria-label="图片放大预览"
|
||
onClick={onClose}
|
||
className="fixed inset-0 z-50 flex items-center justify-center bg-black/80 p-4"
|
||
>
|
||
<div className="relative max-h-full max-w-3xl" onClick={(e) => e.stopPropagation()}>
|
||
<button
|
||
onClick={onClose}
|
||
aria-label="关闭预览"
|
||
className="absolute -top-3 -right-3 z-10 h-9 w-9 rounded-full bg-white text-gray-700 shadow-lg hover:bg-gray-100"
|
||
>
|
||
✕
|
||
</button>
|
||
{/* 原图按真实比例完整展示,不裁切 */}
|
||
<img
|
||
src={url}
|
||
alt={caption || '放大预览'}
|
||
className="max-h-[85vh] w-auto rounded-lg object-contain"
|
||
/>
|
||
{caption && (
|
||
<p className="mt-2 text-center text-sm text-white/90">{caption}</p>
|
||
)}
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|