继上一篇的数字公式 , 这次的功能是将公式能插入编辑器以及修改
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; // 保存当前编辑器 IDconsole.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 和 wmathIdconst 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 因为我会存在多个