/** * OSS Community Editor JS * Markdown 编辑器、实时预览、表单提交 */ document.addEventListener('DOMContentLoaded', () => { initEditor(); initToolbar(); initTags(); initForm(); }); // 初始化编辑器 function initEditor() { const textarea = document.getElementById('postContent'); const titleInput = document.getElementById('postTitle'); // Tab 键支持 if (textarea) { textarea.addEventListener('keydown', (e) => { if (e.key === 'Tab') { e.preventDefault(); const start = textarea.selectionStart; const end = textarea.selectionEnd; textarea.value = textarea.value.substring(0, start) + ' ' + textarea.value.substring(end); textarea.selectionStart = textarea.selectionEnd = start + 2; } }); } } // 初始化工具栏 function initToolbar() { const buttons = document.querySelectorAll('.md-btn'); const textarea = document.getElementById('postContent'); if (!textarea) return; buttons.forEach(btn => { btn.addEventListener('click', () => { const action = btn.dataset.md; insertMarkdown(textarea, action); }); }); } function insertMarkdown(textarea, action) { const start = textarea.selectionStart; const end = textarea.selectionEnd; const selected = textarea.value.substring(start, end); let insertion = ''; switch (action) { case 'bold': insertion = `**${selected || '粗体文本'}**`; break; case 'italic': insertion = `*${selected || '斜体文本'}*`; break; case 'heading': insertion = `\n## ${selected || '标题'}\n`; break; case 'quote': insertion = `\n> ${selected || '引用文本'}\n`; break; case 'code': insertion = selected.includes('\n') ? `\n\`\`\`\n${selected || '代码块'}\n\`\`\`\n` : `\`${selected || '行内代码'}\``; break; case 'link': insertion = `[${selected || '链接文本'}](url)`; break; case 'list': insertion = `\n- ${selected || '列表项'}\n`; break; } textarea.value = textarea.value.substring(0, start) + insertion + textarea.value.substring(end); textarea.focus(); textarea.selectionStart = textarea.selectionEnd = start + insertion.length; } // 初始化标签 function initTags() { const tagInput = document.getElementById('tagInput'); const tagsContainer = document.getElementById('tagsContainer'); if (!tagInput || !tagsContainer) return; tagInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') { e.preventDefault(); const tagName = tagInput.value.trim(); if (tagName) { addTag(tagName); tagInput.value = ''; } } }); } function addTag(name) { const tagsContainer = document.getElementById('tagsContainer'); if (!tagsContainer) return; // 检查是否已存在 const existing = tagsContainer.querySelectorAll('.tag-item'); for (const tag of existing) { if (tag.textContent.trim().replace('×', '').trim() === name) { return; } } const tagEl = document.createElement('span'); tagEl.className = 'tag-item'; tagEl.innerHTML = ` ${name} `; tagsContainer.appendChild(tagEl); } // 初始化表单 function initForm() { const form = document.getElementById('postEditorForm'); const saveBtn = document.getElementById('savePostBtn'); if (!form || !saveBtn) return; saveBtn.addEventListener('click', async (e) => { e.preventDefault(); const postId = document.getElementById('editPostId').value; const title = document.getElementById('postTitle').value.trim(); const content = document.getElementById('postContent').value.trim(); const categoryId = document.getElementById('postCategory').value; // 收集标签 const tags = []; document.querySelectorAll('#tagsContainer .tag-item').forEach(tag => { const name = tag.textContent.replace('×', '').trim(); if (name) tags.push(name); }); // 验证 if (!title) { showError('请输入帖子标题'); return; } if (title.length < 5) { showError('标题至少 5 个字符'); return; } if (!content) { showError('请输入帖子内容'); return; } if (content.length < 10) { showError('内容至少 10 个字符'); return; } if (!categoryId) { showError('请选择分类'); return; } // 提交 setSaveButtonLoading(true); const formData = { title: title, content: content, category_id: categoryId, tags: tags }; if (postId) { formData.id = parseInt(postId); } const action = postId ? 'update' : 'create'; const url = `api/posts.php?action=${action}`; try { const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(formData) }); const result = await response.json(); if (result.success) { showSuccess(postId ? '更新成功!' : '发布成功!正在跳转...'); setTimeout(() => { window.location.href = `post.php?id=${result.post_id || postId}`; }, 1000); } else { showError(result.message || '操作失败'); } } catch (error) { showError('网络错误,请稍后重试'); } finally { setSaveButtonLoading(false); } }); } function showSuccess(message) { const toast = document.getElementById('successToast'); const msgEl = document.getElementById('successMessage'); if (toast && msgEl) { msgEl.textContent = message; toast.style.display = 'flex'; setTimeout(() => { toast.style.display = 'none'; }, 3000); } } function showError(message) { const toast = document.getElementById('errorToast'); const msgEl = document.getElementById('errorMessage'); if (toast && msgEl) { msgEl.textContent = message; toast.style.display = 'flex'; setTimeout(() => { toast.style.display = 'none'; }, 4000); } } function setSaveButtonLoading(loading) { const btn = document.getElementById('savePostBtn'); if (!btn) return; if (loading) { btn.disabled = true; btn.style.opacity = '0.6'; btn.innerHTML = ` 处理中... `; } else { btn.disabled = false; btn.style.opacity = '1'; btn.innerHTML = ` ${document.getElementById('editPostId').value ? '保存修改' : '发布帖子'} `; } }