vue数字公式篇 Tinymce结合使用(二)
继上一篇的数字公式 , 这次的功能是将公式能插入编辑器以及修改
1、Tinymce 自定义 LateX 按钮,打开公式编辑器窗口 LateX.vue
window.tinymce.init({
...//基础配置这里我就不写了
setup(ed) {
//自定义 LateX 按钮
ed.ui.registry.addButton('LateX', {
text: 'LateX', // 按钮文本
onAction: function () {
// 1. 获取当前光标位置
const latexEditorBookmark = ed.selection.getBookmark(2); // 获取光标位置
const editorId = ed.id; // 保存当前编辑器 ID
console.log('activeEditorId:', editorId);
// 2. 生成一个随机的 ID,用于 wmath 标签
const uid = 'wmath-' + Math.random().toString(36).substr(2, 9);
// 3. 创建一个 <wmath> 标签并插入到光标处
const wmathHtml = `<wmath contenteditable="false" data-id="${uid}" data-latex=""></wmath>`;
ed.insertContent(wmathHtml); // 在光标位置插入 wmath 标签
// 4. 打开公式编辑器窗口,并传递光标位置、编辑器 ID 和 wmathId
const url = `/LateX?editorId=${editorId}&wmathId=${uid}`;
window.open(url, '_blank', 'width=1000,height=800,scrollbars=no,resizable=no');
}
});
//点击数字公式时打开窗口进行编辑
var currentWmathElement = null;
ed.on('click', function (e) {
const wmathElement = e.target.closest('wmath');
if (wmathElement) {
currentWmathElement = wmathElement; // 👈 保存当前点击的元素
const latexContentRaw = wmathElement.getAttribute('data-latex') || '';
console.log('at line 488: raw =', latexContentRaw);
// 去除所有 $ 符号
const latexContent = latexContentRaw.replace(/\$/g, '').trim();
console.log('at line 489: cleaned =', latexContent);
// 编码后用于传递到弹窗
const encoded = encodeURIComponent(latexContent);
// 给 wmath 添加唯一 data-id,方便后续精准替换
let wmathId = wmathElement.getAttribute('data-id');
if (!wmathId) {
wmathId = 'wmath-' + Math.random().toString(36).substr(2, 9);
wmathElement.setAttribute('data-id', wmathId);
}
// 当前编辑器 ID 也保存下来(如果你有多个编辑器)
const editorId = ed.id;
// 打开编辑窗口并传参(传递 data-id + 内容)
window.open(
`/LateX?id=${encoded}&wmathId=${wmathId}&editorId=${editorId}`,
'_blank',
'width=1000,height=800,scrollbars=no,resizable=no'
);
}
});
}
})
//监听子页面数据
if (!window._wmath_listener_registered) {
// 💾 新增公式插入点记录
let latexEditorBookmark = null;
let activeEditorId = null;
// 👂 message 监听器:处理编辑 + 新增两种情况
window.addEventListener('message', function (event) {
const data = event.data;
console.log('data at line 648:', data);
// ✅ 编辑现有公式:替换或删除
if (data && data.type === 'update-wmath') {
const { editorId, wmathId, latex } = data;
const newLatex = latex ? latex.trim() : '';
if (!editorId || !wmathId) return;
const targetEditor = tinymce.get(editorId);
if (!targetEditor) return;
const targetWmath = targetEditor.dom.select(`wmath[data-id="${wmathId}"]`, targetEditor.getBody())[0];
if (targetWmath) {
if (!newLatex) {
// ❌ 删除公式
targetEditor.dom.remove(targetWmath);
} else {
// ✅ 更新公式
targetWmath.setAttribute('data-latex', newLatex);
targetWmath.innerHTML = newLatex;
setTimeout(() => {
if (typeof renderMathJax === 'function') {
this.window.renderMathJax(editorId);
}
}, 10);
}
}
}
});
// 🚩 标记为已注册,防止重复
window._wmath_listener_registered = true;
}
注意:所有的公式都是 $$ 公式 $$
并且都是反斜杠
富文本存储的时候 <wmath data-latex="$$ 公式 $$"> $$ 公式 $$ </wmath>
这里解释一下为什么不直接存储$$ 公式 $$
原因:
1、我们是用户编辑内容,最终有后端形成word文件,编辑在进行处理,这就会导致不能随意存储数据
2、所有直接$$ 公式 $$
渲染之后 会取代原内容 转成这样的标签 并且不会记录公式,所以我才想着在套一个自定义的标签
3、为什么不能渲染的时候直接把公式赋值到父级span标签上呢,由于原因1,我是不能存储span 以及 p这种常规的标签 如果把公式放到标签上 也没办法保证用户就只录入一个公式 而且这种直接赋值也是js去渲染的比较慢
综上所述还是自定义标签比较好 ,
id是数字公式 wmathid 是 公式 唯一的id editorId则是编辑器的id 因为我会存在多个