From 9481239fec03a9a109a3487d9cb783c483d3e2b5 Mon Sep 17 00:00:00 2001 From: tangshaojian <63377964@qq.com> Date: Fri, 25 Apr 2025 12:32:39 +0800 Subject: [PATCH] =?UTF-8?q?tsj:=20AreaSelector=20=E7=9A=84=E8=A1=8C?= =?UTF-8?q?=E6=94=BF=E5=8C=BA=E5=88=92=E7=9A=84=E6=8C=89=E9=92=AE=EF=BC=8C?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0hover=EF=BC=88=E5=B1=82=E7=BA=A7=E5=AF=BC?= =?UTF-8?q?=E8=88=AA=EF=BC=89=EF=BC=8C=E4=B8=8E=E7=82=B9=E5=87=BB=E7=9A=84?= =?UTF-8?q?=E8=A1=8C=E4=B8=BA=E5=8C=BA=E5=88=86=E5=BC=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MapContainer/AreaSelector/index.tsx | 146 ++++++++++++++---- 1 file changed, 117 insertions(+), 29 deletions(-) diff --git a/src/pages/Home_v_2504/components/MapContainer/AreaSelector/index.tsx b/src/pages/Home_v_2504/components/MapContainer/AreaSelector/index.tsx index de56f441..50a50ead 100644 --- a/src/pages/Home_v_2504/components/MapContainer/AreaSelector/index.tsx +++ b/src/pages/Home_v_2504/components/MapContainer/AreaSelector/index.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import classNames from 'classnames'; import styles from './index.less'; import { useGlobalModalServices } from '@/pages/GlobalModalServices/provider'; @@ -46,9 +46,17 @@ const AreaSelector: React.FC = ({ mapInstance }) => { const [activeLevel2, setActiveLevel2] = useState(null); const [activeLevel3, setActiveLevel3] = useState(null); + // 悬停状态管理 + const [hoverLevel1, setHoverLevel1] = useState(null); + const [hoverLevel2, setHoverLevel2] = useState(null); + + // 悬停计时器 + const hoverTimerRef = useRef(null); + // 控制第二层、第三层按钮组的显示 - const showLevel2 = activeLevel1 && buttonGroupData.level2[activeLevel1]; - const showLevel3 = activeLevel2 && buttonGroupData.level3[activeLevel2]; + // 使用 hover 或 active 状态来控制显示 + const showLevel2 = (hoverLevel1 || activeLevel1) && buttonGroupData.level2[hoverLevel1 || activeLevel1 || '']; + const showLevel3 = (hoverLevel2 || activeLevel2) && buttonGroupData.level3[hoverLevel2 || activeLevel2 || '']; // 初始化时从 JSON 加载区域树数据 useEffect(() => { @@ -140,26 +148,86 @@ const AreaSelector: React.FC = ({ mapInstance }) => { } }; + // 处理第一层行政区划按钮悬停 + const handleLevel1Hover = (key: string, hasChildren?: boolean) => { + // 只处理行政区划按钮的悬停(成都市) + if (key === 'chengdu' && hasChildren) { + clearTimeout(hoverTimerRef.current); + hoverTimerRef.current = setTimeout(() => { + setHoverLevel1(key); + }, 300); // 300ms 延迟,防止鼠标快速划过时触发 + } + }; + + // 处理第二层行政区划按钮悬停 + const handleLevel2Hover = (key: string, hasChildren?: boolean) => { + if (hasChildren) { + clearTimeout(hoverTimerRef.current); + hoverTimerRef.current = setTimeout(() => { + setHoverLevel2(key); + }, 300); + } + }; + + // 处理鼠标离开 + const handleMouseLeave = (level: number) => { + clearTimeout(hoverTimerRef.current); + + // 延迟清除悬停状态,给用户一些时间移动到子菜单 + hoverTimerRef.current = setTimeout(() => { + if (level === 1) { + setHoverLevel1(null); + } else if (level === 2) { + setHoverLevel2(null); + } + }, 300); + }; + + // 处理子菜单鼠标进入,取消清除悬停状态的计时器 + const handleSubMenuMouseEnter = () => { + clearTimeout(hoverTimerRef.current); + }; + // 处理第一层按钮点击 const handleLevel1Click = (key: string, hasChildren?: boolean, regionCode?: string, dataCode?: string) => { + // 处理特殊功能按钮 if (key === 'oilSmokeAlert') { // 点击油烟告警按钮,显示弹窗 dispatch.push('RestaurantOilAlarm'); + + // 发送数据类型变化事件 + const dataTypeChangeEvent = new CustomEvent('mapDataTypeChange', { + detail: { dataCode: '20102' } + }); + window.dispatchEvent(dataTypeChangeEvent); return; } if (key === 'restaurant') { // 点击餐饮企业按钮,显示弹窗 dispatch.push('RestaurantOilFacility'); + + // 发送数据类型变化事件 + const dataTypeChangeEvent = new CustomEvent('mapDataTypeChange', { + detail: { dataCode: '20103' } + }); + window.dispatchEvent(dataTypeChangeEvent); return; } + if (key === 'oilSmoke') { + // 发送数据类型变化事件 + const dataTypeChangeEvent = new CustomEvent('mapDataTypeChange', { + detail: { dataCode: '20101' } + }); + window.dispatchEvent(dataTypeChangeEvent); + } + + // 处理行政区划按钮点击 - 激活状态切换 if (activeLevel1 === key) { - // 如果点击当前已激活的按钮,则取消选中 setActiveLevel1(null); setActiveLevel2(null); } else { - // 否则激活该按钮 setActiveLevel1(key); setActiveLevel2(null); } @@ -173,10 +241,8 @@ const AreaSelector: React.FC = ({ mapInstance }) => { // 处理第二层按钮点击 const handleLevel2Click = (key: string, hasChildren?: boolean, regionCode?: string) => { if (activeLevel2 === key) { - // 如果点击当前已激活的按钮,则取消选中 setActiveLevel2(null); } else { - // 否则激活该按钮 setActiveLevel2(key); } @@ -204,40 +270,59 @@ const AreaSelector: React.FC = ({ mapInstance }) => { } }, [mapInstance]); + // 清除定时器 + useEffect(() => { + return () => { + clearTimeout(hoverTimerRef.current); + }; + }, []); + return (
{/* 第一层按钮组 */}
- {buttonGroupData.level1.map((button) => ( -
handleLevel1Click(button.key, button.hasChildren, button.regionCode, button.dataCode)} - > - {button.label} - {activeLevel1 === button.key && button.hasChildren && ( - - )} -
- ))} + {buttonGroupData.level1.map((button) => { + // 判断是否为行政区划按钮 + const isAdminButton = button.key === 'chengdu'; + + return ( +
handleLevel1Click(button.key, button.hasChildren, button.regionCode, button.dataCode)} + onMouseEnter={isAdminButton ? () => handleLevel1Hover(button.key, button.hasChildren) : undefined} + onMouseLeave={isAdminButton ? () => handleMouseLeave(1) : undefined} + > + {button.label} + {(activeLevel1 === button.key || hoverLevel1 === button.key) && button.hasChildren && ( + + )} +
+ ); + })}
{/* 第二层按钮组 */} {showLevel2 && ( -
- {buttonGroupData.level2[activeLevel1!].map((button) => ( +
handleMouseLeave(2)} + > + {buttonGroupData.level2[hoverLevel1 || activeLevel1 || ''].map((button) => (
handleLevel2Click(button.key, button.hasChildren, button.regionCode)} + onMouseEnter={button.hasChildren ? () => handleLevel2Hover(button.key, button.hasChildren) : undefined} > {button.label}
@@ -247,8 +332,11 @@ const AreaSelector: React.FC = ({ mapInstance }) => { {/* 第三层按钮组 */} {showLevel3 && ( -
- {buttonGroupData.level3[activeLevel2!].map((button) => ( +
+ {buttonGroupData.level3[hoverLevel2 || activeLevel2 || ''].map((button) => (