| 
			  
			<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(); 
			}); 
			// 為每段文字加上唯一 ID 
			function 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> 
			 |