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 对话侧栏 ===== */}