可落地的方案,把 TinyMCE 改造成「左侧导航栏 + 右侧编辑区」,效果和知乎编辑器非常接近,并且适用于 .NET(ASP.NET / ASP.NET Core)
一、最终结构(知乎式布局
┌──────────────────────────────────────┐
│ 顶部工具栏(TinyMCE toolbar) │
├──────────────┬───────────────────────┤
│ 左侧导航栏 │ 右侧编辑器正文区 │
│(大纲/模块) │ TinyMCE content │
│ │ │
└──────────────┴───────────────────────┘
左侧:
文章大纲(H1 / H2 / H3)
H1 标题
├─ H2 小节
│ ├─ H3 子节
│ │ └─ H4 说明
└─ H2 另一个小节
└─ H3 …
右侧:
原生 TinyMCE 编辑体验
二、思路
TinyMCE 本身不负责布局,我们需要用外层 HTML + CSS 控制布局,。TinyMCE 只作为「右侧编辑器」
三、HTML 布局(左栏 + 编辑器)
<div class="editor-page">
<!-- 左侧导航 -->
<div class="editor-sidebar">
<div class="sidebar-title">文章大纲</div>
<ul id="outlineList"></ul>
</div>
<!-- 右侧编辑器 -->
<div class="editor-main">
<textarea id="editor"></textarea>
</div>
</div>
四、CSS(知乎式视觉)
.editor-page {
display: flex;
height: calc(100vh - 60px);
background: #f6f7f8;
}
.editor-sidebar {
width: 240px;
background: #fff;
border-right: 1px solid #e5e6eb;
padding: 12px;
overflow-y: auto;
}
.sidebar-title {
font-weight: bold;
margin-bottom: 10px;
}
.editor-sidebar ul {
list-style: none;
padding: 0;
}
.editor-sidebar li {
cursor: pointer;
padding: 4px 0;
color: #555;
}
.editor-sidebar li:hover {
color: #1772f6;
}
.editor-main {
flex: 1;
padding: 12px;
}
/* TinyMCE 占满 */
.tox-tinymce {
height: 100% !important;
}
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>知乎风编辑器</title>
@* <script src="https://cdn.tiny.cloud/1/no-api-key/tinymce/6/tinymce.min.js"></script> *@
<script src="//unpkg.com/[email protected]/tinymce.min.js"></script>
<style>
body {
margin: 0;
font-family: -apple-system,BlinkMacSystemFont;
}
.editor-page {
display: flex;
height: 100vh;
}
.editor-sidebar {
width: 240px;
border-right: 1px solid #e5e6eb;
padding: 12px;
background: #fff;
overflow-y: auto;
}
.editor-main {
flex: 1;
padding: 12px;
}
.editor-sidebar li {
cursor: pointer;
padding: 4px 0;
}
.tox-tinymce {
height: 100% !important;
}
</style>
</head>
<body>
<form method="post" asp-action="Save">
<div class="editor-page">
<div class="editor-sidebar">
<strong>文章大纲</strong>
<ul id="outlineList"></ul>
</div>
<div class="editor-main">
<textarea id="editor" name="content"></textarea>
<button type="submit">保存</button>
</div>
</div>
</form>
<script>
tinymce.init({
selector: '#editor',
height: '100%',
menubar: false,
plugins: 'lists link image code',
toolbar: 'undo redo | h1 h2 h3 | bold italic | bullist numlist | code',
setup: function (editor) {
editor.on('Change KeyUp', function () {
updateOutline(editor);
});
}
});
function updateOutline(editor) {
const outline = document.getElementById('outlineList');
outline.innerHTML = '';
editor.getBody().querySelectorAll('h1,h2,h3').forEach(h => {
const li = document.createElement('li');
li.innerText = h.innerText;
li.onclick = () => {
editor.selection.select(h);
editor.selection.scrollIntoView(h);
};
outline.appendChild(li);
});
}
</script>
</body>
</html>
