提交
This commit is contained in:
@@ -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: '/', //正式
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -350,6 +350,21 @@ export default {
|
|||||||
console.error("❌ 找不到 word/document.xml,无法解析 Word 文件");
|
console.error("❌ 找不到 word/document.xml,无法解析 Word 文件");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const relsFile = zip.file("word/_rels/document.xml.rels");
|
||||||
|
let imageRelMap = {};
|
||||||
|
if (relsFile) {
|
||||||
|
const relsXml = await relsFile.async("string");
|
||||||
|
const relDoc = new DOMParser().parseFromString(relsXml, "application/xml");
|
||||||
|
const rels = relDoc.getElementsByTagName("Relationship");
|
||||||
|
for (let r = 0; r < rels.length; r++) {
|
||||||
|
const id = rels[r].getAttribute("Id");
|
||||||
|
const target = rels[r].getAttribute("Target");
|
||||||
|
if (target && target.includes("media/")) {
|
||||||
|
// 补全路径,通常 rels 里的路径是相对 word 文件夹的
|
||||||
|
imageRelMap[id] = `word/${target}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
const documentXml = await documentFile.async("string");
|
const documentXml = await documentFile.async("string");
|
||||||
const parser = new DOMParser();
|
const parser = new DOMParser();
|
||||||
const documentDoc = parser.parseFromString(documentXml, "application/xml");
|
const documentDoc = parser.parseFromString(documentXml, "application/xml");
|
||||||
@@ -458,14 +473,44 @@ export default {
|
|||||||
const drawings = run.getElementsByTagName("w:drawing");
|
const drawings = run.getElementsByTagName("w:drawing");
|
||||||
for (let d = 0; d < drawings.length; d++) {
|
for (let d = 0; d < drawings.length; d++) {
|
||||||
const drawing = drawings[d];
|
const drawing = drawings[d];
|
||||||
// 使用命名空间提取 a:blip
|
|
||||||
|
// --- 1. 提取宽高 (EMUs 转 PX) ---
|
||||||
|
// Word 存储尺寸的地方通常在 wp:extent
|
||||||
|
const extent = drawing.getElementsByTagName("wp:extent")[0];
|
||||||
|
let styleStr = "";
|
||||||
|
if (extent) {
|
||||||
|
const cx = parseInt(extent.getAttribute("cx"));
|
||||||
|
const cy = parseInt(extent.getAttribute("cy"));
|
||||||
|
// 9525 是 EMU 到像素的换算比例
|
||||||
|
const widthPx = Math.round(cx / 9525);
|
||||||
|
const heightPx = Math.round(cy / 9525);
|
||||||
|
styleStr = `width="${widthPx}" height="${heightPx}"`;
|
||||||
|
}
|
||||||
|
|
||||||
const blips = drawing.getElementsByTagNameNS("http://schemas.openxmlformats.org/drawingml/2006/main", "blip");
|
const blips = drawing.getElementsByTagNameNS("http://schemas.openxmlformats.org/drawingml/2006/main", "blip");
|
||||||
for (let b = 0; b < blips.length; b++) {
|
for (let b = 0; b < blips.length; b++) {
|
||||||
const blip = blips[b];
|
const blip = blips[b];
|
||||||
const embedId = blip.getAttribute("r:embed");
|
const embedId = blip.getAttribute("r:embed");
|
||||||
if (embedId) {
|
|
||||||
textContent += `<img data-embed="${embedId}"/>`;
|
|
||||||
|
|
||||||
|
if (embedId && imageRelMap[embedId]) {
|
||||||
|
// const imagePath = imageRelMap[embedId];
|
||||||
|
// const imgFile = zip.file(imagePath);
|
||||||
|
|
||||||
|
// if (imgFile) {
|
||||||
|
// const fileSize = imgFile._data.uncompressedSize;
|
||||||
|
|
||||||
|
// // 依然保留 1MB 限制,保护浏览器不卡死
|
||||||
|
// if (fileSize <= 1048576) {
|
||||||
|
// const base64 = await imgFile.async("base64");
|
||||||
|
// const ext = imagePath.split('.').pop().toLowerCase();
|
||||||
|
// // <img src="data:image/${ext};base64,${base64}" ${styleStr} />
|
||||||
|
// // --- 2. 直接拼接带宽高的 img 标签 ---
|
||||||
|
// textContent += ``;
|
||||||
|
// } else {
|
||||||
|
// // console.warn(`跳过大图片: ${imagePath}, 大小: ${(fileSize / 1024 / 1024).toFixed(2)}MB`);
|
||||||
|
// textContent += ``;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
//记得切换
|
//记得切换
|
||||||
|
|
||||||
//正式
|
//正式
|
||||||
// const mediaUrl = '/public/';
|
const mediaUrl = '/public/';
|
||||||
// const baseUrl = '/';
|
const baseUrl = '/';
|
||||||
|
|
||||||
//正式环境
|
//正式环境
|
||||||
|
|
||||||
@@ -18,8 +18,8 @@
|
|||||||
// const baseUrl = '/api';
|
// const baseUrl = '/api';
|
||||||
|
|
||||||
////新正式环境
|
////新正式环境
|
||||||
const mediaUrl = 'http://mytest.tmrjournals.com/public/';
|
// const mediaUrl = 'http://mytest.tmrjournals.com/public/';
|
||||||
const baseUrl = '/api';
|
// const baseUrl = '/api';
|
||||||
|
|
||||||
//本地(正式环境 )
|
//本地(正式环境 )
|
||||||
// const mediaUrl = 'https://submission.tmrjournals.com/public/';
|
// const mediaUrl = 'https://submission.tmrjournals.com/public/';
|
||||||
|
|||||||
@@ -2804,7 +2804,7 @@ export default {
|
|||||||
that.$commonJS.extractWordTablesToArrays(File.raw, function (wordTables) {
|
that.$commonJS.extractWordTablesToArrays(File.raw, function (wordTables) {
|
||||||
that.addWordTablesList(wordTables);
|
that.addWordTablesList(wordTables);
|
||||||
loading.close();
|
loading.close();
|
||||||
});
|
},that.form.article_id);
|
||||||
};
|
};
|
||||||
reader.readAsArrayBuffer(File.raw);
|
reader.readAsArrayBuffer(File.raw);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1298,7 +1298,7 @@
|
|||||||
<span slot="label" class="title" :style="v.color ? `color:${v.color}` : ''">
|
<span slot="label" class="title" :style="v.color ? `color:${v.color}` : ''">
|
||||||
{{ `${i + 1}. ${v.topic} : ` }}
|
{{ `${i + 1}. ${v.topic} : ` }}
|
||||||
</span>
|
</span>
|
||||||
<div style="">
|
<div style="" v-if="v.value!='hotspot'">
|
||||||
<div
|
<div
|
||||||
style="color: #333; width: calc(100% - 180px); margin-left: 180px"
|
style="color: #333; width: calc(100% - 180px); margin-left: 180px"
|
||||||
v-if="v.parameter && v.parameter.length > 0"
|
v-if="v.parameter && v.parameter.length > 0"
|
||||||
@@ -1349,6 +1349,58 @@
|
|||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div style="color: #888; line-height: 22px" v-if="v.explanationValue">
|
||||||
|
<p
|
||||||
|
:class="{ 'short-content': !v.showFullContent }"
|
||||||
|
@click="toggleContent1(i)"
|
||||||
|
style="margin-top: 0; cursor: pointer; color: #888"
|
||||||
|
>
|
||||||
|
<span>{{ $t('aiReview.Explain') }} : </span> {{ currentArticleData.ai_review[v.explanationValue] }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="" v-else>
|
||||||
|
<div
|
||||||
|
style="color: #333; width: calc(100% - 180px); margin-left: 180px"
|
||||||
|
v-if=" currentArticleData.ai_review[v.value] && currentArticleData.ai_review[v.value].length > 0"
|
||||||
|
>
|
||||||
|
<div label="``" v-for="(item, index) in currentArticleData.ai_review[v.value]">
|
||||||
|
<span class="title" style="" :style="item.color ? `color:${item.color}` : ''">
|
||||||
|
|
||||||
|
{{ `(${index + 1}) 领域 : ${item['领域']} ` }}
|
||||||
|
</span>
|
||||||
|
<div style="">
|
||||||
|
<div style="color: #333">
|
||||||
|
|
||||||
|
是否热点 : 【{{item['是否热点'] }}】
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div v-if="item['解释说明']">
|
||||||
|
<div>
|
||||||
|
<p
|
||||||
|
:class="{ 'short-content': !item.showFullContent }"
|
||||||
|
@click="toggleContent2(i, index)"
|
||||||
|
style="margin-top: 0; cursor: pointer; color: #888; line-height: 22px"
|
||||||
|
>
|
||||||
|
<span>{{ $t('aiReview.Explain') }} : </span>
|
||||||
|
{{ item['解释说明'] }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="color: #333" v-else>
|
||||||
|
<template v-if="v.isShowSign == 1"> 【{{ currentArticleData.ai_review[v.value] }}】 </template>
|
||||||
|
<template v-else>
|
||||||
|
{{ currentArticleData.ai_review[v.value] }}
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div style="color: #888; line-height: 22px" v-if="v.explanationValue">
|
<div style="color: #888; line-height: 22px" v-if="v.explanationValue">
|
||||||
<p
|
<p
|
||||||
:class="{ 'short-content': !v.showFullContent }"
|
:class="{ 'short-content': !v.showFullContent }"
|
||||||
@@ -2076,7 +2128,7 @@ export default {
|
|||||||
ai_review: ''
|
ai_review: ''
|
||||||
};
|
};
|
||||||
if (res.data) {
|
if (res.data) {
|
||||||
this.currentArticleData.ai_review = res.data;
|
this.currentArticleData.ai_review = {...res.data, hotspot: res.data.hotspot?JSON.parse(res.data.hotspot):''};
|
||||||
var aiReview = {};
|
var aiReview = {};
|
||||||
if (this.currentArticleData.ai_review.journal_scope_assessment == '否') {
|
if (this.currentArticleData.ai_review.journal_scope_assessment == '否') {
|
||||||
aiReview = {
|
aiReview = {
|
||||||
@@ -2108,6 +2160,8 @@ export default {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
this.aiReview[0] = aiReview;
|
this.aiReview[0] = aiReview;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
|
|||||||
@@ -2981,7 +2981,7 @@ export default {
|
|||||||
this.preactive = 1;
|
this.preactive = 1;
|
||||||
// 获取文章信息
|
// 获取文章信息
|
||||||
this.$api
|
this.$api
|
||||||
.post('api/Production/getProductionMains', {
|
.post('api/Preaccept/getArticleMains', {
|
||||||
p_article_id: this.p_article_id
|
p_article_id: this.p_article_id
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
|||||||
@@ -347,42 +347,44 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 按照你要求的 XMLHttpRequest 格式编写
|
// 按照你要求的 XMLHttpRequest 格式编写
|
||||||
uploadSingleImage(base64Data, index) {
|
// 直接接收已经转好的 blob
|
||||||
|
uploadSingleImage(blob, index) {
|
||||||
const _this = this;
|
const _this = this;
|
||||||
//转为 Blob
|
|
||||||
const blob = _this.dataURLtoBlob(base64Data);
|
|
||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
// 按照你截图中的参数名,这里假设是 'file'
|
|
||||||
|
// 直接把传进来的 blob 丢进表单
|
||||||
formData.append('file_name', blob, `word_img_${index}.png`);
|
formData.append('file_name', blob, `word_img_${index}.png`);
|
||||||
formData.append('article_id', this.articleId);
|
formData.append('article_id', this.articleId);
|
||||||
|
|
||||||
xhr.withCredentials = false;
|
xhr.withCredentials = false;
|
||||||
xhr.open('POST', _this.baseUrl + 'api/Articlemain/uploadTableImage');
|
xhr.open('POST', _this.baseUrl + 'api/Articlemain/uploadTableImage');
|
||||||
|
|
||||||
xhr.onload = function () {
|
xhr.onload = function () {
|
||||||
if (xhr.status !== 200) {
|
if (xhr.status !== 200) {
|
||||||
console.error('HTTP Error: ' + xhr.status);
|
_this.removePlaceholder(index); // 失败清理
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const json = JSON.parse(xhr.responseText);
|
const json = JSON.parse(xhr.responseText);
|
||||||
if (json.status == 1) {
|
if (json.status == 1) {
|
||||||
// 2. 拼接服务器返回的 URL
|
|
||||||
const finalUrl = _this.mediaUrl + 'articleTableImage/' + json.data;
|
const finalUrl = _this.mediaUrl + 'articleTableImage/' + json.data;
|
||||||
// 3. 找到对应的加载中占位图并替换
|
|
||||||
const doc = tinymce.activeEditor.getDoc();
|
const doc = tinymce.activeEditor.getDoc();
|
||||||
const placeholder = doc.querySelector(`img[data-idx="${index}"]`);
|
const placeholder = doc.querySelector(`img[data-idx="${index}"]`);
|
||||||
if (placeholder) {
|
if (placeholder) {
|
||||||
placeholder.src = finalUrl;
|
placeholder.src = finalUrl;
|
||||||
placeholder.removeAttribute('data-idx'); // 任务完成,移除标记
|
placeholder.removeAttribute('data-idx');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_this.removePlaceholder(index);
|
_this.removePlaceholder(index);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('解析响应失败', e);
|
console.error('解析响应失败', e);
|
||||||
|
_this.removePlaceholder(index);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
xhr.onerror = () => _this.removePlaceholder(index);
|
||||||
xhr.send(formData);
|
xhr.send(formData);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -591,12 +593,17 @@ myfigure *,
|
|||||||
_this.updateUploadProgressNotification(i, 'tooLarge');
|
_this.updateUploadProgressNotification(i, 'tooLarge');
|
||||||
return; // 跳过此图片
|
return; // 跳过此图片
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const base64 = _this.hexToBase64Sync(img.hex, img.mimeType);
|
|
||||||
_this.updateUploadProgressNotification(i, 'uploading'); // 更新为上传中
|
const imageBlob = _this.hexToBlob(img.hex, img.mimeType);
|
||||||
await _this.uploadSingleImage(base64, i);
|
|
||||||
_this.updateUploadProgressNotification(i, 'success'); // 上传成功
|
_this.updateUploadProgressNotification(i, 'uploading');
|
||||||
|
|
||||||
|
// 2. 【核心优化】直接上传这个 Blob 文件
|
||||||
|
// uploadSingleImage 内部需要改用 FormData 发送
|
||||||
|
await _this.uploadSingleImage(imageBlob, i);
|
||||||
|
|
||||||
|
_this.updateUploadProgressNotification(i, 'success');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Upload failed:', err);
|
console.error('Upload failed:', err);
|
||||||
_this.updateUploadProgressNotification(i, 'fail', err.message || 'Network error'); // 上传失败
|
_this.updateUploadProgressNotification(i, 'fail', err.message || 'Network error'); // 上传失败
|
||||||
@@ -895,8 +902,15 @@ console.log('Processed content:', content); // 输出处理后的内容
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 提取 Word 文件中的表格
|
|
||||||
|
|
||||||
|
hexToBlob(hex, mimeType) {
|
||||||
|
const len = hex.length / 2;
|
||||||
|
const bytes = new Uint8Array(len);
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
bytes[i] = parseInt(hex.substr(i * 2, 2), 16);
|
||||||
|
}
|
||||||
|
return new Blob([bytes], { type: mimeType });
|
||||||
|
},
|
||||||
updateTableStyles(container) {
|
updateTableStyles(container) {
|
||||||
var html = this.$commonJS.updateTableStyles(container, this.typesettingType);
|
var html = this.$commonJS.updateTableStyles(container, this.typesettingType);
|
||||||
var editor = window.tinymce.activeEditor; // 将外部 DOM 内容更新到编辑器
|
var editor = window.tinymce.activeEditor; // 将外部 DOM 内容更新到编辑器
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<div class="img-wrapper">
|
<div class="img-wrapper">
|
||||||
<img :src="mediaUrl + processedItem.url" class="full-screen-img" @click="close" title="点击图片关闭">
|
<img :src="mediaUrl + (processedItem.url||processedItem.image)" class="full-screen-img" @click="close" title="点击图片关闭">
|
||||||
</div>
|
</div>
|
||||||
<div class="imageTitle font" style="margin-top: 0px;">
|
<div class="imageTitle font" style="margin-top: 0px;">
|
||||||
<span v-html="processedItem.title"></span>
|
<span v-html="processedItem.title"></span>
|
||||||
@@ -71,7 +71,7 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async open(type, item) {
|
async open(type, item,isNoBg) {
|
||||||
this.visible = true;
|
this.visible = true;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ export default {
|
|||||||
...item.table,
|
...item.table,
|
||||||
tableHeader: processed.tableHeader,
|
tableHeader: processed.tableHeader,
|
||||||
tableContent: processed.tableContent,
|
tableContent: processed.tableContent,
|
||||||
oddRowIds: processed.oddRowIds
|
oddRowIds: isNoBg ? [] : processed.oddRowIds
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -1796,19 +1796,17 @@ export default {
|
|||||||
this.$refs.proofreadingContent.getTinymceContent('proofreadingContent');
|
this.$refs.proofreadingContent.getTinymceContent('proofreadingContent');
|
||||||
}, 2000),
|
}, 2000),
|
||||||
convertSpacesToNbsp(html) {
|
convertSpacesToNbsp(html) {
|
||||||
// 把字符串转成 DOM 结构
|
|
||||||
const parser = new DOMParser();
|
const parser = new DOMParser();
|
||||||
const doc = parser.parseFromString(`<div>${html}</div>`, 'text/html'); // 包一层防止body空
|
const doc = parser.parseFromString(`<div>${html}</div>`, 'text/html'); // 包一层防止body空
|
||||||
|
|
||||||
// 遍历所有文本节点
|
|
||||||
const walker = doc.createTreeWalker(doc.body, NodeFilter.SHOW_TEXT);
|
const walker = doc.createTreeWalker(doc.body, NodeFilter.SHOW_TEXT);
|
||||||
let node;
|
let node;
|
||||||
while ((node = walker.nextNode())) {
|
while ((node = walker.nextNode())) {
|
||||||
const text = node.nodeValue;
|
const text = node.nodeValue;
|
||||||
|
|
||||||
// 转换逻辑:
|
|
||||||
// 1. 保留开头和结尾空格
|
|
||||||
// 2. 保留中间连续空格
|
|
||||||
const replaced = text
|
const replaced = text
|
||||||
.replace(/(^ +)|( +$)/g, (m) => '\u00A0'.repeat(m.length)) // 首尾空格
|
.replace(/(^ +)|( +$)/g, (m) => '\u00A0'.repeat(m.length)) // 首尾空格
|
||||||
.replace(/ {2,}/g, (m) => '\u00A0'.repeat(m.length)); // 中间多个空格
|
.replace(/ {2,}/g, (m) => '\u00A0'.repeat(m.length)); // 中间多个空格
|
||||||
@@ -1828,14 +1826,14 @@ export default {
|
|||||||
};
|
};
|
||||||
this.editProofreadingContentVisible = true;
|
this.editProofreadingContentVisible = true;
|
||||||
|
|
||||||
// this.currentId = data.am_id;
|
|
||||||
},
|
},
|
||||||
async handleClickProofreading(data, index) {
|
async handleClickProofreading(data, index) {
|
||||||
await this.goToListComment(data);
|
await this.goToListComment(data);
|
||||||
},
|
},
|
||||||
// 让右侧相同 id 的项闪一下边框,并可选滚动到可视区域
|
|
||||||
flashRightPanel(proofreadingId, { scroll = true, offset = 80 } = {}) {
|
flashRightPanel(proofreadingId, { scroll = true, offset = 80 } = {}) {
|
||||||
// 1️⃣ 清除所有其他元素的闪烁样式
|
|
||||||
const oldFlashEls = document.querySelectorAll('.flash-border');
|
const oldFlashEls = document.querySelectorAll('.flash-border');
|
||||||
oldFlashEls.forEach((el) => {
|
oldFlashEls.forEach((el) => {
|
||||||
el.classList.remove('flash-border');
|
el.classList.remove('flash-border');
|
||||||
@@ -1849,18 +1847,18 @@ export default {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 2️⃣ 获取当前匹配元素
|
|
||||||
const items = document.querySelectorAll(`[data-proofreading-id="${proofreadingId}"]`);
|
const items = document.querySelectorAll(`[data-proofreading-id="${proofreadingId}"]`);
|
||||||
if (!items.length) return;
|
if (!items.length) return;
|
||||||
|
|
||||||
items.forEach((el) => {
|
items.forEach((el) => {
|
||||||
// 3️⃣ 确保能重新触发动画
|
|
||||||
el.classList.remove('flash-border');
|
el.classList.remove('flash-border');
|
||||||
// 强制重排
|
|
||||||
void el.offsetWidth;
|
void el.offsetWidth;
|
||||||
el.classList.add('flash-border');
|
el.classList.add('flash-border');
|
||||||
|
|
||||||
// 4️⃣ 动画结束时自动清除
|
|
||||||
el.__flashHandler = (evt) => {
|
el.__flashHandler = (evt) => {
|
||||||
if (evt.animationName === 'flashFade') {
|
if (evt.animationName === 'flashFade') {
|
||||||
el.classList.remove('flash-border');
|
el.classList.remove('flash-border');
|
||||||
@@ -1870,7 +1868,6 @@ export default {
|
|||||||
};
|
};
|
||||||
el.addEventListener('animationend', el.__flashHandler);
|
el.addEventListener('animationend', el.__flashHandler);
|
||||||
|
|
||||||
// 5️⃣ 兜底 2 秒后清除
|
|
||||||
el.__flashTimer = setTimeout(() => {
|
el.__flashTimer = setTimeout(() => {
|
||||||
el.classList.remove('flash-border');
|
el.classList.remove('flash-border');
|
||||||
if (el.__flashHandler) {
|
if (el.__flashHandler) {
|
||||||
@@ -1880,8 +1877,7 @@ export default {
|
|||||||
el.__flashTimer = null;
|
el.__flashTimer = null;
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
// 6️⃣ 自动滚动
|
|
||||||
// if (scroll) this.scrollContainerTo(el, offset);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
scrollContainerTo(targetEl, offset = 80) {
|
scrollContainerTo(targetEl, offset = 80) {
|
||||||
@@ -1930,7 +1926,7 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
openMenu(event, type, currentId) {
|
openMenu(event, type, currentId) {
|
||||||
console.log('event at line 860:', event);
|
|
||||||
// 获取鼠标点击位置
|
// 获取鼠标点击位置
|
||||||
this.menuPosition.x = event.clientX + 30;
|
this.menuPosition.x = event.clientX + 30;
|
||||||
this.menuPosition.y = event.clientY + 40;
|
this.menuPosition.y = event.clientY + 40;
|
||||||
@@ -2036,7 +2032,7 @@ export default {
|
|||||||
const range = selection.getRangeAt(0);
|
const range = selection.getRangeAt(0);
|
||||||
let selectedNode = range.commonAncestorContainer;
|
let selectedNode = range.commonAncestorContainer;
|
||||||
|
|
||||||
// **向上查找包含 main-id 的最近 div**
|
|
||||||
let outerDiv = selectedNode;
|
let outerDiv = selectedNode;
|
||||||
while (outerDiv && outerDiv.tagName !== 'DIV') {
|
while (outerDiv && outerDiv.tagName !== 'DIV') {
|
||||||
outerDiv = outerDiv.parentNode;
|
outerDiv = outerDiv.parentNode;
|
||||||
@@ -2047,27 +2043,24 @@ export default {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// **缓存 main-id 和 type**
|
|
||||||
this.cachedMainId = outerDiv.getAttribute('main-id');
|
this.cachedMainId = outerDiv.getAttribute('main-id');
|
||||||
this.cachedType = outerDiv.getAttribute('type');
|
this.cachedType = outerDiv.getAttribute('type');
|
||||||
|
|
||||||
// **创建临时 div 存放选中的 HTML**
|
|
||||||
const tempDiv = document.createElement('div');
|
const tempDiv = document.createElement('div');
|
||||||
tempDiv.appendChild(range.cloneContents());
|
tempDiv.appendChild(range.cloneContents());
|
||||||
|
|
||||||
// **检查是否包含 <img> 标签**
|
|
||||||
if (tempDiv.querySelector('img')) {
|
if (tempDiv.querySelector('img')) {
|
||||||
this.clearCache();
|
this.clearCache();
|
||||||
this.$message.error(this.$t('commonTable.selectComment'));
|
this.$message.error(this.$t('commonTable.selectComment'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// **获取纯文本**
|
|
||||||
let selectedText = tempDiv.innerText.trim().replace(/\s+/g, ' ');
|
let selectedText = tempDiv.innerText.trim().replace(/\s+/g, ' ');
|
||||||
|
|
||||||
// **允许保留的 HTML 标签**
|
|
||||||
const allowedTags = ['sup', 'sub', 'strong', 'em', 'b', 'i', 'blue', 'tr', 'td'];
|
|
||||||
|
|
||||||
|
const allowedTags = ['sup', 'sub', 'strong', 'em', 'b', 'i', 'blue', 'tr', 'td'];
|
||||||
function preserveTags(node) {
|
function preserveTags(node) {
|
||||||
if (node.nodeType === 3) return node.nodeValue; // 文本节点
|
if (node.nodeType === 3) return node.nodeValue; // 文本节点
|
||||||
if (node.nodeType === 1 && allowedTags.includes(node.nodeName.toLowerCase())) {
|
if (node.nodeType === 1 && allowedTags.includes(node.nodeName.toLowerCase())) {
|
||||||
@@ -2078,19 +2071,19 @@ export default {
|
|||||||
|
|
||||||
let preservedContent = Array.from(tempDiv.childNodes).map(preserveTags).join('');
|
let preservedContent = Array.from(tempDiv.childNodes).map(preserveTags).join('');
|
||||||
|
|
||||||
// **检查是否已有批注**
|
|
||||||
if (tempDiv.querySelector('.positionRemarkIndex')) {
|
if (tempDiv.querySelector('.positionRemarkIndex')) {
|
||||||
this.clearCache();
|
this.clearCache();
|
||||||
this.$message.error(this.$t('commonTable.alreadyCommented'));
|
this.$message.error(this.$t('commonTable.alreadyCommented'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// **缓存选区内容**
|
|
||||||
this.cachedHtml = preservedContent;
|
this.cachedHtml = preservedContent;
|
||||||
this.cachedText = selectedText;
|
this.cachedText = selectedText;
|
||||||
},
|
},
|
||||||
|
|
||||||
// **点击“添加批注”按钮**
|
|
||||||
handleSelection() {
|
handleSelection() {
|
||||||
if (!this.cachedText) {
|
if (!this.cachedText) {
|
||||||
this.$message.error(this.$t('commonTable.selectComment'));
|
this.$message.error(this.$t('commonTable.selectComment'));
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
<span
|
<span
|
||||||
>Figure {{ index + 1 }}
|
>Figure {{ index + 1 }}
|
||||||
<span
|
<span
|
||||||
@click="openPreview(index, 'img')"
|
@click="openPreview(index, 'img',img)"
|
||||||
|
|
||||||
>
|
>
|
||||||
<!-- <el-tooltip class="item" effect="dark" :content="$t('commonTable.preview')" placement="top"> -->
|
<!-- <el-tooltip class="item" effect="dark" :content="$t('commonTable.preview')" placement="top"> -->
|
||||||
@@ -149,7 +149,7 @@
|
|||||||
<div class="title">
|
<div class="title">
|
||||||
<span
|
<span
|
||||||
>Table {{ index + 1 }}
|
>Table {{ index + 1 }}
|
||||||
<span @click="openPreview(index, 'table')">
|
<span @click="openPreview(index, 'table',table)">
|
||||||
<el-tooltip class="item" effect="dark" :content="$t('commonTable.preview')" placement="top">
|
<el-tooltip class="item" effect="dark" :content="$t('commonTable.preview')" placement="top">
|
||||||
<i class="el-icon-view" style="font-size: 16px"></i>
|
<i class="el-icon-view" style="font-size: 16px"></i>
|
||||||
</el-tooltip> </span
|
</el-tooltip> </span
|
||||||
@@ -252,11 +252,17 @@
|
|||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
<DynamicTable
|
||||||
|
ref="myTableModal"
|
||||||
|
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import { mediaUrl } from '@/common/js/commonJS.js'; // 引入通用逻辑
|
import { mediaUrl } from '@/common/js/commonJS.js'; // 引入通用逻辑
|
||||||
|
import DynamicTable from './DynamicTable.vue';
|
||||||
export default {
|
export default {
|
||||||
props: ['articleId', 'imgWidth', 'imgHeight', 'scale', 'isEdit', 'isShowEdit', 'urlList', 'content'],
|
props: ['articleId', 'imgWidth', 'imgHeight', 'scale', 'isEdit', 'isShowEdit', 'urlList', 'content'],
|
||||||
data() {
|
data() {
|
||||||
@@ -298,6 +304,9 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
components: {
|
||||||
|
DynamicTable
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
||||||
|
|
||||||
@@ -423,10 +432,10 @@ export default {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
openPreview(index, type) {
|
openPreview(index, type,data) {
|
||||||
this.$nextTick(() => {
|
console.log("🚀 ~ data:", data);
|
||||||
document.getElementById(type + '-modal-' + index).style.display = 'flex';
|
|
||||||
});
|
this.$refs.myTableModal.open(type,data,'no');
|
||||||
},
|
},
|
||||||
async getWordimgList() {
|
async getWordimgList() {
|
||||||
await this.$api
|
await this.$api
|
||||||
@@ -453,31 +462,7 @@ export default {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list.length > 0) {
|
|
||||||
list.forEach((img, index) => {
|
|
||||||
// var extension = img.image.split('.').pop().toLowerCase();
|
|
||||||
// if (extension === 'tif' || extension === 'jpg' || extension === 'jpeg' || extension === 'png') {
|
|
||||||
const modalContent = `<img src="${this.mediaUrl + img.image}" alt="Image ${index}" style="width:100%;background:#FFF;" >`;
|
|
||||||
|
|
||||||
|
|
||||||
this.$commonJS.createImageModal(index, modalContent, 'img');
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (extension === 'tif') {
|
|
||||||
// this.$nextTick(() => {
|
|
||||||
// this.$commonJS.renderTiffImage(
|
|
||||||
// this.mediaUrl + img.image,
|
|
||||||
// `tiff-canvas-modal-${index}`,
|
|
||||||
// function (url) {
|
|
||||||
// list[index].dataUrl = url;
|
|
||||||
// },
|
|
||||||
// index,
|
|
||||||
// true
|
|
||||||
// );
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.images = list;
|
this.images = list;
|
||||||
// this.$emit('loaded');
|
// this.$emit('loaded');
|
||||||
});
|
});
|
||||||
@@ -512,36 +497,7 @@ export default {
|
|||||||
: [];
|
: [];
|
||||||
}
|
}
|
||||||
await this.filterData('table');
|
await this.filterData('table');
|
||||||
if (this.tables.length > 0) {
|
|
||||||
this.tables.forEach((table, index) => {
|
|
||||||
var modalContent = `
|
|
||||||
<div class="wordTableHtml" style="background:#FFF;padding:20px">
|
|
||||||
<table
|
|
||||||
border="1"
|
|
||||||
style="
|
|
||||||
border-collapse: collapse;
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
table-layout: auto;"
|
|
||||||
>`;
|
|
||||||
table.table.forEach((row) => {
|
|
||||||
modalContent += `<tr>`;
|
|
||||||
row.forEach((cell) => {
|
|
||||||
modalContent += `
|
|
||||||
<td
|
|
||||||
colspan="${cell.colspan || 1}"
|
|
||||||
rowspan="${cell.rowspan || 1}"
|
|
||||||
style=""
|
|
||||||
>
|
|
||||||
<span>${cell.text}</span>
|
|
||||||
</td>`;
|
|
||||||
});
|
|
||||||
modalContent += `</tr>`;
|
|
||||||
});
|
|
||||||
modalContent += `</table></div>`;
|
|
||||||
this.$commonJS.createImageModal(index, modalContent, 'table', '');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,9 +71,9 @@ module.exports = {
|
|||||||
proxy: {
|
proxy: {
|
||||||
'/api': {
|
'/api': {
|
||||||
// target: 'http://zmzm.tougao.dev.com/',//晓玲本地
|
// target: 'http://zmzm.tougao.dev.com/',//晓玲本地
|
||||||
// target: 'https://submission.tmrjournals.com/',//正式
|
target: 'https://submission.tmrjournals.com/',//正式
|
||||||
// target: 'http://tougaotest.tmrjournals.com/public/index.php/',//测试环境
|
// target: 'http://tougaotest.tmrjournals.com/public/index.php/',//测试环境
|
||||||
target: 'http://mytest.tmrjournals.com/public/index.php/',//新正式环境
|
// target: 'http://mytest.tmrjournals.com/public/index.php/',//新正式环境
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
pathRewrite: {
|
pathRewrite: {
|
||||||
'^/api': ''
|
'^/api': ''
|
||||||
|
|||||||
Reference in New Issue
Block a user