From b9d669ede4532f4852adc1810a79221c35d29c7d Mon Sep 17 00:00:00 2001 From: JSR Date: Wed, 18 Mar 2026 18:37:53 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=AD=97=E6=AF=8D=E4=BE=A7?= =?UTF-8?q?=E8=BE=B9=E6=BB=91=E5=8A=A8=E4=BD=93=E9=AA=8C=E5=B9=B6=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=B0=B4=E6=BB=B4=E5=AD=97=E6=AF=8D=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Home.tsx | 85 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 80 insertions(+), 5 deletions(-) diff --git a/src/components/Home.tsx b/src/components/Home.tsx index 7a96e48..749b6f2 100644 --- a/src/components/Home.tsx +++ b/src/components/Home.tsx @@ -426,6 +426,27 @@ export const Home: React.FC<{ canEdit: boolean }> = ({ canEdit }) => { const navContainerRef = useRef(null) const isNavDragging = useRef(false) + const bodyUserSelectRef = useRef("") + const bodyWebkitUserSelectRef = useRef("") + const [navActiveKey, setNavActiveKey] = useState(null) + const [navIndicatorY, setNavIndicatorY] = useState(0) + const [navIndicatorVisible, setNavIndicatorVisible] = useState(false) + + const setNavDraggingState = useCallback((dragging: boolean) => { + isNavDragging.current = dragging + if (dragging) { + bodyUserSelectRef.current = document.body.style.userSelect + bodyWebkitUserSelectRef.current = document.body.style.webkitUserSelect + document.body.style.userSelect = "none" + document.body.style.webkitUserSelect = "none" + setNavIndicatorVisible(true) + return + } + + document.body.style.userSelect = bodyUserSelectRef.current + document.body.style.webkitUserSelect = bodyWebkitUserSelectRef.current + setNavIndicatorVisible(false) + }, []) const handleNavAction = useCallback( (clientY: number) => { @@ -442,6 +463,8 @@ export const Home: React.FC<{ canEdit: boolean }> = ({ canEdit }) => { const targetGroup = groupedStudents[safeIndex] if (targetGroup) { + setNavActiveKey(targetGroup.key) + setNavIndicatorY((safeIndex + 0.5) * itemHeight) scrollToGroup(targetGroup.key) } }, @@ -449,7 +472,8 @@ export const Home: React.FC<{ canEdit: boolean }> = ({ canEdit }) => { ) const onNavMouseDown = (e: React.MouseEvent) => { - isNavDragging.current = true + e.preventDefault() + setNavDraggingState(true) handleNavAction(e.clientY) document.addEventListener("mousemove", onGlobalMouseMove) document.addEventListener("mouseup", onGlobalMouseUp) @@ -457,21 +481,23 @@ export const Home: React.FC<{ canEdit: boolean }> = ({ canEdit }) => { const onGlobalMouseMove = (e: MouseEvent) => { if (isNavDragging.current) { + if (e.cancelable) e.preventDefault() handleNavAction(e.clientY) } } const onGlobalMouseUp = () => { - isNavDragging.current = false + setNavDraggingState(false) document.removeEventListener("mousemove", onGlobalMouseMove) document.removeEventListener("mouseup", onGlobalMouseUp) } const onNavTouchStart = (e: React.TouchEvent) => { - isNavDragging.current = true + setNavDraggingState(true) if (e.touches[0]) { handleNavAction(e.touches[0].clientY) } + if (e.cancelable) e.preventDefault() } const onNavTouchMove = (e: React.TouchEvent) => { @@ -482,9 +508,18 @@ export const Home: React.FC<{ canEdit: boolean }> = ({ canEdit }) => { } const onNavTouchEnd = () => { - isNavDragging.current = false + setNavDraggingState(false) } + useEffect(() => { + return () => { + document.removeEventListener("mousemove", onGlobalMouseMove) + document.removeEventListener("mouseup", onGlobalMouseUp) + document.body.style.userSelect = bodyUserSelectRef.current + document.body.style.webkitUserSelect = bodyWebkitUserSelectRef.current + } + }, []) + const renderQuickNav = () => { if ( groupedStudents.length <= 1 || @@ -500,6 +535,7 @@ export const Home: React.FC<{ canEdit: boolean }> = ({ canEdit }) => { onTouchStart={onNavTouchStart} onTouchMove={onNavTouchMove} onTouchEnd={onNavTouchEnd} + onContextMenu={(e) => e.preventDefault()} style={{ position: "fixed", right: "12px", @@ -519,6 +555,38 @@ export const Home: React.FC<{ canEdit: boolean }> = ({ canEdit }) => { touchAction: "none", }} > + {navIndicatorVisible && navActiveKey && ( +
+ + {navActiveKey} + +
+ )} {groupedStudents.map((group) => (
= ({ canEdit }) => { justifyContent: "center", fontSize: "11px", fontWeight: "bold", - color: "var(--ant-color-primary, #1890ff)", + color: + navIndicatorVisible && navActiveKey === group.key + ? "#ffffff" + : "var(--ant-color-primary, #1890ff)", borderRadius: "50%", + backgroundColor: + navIndicatorVisible && navActiveKey === group.key + ? "var(--ant-color-primary, #1890ff)" + : "transparent", pointerEvents: "none", }} >