From 5db41e9883c2226b3130b8397101237110566304 Mon Sep 17 00:00:00 2001 From: zenn Date: Fri, 3 Jul 2026 18:36:13 +0900 Subject: [PATCH] =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EC=A4=91=20=EC=A4=91=EB=B3=B5=20=ED=81=B4=EB=A6=AD?= =?UTF-8?q?=20=EC=B0=A8=EB=8B=A8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 이동 중 site-navigating 클래스로 링크·버튼 pointer-events를 끄는 클라이언트 플러그인 추가 - 게시물 재클릭 시 상단 점프 문제 해결, 안전 타임아웃으로 잠금 잔존 방지 - v1.10.34 Co-authored-by: Cursor --- assets/css/main.css | 10 ++++++++ docs/map.md | 1 + docs/update.md | 6 +++++ package.json | 2 +- plugins/navigation-lock.client.js | 40 +++++++++++++++++++++++++++++++ 5 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 plugins/navigation-lock.client.js diff --git a/assets/css/main.css b/assets/css/main.css index dda1e07..ba53e1b 100644 --- a/assets/css/main.css +++ b/assets/css/main.css @@ -94,6 +94,16 @@ overflow: hidden; } + html.site-navigating { + cursor: progress; + } + + html.site-navigating a, + html.site-navigating button, + html.site-navigating [role="button"] { + pointer-events: none; + } + body { min-width: 320px; margin: 0; diff --git a/docs/map.md b/docs/map.md index 3ef4694..d52fcba 100644 --- a/docs/map.md +++ b/docs/map.md @@ -361,6 +361,7 @@ | server/routes/admin/api/analytics/range-detail.get.js | 관리자 통계 추이 날짜·구간 상세 API | | plugins/site-analytics.client.js | 공개 라우트 pageview·heartbeat·read 클라이언트 전송 | | plugins/bfcache-page-restore.client.js | 뒤로가기 캐시(bfcache) 복원 시 라우터 경로와 실제 URL 어긋남을 감지해 새로고침(HTML 문서 모드 페이지 이동 후 뒤로가기 잔상 방지) | +| plugins/navigation-lock.client.js | 페이지 이동 중 `html.site-navigating` 클래스로 링크·버튼 클릭을 잠가 중복 클릭 차단(안전 타임아웃 포함) | ## 데이터베이스 diff --git a/docs/update.md b/docs/update.md index 832f039..98180be 100644 --- a/docs/update.md +++ b/docs/update.md @@ -1,5 +1,11 @@ # 업데이트 이력 +## v1.10.34 + +- 페이지 이동 중 링크·버튼 중복 클릭(연타) 차단 추가. +- 이동 중 `html.site-navigating` 클래스로 상호작용 요소 pointer-events를 끄는 클라이언트 플러그인 `navigation-lock.client.js` 추가(예외 방지 안전 타임아웃 포함). +- 게시물 클릭 후 재클릭 시 상단으로 점프하던 문제 해결. + ## v1.10.33 - HTML 문서 모드 페이지 뒤로가기 시 홈으로 돌아가지 못하던 문제를 근본 수정. diff --git a/package.json b/package.json index f389750..814eef1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sori.studio", - "version": "1.10.33", + "version": "1.10.34", "private": true, "type": "module", "imports": { diff --git a/plugins/navigation-lock.client.js b/plugins/navigation-lock.client.js new file mode 100644 index 0000000..cec860b --- /dev/null +++ b/plugins/navigation-lock.client.js @@ -0,0 +1,40 @@ +/** + * 페이지 이동 중 링크·버튼 클릭을 잠가 중복 클릭(연타)을 막는다. + * + * 이동 시작 시 `html.site-navigating` 클래스를 붙여 상호작용 요소의 pointer-events를 끄고, + * 이동 종료·실패 시 해제한다. 예외로 클래스가 남는 것을 막기 위해 안전 타임아웃을 둔다. + */ +const NAVIGATION_LOCK_CLASS = 'site-navigating' +const NAVIGATION_LOCK_TIMEOUT_MS = 10000 + +export default defineNuxtPlugin((nuxtApp) => { + const root = document.documentElement + + /** @type {ReturnType | null} */ + let releaseTimer = null + + /** + * 이동 잠금을 건다(안전 타임아웃 포함). + * @returns {void} + */ + const lockNavigation = () => { + root.classList.add(NAVIGATION_LOCK_CLASS) + clearTimeout(releaseTimer) + releaseTimer = setTimeout(() => { + root.classList.remove(NAVIGATION_LOCK_CLASS) + }, NAVIGATION_LOCK_TIMEOUT_MS) + } + + /** + * 이동 잠금을 해제한다. + * @returns {void} + */ + const unlockNavigation = () => { + clearTimeout(releaseTimer) + releaseTimer = null + root.classList.remove(NAVIGATION_LOCK_CLASS) + } + + nuxtApp.hook('page:loading:start', lockNavigation) + nuxtApp.hook('page:loading:end', unlockNavigation) +})