数字公式优化
This commit is contained in:
@@ -33,6 +33,7 @@
|
|||||||
"katex": "^0.16.21",
|
"katex": "^0.16.21",
|
||||||
"mammoth": "^1.5.1",
|
"mammoth": "^1.5.1",
|
||||||
"mathlive": "^0.104.0",
|
"mathlive": "^0.104.0",
|
||||||
|
"mathml-to-latex": "^1.5.0",
|
||||||
"mavon-editor": "^2.6.17",
|
"mavon-editor": "^2.6.17",
|
||||||
"multi-items-input": "^0.2.0",
|
"multi-items-input": "^0.2.0",
|
||||||
"pizzip": "^3.1.7",
|
"pizzip": "^3.1.7",
|
||||||
|
|||||||
@@ -8,14 +8,12 @@ window.MathJax = window.MathJax || {
|
|||||||
displayMath: [['$$', '$$'], ['\\[', '\\]']]
|
displayMath: [['$$', '$$'], ['\\[', '\\]']]
|
||||||
},
|
},
|
||||||
a11y: {
|
a11y: {
|
||||||
// 启用 MathJax 可访问性功能,确保使用 aria-label
|
|
||||||
texHints: true,
|
texHints: true,
|
||||||
screenReader: true,
|
screenReader: true,
|
||||||
mathml: {
|
mathml: {
|
||||||
enable: true,
|
enable: true,
|
||||||
},
|
},
|
||||||
label: {
|
label: {
|
||||||
// 公式的 aria-label 配置
|
|
||||||
enable: true,
|
enable: true,
|
||||||
texClass: 'MathJax-Label',
|
texClass: 'MathJax-Label',
|
||||||
form: 'LaTeX'
|
form: 'LaTeX'
|
||||||
@@ -24,85 +22,71 @@ window.MathJax = window.MathJax || {
|
|||||||
svg: { fontCache: 'global' }
|
svg: { fontCache: 'global' }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function stripLatexDelimiters(latex) {
|
||||||
|
return String(latex || '')
|
||||||
|
.trim()
|
||||||
|
.replace(/^\$\$/, '')
|
||||||
|
.replace(/\$\$$/, '')
|
||||||
|
.replace(/^\$/, '')
|
||||||
|
.replace(/\$$/, '')
|
||||||
|
.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 块/行内统一用 $$ 渲染,保证公式大小一致;排版由 data-wrap + CSS 控制 */
|
||||||
|
function buildLatexContentForRender(latex) {
|
||||||
|
const raw = stripLatexDelimiters(latex);
|
||||||
|
if (!raw) return '';
|
||||||
|
return '$$' + raw + '$$';
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepareWmathElement(element) {
|
||||||
|
const latexContent = element.getAttribute('data-latex');
|
||||||
|
if (!latexContent) return;
|
||||||
|
element.innerHTML = buildLatexContentForRender(latexContent);
|
||||||
|
}
|
||||||
|
|
||||||
// **定义全局渲染方法**
|
// **定义全局渲染方法**
|
||||||
window.renderMathJax = function (tinymceId) {
|
window.renderMathJax = function (tinymceId) {
|
||||||
if (window.MathJax && typeof window.MathJax.typesetPromise === "function") {
|
if (window.MathJax && typeof window.MathJax.typesetPromise === 'function') {
|
||||||
// console.log("正在渲染 MathJax 公式...");
|
|
||||||
|
|
||||||
// 如果提供了 TinyMCE 编辑器 ID
|
|
||||||
if (tinymceId) {
|
if (tinymceId) {
|
||||||
const editorInstance = window.tinymce.get(tinymceId); // 根据 ID 获取 TinyMCE 实例
|
const editorInstance = window.tinymce.get(tinymceId);
|
||||||
if (!editorInstance) return;
|
if (!editorInstance) return;
|
||||||
|
|
||||||
const editorBody = editorInstance.getBody();
|
const editorBody = editorInstance.getBody();
|
||||||
|
|
||||||
// 获取所有 <wmath> 元素
|
|
||||||
const wmathElements = editorBody.querySelectorAll('wmath');
|
const wmathElements = editorBody.querySelectorAll('wmath');
|
||||||
|
|
||||||
if (wmathElements.length > 0) {
|
if (wmathElements.length > 0) {
|
||||||
wmathElements.forEach((element) => {
|
wmathElements.forEach((element) => {
|
||||||
const latexContent = element.getAttribute('data-latex');
|
prepareWmathElement(element);
|
||||||
if (latexContent) {
|
|
||||||
// 将公式内容填入标签内部
|
|
||||||
element.innerHTML = latexContent;
|
|
||||||
|
|
||||||
// 使用 MathJax 渲染该元素
|
|
||||||
window.MathJax.typesetPromise([element]).catch((err) => {
|
window.MathJax.typesetPromise([element]).catch((err) => {
|
||||||
console.warn("TinyMCE MathJax 渲染失败:", err);
|
console.warn('TinyMCE MathJax 渲染失败:', err);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 渲染 <math>(MathML)标签,如果有的话
|
|
||||||
const mathElements = editorBody.querySelectorAll('math');
|
const mathElements = editorBody.querySelectorAll('math');
|
||||||
if (mathElements.length > 0) {
|
if (mathElements.length > 0) {
|
||||||
window.MathJax.typesetPromise(Array.from(mathElements)).catch((err) => {
|
window.MathJax.typesetPromise(Array.from(mathElements)).catch((err) => {
|
||||||
console.warn("MathML 渲染失败:", err);
|
console.warn('MathML 渲染失败:', err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// 处理全局文档中的 <wmath> 标签
|
|
||||||
const wmathElements = document.querySelectorAll('wmath');
|
const wmathElements = document.querySelectorAll('wmath');
|
||||||
wmathElements.forEach((element) => {
|
wmathElements.forEach((element) => {
|
||||||
// 检查 <wmath> 标签是否包含有效的 data-latex 属性值
|
prepareWmathElement(element);
|
||||||
const latexContent = element.getAttribute('data-latex');
|
|
||||||
if (latexContent) {
|
|
||||||
// 将元素的内部内容替换为 data-latex 的值
|
|
||||||
element.innerHTML = latexContent;
|
|
||||||
|
|
||||||
// 渲染 MathJax 公式
|
|
||||||
window.MathJax.typesetPromise([element]).catch((err) => {
|
window.MathJax.typesetPromise([element]).catch((err) => {
|
||||||
console.warn("MathJax 渲染失败:", err);
|
console.warn('MathJax 渲染失败:', err);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 处理全局文档中的 <math> 标签(MathML 内容)
|
|
||||||
const mathElements = document.querySelectorAll('math');
|
const mathElements = document.querySelectorAll('math');
|
||||||
mathElements.forEach((element) => {
|
mathElements.forEach((element) => {
|
||||||
// 渲染 MathJax 公式
|
|
||||||
window.MathJax.typesetPromise([element]).catch((err) => {
|
window.MathJax.typesetPromise([element]).catch((err) => {
|
||||||
console.warn("MathJax 渲染失败:", err);
|
console.warn('MathJax 渲染失败:', err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
console.warn("MathJax 未正确加载!");
|
console.warn('MathJax 未正确加载!');
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -19,8 +19,8 @@ const service = axios.create({
|
|||||||
// baseURL: 'https://submission.tmrjournals.com/', //正式 记得切换
|
// baseURL: 'https://submission.tmrjournals.com/', //正式 记得切换
|
||||||
// baseURL: 'http://www.tougao.com/', //测试本地 记得切换
|
// baseURL: 'http://www.tougao.com/', //测试本地 记得切换
|
||||||
// baseURL: 'http://192.168.110.110/tougao/public/index.php/',
|
// baseURL: 'http://192.168.110.110/tougao/public/index.php/',
|
||||||
// baseURL: '/api', //本地
|
baseURL: '/api', //本地
|
||||||
baseURL: '/', //正式
|
// baseURL: '/', //正式
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1626,6 +1626,166 @@ wmath {
|
|||||||
position: fixed !important;
|
position: fixed !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TinyMCE 行内公式输入框(Latex2) */
|
||||||
|
.tinymce-inline-math-overlay {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 100000;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tinymce-inline-math-panel {
|
||||||
|
min-width: 360px;
|
||||||
|
max-width: min(560px, 92vw);
|
||||||
|
width: max-content;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #e8edf5;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 12px 32px rgba(15, 23, 42, 0.12), 0 2px 8px rgba(15, 23, 42, 0.06);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tinymce-inline-math-field-wrap {
|
||||||
|
padding: 8px 10px 6px;
|
||||||
|
background: linear-gradient(180deg, #fafbfd 0%, #f5f7fb 100%);
|
||||||
|
border-bottom: 1px solid #eef1f6;
|
||||||
|
max-height: 108px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tinymce-inline-math-overlay math-field {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 36px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #dfe4ec !important;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: inset 0 1px 2px rgba(15, 23, 42, 0.04);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tinymce-inline-math-overlay math-field:focus-within {
|
||||||
|
border-color: #1654f7 !important;
|
||||||
|
box-shadow: 0 0 0 3px rgba(22, 84, 247, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tinymce-inline-math-overlay math-field::part(menu-toggle) {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tinymce-inline-math-footer {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 6px 10px 8px;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tinymce-inline-math-tools {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
flex: 0 1 auto;
|
||||||
|
min-width: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tinymce-inline-math-copy,
|
||||||
|
.tinymce-inline-math-wrap-toggle {
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
color: #1654f7;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 18px;
|
||||||
|
padding: 2px 0;
|
||||||
|
cursor: pointer;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tinymce-inline-math-copy:hover,
|
||||||
|
.tinymce-inline-math-wrap-toggle:hover,
|
||||||
|
.tinymce-inline-math-copy.is-copied {
|
||||||
|
color: #0f45d4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tinymce-inline-math-tool-divider {
|
||||||
|
display: inline-block;
|
||||||
|
width: 1px;
|
||||||
|
height: 14px;
|
||||||
|
background: #dcdfe6;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tinymce-inline-math-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tinymce-inline-math-confirm,
|
||||||
|
.tinymce-inline-math-cancel {
|
||||||
|
height: 28px;
|
||||||
|
padding: 0 12px;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-size: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
line-height: 26px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tinymce-inline-math-confirm {
|
||||||
|
border: none;
|
||||||
|
background: #1654f7;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tinymce-inline-math-confirm:hover {
|
||||||
|
background: #0f45d4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tinymce-inline-math-cancel {
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
background: #fff;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tinymce-inline-math-cancel:hover {
|
||||||
|
border-color: #c0c4cc;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tinymce-wmath-context-menu {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 100001;
|
||||||
|
min-width: 200px;
|
||||||
|
padding: 6px 0;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #e4e7ed;
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tinymce-wmath-context-item {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
color: #303133;
|
||||||
|
font-size: 13px;
|
||||||
|
text-align: left;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tinymce-wmath-context-item:hover {
|
||||||
|
background: #f5f7fa;
|
||||||
|
color: #1654f7;
|
||||||
|
}
|
||||||
|
|
||||||
.sticky-header {
|
.sticky-header {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ import Vue from 'vue';
|
|||||||
import katex from 'katex';
|
import katex from 'katex';
|
||||||
import JSZip from 'jszip';
|
import JSZip from 'jszip';
|
||||||
import mammoth from "mammoth";
|
import mammoth from "mammoth";
|
||||||
|
import { MathfieldElement } from 'mathlive';
|
||||||
|
import 'mathlive/dist/mathlive-static.css';
|
||||||
|
import 'mathlive/dist/mathlive-fonts.css';
|
||||||
import { importWordDocumentWithMath as parseWordDocumentWithMath, parseHtmlToLatex as convertHtmlToLatex } from '@/utils/wordMathImport';
|
import { importWordDocumentWithMath as parseWordDocumentWithMath, parseHtmlToLatex as convertHtmlToLatex } from '@/utils/wordMathImport';
|
||||||
import api from '../../api/index.js';
|
import api from '../../api/index.js';
|
||||||
import Common from '@/components/common/common'
|
import Common from '@/components/common/common'
|
||||||
@@ -26,6 +29,499 @@ const replaceNegativeSign = function (text) {
|
|||||||
return text;
|
return text;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let activeInlineMathOverlay = null;
|
||||||
|
|
||||||
|
function escapeLatexForWmathAttr(latex) {
|
||||||
|
return String(latex || '')
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
.replace(/</g, '<');
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildStoredLatex(rawLatex) {
|
||||||
|
const t = String(rawLatex || '').trim();
|
||||||
|
if (!t) return '';
|
||||||
|
if (/^\$\$[\s\S]+\$\$$/.test(t)) return t;
|
||||||
|
if (/^\$[\s\S]+\$$/.test(t)) return `$$${t.replace(/^\$|\$$/g, '')}$$`;
|
||||||
|
return `$$${t}$$`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveWmathWrapMode(latex) {
|
||||||
|
const t = String(latex || '')
|
||||||
|
.trim()
|
||||||
|
.replace(/^\$\$/, '')
|
||||||
|
.replace(/\$\$$/, '');
|
||||||
|
if (!t) return 'block';
|
||||||
|
if (/^\\begin\{/.test(t) || /\n\s*\n/.test(t)) return 'block';
|
||||||
|
if (/\\frac|\\dfrac|\\tfrac|\\sum|\\int|\\prod|\\lim|\\sqrt\{|\\displaystyle/.test(t)) {
|
||||||
|
return 'block';
|
||||||
|
}
|
||||||
|
return 'inline';
|
||||||
|
}
|
||||||
|
|
||||||
|
function createWmathElementHtml(rawLatex, uid, wrapMode) {
|
||||||
|
const storedLatex = buildStoredLatex(rawLatex);
|
||||||
|
const safeLatex = escapeLatexForWmathAttr(storedLatex);
|
||||||
|
const mode = normalizeWmathWrapMode(wrapMode);
|
||||||
|
return (
|
||||||
|
'<wmath contenteditable="false" data-id="' +
|
||||||
|
uid +
|
||||||
|
'" data-latex="' +
|
||||||
|
safeLatex +
|
||||||
|
'" data-wrap="' +
|
||||||
|
mode +
|
||||||
|
'">' +
|
||||||
|
storedLatex +
|
||||||
|
'</wmath>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseLatexFromWmath(wmathElement) {
|
||||||
|
const raw = (wmathElement && wmathElement.getAttribute('data-latex')) || '';
|
||||||
|
return raw
|
||||||
|
.replace(/^\$\$/, '')
|
||||||
|
.replace(/\$\$$/, '')
|
||||||
|
.replace(/^\$/, '')
|
||||||
|
.replace(/\$$/, '')
|
||||||
|
.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getEventElementTarget(target) {
|
||||||
|
if (!target) return null;
|
||||||
|
if (target.nodeType === 3) return target.parentNode;
|
||||||
|
if (target.nodeType === 9) return null;
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
function findWmathAncestor(node, root) {
|
||||||
|
let el = getEventElementTarget(node);
|
||||||
|
while (el && el !== root) {
|
||||||
|
if (el.nodeType === 1 && el.nodeName && el.nodeName.toLowerCase() === 'wmath') {
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
el = el.parentNode;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function stripMceSelectedAttr(html) {
|
||||||
|
return String(html || '').replace(/\s*data-mce-selected="[^"]*"/gi, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeWmathWrapMode(wrap) {
|
||||||
|
return wrap === 'inline' ? 'inline' : 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getOppositeWrapLabel(wrapMode) {
|
||||||
|
const target = wrapMode === 'inline' ? 'Text above and below' : 'Inline with text';
|
||||||
|
return 'Change to ' + target;
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearEditorMathSelection(ed) {
|
||||||
|
if (!ed || !ed.getBody) return;
|
||||||
|
const body = ed.getBody();
|
||||||
|
if (!body) return;
|
||||||
|
body.querySelectorAll('[data-mce-selected]').forEach((el) => {
|
||||||
|
el.removeAttribute('data-mce-selected');
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
ed.selection.collapse(false);
|
||||||
|
} catch (err) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeWmathContextMenu() {
|
||||||
|
const menu = document.getElementById('tinymce-wmath-context-menu');
|
||||||
|
if (menu) menu.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyTextToClipboard(text, onSuccess) {
|
||||||
|
const value = String(text || '').trim();
|
||||||
|
if (!value) return;
|
||||||
|
const done = typeof onSuccess === 'function' ? onSuccess : () => {};
|
||||||
|
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||||
|
navigator.clipboard.writeText(value).then(done).catch(() => {
|
||||||
|
const ta = document.createElement('textarea');
|
||||||
|
ta.value = value;
|
||||||
|
document.body.appendChild(ta);
|
||||||
|
ta.select();
|
||||||
|
document.execCommand('copy');
|
||||||
|
document.body.removeChild(ta);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const ta = document.createElement('textarea');
|
||||||
|
ta.value = value;
|
||||||
|
document.body.appendChild(ta);
|
||||||
|
ta.select();
|
||||||
|
document.execCommand('copy');
|
||||||
|
document.body.removeChild(ta);
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showWmathContextMenu(ed, wmathElement, event) {
|
||||||
|
if (!wmathElement || !event) return;
|
||||||
|
if (document.getElementById('tinymce-inline-math-overlay')) return;
|
||||||
|
|
||||||
|
closeWmathContextMenu();
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
const latex = parseLatexFromWmath(wmathElement);
|
||||||
|
const wrapMode = wmathElement.getAttribute('data-wrap') || 'block';
|
||||||
|
const uid = wmathElement.getAttribute('data-id') || 'wmath-' + Math.random().toString(36).substr(2, 9);
|
||||||
|
const wrapLabel = getOppositeWrapLabel(wrapMode);
|
||||||
|
const nextWrap = wrapMode === 'inline' ? 'block' : 'inline';
|
||||||
|
|
||||||
|
const menu = document.createElement('div');
|
||||||
|
menu.id = 'tinymce-wmath-context-menu';
|
||||||
|
menu.className = 'tinymce-wmath-context-menu';
|
||||||
|
menu.innerHTML =
|
||||||
|
'<button type="button" class="tinymce-wmath-context-item" data-action="copy">Copy LaTeX code</button>' +
|
||||||
|
'<button type="button" class="tinymce-wmath-context-item" data-action="wrap">' +
|
||||||
|
wrapLabel +
|
||||||
|
'</button>';
|
||||||
|
|
||||||
|
menu.style.left = Math.min(event.clientX, window.innerWidth - 220) + 'px';
|
||||||
|
menu.style.top = Math.min(event.clientY, window.innerHeight - 100) + 'px';
|
||||||
|
document.body.appendChild(menu);
|
||||||
|
|
||||||
|
const onMenuAction = (e) => {
|
||||||
|
const item = e.target.closest('[data-action]');
|
||||||
|
if (!item || !menu.contains(item)) return;
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
const action = item.getAttribute('data-action');
|
||||||
|
if (action === 'copy') {
|
||||||
|
copyTextToClipboard(latex);
|
||||||
|
} else if (action === 'wrap' && latex) {
|
||||||
|
ed.dom.setOuterHTML(wmathElement, createWmathElementHtml(latex, uid, nextWrap));
|
||||||
|
setTimeout(() => {
|
||||||
|
if (typeof window.renderMathJax === 'function') {
|
||||||
|
window.renderMathJax(ed.id);
|
||||||
|
}
|
||||||
|
clearEditorMathSelection(ed);
|
||||||
|
}, 10);
|
||||||
|
}
|
||||||
|
closeWmathContextMenu();
|
||||||
|
document.removeEventListener('mousedown', onOutside, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onOutside = (e) => {
|
||||||
|
if (menu.contains(e.target)) return;
|
||||||
|
closeWmathContextMenu();
|
||||||
|
document.removeEventListener('mousedown', onOutside, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
menu.addEventListener('mousedown', (e) => e.stopPropagation());
|
||||||
|
menu.addEventListener('click', onMenuAction);
|
||||||
|
setTimeout(() => document.addEventListener('mousedown', onOutside, true), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function openInlineMathEditor(ed, options) {
|
||||||
|
try {
|
||||||
|
openInlineMathEditorCore(ed, options);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('openInlineMathEditor failed:', err);
|
||||||
|
closeInlineMathOverlay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function openInlineMathEditorCore(ed, options) {
|
||||||
|
const opts = options || {};
|
||||||
|
const mode = opts.mode === 'edit' ? 'edit' : 'insert';
|
||||||
|
const wmathElement = opts.wmathElement || null;
|
||||||
|
|
||||||
|
closeInlineMathOverlay();
|
||||||
|
|
||||||
|
const iframe = ed.iframeElement;
|
||||||
|
const iframeDoc = ed.getDoc();
|
||||||
|
if (!iframe || !iframeDoc) return;
|
||||||
|
|
||||||
|
const placeholderId = 'math-ph-' + Date.now();
|
||||||
|
let uid = 'wmath-' + Math.random().toString(36).substr(2, 9);
|
||||||
|
let initialLatex = '';
|
||||||
|
let originalWmathHtml = null;
|
||||||
|
let preservedWrapMode = null;
|
||||||
|
let currentWrapMode = 'block';
|
||||||
|
|
||||||
|
let anchorRect = null;
|
||||||
|
|
||||||
|
if (mode === 'edit' && wmathElement) {
|
||||||
|
uid = wmathElement.getAttribute('data-id') || uid;
|
||||||
|
initialLatex = parseLatexFromWmath(wmathElement);
|
||||||
|
preservedWrapMode = wmathElement.getAttribute('data-wrap') || null;
|
||||||
|
originalWmathHtml = stripMceSelectedAttr(wmathElement.outerHTML);
|
||||||
|
anchorRect = wmathElement.getBoundingClientRect();
|
||||||
|
const phWidth = Math.max(Math.round(anchorRect.width), 4);
|
||||||
|
const phHeight = Math.max(Math.round(anchorRect.height), 4);
|
||||||
|
ed.dom.setOuterHTML(
|
||||||
|
wmathElement,
|
||||||
|
`<span id="${placeholderId}" class="math-placeholder" style="display:inline-block;min-width:${phWidth}px;min-height:${phHeight}px;vertical-align:middle;">​</span>`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
ed.insertContent(
|
||||||
|
`<span id="${placeholderId}" class="math-placeholder" style="display:inline-block;min-width:4px;">​</span>`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const placeholder = ed.dom.get(placeholderId);
|
||||||
|
if (!placeholder) return;
|
||||||
|
|
||||||
|
currentWrapMode = normalizeWmathWrapMode(preservedWrapMode);
|
||||||
|
|
||||||
|
const phRect = placeholder.getBoundingClientRect();
|
||||||
|
const iframeRect = iframe.getBoundingClientRect();
|
||||||
|
const anchor = anchorRect || phRect;
|
||||||
|
const overlayTop = iframeRect.top + anchor.top;
|
||||||
|
const overlayLeft = iframeRect.left + anchor.left;
|
||||||
|
const overlayMinWidth = Math.min(Math.max(anchor.width, phRect.width, 360), 560);
|
||||||
|
|
||||||
|
let overlay = document.getElementById('tinymce-inline-math-overlay');
|
||||||
|
if (!overlay) {
|
||||||
|
overlay = document.createElement('div');
|
||||||
|
overlay.id = 'tinymce-inline-math-overlay';
|
||||||
|
overlay.className = 'tinymce-inline-math-overlay';
|
||||||
|
document.body.appendChild(overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
overlay.style.display = 'block';
|
||||||
|
overlay.style.top = overlayTop + 'px';
|
||||||
|
overlay.style.left = overlayLeft + 'px';
|
||||||
|
overlay.style.minWidth = overlayMinWidth + 'px';
|
||||||
|
|
||||||
|
overlay.innerHTML = `
|
||||||
|
<div class="tinymce-inline-math-panel">
|
||||||
|
<div class="tinymce-inline-math-field-wrap"></div>
|
||||||
|
<div class="tinymce-inline-math-footer">
|
||||||
|
<div class="tinymce-inline-math-tools">
|
||||||
|
<button type="button" class="tinymce-inline-math-copy">Copy LaTeX code</button>
|
||||||
|
<span class="tinymce-inline-math-tool-divider"></span>
|
||||||
|
<button type="button" class="tinymce-inline-math-wrap-toggle"></button>
|
||||||
|
</div>
|
||||||
|
<div class="tinymce-inline-math-actions">
|
||||||
|
<button type="button" class="tinymce-inline-math-cancel">Cancel</button>
|
||||||
|
<button type="button" class="tinymce-inline-math-confirm">OK</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const fieldWrap = overlay.querySelector('.tinymce-inline-math-field-wrap');
|
||||||
|
const confirmBtn = overlay.querySelector('.tinymce-inline-math-confirm');
|
||||||
|
const cancelBtn = overlay.querySelector('.tinymce-inline-math-cancel');
|
||||||
|
const copyBtn = overlay.querySelector('.tinymce-inline-math-copy');
|
||||||
|
const wrapToggleBtn = overlay.querySelector('.tinymce-inline-math-wrap-toggle');
|
||||||
|
|
||||||
|
const updateWrapToggleLabel = () => {
|
||||||
|
wrapToggleBtn.textContent = getOppositeWrapLabel(currentWrapMode);
|
||||||
|
};
|
||||||
|
updateWrapToggleLabel();
|
||||||
|
|
||||||
|
wrapToggleBtn.addEventListener('mousedown', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
|
wrapToggleBtn.addEventListener('click', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
currentWrapMode = currentWrapMode === 'inline' ? 'block' : 'inline';
|
||||||
|
updateWrapToggleLabel();
|
||||||
|
});
|
||||||
|
|
||||||
|
copyBtn.addEventListener('mousedown', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
|
|
||||||
|
const mf = new MathfieldElement();
|
||||||
|
fieldWrap.appendChild(mf);
|
||||||
|
|
||||||
|
copyBtn.addEventListener('click', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
copyTextToClipboard(mf.value, () => {
|
||||||
|
copyBtn.textContent = 'Copied!';
|
||||||
|
copyBtn.classList.add('is-copied');
|
||||||
|
setTimeout(() => {
|
||||||
|
copyBtn.textContent = 'Copy LaTeX code';
|
||||||
|
copyBtn.classList.remove('is-copied');
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
let mfInitialized = false;
|
||||||
|
const initMathfield = () => {
|
||||||
|
if (mfInitialized) return;
|
||||||
|
mfInitialized = true;
|
||||||
|
mf.virtualKeyboardMode = 'onfocus';
|
||||||
|
mf.placeholder = 'Type formula here.';
|
||||||
|
mf.menuItems = [];
|
||||||
|
try {
|
||||||
|
if (initialLatex) {
|
||||||
|
mf.value = initialLatex;
|
||||||
|
}
|
||||||
|
} catch (valueErr) {
|
||||||
|
console.warn('Mathfield set value failed:', valueErr);
|
||||||
|
}
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
mf.focus();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
mf.addEventListener('mount', initMathfield, { once: true });
|
||||||
|
mf.addEventListener('contextmenu', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
setTimeout(initMathfield, 0);
|
||||||
|
|
||||||
|
let finalized = false;
|
||||||
|
let ignoreOutsideClick = true;
|
||||||
|
const openedAt = Date.now();
|
||||||
|
|
||||||
|
const cleanupOutsideListeners = () => {
|
||||||
|
document.removeEventListener('mousedown', onDocMouseDown, true);
|
||||||
|
iframeDoc.removeEventListener('mousedown', onIframeMouseDown, true);
|
||||||
|
mf.removeEventListener('blur', onMfBlur);
|
||||||
|
};
|
||||||
|
|
||||||
|
const canCancelOutside = () => !ignoreOutsideClick && Date.now() - openedAt > 400;
|
||||||
|
|
||||||
|
const finalize = (save) => {
|
||||||
|
if (finalized) return;
|
||||||
|
finalized = true;
|
||||||
|
cleanupOutsideListeners();
|
||||||
|
|
||||||
|
const latex = (mf.value || '').trim();
|
||||||
|
closeInlineMathOverlay();
|
||||||
|
|
||||||
|
const ph = ed.dom.get(placeholderId);
|
||||||
|
if (!ph) return;
|
||||||
|
|
||||||
|
const afterUpdate = () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (typeof window.renderMathJax === 'function') {
|
||||||
|
window.renderMathJax(ed.id);
|
||||||
|
}
|
||||||
|
clearEditorMathSelection(ed);
|
||||||
|
}, 10);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (save && latex) {
|
||||||
|
ed.dom.setOuterHTML(ph, createWmathElementHtml(latex, uid, currentWrapMode));
|
||||||
|
afterUpdate();
|
||||||
|
} else if (mode === 'edit' && originalWmathHtml) {
|
||||||
|
ed.dom.setOuterHTML(ph, originalWmathHtml);
|
||||||
|
afterUpdate();
|
||||||
|
} else {
|
||||||
|
ed.dom.remove(ph);
|
||||||
|
clearEditorMathSelection(ed);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDocMouseDown = (e) => {
|
||||||
|
if (!canCancelOutside()) return;
|
||||||
|
if (overlay.contains(e.target)) return;
|
||||||
|
if (isMathliveUiTarget(e.target)) return;
|
||||||
|
finalize(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onIframeMouseDown = (e) => {
|
||||||
|
if (!canCancelOutside()) return;
|
||||||
|
if (overlay.contains(e.target)) return;
|
||||||
|
if (isMathliveUiTarget(e.target)) return;
|
||||||
|
finalize(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onMfBlur = () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (finalized) return;
|
||||||
|
if (!canCancelOutside()) return;
|
||||||
|
const activeEl = document.activeElement;
|
||||||
|
const iframeActiveEl = iframeDoc.activeElement;
|
||||||
|
if (overlay.contains(activeEl)) return;
|
||||||
|
if (isMathliveUiTarget(activeEl) || isMathliveUiTarget(iframeActiveEl)) return;
|
||||||
|
finalize(false);
|
||||||
|
}, 150);
|
||||||
|
};
|
||||||
|
|
||||||
|
confirmBtn.addEventListener('mousedown', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
|
confirmBtn.addEventListener('click', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
finalize(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
cancelBtn.addEventListener('mousedown', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
|
cancelBtn.addEventListener('click', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
finalize(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
activeInlineMathOverlay = {
|
||||||
|
overlay,
|
||||||
|
iframeDoc,
|
||||||
|
mf,
|
||||||
|
finalize,
|
||||||
|
cleanupOutsideListeners
|
||||||
|
};
|
||||||
|
|
||||||
|
mf.addEventListener('keydown', (e) => {
|
||||||
|
if (e.key === 'Escape') {
|
||||||
|
e.preventDefault();
|
||||||
|
finalize(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mf.addEventListener('blur', onMfBlur);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
ignoreOutsideClick = false;
|
||||||
|
document.addEventListener('mousedown', onDocMouseDown, true);
|
||||||
|
iframeDoc.addEventListener('mousedown', onIframeMouseDown, true);
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
function insertInlineMathWithMathlive(ed) {
|
||||||
|
openInlineMathEditor(ed, { mode: 'insert' });
|
||||||
|
}
|
||||||
|
|
||||||
|
function editInlineMathWithMathlive(ed, wmathElement) {
|
||||||
|
if (!wmathElement) return;
|
||||||
|
if (activeInlineMathOverlay) return;
|
||||||
|
openInlineMathEditor(ed, { mode: 'edit', wmathElement });
|
||||||
|
}
|
||||||
|
|
||||||
|
function isMathliveUiTarget(target) {
|
||||||
|
if (!target || !target.closest) return false;
|
||||||
|
return !!(
|
||||||
|
target.closest('#tinymce-inline-math-overlay') ||
|
||||||
|
target.closest('.ML__keyboard') ||
|
||||||
|
target.closest('.ML__virtual-keyboard') ||
|
||||||
|
target.closest('.MLK__plate') ||
|
||||||
|
target.closest('math-field')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeInlineMathOverlay() {
|
||||||
|
if (!activeInlineMathOverlay) return;
|
||||||
|
const { overlay, cleanupOutsideListeners } = activeInlineMathOverlay;
|
||||||
|
if (typeof cleanupOutsideListeners === 'function') {
|
||||||
|
cleanupOutsideListeners();
|
||||||
|
}
|
||||||
|
overlay.style.display = 'none';
|
||||||
|
overlay.innerHTML = '';
|
||||||
|
activeInlineMathOverlay = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 首字母大写的方法
|
// 首字母大写的方法
|
||||||
// const capitalizeFirstLetter = function (text) {
|
// const capitalizeFirstLetter = function (text) {
|
||||||
@@ -1837,6 +2333,19 @@ str = str.replace(regex, function (match, content, offset, fullString) {
|
|||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
insertInlineMathWithMathlive(ed) {
|
||||||
|
openInlineMathEditor(ed, { mode: 'insert' });
|
||||||
|
},
|
||||||
|
editInlineMathWithMathlive(ed, wmathElement) {
|
||||||
|
if (!wmathElement) return;
|
||||||
|
openInlineMathEditor(ed, { mode: 'edit', wmathElement });
|
||||||
|
},
|
||||||
|
findWmathFromTarget(target, root) {
|
||||||
|
return findWmathAncestor(target, root);
|
||||||
|
},
|
||||||
|
openWmathContextMenu(ed, wmathElement, event) {
|
||||||
|
showWmathContextMenu(ed, wmathElement, event);
|
||||||
|
},
|
||||||
initEditorButton(vueInstance, ed) {
|
initEditorButton(vueInstance, ed) {
|
||||||
|
|
||||||
ed.ui.registry.addMenuButton('customDropdown', {
|
ed.ui.registry.addMenuButton('customDropdown', {
|
||||||
@@ -2189,28 +2698,37 @@ str = str.replace(regex, function (match, content, offset, fullString) {
|
|||||||
let latexEditorBookmark = null; // 用于记录插入点
|
let latexEditorBookmark = null; // 用于记录插入点
|
||||||
let activeEditorId = null; // 当前激活的编辑器 ID
|
let activeEditorId = null; // 当前激活的编辑器 ID
|
||||||
|
|
||||||
// 在编辑器工具栏中添加 "LateX" 按钮
|
// // 在编辑器工具栏中添加 "LateX" 按钮
|
||||||
ed.ui.registry.addButton('LateX', {
|
// ed.ui.registry.addButton('LateX', {
|
||||||
text: 'LateX', // 按钮文本
|
// text: 'LateX', // 按钮文本
|
||||||
onAction: function () {
|
// onAction: function () {
|
||||||
// 1. 获取当前光标位置
|
// // 1. 获取当前光标位置
|
||||||
const latexEditorBookmark = ed.selection.getBookmark(2); // 获取光标位置
|
// const latexEditorBookmark = ed.selection.getBookmark(2); // 获取光标位置
|
||||||
const editorId = ed.id; // 保存当前编辑器 ID
|
// const editorId = ed.id; // 保存当前编辑器 ID
|
||||||
|
|
||||||
// 2. 生成一个随机的 ID,用于 wmath 标签
|
// // 2. 生成一个随机的 ID,用于 wmath 标签
|
||||||
const uid = 'wmath-' + Math.random().toString(36).substr(2, 9);
|
// const uid = 'wmath-' + Math.random().toString(36).substr(2, 9);
|
||||||
|
|
||||||
// 3. 创建一个 <wmath> 标签并插入到光标处
|
// // 3. 创建一个 <wmath> 标签并插入到光标处
|
||||||
const wmathHtml = `<wmath contenteditable="false" data-id="${uid}" data-latex="" data-wrap="block"></wmath>`;
|
// const wmathHtml = `<wmath contenteditable="false" data-id="${uid}" data-latex="" data-wrap="block"></wmath>`;
|
||||||
ed.insertContent(wmathHtml); // 在光标位置插入 wmath 标签
|
// ed.insertContent(wmathHtml); // 在光标位置插入 wmath 标签
|
||||||
|
|
||||||
// 4. 打开公式编辑器窗口,并传递光标位置、编辑器 ID 和 wmathId
|
// // 4. 打开公式编辑器窗口,并传递光标位置、编辑器 ID 和 wmathId
|
||||||
const url = `/LateX?editorId=${editorId}&wmathId=${uid}`;
|
// const url = `/LateX?editorId=${editorId}&wmathId=${uid}`;
|
||||||
// vueInstance.openLatexEditor({
|
// // vueInstance.openLatexEditor({
|
||||||
// editorId:editorId,
|
// // editorId:editorId,
|
||||||
// wmathId:uid,
|
// // wmathId:uid,
|
||||||
|
// // });
|
||||||
|
// window.open(url, '_blank', 'width=1000,height=800,scrollbars=no,resizable=no');
|
||||||
|
// }
|
||||||
// });
|
// });
|
||||||
window.open(url, '_blank', 'width=1000,height=800,scrollbars=no,resizable=no');
|
|
||||||
|
// 行内公式编辑(MathLive),类似 Word「在此处键入公式」
|
||||||
|
ed.ui.registry.addButton('LateX', {
|
||||||
|
text: 'LateX',
|
||||||
|
tooltip: 'Type formula here',
|
||||||
|
onAction: function () {
|
||||||
|
insertInlineMathWithMathlive(ed);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -2,14 +2,14 @@
|
|||||||
//记得切换
|
//记得切换
|
||||||
|
|
||||||
//正式
|
//正式
|
||||||
const mediaUrl = '/public/';
|
// const mediaUrl = '/public/';
|
||||||
const baseUrl = '/';
|
// const baseUrl = '/';
|
||||||
|
|
||||||
//正式环境
|
//正式环境
|
||||||
|
|
||||||
// const mediaUrl = 'https://submission.tmrjournals.com/public/';
|
const mediaUrl = 'https://submission.tmrjournals.com/public/';
|
||||||
// // const mediaUrl = 'http://zmzm.tougao.dev.com/public/';
|
// const mediaUrl = 'http://zmzm.tougao.dev.com/public/';
|
||||||
// const baseUrl = '/api'
|
const baseUrl = '/api'
|
||||||
|
|
||||||
//测试环境
|
//测试环境
|
||||||
|
|
||||||
|
|||||||
@@ -2614,5 +2614,10 @@ export default {
|
|||||||
wmath[data-wrap='inline'] {
|
wmath[data-wrap='inline'] {
|
||||||
display: inline-block !important;
|
display: inline-block !important;
|
||||||
width: auto !important;
|
width: auto !important;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
wmath[data-wrap='inline'] mjx-container {
|
||||||
|
display: inline-block !important;
|
||||||
|
margin: 0 2px !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -641,6 +641,18 @@ export default {
|
|||||||
font-weight: bold !important;
|
font-weight: bold !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wmath {
|
||||||
|
pointer-events: auto !important;
|
||||||
|
cursor: pointer !important;
|
||||||
|
outline: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
wmath[contenteditable="false"] {
|
||||||
|
cursor: pointer !important;
|
||||||
|
outline: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes blueGlow {
|
@keyframes blueGlow {
|
||||||
0%,
|
0%,
|
||||||
100% {
|
100% {
|
||||||
@@ -731,35 +743,24 @@ export default {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
_this.pasteClipboardAsMath(ed);
|
_this.pasteClipboardAsMath(ed);
|
||||||
});
|
});
|
||||||
var currentWmathElement = null;
|
|
||||||
ed.on('click', function (e) {
|
ed.on('click', function (e) {
|
||||||
const wmathElement = e.target.closest('wmath');
|
const wmathElement = _this.$commonJS.findWmathFromTarget
|
||||||
|
? _this.$commonJS.findWmathFromTarget(e.target, ed.getBody())
|
||||||
|
: null;
|
||||||
if (wmathElement) {
|
if (wmathElement) {
|
||||||
currentWmathElement = wmathElement; // 保存当前点击的元素
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
// 1. 提取内容:获取 LaTeX
|
_this.$commonJS.editInlineMathWithMathlive(ed, wmathElement);
|
||||||
const latexContentRaw = wmathElement.getAttribute('data-latex') || '';
|
|
||||||
const latexContent = latexContentRaw.replace(/\$/g, '').trim();
|
|
||||||
const encoded = encodeURIComponent(latexContent);
|
|
||||||
|
|
||||||
// 2. 提取状态:获取之前的 wrap 模式 👈 重要新增
|
|
||||||
const wrapMode = wmathElement.getAttribute('data-wrap') || 'block';
|
|
||||||
|
|
||||||
// 3. 处理唯一 ID
|
|
||||||
let wmathId = wmathElement.getAttribute('data-id');
|
|
||||||
if (!wmathId) {
|
|
||||||
wmathId = 'wmath-' + Math.random().toString(36).substr(2, 9);
|
|
||||||
wmathElement.setAttribute('data-id', wmathId);
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const editorId = ed.id;
|
ed.on('contextmenu', function (e) {
|
||||||
|
const wmathElement = _this.$commonJS.findWmathFromTarget
|
||||||
// 4. 打开窗口:在 URL 参数中增加 wrap 模式 👈 这样弹窗就知道该默认选哪个了
|
? _this.$commonJS.findWmathFromTarget(e.target, ed.getBody())
|
||||||
window.open(
|
: null;
|
||||||
`/LateX?id=${encoded}&wmathId=${wmathId}&editorId=${editorId}&wrap=${wrapMode}`,
|
if (wmathElement) {
|
||||||
'_blank',
|
_this.$commonJS.openWmathContextMenu(ed, wmathElement, e);
|
||||||
'width=1000,height=800,scrollbars=no,resizable=no'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -240,4 +240,29 @@ export default {
|
|||||||
|
|
||||||
.table-fade-enter-active, .table-fade-leave-active { transition: opacity 0.3s ease; }
|
.table-fade-enter-active, .table-fade-leave-active { transition: opacity 0.3s ease; }
|
||||||
.table-fade-enter, .table-fade-leave-to { opacity: 0; }
|
.table-fade-enter, .table-fade-leave-to { opacity: 0; }
|
||||||
|
|
||||||
|
/* 表格预览:行内公式与文字同一行 */
|
||||||
|
.table-paper-view ::v-deep wmath[data-wrap='inline'] {
|
||||||
|
display: inline !important;
|
||||||
|
width: auto !important;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-paper-view ::v-deep wmath[data-wrap='inline'] mjx-container {
|
||||||
|
display: inline-block !important;
|
||||||
|
width: auto !important;
|
||||||
|
margin: 0 2px !important;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-paper-view ::v-deep wmath[data-wrap='inline'] mjx-container[display='true'] {
|
||||||
|
display: inline-block !important;
|
||||||
|
margin: 0 2px !important;
|
||||||
|
font-size: 12px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-paper-view ::v-deep wmath[data-wrap='block'] {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
:value="value"
|
:value="value"
|
||||||
:typesettingType="typesettingType"
|
:typesettingType="typesettingType"
|
||||||
class="paste-area text-container"
|
class="paste-area text-container"
|
||||||
:toolbar="!isAutomaticUpdate?['bold italic |customBlue removeBlue|LateX| myuppercase myuppercasea Line MoreSymbols|subscript superscript|clearButton|searchreplace']:['bold italic |customBlue removeBlue| myuppercase myuppercasea Line MoreSymbols|subscript superscript|clearButton|searchreplace']"
|
:toolbar="!isAutomaticUpdate?['bold italic |customBlue removeBlue|LateX Latex2| myuppercase myuppercasea Line MoreSymbols|subscript superscript|clearButton|searchreplace']:['bold italic |customBlue removeBlue|Latex2| myuppercase myuppercasea Line MoreSymbols|subscript superscript|clearButton|searchreplace']"
|
||||||
style="
|
style="
|
||||||
/* white-space: pre-line; */
|
/* white-space: pre-line; */
|
||||||
line-height: 12px;
|
line-height: 12px;
|
||||||
|
|||||||
@@ -1,8 +1,26 @@
|
|||||||
export const tableStyle = `
|
export const tableStyle = `
|
||||||
wmath[data-wrap="inline"] {
|
wmath[data-wrap="inline"] {
|
||||||
|
display: inline !important;
|
||||||
|
width: auto !important;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
wmath[data-wrap="inline"] mjx-container {
|
||||||
display: inline-block !important;
|
display: inline-block !important;
|
||||||
width: auto !important;
|
width: auto !important;
|
||||||
|
margin: 0 2px !important;
|
||||||
|
vertical-align: middle;
|
||||||
|
font-size: 14px !important;
|
||||||
|
}
|
||||||
|
wmath[data-wrap="inline"] mjx-container[display="true"] {
|
||||||
|
display: inline-block !important;
|
||||||
|
margin: 0 2px !important;
|
||||||
|
}
|
||||||
|
wmath[data-wrap="block"] {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
wmath[data-wrap="block"] mjx-container {
|
||||||
|
font-size: 14px !important;
|
||||||
}
|
}
|
||||||
.word-img-placeholder {
|
.word-img-placeholder {
|
||||||
background: #f0f0f0 ;
|
background: #f0f0f0 ;
|
||||||
@@ -128,10 +146,10 @@ mjx-container {
|
|||||||
font-size: 14px !important;
|
font-size: 14px !important;
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
wmath{
|
wmath[data-wrap="block"] {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: block;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
margin-bottom: 1em;
|
||||||
}
|
}
|
||||||
Info{
|
Info{
|
||||||
color:#ff8f25;
|
color:#ff8f25;
|
||||||
|
|||||||
Reference in New Issue
Block a user