This commit is contained in:
2024-12-05 16:32:46 +08:00
parent 7aa531c2ca
commit b1cac52d2a
10 changed files with 315 additions and 4621 deletions

215
src/common/js/commonJS.js Normal file
View File

@@ -0,0 +1,215 @@
export default {
// 提取 Word 文件中的表格
extractTablesFromWord(arrayBuffer, callback) {
const zip = new JSZip();
zip.loadAsync(arrayBuffer)
.then((zip) => zip.file('word/document.xml').async('string'))
.then((docXml) => {
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(docXml, 'text/xml');
const tables = xmlDoc.getElementsByTagName('w:tbl'); // 查找 Word 表格标签
let html = '';
const wordTables = []
for (let table of tables) {
var str = this.convertTableToHtml(table);
const container = document.createElement('div');
container.innerHTML = str;
wordTables.push({
html: this.updateTableStyles(container),
orientation: 'portrait' // 默认纵向
});
html += str;
}
if (!html)
html = '<p>未检测到表格内容。</p>';
callback( Array.from(wordTables).map((table) => table.html).join(''), wordTables);
})
.catch(function (err) {
console.error('解析 Word 文件出错:', err);
callback('<p>文件解析失败,请检查文件格式。</p>');
});
},
//更新传入所有表格样式
updateTableStyles(container,type,setTopBottomBorder) {
var typesettingType=type?type:1
const tables = container.querySelectorAll('table');
tables.forEach((table) => {
table.setAttribute(
'style',
`width: ${typesettingType == 1 ? '17.18cm' : '25.88cm'
};border: none; margin: 0 auto !important;border-collapse: collapse; `
);
const cells = table.querySelectorAll('td');
cells.forEach((td) => {
if (/^-?\d+(\.\d+)?$/.test(td.textContent.trim())) {
this.replaceNegativeSign(td);
}
// 检查当前 td 是否包含上下标
if (!this.containsSupOrSub(td)) {
// 递归处理单元格内的所有子节点
td.childNodes.forEach((node) => this.capitalizeFirstLetter(node));
// 替换 <a> 标签为其内部文本
td.querySelectorAll('a').forEach((a) => a.replaceWith(document.createTextNode(a.textContent)));
}
const childElements = td.querySelectorAll('*');
// 遍历每个子元素
childElements.forEach((element) => {
// 如果元素的文本内容匹配正则表达式
if (/\[\d+(?:,\d+)*\]/g.test(element.textContent)) {
element.classList.add('color-highlight');
element.style.color = 'rgb(0,130,170)';
}
});
});
if(setTopBottomBorder){
const firstRowTdElements = container.querySelectorAll('tr:first-child td'); // 获取第一个 <tr> 中的所有 <td> 元素
firstRowTdElements.forEach((td) => {
const currentStyle = td.getAttribute('style');
if (currentStyle) {
td.setAttribute(
'style',
currentStyle +
';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;'
);
} else {
td.setAttribute(
'style',
'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;'
);
}
});
const firstRowTdElementsLast = container.querySelectorAll('tr:last-of-type td');
firstRowTdElementsLast.forEach((td) => {
// 获取当前的 style 属性(如果有)
const currentStyle = td.getAttribute('style');
// 如果已有 style 属性,则追加边框样式;如果没有 style 属性,则设置新的 style
if (currentStyle) {
td.setAttribute(
'style',
currentStyle +
';border-bottom:1.0000pt solid #000 !important;mso-border-bottom-alt:0.5000pt solid #000 !important;'
);
} else {
td.setAttribute(
'style',
'border-bottom:1.0000pt solid #000 !important;mso-border-bottom-alt:0.5000pt solid #000 !important;'
);
}
});
}
});
return Array.from(tables).map((table) => table.outerHTML).join('');
},
// 将 XML 表格转换为 HTML
convertTableToHtml(tableNode) {
const rows = tableNode.getElementsByTagName('w:tr');
let html = '<table border="1" style="border-collapse: collapse;">';
for (let row of rows) {
html += '<tr>';
const cells = row.getElementsByTagName('w:tc');
for (let cell of cells) {
let cellHtml = '';
const paragraphs = cell.getElementsByTagName('w:p'); // 获取单元格内段落
for (let paragraph of paragraphs) {
const texts = paragraph.getElementsByTagName('w:r'); // 获取段落内的文本和样式
for (let run of texts) {
const textNode = run.getElementsByTagName('w:t')[0];
if (textNode) {
const style = this.getStyleFromRun(run); // 提取样式
cellHtml += `<span style="${style}">${textNode.textContent}</span>`;
}
}
cellHtml += '<br>'; // 段落换行
}
html += `<td>${cellHtml}</td>`;
}
html += '</tr>';
}
html += '</table>';
return html;
},
// 提取 w:r 节点中的样式并转换为 CSS
getStyleFromRun(run) {
const styleNode = run.getElementsByTagName('w:rPr')[0];
let style = '';
if (styleNode) {
// 加粗
if (styleNode.getElementsByTagName('w:b').length > 0) {
style += 'font-weight: bold;';
}
// 斜体
if (styleNode.getElementsByTagName('w:i').length > 0) {
style += 'font-style: italic;';
}
// 上标或下标
const vertAlign = styleNode.getElementsByTagName('w:vertAlign')[0];
if (vertAlign) {
const alignVal = vertAlign.getAttribute('w:val');
if (alignVal === 'superscript') {
style += 'vertical-align: super; font-size: smaller;';
} else if (alignVal === 'subscript') {
style += 'vertical-align: sub; font-size: smaller;';
}
}
// 字体颜色
const colorNode = styleNode.getElementsByTagName('w:color')[0];
if (colorNode) {
const colorVal = colorNode.getAttribute('w:val');
style += `color: #${colorVal};`;
}
}
return style;
},
replaceNegativeSign(node) {
if (node.nodeType === Node.TEXT_NODE) {
// 如果是文本节点,替换负号
node.nodeValue = node.nodeValue.replace(/^-(?=\d)/, '');
} else if (node.nodeType === Node.ELEMENT_NODE) {
this.applyToChildNodes(node, (child) => this.replaceNegativeSign(child));
}
},
capitalizeFirstLetter(node) {
if (node.nodeType === Node.TEXT_NODE) {
// 如果是文本节点,只处理第一个非空字符
node.nodeValue = node.nodeValue.replace(/^\s*([a-zA-Z])/, (match, firstLetter) => firstLetter.toUpperCase());
} else if (node.nodeType === Node.ELEMENT_NODE) {
this.applyToChildNodes(node, (child) => this.capitalizeFirstLetter(child));
}
},
applyToChildNodes(node, fn) {
if (node.nodeType === Node.ELEMENT_NODE) {
node.childNodes.forEach(fn);
}
},
containsSupOrSub(element) {
// 如果当前节点是元素节点
if (element.nodeType === 1) {
// 如果是 <sup> 或 <sub> 标签,返回 true
if (element.tagName === 'SUP' || element.tagName === 'SUB') {
return true;
}
// 否则,递归检查子节点
return Array.from(element.childNodes).some((child) => this.containsSupOrSub(child));
}
// 如果不是元素节点(如文本节点),返回 false
return false;
},
// 通用递归方法
};