From 19e50944d9078b9095e3f95ef960c46dd8d1a596 Mon Sep 17 00:00:00 2001 From: lkddi Date: Sat, 25 Apr 2026 13:43:55 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=81=E7=A7=BB=E5=89=8D=E5=8F=B0=E5=9F=BA?= =?UTF-8?q?=E7=A1=80=E9=A1=B5=E9=9D=A2=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/js/front.js | 133 ++++++++++++++++++++++ resources/views/guestbook/index.blade.php | 2 +- resources/views/layouts/app.blade.php | 1 + resources/views/rooms/guide.blade.php | 49 +------- resources/views/rooms/index.blade.php | 26 +---- vite.config.js | 1 + 6 files changed, 141 insertions(+), 71 deletions(-) create mode 100644 resources/js/front.js diff --git a/resources/js/front.js b/resources/js/front.js new file mode 100644 index 0000000..69f6425 --- /dev/null +++ b/resources/js/front.js @@ -0,0 +1,133 @@ +// 前台普通页面交互入口,集中管理确认弹窗、聊天室弹窗和说明页导航高亮。 + +let frontControlsBound = false; + +/** + * 读取元素上声明的确认文案,并在用户取消时拦截默认行为。 + * + * @param {Event} event + * @param {Element} element + * @param {string} attribute + * @returns {boolean} + */ +function confirmBeforeAction(event, element, attribute) { + const message = element.getAttribute(attribute); + if (!message || window.confirm(message)) { + return true; + } + + event.preventDefault(); + return false; +} + +/** + * 打开独立聊天室窗口,并尽量铺满当前可用屏幕。 + * + * @param {string} url + * @param {string} roomName + * @returns {void} + */ +function openChatRoomWindow(url, roomName) { + const chatWindow = window.open( + url, + `chatroom_${roomName}`, + "toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes", + ); + + if (!chatWindow) { + return; + } + + chatWindow.moveTo(0, 0); + chatWindow.resizeTo(window.screen.availWidth, window.screen.availHeight); + chatWindow.focus(); +} + +/** + * 绑定说明页右侧导航的可视区高亮。 + * + * @returns {void} + */ +function bindGuideNavigation() { + const aside = document.getElementById("guide-aside"); + const nav = document.getElementById("guide-nav"); + if (!aside || !nav) { + return; + } + + const checkWidth = () => { + aside.style.display = window.innerWidth >= 1024 ? "block" : "none"; + }; + checkWidth(); + window.addEventListener("resize", checkWidth); + + const links = Array.from(nav.querySelectorAll("a")); + const sections = links + .map((link) => { + const id = link.getAttribute("href")?.slice(1); + const element = id ? document.getElementById(id) : null; + + return element ? { element, link } : null; + }) + .filter(Boolean); + + const onScroll = () => { + let current = sections[0]; + sections.forEach((section) => { + if (section.element.getBoundingClientRect().top <= 120) { + current = section; + } + }); + + links.forEach((link) => link.classList.remove("active")); + current?.link.classList.add("active"); + }; + + window.addEventListener("scroll", onScroll, { passive: true }); + onScroll(); +} + +/** + * 绑定前台普通页面的轻量事件代理。 + * + * @returns {void} + */ +function bindFrontControls() { + if (frontControlsBound || typeof document === "undefined") { + return; + } + + frontControlsBound = true; + + document.addEventListener("click", (event) => { + if (!(event.target instanceof Element)) { + return; + } + + const submitButton = event.target.closest("[data-front-submit-confirm]"); + if (submitButton && !confirmBeforeAction(event, submitButton, "data-front-submit-confirm")) { + return; + } + + const roomLink = event.target.closest("[data-chat-room-window-url]"); + if (roomLink) { + event.preventDefault(); + openChatRoomWindow( + roomLink.getAttribute("data-chat-room-window-url") ?? "", + roomLink.getAttribute("data-chat-room-window-name") ?? "room", + ); + } + }); + + document.addEventListener("submit", (event) => { + if (!(event.target instanceof HTMLFormElement)) { + return; + } + + confirmBeforeAction(event, event.target, "data-front-confirm"); + }); + + bindGuideNavigation(); +} + +bindFrontControls(); diff --git a/resources/views/guestbook/index.blade.php b/resources/views/guestbook/index.blade.php index 5e42b89..d3f1a88 100644 --- a/resources/views/guestbook/index.blade.php +++ b/resources/views/guestbook/index.blade.php @@ -204,7 +204,7 @@ {{ \Carbon\Carbon::parse($msg->post_time)->diffForHumans() }} @if ($isFromMe || $isToMe || (Auth::check() && Auth::user()->user_level >= 15))
+ data-front-confirm="确定要抓除这条留言吗?" class="inline"> @csrf @method('DELETE') @@ -551,48 +551,3 @@ @endsection - -@section('scripts') - - -@endsection diff --git a/resources/views/rooms/index.blade.php b/resources/views/rooms/index.blade.php index 4943946..d1cb9f3 100644 --- a/resources/views/rooms/index.blade.php +++ b/resources/views/rooms/index.blade.php @@ -106,7 +106,7 @@ 转让 + data-front-confirm="警告:确实要彻底解散「{{ $room->name }}」吗?此操作不可逆!"> @csrf @method('delete') @@ -117,7 +117,8 @@ {{-- 进入按钮 --}} 立刻进入 → @@ -417,24 +418,3 @@ @endsection - -@section('scripts') - {{-- 原版风格:弹出独立聊天窗口 --}} - -@endsection diff --git a/vite.config.js b/vite.config.js index e03b379..0c53768 100644 --- a/vite.config.js +++ b/vite.config.js @@ -11,6 +11,7 @@ export default defineConfig({ "resources/js/app.js", "resources/js/chat.js", "resources/js/effects.js", + "resources/js/front.js", ], refresh: true, }),