New api and zone management; highligh occlusion and highlighAll functionality; improved search in reports and alerts history + autofill; refactored alert panel
This commit is contained in:
@@ -7,7 +7,7 @@ interface ObjectData {
|
||||
object_id: string
|
||||
title: string
|
||||
description: string
|
||||
image: string
|
||||
image: string | null
|
||||
location: string
|
||||
floors?: number
|
||||
area?: string
|
||||
@@ -45,6 +45,41 @@ const ObjectCard: React.FC<ObjectCardProps> = ({ object, onSelect, isSelected =
|
||||
// Логика редактирования объекта
|
||||
}
|
||||
|
||||
// Возврат к тестовому изображению, если src отсутствует/некорректен; нормализация относительных путей
|
||||
const resolveImageSrc = (src?: string | null): string => {
|
||||
if (!src || typeof src !== 'string') return '/images/test_image.png'
|
||||
let s = src.trim()
|
||||
if (!s) return '/images/test_image.png'
|
||||
|
||||
// Нормализуем обратные слеши в стиле Windows
|
||||
s = s.replace(/\\/g, '/')
|
||||
const lower = s.toLowerCase()
|
||||
|
||||
// Обрабатываем явный плейсхолдер test_image.png только как заглушку
|
||||
if (lower === 'test_image.png' || lower.endsWith('/test_image.png') || lower.includes('/public/images/test_image.png')) {
|
||||
return '/images/test_image.png'
|
||||
}
|
||||
|
||||
// Абсолютные URL
|
||||
if (s.startsWith('http://') || s.startsWith('https://')) return s
|
||||
|
||||
// Пути, относительные к сайту
|
||||
if (s.startsWith('/')) {
|
||||
// Преобразуем /public/images/... в /images/...
|
||||
if (/\/public\/images\//i.test(s)) {
|
||||
return s.replace(/\/public\/images\//i, '/images/')
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Нормализуем относительные имена ресурсов до путей сайта под /images
|
||||
// Убираем ведущий 'public/', если он присутствует
|
||||
s = s.replace(/^public\//i, '')
|
||||
return s.startsWith('images/') ? `/${s}` : `/images/${s}`
|
||||
}
|
||||
|
||||
const imgSrc = resolveImageSrc(object.image)
|
||||
|
||||
return (
|
||||
<article
|
||||
className={`flex flex-col w-full min-h-[414px] h-[414px] sm:h-auto sm:min-h-[350px] items-start gap-4 p-4 sm:p-6 relative bg-[#161824] rounded-[20px] overflow-hidden cursor-pointer transition-all duration-200 hover:bg-[#1a1d2e] ${
|
||||
@@ -85,13 +120,13 @@ const ObjectCard: React.FC<ObjectCardProps> = ({ object, onSelect, isSelected =
|
||||
<Image
|
||||
className="absolute w-full h-full top-0 left-0 object-cover"
|
||||
alt={object.title}
|
||||
src={object.image}
|
||||
src={imgSrc}
|
||||
fill
|
||||
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
|
||||
onError={(e) => {
|
||||
// Заглушка при ошибке загрузки изображения
|
||||
const target = e.target as HTMLImageElement
|
||||
target.src = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDUyIiBoZWlnaHQ9IjMwMiIgdmlld0JveD0iMCAwIDQ1MiAzMDIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSI0NTIiIGhlaWdodD0iMzAyIiBmaWxsPSIjRjFGMUYxIi8+CjxwYXRoIGQ9Ik0yMjYgMTUxTDI0NiAxMzFMMjY2IDE1MUwyNDYgMTcxTDIyNiAxNTFaIiBmaWxsPSIjOTk5OTk5Ii8+Cjx0ZXh0IHg9IjIyNiIgeT0iMTkwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjOTk5OTk5IiBmb250LXNpemU9IjE0Ij7QntCx0YrQtdC60YI8L3RleHQ+Cjwvc3ZnPgo='
|
||||
target.src = '/images/test_image.png'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user