提交
This commit is contained in:
@@ -2,7 +2,7 @@ import Vue from 'vue';
|
||||
import JSZip from 'jszip';
|
||||
import Common from '@/components/common/common'
|
||||
import Tiff from 'tiff.js';
|
||||
var mediaUrl = Common.mediaUrl+'articleImage/';
|
||||
var mediaUrl = Common.mediaUrl + 'articleImage/';
|
||||
// var mediaUrl1 = 'https://submission.tmrjournals.com/public/articleImage/';
|
||||
|
||||
const fs = require('fs');
|
||||
@@ -24,7 +24,7 @@ export default {
|
||||
// 获取单元格的 HTML 内容
|
||||
let htmlContent = cell.innerHTML.trim();
|
||||
str = this.transformHtmlString(htmlContent)
|
||||
|
||||
|
||||
// 创建一个临时的 DOM 元素来解析 HTML
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = htmlContent;
|
||||
@@ -55,7 +55,7 @@ export default {
|
||||
// 创建临时 DOM 容器
|
||||
const tempDiv = document.createElement("div");
|
||||
tempDiv.innerHTML = pastedHtml; // 插入粘贴的 HTML 内容
|
||||
|
||||
|
||||
// 获取表格
|
||||
const tables = tempDiv.querySelectorAll("table");
|
||||
if (tables.length === 0) {
|
||||
@@ -63,31 +63,31 @@ export default {
|
||||
callback([]);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const allTables = []; // 存储所有表格的二维数组
|
||||
|
||||
|
||||
for (const table of tables) {
|
||||
const rows = table.querySelectorAll("tr");
|
||||
const tableArray = []; // 当前表格的二维数组
|
||||
|
||||
|
||||
// 存储合并单元格信息
|
||||
const mergeMap = {};
|
||||
|
||||
|
||||
rows.forEach((row, rowIndex) => {
|
||||
const cells = row.querySelectorAll("td, th");
|
||||
const rowArray = [];
|
||||
|
||||
|
||||
let colIndex = 0;
|
||||
|
||||
|
||||
cells.forEach((cell) => {
|
||||
// 跳过被合并的单元格
|
||||
while (mergeMap[`${rowIndex},${colIndex}`]) {
|
||||
colIndex++;
|
||||
}
|
||||
|
||||
|
||||
// 获取单元格内容,如果为空则设置为默认值
|
||||
let cellText = cell.innerText.trim() || " "; // 处理空值
|
||||
|
||||
|
||||
// 处理样式
|
||||
if (cell.style.fontWeight === "bold") {
|
||||
cellText = `<b>${cellText}</b>`;
|
||||
@@ -101,18 +101,18 @@ export default {
|
||||
if (cell.style.verticalAlign === "sub") {
|
||||
cellText = `<sub>${cellText}</sub>`;
|
||||
}
|
||||
|
||||
|
||||
// 检查合并单元格属性
|
||||
const colspan = parseInt(cell.getAttribute("colspan") || "1", 10);
|
||||
const rowspan = parseInt(cell.getAttribute("rowspan") || "1", 10);
|
||||
|
||||
|
||||
// 保存当前单元格信息
|
||||
rowArray[colIndex] = {
|
||||
text: cellText,
|
||||
colspan: colspan,
|
||||
rowspan: rowspan,
|
||||
};
|
||||
|
||||
|
||||
// 更新合并单元格信息
|
||||
if (rowspan > 1 || colspan > 1) {
|
||||
for (let i = 0; i < rowspan; i++) {
|
||||
@@ -122,16 +122,16 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
colIndex++; // 移动到下一列
|
||||
});
|
||||
|
||||
|
||||
tableArray.push(rowArray); // 添加当前行到表格数组
|
||||
});
|
||||
|
||||
|
||||
allTables.push(tableArray); // 添加当前表格到所有表格数组
|
||||
}
|
||||
|
||||
|
||||
console.log("解析后的表格数组:", allTables);
|
||||
callback(allTables); // 返回处理后的数组
|
||||
} catch (error) {
|
||||
@@ -139,7 +139,7 @@ export default {
|
||||
callback([]);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
async extractWordTablesToArrays(file, callback) {
|
||||
const Zip = new JSZip();
|
||||
try {
|
||||
@@ -445,23 +445,23 @@ export default {
|
||||
console.log('numberingMap at line 232:', numberingMap)
|
||||
// 提取表格
|
||||
// 获取所有的段落
|
||||
const paragraphs = xmlDoc.getElementsByTagName("w:p");
|
||||
// 获取所有的表格
|
||||
const tables = xmlDoc.getElementsByTagName("w:tbl");
|
||||
const paragraphs = xmlDoc.getElementsByTagName("w:p");
|
||||
// 获取所有的表格
|
||||
const tables = xmlDoc.getElementsByTagName("w:tbl");
|
||||
|
||||
// 找到表格前的段落
|
||||
let previousParagraphs = [];
|
||||
let tableIndex = 0;
|
||||
// 找到表格前的段落
|
||||
let previousParagraphs = [];
|
||||
let tableIndex = 0;
|
||||
|
||||
// 遍历段落,找到第一个表格之前的段落
|
||||
for (let i = 0; i < paragraphs.length; i++) {
|
||||
if (tableIndex < tables.length && paragraphs[i].nextSibling === tables[tableIndex]) {
|
||||
break; // 找到表格
|
||||
// 遍历段落,找到第一个表格之前的段落
|
||||
for (let i = 0; i < paragraphs.length; i++) {
|
||||
if (tableIndex < tables.length && paragraphs[i].nextSibling === tables[tableIndex]) {
|
||||
break; // 找到表格
|
||||
}
|
||||
previousParagraphs.push(paragraphs[i]);
|
||||
}
|
||||
previousParagraphs.push(paragraphs[i]);
|
||||
}
|
||||
// 将前一段的内容转化为 HTML 或文本
|
||||
const previousHtml = this.convertParagraphsToHtml(previousParagraphs);
|
||||
// 将前一段的内容转化为 HTML 或文本
|
||||
const previousHtml = this.convertParagraphsToHtml(previousParagraphs);
|
||||
console.log('tables at line 17:', previousHtml)
|
||||
const tableHtml = this.convertTablesToHtml(tables, numberingMap);
|
||||
console.log('tableHtml at line 18:', tableHtml)
|
||||
@@ -478,45 +478,45 @@ const previousHtml = this.convertParagraphsToHtml(previousParagraphs);
|
||||
callback("<p>文件解析失败,请检查文件格式。</p>");
|
||||
}
|
||||
},
|
||||
// 转换段落为 HTML
|
||||
convertParagraphsToHtml(paragraphs) {
|
||||
let html = "";
|
||||
paragraphs.forEach(p => {
|
||||
let paragraphHtml = "";
|
||||
|
||||
// 处理段落中的所有子元素
|
||||
const runs = p.getElementsByTagName("w:r"); // 获取段落中的所有文本运行(可能包含上标、下标等)
|
||||
|
||||
Array.from(runs).forEach(run => {
|
||||
let text = "";
|
||||
|
||||
// 获取文本内容
|
||||
const textNodes = run.getElementsByTagName("w:t");
|
||||
Array.from(textNodes).forEach(t => {
|
||||
text += t.textContent || t.text;
|
||||
// 转换段落为 HTML
|
||||
convertParagraphsToHtml(paragraphs) {
|
||||
let html = "";
|
||||
paragraphs.forEach(p => {
|
||||
let paragraphHtml = "";
|
||||
|
||||
// 处理段落中的所有子元素
|
||||
const runs = p.getElementsByTagName("w:r"); // 获取段落中的所有文本运行(可能包含上标、下标等)
|
||||
|
||||
Array.from(runs).forEach(run => {
|
||||
let text = "";
|
||||
|
||||
// 获取文本内容
|
||||
const textNodes = run.getElementsByTagName("w:t");
|
||||
Array.from(textNodes).forEach(t => {
|
||||
text += t.textContent || t.text;
|
||||
});
|
||||
|
||||
// 检查是否为上标或下标
|
||||
const isSuperscript = run.getElementsByTagName("w:vertAlign")[0] ? run.getElementsByTagName("w:vertAlign")[0].getAttribute("w:val") === "superscript" : "";
|
||||
const isSubscript = run.getElementsByTagName("w:vertAlign")[0] ? run.getElementsByTagName("w:vertAlign")[0].getAttribute("w:val") === "subscript" : '';
|
||||
|
||||
if (isSuperscript) {
|
||||
text = `<sup>${text}</sup>`;
|
||||
} else if (isSubscript) {
|
||||
text = `<sub>${text}</sub>`;
|
||||
}
|
||||
|
||||
// 拼接到段落 HTML 中
|
||||
paragraphHtml += text;
|
||||
});
|
||||
|
||||
// 检查是否为上标或下标
|
||||
const isSuperscript = run.getElementsByTagName("w:vertAlign")[0]?run.getElementsByTagName("w:vertAlign")[0].getAttribute("w:val") === "superscript":"";
|
||||
const isSubscript = run.getElementsByTagName("w:vertAlign")[0]?run.getElementsByTagName("w:vertAlign")[0].getAttribute("w:val") === "subscript":'';
|
||||
|
||||
if (isSuperscript) {
|
||||
text = `<sup>${text}</sup>`;
|
||||
} else if (isSubscript) {
|
||||
text = `<sub>${text}</sub>`;
|
||||
}
|
||||
|
||||
// 拼接到段落 HTML 中
|
||||
paragraphHtml += text;
|
||||
// 将运行的文本拼接成完整的段落
|
||||
html += `<p>${paragraphHtml}</p>`;
|
||||
});
|
||||
|
||||
// 将运行的文本拼接成完整的段落
|
||||
html += `<p>${paragraphHtml}</p>`;
|
||||
});
|
||||
|
||||
return html;
|
||||
}
|
||||
,
|
||||
return html;
|
||||
}
|
||||
,
|
||||
convertTablesToHtml(tables, numberingMap) {
|
||||
const namespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
||||
let html = "";
|
||||
@@ -774,7 +774,7 @@ convertParagraphsToHtml(paragraphs) {
|
||||
if (['jpg', 'jpeg', 'png'].includes(extension)) {
|
||||
thumbnailContent = `<img src="${mediaUrl + img.image}" alt="Image ${index}" style="width: 100%; height: auto;">`;
|
||||
} else if (extension === 'tif') {
|
||||
thumbnailContent = `<canvas id="tiff-canvas-${index} ${img.article_image_id?`tiff-canvas-${img.article_image_id}`:''}" style="width: 100%; height: auto;"></canvas>`;
|
||||
thumbnailContent = `<canvas id="tiff-canvas-${index} ${img.article_image_id ? `tiff-canvas-${img.article_image_id}` : ''}" style="width: 100%; height: auto;"></canvas>`;
|
||||
} else {
|
||||
thumbnailContent = `<a href="${mediaUrl + img.image}" style="color: #75abf1;width:100%; height: 100%;">
|
||||
<div
|
||||
@@ -948,7 +948,7 @@ convertParagraphsToHtml(paragraphs) {
|
||||
|
||||
//更新传入所有表格样式
|
||||
updateTableStyles(container, type, setTopBottomBorder) {
|
||||
|
||||
|
||||
var typesettingType = type ? type : 1
|
||||
const tables = container.querySelectorAll('table');
|
||||
tables.forEach((table) => {
|
||||
@@ -1151,8 +1151,8 @@ convertParagraphsToHtml(paragraphs) {
|
||||
},
|
||||
|
||||
|
||||
initEditorButton(vueInstance,ed) {
|
||||
|
||||
initEditorButton(vueInstance, ed) {
|
||||
|
||||
ed.ui.registry.addMenuButton('customDropdown', {
|
||||
text: 'Set Title', // 下拉框标题
|
||||
fetch: function (callback) {
|
||||
@@ -1197,6 +1197,26 @@ convertParagraphsToHtml(paragraphs) {
|
||||
callback(menuItems);
|
||||
}
|
||||
});
|
||||
ed.ui.registry.addButton('addRow', {
|
||||
icon:'duplicate-row',
|
||||
text: 'Add Row', // 下拉框标题
|
||||
onAction: function () {
|
||||
var edSelection = ed.selection;
|
||||
const selectedNode = edSelection.getNode(); // 获取选中的节点
|
||||
let outerDiv = selectedNode;
|
||||
while (outerDiv && outerDiv.tagName !== 'DIV') {
|
||||
outerDiv = outerDiv.parentNode;
|
||||
}
|
||||
// 如果找到的 div 节点存在
|
||||
if (outerDiv) {
|
||||
const dataId = outerDiv.getAttribute('main-id');
|
||||
console.log('dataId at line 1258:', dataId)
|
||||
|
||||
vueInstance.$emit('onAddRow', dataId);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
// 添加自定义菜单项
|
||||
ed.ui.registry.addButton('Save', {
|
||||
icon: 'checkmark',
|
||||
@@ -1215,11 +1235,11 @@ convertParagraphsToHtml(paragraphs) {
|
||||
var content;
|
||||
console.log('outerDiv at line 663:', outerDiv.innerHTML);
|
||||
content = outerDiv.innerHTML.replace(/<(?!\/?(img|b|i|sub|sup|span|strong|em |blue)\b)[^>]+>/g, '');
|
||||
content =content.replace(/<([a-zA-Z]+)>\s*<\/\1>/g, '');
|
||||
content = content.replace(/ /g, ' ');
|
||||
|
||||
content = content.replace(/\s*style="[^"]*"/g, '');
|
||||
|
||||
content = content.replace(/<([a-zA-Z]+)>\s*<\/\1>/g, '');
|
||||
content = content.replace(/ /g, ' ');
|
||||
|
||||
content = content.replace(/\s*style="[^"]*"/g, '');
|
||||
|
||||
var div = document.createElement('div');
|
||||
div.innerHTML = content; // 将 HTML 字符串加载到 div 中
|
||||
// 替换所有 <strong> 为 <b>
|
||||
@@ -1243,6 +1263,72 @@ convertParagraphsToHtml(paragraphs) {
|
||||
}
|
||||
}
|
||||
});
|
||||
ed.ui.registry.addButton('level1', {
|
||||
// icon: 'highlight-bg-color',
|
||||
text: 'First level title',
|
||||
onAction: function () {
|
||||
var edSelection = ed.selection;
|
||||
const selectedNode = edSelection.getNode(); // 获取选中的节点
|
||||
let outerDiv = selectedNode;
|
||||
while (outerDiv && outerDiv.tagName !== 'DIV') {
|
||||
outerDiv = outerDiv.parentNode;
|
||||
}
|
||||
// 如果找到的 div 节点存在
|
||||
if (outerDiv) {
|
||||
const dataId = outerDiv.getAttribute('main-id');
|
||||
console.log('dataId at line 1258:', dataId)
|
||||
vueInstance.$emit('onEditTitle', {
|
||||
mainId: dataId,
|
||||
value: 1
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
ed.ui.registry.addButton('level2', {
|
||||
// icon: 'highlight-bg-color',
|
||||
text: 'Second level Title',
|
||||
onAction: function () {
|
||||
var edSelection = ed.selection;
|
||||
const selectedNode = edSelection.getNode(); // 获取选中的节点
|
||||
let outerDiv = selectedNode;
|
||||
while (outerDiv && outerDiv.tagName !== 'DIV') {
|
||||
outerDiv = outerDiv.parentNode;
|
||||
}
|
||||
// 如果找到的 div 节点存在
|
||||
if (outerDiv) {
|
||||
const dataId = outerDiv.getAttribute('main-id');
|
||||
console.log('dataId at line 1258:', dataId)
|
||||
vueInstance.$emit('onEditTitle', {
|
||||
mainId: dataId,
|
||||
value: 2
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
ed.ui.registry.addButton('level3', {
|
||||
// icon: 'highlight-bg-color',
|
||||
text: 'Third level title',
|
||||
onAction: function () {
|
||||
var edSelection = ed.selection;
|
||||
const selectedNode = edSelection.getNode(); // 获取选中的节点
|
||||
let outerDiv = selectedNode;
|
||||
while (outerDiv && outerDiv.tagName !== 'DIV') {
|
||||
outerDiv = outerDiv.parentNode;
|
||||
}
|
||||
// 如果找到的 div 节点存在
|
||||
if (outerDiv) {
|
||||
const dataId = outerDiv.getAttribute('main-id');
|
||||
console.log('dataId at line 1258:', dataId)
|
||||
vueInstance.$emit('onEditTitle', {
|
||||
mainId: dataId,
|
||||
value: 3
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
ed.ui.registry.addButton('Edit', {
|
||||
icon: 'highlight-bg-color',
|
||||
text: 'Edit',
|
||||
@@ -1277,15 +1363,87 @@ convertParagraphsToHtml(paragraphs) {
|
||||
// 如果找到的 div 节点存在
|
||||
if (outerDiv) {
|
||||
const dataId = outerDiv.getAttribute('main-id');
|
||||
let selectedText = edSelection.getContent({ format: 'text' });
|
||||
vueInstance.$emit('onAddComment', {
|
||||
mainId: dataId,
|
||||
label: selectedText ? selectedText : ''
|
||||
const type = outerDiv.getAttribute('type');
|
||||
|
||||
console.log('type:', type);
|
||||
|
||||
// 获取选中的内容(HTML格式)
|
||||
let selectedContent = edSelection.getContent({ format: 'html' });
|
||||
|
||||
// 创建一个临时容器来处理 HTML
|
||||
const tempDiv = document.createElement('div');
|
||||
tempDiv.innerHTML = selectedContent;
|
||||
|
||||
// 检查是否包含 <img> 标签
|
||||
const hasImage = tempDiv.querySelector('img') !== null;
|
||||
if (hasImage) {
|
||||
vueInstance.$message.error(vueInstance.$t('commonTable.selectComment'));
|
||||
return; // 如果包含图片,停止处理
|
||||
}
|
||||
|
||||
// 获取清理后的纯文本内容
|
||||
let selectedText = tempDiv.innerText.trim(); // 使用 trim() 清理前后的空格
|
||||
|
||||
// 处理文本中的多余空格:替换多个连续空格为一个空格
|
||||
selectedText = selectedText.replace(/\s+/g, ' ');
|
||||
|
||||
// 确保保留的标签
|
||||
const allowedTags = ['sup', 'sub', 'strong', 'em', 'b', 'i', 'blue', 'tr', 'td'];
|
||||
|
||||
// 遍历选中的节点并保留需要的标签
|
||||
function preserveTags(node) {
|
||||
if (node.nodeType === 3) { // 文本节点
|
||||
return node.nodeValue;
|
||||
}
|
||||
if (node.nodeType === 1 && allowedTags.includes(node.nodeName.toLowerCase())) {
|
||||
return node.outerHTML; // 保留整个标签
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
let preservedContent = '';
|
||||
Array.from(tempDiv.childNodes).forEach((childNode) => {
|
||||
preservedContent += preserveTags(childNode);
|
||||
});
|
||||
|
||||
// 检查选中的内容是否已经包含嵌套批注
|
||||
const containsPositionRemark = tempDiv.querySelector('.positionRemarkIndex');
|
||||
if (containsPositionRemark) {
|
||||
vueInstance.$message.error(vueInstance.$t('commonTable.alreadyCommented'));
|
||||
return; // 如果已有嵌套批注,停止处理
|
||||
}
|
||||
|
||||
// 如果内容不为空,发送批注请求
|
||||
if (type == 0) {
|
||||
if (selectedText !== '') {
|
||||
vueInstance.$emit('onAddComment', {
|
||||
mainId: dataId,
|
||||
label: preservedContent // 发送保留标签的内容
|
||||
});
|
||||
} else {
|
||||
vueInstance.$message.error(vueInstance.$t('commonTable.selectComment'));
|
||||
}
|
||||
} else if (type == 1) {
|
||||
vueInstance.$emit('onAddComment', {
|
||||
mainId: dataId,
|
||||
label: preservedContent // 发送保留标签的内容
|
||||
});
|
||||
} else if (type == 2) {
|
||||
vueInstance.$emit('onAddComment', {
|
||||
mainId: dataId,
|
||||
label: preservedContent // 发送保留标签的内容
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ed.ui.registry.addButton('delete', {
|
||||
icon: 'remove',
|
||||
text: 'Delete',
|
||||
@@ -1301,10 +1459,10 @@ convertParagraphsToHtml(paragraphs) {
|
||||
// 如果找到的 div 节点存在
|
||||
if (outerDiv) {
|
||||
const dataId = outerDiv.getAttribute('main-id');
|
||||
vueInstance.$emit('onDelete',dataId);
|
||||
vueInstance.$emit('onDelete', dataId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1320,6 +1478,8 @@ convertParagraphsToHtml(paragraphs) {
|
||||
|
||||
ed.ui.registry.addButton('customBlue', {
|
||||
text: 'Blue', // 按钮文本
|
||||
className: 'custom-button-blue', // 添加自定义类
|
||||
// shortcut: "Ctrl+J",
|
||||
onAction: function () {
|
||||
// 在选中的文本周围包裹 <blue> 标签
|
||||
var selectedText = ed.selection.getContent();
|
||||
@@ -1369,7 +1529,39 @@ convertParagraphsToHtml(paragraphs) {
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
inTinymceButtonClass() {
|
||||
setTimeout(function () {
|
||||
// 查找该按钮并添加 className
|
||||
const commentaddbutton = document.querySelector('.tox-toolbar .tox-toolbar__group .tox-tbtn[data-mce-name="commentadd"]');
|
||||
if (commentaddbutton) {
|
||||
commentaddbutton.classList.add('tinymce-custom-button-commentadd');
|
||||
}
|
||||
const addrowbutton = document.querySelector('.tox-toolbar .tox-toolbar__group .tox-tbtn[data-mce-name="addrow"]');
|
||||
if (addrowbutton) {
|
||||
addrowbutton.classList.add('tinymce-custom-button-addrow');
|
||||
}
|
||||
const deletebutton = document.querySelector('.tox-toolbar .tox-toolbar__group .tox-tbtn[data-mce-name="delete"]');
|
||||
if (deletebutton) {
|
||||
deletebutton.classList.add('tinymce-custom-button-delete');
|
||||
}
|
||||
const editbutton = document.querySelector('.tox-toolbar .tox-toolbar__group .tox-tbtn[data-mce-name="edit"]');
|
||||
if (editbutton) {
|
||||
editbutton.classList.add('tinymce-custom-button-edit');
|
||||
}
|
||||
const savebutton = document.querySelector('.tox-toolbar .tox-toolbar__group .tox-tbtn[data-mce-name="save"]');
|
||||
if (savebutton) {
|
||||
savebutton.classList.add('tinymce-custom-button-save');
|
||||
}
|
||||
const button = document.querySelector('.tox-toolbar .tox-toolbar__group .tox-tbtn[data-mce-name="customblue"]');
|
||||
if (button) {
|
||||
button.classList.add('tinymce-custom-button-blue');
|
||||
}
|
||||
const removebutton = document.querySelector('.tox-toolbar .tox-toolbar__group .tox-tbtn[data-mce-name="removeblue"]');
|
||||
if (removebutton) {
|
||||
removebutton.classList.add('tinymce-custom-button-removeblue');
|
||||
}
|
||||
}, 100); // 延迟执行,确保按钮渲染完成
|
||||
}
|
||||
|
||||
// 通用递归方法
|
||||
|
||||
|
||||
Reference in New Issue
Block a user