初始化
This commit is contained in:
133
frontend/static/js/editor.js
Normal file
133
frontend/static/js/editor.js
Normal file
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user