Добавлено получение баннеров для главного слайдера с использованием GraphQL. Обновлен компонент HeroSlider для отображения активных баннеров с сортировкой. Реализована логика отображения дефолтного баннера при отсутствии данных. Обновлены стили и структура компонента для улучшения пользовательского интерфейса.
This commit is contained in:
@ -404,16 +404,19 @@ const KnotIn: React.FC<KnotInProps> = ({
|
||||
onClick={() => setIsImageModalOpen(false)}
|
||||
style={{ cursor: 'zoom-out' }}
|
||||
>
|
||||
<img
|
||||
src={imageUrl}
|
||||
alt={unitName || unitInfo?.name || "Изображение узла"}
|
||||
className="max-h-[90vh] max-w-[90vw] rounded shadow-lg"
|
||||
onClick={e => e.stopPropagation()}
|
||||
style={{ background: '#fff' }}
|
||||
/>
|
||||
<div className="relative">
|
||||
<img
|
||||
src={imageUrl}
|
||||
alt={unitName || unitInfo?.name || "Изображение узла"}
|
||||
className="max-h-[90vh] max-w-[90vw] rounded shadow-lg"
|
||||
onClick={e => e.stopPropagation()}
|
||||
style={{ background: '#fff' }}
|
||||
/>
|
||||
{/* Убираем интерактивные точки в модальном окне */}
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setIsImageModalOpen(false)}
|
||||
className="absolute top-4 right-4 text-white text-3xl font-bold bg-black bg-opacity-40 rounded-full w-10 h-10 flex items-center justify-center"
|
||||
className="absolute top-4 right-4 text-white text-3xl font-bold bg-black bg-opacity-40 rounded-full w-10 h-10 flex items-center justify-center hover:bg-black hover:bg-opacity-60 transition-colors"
|
||||
aria-label="Закрыть"
|
||||
style={{ zIndex: 10000 }}
|
||||
>
|
||||
|
@ -36,7 +36,9 @@ const KnotParts: React.FC<KnotPartsProps> = ({
|
||||
const [showTooltip, setShowTooltip] = useState(false);
|
||||
const [tooltipPosition, setTooltipPosition] = useState({ x: 0, y: 0 });
|
||||
const [tooltipPart, setTooltipPart] = useState<any>(null);
|
||||
const [clickedPart, setClickedPart] = useState<string | number | null>(null);
|
||||
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||
const clickTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
// Отладочные логи для проверки данных
|
||||
React.useEffect(() => {
|
||||
@ -63,8 +65,31 @@ const KnotParts: React.FC<KnotPartsProps> = ({
|
||||
|
||||
// Обработчик клика по детали в списке
|
||||
const handlePartClick = (part: any) => {
|
||||
if (part.codeonimage && onPartSelect) {
|
||||
onPartSelect(part.codeonimage);
|
||||
const codeOnImage = part.codeonimage || part.detailid;
|
||||
if (codeOnImage && onPartSelect) {
|
||||
onPartSelect(codeOnImage);
|
||||
}
|
||||
|
||||
// Также подсвечиваем деталь на схеме при клике
|
||||
if (codeOnImage && onPartHover) {
|
||||
// Очищаем предыдущий таймер, если он есть
|
||||
if (clickTimeoutRef.current) {
|
||||
clearTimeout(clickTimeoutRef.current);
|
||||
}
|
||||
|
||||
// Устанавливаем состояние кликнутой детали
|
||||
setClickedPart(codeOnImage);
|
||||
|
||||
// Подсвечиваем на схеме
|
||||
onPartHover(codeOnImage);
|
||||
|
||||
// Убираем подсветку через интервал
|
||||
clickTimeoutRef.current = setTimeout(() => {
|
||||
setClickedPart(null);
|
||||
if (onPartHover) {
|
||||
onPartHover(null);
|
||||
}
|
||||
}, 1500); // Подсветка будет видна 1.5 секунды
|
||||
}
|
||||
};
|
||||
|
||||
@ -150,6 +175,9 @@ const KnotParts: React.FC<KnotPartsProps> = ({
|
||||
if (timeoutRef.current) {
|
||||
clearTimeout(timeoutRef.current);
|
||||
}
|
||||
if (clickTimeoutRef.current) {
|
||||
clearTimeout(clickTimeoutRef.current);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
@ -213,12 +241,17 @@ const KnotParts: React.FC<KnotPartsProps> = ({
|
||||
|
||||
<div className="knot-parts">
|
||||
{parts.map((part, idx) => {
|
||||
const codeOnImage = part.codeonimage || part.detailid;
|
||||
const isHighlighted = highlightedCodeOnImage !== null && highlightedCodeOnImage !== undefined && (
|
||||
(part.codeonimage && part.codeonimage.toString() === highlightedCodeOnImage.toString()) ||
|
||||
(part.detailid && part.detailid.toString() === highlightedCodeOnImage.toString())
|
||||
);
|
||||
|
||||
const isSelected = selectedParts.has(part.detailid || part.codeonimage || idx.toString());
|
||||
const isClicked = clickedPart !== null && (
|
||||
(part.codeonimage && part.codeonimage.toString() === clickedPart.toString()) ||
|
||||
(part.detailid && part.detailid.toString() === clickedPart.toString())
|
||||
);
|
||||
|
||||
// Создаем уникальный ключ
|
||||
const uniqueKey = `part-${idx}-${part.detailid || part.oem || part.name || 'unknown'}`;
|
||||
@ -226,12 +259,14 @@ const KnotParts: React.FC<KnotPartsProps> = ({
|
||||
return (
|
||||
<div
|
||||
key={uniqueKey}
|
||||
className={`w-layout-hflex knotlistitem rounded-lg cursor-pointer transition-colors ${
|
||||
className={`w-layout-hflex knotlistitem rounded-lg cursor-pointer transition-all duration-300 ${
|
||||
isSelected
|
||||
? 'bg-green-100 border-green-500'
|
||||
: isHighlighted
|
||||
? 'bg-slate-200'
|
||||
: 'bg-white border-gray-200 hover:border-gray-300'
|
||||
: isClicked
|
||||
? 'bg-red-100 border-red-400 shadow-md'
|
||||
: isHighlighted
|
||||
? 'bg-slate-200'
|
||||
: 'bg-white border-gray-200 hover:border-gray-300'
|
||||
}`}
|
||||
onClick={() => handlePartClick(part)}
|
||||
onMouseEnter={() => handlePartMouseEnter(part)}
|
||||
@ -240,13 +275,37 @@ const KnotParts: React.FC<KnotPartsProps> = ({
|
||||
>
|
||||
<div className="w-layout-hflex flex-block-116">
|
||||
<div
|
||||
className={`nuberlist ${isSelected ? 'text-green-700 font-bold' : isHighlighted ? ' font-bold' : ''}`}
|
||||
className={`nuberlist ${
|
||||
isSelected
|
||||
? 'text-green-700 font-bold'
|
||||
: isClicked
|
||||
? 'text-red-700 font-bold'
|
||||
: isHighlighted
|
||||
? 'font-bold'
|
||||
: ''
|
||||
}`}
|
||||
>
|
||||
{part.codeonimage || idx + 1}
|
||||
</div>
|
||||
<div className={`oemnuber ${isSelected ? 'text-green-800 font-semibold' : isHighlighted ? ' font-semibold' : ''}`}>{part.oem}</div>
|
||||
<div className={`oemnuber ${
|
||||
isSelected
|
||||
? 'text-green-800 font-semibold'
|
||||
: isClicked
|
||||
? 'text-red-800 font-semibold'
|
||||
: isHighlighted
|
||||
? 'font-semibold'
|
||||
: ''
|
||||
}`}>{part.oem}</div>
|
||||
</div>
|
||||
<div className={`partsname ${isSelected ? 'text-green-800 font-semibold' : isHighlighted ? ' font-semibold' : ''}`}>
|
||||
<div className={`partsname ${
|
||||
isSelected
|
||||
? 'text-green-800 font-semibold'
|
||||
: isClicked
|
||||
? 'text-red-800 font-semibold'
|
||||
: isHighlighted
|
||||
? 'font-semibold'
|
||||
: ''
|
||||
}`}>
|
||||
{part.name}
|
||||
</div>
|
||||
<div className="w-layout-hflex flex-block-117">
|
||||
|
Reference in New Issue
Block a user