H3+审稿人编委机构

This commit is contained in:
2026-02-04 14:57:54 +08:00
parent beee2ec54b
commit 9f108e7c81
18 changed files with 462 additions and 238 deletions

BIN
dist.zip

Binary file not shown.

BIN
node_modules.zip Normal file

Binary file not shown.

View File

@@ -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: '/', //正式
}); });

View File

@@ -241,25 +241,29 @@ export default {
str = capitalizeFirstLetter(str); str = capitalizeFirstLetter(str);
// 添加蓝色标签 // 添加蓝色标签
const regex = /\[(\d+(?:\d+)?(?:, ?\d+(?:\d+)?)*)\]/g; // 1. 修改正则,只匹配不在 <blue> 标签内的 [数字]
// 这里的思路是:匹配 [内容],但通过逻辑过滤掉已经被包裹的情况
const regex = /\[(\d+(?:\d+)?(?:, ?\d+(?:\d+)?)*)\]/g;
str = str.replace(/<blue>/g, '').replace(/<\/blue>/g, ''); // 先去掉所有的 <blue> 标签 // 注意:不要在最上面执行 str.replace(/<blue>/g, ''),否则之前的标记就全白做了
if (regex.test(str)) { str = str.replace(regex, function (match, content, offset, fullString) {
str = str.replace(regex, function (match) { // 【关键判断】:检查匹配位置的前后,是否已经存在 <blue> 和 </blue>
// 提取出方括号中的内容,并进行匹配 const prefix = fullString.substring(offset - 6, offset); // <blue> 是 6 位
const content = match.slice(1, match.length - 1); // 去掉方括号 const suffix = fullString.substring(offset + match.length, offset + match.length + 7); // </blue> 是 7 位
// 这个需要程序去判断所以需要告诉我满足哪些条件的标蓝
// 上标中 只有 * # & 纯数字 纯数字逗号 纯数字逗号和空格 ỻ 标蓝
// 判断是否符合条件,纯数字、逗号后有空格、连字符 if (prefix === '<blue>' && suffix === '</blue>') {
return match; // 如果已经有标签了,原样返回,不重复标记
}
// 判断逻辑:纯数字、逗号空格、连字符
if (/^\d+$/.test(content) || /, ?/.test(content) || //.test(content)) { if (/^\d+$/.test(content) || /, ?/.test(content) || //.test(content)) {
return `<blue>${match}</blue>`; // 如果符合条件则加上蓝色标签 return `<blue>${match}</blue>`;
}
return match; // 如果不符合条件,则保持原样
});
} }
return match;
});
@@ -907,9 +911,9 @@ export default {
}); });
// 2. 删除所有不需要的标签 (除 `strong`, `em`, `sub`, `sup`, `b`, `i` 外的所有标签) // 2. 删除所有不需要的标签 (除 `strong`, `em`, `sub`, `sup`, `b`, `i` 外的所有标签)
if (type == 'table') { if (type == 'table') {
inputHtml = inputHtml.replace(/<(?!\/?(strong|em|sub|sup|b|i|blue|wmath|img|myfigure|mytable))[^>]+>/g, ''); // 删除不需要的标签 inputHtml = inputHtml.replace(/<(?!\/?(strong|em|sub|sup|b|i|blue|wmath|img|myfigure|mytable|myh3))[^>]+>/g, ''); // 删除不需要的标签
} else { } else {
inputHtml = inputHtml.replace(/<(?!\/?(strong|em|sub|sup|b|i|blue|wmath|myfigure|mytable))[^>]+>/g, ''); // 删除不需要的标签 inputHtml = inputHtml.replace(/<(?!\/?(strong|em|sub|sup|b|i|blue|wmath|myfigure|mytable|myh3))[^>]+>/g, ''); // 删除不需要的标签
} }
@@ -963,14 +967,11 @@ export default {
return parsedData; return parsedData;
} },
,
async parseTableToArray(tableString, callback) { async parseTableToArray(tableString, callback) {
const parser = new DOMParser(); const parser = new DOMParser();
const doc = parser.parseFromString(tableString, 'text/html'); const doc = parser.parseFromString(tableString, 'text/html');
const rows = doc.querySelectorAll('table tr'); // 获取所有的行(<tr> const rows = doc.querySelectorAll('table tr'); // 获取所有的行(<tr>
@@ -993,6 +994,8 @@ export default {
); );
callback(result) callback(result)
// 返回处理后的数组 // 返回处理后的数组
}, },

View File

@@ -426,6 +426,7 @@ const en = {
jump: 'Locate', jump: 'Locate',
editAssociation: 'Edit Association', editAssociation: 'Edit Association',
UnbindAssociation: 'Unbind Association', UnbindAssociation: 'Unbind Association',
selectContent: 'Please select the content to operate first',
}, },
pendingPayment: { pendingPayment: {
title: 'Title', title: 'Title',

View File

@@ -412,6 +412,7 @@ const zh = {
jump: '定位', jump: '定位',
editAssociation: '编辑关联', editAssociation: '编辑关联',
UnbindAssociation: '取消关联', UnbindAssociation: '取消关联',
selectContent: '请先选择需要操作的内容',
}, },
pendingPayment: { pendingPayment: {
title: 'Title', title: 'Title',

View File

@@ -88,7 +88,6 @@
</div> </div>
</div> </div>
<div style="width: 100%; width: calc(100% - 260px); float: right; height: calc(100% - 0px); background-color: #e4e9ed"> <div style="width: 100%; width: calc(100% - 260px); float: right; height: calc(100% - 0px); background-color: #e4e9ed">
<common-word <common-word
:articleId="articleId" :articleId="articleId"
v-if="htmlContent" v-if="htmlContent"
@@ -369,6 +368,7 @@
<font style="color: #f56c6c; margin-right: 5px">*</font> <font style="color: #f56c6c; margin-right: 5px">*</font>
Content : Content :
</span> </span>
<common-content <common-content
type="content" type="content"
@openAddTable="openAddTable" @openAddTable="openAddTable"
@@ -595,12 +595,10 @@ export default {
} }
}, },
async created() { async created() {
localStorage.removeItem('scrollPosition'); localStorage.removeItem('scrollPosition');
this.isShowEditComment(); this.isShowEditComment();
this.getDate(); this.getDate();
this.getCommentList(); this.getCommentList();
}, },
mounted() { mounted() {
document.addEventListener('copy', (event) => { document.addEventListener('copy', (event) => {
@@ -613,10 +611,9 @@ export default {
console.log('用户复制了内容:', selection); console.log('用户复制了内容:', selection);
// 阻止默认行为(如果需要自定义复制逻辑的话) // 阻止默认行为(如果需要自定义复制逻辑的话)
// event.preventDefault(); // event.preventDefault();
}); });
}, },
async activated() { async activated() {
this.isShowEditComment(); this.isShowEditComment();
this.getDate(); this.getDate();
this.getCommentList(); this.getCommentList();
@@ -690,6 +687,7 @@ export default {
async getContent(type, content) { async getContent(type, content) {
if (type == 'content') { if (type == 'content') {
content = this.$commonJS.transformHtmlString(content); content = this.$commonJS.transformHtmlString(content);
var div = document.createElement('div'); var div = document.createElement('div');
div.innerHTML = content; // 将 HTML 字符串加载到 div 中 div.innerHTML = content; // 将 HTML 字符串加载到 div 中
// 替换所有 <strong> 为 <b> // 替换所有 <strong> 为 <b>
@@ -722,7 +720,7 @@ export default {
return false; return false;
} }
var list = this.$commonJS.cleanAndParseWordContent(content); var list = this.$commonJS.cleanAndParseWordContent(content);
console.log('list at line 569:', list);
this.saveContentList(list, this.currentId); this.saveContentList(list, this.currentId);
} else if (type == 'table') { } else if (type == 'table') {
@@ -771,6 +769,8 @@ export default {
}, },
async saveContent(content, am_id) { async saveContent(content, am_id) {
const loading = this.$loading({ const loading = this.$loading({
lock: true, lock: true,
text: 'Loading...', text: 'Loading...',
@@ -780,6 +780,9 @@ export default {
var that = this; var that = this;
var str = content.replace(/^<p>\s*(.*?)\s*<\/p>$/, '$1').trim(); var str = content.replace(/^<p>\s*(.*?)\s*<\/p>$/, '$1').trim();
if (str.replace(/<br\s*\/?>/gi, '').trim() === '') {
str = '';
}
str = await that.$commonJS.decodeHtml(str); str = await that.$commonJS.decodeHtml(str);
await that.$api await that.$api
@@ -816,6 +819,14 @@ export default {
spinner: 'el-icon-loading', spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)' background: 'rgba(0, 0, 0, 0.7)'
}); });
content = content.map((str) => {
// 逻辑:去掉所有换行符后,如果剩下的内容是空的
if (str.replace(/<br\s*\/?>/gi, '').trim() === '') {
return ''; // 变成真正的空字符串
}
return str; // 如果有文字,保留原样
});
await this.$api await this.$api
.post('api/Preaccept/addMoreRow', { .post('api/Preaccept/addMoreRow', {
article_id: this.articleId, article_id: this.articleId,
@@ -846,7 +857,6 @@ export default {
return rowIndex < head[0].rowspan; // 假设前两行是表头 return rowIndex < head[0].rowspan; // 假设前两行是表头
}, },
deleteComment(comment, index) { deleteComment(comment, index) {
console.log('comment at line 480:', comment);
if (this.isEditComment) { if (this.isEditComment) {
this.$confirm(this.$t('commonTable.removeAnnotations'), 'Prompt', { this.$confirm(this.$t('commonTable.removeAnnotations'), 'Prompt', {
confirmButtonText: 'Submit', confirmButtonText: 'Submit',
@@ -872,7 +882,7 @@ export default {
} }
}, },
saveLateX(data) { saveLateX(data) {
console.log('data at line 735:', data);
// 1. 从 data 中解构出 wrap (或者你命名的模式变量) // 1. 从 data 中解构出 wrap (或者你命名的模式变量)
const { editorId, wmathId, latex, wrap } = data; const { editorId, wmathId, latex, wrap } = data;
const newLatex = latex ? latex.trim() : ''; const newLatex = latex ? latex.trim() : '';
@@ -910,7 +920,7 @@ export default {
}, 10); }, 10);
} }
} }
}, },
async huifu(id) { async huifu(id) {
var that = this; var that = this;
await this.$confirm(this.$t('commonTable.reContent'), 'Prompt', { await this.$confirm(this.$t('commonTable.reContent'), 'Prompt', {
@@ -1094,16 +1104,13 @@ export default {
}); });
}, },
async changeSort(type, id) { async changeSort(type, id) {
var that = this; var that = this;
const index = this.Main_List.findIndex((item) => item.am_id == id); const index = this.Main_List.findIndex((item) => item.am_id == id);
if(type=='up'&&index==0){ if (type == 'up' && index == 0) {
return;
return
} }
if(type=='down'&&index==this.Main_List.length-1){ if (type == 'down' && index == this.Main_List.length - 1) {
return;
return
} }
const load = this.$loading({ const load = this.$loading({
lock: true, lock: true,
@@ -1131,7 +1138,7 @@ export default {
}); });
}, },
async addCommentSetting(content) { async addCommentSetting(content) {
console.log('content at line 602:', content);
await this.$api await this.$api
.post(this.urlList.addComment, { .post(this.urlList.addComment, {
am_id: content.am_id, am_id: content.am_id,
@@ -1154,7 +1161,7 @@ export default {
}); });
}, },
async addComment(content) { async addComment(content) {
console.log('content at line 603:', this.commentForm);
var str = content.replace(/^<p>(.*?)<\/p>$/, '$1') ? content.replace(/^<p>(.*?)<\/p>$/, '$1') : ''; var str = content.replace(/^<p>(.*?)<\/p>$/, '$1') ? content.replace(/^<p>(.*?)<\/p>$/, '$1') : '';
if (str == '') { if (str == '') {
this.$message({ this.$message({
@@ -1237,13 +1244,13 @@ export default {
this.getCommentList(); this.getCommentList();
}, },
editComment(comment, type) { editComment(comment, type) {
console.log('comment at line 813:', comment);
this.commentForm = { this.commentForm = {
...comment, ...comment,
type: type, type: type,
remark: type == 'user' ? comment.author_remark : comment.remark remark: type == 'user' ? comment.author_remark : comment.remark
}; };
console.log('this.commentForm at line 815:', this.commentForm);
this.commentVisible = true; this.commentVisible = true;
}, },
async onAddComment(data) { async onAddComment(data) {
@@ -1288,7 +1295,6 @@ export default {
break; break;
} }
console.log('data at line 739:', data);
await this.$api await this.$api
.post(url, { .post(url, {
am_id: data.mainId am_id: data.mainId
@@ -1330,21 +1336,19 @@ export default {
return; return;
} }
if (index !== -1 && resData) { if (index !== -1 && resData) {
var newData = Array.isArray(resData) ? resData : (resData ? [resData] : []); var newData = Array.isArray(resData) ? resData : resData ? [resData] : [];
const updatedItems= newData.map((item) => ({ const updatedItems = newData.map((item) => ({
...item, ...item,
checked: false, checked: false,
getnum: 0, getnum: 0
})); }));
if (type == 'addRow') { if (type == 'addRow') {
this.Main_List.splice(index + 1, 0, updatedItems[0]); this.Main_List.splice(index + 1, 0, updatedItems[0]);
} else if (type == 'addMoreRow') { } else if (type == 'addMoreRow') {
this.Main_List.splice(index + 1, 0, ...updatedItems); this.Main_List.splice(index + 1, 0, ...updatedItems);
}else if(type=='positioningImg'||type=='positioningTable'){ } else if (type == 'positioningImg' || type == 'positioningTable') {
this.Main_List.splice(index + 1, 0, ...updatedItems); this.Main_List.splice(index + 1, 0, ...updatedItems);
} } else {
else {
this.$set(this.Main_List, index, updatedItems[0]); this.$set(this.Main_List, index, updatedItems[0]);
} }
} else { } else {
@@ -1366,7 +1370,7 @@ export default {
}); });
// 处理文件上传并传递回调函数 // 处理文件上传并传递回调函数
this.$commonJS.handleFileUpload(event, function (tables) { this.$commonJS.handleFileUpload(event, function (tables) {
console.log('tables at line 1138:', tables);
if (tables.length == 0) { if (tables.length == 0) {
loading.close(); loading.close();
that.$message({ that.$message({
@@ -1614,8 +1618,7 @@ export default {
} }
}, },
updateChange(content, type) { updateChange(content, type) {
// console.log('content at line 1154:', content);
// console.log('content at line 976:', content);
var str = this.$commonJS.transformHtmlString(content); var str = this.$commonJS.transformHtmlString(content);
if (type == 'imgNote') { if (type == 'imgNote') {
this.picStyle1.note = str; this.picStyle1.note = str;
@@ -1685,28 +1688,29 @@ export default {
const draggedImage = JSON.parse(event.dataTransfer.getData('image')); const draggedImage = JSON.parse(event.dataTransfer.getData('image'));
const draggedImageIndex = JSON.parse(event.dataTransfer.getData('imageIndex')); const draggedImageIndex = JSON.parse(event.dataTransfer.getData('imageIndex'));
this.$nextTick(async () => { this.$nextTick(async () => {
await this.$api await this.$api
.post(this.urlList.setPositioningImage, { .post(this.urlList.setPositioningImage, {
am_id: dataId, am_id: dataId,
ami_id: draggedImage.ami_id ami_id: draggedImage.ami_id
}) })
.then(async (res) => { .then(async (res) => {
if (res.code == 0) {loading.close() if (res.code == 0) {
this.refreshCurrentContent('positioningImg',dataId, res.data); loading.close();
this.refreshCurrentContent('positioningImg', dataId, res.data);
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.commonWordHtmlTypeSetting.refresh('positioningImg', res.data); this.$refs.commonWordHtmlTypeSetting.refresh('positioningImg', res.data);
}); });
this.$forceUpdate(); this.$forceUpdate();
} else {loading.close() } else {
loading.close();
this.$message.error(res.msg); this.$message.error(res.msg);
} }
}) })
.catch((err) => {loading.close() .catch((err) => {
loading.close();
this.$message.error(err.msg); this.$message.error(err.msg);
}); });
}); });
} else { } else {
const draggedtable = JSON.parse(event.dataTransfer.getData('table')); const draggedtable = JSON.parse(event.dataTransfer.getData('table'));
@@ -1717,27 +1721,24 @@ export default {
amt_id: draggedtable.amt_id amt_id: draggedtable.amt_id
}) })
.then(async (res) => { .then(async (res) => {
if (res.code == 0) {loading.close() if (res.code == 0) {
this.refreshCurrentContent('positioningTable',dataId, res.data); loading.close();
this.refreshCurrentContent('positioningTable', dataId, res.data);
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.commonWordHtmlTypeSetting.refresh('positioningTable', res.data); this.$refs.commonWordHtmlTypeSetting.refresh('positioningTable', res.data);
}); });
this.$forceUpdate(); this.$forceUpdate();
} else { } else {
loading.close() loading.close();
this.$message.error(res.msg); this.$message.error(res.msg);
} }
}) })
.catch((err) => { .catch((err) => {
loading.close() loading.close();
this.$message.error(err.msg); this.$message.error(err.msg);
}); });
}); });
} }
}, },
getCommentList() { getCommentList() {
this.$api this.$api
@@ -1912,8 +1913,11 @@ export default {
loading.close(); loading.close();
this.$message.success('Successfully edit Figure!'); this.$message.success('Successfully edit Figure!');
this.pictVisible = false; this.pictVisible = false;
this.$refs.commonWordHtmlTypeSetting.refresh('editImg', res.data.image?{...res.data.image,has_selected:1}:res.data); this.$refs.commonWordHtmlTypeSetting.refresh(
this.refreshCurrentContent('editImg',res.data.am_id, res.data); 'editImg',
res.data.image ? { ...res.data.image, has_selected: 1 } : res.data
);
this.refreshCurrentContent('editImg', res.data.am_id, res.data);
this.$nextTick(() => { this.$nextTick(() => {
this.getCommentList(); this.getCommentList();
this.$forceUpdate(); this.$forceUpdate();
@@ -1942,7 +1946,6 @@ export default {
this.pictVisible = false; this.pictVisible = false;
this.$refs.commonWordHtmlTypeSetting.refresh('addImg', res.data); this.$refs.commonWordHtmlTypeSetting.refresh('addImg', res.data);
} else { } else {
loading.close(); loading.close();
this.$message.error(res.msg); this.$message.error(res.msg);
@@ -2026,8 +2029,11 @@ export default {
this.$message.success('Successfully edit Table!'); this.$message.success('Successfully edit Table!');
this.threeVisible = false; this.threeVisible = false;
setTimeout(() => { setTimeout(() => {
this.$refs.commonWordHtmlTypeSetting.refresh('editTable', res.data.table?{...res.data.table,has_selected:1}:res.data); this.$refs.commonWordHtmlTypeSetting.refresh(
this.refreshCurrentContent('editTable',res.data.am_id, res.data); 'editTable',
res.data.table ? { ...res.data.table, has_selected: 1 } : res.data
);
this.refreshCurrentContent('editTable', res.data.am_id, res.data);
this.getCommentList(); this.getCommentList();
}); });
} else { } else {
@@ -2571,9 +2577,8 @@ export default {
background-color: #0066990d; background-color: #0066990d;
/* display: block !important; */ /* display: block !important; */
} }
wmath[data-wrap="inline"] { wmath[data-wrap='inline'] {
display: inline-block !important; display: inline-block !important;
width: auto !important; width: auto !important;
} }
</style> </style>

View File

@@ -721,7 +721,7 @@ export default {
return false; return false;
} }
var list = this.$commonJS.cleanAndParseWordContent(content); var list = this.$commonJS.cleanAndParseWordContent(content);
console.log('list at line 569:', list);
this.saveContentList(list, this.currentId); this.saveContentList(list, this.currentId);
} else if (type == 'table') { } else if (type == 'table') {
@@ -1162,7 +1162,7 @@ export default {
break; break;
} }
console.log('data at line 739:', data);
await this.$api await this.$api
.post(url, { .post(url, {
am_id: data.mainId am_id: data.mainId

View File

@@ -1881,8 +1881,37 @@ export default {
.catch(() => {}); .catch(() => {});
}, },
handleClickFinal(data) { handleClickFinal(data) {
this.finalDecisionData = { ...data }; console.log("🚀 ~ handleClickFinal ~ data:", data);
const loading = this.$loading({
lock: true,
text: 'Loading',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)',
zIndex: 9999 // 设置一个足够高的层级
});
this.$api
.post('api/Finalreview/getById', {
record_id: data.id,
reviewer_id:data.reviewer_id,
})
.then((res) => {
if (res.status == 1) {
loading.close()
this.finalDecisionData = { ...res.data,reviewer_company : res.data.company,reviewer_email:res.data.email}
this.FinalDecisionVisible = true; this.FinalDecisionVisible = true;
} else {
loading.close()
this.$message.error(res.msg);
}
})
.catch((err) => {
loading.close()
console.log(err);
});
}, },
handleClickRemark() { handleClickRemark() {
this.expanded = !this.expanded; this.expanded = !this.expanded;

View File

@@ -2982,11 +2982,12 @@ export default {
// 获取文章信息 // 获取文章信息
this.$api this.$api
.post('api/Preaccept/getArticleMains', { .post('api/Preaccept/getArticleMains', {
p_article_id: this.p_article_id
article_id: this.detailMes.article_id
}) })
.then((res) => { .then((res) => {
if (res.code == 0) { if (res.code == 0) {
this.deMesYul.htmlList = res.data.mains; this.deMesYul.htmlList = res.data.list;
this.preArtVisible = true; this.preArtVisible = true;
} else { } else {
this.$message.error(res.msg); this.$message.error(res.msg);

View File

@@ -648,7 +648,7 @@ export default {
break; break;
} }
console.log('data at line 739:', data);
await this.$api await this.$api
.post(url, { .post(url, {
am_id: data.mainId am_id: data.mainId

View File

@@ -5,13 +5,25 @@
<el-row :gutter="24"> <el-row :gutter="24">
<el-col :span="24"> <el-col :span="24">
<div class="form-box" style="width: 100%"> <div class="form-box" style="width: 100%">
<el-form ref="articleform" :model="detailDate" label-width="200px"> <el-form ref="articleform" :model="detailDate" label-width="220px">
<!-- <el-form-item label="Article : "> <!-- <el-form-item label="Article : ">
<span>{{ detailDate.article }}</span> <span>{{ detailDate.article }}</span>
</el-form-item> --> </el-form-item> -->
<el-form-item label="Editorial Board Member : "> <el-form-item label="Editorial Board Member : ">
<span>{{ detailDate.reviewer }}</span> <span>{{ detailDate.reviewer }}</span>
</el-form-item> </el-form-item>
<el-form-item label="Editorial Board Member Email : ">
<span>{{ detailDate.article_final.reviewer_email }}</span>
</el-form-item>
<el-form-item label="Affiliation : " v-if="detailDate.article_final.reviewer_company">
<span
>
{{ detailDate.article_final.reviewer_company }}
</span>
</el-form-item>
<el-form-item label="Final decision time : "> <el-form-item label="Final decision time : ">
<span>{{ detailDate.ctime }}</span> <span>{{ detailDate.ctime }}</span>
</el-form-item> </el-form-item>

View File

@@ -1,6 +1,7 @@
<template> <template>
<div class="tinymce-container editor-container"> <div class="tinymce-container editor-container">
<textarea class="tinymce-textarea" :id="tinymceId"></textarea> <textarea class="tinymce-textarea" :id="tinymceId"></textarea>
</div> </div>
</template> </template>
@@ -69,6 +70,7 @@ export default {
data() { data() {
return { return {
uploadNotifications: {}, uploadNotifications: {},
content: '',
totalUploadImages: 0, totalUploadImages: 0,
uploadedImageCount: 0, uploadedImageCount: 0,
uploadNotificationInstance: null, // 全局通知实例 uploadNotificationInstance: null, // 全局通知实例
@@ -132,6 +134,8 @@ export default {
// console.log('val at line 208:', val); // console.log('val at line 208:', val);
if (!this.hasChange && this.hasInit) { if (!this.hasChange && this.hasInit) {
this.$nextTick(() => { this.$nextTick(() => {
window.tinymce.get(this.tinymceId).setContent(val); window.tinymce.get(this.tinymceId).setContent(val);
// window.renderMathJax(); // 主动触发 MathJax 渲染 // window.renderMathJax(); // 主动触发 MathJax 渲染
}); });
@@ -409,11 +413,38 @@ uploadSingleImage(blob, index) {
return new Blob([u8arr], { type: mime }); return new Blob([u8arr], { type: mime });
}, },
initTinymce() { initTinymce() {
if (this.value.includes('wordTableHtml')) {
const parser = new DOMParser();
const doc = parser.parseFromString(this.value, 'text/html');
// 1. 只针对单元格 (td, th) 进行处理
const cells = doc.querySelectorAll('td, th');
cells.forEach(cell => {
let html = cell.innerHTML;
// 执行你原来的清理逻辑,但仅限单元格内部
html = html.replace(/<([a-zA-Z1-6]+)\b[^>]*><\/\1>/g, '') // 清理空标签
.replace(/\s+(?=<)|(?<=>)\s+/g, '&nbsp;'); // 补全空格
cell.innerHTML = html;
});
// 2. 将处理后的完整 HTML 重新赋回,此时 table 外部的换行符保持原样(纯文本)
this.content = doc.body.innerHTML;
} else {
// 非表格模式,维持你原有的全局逻辑
this.content = this.value
.replace(/<([a-zA-Z1-6]+)\b[^>]*><\/\1>/g, '')
.replace(/\s+(?=<)|(?<=>)\s+/g, '&nbsp;');
}
let globalImgCounter = 0; // 放在 init 闭包内,确保计数器持续增长 let globalImgCounter = 0; // 放在 init 闭包内,确保计数器持续增长
let currentPasteBase64Images = []; let currentPasteBase64Images = [];
var _this = this; var _this = this;
window.tinymce.init({ window.tinymce.init({
..._this.tinymceOtherInit, ..._this.tinymceOtherInit,
trim_span_elements: false, // 禁止修剪内联标签周围的空格
extended_valid_elements: 'blue[*]', extended_valid_elements: 'blue[*]',
custom_elements: 'blue', custom_elements: 'blue',
valid_children: '+blue[#text|i|em|b|strong|span],+body[blue],+p[blue]', valid_children: '+blue[#text|i|em|b|strong|span],+body[blue],+p[blue]',
@@ -453,6 +484,9 @@ myfigure *,
color: inherit !important; color: inherit !important;
text-shadow: inherit !important; text-shadow: inherit !important;
background: transparent !important; /* 防止内部标签背景干扰 */ background: transparent !important; /* 防止内部标签背景干扰 */
}
myh3 ,myh3 *{
font-weight: bold !important;
} }
@keyframes blueGlow { @keyframes blueGlow {
@@ -572,6 +606,8 @@ myfigure *,
}); });
ed.on('paste', async (event) => { ed.on('paste', async (event) => {
const rtf = event.clipboardData.getData('text/rtf'); const rtf = event.clipboardData.getData('text/rtf');
if (rtf && rtf.includes('\\pict')) { if (rtf && rtf.includes('\\pict')) {
@@ -604,7 +640,7 @@ myfigure *,
await _this.uploadSingleImage(imageBlob, i); await _this.uploadSingleImage(imageBlob, i);
_this.updateUploadProgressNotification(i, 'success'); _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'); // 上传失败
} }
@@ -644,7 +680,9 @@ myfigure *,
const editorBody = ed.getBody(); const editorBody = ed.getBody();
const observer = new MutationObserver(() => { const observer = new MutationObserver(() => {
const currentContent = ed.getContent(); const currentContent = ed.getContent({ format: 'raw' });
if (_this.isAutomaticUpdate) { if (_this.isAutomaticUpdate) {
_this.$emit('updateChange', currentContent); _this.$emit('updateChange', currentContent);
// _this.$emit('updateChange', _this.$commonJS.decodeHtml(currentContent)); // _this.$emit('updateChange', _this.$commonJS.decodeHtml(currentContent));
@@ -674,7 +712,7 @@ myfigure *,
text: _this.$t('commonTable.exportWord'), text: _this.$t('commonTable.exportWord'),
onAction: () => { onAction: () => {
// 插入自定义表格到编辑器中 // 插入自定义表格到编辑器中
let content = ed.getContent(); // 获取内容 let content = ed.getContent({ format: 'raw' }); // 获取内容
content = content.replace(/<strong>/g, '<b>').replace(/<\/strong>/g, '</b>'); content = content.replace(/<strong>/g, '<b>').replace(/<\/strong>/g, '</b>');
content = content.replace(/<em>/g, '<i>').replace(/<\/em>/g, '</i>'); content = content.replace(/<em>/g, '<i>').replace(/<\/em>/g, '</i>');
const container = document.createElement('div'); const container = document.createElement('div');
@@ -688,7 +726,7 @@ myfigure *,
text: _this.$t('commonTable.exportImg'), text: _this.$t('commonTable.exportImg'),
onAction: () => { onAction: () => {
// 插入自定义表格到编辑器中 // 插入自定义表格到编辑器中
_this.export('image', ed.getContent()); _this.export('image', ed.getContent({ format: 'raw' }));
} }
}); });
ed.ui.registry.addContextToolbar('spacer', { ed.ui.registry.addContextToolbar('spacer', {
@@ -705,6 +743,7 @@ myfigure *,
}); });
e.content = e.content.replace(/<strong>/g, '<b>').replace(/<\/strong>/g, '</b>'); e.content = e.content.replace(/<strong>/g, '<b>').replace(/<\/strong>/g, '</b>');
e.content = e.content.replace(/<em>/g, '<i>').replace(/<\/em>/g, '</i>'); e.content = e.content.replace(/<em>/g, '<i>').replace(/<\/em>/g, '</i>');
}); });
ed.on('GetContent', function (e) { ed.on('GetContent', function (e) {
e.content = e.content.replace(/<b>/g, '<strong>').replace(/<\/b>/g, '</strong>'); e.content = e.content.replace(/<b>/g, '<strong>').replace(/<\/b>/g, '</strong>');
@@ -818,22 +857,30 @@ console.log('Processed content:', content); // 输出处理后的内容
vm.onClear(); vm.onClear();
}, },
init_instance_callback: (editor) => { init_instance_callback: (editor) => {
if (_this.value) {
editor.setContent('<p>' + _this.value + '</p>');
if (_this.content) {
let finalContent = _this.content;
if (finalContent.includes('wordTableHtml')) {
editor.setContent(finalContent);
} else {
editor.setContent('<p>' + finalContent + '</p>');
}
setTimeout(() => { setTimeout(() => {
window.renderMathJax(_this.tinymceId); // 初始化时渲染 MathJax if (window.renderMathJax) {
}, 10); window.renderMathJax(_this.tinymceId);
} }
}, 10);
}
_this.hasInit = true; _this.hasInit = true;
editor.on('NodeChange Change KeyUp SetContent', () => { editor.on('NodeChange Change KeyUp SetContent', () => {
this.hasChange = true; this.hasChange = true;
this.$emit('input', editor.getContent()); this.$emit('input', editor.getContent({ format: 'raw' }));
// console.log('at line 518:', '改变');
// setTimeout(() => {
// window.renderMathJax(); // 初始化时渲染 MathJax
// }, 50);
}); });
} }
}); });
@@ -932,11 +979,14 @@ console.log('Processed content:', content); // 输出处理后的内容
}, },
//获取内容 //获取内容
async getContent(type) { async getContent(type) {
var content = window.tinymce.get(this.tinymceId).getContent(); var content = window.tinymce.get(this.tinymceId).getContent({ format: 'raw' });
content = content.replace(/<span[^>]*>/g, '').replace(/<\/span>/g, ''); // 去除span标签 content = content.replace(/<span[^>]*>/g, '').replace(/<\/span>/g, ''); // 去除span标签
content = content.replace(/<strong>/g, '<b>').replace(/<\/strong>/g, '</b>'); content = content.replace(/<strong>/g, '<b>').replace(/<\/strong>/g, '</b>');
content = content.replace(/<em>/g, '<i>').replace(/<\/em>/g, '</i>'); content = content.replace(/<em>/g, '<i>').replace(/<\/em>/g, '</i>');
content = content.replace(/&nbsp;/g, ' '); // 将所有 &nbsp; 替换为空格 content = content.replace(/&nbsp;/g, ' '); // 将所有 &nbsp; 替换为空格
this.$emit('getContent', type, content); this.$emit('getContent', type, content);
}, },

View File

@@ -20,20 +20,27 @@
<el-row :gutter="10"> <el-row :gutter="10">
<el-col :span="24"> <el-col :span="24">
<div class="form-box" style="width: 100%"> <div class="form-box" style="width: 100%">
<el-form ref="articleform" :model="detailDate" label-width="140px"> <el-form ref="articleform" :model="detailDate" label-width="160px">
<el-form-item label="Title"> <el-form-item label="Title : ">
<span style="font-weight: bold;color: #333;">{{ detailDate.article }}</span> <span style="font-weight: bold;color: #333;">{{ detailDate.article }}</span>
</el-form-item> </el-form-item>
<el-form-item label="Reviewer"> <el-form-item label="Reviewer : ">
<span>{{ detailDate.reviewer }}</span> <span>{{ detailDate.reviewer }}</span>
</el-form-item> </el-form-item>
<el-form-item label="Reviewer email"> <el-form-item label="Reviewer email : ">
<span>{{ detailDate.reviewer_email }}</span> <span>{{ detailDate.reviewer_email }}</span>
</el-form-item> </el-form-item>
<el-form-item label="CreateTime"> <el-form-item label="Affiliation : ">
<p>
{{ detailDate.reviewer_company }}
</p>
</el-form-item>
<el-form-item label="CreateTime : ">
<span>{{ formatDate(detailDate.ctime) }}</span> <span>{{ formatDate(detailDate.ctime) }}</span>
</el-form-item> </el-form-item>
<el-form-item label="Disclose name or anonymous" label-width="200px" v-if="reviewerDetail.state != 0"> <el-form-item label="Disclose name or anonymous : " label-width="210px" v-if="reviewerDetail.state != 0">
<span v-if="detailDate.is_anonymous == 0">Disclose name</span> <span v-if="detailDate.is_anonymous == 0">Disclose name</span>
<span v-if="detailDate.is_anonymous == 1">Remain anonymous</span> <span v-if="detailDate.is_anonymous == 1">Remain anonymous</span>
</el-form-item> </el-form-item>
@@ -144,6 +151,7 @@ export default {
article: '', article: '',
reviewer: '', reviewer: '',
reviewer_email: '', reviewer_email: '',
reviewer_company:'',
articlefile: '', articlefile: '',
articlezip: '', articlezip: '',
ctime: '', ctime: '',
@@ -331,6 +339,7 @@ export default {
this.detailDate.article = res.data.article.title; this.detailDate.article = res.data.article.title;
this.detailDate.reviewer = res.data.article_reviewer.realname; this.detailDate.reviewer = res.data.article_reviewer.realname;
this.detailDate.reviewer_email = res.data.article_reviewer.email; this.detailDate.reviewer_email = res.data.article_reviewer.email;
this.detailDate.reviewer_company = res.data.article_reviewer.company;
this.detailDate.ctime = res.data.article_reviewer.ctime; this.detailDate.ctime = res.data.article_reviewer.ctime;
this.detailDate.is_anonymous = res.data.article_reviewer.is_anonymous; this.detailDate.is_anonymous = res.data.article_reviewer.is_anonymous;

View File

@@ -58,7 +58,7 @@ export default {
if (this.lineStyle.table) { if (this.lineStyle.table) {
this.tableData = [...this.lineStyle.table]; this.tableData = [...this.lineStyle.table];
var modalContent = ` var modalContent = `
<div class="wordTableHtml" > <div class="wordTableHtml">
<table <table
border="1" border="1"
style=" style="
@@ -84,6 +84,10 @@ export default {
modalContent += `</table></div>`; modalContent += `</table></div>`;
this.updatedHtml = modalContent; this.updatedHtml = modalContent;
this.$nextTick(() => {
this.$refs.tinymceChild1.initTinymce()
})
} }
} else { } else {
this.updatedHtml = ''; this.updatedHtml = '';
@@ -106,10 +110,15 @@ export default {
this.$refs.tinymceChild1.getContent(type); this.$refs.tinymceChild1.getContent(type);
}, },
getContent(type, content) { getContent(type, content) {
if (content) { if (content) {
const container = document.createElement('div'); const container = document.createElement('div');
container.innerHTML = content; container.innerHTML = content;
this.$commonJS.parseTableToArray(content, (table) => { this.$commonJS.parseTableToArray(content, (table) => {
this.$emit('getContent', type, { html_data: content, table: table }); this.$emit('getContent', type, { html_data: content, table: table });
}); });
} else { } else {

View File

@@ -1,7 +1,7 @@
<template> <template>
<div <div
@click="handleGlobalClick" @click="handleGlobalClick"
class="tinymce-container editor-container word-container" class="tinymce-container editor-container word-container" :class="{'preview-container': isPreview}"
:style="!isPreview ? 'padding:10px 20px 40px 24px;' : 'padding:0px;'" :style="!isPreview ? 'padding:10px 20px 40px 24px;' : 'padding:0px;'"
ref="scrollDiv" ref="scrollDiv"
> >
@@ -181,24 +181,23 @@
</span> </span>
<div <div
:class=" :class="
!isPreview item.is_h1
? item.is_h1
? 'isTitleH1 pMainH1' ? 'isTitleH1 pMainH1'
: item.is_h2 : item.is_h2
? 'isTitleH2' ? 'isTitleH2'
: item.is_h3 : item.is_h3
? 'isTitleH3' ? 'isTitleH3'
: '' : ''
: item.is_h1
? 'Ptitle'
: ''
" "
style="line-height: 24px" style="line-height: 24px"
> >
<template v-if="!isPreview"> <template v-if="!isPreview">
<span class="Htitle Htitle1" v-if="item.is_h1 == 1">H1</span> <span class="Htitle Htitle1" v-if="item.is_h1 == 1">H1</span>
<span class="Htitle Htitle2" v-else-if="item.is_h2 == 1">H2</span> <span class="Htitle Htitle2" v-else-if="item.is_h2 == 1">H2</span>
<span class="Htitle Htitle3" v-else-if="item.is_h3 == 1">H3</span></template <span class="Htitle Htitle3" v-else-if="item.is_h3 == 1">H3</span>
</template
> >
<div :class="currentId == item.am_id ? 'glowing-border' : ''" style="position: relative"> <div :class="currentId == item.am_id ? 'glowing-border' : ''" style="position: relative">
@@ -967,7 +966,7 @@
<div v-if="currentData.type == 0" class="h-group"> <div v-if="currentData.type == 0" class="h-group">
<span :class="['h-item', { active: currentData.is_h1 == 1 }]" @click="changeTitle(currentData.is_h1 ? 0 : 1)">H1</span> <span :class="['h-item', { active: currentData.is_h1 == 1 }]" @click="changeTitle(currentData.is_h1 ? 0 : 1)">H1</span>
<span :class="['h-item', { active: currentData.is_h2 == 1 }]" @click="changeTitle(currentData.is_h2 ? 0 : 2)">H2</span> <span :class="['h-item', { active: currentData.is_h2 == 1 }]" @click="changeTitle(currentData.is_h2 ? 0 : 2)">H2</span>
<span :class="['h-item', { active: currentData.is_h3 == 1 }]" @click="changeTitle(currentData.is_h3 ? 0 : 3)">H3</span> <span :class="['h-item', { active: currentData.is_h3 == 1||currentTag == 'h3' }]" @click="changeTitle3(currentData.is_h3||currentTag == 'h3' ? 0 : 3)">H3</span>
</div> </div>
<div class="row-divider" v-if="currentData.type == 0"></div> <div class="row-divider" v-if="currentData.type == 0"></div>
<div v-if="isEditComment && currentData.type == 0" class="menu-item ai-feat" @click="menuAction('proofreading')"> <div v-if="isEditComment && currentData.type == 0" class="menu-item ai-feat" @click="menuAction('proofreading')">
@@ -978,19 +977,19 @@
</div> </div>
<div class="row-divider" v-if="isEditComment && currentData.type == 0"></div> <div class="row-divider" v-if="isEditComment && currentData.type == 0"></div>
<div class="menu-item menu-link" v-if="currentData.type == 0 && !currentTag" @click="menuAction('link')"> <div class="menu-item menu-link" v-if="currentData.type == 0 && !['figure', 'table'].includes(currentTag)" @click="menuAction('link')">
<i class="el-icon-link"></i><span>{{ $t('commonTable.Association') }}</span> <i class="el-icon-link"></i><span>{{ $t('commonTable.Association') }}</span>
</div> </div>
<div class="menu-item menu-link menu-jump" v-if="currentData.type == 0 && currentTag" @click="menuAction('jump')"> <div class="menu-item menu-link menu-jump" v-if="currentData.type == 0 && ['figure', 'table'].includes(currentTag)" @click="menuAction('jump')">
<i class="el-icon-location-outline"></i><span style="margin-right: 10px">{{ $t('commonTable.jump') }}</span> <i class="el-icon-location-outline"></i><span style="margin-right: 10px">{{ $t('commonTable.jump') }}</span>
</div> </div>
<div class="menu-item menu-link" v-if="currentData.type == 0 && currentTag" @click="menuAction('editLink')"> <div class="menu-item menu-link" v-if="currentData.type == 0 && ['figure', 'table'].includes(currentTag)" @click="menuAction('editLink')">
<i class="el-icon-link"></i><span>{{ $t('commonTable.editAssociation') }}</span> <i class="el-icon-link"></i><span>{{ $t('commonTable.editAssociation') }}</span>
</div> </div>
<div <div
class="menu-item menu-link" class="menu-item menu-link"
style="color: #f56c6c" style="color: #f56c6c"
v-if="currentData.type == 0 && currentTag" v-if="currentData.type == 0 && ['figure', 'table'].includes(currentTag)"
@click="menuAction('unbindLink')" @click="menuAction('unbindLink')"
> >
<i class="el-icon-link"></i><span>{{ $t('commonTable.UnbindAssociation') }}</span> <i class="el-icon-link"></i><span>{{ $t('commonTable.UnbindAssociation') }}</span>
@@ -1275,6 +1274,7 @@ export default {
this.$refs.scrollDiv.addEventListener('scroll', this.divOnScroll, { passive: true }); this.$refs.scrollDiv.addEventListener('scroll', this.divOnScroll, { passive: true });
document.addEventListener('selectionchange', () => { document.addEventListener('selectionchange', () => {
if(this.isPreview)return;
const selection = window.getSelection(); const selection = window.getSelection();
if (selection.rangeCount === 0) return; if (selection.rangeCount === 0) return;
@@ -1475,6 +1475,7 @@ export default {
this.$forceUpdate(); this.$forceUpdate();
}, },
handleGlobalClick(e) { handleGlobalClick(e) {
if(this.isPreview)return;
// 如果点在气泡内,不关 // 如果点在气泡内,不关
if (e.target.closest('.bubble-container')) return; if (e.target.closest('.bubble-container')) return;
@@ -1787,7 +1788,6 @@ export default {
const el = Array.isArray(r) ? r[0] : r; const el = Array.isArray(r) ? r[0] : r;
if (!sc || !el) return; if (!sc || !el) return;
const top = this.topInScroll(el, sc) - 80; const top = this.topInScroll(el, sc) - 80;
console.log('top at line 1491:', top);
sc.scrollTo({ top, behavior: 'smooth' }); sc.scrollTo({ top, behavior: 'smooth' });
}, },
@@ -1817,7 +1817,6 @@ export default {
return doc.body.innerHTML; return doc.body.innerHTML;
}, },
async editProofreadingContent(data) { async editProofreadingContent(data) {
console.log('data at line 1276:', data);
data.revised_content = await this.convertSpacesToNbsp(data.revised_content); data.revised_content = await this.convertSpacesToNbsp(data.revised_content);
this.proofreadingContent = { this.proofreadingContent = {
@@ -1898,7 +1897,7 @@ export default {
container.scrollTo({ top: Math.max(0, top), behavior: 'smooth' }); container.scrollTo({ top: Math.max(0, top), behavior: 'smooth' });
}, },
handleClick(tab, event) { handleClick(tab, event) {
console.log(tab, event);
if (this.isEditComment) { if (this.isEditComment) {
if (tab.index == 0) { if (tab.index == 0) {
this.activeName == 'proofreading'; this.activeName == 'proofreading';
@@ -2001,7 +2000,7 @@ export default {
}, },
changeSort(type) { changeSort(type) {
console.log('type at line 782:', type);
if (this.currentId) { if (this.currentId) {
this.$emit('changeSort', type, this.currentId); this.$emit('changeSort', type, this.currentId);
} }
@@ -2130,6 +2129,7 @@ export default {
// 3. 核心调用逻辑 // 3. 核心调用逻辑
async handleOpenLink() { async handleOpenLink() {
// 1. 校验是否选中内容 // 1. 校验是否选中内容
const selectedText = this.currentSelection.label || ''; const selectedText = this.currentSelection.label || '';
if (!selectedText) { if (!selectedText) {
@@ -2234,12 +2234,81 @@ export default {
} }
}, },
changeTitle3(value) {
if (this.currentData.type !== 0) return;
if (value == 3) {
const label = this.currentSelection.label || '';
if (!label) {
this.$message.error(this.$t('commonTable.selectContent'));
return;
}
let originalContent = this.currentSelection.content || '';
// 1. 【清洗阶段】:先彻底清除 content 里的所有 myh3 痕迹(修复孤儿标签)
let workingContent = originalContent.replace(/<\/?myh3[^>]*>/gi, '');
// 2. 【归一化匹配】:处理转义字符冲突 (&lt; vs <)
// 我们不生成复杂的穿透正则,而是将内容和标签都转为纯文本比对
const decodeHTML = (str) => {
const txt = document.createElement("textarea");
txt.innerHTML = str;
return txt.value;
};
const plainLabel = decodeHTML(label);
const plainContent = decodeHTML(workingContent);
// 寻找文字在纯文本中的起始位置
const startIndex = plainContent.indexOf(plainLabel);
if (startIndex !== -1) {
/**
* 3. 【精准爆破】:
* 因为 HTML 标签和实体字符会改变字符串长度,我们不能直接按索引切。
* 我们用一个简单的正则,只处理 label 里的特殊符号和中间可能存在的标签。
*/
const safeLabelRegexStr = plainLabel
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
.replace(/\s+/g, '[\\s\\S]*?'); // 将空格替换为模糊匹配,允许中间夹杂任何内容(标签)
const finalRegex = new RegExp(safeLabelRegexStr, 'g');
// 执行替换
const newContent = workingContent.replace(finalRegex, (match) => {
// 如果已经有标签包着,直接包在最外面
return `<myh3>${match}</myh3>`;
});
this.$emit('saveContent', newContent, this.currentSelection.mainId);
} else {
console.warn('匹配失败,尝试直接字符串替换');
// 最后的兜底:如果正则还是不行,直接强行替换 label
const fallbackContent = workingContent.split(label).join(`<myh3>${label}</myh3>`);
this.$emit('saveContent', fallbackContent, this.currentSelection.mainId);
}
} else {
// 删除逻辑:简单直接
const rootItem = this.wordList.find((item) => item.am_id == this.currentTagData.main_id);
if (rootItem) {
const finalContent = rootItem.content.replace(/<\/?myh3[^>]*>/gi, '');
this.$emit('saveContent', finalContent, this.currentTagData.main_id);
}
}
},
changeTitle(value) { changeTitle(value) {
if (this.currentData.type == 0) { if (this.currentData.type == 0) {
this.$emit('onEditTitle', { this.$emit('onEditTitle', {
mainId: this.currentId, mainId: this.currentId,
value: value value: value
}); });
} }
}, },
clearHighlight1() { clearHighlight1() {
@@ -2319,7 +2388,7 @@ export default {
revokeProofreading(data) { revokeProofreading(data) {
// this.$emit('revokeProofreading', data); // this.$emit('revokeProofreading', data);
var content = this.wordList.find((e) => e.am_id == data.am_id).content; var content = this.wordList.find((e) => e.am_id == data.am_id).content;
console.log('content at line 1890:', content);
this.$api this.$api
.post('api/Proofread/change', { .post('api/Proofread/change', {
am_id: data.am_id, am_id: data.am_id,
@@ -2344,10 +2413,10 @@ export default {
}); });
}, },
executeProofreading(data) { executeProofreading(data) {
console.log('data at line 1416:', data);
// this.$emit('executeProofreading', data); // this.$emit('executeProofreading', data);
var content = this.wordList.find((e) => e.am_id == data.am_id).content; var content = this.wordList.find((e) => e.am_id == data.am_id).content;
console.log('content at line 1890:', content);
this.$api this.$api
.post('api/Proofread/change', { .post('api/Proofread/change', {
am_id: data.am_id, am_id: data.am_id,
@@ -2370,7 +2439,7 @@ export default {
}); });
}, },
refreshCurrentData(am_id, newData, type) { refreshCurrentData(am_id, newData, type) {
console.log('newData at line 2106:', newData);
var refreshData = { ...this.wordList.find((e) => e.am_id == am_id) }; var refreshData = { ...this.wordList.find((e) => e.am_id == am_id) };
var refreshDataIndex = this.wordList.findIndex((e) => e.am_id == am_id); var refreshDataIndex = this.wordList.findIndex((e) => e.am_id == am_id);
if (refreshData.type == 0) { if (refreshData.type == 0) {
@@ -2391,10 +2460,10 @@ export default {
} }
//图片的注解 表格标题和注解 还有表格要单独处理 //图片的注解 表格标题和注解 还有表格要单独处理
console.log('refreshData at line 1293:', refreshData);
}, },
deleteProofreading(data, index) { deleteProofreading(data, index) {
console.log('data at line 1599:', data);
// this.$emit('deleteProofreading', data); // this.$emit('deleteProofreading', data);
if (this.isEditComment) { if (this.isEditComment) {
this.$confirm(this.$t('commonTable.removeProofread'), 'Prompt', { this.$confirm(this.$t('commonTable.removeProofread'), 'Prompt', {
@@ -2470,7 +2539,7 @@ export default {
this.$emit('onDrop', e, targetId.slice(6)); // 阻止默认的行为 this.$emit('onDrop', e, targetId.slice(6)); // 阻止默认的行为
}, },
clearEditor(editorId) { clearEditor(editorId) {
console.log('editorId at line 462:', editorId);
for (const key in this.editors) { for (const key in this.editors) {
if (this.editors[key]) { if (this.editors[key]) {
// 确保销毁所有编辑器实例 // 确保销毁所有编辑器实例
@@ -2732,20 +2801,11 @@ export default {
if (event && event.stopPropagation) { if (event && event.stopPropagation) {
event.stopPropagation(); event.stopPropagation();
} }
if (!this.isPreview) {
this.clearHighlight();
this.selectedIds = [];
this.menuType = type;
this.currentTag = ''; this.currentTag = '';
this.currentTagData = null; // 必须重置,防止带入旧数据 this.currentTagData = null; // 必须重置,防止带入旧数据
this.$set(this, 'currentId', id); const clickedTag = event.target.closest('myfigure, mytable, myh3');
this.currentIndex = index;
this.currentData = data;
const clickedTag = event.target.closest('myfigure, mytable');
if (clickedTag) { if (clickedTag) {
this.currentTag = clickedTag; this.currentTag = clickedTag.tagName.toLowerCase().replace('my', '');
this.currentTagData = { this.currentTagData = {
link_id: clickedTag.getAttribute('data-id'), link_id: clickedTag.getAttribute('data-id'),
link_type: clickedTag.tagName.toLowerCase().replace('my', ''), link_type: clickedTag.tagName.toLowerCase().replace('my', ''),
@@ -2753,7 +2813,20 @@ export default {
fullHtml: clickedTag.outerHTML, fullHtml: clickedTag.outerHTML,
main_id: id main_id: id
}; };
console.log('6666666666666666',this.currentTagData);
} }
if (!this.isPreview) {
this.clearHighlight();
this.selectedIds = [];
this.menuType = type;
this.$set(this, 'currentId', id);
this.currentIndex = index;
this.currentData = data;
this.updateBubblePosition(event); this.updateBubblePosition(event);
this.isMenuVisible = true; this.isMenuVisible = true;
@@ -2761,6 +2834,11 @@ export default {
await this.getProofreadingList([id]); // 建议 await 异步操作 await this.getProofreadingList([id]); // 建议 await 异步操作
this.getPList(id); this.getPList(id);
} }
}else{
if (clickedTag) {
this.handleClickJump();
}
} }
setTimeout(() => { setTimeout(() => {
this.isInternalAction = false; this.isInternalAction = false;
@@ -2786,12 +2864,12 @@ export default {
this.$emit('editComment', data, type); this.$emit('editComment', data, type);
}, },
getCommentRemark(data) { getCommentRemark(data) {
console.log('data at line 426:', data);
const items = this.comments[data.am_id]; const items = this.comments[data.am_id];
// 如果找到了对应的数据项 // 如果找到了对应的数据项
if (items) { if (items) {
console.log(items);
return items; return items;
} else { } else {
} }
@@ -2816,7 +2894,7 @@ export default {
return formattedDate; return formattedDate;
}, },
async goToListComment(data, fn) { async goToListComment(data, fn) {
console.log('data at line 993:', data);
await this.goToComment(data.am_id, fn); await this.goToComment(data.am_id, fn);
}, },
divOnScroll() { divOnScroll() {
@@ -3359,11 +3437,10 @@ export default {
changeTable() { changeTable() {
// 获取所有表格 // 获取所有表格
const tables = window.tinymce.get(this.tinymceId).getBody().querySelectorAll('table'); const tables = window.tinymce.get(this.tinymceId).getBody().querySelectorAll('table');
console.log('tables at line 110:', tables);
// 遍历并设置样式 // 遍历并设置样式
tables.forEach((table) => { tables.forEach((table) => {
console.log('table at line 360:', table);
const editor = window.tinymce.get(this.tinymceId); const editor = window.tinymce.get(this.tinymceId);
editor.dom.setStyles(table, { editor.dom.setStyles(table, {
width: this.typesettingType == 1 ? '17.18cm' : '25.88cm' width: this.typesettingType == 1 ? '17.18cm' : '25.88cm'
@@ -3405,11 +3482,11 @@ export default {
this.selectedComment = null; this.selectedComment = null;
}, },
replacePlaceholderImage(ami_id, realImgSrc) { replacePlaceholderImage(ami_id, realImgSrc) {
console.log('realImgSrc at line 638:', ami_id, realImgSrc);
const iframeDocument = window.tinymce.get(this.tinymceId).getDoc(); const iframeDocument = window.tinymce.get(this.tinymceId).getDoc();
console.log('iframeDocument at line 639:', iframeDocument);
const placeholderImg = iframeDocument.querySelector(`img[data-img-id="${ami_id}"]`); const placeholderImg = iframeDocument.querySelector(`img[data-img-id="${ami_id}"]`);
console.log('placeholderImg at line 640:', placeholderImg);
if (placeholderImg) { if (placeholderImg) {
placeholderImg.src = realImgSrc; // 替换图片 URL placeholderImg.src = realImgSrc; // 替换图片 URL
@@ -3443,7 +3520,7 @@ export default {
//获取内容 //获取内容
getContent1(type, content) { getContent1(type, content) {
console.log('content at line 2986:', content);
content = this.$commonJS.transformHtmlString(content); content = this.$commonJS.transformHtmlString(content);
var div = document.createElement('div'); var div = document.createElement('div');
@@ -3465,7 +3542,7 @@ export default {
// 获取最终修改后的 HTML // 获取最终修改后的 HTML
content = div.innerHTML; content = div.innerHTML;
console.log('content at line 3007:', content);
this.$api this.$api
.post('api/Proofread/modify', { .post('api/Proofread/modify', {
am_id: this.proofreadingContent.am_id, am_id: this.proofreadingContent.am_id,
@@ -4318,7 +4395,12 @@ wmath {
text-shadow: inherit !important; text-shadow: inherit !important;
background: transparent !important; /* 防止内部标签背景干扰 */ background: transparent !important; /* 防止内部标签背景干扰 */
} }
::v-deep myh3 {
font-weight: bold !important;
}
::v-deep myh3 *{
font-weight: bold !important;
}
@keyframes blueGlow { @keyframes blueGlow {
0%, 0%,
100% { 100% {
@@ -4347,4 +4429,11 @@ wmath {
display: inline-block !important; display: inline-block !important;
width: auto !important; width: auto !important;
} }
.preview-container{
::v-deep myfigure,
::v-deep mytable {
text-shadow: none !important
}
}
</style> </style>

View File

@@ -154,8 +154,10 @@
class="status ok" class="status ok"
:class="scope.row.refer_type == 'journal' ? getJournalDateno(scope.row.dateno, 'status') : ''" :class="scope.row.refer_type == 'journal' ? getJournalDateno(scope.row.dateno, 'status') : ''"
v-if=" v-if="
(scope.row.refer_type == 'journal' && scope.row.doilink != ''&&scope.row.cs==1) || (
(scope.row.refer_type == 'book' && scope.row.isbn != ''&&scope.row.cs==1) (scope.row.refer_type == 'journal' && scope.row.doilink != '' && scope.row.cs == 1) ||
(scope.row.refer_type == 'book' && scope.row.isbn != '' && scope.row.cs == 1)
) && scope.row.retract == 0
" "
> >
<i class="el-icon-circle-check"></i> <i class="el-icon-circle-check"></i>
@@ -171,7 +173,7 @@
<!-- journal 形式 --> <!-- journal 形式 -->
<div style="text-align: left" v-if="scope.row.refer_type == 'journal'" class="reference-item"> <div style="text-align: left" v-if="scope.row.refer_type == 'journal'" class="reference-item">
<p> <p>
{{ scope.row.author }}&nbsp;{{ scope.row.title }}. &nbsp;<em>{{ scope.row.joura }}</em {{ scope.row.author }}&nbsp;<span v-html="formatTitle(scope.row.title)"></span>. &nbsp;<em>{{ scope.row.joura }}</em
>.&nbsp;<span :class="getJournalDateno(scope.row.dateno, 'title')">{{ scope.row.dateno }}</span >.&nbsp;<span :class="getJournalDateno(scope.row.dateno, 'title')">{{ scope.row.dateno }}</span
>.<br /> >.<br />
</p> </p>
@@ -179,12 +181,13 @@
</div> </div>
<!-- book 形式 --> <!-- book 形式 -->
<div style="text-align: left" v-if="scope.row.refer_type == 'book'" class="reference-item"> <div style="text-align: left" v-if="scope.row.refer_type == 'book'" class="reference-item">
<p>{{ scope.row.author }}&nbsp;{{ scope.row.title }}.&nbsp;{{ scope.row.dateno }}.&nbsp;<br /></p> <p>{{ scope.row.author }}&nbsp;<span v-html="formatTitle(scope.row.title)"></span>.&nbsp;{{ scope.row.dateno }}.&nbsp;<br /></p>
<a class="doiLink" :href="scope.row.isbn" target="_blank">{{ scope.row.isbn }}</a> <a class="doiLink" :href="scope.row.isbn" target="_blank">{{ scope.row.isbn }}</a>
</div> </div>
<!-- other 形式 --> <!-- other 形式 -->
<p class="wrongLine reference-item" style="text-align: left" v-if="scope.row.refer_type == 'other'"> <p class="wrongLine reference-item" style="text-align: left" v-if="scope.row.refer_type == 'other'">
{{ scope.row.refer_frag }} <span v-html="formatTitle(scope.row.refer_frag)"></span>
</p> </p>
</template> </template>
</el-table-column> </el-table-column>
@@ -569,6 +572,18 @@ export default {
} }
}, },
methods: { methods: {
formatTitle(title) {
if (!title) return '';
// 使用正则匹配,'gi' 表示全局匹配且不区分大小写
// \b 确保是完整单词匹配,防止误伤含有这些字母的其他单词
const reg = /\b(Retracted|Retraction)\b/gi;
return title.replace(reg, (match) => {
return `<span style="color: red; font-weight: bold;">${match}</span>`;
});
}
,
getJournalDateno(dateno, type) { getJournalDateno(dateno, type) {
if (dateno && typeof dateno === 'string') { if (dateno && typeof dateno === 'string') {
const hasInvalidColon = !dateno.includes(':') || (dateno.includes(':') && dateno.split(':').pop().trim() === ''); const hasInvalidColon = !dateno.includes(':') || (dateno.includes(':') && dateno.split(':').pop().trim() === '');

View File

@@ -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': ''