請ChatGpt,Gmini,claude協助完成,可惜不是自架站,不然就可以嘗試將回應資料上傳伺服器了 。
這是一段可以留言的文章內容。你可以選擇其中的任何句子來留言。。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
這是另一段文章內容,同樣可以被選取與留言。
底下是網頁原始檔:
<meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title></title><style type="text/css">* { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', sans-serif; line-height: 1.6; background: #f5f5f5; color: #333; } .container { max-width: 1200px; margin: 0 auto; display: flex; gap: 20px; padding: 20px; } .article-section { flex: 2; background: white; border-radius: 12px; box-shadow: 0 2px 12px rgba(0,0,0,0.1); padding: 40px; } .comments-section { flex: 1; background: white; border-radius: 12px; box-shadow: 0 2px 12px rgba(0,0,0,0.1); padding: 20px; height: fit-content; position: sticky; top: 20px; } .article-title { font-size: 24px; font-weight: bold; margin-bottom: 20px; color: #1a1a1a; } .article-content { font-size: 16px; line-height: 1.8; color: #333; } .article-content p { margin-bottom: 20px; position: relative; } /* 選中文字的樣式 */ .selected-text { background: linear-gradient(120deg, #a8e6cf 0%, #dcedc1 100%); padding: 2px 4px; border-radius: 4px; position: relative; cursor: pointer; } /* 評論數量標記 */ .comment-count { display: inline-block; background: #ff6b6b; color: white; font-size: 12px; padding: 2px 6px; border-radius: 10px; margin-left: 5px; font-weight: bold; cursor: pointer; animation: pulse 0.3s ease-in-out; } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.1); } 100% { transform: scale(1); } } /* 評論彈窗 */ .comment-popup { position: fixed; background: white; border: 1px solid #e0e0e0; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.15); padding: 15px; width: 400px; z-index: 1000; display: none; } .comment-popup textarea { width: 100%; height: 100px; border: 1px solid #e0e0e0; border-radius: 6px; padding: 10px; font-size: 14px; resize: vertical; } .comment-popup-buttons { display: flex; gap: 10px; margin-top: 10px; justify-content: flex-end; } .btn { padding: 8px 16px; border: none; border-radius: 6px; cursor: pointer; font-size: 14px; transition: all 0.2s; } .btn-primary { background: #4CAF50; color: white; } .btn-primary:hover { background: #45a049; } .btn-secondary { background: #f5f5f5; color: #666; } .btn-secondary:hover { background: #e0e0e0; } /* 評論區域 */ .comments-header { font-size: 16px; font-weight: bold; margin-bottom: 20px; color: #1a1a1a; border-bottom: 2px solid #f0f0f0; padding-bottom: 10px; } .comment-item { margin-bottom: 20px; padding: 15px; background: #f9f9f9; border-radius: 8px; border-left: 4px solid #4CAF50; animation: slideIn 0.3s ease-out; } @keyframes slideIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .comment-user { font-weight: bold; color: #2c3e50; margin-bottom: 5px; } .comment-quote { background: white; padding: 8px 12px; border-radius: 6px; font-style: italic; color: #666; border-left: 3px solid #ddd; margin-bottom: 8px; } .comment-text { color: #333; line-height: 1.5; } .comment-time { font-size: 12px; color: #999; margin-top: 8px; } /* 使用者登錄區域 */ .user-login { margin-bottom: 20px; padding: 15px; background: #e8f5e8; border-radius: 8px; } .user-login input { width: 100%; padding: 8px 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 14px; } /* 選擇提示 */ .selection-hint { position: fixed; background: #333; color: white; padding: 8px 12px; border-radius: 6px; font-size: 12px; z-index: 999; display: none; pointer-events: none; } /* 回應式設計 */ @media (max-width: 768px) { .container { flex-direction: column; padding: 10px; } .article-section { padding: 20px; } .comments-section { position: static; } }</style><div class="container"><div class="article-section"><h1 class="article-title">這是文章標題</h1><div class="article-content" id="articleContent"><p>這是一段可以留言的文章內容。你可以選擇其中的任何句子來留言。。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p>這是另一段文章內容,同樣可以被選取與留言。</p><p> </p></div></div><div class="comments-section"><div class="user-login"><input id="username" placeholder="請輸入您的用戶名" type="text" value="訪客用戶" /></div><div class="comments-header">評論區 (<span id="commentCount">0</span>)</div><div id="commentsList"><!-- 評論將在這裡顯示 --></div></div></div><!-- 評論彈窗 --><div class="comment-popup" id="commentPopup"><textarea id="commentText" placeholder="寫下你的想法..."></textarea><div class="comment-popup-buttons"><button class="btn btn-secondary">取消</button><button class="btn btn-primary">發表</button></div></div><!-- 選擇提示 --><div class="selection-hint" id="selectionHint">選擇文字後點擊添加評論</div><script>let comments = [];let currentSelection = null;let commentIdCounter = 1;// 初始化window.addEventListener('DOMContentLoaded', () => { initializeParagraphIds(); initializeTextSelection(); updateCommentCount();});// 為每段文字加上唯一 IDfunction initializeParagraphIds() { const paragraphs = document.querySelectorAll('#articleContent p'); paragraphs.forEach((p, index) => { p.setAttribute('data-para-id', index); });}// 選取文字時處理function initializeTextSelection() { const articleContent = document.getElementById('articleContent'); articleContent.addEventListener('mouseup', handleTextSelection); articleContent.addEventListener('touchend', handleTextSelection); document.addEventListener('click', function(e) { if (!e.target.closest('.comment-popup') && !e.target.closest('#articleContent')) { clearSelection(); } });}function handleTextSelection(e) { const selection = window.getSelection(); const selectedText = selection.toString().trim(); if (!selectedText) return; const range = selection.getRangeAt(0); let para = range.startContainer; while (para && para.tagName !== 'P') { para = para.parentNode; } if (!para) return; const paraId = para.dataset.paraId; currentSelection = { text: selectedText, paraId: paraId }; // 改成智慧浮動定位 showCommentPopupFromSelection();}function showCommentPopupFromSelection() { const popup = document.getElementById('commentPopup'); const textarea = document.getElementById('commentText'); const width = 600; const height = 300; const selection = window.getSelection(); if (selection.rangeCount === 0) return; const range = selection.getRangeAt(0); const rect = range.getBoundingClientRect(); if (!rect) return; // 計算理想彈窗位置 let left = rect.left ; let top = rect.bottom ; // 避免超出畫面邊界(右邊與下方) if (left + width > window.innerWidth + window.scrollX) { left = window.innerWidth + window.scrollX - width - 20; } if (top + height > window.innerHeight + window.scrollY) { top = rect.top + window.scrollY - height - 10; } // 保底:避免超出上方與左邊 if (left < 0) left = 10; if (top < 0) top = 10; // 顯示彈窗 popup.style.left = left + 'px'; popup.style.top = top + 'px'; popup.style.display = 'block'; textarea.focus();}function closeCommentPopup() { document.getElementById('commentPopup').style.display = 'none'; document.getElementById('commentText').value = ''; clearSelection();}function clearSelection() { window.getSelection().removeAllRanges(); currentSelection = null;}function submitComment() { const text = document.getElementById('commentText').value.trim(); const user = document.getElementById('username').value.trim() || '匿名使用者'; const { text: quote, paraId } = currentSelection; if (!text || !quote || paraId == null) return; const key = `${paraId}::${quote}`; const comment = { id: commentIdCounter++, user: user, quote: quote, text: text, time: new Date().toLocaleString('zh-CN'), paraId: paraId, key: key }; comments.push(comment); highlightTextInParagraph(paraId, quote, key); updateCommentsDisplay(); updateCommentCount(); closeCommentPopup();}function highlightTextInParagraph(paraId, quoteText, key) { const p = document.querySelector(`p[data-para-id="${paraId}"]`); if (!p) return; const html = p.innerHTML; if (html.includes(`data-highlight="${key}"`)) { const countSpan = p.querySelector(`.selected-text[data-highlight="${key}"] .comment-count`); if (countSpan) { const count = parseInt(countSpan.textContent); countSpan.textContent = count + 1; } return; } const safeQuote = quoteText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); const pattern = new RegExp(`(${safeQuote})`); const replaced = html.replace(pattern, `<span class="selected-text" data-highlight="${key}">$1 <span class="comment-count">1</span></span>`); p.innerHTML = replaced; const span = p.querySelector(`.selected-text[data-highlight="${key}"]`); if (span) { span.onclick = () => scrollToComment(commentIdCounter - 1); }}function updateCommentsDisplay() { const list = document.getElementById('commentsList'); list.innerHTML = ''; comments.slice().reverse().forEach(comment => { const item = document.createElement('div'); item.className = 'comment-item'; item.setAttribute('data-comment-id', comment.id); item.innerHTML = ` <div class="comment-user">${comment.user}</div> <div class="comment-quote">"${comment.quote}"</div> <div class="comment-text">${comment.text}</div> <div class="comment-time">${comment.time}</div> `; list.appendChild(item); });}function scrollToComment(commentId) { const el = document.querySelector(`.comment-item[data-comment-id="${commentId}"]`); if (el) { el.scrollIntoView({ behavior: 'smooth', block: 'center' }); el.style.animation = 'pulse 0.6s ease-in-out'; setTimeout(() => el.style.animation = '', 600); }}function updateCommentCount() { document.getElementById('commentCount').textContent = comments.length;}// 快捷鍵支援document.querySelector('.btn-primary').addEventListener('click', submitComment);document.querySelector('.btn-secondary').addEventListener('click', closeCommentPopup);document.addEventListener('keydown', function(e) { if (e.key === 'Escape') closeCommentPopup(); if (e.ctrlKey && e.key === 'Enter' && document.getElementById('commentPopup').style.display === 'block') submitComment();});</script>
評論區 (0)
取消發表
選擇文字後點擊添加評論