134 lines
5.3 KiB
JavaScript
134 lines
5.3 KiB
JavaScript
/**
|
||
* Tiptap 增强编辑器初始化
|
||
* 支持:文字颜色、背景高亮、图片、表格、任务列表、代码块
|
||
*/
|
||
let editor = null;
|
||
|
||
function initEditor(content) {
|
||
content = content || '';
|
||
if (editor) {
|
||
editor.destroy();
|
||
}
|
||
|
||
editor = new tiptap.Editor({
|
||
element: document.querySelector("#tiptapEditor"),
|
||
extensions: [
|
||
tiptap.StarterKit,
|
||
tiptap.TextStyle,
|
||
tiptap.Color,
|
||
tiptap.Highlight.configure({ multicolor: true }),
|
||
tiptap.Image.configure({ inline: true, allowBase64: true }),
|
||
tiptap.Table.configure({ resizable: true }),
|
||
tiptap.TableRow,
|
||
tiptap.TableCell,
|
||
tiptap.TableHeader,
|
||
tiptap.TaskList,
|
||
tiptap.TaskItem.configure({ nested: true }),
|
||
],
|
||
content: content,
|
||
onUpdate: function() {
|
||
updatePreview();
|
||
scheduleSave();
|
||
},
|
||
});
|
||
|
||
renderToolbar();
|
||
}
|
||
|
||
function renderToolbar() {
|
||
var toolbar = document.querySelector("#tiptapToolbar");
|
||
if (!toolbar) return;
|
||
|
||
var html = '';
|
||
|
||
// 标题
|
||
html += '<span class="tb-group">';
|
||
html += '<button class="tb-btn" data-action="h1">H1</button>';
|
||
html += '<button class="tb-btn" data-action="h2">H2</button>';
|
||
html += '<button class="tb-btn" data-action="h3">H3</button>';
|
||
html += '</span>';
|
||
|
||
// 内联格式
|
||
html += '<span class="tb-group">';
|
||
html += '<button class="tb-btn" data-action="bold" style="font-weight:bold;">B</button>';
|
||
html += '<button class="tb-btn" data-action="italic" style="font-style:italic;">I</button>';
|
||
html += '<button class="tb-btn" data-action="strike" style="text-decoration:line-through;">S</button>';
|
||
html += '</span>';
|
||
|
||
// 颜色
|
||
html += '<span class="tb-group">';
|
||
html += '<input type="color" id="textColor" title="文字颜色" style="width:22px;height:22px;border:none;cursor:pointer;padding:0;border-radius:3px;" value="#333333">';
|
||
html += '<input type="color" id="bgColor" title="背景高亮" style="width:22px;height:22px;border:none;cursor:pointer;padding:0;border-radius:3px;" value="#fff3cd">';
|
||
html += '</span>';
|
||
|
||
// 媒体
|
||
html += '<span class="tb-group">';
|
||
html += '<button class="tb-btn" data-action="image">🖼 图片</button>';
|
||
html += '<button class="tb-btn" data-action="emoji">😊 表情</button>';
|
||
html += '</span>';
|
||
|
||
// 块级元素
|
||
html += '<span class="tb-group">';
|
||
html += '<button class="tb-btn" data-action="bulletList">• 列表</button>';
|
||
html += '<button class="tb-btn" data-action="orderedList">1. 列表</button>';
|
||
html += '<button class="tb-btn" data-action="taskList">✅ 任务</button>';
|
||
html += '<button class="tb-btn" data-action="blockquote">❝ 引用</button>';
|
||
html += '<button class="tb-btn" data-action="codeBlock"></> 代码</button>';
|
||
html += '</span>';
|
||
|
||
// 表格
|
||
html += '<span class="tb-group">';
|
||
html += '<button class="tb-btn" data-action="table">📋 表格</button>';
|
||
html += '</span>';
|
||
|
||
toolbar.innerHTML = html;
|
||
|
||
// 绑定按钮事件
|
||
var actions = {
|
||
'h1': function() { editor.chain().focus().toggleHeading({ level: 1 }).run(); },
|
||
'h2': function() { editor.chain().focus().toggleHeading({ level: 2 }).run(); },
|
||
'h3': function() { editor.chain().focus().toggleHeading({ level: 3 }).run(); },
|
||
'bold': function() { editor.chain().focus().toggleBold().run(); },
|
||
'italic': function() { editor.chain().focus().toggleItalic().run(); },
|
||
'strike': function() { editor.chain().focus().toggleStrike().run(); },
|
||
'image': function() {
|
||
var url = prompt('输入图片 URL(支持直接粘贴图片链接):');
|
||
if (url) editor.chain().focus().setImage({ src: url }).run();
|
||
},
|
||
'emoji': function() {
|
||
var emoji = prompt('输入表情符号(Win+. 打开系统表情面板粘贴):');
|
||
if (emoji) editor.chain().focus().insertContent(emoji).run();
|
||
},
|
||
'bulletList': function() { editor.chain().focus().toggleBulletList().run(); },
|
||
'orderedList': function() { editor.chain().focus().toggleOrderedList().run(); },
|
||
'taskList': function() { editor.chain().focus().toggleTaskList().run(); },
|
||
'blockquote': function() { editor.chain().focus().toggleBlockquote().run(); },
|
||
'codeBlock': function() { editor.chain().focus().toggleCodeBlock().run(); },
|
||
'table': function() { editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run(); },
|
||
};
|
||
|
||
toolbar.querySelectorAll('.tb-btn').forEach(function(btn) {
|
||
var action = btn.dataset.action;
|
||
if (actions[action]) {
|
||
btn.addEventListener('click', actions[action]);
|
||
}
|
||
});
|
||
|
||
// 颜色选择器
|
||
var textColor = document.querySelector('#textColor');
|
||
var bgColor = document.querySelector('#bgColor');
|
||
if (textColor) textColor.addEventListener('input', function(e) {
|
||
editor.chain().focus().setColor(e.target.value).run();
|
||
});
|
||
if (bgColor) bgColor.addEventListener('input', function(e) {
|
||
editor.chain().focus().toggleHighlight({ color: e.target.value }).run();
|
||
});
|
||
}
|
||
|
||
function updatePreview() {
|
||
var preview = document.querySelector("#previewContent");
|
||
if (preview && editor) {
|
||
preview.innerHTML = editor.getHTML();
|
||
}
|
||
}
|