/* 固定版面富文本编辑器(依赖 contenteditable + execCommand,无外部依赖) * - 工具栏:加粗/斜体/标题/列表/引用/链接/图片 * - 图片:从素材库选择或上传(复用 admin/media 接口) * - 保存前将富文本 HTML 同步到隐藏 textarea(name=content) */ (function () { 'use strict'; var ed = document.getElementById('fxEditor'); var ta = document.getElementById('fxContent'); var form = document.getElementById('fxForm'); if (!ed || !ta || !form) return; function sync() { ta.value = ed.innerHTML; } ed.addEventListener('input', sync); form.addEventListener('submit', function () { sync(); }); // 工具栏命令 document.querySelectorAll('.fx-toolbar button[data-cmd]').forEach(function (b) { b.addEventListener('mousedown', function (e) { e.preventDefault(); }); // 防止编辑器失焦 b.addEventListener('click', function () { var cmd = b.getAttribute('data-cmd'); var val = b.getAttribute('data-val') || null; ed.focus(); document.execCommand(cmd, false, val); sync(); }); }); // 链接 var linkBtn = document.getElementById('fxLink'); if (linkBtn) linkBtn.addEventListener('click', function () { var url = prompt('链接地址(如 /contact 或 https://...)'); if (url) { ed.focus(); document.execCommand('createLink', false, url); sync(); } }); // 图片弹层 var modal = document.getElementById('fxModal'); var imgBtn = document.getElementById('fxImg'); var closeBtn = document.getElementById('fxModalClose'); if (imgBtn) imgBtn.addEventListener('click', openModal); if (closeBtn) closeBtn.addEventListener('click', function () { modal.hidden = true; }); if (modal) modal.addEventListener('click', function (e) { if (e.target === modal) modal.hidden = true; }); function insertImg(url) { ed.focus(); document.execCommand('insertHTML', false, ''); sync(); modal.hidden = true; } function openModal() { modal.hidden = false; var lib = document.getElementById('fxLib'); lib.innerHTML = '加载中…'; fetch(window.__PB_MEDIA__) .then(function (r) { return r.json(); }) .then(function (j) { lib.innerHTML = ''; var items = (j && j.items) || []; if (!items.length) { lib.innerHTML = '暂无素材,先上传'; return; } items.forEach(function (it) { var img = document.createElement('img'); img.src = it.url; img.title = it.name; img.addEventListener('click', function () { insertImg(it.url); }); lib.appendChild(img); }); }) .catch(function () { lib.innerHTML = '加载失败'; }); } // 上传图片 var up = document.getElementById('fxUp'); if (up) up.addEventListener('change', function () { var file = this.files && this.files[0]; if (!file) return; var fd = new FormData(); fd.append('file', file); fetch(window.__PB_UPLOAD__, { method: 'POST', body: fd, headers: { 'X-CSRF-TOKEN': window.__PB_CSRF__ } }) .then(function (r) { return r.json(); }) .then(function (j) { if (j && j.ok) { insertImg(j.url); openModal(); } else alert((j && j.msg) || '上传失败'); }) .catch(function () { alert('上传失败,请重试'); }); this.value = ''; }); })();