数字公式

This commit is contained in:
2025-03-25 09:23:51 +08:00
parent 46f3923a06
commit 3ce099e454
14 changed files with 670 additions and 872 deletions

View File

@@ -26,74 +26,72 @@ window.MathJax = window.MathJax || {
// **定义全局渲染方法**
window.renderMathJax = function (tinymceId) {
// if (window.MathJax && typeof window.MathJax.typesetPromise === "function") {
// console.log("正在渲染 MathJax 公式...");
if (window.MathJax && typeof window.MathJax.typesetPromise === "function") {
console.log("正在渲染 MathJax 公式...");
// // 如果提供了 TinyMCE 编辑器 ID
// if (tinymceId) {
// const editorInstance = window.tinymce.get(tinymceId); // 根据 ID 获取编辑器实例
// if (!editorInstance) {
// return;
// }
// 如果提供了 TinyMCE 编辑器 ID
if (tinymceId) {
const editorInstance = window.tinymce.get(tinymceId); // 根据 ID 获取 TinyMCE 实例
if (!editorInstance) return;
const editorBody = editorInstance.getBody();
// 获取所有 <wmath> 元素
const wmathElements = editorBody.querySelectorAll('wmath');
if (wmathElements.length > 0) {
wmathElements.forEach((element) => {
const latexContent = element.getAttribute('data-latex');
if (latexContent) {
// 将公式内容填入标签内部
element.innerHTML = latexContent;
// 使用 MathJax 渲染该元素
window.MathJax.typesetPromise([element]).catch((err) => {
console.warn("TinyMCE MathJax 渲染失败:", err);
});
}
});
}
// 渲染 <math>MathML标签如果有的话
const mathElements = editorBody.querySelectorAll('math');
if (mathElements.length > 0) {
window.MathJax.typesetPromise(Array.from(mathElements)).catch((err) => {
console.warn("MathML 渲染失败:", err);
});
}
}
else {
// 处理全局文档中的 <wmath> 标签
const wmathElements = document.querySelectorAll('wmath');
wmathElements.forEach((element) => {
// 检查 <wmath> 标签是否包含有效的 data-latex 属性值
const latexContent = element.getAttribute('data-latex');
if (latexContent) {
// 将元素的内部内容替换为 data-latex 的值
element.innerHTML = latexContent;
// // 获取指定的 TinyMCE 编辑器中的内容
// const editorBody = editorInstance.getBody();
// 渲染 MathJax 公式
window.MathJax.typesetPromise([element]).catch((err) => {
console.warn("MathJax 渲染失败:", err);
});
}
});
// // 渲染 editorBody 中所有 <wmath> 标签,并使用 data-latex 的值
// const wmathElements = editorBody.querySelectorAll('wmath');
// wmathElements.forEach((element) => {
// // 检查 <wmath> 标签是否包含有效的 data-latex 属性值
// const latexContent = element.getAttribute('data-latex');
// if (latexContent) {
// // 将元素的内部内容替换为 data-latex 的值
// element.innerHTML = latexContent;
// 处理全局文档中的 <math> 标签MathML 内容)
const mathElements = document.querySelectorAll('math');
mathElements.forEach((element) => {
// 渲染 MathJax 公式
window.MathJax.typesetPromise([element]).catch((err) => {
console.warn("MathJax 渲染失败:", err);
});
});
}
// // 渲染 MathJax 公式
// window.MathJax.typesetPromise([element]).catch((err) => {
// console.warn("TinyMCE MathJax 渲染失败:", err);
// });
// }
// });
// // 渲染 editorBody 中所有 <math> 标签MathML 内容)
// const mathElements = editorBody.querySelectorAll('math');
// mathElements.forEach((element) => {
// // 渲染 MathJax 公式
// window.MathJax.typesetPromise([element]).catch((err) => {
// console.warn("MathJax 渲染失败:", err);
// });
// });
// } else {
// // 处理全局文档中的 <wmath> 标签
// const wmathElements = document.querySelectorAll('wmath');
// wmathElements.forEach((element) => {
// // 检查 <wmath> 标签是否包含有效的 data-latex 属性值
// const latexContent = element.getAttribute('data-latex');
// if (latexContent) {
// // 将元素的内部内容替换为 data-latex 的值
// element.innerHTML = latexContent;
// // 渲染 MathJax 公式
// window.MathJax.typesetPromise([element]).catch((err) => {
// console.warn("MathJax 渲染失败:", err);
// });
// }
// });
// // 处理全局文档中的 <math> 标签MathML 内容)
// const mathElements = document.querySelectorAll('math');
// mathElements.forEach((element) => {
// // 渲染 MathJax 公式
// window.MathJax.typesetPromise([element]).catch((err) => {
// console.warn("MathJax 渲染失败:", err);
// });
// });
// }
// } else {
// console.warn("MathJax 未正确加载!");
// }
} else {
console.warn("MathJax 未正确加载!");
}
}

View File

@@ -19,8 +19,8 @@ const service = axios.create({
// baseURL: 'https://submission.tmrjournals.com/', //正式 记得切换
// baseURL: 'http://www.tougao.com/', //测试本地 记得切换
// baseURL: 'http://192.168.110.110/tougao/public/index.php/',
// baseURL: '/api', //本地
baseURL: '/', //正式
baseURL: '/api', //本地
// baseURL: '/', //正式
});

View File

@@ -1170,10 +1170,10 @@ a {
color: #000000;
text-align: left !important;
font-family: 'Charis SIL' !important;
font-size:12px !important;
font-size: 12px !important;
line-height: 20px !important;
}
.wordTableHtml table .color-highlight {
@@ -1213,7 +1213,7 @@ a {
/* 给最后一个 table-header-row第二行加样式 */
.wordTableHtml table tr.table-header-row:nth-of-type(2) td {
border-bottom: 1px solid #000 !important;
border-bottom: 1px solid #000 !important;
}
.word-container b span {
@@ -1294,7 +1294,7 @@ a {
border-left: 1px dashed #dcdfe6 !important;
border-right: 1px dashed #dcdfe6 !important;
word-break: keep-all !important;
white-space: pre-wrap !important;
white-space: pre-wrap !important;
/* text-align: justify !important; */
}
@@ -1434,11 +1434,19 @@ a {
text-decoration: line-through !important;
/* 设置字体颜色 */
}
mjx-container {
font-size: 14px !important;
}
wmath{
}
wmath {
width: 100%;
display: block;display: flex;
}
display: block;
display: flex;
}
/* 强制 MathLive 虚拟键盘浮在最顶层 */
.ML__keyboard {
z-index: 99999 !important;
position: fixed !important;
}

View File

@@ -49,14 +49,14 @@ export default {
replaceWMathContent(inputHtml, callback) {
// 使用正则表达式查找所有 <wmath> 标签,并提取 data-latex 的内容
var str = inputHtml.replace(/<wmath data-latex="([^"]+)">[^<]*<\/wmath>/g, function(match, latexContent) {
var str = inputHtml.replace(/<wmath data-latex="([^"]+)">[^<]*<\/wmath>/g, function (match, latexContent) {
// 返回 <wmath> 标签,内容替换为 data-latex 的值
return `<wmath data-latex="${latexContent}">${latexContent}</wmath>`;
});
// 调用回调函数并传递处理后的结果
callback(str);
// 输出结果到控制台
console.log('Processed HTML:', str);
}
@@ -65,37 +65,37 @@ export default {
,
// **解析 MathJax 公式,获取 LaTeX**
async extractMathJaxLatex(cell, callback) {
console.log('cell at line 67:', cell)
console.log('cell at line 67:', cell)
return new Promise((resolve, reject) => {
// Step 1: First, process the math content and extract LaTeX from <wmath> tags
let updatedContent = cell.innerHTML; // Start with the cell's inner HTML
console.log('cell content at the start:', updatedContent);
// Find all <wmath> elements
const wmathElements = cell.querySelectorAll('wmath');
wmathElements.forEach((element) => {
// Get the LaTeX content from the data-latex attribute
const latexContent = element.getAttribute('data-latex');
console.log('LaTeX content from data-latex:', latexContent);
// Replace the <wmath> tag with its LaTeX content wrapped in $$...$$
updatedContent = updatedContent.replace(element.outerHTML, `<wmath data-latex="${latexContent}">${latexContent}</wmath>`);
});
console.log('updatedContent after processing wmath tags:', updatedContent);
// Step 2: Now extract content without the outer <span> tags
updatedContent = this.extractContentWithoutOuterSpan(updatedContent);
console.log('updatedContent after extractContentWithoutOuterSpan:', updatedContent);
// Step 3: Call the callback function with the final updated content
// callback(updatedContent);
// Resolve the promise with the final content
resolve(updatedContent);
});
}
,
renderLatex(latexString) {
@@ -112,7 +112,7 @@ export default {
extractContentWithoutOuterSpan(cell) {
console.log('cell at line 90:', cell)
var str = ''
if(!cell){
if (!cell) {
return ''
}
// 获取单元格的 HTML 内容
@@ -753,7 +753,7 @@ export default {
// 2⃣ 将 <p> 内容转换为数组,并处理内容
let parsedData = Array.from(paragraphs).map(p => {
let text = p.innerHTML.trim(); // 获取内容,去除两端空格
text= this.transformHtmlString(text)
text = this.transformHtmlString(text)
// 3⃣ **正确移除 <o:p>Word 复制的无效标签)**
text = text.replace(/<\/?o:p[^>]*>/g, "");
@@ -1948,18 +1948,39 @@ export default {
}
}
});
let latexEditorBookmark = null; // 用于记录插入点
let activeEditorId = null; // 当前激活的编辑器 ID
// 在编辑器工具栏中添加 "LateX" 按钮
ed.ui.registry.addButton('LateX', {
text: 'LateX', // 按钮文本
// className: 'custom-button-blue', // 添加自定义类
// shortcut: "Ctrl+J",
onAction: function () {
window.open('/LateX?id=4477', '_blank', 'width=600,height=400');
// 1. 获取当前光标位置
const latexEditorBookmark = ed.selection.getBookmark(2); // 获取光标位置
const editorId = ed.id; // 保存当前编辑器 ID
console.log('activeEditorId:', editorId);
// 在新页面中插入 MathLive 编辑器
// formulaWindow.document.write(``);
}
// 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=""><Info >Insert formula here</Info></wmath>`;
ed.insertContent(wmathHtml); // 在光标位置插入 wmath 标签
// 4. 打开公式编辑器窗口,并传递光标位置、编辑器 ID 和 wmathId
const url = `/LateX?editorId=${editorId}&wmathId=${uid}`;
// vueInstance.openLatexEditor({
// editorId:editorId,
// wmathId:uid,
// });
window.open(url, '_blank', 'width=600,height=460,scrollbars=no,resizable=no');
}
});
ed.ui.registry.addButton('myuppercase', {
text: 'A', // 按钮文本

View File

@@ -32,7 +32,7 @@
</template>
</template>
<template v-else>
<div style="width: 100%; height: calc(100%); overflow: hidden">
<div style="width: 100%; ">
<div class="content" style="padding: 0; overflow: hidden">
<router-view></router-view>

View File

@@ -2,12 +2,12 @@
//记得切换
//正式
const mediaUrl = '/public/';
const baseUrl = '/';
// const mediaUrl = '/public/';
// const baseUrl = '/';
// const mediaUrl = 'https://submission.tmrjournals.com/public/';
// const baseUrl = '/api';
const mediaUrl = 'https://submission.tmrjournals.com/public/';
const baseUrl = '/api';

View File

@@ -151,6 +151,7 @@
:isAutomaticUpdate="true"
:value="picStyle.note"
@getContent="getContent"
@openLatexEditor="openLatexEditor"
v-if="pictVisible"
@updateChange="(res) => updateChange(res, 'imgNote')"
:height="120"
@@ -162,8 +163,8 @@
<span slot="footer" class="dialog-footer">
<el-button @click="pictVisible = false"> Cancel </el-button>
<el-button type="primary" @click="savePic" >
<i class="el-icon-finished" style="margin-right: 5px;"></i>
<el-button type="primary" @click="savePic">
<i class="el-icon-finished" style="margin-right: 5px"></i>
Save Figure
</el-button>
</span>
@@ -171,81 +172,26 @@
<!-- 添加表格 -->
<el-drawer
title="我嵌套了表格!"
class="editTableDialog"
destroy-on-close
v-if="threeVisible"
:title="lineStyle.visiTitle"
:visible.sync="threeVisible"
:wrapperClosable ="false"
:close-on-click-modal="false"
direction="rtl"
size="70%">
<el-form ref="editMes" :model="lineStyle" label-width="80px">
<!-- <common-late-x></common-late-x> -->
<el-form-item label="Title:">
<common-content
:id="`editor-${new Date().getTime()}-${lineStyle.am_id}-${lineStyle.amt_id}-title`"
:isAutomaticUpdate="true"
:value="lineStyle.title"
@getContent="getContent"
v-if="threeVisible"
@updateChange="(res) => updateChange(res, 'title')"
:height="120"
ref="tinymceChildTitle"
style="margin-left: -115px"
></common-content>
</el-form-item>
<el-form-item label="Word">
<span slot="label">
<font style="color: #f56c6c; margin-right: 5px">*</font>
Table:
</span>
<common-table
@getContent="getContent"
v-if="threeVisible"
ref="commonTable"
:lineStyle="lineStyle"
></common-table>
</el-form-item>
<el-form-item label="Note:">
<common-content
:id="`editor-${new Date().getTime()}-${lineStyle.am_id}-${lineStyle.amt_id}-note`"
:isAutomaticUpdate="true"
:value="lineStyle.note"
@getContent="getContent"
v-if="threeVisible"
@updateChange="(res) => updateChange(res, 'note')"
:height="120"
ref="tinymceChildNote"
></common-content>
</el-form-item>
</el-form>
<p style="margin-top: 20px; text-align: right">
<el-button @click="threeVisible = false"> Cancel </el-button>
<el-button type="primary" plain @click="handleSaveTable" style="background-color: #006699 !important;background: #006699 !important;margin-right: 20px;color: #fff !important;"> save Table </el-button>
</p>
</el-drawer>
<!-- <el-dialog
title="我嵌套了表格!"
class="editTableDialog"
destroy-on-close
v-if="threeVisible"
:title="lineStyle.visiTitle"
:visible.sync="threeVisible"
width="1200px"
:wrapperClosable="false"
:close-on-click-modal="false"
direction="rtl"
size="70%"
>
<el-form ref="editMes" :model="lineStyle" label-width="80px">
<!-- <common-late-x></common-late-x> -->
<el-form-item label="Title:">
<common-content
:id="`editor-${new Date().getTime()}-${lineStyle.am_id}-${lineStyle.amt_id}-title`"
:isAutomaticUpdate="true"
:value="lineStyle.title"
@getContent="getContent"
@openLatexEditor="openLatexEditor"
v-if="threeVisible"
@updateChange="(res) => updateChange(res, 'title')"
:height="120"
@@ -262,7 +208,7 @@
@getContent="getContent"
v-if="threeVisible"
ref="commonTable"
style="margin-left: -115px"
@openLatexEditor="openLatexEditor"
:lineStyle="lineStyle"
></common-table>
</el-form-item>
@@ -272,20 +218,27 @@
:isAutomaticUpdate="true"
:value="lineStyle.note"
@getContent="getContent"
@openLatexEditor="openLatexEditor"
v-if="threeVisible"
@updateChange="(res) => updateChange(res, 'note')"
:height="120"
ref="tinymceChildNote"
style="margin-left: -115px"
></common-content>
</el-form-item>
</el-form>
<p style="margin: 20px 0; text-align: right">
<p style="margin-top: 20px; text-align: right">
<el-button @click="threeVisible = false"> Cancel </el-button>
<el-button type="primary" plain @click="handleSaveTable"> save Table </el-button>
<el-button
type="primary"
plain
@click="handleSaveTable"
style="background-color: #006699 !important; background: #006699 !important; margin-right: 20px; color: #fff !important"
>
save Table
</el-button>
</p>
</el-dialog> -->
<el-dialog
</el-drawer>
<el-dialog
destroy-on-close
v-if="commentVisible"
title="Comment"
@@ -342,6 +295,7 @@
<common-content
:value="currentContent.content"
@getContent="getContent"
@openLatexEditor="openLatexEditor"
v-if="editVisible"
ref="commonContent"
style="margin-left: -115px"
@@ -363,7 +317,6 @@
title="Add Content"
:visible.sync="addContentVisible"
width="1200px"
:close-on-click-modal="false"
>
<el-form ref="editMes" :model="addContent" label-width="115px">
@@ -375,9 +328,9 @@
<common-content
:value="addContent.content"
@getContent="getContent"
@openLatexEditor="openLatexEditor"
v-if="addContentVisible"
ref="addContent"
style="margin-left: -115px"
></common-content>
</el-form-item>
@@ -391,6 +344,7 @@
</el-button>
</span>
</el-dialog>
<common-late-x v-if="showLateX" @close="showLateX = false" @save="saveLateX" :LateXInfo="LateXInfo"></common-late-x>
</div>
</template>
@@ -404,7 +358,9 @@ import bottomTinymce from '@/components/page/components/Tinymce';
export default {
data() {
return {
LateXInfo: {},
isEditComment: false,
showLateX: false,
comments: [],
remarkImageUrl: 'https://submission.tmrjournals.com/public/usericon/20241222/4e77ba3f29ce3cf798b36f24dc411b76.png',
isFirstComponentLoaded: false,
@@ -559,6 +515,11 @@ export default {
},
methods: {
openLatexEditor(data) {
console.log('data at line 563:', data);
this.showLateX = true;
this.LateXInfo=data
},
isShowEditComment() {
if (localStorage.getItem('U_role')) {
var identity = localStorage.getItem('U_role');
@@ -602,7 +563,7 @@ export default {
console.log('content at line 539:', content);
if (type == 'content') {
content = this.$commonJS.transformHtmlString(content);
console.log('content at line 604:', content)
console.log('content at line 604:', content);
var div = document.createElement('div');
div.innerHTML = content; // 将 HTML 字符串加载到 div 中
// 替换所有 <strong> 为 <b>
@@ -632,14 +593,13 @@ export default {
type: 'warning',
message: 'Table content is not supported!'
});
return false
return false;
}
var list = this.$commonJS.cleanAndParseWordContent(content);
console.log('list at line 569:', list);
this.saveContentList(list, this.currentId);
} else if (type == 'table') {
this.saveTable(content);
} else if (type == 'comment') {
this.addComment(content);
@@ -719,7 +679,31 @@ export default {
.catch(() => {});
}
},
saveLateX(data) {
console.log('data at line 735:', data)
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);
}
}
},
async huifu(id) {
var that = this;
await this.$confirm(this.$t('commonTable.reContent'), 'Prompt', {
@@ -882,22 +866,22 @@ export default {
console.log('err at line 466:', err);
});
},
async changeSort(type,id) {
var that=this
async changeSort(type, id) {
var that = this;
await that.$api
.post(type=='up'?'/api/Preaccept/upArticleMain':'/api/Preaccept/downArticleMain', {
am_id: id
})
.then(async (res) => {
if (res.code == 0) {
setTimeout(() => {
that.getDate();
that.getCommentList();
that.$forceUpdate();
});
}
.post(type == 'up' ? '/api/Preaccept/upArticleMain' : '/api/Preaccept/downArticleMain', {
am_id: id
})
.then(async (res) => {
if (res.code == 0) {
setTimeout(() => {
that.getDate();
that.getCommentList();
that.$forceUpdate();
});
}
});
},
async addCommentSetting(content) {
console.log('content at line 602:', content);
@@ -1152,7 +1136,7 @@ export default {
}
},
updateChange(content, type) {
console.log('content at line 1154:', content)
console.log('content at line 1154:', content);
// console.log('content at line 976:', content);
var str = this.$commonJS.transformHtmlString(content);
if (type == 'imgNote') {
@@ -1600,6 +1584,12 @@ export default {
if (content && content.table && content.table.length > 0) {
if (this.lineStyle.visiTitle == 'Edit Table') {
const loading = this.$loading({
lock: true,
text: 'Loading...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
this.$api
.post(this.urlList.editTable, {
amt_id: this.lineStyle.amt_id,
@@ -2123,5 +2113,4 @@ export default {
::-webkit-scrollbar-thumb:hover {
background: #555; /* 滑块悬停时的颜色 */
}
</style>

View File

@@ -1,531 +0,0 @@
<template>
<div class="tinymce-container editor-container">
<textarea class="tinymce-textarea" :id="tinymceId"></textarea>
</div>
</template>
<script>
import { string } from 'html-docx-js/dist/html-docx';
import htmlDocx from 'html-docx-js/dist/html-docx.js';
import { Document, Packer, PageOrientation, Paragraph, TextRun } from 'docx'; // 引入 docx.js
import html2canvas from 'html2canvas';
const tableStyle = ` b span{
font-weight: bold !important;
}
i span{
font-style: italic !important; ;
}
sub span{
vertical-align: sub;
}
sup span{
vertical-align: sup;
}
sub {
vertical-align: sub!important;
}
sup {
vertical-align: sup !important;
}
span[style*="vertical-align: super"] {
vertical-align: super !important;
}
span[style*="vertical-align: sub"] {
vertical-align: sub !important;
}
table {
border:0px !important;
border-collapse: collapse; /* 去除单元格间隙 */
width: auto;
margin : 0 auto !important;
table-layout: auto; /* 自动调整列宽 */
text-align:left;
font-family:'Charis SIL' !important;
font-size: 14px !important;
mso-font-kerning: 1.0000pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
}
table td, table th {
padding: 5px;
text-align:left !important;
white-space: pre-wrap; /* 保留换行符并换行 */
word-wrap: break-word; /* 长单词自动换行 */
word-break: break-word;
font-family:'Charis SIL' !important;
font-size: 14px !important;
mso-font-kerning: 1.0000pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
}
table tbody tr td{
text-align:left !important;
border-left:none !important;
mso-border-left-alt:none !important;
border-right:none !important;
mso-border-right-alt:none !important;
border-top:none;mso-border-top-alt:none !important;
border-bottom:none !important;
mso-border-bottom-alt:none !important;
word-break: keep-all !important;
text-align: justify !important; // 设置两端对齐
}
table tr td p{
text-align:left !important;
margin:0;
font-family:'Charis SIL' !important;
font-size: 14px !important;
mso-font-kerning: 1.0000pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
}
table span{
color:#000000;text-align:left !important;
font-family:'Charis SIL' !important;
font-size: 14px !important;
mso-font-kerning: 1.0000pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
}
table .color-highlight{
color:rgb(0,130,170) !important;
font-family:'Charis SIL' !important;
font-size: 14px !important;
mso-font-kerning: 1.0000pt !important;
line-height: 20px !important;
mos-line-height: 20px !important;
}
table tr:first-child td {
border-top:1.0000pt solid #000 !important;mso-border-top-alt:0.5000pt solid #000 !important;border-bottom:1.0000pt solid #000 !important;mso-border-bottom-alt:0.5000pt solid #000 !important;
}
table tr:last-of-type td {
border-bottom:1.0000pt solid #000 !important;mso-border-bottom-alt:0.5000pt solid #000 !important;;
}
`;
export default {
name: 'tinymce',
components: {},
props: {
id: {
type: String
},
value: {
type: String,
default: ''
},
isEdit: {},
toolbar: {
type: Array,
required: false,
default() {
return [];
}
},
menubar: {
default: 'file edit insert view format table '
},
height: {
type: Number,
required: false,
default: 360
},
width: {
type: String,
required: false,
default: '100%'
},
isShowArtWorkButton: {
default: false
}
},
data() {
return {
typesettingType: 1,
typesettingTypeOptions: [
{
label: this.$t('commonTable.typesettingType1'),
value: 1,
orientation: 'portrait',
pageSize: {
width: 11906,
height: 16976
},
pageMargins: {
top: 1440,
bottom: 1440,
left: 1084,
right: 1084
}
},
// 1 cm = 144 Twip 上边距2.54 cm = 2.54 × 144 = 365.76 Twip
{
label: this.$t('commonTable.typesettingType2'),
value: 2,
orientation: 'landscape',
pageSize: {
width: 16976,
height: 11906
},
pageMargins: {
top: 1440,
bottom: 1440,
left: 1084,
right: 1084
}
}
],
uploadReset: false,
dialogVisible: false,
form: {
name: '',
region: '',
date1: '',
date2: '',
delivery: false,
type: [],
resource: '',
desc: ''
},
formLabelWidth: '120px',
hasChange: false,
hasInit: false,
tinymceId: this.id || 'vue-tinymce-' + +new Date()
};
},
watch: {
value(val) {
if (!this.hasChange && this.hasInit) {
this.$nextTick(() => window.tinymce.get(this.tinymceId).setContent(val));
}
}
},
mounted() {
this.typesettingType = 1;
this.initTinymce();
},
activated() {
this.typesettingType = 1;
this.initTinymce();
},
deactivated() {
this.destroyTinymce();
},
methods: {
handleSubmit() {
this.$refs.uploadImage.handleSubmit();
},
getDetail(val) {
if (this.hasInit == true) {
this.$nextTick(() => window.tinymce.get(this.tinymceId).setContent(val));
}
},
//将字符串添加到富文本编辑器中
addArtWork(str) {
window.tinymce.get(this.tinymceId).insertContent(str);
},
onClick(e) {
this.$emit('onClick', e, tinymce);
},
changeTable() {
// 获取所有表格
const tables = window.tinymce.get(this.tinymceId).getBody().querySelectorAll('table');
console.log('tables at line 110:', tables);
// 遍历并设置样式
tables.forEach((table) => {
const editor = window.tinymce.get(this.tinymceId);
editor.dom.setStyles(table, {
width: this.typesettingType == 1 ? '17.18cm' : '25.88cm'
});
});
this.$forceUpdate();
},
initTinymce() {
const _this = this;
window.tinymce.init({
selector: `#${this.tinymceId}`,
content_css: false, // 禁用默认样式
table_resize_bars: true, // 启用拖动调整功能
valid_elements: '*[*]', // 允许所有 HTML 标签
paste_preprocess: function (plugin, args) {
let content = args.content;
const container = document.createElement('div');
container.innerHTML = content;
_this.updateTableStyles(container);
args.content = container.innerHTML; // 更新内容
},
content_style: `${tableStyle}`,
formats: {
bold: { inline: 'b' },
italic: { inline: 'i' }
},
body_class: 'panel-body ',
object_resizing: false,
toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar,
menubar: false, // 启用菜单栏并保持必要的项目
statusbar: false, // 关闭底部状态栏
custom_colors: false,
color_map: ['000000', 'Black', '0082AA', 'TMR Blue'],
plugins: 'forecolor code paste table image', // 启用 forecolor 和 code 插件
end_container_on_empty_block: true,
content_css: 'default', // 加载 TinyMCE 默认样式表
//设置自定义按钮 myCustomToolbarButton
setup(ed) {
ed.ui.registry.addButton('uploadWord', {
text: 'Word',
icon: 'import-word', // 使用自定义图标
onAction: function () {
const input = document.createElement('input');
input.type = 'file';
input.accept = '.docx'; // 限制为 Word 文件
input.addEventListener('change', function () {
const file = input.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function (e) {
const arrayBuffer = e.target.result;
_this.$commonJS.extractTablesFromWord(arrayBuffer, function (tablesHtml) {
console.log('tablesHtml at line 279:', tablesHtml);
ed.setContent(tablesHtml);
});
};
reader.readAsArrayBuffer(file);
}
});
input.click();
}
});
ed.ui.registry.addMenuButton('customDropdown', {
text: _this.$t('commonTable.PaperRotation'), // 下拉框标题
fetch: function (callback) {
// 定义下拉框的内容
const items = [..._this.typesettingTypeOptions];
const menuItems = items.map((item) => ({
type: 'menuitem',
text: item.label,
onAction: function () {
_this.typesettingType = item.value;
_this.changeTable();
// ed.execCommand(item.value); // 执行命令
}
}));
callback(menuItems);
}
});
ed.on('init', function () {
const editorBody = ed.getBody();
// 创建 MutationObserver 监听内容变化
const observer = new MutationObserver(() => {
console.log('editorBody at line 313:', editorBody);
// _this.updateTableStyles(editorBody, _this.typesettingType);
// const hasHorizontalScrollbar = editorBody.scrollWidth > editorBody.clientWidth;
// if (hasHorizontalScrollbar) {
// console.log('TinyMCE 出现横向滚动条');
// } else {
// console.log('没有横向滚动条');
// }
});
// 监听子节点和内容的变化
observer.observe(editorBody, { childList: true, subtree: true, characterData: true });
});
// 定义自定义按钮
ed.ui.registry.addButton('clearButton', {
text: 'Empty',
onAction: () => {
// 插入自定义表格到编辑器中
ed.setContent('');
}
});
// 定义自定义按钮
ed.ui.registry.addButton('customButtonExportWord', {
text: _this.$t('commonTable.exportWord'),
onAction: () => {
// 插入自定义表格到编辑器中
let content = ed.getContent(); // 获取内容
content = content.replace(/<strong>/g, '<b>').replace(/<\/strong>/g, '</b>');
content = content.replace(/<em>/g, '<i>').replace(/<\/strong>/g, '</i>');
const container = document.createElement('div');
container.innerHTML = content;
_this.export('table', _this.$commonJS.updateTableStyles(container, _this.typesettingType, 1));
}
});
// 定义自定义按钮
ed.ui.registry.addButton('customButtonExportImg', {
text: _this.$t('commonTable.exportImg'),
onAction: () => {
// 插入自定义表格到编辑器中
_this.export('image', ed.getContent());
}
});
ed.ui.registry.addContextToolbar('spacer', {
predicate: () => false, // 保持静态
items: '',
scope: 'node'
});
ed.on('paste', (event) => {});
ed.on('SetContent', function (e) {
e.content = e.content.replace(/<strong>/g, '<b>').replace(/<\/strong>/g, '</b>');
e.content = e.content.replace(/<em>/g, '<i>').replace(/<\/em>/g, '</i>');
});
ed.on('GetContent', function (e) {
e.content = e.content.replace(/<b>/g, '<strong>').replace(/<\/b>/g, '</strong>');
e.content = e.content.replace(/<i>/g, '<em>').replace(/<\/i>/g, '</em>');
});
},
init_instance_callback: (editor) => {
if (_this.value) {
editor.setContent(_this.value);
}
_this.hasInit = true;
editor.on('NodeChange Change KeyUp SetContent', () => {
this.hasChange = true;
this.$emit('input', editor.getContent());
});
}
});
},
// 提取 Word 文件中的表格
updateTableStyles(container) {
var html = this.$commonJS.updateTableStyles(container, this.typesettingType);
var editor = window.tinymce.activeEditor; // 将外部 DOM 内容更新到编辑器
const container1 = document.createElement('div');
container1.innerHTML = html; // html 是更新后的 HTML 内容
editor.setContent(container1.innerHTML); // 更新编辑器内容
editor.focus(); // 聚焦到编辑器// 触发编辑器内容变化后,如果需要,可能还要设置编辑器的样式
},
//销毁富文本
destroyTinymce() {
if (window.tinymce.get(this.tinymceId)) {
window.tinymce.get(this.tinymceId).destroy();
}
},
//设置内容
setContent(value) {
window.tinymce.get(this.tinymceId).setContent(value);
},
//获取内容
getContent(type) {
this.$emit('getContent', type, window.tinymce.get(this.tinymceId).getContent());
console.log('window.tinymce.get(this.tinymceId).getContent() at line 431:', window.tinymce.get(this.tinymceId).getContent());
},
async export(type, data) {
if (type == 'table') {
var tableHtml = `<html xmlns:w="urn:schemas-microsoft-com:office:word">
<head>
<style>
${tableStyle}
</style>
</head>
<body>
${data}
</body>
</html>`;
const converted = htmlDocx.asBlob(tableHtml, {
orientation: this.typesettingTypeOptions[this.typesettingType - 1].orientation,
pageSize: {
...this.typesettingTypeOptions[this.typesettingType - 1].pageSize
},
pageMargins: {
...this.typesettingTypeOptions[this.typesettingType - 1].pageMargins
}
});
// const converted = htmlDocx.asBlob(tableHtml); // 将 HTML 转换为 Word Blob
// 触发文件下载
const link = document.createElement('a');
link.href = URL.createObjectURL(converted);
link.download = 'table.docx';
link.click();
} else if (type == 'image') {
const hiddenContainer = document.createElement('div');
hiddenContainer.style.position = 'absolute';
hiddenContainer.style.left = '-9999ppx';
hiddenContainer.style.top = '0';
hiddenContainer.innerHTML = data;
const style = document.createElement('style');
style.innerHTML = `${tableStyle}`;
document.head.appendChild(style);
document.body.appendChild(hiddenContainer);
// 使用 html2canvas 捕获表格内容
const table = hiddenContainer.querySelector('table'); // 找到表格
table.style.border = 'none';
// 使用 html2canvas 将内容转为图片
html2canvas(hiddenContainer, {
scale: 2, // 提高图片的分辨率默认为1设置为2可以使图片更清晰
logging: false, // 禁用日志输出
useCORS: true, // 允许跨域图像
allowTaint: true // 允许污染 canvas解决图片链接不可用问题
})
// 清空现有内容,显示图片
.then((canvas) => {
const imgData = canvas.toDataURL('image/png'); // 创建一个图片对象
const link = document.createElement('a'); // 创建一个链接并下载图片
link.href = imgData;
link.download = 'image.png';
link.click();
});
}
},
inlineStyles(element) {
const styles = window.getComputedStyle(element);
for (let style in styles) {
if (styles.hasOwnProperty(style)) {
element.style[style] = styles[style];
}
}
},
//获取上传图片后的地址,并设置图片样式
tableSuccessCBK(arr) {
console.log(arr, '222');
const _this = this;
window.tinymce.get(_this.tinymceId).insertContent(arr);
}
},
destroyed() {
this.destroyTinymce();
}
};
</script>
<style scoped>
::v-deep .tox-tinymce-aux {
z-index: 9999 !important;
}
::v-deep .tox .tox-menu {
z-index: 9999 !important;
}
/* 自定义按钮样式 */
.custom-btn {
background-color: #28a745 !important;
color: #fff !important;
border-radius: 4px;
padding: 5px 10px;
font-weight: bold;
}
.custom-btn:hover {
background-color: #218838 !important;
}
</style>

View File

@@ -127,7 +127,9 @@ wmath{
display: block;
display: flex;
}
Info{
color:#ff8f25;
}
`;
export default {
name: 'tinymce',
@@ -250,7 +252,8 @@ export default {
this.destroyTinymce();
},
methods: {
onpenLatex() {
openLatexEditor(data) {
this.$emit('openLatexEditor',data)
console.log('at line 254:', '打开数字公式');
},
handleSubmit() {
@@ -284,7 +287,9 @@ export default {
this.$forceUpdate();
},
generateUniqueId() {
return 'wmath-' + Math.random().toString(36).substr(2, 9);
},
initTinymce() {
var _this = this;
window.tinymce.init({
@@ -477,15 +482,45 @@ export default {
//设置自定义按钮 myCustomToolbarButton
setup(ed) {
_this.$commonJS.initEditorButton(_this, ed);
ed.on('click', function (e) {
console.log('e at line 471:', e);
// 判断点击是否为 wmath 标签
const wmathElement = e.target.closest('wmath');
if (wmathElement) {
// 执行点击 wmath 标签时的操作
}
});
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=600,height=460,scrollbars=no,resizable=no'
);
}
});
ed.ui.registry.addButton('uploadWord', {
text: 'Word',
icon: 'import-word', // 使用自定义图标
@@ -511,32 +546,16 @@ export default {
}
});
// ed.ui.registry.addMenuButton('customDropdown', {
// text: _this.$t('commonTable.PaperRotation'), // 下拉框标题
// fetch: function (callback) {
// // 定义下拉框的内容
// const items = [..._this.typesettingTypeOptions];
// const menuItems = items.map((item) => ({
// type: 'menuitem',
// text: item.label,
// onAction: function () {
// _this.typesettingType = item.value;
// _this.changeTable();
// // ed.execCommand(item.value); // 执行命令
// }
// }));
// callback(menuItems);
// }
// });
ed.on('init', function () {
_this.$commonJS.inTinymceButtonClass();
const editorBody = ed.getBody();
// 监听点击事件来确保用户可以删除<wmath>元素
// 创建 MutationObserver 监听内容变化
const observer = new MutationObserver(() => {
const currentContent = ed.getContent();
console.log('currentContent at line 447:', currentContent);
// console.log('currentContent at line 447:', currentContent);
if (_this.isAutomaticUpdate) {
// _this.$emit('updateChange', _this.$commonJS.decodeHtml(currentContent));
@@ -589,6 +608,11 @@ export default {
});
ed.on('SetContent', function (e) {
const editorBody = ed.getBody();
ed.dom.select('wmath', editorBody).forEach(function (wmathElement) {
ed.dom.setAttrib(wmathElement, 'contenteditable', 'false');
// ed.dom.addClass(wmathElement, 'non-editable-wmath');
});
e.content = e.content.replace(/<strong>/g, '<b>').replace(/<\/strong>/g, '</b>');
e.content = e.content.replace(/<em>/g, '<i>').replace(/<\/em>/g, '</i>');
});
@@ -618,6 +642,87 @@ export default {
});
}
});
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);
}
}
}
// ✅ 插入新公式
// if (data && data.type === 'insert-new-wmath') {
// const latex = data.latex ? data.latex.trim() : '';
// // if (!activeEditorId || !latexEditorBookmark) return;
// const editor = window.tinymce.get(activeEditorId);
// if (!editor) return;
// // 恢复光标位置
// editor.focus();
// setTimeout(() => {
// editor.selection.moveToBookmark(latexEditorBookmark);
// const uid = 'wmath-' + Math.random().toString(36).substr(2, 9);
// const wmathHtml = `<wmath contenteditable="false" data-id="${uid}" data-latex="${latex}">${latex}</wmath>`;
// editor.insertContent(wmathHtml);
// // 清除焦点,防止影响渲染
// editor.focus(false); // 取消焦点
// // 清除
// latexEditorBookmark = null;
// activeEditorId = null;
// }, 20);
// setTimeout(() => {
// if (typeof renderMathJax === 'function') {
// _this.window.renderMathJax(_this.tinymceId);
// }
// }, 1000);
// }
});
// 🚩 标记为已注册,防止重复
window._wmath_listener_registered = true;
// 🧠 导出保存位置函数(你可以在按钮点击时调用它)
window._recordLatexInsertContext = function (editorInstance) {
latexEditorBookmark = editorInstance.selection.getBookmark(2);
activeEditorId = editorInstance.id;
};
}
},
// 提取 Word 文件中的表格

View File

@@ -0,0 +1,151 @@
<template>
<div style="position: fixed;top: 0;left: 0;background-color: #f8f8f8; width: 100%; height: 100%; overflow: hidden; background: linear-gradient(to top, #fbfffe, #ebf9ff);">
<div class="navbar-default">
<div class="nav commonWidth" style="height: 100%">
<div class="title">Digital Formula Editor</div>
</div>
</div>
<div class="commonWidth" style="padding:40px 20px; box-sizing: border-box;">
<!-- <div style="margin-bottom: 20px;font-size: 20px;">Numerical formula:</div> -->
<div style="display: flex;align-items: center;justify-content: space-between;">
<div ref="mathField" class="math-container" style="width: calc(100% - 100px);"></div>
<span @click="copyLatex" style="font-size: 20px;width: 80px;cursor: pointer;">📋 Copy </span>
</div>
<!-- 公式显示框 -->
<div class="formula-box" :style="{ opacity: showLatex ? 1 : 0 }">
<p>LaTeX 代码:</p>
<textarea ref="latexBox" class="latex-text" readonly>$${{ latex }}$$</textarea>
</div>
</div>
</div>
</template>
<script>
import { MathfieldElement } from 'mathlive';
export default {
data() {
return {
latex: '', // 默认公式
// latex: '\\frac{a}{b} + \\sqrt{x^2 + y^2} + e^{i\\pi}', // 默认公式
mathFieldInstance: null,
showLatex: false, // 控制 LaTeX 代码框的显示与隐藏
};
},
mounted() {
if (this.$refs.mathField) {
// 创建 MathfieldElement 组件
const mf = new MathfieldElement();
mf.style.width = '100%';
mf.virtualKeyboardMode = 'manual'; // 显示虚拟键盘
mf.value = this.latex; // 设置默认值
// 监听输入变化,更新 LaTeX 代码
mf.addEventListener('input', (event) => {
this.latex = event.target.value;
});
// 挂载到 DOM
this.$refs.mathField.appendChild(mf);
this.mathFieldInstance = mf;
// 强制显示虚拟键盘并保持显示
mf.executeCommand('showVirtualKeyboard');
// 保证虚拟键盘持续显示
this.keepKeyboardVisible(mf);
} else {
console.error('MathLive 未正确加载');
}
},
methods: {
keepKeyboardVisible(mf) {
// 每秒确保虚拟键盘显示
setInterval(() => {
mf.executeCommand('showVirtualKeyboard');
}, 20); // 每秒确保键盘显示
},
copyLatex() {
if (this.$refs.latexBox) {
this.$refs.latexBox.select(); // 选中文本
document.execCommand('copy'); // 复制到剪贴板
setTimeout(( )=>{
window.close();
},100)
}
},
},
beforeDestroy() {
this.mathFieldInstance = null; // 组件销毁时清除实例
}
};
</script>
<style scoped>
.commonWidth {
width: 100%;
margin: 0 auto;
}
.title {
font-size: 32px;
font-weight: bold;
line-height: 80px;
background-color: #0f4eb6;
color: #fff;
}
.navbar-default {
width: 100%;
height: 80px;
background-color: #0f4eb6;
border-color: #e7e7e7;
}
.math-container {
min-height: 40px;
border: 1px solid #ccc;
padding: 5px;
font-size: 18px;
/* margin-bottom: 20px; */
}
/* 公式弹出框样式 */
.formula-box {
margin-top: 10px;
padding: 10px;
border: 1px solid #ccc;
background-color: #f9f9f9;
display: flex;
flex-direction: column;
align-items: flex-start;
}
/* LaTeX 代码框 */
.latex-text {
width: 100%;
height: 50px;
font-size: 16px;
border: 1px solid #ccc;
padding: 5px;
margin-bottom: 10px;
resize: none;
}
/* 复制按钮 */
button {
padding: 5px 10px;
background-color: #007bff;
color: white;
border: none;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
/* 防止虚拟键盘覆盖 */
::v-deep .ML__virtual-keyboard-toggle {
opacity: 1 !important; /* 确保虚拟键盘的按钮可见 */
}
</style>

View File

@@ -1,151 +1,198 @@
<template>
<div style="position: fixed;top: 0;left: 0;background-color: #f8f8f8; width: 100%; height: 100%; overflow: hidden; background: linear-gradient(to top, #fbfffe, #ebf9ff);">
<div class="navbar-default">
<div class="nav commonWidth" style="height: 100%">
<div class="title">Digital Formula Editor</div>
</div>
<div
style="
position: fixed;
top: 0;
left: 5px;
right: 5px;
background-color: #f8f8f8;
/* width: 400px; */
height: 300px;
overflow: hidden;
background: linear-gradient(to top, #fbfffe, #ebf9ff);
z-index: 9999;
border-radius: 10px 10px 0 0;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
"
>
<div class="navbar-default" style="padding: 10px">
<div class="nav commonWidth" style="height: 100%">
<div class="title" style="padding: 0 0px; box-sizing: border-box">
<img src="@/assets/img/logo.png" style="width: 30px; height: 20px; margin-right: 10px" />
Digital Formula Editor
</div>
</div>
</div>
<div class="commonWidth" style="padding: 40px 10px; box-sizing: border-box">
<div style="display: flex; align-items: center; justify-content: space-between">
<div ref="mathField" class="math-container" style="width: calc(100%)"></div>
<el-button type="danger" @click="handleClear" plain style="float: right"> Clear</el-button>
</div>
<div style="margin-top: 40px; overflow: hidden">
<div style="float: left">
<span @click="copyLatex" style="font-size: 16px; cursor: pointer; opacity: 0.6" disabled v-if="!this.latex"
>📋 Copy
</span>
<span @click="copyLatex" style="font-size: 16px; cursor: pointer; opacity: 1" v-else>📋 Copy </span>
</div>
<el-button type="primary" @click="SaveyLatex" style="background-color: #1654f7 !important; float: right">Submit</el-button>
<el-button @click="handleCancel" style="float: right; margin-right: 10px">Cancel</el-button>
</div>
<!-- 公式显示框 -->
<div class="formula-box" :style="{ opacity: showLatex ? 1 : 0 }">
<p>LaTeX 代码:</p>
<textarea ref="latexBox" class="latex-text" readonly>$${{ latex }}$$</textarea>
</div>
</div>
</div>
<div class="commonWidth" style="padding:40px 20px; box-sizing: border-box;">
<!-- <div style="margin-bottom: 20px;font-size: 20px;">Numerical formula:</div> -->
<div style="display: flex;align-items: center;justify-content: space-between;">
<div ref="mathField" class="math-container" style="width: calc(100% - 100px);"></div>
<span @click="copyLatex" style="font-size: 20px;width: 80px;cursor: pointer;">📋 Copy </span>
</div>
<!-- 公式显示框 -->
<div class="formula-box" :style="{ opacity: showLatex ? 1 : 0 }">
<p>LaTeX 代码:</p>
<textarea ref="latexBox" class="latex-text" readonly>$${{ latex }}$$</textarea>
</div>
</div>
</div>
</template>
<script>
import { MathfieldElement } from 'mathlive';
export default {
data() {
return {
latex: '', // 默认公式
// latex: '\\frac{a}{b} + \\sqrt{x^2 + y^2} + e^{i\\pi}', // 默认公式
mathFieldInstance: null,
showLatex: false, // 控制 LaTeX 代码框的显示与隐藏
};
},
mounted() {
if (this.$refs.mathField) {
// 创建 MathfieldElement 组件
const mf = new MathfieldElement();
mf.style.width = '100%';
mf.virtualKeyboardMode = 'manual'; // 显示虚拟键盘
mf.value = this.latex; // 设置默认值
props:['LateXInfo'],
data() {
return {
latex: '', // 默认公式
mathFieldInstance: null,
showLatex: false // 控制 LaTeX 代码框的显示与隐藏
};
},
mounted() {
// 获取并初始化公式
if (this.$route.query.id) {
this.latex = this.$route.query.id;
}
if (this.$refs.mathField) {
const mf = new MathfieldElement();
mf.style.width = '100%';
mf.virtualKeyboardMode = 'manual'; // 显示虚拟键盘
mf.value = this.latex;
// 监听输入变化,更新 LaTeX 代码
mf.addEventListener('input', (event) => {
this.latex = event.target.value;
});
// 监听输入变化,更新 LaTeX 代码
mf.addEventListener('input', (event) => {
this.latex = event.target.value;
});
// 挂载到 DOM
this.$refs.mathField.appendChild(mf);
this.mathFieldInstance = mf;
this.$refs.mathField.appendChild(mf);
this.mathFieldInstance = mf;
mf.executeCommand('showVirtualKeyboard');
this.keepKeyboardVisible(mf);
} else {
console.error('MathLive 未正确加载');
}
},
methods: {
keepKeyboardVisible(mf) {
setInterval(() => {
mf.executeCommand('showVirtualKeyboard');
}, 50); // 每秒确保键盘显示
},
copyLatex() {
if (this.latex == '') {
return;
}
if (this.$refs.latexBox) {
this.$refs.latexBox.select(); // 选中文本
document.execCommand('copy'); // 复制到剪贴板
this.$message({
message: 'Replicating Success',
type: 'success'
});
}
},
handleClear() {
this.latex = '';
this.mathFieldInstance.value = '';
this.$forceUpdate();
},
handleCancel() {
this.$emit('close');
},
SaveyLatex() {
const wmathId = this.$route.query.wmathId;
const editorId = this.$route.query.editorId;
// this.$emit('save', {
// latex: this.latex && this.latex != '' ? `$$${this.latex}$$` : '',
// editorId: this.LateXInfo.editorId,
// wmathId: this.LateXInfo.wmathId
// });
// 强制显示虚拟键盘并保持显示
mf.executeCommand('showVirtualKeyboard');
window.opener.postMessage(
{
type: 'update-wmath',
latex: this.latex && this.latex != '' ? `$$${this.latex}$$` : '',
editorId: editorId,
wmathId: wmathId
},
'*'
);
// 保证虚拟键盘持续显示
this.keepKeyboardVisible(mf);
} else {
console.error('MathLive 未正确加载');
setTimeout(() => {
window.close();
// this.$emit('close');
}, 100);
}
},
beforeDestroy() {
this.mathFieldInstance = null; // 组件销毁时清除实例
}
},
methods: {
keepKeyboardVisible(mf) {
// 每秒确保虚拟键盘显示
setInterval(() => {
mf.executeCommand('showVirtualKeyboard');
}, 20); // 每秒确保键盘显示
},
copyLatex() {
if (this.$refs.latexBox) {
this.$refs.latexBox.select(); // 选中文本
document.execCommand('copy'); // 复制到剪贴板
setTimeout(( )=>{
window.close();
},100)
}
},
},
beforeDestroy() {
this.mathFieldInstance = null; // 组件销毁时清除实例
}
};
</script>
<style scoped>
.commonWidth {
width: 100%;
margin: 0 auto;
width: 100%;
margin: 0 auto;
}
.title {
font-size: 32px;
font-weight: bold;
line-height: 80px;
background-color: #0f4eb6;
color: #fff;
font-size: 20px;
font-weight: bold;
line-height: 30px;
background-color: #0f4eb6;
color: #fff;
display: flex;
align-items: center;
}
.navbar-default {
width: 100%;
height: 80px;
background-color: #0f4eb6;
border-color: #e7e7e7;
width: 100%;
height: 30px;
background-color: #0f4eb6;
border-color: #e7e7e7;
}
.math-container {
min-height: 40px;
border: 1px solid #ccc;
padding: 5px;
font-size: 18px;
/* margin-bottom: 20px; */
min-height: 40px;
padding: 5px;
font-size: 18px;
width: 100%;
}
/* 公式弹出框样式 */
.formula-box {
margin-top: 10px;
padding: 10px;
border: 1px solid #ccc;
background-color: #f9f9f9;
display: flex;
flex-direction: column;
align-items: flex-start;
margin-top: 10px;
padding: 10px;
border: 1px solid #ccc;
background-color: #f9f9f9;
display: flex;
flex-direction: column;
align-items: flex-start;
}
/* LaTeX 代码框 */
.latex-text {
width: 100%;
height: 50px;
font-size: 16px;
border: 1px solid #ccc;
padding: 5px;
margin-bottom: 10px;
resize: none;
width: 100%;
height: 50px;
font-size: 16px;
padding: 5px;
margin-bottom: 10px;
resize: none;
}
/* 复制按钮 */
button {
padding: 5px 10px;
background-color: #007bff;
color: white;
border: none;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
/* 防止虚拟键盘覆盖 */
::v-deep .ML__virtual-keyboard-toggle {
opacity: 1 !important; /* 确保虚拟键盘的按钮可见 */
opacity: 1 !important;
}
</style>

View File

@@ -11,11 +11,12 @@
:wordStyle="wordStyle"
:isAutomaticUpdate="isAutomaticUpdate"
@getContent="getContent"
@openLatexEditor="openLatexEditor"
@updateChange="updateChange"
:value="value"
:typesettingType="typesettingType"
class="paste-area text-container"
:toolbar="['bold italic|customBlue removeBlue|myuppercase myuppercasea Line|subscript superscript|searchreplace|clearButton']"
:toolbar="`['bold italic|customBlue removeBlue|${!isAutomaticUpdate?'LateX|':''}myuppercase myuppercasea Line|subscript superscript|searchreplace|clearButton']`"
style="
/* white-space: pre-line; */
line-height: 12px;
@@ -73,6 +74,10 @@ export default {
}
},
methods: {
openLatexEditor(data) {
this.$emit('openLatexEditor',data)
console.log('at line 254:', '打开数字公式');
},
updateChange(content){
this.$emit('updateChange',content)
},

View File

@@ -8,11 +8,12 @@
ref="tinymceChild1"
:wordStyle="wordStyle"
@getContent="getContent"
@openLatexEditor="openLatexEditor"
:height="calcDynamicWidth()"
:value="updatedHtml"
:typesettingType="typesettingType"
class="paste-area text-container"
:toolbar="['bold italic|customBlue removeBlue|kityformula-editor |myuppercase myuppercasea Line|subscript superscript|table tabledelete| searchreplace |clearButton']"
:toolbar="['bold italic|customBlue removeBlue|kityformula-editor|LateX |myuppercase myuppercasea Line|subscript superscript|table tabledelete| searchreplace |clearButton']"
style="
/* white-space: pre-line; */
line-height: 12px;
@@ -101,6 +102,10 @@ export default {
}
},
methods: {
openLatexEditor(data) {
this.$emit('openLatexEditor',data)
console.log('at line 254:', '打开数字公式');
},
calcDynamicWidth() {
const parentWidth = window.innerHeight; // 获取窗口宽度
const result = parentWidth - 420; // 计算 `100% - 200px`

View File

@@ -899,7 +899,7 @@ export default {
this.currentId = null;
this.currentData = {};
// this.uniqueIds = [...new Set(this.wordList.filter((item) => item.checked).map((item) => item.am_id))];
console.log('this.uniqueIds at line 839:', this.selectedIds);
// console.log('this.uniqueIds at line 839:', this.selectedIds);
this.$forceUpdate();
},
onEdit() {
@@ -911,7 +911,7 @@ export default {
this.$emit('onAddRow', this.currentId);
},
onDelete() {
console.log('this.uniqueIds.length at line 866:', this.selectedIds.length);
// console.log('this.uniqueIds.length at line 866:', this.selectedIds.length);
if (this.selectedIds.length > 0) {
this.$emit('onDeletes', this.selectedIds.toString());
this.$forceUpdate();