/** * editor-v3.js - 三栏布局交互增强 * 版本: 3.0 * 功能: 卡片折叠、浮动面板、平台选择弹窗、封面图改进 */ // ==================== 卡片折叠功能 ==================== /** * 切换卡片折叠/展开状态 * @param {string} cardId - 卡片ID */ function toggleCard(cardId) { const card = document.getElementById(cardId); if (!card) return; card.classList.toggle('collapsed'); // 保存状态到 localStorage const isCollapsed = card.classList.contains('collapsed'); localStorage.setItem(`card_${cardId}_collapsed`, isCollapsed); } /** * 初始化卡片状态(从 localStorage 恢复) */ function initCardStates() { const cardIds = ['contentStatsCard']; // 仅保留真实存在的卡片;大纲/版本卡片已移除 cardIds.forEach(cardId => { const card = document.getElementById(cardId); if (!card) return; const isCollapsed = localStorage.getItem(`card_${cardId}_collapsed`) === 'true'; if (isCollapsed) { card.classList.add('collapsed'); } }); } // ==================== 浮动面板功能 ==================== /** * 切换浮动面板显示/隐藏 * @param {string} panelId - 面板ID */ function toggleFloatingPanel(panelId) { const panel = document.getElementById(panelId); if (!panel) return; // 关闭其他面板 document.querySelectorAll('.floating-panel').forEach(p => { if (p.id !== panelId) { p.classList.remove('active'); } }); // 切换当前面板 panel.classList.toggle('active'); // 如果面板打开,触发相应更新 if (panel.classList.contains('active')) { if (panelId === 'healthPanel') { updateHealthCheck(); } else if (panelId === 'internalLinksPanel') { updateInternalLinks(); } } } /** * 关闭浮动面板 * @param {string} panelId - 面板ID */ function closeFloatingPanel(panelId) { const panel = document.getElementById(panelId); if (panel) { panel.classList.remove('active'); } } /** * 初始化浮动按钮事件 */ function initFloatingButtons() { // 点击页面其他地方关闭面板 document.addEventListener('click', (e) => { const floatingButtons = document.querySelector('.floating-buttons'); const floatingPanels = document.querySelectorAll('.floating-panel'); // 如果点击的不是浮动按钮或面板,关闭所有面板 if (!floatingButtons.contains(e.target)) { let clickedPanel = false; floatingPanels.forEach(panel => { if (panel.contains(e.target)) { clickedPanel = true; } }); if (!clickedPanel) { floatingPanels.forEach(panel => panel.classList.remove('active')); } } }); } // ==================== 封面图功能改进 ==================== /** * 上传封面图 */ function uploadCover() { const input = document.getElementById('coverFileInput'); if (input) { input.click(); } } // 让整个封面预览区点击也能触发上传(不只能点"更换"按钮) (function bindCoverPreviewClick() { const preview = document.getElementById('coverPreview'); if (preview && !preview.dataset.coverBound) { preview.dataset.coverBound = '1'; preview.style.cursor = 'pointer'; preview.addEventListener('click', function (e) { if (e.target.closest('.cover-action-btn')) return; uploadCover(); }); } })(); // 让整个封面预览区点击也能触发上传 (function bindCoverPreviewClick() { const preview = document.getElementById('coverPreview'); if (preview && !preview.dataset.coverBound) { preview.dataset.coverBound = '1'; preview.style.cursor = 'pointer'; preview.addEventListener('click', function(e) { // 避免与内部"更换/裁剪/删除"按钮冲突 if (e.target.closest('.cover-action-btn')) return; uploadCover(); }); } })(); /** * 上传封面图(真实定义) */ function uploadCover() { const input = document.getElementById('coverFileInput'); if (input) { input.click(); } } // 让整个封面预览区点击也能触发上传(不只能点"更换"按钮) (function bindCoverPreviewClick() { const preview = document.getElementById('coverPreview'); if (preview && !preview.dataset.coverBound) { preview.dataset.coverBound = '1'; preview.style.cursor = 'pointer'; preview.addEventListener('click', function (e) { if (e.target.closest('.cover-action-btn')) return; uploadCover(); }); } })(); /** * 处理封面图文件选择 * @param {Event} event - 文件输入事件 */ // ==================== 视频上传功能改进 ==================== /** * 处理视频文件选择 * @param {Event} event - 文件输入事件 */ function handleVideoFile(event) { const file = event.target.files[0]; if (!file) return; // 验证文件类型 if (!file.type.startsWith('video/')) { showNotification('请选择视频文件', 'error'); return; } // 验证文件大小(最大 500MB) if (file.size > 500 * 1024 * 1024) { showNotification('视频大小不能超过 500MB', 'error'); return; } // 显示视频预览 const url = URL.createObjectURL(file); const player = document.getElementById('videoPlayer'); if (player) { player.src = url; const preview = document.getElementById('videoPreview'); if (preview) { preview.style.display = ''; } const uploadArea = document.getElementById('videoUploadArea'); if (uploadArea) { uploadArea.style.display = 'none'; } // 显示文件信息 const fileName = document.getElementById('videoFileName'); if (fileName) { fileName.textContent = file.name; } const fileSize = document.getElementById('videoFileSize'); if (fileSize) { fileSize.textContent = formatFileSize(file.size); } } } /** * 删除视频 */ function deleteVideo() { const preview = document.getElementById('videoPreview'); if (preview) { preview.style.display = 'none'; } const player = document.getElementById('videoPlayer'); if (player) { player.src = ''; } const uploadArea = document.getElementById('videoUploadArea'); if (uploadArea) { uploadArea.style.display = ''; } const input = document.getElementById('videoFileInput'); if (input) { input.value = ''; } } /** * 格式化文件大小 * @param {number} bytes - 字节数 * @returns {string} 格式化的大小字符串 */ function formatFileSize(bytes) { if (bytes === 0) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; } // ==================== 内容健康度更新 ==================== /** * 更新内容健康度 */ function updateHealthCheck() { // 这里应该调用实际的健康度检查逻辑 // 目前使用模拟数据 const score = calculateHealthScore(); updateHealthDisplay(score); } /** * 计算健康度分数 * @returns {number} 健康度分数 (0-100) */ function calculateHealthScore() { // 获取编辑器内容 const editorContent = document.getElementById('editor-container'); if (!editorContent) return 0; const text = editorContent.innerText || ''; const wordCount = text.trim().split(/\s+/).length; // 简单的评分逻辑 let score = 0; // 字数评分 if (wordCount >= 800) score += 40; else if (wordCount >= 500) score += 30; else if (wordCount >= 300) score += 20; else if (wordCount >= 100) score += 10; // 标题评分 const hasTitle = document.getElementById('articleTitle')?.value?.trim().length > 0; if (hasTitle) score += 20; // 摘要评分 const hasSummary = document.getElementById('articleSummary')?.value?.trim().length > 0; if (hasSummary) score += 20; // 封面评分 const hasCover = document.getElementById('coverPreviewImg')?.src; if (hasCover) score += 20; return Math.min(score, 100); } /** * 更新健康度显示 * @param {number} score - 健康度分数 */ function updateHealthDisplay(score) { // 更新圆环 const circle = document.getElementById('healthScoreCircle'); if (circle) { const circumference = 2 * Math.PI * 45; // r = 45 const offset = circumference - (score / 100) * circumference; circle.style.strokeDashoffset = offset; } // 更新分数文字 const scoreText = document.getElementById('healthScoreText'); if (scoreText) { scoreText.textContent = score; } // 更新状态文字 const statusText = document.getElementById('healthStatusText'); if (statusText) { if (score >= 80) { statusText.textContent = '内容质量优秀!'; statusText.style.color = '#10b981'; } else if (score >= 60) { statusText.textContent = '内容质量良好'; statusText.style.color = '#f59e0b'; } else if (score >= 40) { statusText.textContent = '内容质量一般'; statusText.style.color = '#f97316'; } else { statusText.textContent = '内容需要完善'; statusText.style.color = '#ef4444'; } } // 更新建议 updateHealthSuggestions(score); } /** * 更新健康度建议 * @param {number} score - 健康度分数 */ function updateHealthSuggestions(score) { const suggestionsContainer = document.getElementById('healthSuggestions'); if (!suggestionsContainer) return; const suggestions = []; if (score < 40) { suggestions.push({ icon: '📝', text: '建议增加文章字数,当前内容过少' }); suggestions.push({ icon: '🏷️', text: '添加文章标题和摘要' }); suggestions.push({ icon: '🖼️', text: '上传封面图提升吸引力' }); } else if (score < 60) { suggestions.push({ icon: '📊', text: '内容字数适中,可以考虑增加更多细节' }); suggestions.push({ icon: '🔗', text: '添加内部链接提升 SEO' }); } else if (score < 80) { suggestions.push({ icon: '✅', text: '内容质量良好,可以继续优化' }); suggestions.push({ icon: '🏷️', text: '检查标签和分类是否准确' }); } else { suggestions.push({ icon: '🎉', text: '内容质量优秀,可以发布了!' }); } suggestionsContainer.innerHTML = suggestions.map(s => `
${s.icon} ${s.text}
`).join(''); } // ==================== 内部链接更新 ==================== /** * 更新内部链接建议 */ function updateInternalLinks() { // 这里应该调用实际的内部链接分析逻辑 // 目前显示加载状态 const panel = document.getElementById('internalLinksPanelBody'); if (panel) { panel.innerHTML = `

正在分析内容...

`; // 模拟延迟 setTimeout(() => { panel.innerHTML = `
🔗 内部链接分析功能正在完善中...
`; }, 1500); } } // ==================== 通知功能 ==================== /** * 显示通知 * @param {string} message - 通知消息 * @param {string} type - 通知类型 (success/error/warning/info) */ function showNotification(message, type = 'info') { // 创建通知元素 const notification = document.createElement('div'); notification.style.cssText = ` position: fixed; top: 20px; right: 20px; padding: 16px 24px; background: var(--surface); border-radius: 12px; box-shadow: 0 8px 30px rgba(0,0,0,0.15); z-index: 10000; animation: slideInRight 0.3s ease; display: flex; align-items: center; gap: 12px; max-width: 400px; `; // 根据类型设置图标和颜色 const icons = { success: '✅', error: '❌', warning: '⚠️', info: 'ℹ️' }; const colors = { success: '#10b981', error: '#ef4444', warning: '#f59e0b', info: '#6366f1' }; notification.innerHTML = ` ${icons[type] || icons.info} ${message} `; notification.style.borderLeft = `4px solid ${colors[type] || colors.info}`; // 添加到页面 document.body.appendChild(notification); // 3秒后自动移除 setTimeout(() => { notification.style.animation = 'fadeOut 0.3s ease'; setTimeout(() => { if (notification.parentNode) { notification.parentNode.removeChild(notification); } }, 300); }, 3000); } // ==================== 初始化 ==================== /** * 初始化编辑器 v3 功能 */ function initEditorV3() { console.log('Initializing Editor v3...'); // 初始化卡片状态 initCardStates(); // 初始化浮动按钮 initFloatingButtons(); // 初始化平台选择(从之前保存的状态恢复) initPlatformSelection(); // 添加 CSS 动画 addAnimationStyles(); console.log('Editor v3 initialized successfully'); } /** * 初始化平台选择(恢复之前的选择) */ function initPlatformSelection() { // 这里可以从 localStorage 或服务器恢复之前选择的平台 // 目前使用模拟数据 console.log('Platform selection initialized'); } /** * 添加动画样式 */ function addAnimationStyles() { const style = document.createElement('style'); style.textContent = ` @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } `; document.head.appendChild(style); } // 页面加载完成后初始化 document.addEventListener('DOMContentLoaded', () => { // 等待其他脚本加载完成 setTimeout(() => { initEditorV3(); }, 500); }); // 导出函数供全局使用 window.toggleCard = toggleCard; window.toggleFloatingPanel = toggleFloatingPanel; window.closeFloatingPanel = closeFloatingPanel; window.uploadCover = uploadCover; window.handleVideoFile = handleVideoFile; window.deleteVideo = deleteVideo; window.showNotification = showNotification;