diff --git a/app/page.js b/app/page.js index 0a82e2b..decc51c 100644 --- a/app/page.js +++ b/app/page.js @@ -295,64 +295,108 @@ export default function Home() { )} - {/* GitHub 链接 */} - e.currentTarget.style.opacity = '1'} - onMouseLeave={(e) => e.currentTarget.style.opacity = '0.8'} - title="GitHub" - > - - - - - - {/* 帮助与向导按钮 */} - + {/* 可拖动浮动按钮组 */} + {(() => { + const STORAGE_KEY = 'author-fab-pos'; + const saved = typeof window !== 'undefined' ? JSON.parse(localStorage.getItem(STORAGE_KEY) || 'null') : null; + const defaultPos = { right: 24, bottom: 24 }; + return ( +
{ + if (e.target.closest('a') || (e.target.tagName === 'BUTTON' && !e.target.classList.contains('fab-drag-handle'))) return; + const el = e.currentTarget; + const rect = el.getBoundingClientRect(); + const parentRect = el.parentElement.getBoundingClientRect(); + const offsetX = e.clientX - rect.left; + const offsetY = e.clientY - rect.top; + el.style.cursor = 'grabbing'; + let moved = false; + const onMove = (ev) => { + moved = true; + const newRight = parentRect.right - ev.clientX - (rect.width - offsetX); + const newBottom = parentRect.bottom - ev.clientY - (rect.height - offsetY); + const clampedRight = Math.max(0, Math.min(parentRect.width - rect.width, newRight)); + const clampedBottom = Math.max(0, Math.min(parentRect.height - rect.height, newBottom)); + el.style.right = `${clampedRight}px`; + el.style.bottom = `${clampedBottom}px`; + }; + const onUp = () => { + el.style.cursor = 'grab'; + document.removeEventListener('pointermove', onMove); + document.removeEventListener('pointerup', onUp); + if (moved) { + localStorage.setItem(STORAGE_KEY, JSON.stringify({ + right: parseInt(el.style.right), + bottom: parseInt(el.style.bottom), + })); + } + }; + document.addEventListener('pointermove', onMove); + document.addEventListener('pointerup', onUp); + }} + > + e.currentTarget.style.opacity = '1'} + onMouseLeave={(e) => e.currentTarget.style.opacity = '0.8'} + title="GitHub" + > + + + + + +
+ ); + })()} {/* ===== AI 对话侧栏 ===== */}