This commit is contained in:
2025-06-09 15:55:07 +08:00
parent 8c4701c2e6
commit 19c672b3c7
9 changed files with 220 additions and 137 deletions

View File

@@ -52,9 +52,10 @@ const capitalizeFirstLetter = function (text) {
//px
function emuToPixels(emu) {
// 将 EMU 转换为厘米,并进一步转换为像素
const emuToPixels = emu / 914400 * 2.54 * 96;
const emuToPixels = emu * 96 / 914400;
// return parseFloat((emu * 96 / 914400).toFixed(2)); // ✅
// 四舍五入并保留两位小数
return (Math.round(emuToPixels * 100) / 100).toFixed(2);
return (Math.round(emuToPixels * 100) / 100).toFixed(0);
}
function findExtentElement(blipElement) {
let current = blipElement.parentElement;
@@ -87,7 +88,7 @@ export default {
},
opMedicalList() {
var opMedical =JSON.parse(localStorage.getItem('opMedicalListData'))
var opMedical = JSON.parse(localStorage.getItem('opMedicalListData'))
return opMedical;
},
@@ -113,37 +114,37 @@ export default {
handleFileUpload(event, callback) {
handleFileUpload(event, callback) {
const file = event.target.files[0];
if (!file || file.type !== 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
alert('请上传一个有效的 Word 文件');
alert('Please upload a valid Word file !');
return;
}
const reader = new FileReader();
reader.onload = (e) => {
const arrayBuffer = e.target.result;
const zip = new JSZip();
zip.loadAsync(arrayBuffer).then(async (zip) => {
const relsXml = await zip.files['word/_rels/document.xml.rels'].async('string');
const docXml = await zip.files['word/document.xml'].async('string');
const parser = new DOMParser();
const relDoc = parser.parseFromString(relsXml, "text/xml");
const docDom = parser.parseFromString(docXml, "text/xml");
const rels = {};
Array.from(relDoc.getElementsByTagName('Relationship')).forEach((rel) => {
const id = rel.getAttribute('Id');
const target = rel.getAttribute('Target'); // e.g., 'media/image1.jpeg'
const target = rel.getAttribute('Target');
rels[id] = target;
});
const imageInfoMap = {};
const blips = docDom.getElementsByTagName('a:blip');
Array.from(blips).forEach((blip) => {
const embedId = blip.getAttribute('r:embed');
const extent = findExtentElement(blip);
@@ -153,84 +154,57 @@ export default {
if (cx && cy) {
const width = emuToPixels(cx);
const height = emuToPixels(cy);
const mediaFile = rels[embedId];
if (mediaFile) {
imageInfoMap[mediaFile] = { width, height };
console.log('imageInfoMap at line 158:', imageInfoMap)
}
imageInfoMap[embedId] = { width, height };
}
}
});
mammoth.convertToHtml({ arrayBuffer },
{
convertImage: mammoth.images.inline(async function (image) {
const contentType = image.contentType.toLowerCase();
// 只允许这三种格式
const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png'];
if (!allowedTypes.includes(contentType)) {
// 跳过不支持的格式(如 image/tiff、image/x-emf 等)
return { src: '' }; // 会从 HTML 中删除这张图片
}
// 读取为 base64 并构造 src
const imageBuffer = await image.read("base64");
const base64Src = `data:${contentType};base64,${imageBuffer}`;
return {
src: base64Src
};
})
})
.then((result) => {
let html = result.value;
// html = html.replace(/<img[^>]+src="data:image\/x-emf[^"]*"[^>]*>/gi, '');
// 替换图片标签中的宽高
const imgTags = html.match(/<img[^>]*src="data:image\/(png|jpg|jpeg);base64,[^"]*"/gi);
console.log('imgTags at line 190:', imgTags);
if (imgTags) {
imgTags.forEach((imgTag) => {
// 提取 "image数字.png" 或 "image数字.jpg" 这样的文件名
const match = imgTag.match(/image(\d+)\.(png|jpg|jpeg)/);
if (match) {
// 构造文件名,例如 "media/image1.png"
const filename = `media/image${match[1]}.${match[2]}`;
const info = imageInfoMap[filename]; // 从 imageInfoMap 中查找宽高信息
console.log('info at line 196:', info); // 查看是否找到了相关图片信息
if (info) {
// 如果找到了图片的信息,就添加宽度和高度到 <img> 标签
const newImgTag = imgTag.replace(
/<img/,
`<img width="${info.width}" height="${info.height}"`
);
html = html.replace(imgTag, newImgTag); // 替换原始的 <img> 标签
}
}
});
mammoth.convertToHtml({ arrayBuffer }, {
convertImage: mammoth.images.inline(async function (image) {
console.log('image at line 163:', image)
const contentType = image.contentType.toLowerCase();
const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png'];
if (!allowedTypes.includes(contentType)) {
return { src: '' };
}
// 提取合法表格
const tableContent = html.match(/<table[\s\S]*?<\/table>/g);
const validTables = tableContent
? tableContent.filter(table => /<td[\s\S]*?>/.test(table))
: [];
callback(validTables);
const embedId = image.relationshipId || image.refId || '';
const imageBuffer = await image.read("base64");
const base64Src = `data:${contentType};base64,${imageBuffer}`;
let width = '', height = '';
if (embedId && imageInfoMap[embedId]) {
width = imageInfoMap[embedId].width;
height = imageInfoMap[embedId].height;
}
return {
src: base64Src,
alt: '',
width,
height,
refId: embedId,
'content-type': contentType
};
})
.catch(err => {
console.error('mammoth 转换失败:', err);
});
}).then((result) => {
let html = result.value;
// 提取合法表格
const tableContent = html.match(/<table[\s\S]*?<\/table>/g);
const validTables = tableContent
? tableContent.filter(table => /<td[\s\S]*?>/.test(table))
: [];
callback(validTables);
}).catch(err => {
console.error('mammoth 转换失败:', err);
});
}).catch(err => {
console.error("Zip 读取失败:", err);
});
};
reader.readAsArrayBuffer(file);
},