Compare commits
3 Commits
beee2ec54b
...
Editorial-
| Author | SHA1 | Date | |
|---|---|---|---|
| d05ffdf9c6 | |||
| 5edf128cfb | |||
| 9f108e7c81 |
BIN
node_modules.zip
Normal file
BIN
node_modules.zip
Normal file
Binary file not shown.
@@ -241,24 +241,28 @@ export default {
|
||||
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) {
|
||||
// 提取出方括号中的内容,并进行匹配
|
||||
const content = match.slice(1, match.length - 1); // 去掉方括号
|
||||
// 这个需要程序去判断所以需要告诉我满足哪些条件的标蓝
|
||||
// 上标中 只有 * # & 纯数字 纯数字逗号 纯数字逗号和空格 ỻ 标蓝
|
||||
str = str.replace(regex, function (match, content, offset, fullString) {
|
||||
// 【关键判断】:检查匹配位置的前后,是否已经存在 <blue> 和 </blue>
|
||||
const prefix = fullString.substring(offset - 6, offset); // <blue> 是 6 位
|
||||
const suffix = fullString.substring(offset + match.length, offset + match.length + 7); // </blue> 是 7 位
|
||||
|
||||
// 判断是否符合条件,纯数字、逗号后有空格、连字符
|
||||
if (/^\d+$/.test(content) || /, ?/.test(content) || /–/.test(content)) {
|
||||
return `<blue>${match}</blue>`; // 如果符合条件则加上蓝色标签
|
||||
}
|
||||
return match; // 如果不符合条件,则保持原样
|
||||
});
|
||||
}
|
||||
if (prefix === '<blue>' && suffix === '</blue>') {
|
||||
return match; // 如果已经有标签了,原样返回,不重复标记
|
||||
}
|
||||
|
||||
// 判断逻辑:纯数字、逗号空格、连字符
|
||||
if (/^\d+$/.test(content) || /, ?/.test(content) || /–/.test(content)) {
|
||||
return `<blue>${match}</blue>`;
|
||||
}
|
||||
|
||||
return match;
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -907,9 +911,9 @@ export default {
|
||||
});
|
||||
// 2. 删除所有不需要的标签 (除 `strong`, `em`, `sub`, `sup`, `b`, `i` 外的所有标签)
|
||||
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 {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
,
|
||||
},
|
||||
|
||||
|
||||
async parseTableToArray(tableString, callback) {
|
||||
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(tableString, 'text/html');
|
||||
const rows = doc.querySelectorAll('table tr'); // 获取所有的行(<tr>)
|
||||
@@ -993,6 +994,8 @@ export default {
|
||||
);
|
||||
|
||||
callback(result)
|
||||
|
||||
|
||||
// 返回处理后的数组
|
||||
|
||||
},
|
||||
|
||||
@@ -13,9 +13,7 @@ const baseUrl = '/';
|
||||
|
||||
//测试环境
|
||||
|
||||
// const mediaUrl = 'http://tougaotest.tmrjournals.com/public/';
|
||||
// // const mediaUrl = 'http://zmzm.tougao.dev.com/public/';
|
||||
// const baseUrl = '/api';
|
||||
|
||||
|
||||
////新正式环境
|
||||
// const mediaUrl = 'http://mytest.tmrjournals.com/public/';
|
||||
|
||||
@@ -290,12 +290,13 @@ const en = {
|
||||
state1: 'With editor',
|
||||
state2: 'Under review',
|
||||
state3: 'Reject',
|
||||
stateDraft: 'Awaiting Submission',
|
||||
state4: 'Revision',
|
||||
state5: 'Accept',
|
||||
state6: 'Pre-accept',
|
||||
state8: 'Final Decision',
|
||||
act1: 'Dealing',
|
||||
act2: 'Finished'
|
||||
act2: 'Finished',
|
||||
},
|
||||
evaluationsis: {
|
||||
EmploymentRate: 'Employment Rate',
|
||||
@@ -426,6 +427,7 @@ const en = {
|
||||
jump: 'Locate',
|
||||
editAssociation: 'Edit Association',
|
||||
UnbindAssociation: 'Unbind Association',
|
||||
selectContent: 'Please select the content to operate first',
|
||||
},
|
||||
pendingPayment: {
|
||||
title: 'Title',
|
||||
|
||||
@@ -276,6 +276,7 @@ const zh = {
|
||||
state1: '已受理',
|
||||
state2: '送审中',
|
||||
state3: '拒稿',
|
||||
stateDraft: '待提交',
|
||||
state4: '退修',
|
||||
state5: '接收',
|
||||
state6: '预接收',
|
||||
@@ -412,6 +413,7 @@ const zh = {
|
||||
jump: '定位',
|
||||
editAssociation: '编辑关联',
|
||||
UnbindAssociation: '取消关联',
|
||||
selectContent: '请先选择需要操作的内容',
|
||||
},
|
||||
pendingPayment: {
|
||||
title: 'Title',
|
||||
|
||||
@@ -88,7 +88,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<div style="width: 100%; width: calc(100% - 260px); float: right; height: calc(100% - 0px); background-color: #e4e9ed">
|
||||
|
||||
<common-word
|
||||
:articleId="articleId"
|
||||
v-if="htmlContent"
|
||||
@@ -369,6 +368,7 @@
|
||||
<font style="color: #f56c6c; margin-right: 5px">*</font>
|
||||
Content :
|
||||
</span>
|
||||
|
||||
<common-content
|
||||
type="content"
|
||||
@openAddTable="openAddTable"
|
||||
@@ -595,28 +595,25 @@ export default {
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
|
||||
localStorage.removeItem('scrollPosition');
|
||||
this.isShowEditComment();
|
||||
this.getDate();
|
||||
this.getCommentList();
|
||||
|
||||
},
|
||||
mounted() {
|
||||
document.addEventListener('copy', (event) => {
|
||||
// 获取用户选中的文本
|
||||
const selection = document.getSelection().toString();
|
||||
|
||||
// 你可以修改剪贴板内容
|
||||
// event.clipboardData.setData('text/plain', selection + '\n---来自我的系统---');
|
||||
|
||||
console.log('用户复制了内容:', selection);
|
||||
// 阻止默认行为(如果需要自定义复制逻辑的话)
|
||||
// event.preventDefault();
|
||||
});
|
||||
// 获取用户选中的文本
|
||||
const selection = document.getSelection().toString();
|
||||
|
||||
// 你可以修改剪贴板内容
|
||||
// event.clipboardData.setData('text/plain', selection + '\n---来自我的系统---');
|
||||
|
||||
console.log('用户复制了内容:', selection);
|
||||
// 阻止默认行为(如果需要自定义复制逻辑的话)
|
||||
// event.preventDefault();
|
||||
});
|
||||
},
|
||||
async activated() {
|
||||
|
||||
this.isShowEditComment();
|
||||
this.getDate();
|
||||
this.getCommentList();
|
||||
@@ -624,9 +621,9 @@ export default {
|
||||
|
||||
methods: {
|
||||
openAddTable(content) {
|
||||
this.editVisible = false;
|
||||
this.threeVisible = true;
|
||||
this.$forceUpdate();
|
||||
this.editVisible = false;
|
||||
this.threeVisible = true;
|
||||
this.$forceUpdate();
|
||||
},
|
||||
async copyArray(data) {
|
||||
try {
|
||||
@@ -690,6 +687,7 @@ export default {
|
||||
async getContent(type, content) {
|
||||
if (type == 'content') {
|
||||
content = this.$commonJS.transformHtmlString(content);
|
||||
|
||||
var div = document.createElement('div');
|
||||
div.innerHTML = content; // 将 HTML 字符串加载到 div 中
|
||||
// 替换所有 <strong> 为 <b>
|
||||
@@ -709,7 +707,7 @@ export default {
|
||||
|
||||
// 获取最终修改后的 HTML
|
||||
content = div.innerHTML;
|
||||
|
||||
|
||||
this.saveContent(content, this.currentContent.am_id);
|
||||
} else if (type == 'addcontent') {
|
||||
var hasTable = /<table[\s\S]*?>[\s\S]*?<\/table>/i.test(content);
|
||||
@@ -722,7 +720,7 @@ export default {
|
||||
return false;
|
||||
}
|
||||
var list = this.$commonJS.cleanAndParseWordContent(content);
|
||||
console.log('list at line 569:', list);
|
||||
|
||||
|
||||
this.saveContentList(list, this.currentId);
|
||||
} else if (type == 'table') {
|
||||
@@ -771,6 +769,8 @@ export default {
|
||||
},
|
||||
|
||||
async saveContent(content, am_id) {
|
||||
|
||||
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
text: 'Loading...',
|
||||
@@ -780,8 +780,10 @@ export default {
|
||||
var that = this;
|
||||
var str = content.replace(/^<p>\s*(.*?)\s*<\/p>$/, '$1').trim();
|
||||
|
||||
str = str.replace(/<br\s*\/?>/gi, '');
|
||||
|
||||
str = await that.$commonJS.decodeHtml(str);
|
||||
|
||||
|
||||
await that.$api
|
||||
.post(that.urlList.editContent, {
|
||||
am_id: am_id,
|
||||
@@ -816,6 +818,14 @@ export default {
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
});
|
||||
|
||||
content = content.map((str) => {
|
||||
// 逻辑:去掉所有换行符后,如果剩下的内容是空的
|
||||
if (str.replace(/<br\s*\/?>/gi, '').trim() === '') {
|
||||
return ''; // 变成真正的空字符串
|
||||
}
|
||||
return str; // 如果有文字,保留原样
|
||||
});
|
||||
await this.$api
|
||||
.post('api/Preaccept/addMoreRow', {
|
||||
article_id: this.articleId,
|
||||
@@ -846,7 +856,6 @@ export default {
|
||||
return rowIndex < head[0].rowspan; // 假设前两行是表头
|
||||
},
|
||||
deleteComment(comment, index) {
|
||||
console.log('comment at line 480:', comment);
|
||||
if (this.isEditComment) {
|
||||
this.$confirm(this.$t('commonTable.removeAnnotations'), 'Prompt', {
|
||||
confirmButtonText: 'Submit',
|
||||
@@ -872,45 +881,45 @@ export default {
|
||||
}
|
||||
},
|
||||
saveLateX(data) {
|
||||
console.log('data at line 735:', data);
|
||||
// 1. 从 data 中解构出 wrap (或者你命名的模式变量)
|
||||
const { editorId, wmathId, latex, wrap } = data;
|
||||
const newLatex = latex ? latex.trim() : '';
|
||||
|
||||
if (!editorId || !wmathId) return;
|
||||
|
||||
const targetEditor = tinymce.get(editorId);
|
||||
if (!targetEditor) return;
|
||||
|
||||
// 2. 找到编辑器中现有的 wmath 标签
|
||||
const targetWmath = targetEditor.dom.select(`wmath[data-id="${wmathId}"]`, targetEditor.getBody())[0];
|
||||
|
||||
if (targetWmath) {
|
||||
if (!newLatex) {
|
||||
// ❌ 删除公式
|
||||
targetEditor.dom.remove(targetWmath);
|
||||
} else {
|
||||
// ✅ 更新公式
|
||||
// 保持属性纯净:同时更新 latex 内容和 wrap 属性
|
||||
targetWmath.setAttribute('data-latex', newLatex);
|
||||
|
||||
// 如果 data 中传了 wrap 模式就更新它,否则可以保留原样或设为默认
|
||||
if (wrap) {
|
||||
targetWmath.setAttribute('data-wrap', wrap);
|
||||
}
|
||||
|
||||
// 内部只放纯 latex 文本,不包裹 $ 符号
|
||||
targetWmath.innerHTML = newLatex;
|
||||
|
||||
// 1. 从 data 中解构出 wrap (或者你命名的模式变量)
|
||||
const { editorId, wmathId, latex, wrap } = data;
|
||||
const newLatex = latex ? latex.trim() : '';
|
||||
|
||||
setTimeout(() => {
|
||||
if (typeof renderMathJax === 'function') {
|
||||
// 重新渲染该编辑器内的数学公式
|
||||
renderMathJax(editorId);
|
||||
if (!editorId || !wmathId) return;
|
||||
|
||||
const targetEditor = tinymce.get(editorId);
|
||||
if (!targetEditor) return;
|
||||
|
||||
// 2. 找到编辑器中现有的 wmath 标签
|
||||
const targetWmath = targetEditor.dom.select(`wmath[data-id="${wmathId}"]`, targetEditor.getBody())[0];
|
||||
|
||||
if (targetWmath) {
|
||||
if (!newLatex) {
|
||||
// ❌ 删除公式
|
||||
targetEditor.dom.remove(targetWmath);
|
||||
} else {
|
||||
// ✅ 更新公式
|
||||
// 保持属性纯净:同时更新 latex 内容和 wrap 属性
|
||||
targetWmath.setAttribute('data-latex', newLatex);
|
||||
|
||||
// 如果 data 中传了 wrap 模式就更新它,否则可以保留原样或设为默认
|
||||
if (wrap) {
|
||||
targetWmath.setAttribute('data-wrap', wrap);
|
||||
}
|
||||
|
||||
// 内部只放纯 latex 文本,不包裹 $ 符号
|
||||
targetWmath.innerHTML = newLatex;
|
||||
|
||||
setTimeout(() => {
|
||||
if (typeof renderMathJax === 'function') {
|
||||
// 重新渲染该编辑器内的数学公式
|
||||
renderMathJax(editorId);
|
||||
}
|
||||
}, 10);
|
||||
}
|
||||
}, 10);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
async huifu(id) {
|
||||
var that = this;
|
||||
await this.$confirm(this.$t('commonTable.reContent'), 'Prompt', {
|
||||
@@ -987,7 +996,7 @@ export default {
|
||||
var that = this;
|
||||
var dataInfo = this.Main_List.find((item) => item.am_id == dataId);
|
||||
var dataIndex = this.Main_List.indexOf(dataInfo);
|
||||
|
||||
|
||||
var type = '';
|
||||
if (dataInfo.type == 1) {
|
||||
type = 'img';
|
||||
@@ -1094,18 +1103,15 @@ export default {
|
||||
});
|
||||
},
|
||||
async changeSort(type, id) {
|
||||
|
||||
var that = this;
|
||||
const index = this.Main_List.findIndex((item) => item.am_id == id);
|
||||
if(type=='up'&&index==0){
|
||||
|
||||
return
|
||||
}
|
||||
if(type=='down'&&index==this.Main_List.length-1){
|
||||
|
||||
return
|
||||
}
|
||||
const load = this.$loading({
|
||||
if (type == 'up' && index == 0) {
|
||||
return;
|
||||
}
|
||||
if (type == 'down' && index == this.Main_List.length - 1) {
|
||||
return;
|
||||
}
|
||||
const load = this.$loading({
|
||||
lock: true,
|
||||
text: 'Loading...',
|
||||
spinner: 'el-icon-loading',
|
||||
@@ -1131,7 +1137,7 @@ export default {
|
||||
});
|
||||
},
|
||||
async addCommentSetting(content) {
|
||||
console.log('content at line 602:', content);
|
||||
|
||||
await this.$api
|
||||
.post(this.urlList.addComment, {
|
||||
am_id: content.am_id,
|
||||
@@ -1154,8 +1160,10 @@ export default {
|
||||
});
|
||||
},
|
||||
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= this.$commonJS.transformHtmlString(content)
|
||||
str=str.replace(/<br\s*\/?>/gi, '');
|
||||
console.log("🚀 ~ addComment ~ content:", str);
|
||||
if (str == '') {
|
||||
this.$message({
|
||||
type: 'warning',
|
||||
@@ -1237,13 +1245,13 @@ export default {
|
||||
this.getCommentList();
|
||||
},
|
||||
editComment(comment, type) {
|
||||
console.log('comment at line 813:', comment);
|
||||
|
||||
this.commentForm = {
|
||||
...comment,
|
||||
type: type,
|
||||
remark: type == 'user' ? comment.author_remark : comment.remark
|
||||
};
|
||||
console.log('this.commentForm at line 815:', this.commentForm);
|
||||
|
||||
this.commentVisible = true;
|
||||
},
|
||||
async onAddComment(data) {
|
||||
@@ -1288,7 +1296,6 @@ export default {
|
||||
break;
|
||||
}
|
||||
|
||||
console.log('data at line 739:', data);
|
||||
await this.$api
|
||||
.post(url, {
|
||||
am_id: data.mainId
|
||||
@@ -1330,21 +1337,19 @@ export default {
|
||||
return;
|
||||
}
|
||||
if (index !== -1 && resData) {
|
||||
var newData = Array.isArray(resData) ? resData : (resData ? [resData] : []);
|
||||
const updatedItems= newData.map((item) => ({
|
||||
...item,
|
||||
checked: false,
|
||||
getnum: 0,
|
||||
|
||||
}));
|
||||
var newData = Array.isArray(resData) ? resData : resData ? [resData] : [];
|
||||
const updatedItems = newData.map((item) => ({
|
||||
...item,
|
||||
checked: false,
|
||||
getnum: 0
|
||||
}));
|
||||
if (type == 'addRow') {
|
||||
this.Main_List.splice(index + 1, 0, updatedItems[0]);
|
||||
} else if (type == 'addMoreRow') {
|
||||
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);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.$set(this.Main_List, index, updatedItems[0]);
|
||||
}
|
||||
} else {
|
||||
@@ -1366,7 +1371,7 @@ export default {
|
||||
});
|
||||
// 处理文件上传并传递回调函数
|
||||
this.$commonJS.handleFileUpload(event, function (tables) {
|
||||
console.log('tables at line 1138:', tables);
|
||||
|
||||
if (tables.length == 0) {
|
||||
loading.close();
|
||||
that.$message({
|
||||
@@ -1614,8 +1619,7 @@ export default {
|
||||
}
|
||||
},
|
||||
updateChange(content, type) {
|
||||
// console.log('content at line 1154:', content);
|
||||
// console.log('content at line 976:', content);
|
||||
|
||||
var str = this.$commonJS.transformHtmlString(content);
|
||||
if (type == 'imgNote') {
|
||||
this.picStyle1.note = str;
|
||||
@@ -1685,28 +1689,29 @@ export default {
|
||||
const draggedImage = JSON.parse(event.dataTransfer.getData('image'));
|
||||
const draggedImageIndex = JSON.parse(event.dataTransfer.getData('imageIndex'));
|
||||
this.$nextTick(async () => {
|
||||
|
||||
await this.$api
|
||||
.post(this.urlList.setPositioningImage, {
|
||||
am_id: dataId,
|
||||
ami_id: draggedImage.ami_id
|
||||
})
|
||||
.then(async (res) => {
|
||||
if (res.code == 0) {loading.close()
|
||||
this.refreshCurrentContent('positioningImg',dataId, res.data);
|
||||
if (res.code == 0) {
|
||||
loading.close();
|
||||
this.refreshCurrentContent('positioningImg', dataId, res.data);
|
||||
this.$nextTick(() => {
|
||||
this.$refs.commonWordHtmlTypeSetting.refresh('positioningImg', res.data);
|
||||
});
|
||||
this.$forceUpdate();
|
||||
} else {loading.close()
|
||||
} else {
|
||||
loading.close();
|
||||
this.$message.error(res.msg);
|
||||
}
|
||||
})
|
||||
.catch((err) => {loading.close()
|
||||
.catch((err) => {
|
||||
loading.close();
|
||||
this.$message.error(err.msg);
|
||||
});
|
||||
});
|
||||
|
||||
} else {
|
||||
const draggedtable = JSON.parse(event.dataTransfer.getData('table'));
|
||||
|
||||
@@ -1717,27 +1722,24 @@ export default {
|
||||
amt_id: draggedtable.amt_id
|
||||
})
|
||||
.then(async (res) => {
|
||||
if (res.code == 0) {loading.close()
|
||||
this.refreshCurrentContent('positioningTable',dataId, res.data);
|
||||
if (res.code == 0) {
|
||||
loading.close();
|
||||
this.refreshCurrentContent('positioningTable', dataId, res.data);
|
||||
this.$nextTick(() => {
|
||||
this.$refs.commonWordHtmlTypeSetting.refresh('positioningTable', res.data);
|
||||
});
|
||||
this.$forceUpdate();
|
||||
} else {
|
||||
loading.close()
|
||||
loading.close();
|
||||
this.$message.error(res.msg);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
loading.close()
|
||||
loading.close();
|
||||
this.$message.error(err.msg);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
getCommentList() {
|
||||
this.$api
|
||||
@@ -1883,6 +1885,9 @@ export default {
|
||||
// 确定保存图片
|
||||
async savePic() {
|
||||
var str = this.picStyle1.note ? await this.$commonJS.decodeHtml(this.picStyle1.note) : '';
|
||||
|
||||
|
||||
|
||||
var titleStr = this.picStyle1.title ? await this.$commonJS.decodeHtml(this.picStyle1.title) : '';
|
||||
|
||||
if (!this.picStyle.picUrl) {
|
||||
@@ -1893,6 +1898,8 @@ export default {
|
||||
this.$message.error('Please enter a title');
|
||||
return;
|
||||
}
|
||||
str = str.replace(/<br\s*\/?>/gi, '');
|
||||
titleStr = titleStr.replace(/<br\s*\/?>/gi, '');
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
text: 'Loading...',
|
||||
@@ -1912,8 +1919,11 @@ export default {
|
||||
loading.close();
|
||||
this.$message.success('Successfully edit Figure!');
|
||||
this.pictVisible = false;
|
||||
this.$refs.commonWordHtmlTypeSetting.refresh('editImg', res.data.image?{...res.data.image,has_selected:1}:res.data);
|
||||
this.refreshCurrentContent('editImg',res.data.am_id, res.data);
|
||||
this.$refs.commonWordHtmlTypeSetting.refresh(
|
||||
'editImg',
|
||||
res.data.image ? { ...res.data.image, has_selected: 1 } : res.data
|
||||
);
|
||||
this.refreshCurrentContent('editImg', res.data.am_id, res.data);
|
||||
this.$nextTick(() => {
|
||||
this.getCommentList();
|
||||
this.$forceUpdate();
|
||||
@@ -1942,7 +1952,6 @@ export default {
|
||||
this.pictVisible = false;
|
||||
|
||||
this.$refs.commonWordHtmlTypeSetting.refresh('addImg', res.data);
|
||||
|
||||
} else {
|
||||
loading.close();
|
||||
this.$message.error(res.msg);
|
||||
@@ -1966,28 +1975,42 @@ export default {
|
||||
},
|
||||
async saveTable(content) {
|
||||
const cleanTableData = (tableList) => {
|
||||
if (tableList.length == 0) {
|
||||
return [];
|
||||
} else {
|
||||
// 假设第一行是表头,保存表头
|
||||
const header = tableList[0];
|
||||
if (tableList.length == 0) {
|
||||
return [];
|
||||
} else {
|
||||
// 定义清理函数:去掉所有 br 标签和 TinyMCE 占位符
|
||||
const cleanText = (text) => {
|
||||
if (!text) return "";
|
||||
return text.replace(/<br\s*\/?>/gi, '').trim();
|
||||
};
|
||||
|
||||
// 从第二行开始,移除与表头相同的行
|
||||
const cleanedTable = tableList.filter((row, index) => {
|
||||
// 如果是第一行,则保留
|
||||
if (index === 0) return true;
|
||||
// 1. 获取处理后的干净表头
|
||||
const header = tableList[0].map(cell => ({
|
||||
...cell,
|
||||
text: cleanText(cell.text)
|
||||
}));
|
||||
|
||||
// 比较当前行的每个单元格与表头是否相同
|
||||
const isHeaderRow = row.every((cell, cellIndex) => {
|
||||
return cell.text === header[cellIndex].text;
|
||||
});
|
||||
// 2. 过滤逻辑
|
||||
const cleanedTable = tableList.map((row) => {
|
||||
// 首先:把每一行里的每个 cell.text 里的 <br> 都去掉
|
||||
return row.map(cell => ({
|
||||
...cell,
|
||||
text: cleanText(cell.text)
|
||||
}));
|
||||
}).filter((row, index) => {
|
||||
if (index === 0) return true;
|
||||
|
||||
return !isHeaderRow; // 只保留与表头不同的行
|
||||
});
|
||||
// 3. 此时比较的就是没有 <br> 的文本了
|
||||
const isHeaderRow = row.every((cell, cellIndex) => {
|
||||
return cell.text === header[cellIndex].text;
|
||||
});
|
||||
|
||||
return cleanedTable;
|
||||
}
|
||||
};
|
||||
return !isHeaderRow;
|
||||
});
|
||||
|
||||
return cleanedTable;
|
||||
}
|
||||
};
|
||||
var cleanedTableList = content.table ? content.table : [];
|
||||
|
||||
cleanedTableList = cleanTableData(content.table);
|
||||
@@ -2011,11 +2034,15 @@ export default {
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
});
|
||||
strNote = strNote.replace(/<br\s*\/?>/gi, '');
|
||||
strTitle = strTitle.replace(/<br\s*\/?>/gi, '');
|
||||
var tableStr=JSON.stringify(cleanedTableList)
|
||||
|
||||
if (this.lineStyle.visiTitle == 'Edit Table') {
|
||||
this.$api
|
||||
.post(this.urlList.editTable, {
|
||||
amt_id: this.lineStyle.amt_id,
|
||||
table_data: JSON.stringify(cleanedTableList),
|
||||
table_data: tableStr,
|
||||
html_data: content.html_data,
|
||||
note: strNote,
|
||||
title: strTitle
|
||||
@@ -2026,8 +2053,11 @@ export default {
|
||||
this.$message.success('Successfully edit Table!');
|
||||
this.threeVisible = false;
|
||||
setTimeout(() => {
|
||||
this.$refs.commonWordHtmlTypeSetting.refresh('editTable', res.data.table?{...res.data.table,has_selected:1}:res.data);
|
||||
this.refreshCurrentContent('editTable',res.data.am_id, res.data);
|
||||
this.$refs.commonWordHtmlTypeSetting.refresh(
|
||||
'editTable',
|
||||
res.data.table ? { ...res.data.table, has_selected: 1 } : res.data
|
||||
);
|
||||
this.refreshCurrentContent('editTable', res.data.am_id, res.data);
|
||||
this.getCommentList();
|
||||
});
|
||||
} else {
|
||||
@@ -2571,9 +2601,8 @@ export default {
|
||||
background-color: #0066990d;
|
||||
/* display: block !important; */
|
||||
}
|
||||
wmath[data-wrap="inline"] {
|
||||
wmath[data-wrap='inline'] {
|
||||
display: inline-block !important;
|
||||
width: auto !important;
|
||||
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -721,7 +721,7 @@ export default {
|
||||
return false;
|
||||
}
|
||||
var list = this.$commonJS.cleanAndParseWordContent(content);
|
||||
console.log('list at line 569:', list);
|
||||
|
||||
|
||||
this.saveContentList(list, this.currentId);
|
||||
} else if (type == 'table') {
|
||||
@@ -1162,7 +1162,7 @@ export default {
|
||||
break;
|
||||
}
|
||||
|
||||
console.log('data at line 739:', data);
|
||||
|
||||
await this.$api
|
||||
.post(url, {
|
||||
am_id: data.mainId
|
||||
|
||||
@@ -928,7 +928,7 @@
|
||||
<div>
|
||||
<span>Status : </span>
|
||||
<b>{{ articleState }}</b>
|
||||
<el-button type="text" @click="testvis" icon="el-icon-edit">Change</el-button>
|
||||
<el-button type="text" @click="testvis" icon="el-icon-edit" v-if="!(form.is_draft==1&&form.state==3)">Change</el-button>
|
||||
</div>
|
||||
<div style="display: flex; width: 100%">
|
||||
<span>Remarks :</span>
|
||||
@@ -1553,6 +1553,7 @@ export default {
|
||||
remarks: '',
|
||||
state: '',
|
||||
ctime: '',
|
||||
is_draft: '',
|
||||
authorList: [],
|
||||
transList: []
|
||||
},
|
||||
@@ -1788,10 +1789,17 @@ export default {
|
||||
},
|
||||
articleState: function () {
|
||||
let str = '';
|
||||
switch (this.form.state) {
|
||||
|
||||
|
||||
if(this.form.is_draft==1&&this.form.state==3){
|
||||
str = this.$t('artstate.stateDraft');
|
||||
return str;
|
||||
}else{
|
||||
switch (this.form.state) {
|
||||
case 0:
|
||||
str = this.$t('artstate.state0');
|
||||
break;
|
||||
|
||||
case 1:
|
||||
str = this.$t('artstate.state1');
|
||||
break;
|
||||
@@ -1814,7 +1822,9 @@ export default {
|
||||
str = this.$t('artstate.state6');
|
||||
break;
|
||||
}
|
||||
return str;
|
||||
return str;
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -1881,8 +1891,37 @@ export default {
|
||||
.catch(() => {});
|
||||
},
|
||||
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;
|
||||
|
||||
} else {
|
||||
loading.close()
|
||||
this.$message.error(res.msg);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
loading.close()
|
||||
console.log(err);
|
||||
});
|
||||
|
||||
},
|
||||
handleClickRemark() {
|
||||
this.expanded = !this.expanded;
|
||||
@@ -2511,6 +2550,7 @@ export default {
|
||||
this.form.is_use_ai = res.article.is_use_ai;
|
||||
this.form.use_ai_explain = res.article.use_ai_explain;
|
||||
this.form.transList = res.transfer;
|
||||
this.form.is_draft = res.article.is_draft;
|
||||
this.msgs = res.msg;
|
||||
var alist = res.authors;
|
||||
let alist_name = [];
|
||||
|
||||
@@ -87,9 +87,13 @@
|
||||
</p> -->
|
||||
|
||||
<div class="man_state" :style="item.state,'3' | stateChange" >
|
||||
<b :style="item.state,'4' | stateChange">
|
||||
<b :style="item.state,'4' | stateChange" v-if="item.is_draft==1&&item.state==3">
|
||||
{{$t('artstate.stateDraft')}}
|
||||
</b>
|
||||
<b :style="item.state,'4' | stateChange" v-else>
|
||||
{{item.state,'tst' | stateChange}}
|
||||
</b>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="man_btn" style="overflow: hidden;">
|
||||
@@ -1058,7 +1062,7 @@ this.$router.push({
|
||||
border: 1px solid #fff;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
padding: 6px 18px;
|
||||
padding: 6px 12px;
|
||||
letter-spacing: -0.5px;
|
||||
border-top-right-radius: 3px;
|
||||
/* border-top-left-radius: 3px; */
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
<span style="float: right">
|
||||
<span class="labelTitle" style="font-weight: 500; font-size: 13px">Status :</span>
|
||||
<font style="margin-right: 15px; font-size: 13px; letter-spacing: -0.5px; font-weight: 700">
|
||||
{{ stateFormat(item.state) }}
|
||||
{{ stateFormat(item.is_draft==1&&item.state==3?'draft':item.state) }}
|
||||
</font>
|
||||
</span>
|
||||
</p>
|
||||
@@ -2629,6 +2629,9 @@ export default {
|
||||
case 0:
|
||||
str = this.$t('artstate.state0');
|
||||
break;
|
||||
case 'draft':
|
||||
str = this.$t('artstate.stateDraft');
|
||||
break;
|
||||
case 1:
|
||||
str = this.$t('artstate.state1');
|
||||
break;
|
||||
|
||||
@@ -96,6 +96,11 @@
|
||||
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Use the Picture as Graphic Abstract :" prop="is_graphical_abstract" label-width="260px">
|
||||
<el-radio v-model="detailMes.is_graphical_abstract" :label="1">Yes</el-radio>
|
||||
<el-radio v-model="detailMes.is_graphical_abstract" :label="2">No</el-radio>
|
||||
</el-form-item>
|
||||
<el-form-item label="Type :" prop="type">
|
||||
<el-select v-model="detailMes.type" filterable placeholder="Please select an article type">
|
||||
<el-option v-for="item in opMedical" :key="item.value" :label="item.label" :value="item.value"> </el-option>
|
||||
@@ -108,65 +113,61 @@
|
||||
<el-input v-model="detailMes.tradition_tag" placeholder="eg :Highlights"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Tradition Content :">
|
||||
<tinymce
|
||||
type="tradition"
|
||||
<div class="tinymce-container">
|
||||
<div v-if="tradition==null" class="loading-status loadTinymceBox">
|
||||
<i class="el-icon-loading"></i> Fetching highlights, please wait...
|
||||
</div>
|
||||
<tinymce v-else
|
||||
type="table"
|
||||
:height="160"
|
||||
id="tiny-tradition"
|
||||
ref="tinymceChild2"
|
||||
:tinymceOtherInit="{
|
||||
forced_root_block: '',
|
||||
newline_behavior: 'linebreak',
|
||||
newline_behavior: 'linebreak'
|
||||
}"
|
||||
valid_elements=",br"
|
||||
:wordStyle="`p{font-size: 13px;}`"
|
||||
:isAutomaticUpdate="true"
|
||||
@getContent="getContent"
|
||||
@updateChange="(content) => updateChange('tradition',content)"
|
||||
@updateChange="(content) => updateChange('tradition', content)"
|
||||
:value="tradition"
|
||||
class="paste-area text-container"
|
||||
:toolbar="[
|
||||
'bold italic |customBlue removeBlue|myuppercase myuppercasea Line MoreSymbols|subscript superscript|clearButton'
|
||||
]"
|
||||
style="
|
||||
line-height: 12px;
|
||||
overflow: auto;
|
||||
font-size: 13px; /* 字体大小 */
|
||||
margin-top: 0pt; /* 段前间距 */
|
||||
margin-bottom: 0pt; /* 段后间距 */
|
||||
"
|
||||
style="line-height: 12px; overflow: auto; font-size: 13px; margin-top: 0pt; margin-bottom: 0pt"
|
||||
></tinymce>
|
||||
|
||||
</div>
|
||||
<!-- <quill-editor ref="myTextEditor" v-model="detailMes.tradition" :options="editorOption"> </quill-editor> -->
|
||||
</el-form-item>
|
||||
<el-form-item label="Medical history of objective :">
|
||||
|
||||
<tinymce
|
||||
type="mhooStr"
|
||||
<div class="tinymce-container">
|
||||
<div v-if="mhooStr==null" class="loading-status loadTinymceBox">
|
||||
<i class="el-icon-loading"></i> Fetching medical history of objective, please wait...
|
||||
</div>
|
||||
<tinymce v-else
|
||||
type="table"
|
||||
:height="160"
|
||||
ref="tinymceChild3"
|
||||
:tinymceOtherInit="{
|
||||
forced_root_block: '',
|
||||
newline_behavior: 'linebreak',
|
||||
newline_behavior: 'linebreak'
|
||||
}"
|
||||
valid_elements=",br"
|
||||
:wordStyle="`p{font-size: 13px;}`"
|
||||
:isAutomaticUpdate="true"
|
||||
@getContent="getContent"
|
||||
@updateChange="(content) => updateChange('mhooStr',content)"
|
||||
id="tiny-mhoo"
|
||||
@updateChange="(content) => updateChange('mhooStr', content)"
|
||||
:value="mhooStr"
|
||||
class="paste-area text-container"
|
||||
:toolbar="[
|
||||
'bold italic |customBlue removeBlue|myuppercase myuppercasea Line MoreSymbols|subscript superscript|clearButton'
|
||||
]"
|
||||
style="
|
||||
line-height: 12px;
|
||||
overflow: auto;
|
||||
font-size: 13px; /* 字体大小 */
|
||||
margin-top: 0pt; /* 段前间距 */
|
||||
margin-bottom: 0pt; /* 段后间距 */
|
||||
"
|
||||
style="line-height: 12px; overflow: auto; font-size: 13px; margin-top: 0pt; margin-bottom: 0pt"
|
||||
></tinymce>
|
||||
|
||||
|
||||
</div>
|
||||
<!-- <quill-editor ref="myTextEditor" v-model="detailMes.mhoo" :options="editorOption"> </quill-editor> -->
|
||||
</el-form-item>
|
||||
<el-form-item label="keywords :" prop="keywords">
|
||||
@@ -188,27 +189,27 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="Abstract :" prop="abstract">
|
||||
<template slot="label"> <span style="color: #f56c6c; margin-right: 4px">*</span>Abstract : </template>
|
||||
<tinymce
|
||||
type="Abstract"
|
||||
:height="160"
|
||||
ref="tinymceChild1"
|
||||
:wordStyle="`p{font-size: 13px;}`"
|
||||
:isAutomaticUpdate="true"
|
||||
@getContent="getContent"
|
||||
@updateChange="(content) => updateChange('abstract',content)"
|
||||
:value="abstract"
|
||||
class="paste-area text-container"
|
||||
:toolbar="[
|
||||
'bold italic |customBlue removeBlue|myuppercase myuppercasea Line MoreSymbols|subscript superscript|clearButton'
|
||||
]"
|
||||
style="
|
||||
line-height: 12px;
|
||||
overflow: auto;
|
||||
font-size: 13px; /* 字体大小 */
|
||||
margin-top: 0pt; /* 段前间距 */
|
||||
margin-bottom: 0pt; /* 段后间距 */
|
||||
"
|
||||
></tinymce>
|
||||
<div class="tinymce-container">
|
||||
<div v-if="abstract==null" class="loading-status loadTinymceBox">
|
||||
<i class="el-icon-loading"></i> Fetching abstract, please wait...
|
||||
</div>
|
||||
|
||||
<tinymce
|
||||
v-else
|
||||
type="table"
|
||||
:height="160"
|
||||
ref="tinymceChild1"
|
||||
id="tiny-abstract"
|
||||
:wordStyle="`p{font-size: 13px;}`"
|
||||
:isAutomaticUpdate="true"
|
||||
@getContent="getContent"
|
||||
@updateChange="(content) => updateChange('abstract', content)"
|
||||
:value="abstract"
|
||||
class="paste-area text-container"
|
||||
:toolbar="['bold italic |customBlue removeBlue|myuppercase myuppercasea Line MoreSymbols|subscript superscript|clearButton']"
|
||||
style="line-height: 12px; overflow: auto; font-size: 13px; margin-top: 0pt; margin-bottom: 0pt"
|
||||
></tinymce>
|
||||
</div>
|
||||
|
||||
<!-- <quill-editor ref="myTextEditor" v-model="detailMes.abstract" :options="editorOption"> </quill-editor> -->
|
||||
</el-form-item>
|
||||
@@ -266,6 +267,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="author_country" label="Country" width="140px"></el-table-column>
|
||||
<el-table-column prop="orcid" label="ORCID"></el-table-column>
|
||||
<el-table-column prop="mailing_address" label="Corresponding author details" min-width="160px"></el-table-column>
|
||||
<el-table-column label="" width="190" align="center">
|
||||
<template slot-scope="scope">
|
||||
<div class="operation">
|
||||
@@ -292,7 +294,7 @@
|
||||
</el-table>
|
||||
<!-- 添加作者弹出框 -->
|
||||
<el-dialog title="Add author" :visible.sync="addAuthor" width="650px" destroy-on-close :close-on-click-modal="false">
|
||||
<el-form ref="add_Author" :model="addFomauthor" :rules="rules" label-width="165px">
|
||||
<el-form ref="add_Author" :model="addFomauthor" :rules="rules" label-width="215px">
|
||||
<el-form-item label="Author first name :" prop="first_name">
|
||||
<el-input v-model="addFomauthor.first_name"></el-input>
|
||||
</el-form-item>
|
||||
@@ -312,7 +314,7 @@
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="Email :" v-if="addFomauthor.is_report != '1'">
|
||||
<el-input v-model="editFomauthor.email" type="email"></el-input>
|
||||
<el-input v-model="addFomauthor.email" type="email"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Email :" prop="email" v-if="addFomauthor.is_report == '1'">
|
||||
<el-input v-model="addFomauthor.email" type="email"></el-input>
|
||||
@@ -350,6 +352,17 @@
|
||||
<template slot="prepend">https://orcid.org/</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:required="addFomauthor.is_report == '1'"
|
||||
label="Corresponding author details :"
|
||||
prop="mailing_address"
|
||||
>
|
||||
<el-input
|
||||
v-model="addFomauthor.mailing_address"
|
||||
type="textarea"
|
||||
placeholder="eg: Author full name. Affiliation address. Email."
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="addAuthor = false">Canel</el-button>
|
||||
@@ -358,7 +371,7 @@
|
||||
</el-dialog>
|
||||
<!-- 编辑作者弹出框 -->
|
||||
<el-dialog title="Edit Author" :visible.sync="editAuthor" width="650px" :close-on-click-modal="false">
|
||||
<el-form ref="edit_Author" :model="editFomauthor" :rules="rules" label-width="165px">
|
||||
<el-form ref="edit_Author" :model="editFomauthor" :rules="rules" label-width="215px">
|
||||
<el-form-item label="Author first name :" prop="first_name">
|
||||
<el-input v-model="editFomauthor.first_name"></el-input>
|
||||
</el-form-item>
|
||||
@@ -415,6 +428,18 @@
|
||||
<template slot="prepend">https://orcid.org/</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item
|
||||
:required="editFomauthor.is_report == '1'"
|
||||
label="Corresponding author details :"
|
||||
prop="mailing_address"
|
||||
>
|
||||
<el-input
|
||||
v-model="editFomauthor.mailing_address"
|
||||
type="textarea"
|
||||
placeholder="eg: Author full name. Affiliation address. Email."
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="editAuthor = false">Cancel</el-button>
|
||||
@@ -688,7 +713,7 @@
|
||||
<div class="bor_style_onli">
|
||||
<h4>{{ tabsList[5].name }}</h4>
|
||||
<div style="font-size: 14px">
|
||||
<div style="margin: 30px 0px 0 0">
|
||||
<div style="margin: 30px 0px 0 0">
|
||||
<h5 style="font-size: 16px; margin: 0 0 30px 0; letter-spacing: -0.5px">Improve information</h5>
|
||||
<!-- 时间Doi简介信息 -->
|
||||
<el-form ref="Abs_Form" :model="detailMes" :rules="rules" label-width="150px" style="margin-top: 30px">
|
||||
@@ -709,80 +734,97 @@
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div style="text-align: center; margin: 0px 0 0 0">
|
||||
<el-button type="primary" @click="ZsSaveAbs" class="save-btn" style="margin-top: 10px;">
|
||||
<el-button type="primary" @click="ZsSaveAbs" class="save-btn" style="margin-top: 10px">
|
||||
<i class="el-icon-check"></i>
|
||||
Save Essential Information
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div style="height: 1px; background-color: #c5e1f1; width: 100%; margin: 80px 0 40px"></div>
|
||||
<div style="display: flex; /* 开启 flex 布局 */
|
||||
justify-content: space-between;
|
||||
padding: 20px;">
|
||||
<div class="left-panel">
|
||||
<div style="margin: 0 0 40px 0">
|
||||
Choose Template :
|
||||
<el-select v-model="shuTter.board" placeholder="Please select a template..." @change="select_tem($event)" style="width: 225px">
|
||||
<el-option v-for="item in fol_low" :key="item.value" :label="item.label" :value="item.value"> </el-option>
|
||||
</el-select>
|
||||
<el-button type="primary" plain style="width: 150px; margin: 0 5px 0 15px" @click="EstaBlish">
|
||||
<i class="el-icon-document"></i> Create Manuscript
|
||||
</el-button>
|
||||
</div>
|
||||
<div style="display: flex; /* 开启 flex 布局 */ justify-content: space-between; padding: 20px">
|
||||
<div class="left-panel">
|
||||
<div style="margin: 0 0 40px 0">
|
||||
Choose Template :
|
||||
<el-select
|
||||
v-model="shuTter.board"
|
||||
placeholder="Please select a template..."
|
||||
@change="select_tem($event)"
|
||||
style="width: 225px"
|
||||
>
|
||||
<el-option v-for="item in fol_low" :key="item.value" :label="item.label" :value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-button type="primary" plain style="width: 150px; margin: 0 5px 0 15px" @click="EstaBlish">
|
||||
<i class="el-icon-document"></i> Create Manuscript
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<div style="margin: 30px 0 40px 0">
|
||||
<h5 style="font-size: 16px; margin: 0 0 30px 0; letter-spacing: -0.5px">Download list</h5>
|
||||
<p v-if="DLfileList.length == 0" style="color: #666; font-size: 14px">No Manuscript</p>
|
||||
<div v-for="(item, index) in DLfileList" :key="index" class="load_pdf">
|
||||
<img src="../../assets/img/icon_0.png" />
|
||||
<span style="color: #333">Typesetting {{ index + 1 }}</span>
|
||||
<span style="margin-left: 40px; color: #888; font-size: 13px">Time : {{ modifDate(item.ctime * 1000) }}</span>
|
||||
<a :href="'/tsfile/' + item.url" target="_blank" style="margin-left: 40px">
|
||||
<i class="el-icon-download" style="color: #66b1ff; font-weight: bold"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin: 30px 0 40px 0">
|
||||
<h5 style="font-size: 16px; margin: 0 0 30px 0; letter-spacing: -0.5px">Download list</h5>
|
||||
<p v-if="DLfileList.length == 0" style="color: #666; font-size: 14px">No Manuscript</p>
|
||||
<div v-for="(item, index) in DLfileList" :key="index" class="load_pdf">
|
||||
<img src="../../assets/img/icon_0.png" />
|
||||
<span style="color: #333">Typesetting {{ index + 1 }}</span>
|
||||
<span style="margin-left: 40px; color: #888; font-size: 13px"
|
||||
>Time : {{ modifDate(item.ctime * 1000) }}</span
|
||||
>
|
||||
<a :href="'/tsfile/' + item.url" target="_blank" style="margin-left: 40px">
|
||||
<i class="el-icon-download" style="color: #66b1ff; font-weight: bold"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="right-panel">
|
||||
<h5 style="font-size: 14px; margin: 0 0 40px 0">
|
||||
<el-button
|
||||
type="success"
|
||||
icon="el-icon-printer"
|
||||
style="width: 150px; height: 32px; font-size: 12px; margin-right: 14px"
|
||||
:loading="isGenerating"
|
||||
@click="generatePDF"
|
||||
>
|
||||
{{ isGenerating ? 'Generating PDF...' : 'Generate PDF' }}
|
||||
</el-button>
|
||||
<span>Click the button below to start high-quality PDF typesetting.</span>
|
||||
</h5>
|
||||
<div style="margin: 30px 0 40px 0">
|
||||
<h5 style="font-size: 16px; margin: 0 0 30px 0; letter-spacing: -0.5px; font-weight: bold">
|
||||
Download list
|
||||
<span
|
||||
><i
|
||||
class="el-icon-refresh"
|
||||
style="color: #006699; font-weight: bold; margin-left: 6px; cursor: pointer"
|
||||
@click="refreshPdfList"
|
||||
></i
|
||||
></span>
|
||||
|
||||
<span
|
||||
v-if="detailMes.file_sub_table"
|
||||
style="color: #006699; font-size: 13px; font-weight: normal; float: right"
|
||||
>Supplementary Material :<a
|
||||
:href="'/public/articleSUBTAB/' + detailMes.file_sub_table"
|
||||
target="_blank"
|
||||
style="margin-left: 20px"
|
||||
>
|
||||
<i class="el-icon-download" style="color: #006699; font-weight: bold"></i> </a
|
||||
></span>
|
||||
</h5>
|
||||
<p v-if="PDFfileList.length == 0" style="color: #666; font-size: 14px">No Manuscript</p>
|
||||
<div v-for="(item, index) in PDFfileList" :key="index" class="load_pdf">
|
||||
<img src="../../assets/img/icon_pdf.png" style="width: 26px; height: 26px" />
|
||||
<span style="color: #333">Typesetting {{ index + 1 }}</span>
|
||||
<span style="margin-left: 40px; color: #888; font-size: 13px"
|
||||
>Time : {{ modifDate(item.create_time * 1000) }}</span
|
||||
>
|
||||
<a :href="'/public/' + item.url" target="_blank" style="margin-left: 40px">
|
||||
<i class="el-icon-download" style="color: #66b1ff; font-weight: bold"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="right-panel">
|
||||
<h5 style="font-size: 14px; margin: 0 0 40px 0;">
|
||||
|
||||
<el-button
|
||||
type="success"
|
||||
icon="el-icon-printer"
|
||||
style="width: 150px; height: 32px; font-size: 12px;margin-right: 14px;"
|
||||
:loading="isGenerating"
|
||||
@click="generatePDF"
|
||||
>
|
||||
|
||||
{{ isGenerating ? 'Generating PDF...' : 'Generate PDF' }}
|
||||
</el-button>
|
||||
<span>Click the button below to start high-quality PDF typesetting.</span>
|
||||
</h5>
|
||||
<div style="margin: 30px 0 40px 0">
|
||||
<h5 style="font-size: 16px; margin: 0 0 30px 0; letter-spacing: -0.5px;font-weight: bold;">Download list
|
||||
<span><i class="el-icon-refresh" style="color: #006699; font-weight: bold;margin-left: 6px;cursor: pointer;" @click="refreshPdfList"></i></span>
|
||||
|
||||
<span v-if="detailMes.file_sub_table" style="color: #006699; font-size: 13px;font-weight: normal;float: right;">Supplementary Material :<a :href="'/public/articleSUBTAB/' +detailMes.file_sub_table" target="_blank" style="margin-left: 20px">
|
||||
<i class="el-icon-download" style="color: #006699; font-weight: bold"></i>
|
||||
</a></span>
|
||||
</h5>
|
||||
<p v-if="PDFfileList.length == 0" style="color: #666; font-size: 14px">No Manuscript</p>
|
||||
<div v-for="(item, index) in PDFfileList" :key="index" class="load_pdf">
|
||||
<img src="../../assets/img/icon_pdf.png" style="width: 26px; height: 26px;" />
|
||||
<span style="color: #333">Typesetting {{ index + 1 }}</span>
|
||||
<span style="margin-left: 40px; color: #888; font-size: 13px">Time : {{ modifDate(item.create_time * 1000) }}</span>
|
||||
<a :href="'/public/' + item.url" target="_blank" style="margin-left: 40px">
|
||||
<i class="el-icon-download" style="color: #66b1ff; font-weight: bold"></i>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="height: 1px; background-color: #c5e1f1; width: 100%; margin: 10px 0"></div>
|
||||
<div style="margin: 30px 0 30px 0">
|
||||
<h5 style="font-size: 16px; margin: 0 0 30px 0; letter-spacing: -0.5px">Upload the final typeset file</h5>
|
||||
@@ -829,7 +871,6 @@
|
||||
</el-upload>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1030,7 +1071,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
isGenerating: false, // 按钮加载状态
|
||||
percentage: 0, // 进度条
|
||||
percentage: 0, // 进度条
|
||||
finalReview: null,
|
||||
baseUrl: this.Common.baseUrl,
|
||||
mediaUrl: this.Common.mediaUrl,
|
||||
@@ -1096,11 +1137,13 @@ export default {
|
||||
],
|
||||
detailMes: {
|
||||
type: '',
|
||||
is_graphical_abstract: '3',
|
||||
journal_special_id: 'None'
|
||||
},
|
||||
abstract: '',
|
||||
tradition: '',
|
||||
mhooStr: '',
|
||||
abstract: null,
|
||||
|
||||
tradition:null,
|
||||
mhooStr: null,
|
||||
opInstal: [],
|
||||
// opMedical: [
|
||||
// {
|
||||
@@ -1475,6 +1518,40 @@ export default {
|
||||
message: 'Please use English characters only',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
is_graphical_abstract: [
|
||||
{
|
||||
required: true,
|
||||
validator: function (rule, value, callback) {
|
||||
if (value == 1 || value == 2) {
|
||||
callback();
|
||||
} else {
|
||||
// 这里的英文提示更加符合地道的校验语境
|
||||
callback(
|
||||
new Error(
|
||||
'Please select whether the uploaded picture should be shown as graphic abstract on the PDF title page.'
|
||||
)
|
||||
);
|
||||
}
|
||||
},
|
||||
trigger: 'change' // 建议下拉框用 change,失去焦点用 blur
|
||||
}
|
||||
],
|
||||
mailing_address: [
|
||||
{
|
||||
validator: (rule, value, callback) => {
|
||||
var formData = this.addAuthor ? this.addFomauthor : this.editFomauthor;
|
||||
if (formData.is_report == '1') {
|
||||
if (!value || value.trim() === '') {
|
||||
// 更加正式的表达:请提供通讯作者的详细信息
|
||||
return callback(new Error('Please provide the corresponding author details.'));
|
||||
}
|
||||
}
|
||||
// 必须确保所有逻辑路径都能执行到 callback()
|
||||
callback();
|
||||
},
|
||||
trigger: ['blur', 'change'] // 建议加上 change,体验更好
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
@@ -1484,7 +1561,6 @@ export default {
|
||||
this.getHight();
|
||||
window.addEventListener('resize', this.getHight);
|
||||
this.getData();
|
||||
|
||||
this.getAuthorJG();
|
||||
this.getCount();
|
||||
this.getWorldPdf();
|
||||
@@ -1492,30 +1568,29 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
async generatePDF() {
|
||||
// 1. 验证逻辑(保持原样)
|
||||
// 1. 验证逻辑(保持原样)
|
||||
|
||||
try {
|
||||
this.isGenerating = true; // 开启加载
|
||||
try {
|
||||
this.isGenerating = true; // 开启加载
|
||||
|
||||
// 注意:这里要加 await,确保拿到结果后再往下走
|
||||
const res = await this.$api.post('api/Production/createArticlePdf', {
|
||||
p_article_id: this.p_article_id
|
||||
});
|
||||
// 注意:这里要加 await,确保拿到结果后再往下走
|
||||
const res = await this.$api.post('api/Production/createArticlePdf', {
|
||||
p_article_id: this.p_article_id
|
||||
});
|
||||
|
||||
if (res.status == 1) {
|
||||
this.$message.success("The PDF document is being processed. Please wait and refresh the page in one minute.");
|
||||
} else {
|
||||
this.$message.error("Generation failed, please try again.");
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
this.$message.error("Network error, please try again.");
|
||||
} finally {
|
||||
// 只有请求真正完成后,才会执行这里
|
||||
this.isGenerating = false;
|
||||
}
|
||||
},
|
||||
if (res.status == 1) {
|
||||
this.$message.success('The PDF document is being processed. Please wait and refresh the page in one minute.');
|
||||
} else {
|
||||
this.$message.error('Generation failed, please try again.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
this.$message.error('Network error, please try again.');
|
||||
} finally {
|
||||
// 只有请求真正完成后,才会执行这里
|
||||
this.isGenerating = false;
|
||||
}
|
||||
},
|
||||
getArticleFinal(id) {
|
||||
// api/Finalreview/getRecord
|
||||
this.$api
|
||||
@@ -1524,7 +1599,6 @@ export default {
|
||||
// article_id: 6075
|
||||
})
|
||||
.then((res) => {
|
||||
|
||||
if (res.status == 1) {
|
||||
this.finalReview = res.data;
|
||||
} else {
|
||||
@@ -1533,17 +1607,13 @@ export default {
|
||||
});
|
||||
},
|
||||
updateChange(type, content) {
|
||||
|
||||
this[type] = content;
|
||||
},
|
||||
|
||||
getTinymceContent(type) {
|
||||
|
||||
this.$refs.tinymceChild1.getContent(type);
|
||||
},
|
||||
getContent(type, content) {
|
||||
|
||||
},
|
||||
getContent(type, content) {},
|
||||
// 跳转文章详情
|
||||
showdetaileditor(data) {
|
||||
this.$router.push({
|
||||
@@ -1583,45 +1653,49 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
wrapWithP(content){
|
||||
if (!content) return '';
|
||||
const trimmed = content.trim();
|
||||
// 判断是否以 <p 开头(兼容带属性的 p 标签)且以 </p> 结尾
|
||||
if (content.startsWith('<p>')) {
|
||||
return trimmed;
|
||||
}
|
||||
// 如果没有包裹,则手动包裹
|
||||
return `<p>${trimmed}</p>`;
|
||||
},
|
||||
getData() {
|
||||
this.idform.p_article_id = this.p_article_id;
|
||||
this.detailMes.p_article_id = this.p_article_id;
|
||||
this.addFomauthor.p_article_id = this.p_article_id;
|
||||
this.addFomschool.p_article_id = this.p_article_id;
|
||||
this.UpTypeFile.p_article_id = this.p_article_id;
|
||||
this.abstract = '';
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
text: 'Loading...',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
});
|
||||
this.idform.p_article_id = this.p_article_id;
|
||||
this.detailMes.p_article_id = this.p_article_id;
|
||||
this.detailMes.is_graphical_abstract = 3;
|
||||
this.addFomauthor.p_article_id = this.p_article_id;
|
||||
this.addFomschool.p_article_id = this.p_article_id;
|
||||
this.UpTypeFile.p_article_id = this.p_article_id;
|
||||
this.abstract = null;
|
||||
this.tradition = null;
|
||||
this.mhooStr = null;
|
||||
|
||||
|
||||
|
||||
// 获取文章信息
|
||||
this.$api
|
||||
.post('api/Production/getProductionDetail', this.idform)
|
||||
.then((res) => {
|
||||
if (res.code == 0) {
|
||||
if (res.code == 0) {
|
||||
|
||||
this.abstract = res.data.production.abstract ? res.data.production.abstract : '';
|
||||
|
||||
this.tradition = res.data.production.tradition ? res.data.production.tradition : '';
|
||||
this.mhooStr = res.data.production.mhoo ? res.data.production.mhoo : '';
|
||||
|
||||
this.detailMes = res.data.production;
|
||||
this.abstract = res.data.production.abstract?res.data.production.abstract:'';
|
||||
this.tradition = res.data.production.tradition?res.data.production.tradition:'';
|
||||
this.mhooStr = res.data.production.mhoo?res.data.production.mhoo:'';
|
||||
if (this.abstract != '') {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.tinymceChild1.setContent(this.abstract);
|
||||
});
|
||||
}
|
||||
if (this.tradition != '') {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.tinymceChild2.setContent(this.tradition);
|
||||
});
|
||||
}
|
||||
if (this.mhooStr != '') {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.tinymceChild3.setContent(this.mhooStr);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
this.UpTyFIle = res.data.production.file_pdf;
|
||||
this.getArticleFinal(res.data.production.article_id);
|
||||
if (res.data.production.icon != '') {
|
||||
@@ -1785,7 +1859,8 @@ export default {
|
||||
this.$message.error(err);
|
||||
});
|
||||
},
|
||||
refreshPdfList(){ const loading = this.$loading({
|
||||
refreshPdfList() {
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
text: 'Loading...',
|
||||
spinner: 'el-icon-loading',
|
||||
@@ -1800,22 +1875,19 @@ export default {
|
||||
},
|
||||
getPdfList() {
|
||||
// 可以下载的word列表
|
||||
|
||||
|
||||
this.$api
|
||||
.post('/api/Production/getProductionArticlePdf', {
|
||||
p_article_id: this.p_article_id
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.status == 1) {
|
||||
|
||||
this.PDFfileList = res.data;
|
||||
} else {
|
||||
|
||||
this.$message.error(res.msg);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
|
||||
this.$message.error(err);
|
||||
});
|
||||
},
|
||||
@@ -1944,7 +2016,7 @@ export default {
|
||||
return e.stage_year + ' Vol.' + e.stage_vol + ' issue.' + e.stage_no + e.stage_pagename + e.stage_page;
|
||||
},
|
||||
async abstractFormat(content) {
|
||||
content = this.$commonJS.transformHtmlString(content,'content',{keepBr:true});
|
||||
content = this.$commonJS.transformHtmlString(content, 'content', { keepBr: true });
|
||||
var div = document.createElement('div');
|
||||
div.innerHTML = content;
|
||||
var imgTags = div.getElementsByTagName('img');
|
||||
@@ -1969,41 +2041,46 @@ export default {
|
||||
}
|
||||
// 处理 p 标签 + 解码
|
||||
content = div.innerHTML;
|
||||
|
||||
|
||||
content = content.replace(/^<p>\s*(.*?)\s*<\/p>$/, '$1').trim();
|
||||
|
||||
|
||||
content = await this.$commonJS.decodeHtml(content);
|
||||
content = content.replace(/ |\u00A0/g, ' ');
|
||||
|
||||
|
||||
return content;
|
||||
},
|
||||
// 1----保存稿件信息
|
||||
async ZsSaveMes() {
|
||||
|
||||
var abstractStr = '';
|
||||
var mhooStr = '';
|
||||
var traditionStr = '';
|
||||
if (this.detailMes.journal_stage_id == 0) {
|
||||
this.$message.error('Please select an installment!');
|
||||
return;
|
||||
} if (this.tradition!='') {
|
||||
}
|
||||
if (this.tradition != '') {
|
||||
traditionStr = await this.abstractFormat(this.tradition);
|
||||
}
|
||||
if (this.mhooStr!='') {
|
||||
}
|
||||
if (this.mhooStr != '') {
|
||||
mhooStr = await this.abstractFormat(this.mhooStr);
|
||||
}
|
||||
|
||||
|
||||
if (this.abstract == '') {
|
||||
this.$message.error('Please input abstract!');
|
||||
return false;
|
||||
} else {
|
||||
abstractStr = await this.abstractFormat(this.abstract);
|
||||
}
|
||||
|
||||
|
||||
this.$refs.Mes_Form.validate((valid) => {
|
||||
if (valid) {
|
||||
this.$api
|
||||
.post('api/Production/editProduction', { ...this.detailMes, abstract: abstractStr, mhoo: mhooStr, tradition: traditionStr })
|
||||
.post('api/Production/editProduction', {
|
||||
...this.detailMes,
|
||||
abstract: abstractStr,
|
||||
mhoo: mhooStr,
|
||||
tradition: traditionStr
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.code == 0) {
|
||||
this.$message.success(`Successfully save the article!`);
|
||||
@@ -2025,6 +2102,10 @@ export default {
|
||||
|
||||
// 2----添加作者操作
|
||||
add_Authorclick(index, row) {
|
||||
if (this.schoolData.length == 0) {
|
||||
this.$message.error('Please provide at least one institutional affiliation.');
|
||||
return;
|
||||
}
|
||||
this.aid = index;
|
||||
this.addFomauthor = {
|
||||
is_first: '0',
|
||||
@@ -2035,7 +2116,6 @@ export default {
|
||||
this.addAuthor = true;
|
||||
},
|
||||
authorAdd(addFomauthor) {
|
||||
console.log(this.addFomauthor);
|
||||
this.$refs.add_Author.validate((valid) => {
|
||||
if (valid) {
|
||||
this.$api
|
||||
@@ -2982,11 +3062,11 @@ export default {
|
||||
// 获取文章信息
|
||||
this.$api
|
||||
.post('api/Preaccept/getArticleMains', {
|
||||
p_article_id: this.p_article_id
|
||||
article_id: this.detailMes.article_id
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.code == 0) {
|
||||
this.deMesYul.htmlList = res.data.mains;
|
||||
this.deMesYul.htmlList = res.data.list;
|
||||
this.preArtVisible = true;
|
||||
} else {
|
||||
this.$message.error(res.msg);
|
||||
@@ -3170,35 +3250,43 @@ export default {
|
||||
min-height: 60px;
|
||||
}
|
||||
.left-panel {
|
||||
flex: 1; /* 左侧占据剩余空间 */
|
||||
margin-right: 40px;
|
||||
border-right: 1px dashed #eee; /* 加一条虚线分隔线 */
|
||||
padding-right: 20px;
|
||||
flex: 1; /* 左侧占据剩余空间 */
|
||||
margin-right: 40px;
|
||||
border-right: 1px dashed #eee; /* 加一条虚线分隔线 */
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.right-panel {
|
||||
width: 48%; /* 右侧固定宽度 */
|
||||
width: 48%; /* 右侧固定宽度 */
|
||||
}
|
||||
.right-panel h5 {
|
||||
font-weight: normal;
|
||||
}
|
||||
.console-card {
|
||||
background: #f9f9f9;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
border: 1px solid #ebeef5;
|
||||
background: #f9f9f9;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
border: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.load_pdf {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
padding: 10px;
|
||||
transition: background 0.3s;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
padding: 10px;
|
||||
transition: background 0.3s;
|
||||
}
|
||||
|
||||
.load_pdf:hover {
|
||||
background: #f5f7fa;
|
||||
background: #f5f7fa;
|
||||
}
|
||||
.loadTinymceBox {
|
||||
height: 160px; line-height: 160px; text-align: center; border: 2px solid #eee;
|
||||
border-radius: 10px;
|
||||
color: #c0c4cc !important;
|
||||
}
|
||||
.loadTinymceBox *{
|
||||
color: #c0c4cc !important;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
</p>
|
||||
<!-- <p style="color: #7f8790;margin: 10px 0 0 0;">Follow the progress of your submission.</p> -->
|
||||
<div class="tit_head">
|
||||
Status : <b style="margin: 0 50px 0 0">{{ statetostr(artMes.laststate) }}</b> Journal : <b>{{ artMes.journalname }}</b>
|
||||
Status : <b style="margin: 0 50px 0 0">{{ artMes.is_draft==1&&(artMes.laststate==3||artMes.laststate==-1) ? $t('artstate.stateDraft') : statetostr(artMes.laststate)}}</b><span v-if="artMes.journalname">Journal : <b>{{ artMes.journalname }}</b></span>
|
||||
</div>
|
||||
<div class="tit_head" v-if="artMes.majors && artMes.majors.length > 0">
|
||||
<b style="margin: 0 50px 0 0; font-size: 20px">Research areas</b>
|
||||
|
||||
@@ -648,7 +648,7 @@ export default {
|
||||
break;
|
||||
}
|
||||
|
||||
console.log('data at line 739:', data);
|
||||
|
||||
await this.$api
|
||||
.post(url, {
|
||||
am_id: data.mainId
|
||||
|
||||
@@ -5,13 +5,25 @@
|
||||
<el-row :gutter="24">
|
||||
<el-col :span="24">
|
||||
<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 : ">
|
||||
<span>{{ detailDate.article }}</span>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="Editorial Board Member : ">
|
||||
<span>{{ detailDate.reviewer }}</span>
|
||||
</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 : ">
|
||||
<span>{{ detailDate.ctime }}</span>
|
||||
</el-form-item>
|
||||
|
||||
@@ -441,7 +441,7 @@ export default {
|
||||
},
|
||||
async created() {
|
||||
this.isCollapse = localStorage.getItem('isCollapse') == 'true' ? true : false;
|
||||
console.log('localStorage.getItem', typeof localStorage.getItem('isCollapse'));
|
||||
|
||||
this.isShowEditComment();
|
||||
this.isFresh = false;
|
||||
this.$nextTick(async () => {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<div class="tinymce-container editor-container">
|
||||
|
||||
<textarea class="tinymce-textarea" :id="tinymceId"></textarea>
|
||||
</div>
|
||||
</template>
|
||||
@@ -69,6 +68,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
uploadNotifications: {},
|
||||
content: '',
|
||||
totalUploadImages: 0,
|
||||
uploadedImageCount: 0,
|
||||
uploadNotificationInstance: null, // 全局通知实例
|
||||
@@ -123,19 +123,23 @@ export default {
|
||||
formLabelWidth: '120px',
|
||||
hasChange: false,
|
||||
hasInit: false,
|
||||
|
||||
editorInstance: null,
|
||||
tinymceId: this.id || 'vue-tinymce-' + +new Date()
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
value(val) {
|
||||
// console.log('val at line 208:', val);
|
||||
value: {
|
||||
|
||||
handler(val) {
|
||||
|
||||
|
||||
if (!this.hasChange && this.hasInit) {
|
||||
this.$nextTick(() => {
|
||||
window.tinymce.get(this.tinymceId).setContent(val);
|
||||
// window.renderMathJax(); // 主动触发 MathJax 渲染
|
||||
});
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@@ -159,13 +163,31 @@ export default {
|
||||
this.destroyTinymce();
|
||||
},
|
||||
methods: {
|
||||
handleSetContent(val) {
|
||||
if (!this.editorInstance) return;
|
||||
|
||||
let finalContent = val || '';
|
||||
// 你的业务逻辑:自动包裹 <p> 标签
|
||||
if (!finalContent.includes('wordTableHtml') && !finalContent.startsWith('<p>')) {
|
||||
finalContent = '<p>' + finalContent + '</p>';
|
||||
}
|
||||
|
||||
this.editorInstance.setContent(finalContent);
|
||||
|
||||
// 渲染数学公式
|
||||
this.$nextTick(() => {
|
||||
if (window.renderMathJax) {
|
||||
window.renderMathJax(this.tinymceId);
|
||||
}
|
||||
});
|
||||
},
|
||||
onClear() {
|
||||
if (this.uploadNotificationInstance) {
|
||||
this.uploadNotificationInstance.close(); this.uploadNotificationInstance = null;
|
||||
this.uploadedImageCount = 0;
|
||||
this.totalUploadImages = 0;}
|
||||
|
||||
this.uploadNotificationInstance.close();
|
||||
this.uploadNotificationInstance = null;
|
||||
this.uploadedImageCount = 0;
|
||||
this.totalUploadImages = 0;
|
||||
}
|
||||
},
|
||||
updateUploadProgressNotification(imgIndex, status = 'processing', message = '') {
|
||||
// 快捷调用 $t
|
||||
@@ -180,7 +202,7 @@ export default {
|
||||
<p id="total-status-text" style="margin: 0 0 12px 0; font-size: 14px; color: #606266; font-weight: 500;">
|
||||
${t('preparing', { total: this.totalUploadImages })}
|
||||
</p>
|
||||
|
||||
|
||||
<div class="el-progress el-progress--line" style="margin-bottom: 15px;">
|
||||
<div class="el-progress-bar">
|
||||
<div class="el-progress-bar__outer" style="height: 10px; background: #ebeef5; border-radius: 5px;">
|
||||
@@ -347,46 +369,46 @@ export default {
|
||||
}
|
||||
},
|
||||
// 按照你要求的 XMLHttpRequest 格式编写
|
||||
// 直接接收已经转好的 blob
|
||||
uploadSingleImage(blob, index) {
|
||||
const _this = this;
|
||||
const xhr = new XMLHttpRequest();
|
||||
const formData = new FormData();
|
||||
|
||||
// 直接把传进来的 blob 丢进表单
|
||||
formData.append('file_name', blob, `word_img_${index}.png`);
|
||||
formData.append('article_id', this.articleId);
|
||||
// 直接接收已经转好的 blob
|
||||
uploadSingleImage(blob, index) {
|
||||
const _this = this;
|
||||
const xhr = new XMLHttpRequest();
|
||||
const formData = new FormData();
|
||||
|
||||
xhr.withCredentials = false;
|
||||
xhr.open('POST', _this.baseUrl + 'api/Articlemain/uploadTableImage');
|
||||
|
||||
xhr.onload = function () {
|
||||
if (xhr.status !== 200) {
|
||||
_this.removePlaceholder(index); // 失败清理
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const json = JSON.parse(xhr.responseText);
|
||||
if (json.status == 1) {
|
||||
const finalUrl = _this.mediaUrl + 'articleTableImage/' + json.data;
|
||||
const doc = tinymce.activeEditor.getDoc();
|
||||
const placeholder = doc.querySelector(`img[data-idx="${index}"]`);
|
||||
if (placeholder) {
|
||||
placeholder.src = finalUrl;
|
||||
placeholder.removeAttribute('data-idx');
|
||||
// 直接把传进来的 blob 丢进表单
|
||||
formData.append('file_name', blob, `word_img_${index}.png`);
|
||||
formData.append('article_id', this.articleId);
|
||||
|
||||
xhr.withCredentials = false;
|
||||
xhr.open('POST', _this.baseUrl + 'api/Articlemain/uploadTableImage');
|
||||
|
||||
xhr.onload = function () {
|
||||
if (xhr.status !== 200) {
|
||||
_this.removePlaceholder(index); // 失败清理
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
_this.removePlaceholder(index);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('解析响应失败', e);
|
||||
_this.removePlaceholder(index);
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onerror = () => _this.removePlaceholder(index);
|
||||
xhr.send(formData);
|
||||
},
|
||||
try {
|
||||
const json = JSON.parse(xhr.responseText);
|
||||
if (json.status == 1) {
|
||||
const finalUrl = _this.mediaUrl + 'articleTableImage/' + json.data;
|
||||
const doc = tinymce.activeEditor.getDoc();
|
||||
const placeholder = doc.querySelector(`img[data-idx="${index}"]`);
|
||||
if (placeholder) {
|
||||
placeholder.src = finalUrl;
|
||||
placeholder.removeAttribute('data-idx');
|
||||
}
|
||||
} else {
|
||||
_this.removePlaceholder(index);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('解析响应失败', e);
|
||||
_this.removePlaceholder(index);
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onerror = () => _this.removePlaceholder(index);
|
||||
xhr.send(formData);
|
||||
},
|
||||
|
||||
removePlaceholder(idx) {
|
||||
const doc = tinymce.activeEditor.getDoc();
|
||||
@@ -408,12 +430,75 @@ uploadSingleImage(blob, index) {
|
||||
}
|
||||
return new Blob([u8arr], { type: mime });
|
||||
},
|
||||
formatHtml(val) {
|
||||
const rawValue = val || ''; // 处理 null
|
||||
const cleanEmptyTags = /<([a-zA-Z1-6]+)\b[^>]*><\/\1>/g;
|
||||
const replaceSpaces = /\s+(?=<)|(?<=>)\s+/g;
|
||||
const removeBr = /<br\s*\/?>/gi; // 移除所有 br 标签
|
||||
|
||||
if (rawValue.includes('wordTableHtml')) {
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(rawValue, 'text/html');
|
||||
const cells = doc.querySelectorAll('td, th');
|
||||
|
||||
cells.forEach((cell) => {
|
||||
cell.innerHTML = cell.innerHTML
|
||||
.replace(cleanEmptyTags, '')
|
||||
.replace(removeBr, '') // 针对你“不想要br”的需求
|
||||
.replace(replaceSpaces, ' ');
|
||||
});
|
||||
return doc.body.innerHTML;
|
||||
} else {
|
||||
return rawValue
|
||||
.replace(cleanEmptyTags, '')
|
||||
.replace(removeBr, '')
|
||||
.replace(replaceSpaces, ' ');
|
||||
}
|
||||
},
|
||||
getSafeContent(val) {
|
||||
const rawValue = val || '';
|
||||
const cleanEmptyTags = /<([a-zA-Z1-6]+)\b[^>]*><\/\1>/g;
|
||||
const replaceSpaces = /\s+(?=<)|(?<=>)\s+/g;
|
||||
|
||||
|
||||
const escapeIllegalLT = (str) => {
|
||||
return str.replace(/<(?!(\/?(p|div|span|table|tr|td|th|b|i|strong|em|ul|ol|li|br|img)))/gi, '<');
|
||||
};
|
||||
|
||||
let processedHtml = '';
|
||||
|
||||
if (rawValue.includes('wordTableHtml')) {
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(rawValue, 'text/html');
|
||||
const cells = doc.querySelectorAll('td, th');
|
||||
|
||||
cells.forEach((cell) => {
|
||||
// 1. 先把单元格内的非法 < 转义
|
||||
let cellText = cell.innerHTML;
|
||||
// let cellText = escapeIllegalLT(cell.innerHTML);
|
||||
// 2. 再清理空标签和多余空格
|
||||
cell.innerHTML = cellText
|
||||
.replace(cleanEmptyTags, '')
|
||||
.replace(replaceSpaces, ' ');
|
||||
});
|
||||
processedHtml = doc.body.innerHTML;
|
||||
} else {
|
||||
// 非表格逻辑也同样处理转义
|
||||
// processedHtml = escapeIllegalLT(rawValue)
|
||||
processedHtml = rawValue
|
||||
.replace(cleanEmptyTags, '')
|
||||
.replace(replaceSpaces, ' ');
|
||||
}
|
||||
|
||||
return processedHtml;
|
||||
},
|
||||
|
||||
initTinymce() {
|
||||
let globalImgCounter = 0; // 放在 init 闭包内,确保计数器持续增长
|
||||
let currentPasteBase64Images = [];
|
||||
|
||||
var _this = this;
|
||||
window.tinymce.init({
|
||||
..._this.tinymceOtherInit,
|
||||
trim_span_elements: false, // 禁止修剪内联标签周围的空格
|
||||
extended_valid_elements: 'blue[*]',
|
||||
custom_elements: 'blue',
|
||||
valid_children: '+blue[#text|i|em|b|strong|span],+body[blue],+p[blue]',
|
||||
@@ -439,34 +524,37 @@ uploadSingleImage(blob, index) {
|
||||
blue{
|
||||
display: inline;
|
||||
}
|
||||
myfigure,
|
||||
mytable {
|
||||
pointer-events: auto !important; /* 强制允许鼠标点击 */
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
color: rgb(0, 130, 170) !important;
|
||||
text-shadow: 0 0 3px #09c2fb, 0 0 4px rgba(0, 130, 170, 0.3);
|
||||
}
|
||||
myfigure,
|
||||
mytable {
|
||||
pointer-events: auto !important; /* 强制允许鼠标点击 */
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
color: rgb(0, 130, 170) !important;
|
||||
text-shadow: 0 0 3px #09c2fb, 0 0 4px rgba(0, 130, 170, 0.3);
|
||||
}
|
||||
|
||||
myfigure *,
|
||||
mytable * {
|
||||
color: inherit !important;
|
||||
text-shadow: inherit !important;
|
||||
background: transparent !important; /* 防止内部标签背景干扰 */
|
||||
}
|
||||
myfigure *,
|
||||
mytable * {
|
||||
color: inherit !important;
|
||||
text-shadow: inherit !important;
|
||||
background: transparent !important; /* 防止内部标签背景干扰 */
|
||||
}
|
||||
myh3 ,myh3 *{
|
||||
font-weight: bold !important;
|
||||
}
|
||||
|
||||
@keyframes blueGlow {
|
||||
0%,
|
||||
100% {
|
||||
transform: scale(1);
|
||||
opacity: 0.9;
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.02);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
`,
|
||||
@keyframes blueGlow {
|
||||
0%,
|
||||
100% {
|
||||
transform: scale(1);
|
||||
opacity: 0.9;
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.02);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
`,
|
||||
formats: {
|
||||
bold: { inline: 'b' },
|
||||
italic: { inline: 'i' }
|
||||
@@ -541,40 +629,39 @@ myfigure *,
|
||||
_this.$commonJS.initEditorButton(_this, ed);
|
||||
var currentWmathElement = null;
|
||||
ed.on('click', function (e) {
|
||||
const wmathElement = e.target.closest('wmath');
|
||||
if (wmathElement) {
|
||||
currentWmathElement = wmathElement; // 保存当前点击的元素
|
||||
|
||||
// 1. 提取内容:获取 LaTeX
|
||||
const latexContentRaw = wmathElement.getAttribute('data-latex') || '';
|
||||
const latexContent = latexContentRaw.replace(/\$/g, '').trim();
|
||||
const encoded = encodeURIComponent(latexContent);
|
||||
const wmathElement = e.target.closest('wmath');
|
||||
if (wmathElement) {
|
||||
currentWmathElement = wmathElement; // 保存当前点击的元素
|
||||
|
||||
// 2. 提取状态:获取之前的 wrap 模式 👈 重要新增
|
||||
const wrapMode = wmathElement.getAttribute('data-wrap') || 'block';
|
||||
// 1. 提取内容:获取 LaTeX
|
||||
const latexContentRaw = wmathElement.getAttribute('data-latex') || '';
|
||||
const latexContent = latexContentRaw.replace(/\$/g, '').trim();
|
||||
const encoded = encodeURIComponent(latexContent);
|
||||
|
||||
// 3. 处理唯一 ID
|
||||
let wmathId = wmathElement.getAttribute('data-id');
|
||||
if (!wmathId) {
|
||||
wmathId = 'wmath-' + Math.random().toString(36).substr(2, 9);
|
||||
wmathElement.setAttribute('data-id', wmathId);
|
||||
}
|
||||
// 2. 提取状态:获取之前的 wrap 模式 👈 重要新增
|
||||
const wrapMode = wmathElement.getAttribute('data-wrap') || 'block';
|
||||
|
||||
const editorId = ed.id;
|
||||
// 3. 处理唯一 ID
|
||||
let wmathId = wmathElement.getAttribute('data-id');
|
||||
if (!wmathId) {
|
||||
wmathId = 'wmath-' + Math.random().toString(36).substr(2, 9);
|
||||
wmathElement.setAttribute('data-id', wmathId);
|
||||
}
|
||||
|
||||
// 4. 打开窗口:在 URL 参数中增加 wrap 模式 👈 这样弹窗就知道该默认选哪个了
|
||||
window.open(
|
||||
`/LateX?id=${encoded}&wmathId=${wmathId}&editorId=${editorId}&wrap=${wrapMode}`,
|
||||
'_blank',
|
||||
'width=1000,height=800,scrollbars=no,resizable=no'
|
||||
);
|
||||
}
|
||||
});
|
||||
const editorId = ed.id;
|
||||
|
||||
ed.on('paste', async (event) => {
|
||||
// 4. 打开窗口:在 URL 参数中增加 wrap 模式 👈 这样弹窗就知道该默认选哪个了
|
||||
window.open(
|
||||
`/LateX?id=${encoded}&wmathId=${wmathId}&editorId=${editorId}&wrap=${wrapMode}`,
|
||||
'_blank',
|
||||
'width=1000,height=800,scrollbars=no,resizable=no'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
ed.on('paste', async (event) => {
|
||||
const rtf = event.clipboardData.getData('text/rtf');
|
||||
if (rtf && rtf.includes('\\pict')) {
|
||||
|
||||
const extracted = extractHexImagesFromRTF(rtf);
|
||||
_this.totalUploadImages = extracted.length; // 设置总数
|
||||
_this.uploadedImageCount = 0; // 重置已上传数
|
||||
@@ -594,22 +681,21 @@ myfigure *,
|
||||
return; // 跳过此图片
|
||||
}
|
||||
try {
|
||||
|
||||
const imageBlob = _this.hexToBlob(img.hex, img.mimeType);
|
||||
|
||||
_this.updateUploadProgressNotification(i, 'uploading');
|
||||
const imageBlob = _this.hexToBlob(img.hex, img.mimeType);
|
||||
|
||||
// 2. 【核心优化】直接上传这个 Blob 文件
|
||||
// uploadSingleImage 内部需要改用 FormData 发送
|
||||
await _this.uploadSingleImage(imageBlob, i);
|
||||
|
||||
_this.updateUploadProgressNotification(i, 'success');
|
||||
} catch (err) {
|
||||
_this.updateUploadProgressNotification(i, 'uploading');
|
||||
|
||||
// 2. 【核心优化】直接上传这个 Blob 文件
|
||||
// uploadSingleImage 内部需要改用 FormData 发送
|
||||
await _this.uploadSingleImage(imageBlob, i);
|
||||
|
||||
_this.updateUploadProgressNotification(i, 'success');
|
||||
} catch (err) {
|
||||
console.error('Upload failed:', err);
|
||||
_this.updateUploadProgressNotification(i, 'fail', err.message || 'Network error'); // 上传失败
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
await Promise.all(uploadPromises);
|
||||
// Promise.all 完成后, updateUploadProgressNotification 会自动计算 totalCount === uploadedCount 并关闭
|
||||
}
|
||||
@@ -640,41 +726,47 @@ myfigure *,
|
||||
}
|
||||
});
|
||||
ed.on('init', function () {
|
||||
_this.$commonJS.inTinymceButtonClass();
|
||||
const editorBody = ed.getBody();
|
||||
_this.editorInstance = ed;
|
||||
_this.hasInit = true;
|
||||
_this.$commonJS.inTinymceButtonClass();
|
||||
if (_this.isAutomaticUpdate) {
|
||||
_this.$emit('updateChange', _this.value);
|
||||
|
||||
const observer = new MutationObserver(() => {
|
||||
const currentContent = ed.getContent();
|
||||
if (_this.isAutomaticUpdate) {
|
||||
_this.$emit('updateChange', currentContent);
|
||||
// _this.$emit('updateChange', _this.$commonJS.decodeHtml(currentContent));
|
||||
//暂时注释掉数字公式
|
||||
// _this.$commonJS.replaceWMathContent(currentContent, (res) => {
|
||||
// console.log('res at line 451:', res);
|
||||
// _this.$emit('updateChange', res);
|
||||
// });
|
||||
}
|
||||
});
|
||||
|
||||
// 监听子节点和内容的变化
|
||||
observer.observe(editorBody, { childList: true, subtree: true, characterData: true });
|
||||
});
|
||||
// // 定义自定义按钮
|
||||
// ed.ui.registry.addButton('clearButton', {
|
||||
// text: 'Empty',
|
||||
}
|
||||
_this.content = _this.getSafeContent(_this.value);
|
||||
|
||||
// onAction: () => {
|
||||
// // 插入自定义表格到编辑器中
|
||||
// ed.setContent('');
|
||||
// }
|
||||
// });
|
||||
_this.handleSetContent(_this.content || '');
|
||||
|
||||
// 3. 监听内容变化
|
||||
ed.on('NodeChange Change KeyUp SetContent', () => {
|
||||
_this.hasChange = true;
|
||||
_this.$emit('input', ed.getContent({ format: 'raw' }));
|
||||
});
|
||||
|
||||
// 4. 监听 DOM 变化
|
||||
const observer = new MutationObserver(() => {
|
||||
const currentContent = ed.getContent({ format: 'raw' });
|
||||
if (_this.isAutomaticUpdate) {
|
||||
_this.$emit('updateChange', currentContent);
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(ed.getBody(), {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
characterData: true
|
||||
});
|
||||
});
|
||||
|
||||
// 定义自定义按钮
|
||||
ed.ui.registry.addButton('customButtonExportWord', {
|
||||
text: _this.$t('commonTable.exportWord'),
|
||||
onAction: () => {
|
||||
// 插入自定义表格到编辑器中
|
||||
let content = ed.getContent(); // 获取内容
|
||||
let content = ed.getContent({ format: 'raw' }); // 获取内容
|
||||
content = content.replace(/<strong>/g, '<b>').replace(/<\/strong>/g, '</b>');
|
||||
content = content.replace(/<em>/g, '<i>').replace(/<\/em>/g, '</i>');
|
||||
const container = document.createElement('div');
|
||||
@@ -688,7 +780,7 @@ myfigure *,
|
||||
text: _this.$t('commonTable.exportImg'),
|
||||
onAction: () => {
|
||||
// 插入自定义表格到编辑器中
|
||||
_this.export('image', ed.getContent());
|
||||
_this.export('image', ed.getContent({ format: 'raw' }));
|
||||
}
|
||||
});
|
||||
ed.ui.registry.addContextToolbar('spacer', {
|
||||
@@ -724,7 +816,6 @@ myfigure *,
|
||||
tempDiv.innerHTML = content;
|
||||
|
||||
if (tempDiv.querySelector('table')) {
|
||||
|
||||
if (_this.type == 'table') {
|
||||
// 3. 在这里直接消费外部变量 currentPasteBase64Images
|
||||
// content = content.replace(new RegExp(`src="${silentPlaceholder}"`, 'gi'), () => {
|
||||
@@ -765,40 +856,29 @@ myfigure *,
|
||||
args.content = container.innerHTML; // 更新处理后的内容
|
||||
});
|
||||
} else {
|
||||
// _this.$confirm('检测到粘贴内容包含表格,是否需要以表格形式添加?', '提示', {
|
||||
// confirmButtonText: '添加表格',
|
||||
// cancelButtonText: '纯文本添加',
|
||||
// type: 'info'
|
||||
// }).then(() => {
|
||||
// _this.$emit('openAddTable', content);
|
||||
// return false
|
||||
// }).catch(() => {
|
||||
|
||||
// });
|
||||
// _this.$confirm('检测到粘贴内容包含表格,是否需要以表格形式添加?', '提示', {
|
||||
// confirmButtonText: '添加表格',
|
||||
// cancelButtonText: '纯文本添加',
|
||||
// type: 'info'
|
||||
// }).then(() => {
|
||||
// _this.$emit('openAddTable', content);
|
||||
// return false
|
||||
// }).catch(() => {
|
||||
// });
|
||||
}
|
||||
} else {
|
||||
console.log('Original content:', content); // 输出原始粘贴内容
|
||||
const mathRegex = /\$\$([\s\S]+?)\$\$|\$([\s\S]+?)\$/g;
|
||||
content = content.replace(mathRegex, function (match, blockFormula, inlineFormula) {
|
||||
const formula = blockFormula || inlineFormula;
|
||||
const mode = blockFormula ? 'block' : 'inline';
|
||||
console.log(`Matched ${mode} formula:`, formula);
|
||||
|
||||
// 1. 修改正则:同时匹配 $$...$$ (块级) 和 $...$ (行内)
|
||||
// 注意:先匹配双美元符,再匹配单美元符,防止冲突
|
||||
const mathRegex = /\$\$([\s\S]+?)\$\$|\$([\s\S]+?)\$/g;
|
||||
return `<wmath data-wrap="${mode}" data-latex="${formula.trim()}">${formula.trim()}</wmath>`;
|
||||
});
|
||||
|
||||
content = content.replace(mathRegex, function (match, blockFormula, inlineFormula) {
|
||||
// 判断是块级还是行内
|
||||
const formula = blockFormula || inlineFormula;
|
||||
const mode = blockFormula ? 'block' : 'inline';
|
||||
|
||||
console.log(`Matched ${mode} formula:`, formula);
|
||||
|
||||
// 2. 统一改造:标签内只放纯 formula,不带 $ 符号
|
||||
// 属性中保存 data-latex 和 data-wrap
|
||||
return `<wmath data-wrap="${mode}" data-latex="${formula.trim()}">${formula.trim()}</wmath>`;
|
||||
});
|
||||
|
||||
console.log('Processed content:', content); // 输出处理后的内容
|
||||
|
||||
}
|
||||
// 更新 args.content 为处理后的内容
|
||||
// 阻止默认的粘贴行为,确保自定义处理优先执行
|
||||
|
||||
if (args.event) {
|
||||
args.event.preventDefault();
|
||||
args.event.stopPropagation();
|
||||
@@ -814,103 +894,79 @@ console.log('Processed content:', content); // 输出处理后的内容
|
||||
}, 10);
|
||||
},
|
||||
clear_custom_action: (editor, vm) => {
|
||||
|
||||
vm.onClear();
|
||||
},
|
||||
init_instance_callback: (editor) => {
|
||||
if (_this.value) {
|
||||
editor.setContent('<p>' + _this.value + '</p>');
|
||||
|
||||
setTimeout(() => {
|
||||
window.renderMathJax(_this.tinymceId); // 初始化时渲染 MathJax
|
||||
}, 10);
|
||||
}
|
||||
_this.hasInit = true;
|
||||
editor.on('NodeChange Change KeyUp SetContent', () => {
|
||||
this.hasChange = true;
|
||||
this.$emit('input', editor.getContent());
|
||||
|
||||
// console.log('at line 518:', '改变');
|
||||
// setTimeout(() => {
|
||||
// window.renderMathJax(); // 初始化时渲染 MathJax
|
||||
// }, 50);
|
||||
});
|
||||
}
|
||||
// init_instance_callback: (editor) => {
|
||||
|
||||
// }
|
||||
});
|
||||
if (!window._wmath_listener_registered) {
|
||||
// 💾 新增公式插入点记录
|
||||
let latexEditorBookmark = null;
|
||||
let activeEditorId = null;
|
||||
|
||||
// 👂 message 监听器:处理编辑 + 新增两种情况
|
||||
window.addEventListener('message', function (event) {
|
||||
const data = event.data;
|
||||
|
||||
if (data && (data.type === 'update-wmath' || data.type === 'insert-wmath')) {
|
||||
const { editorId, wmathId, latex } = data;
|
||||
const newLatex = latex ? latex.trim() : '';
|
||||
if (!editorId) return;
|
||||
const data = event.data;
|
||||
|
||||
const targetEditor = tinymce.get(editorId);
|
||||
if (!targetEditor) return;
|
||||
if (data && (data.type === 'update-wmath' || data.type === 'insert-wmath')) {
|
||||
const { editorId, wmathId, latex } = data;
|
||||
const newLatex = latex ? latex.trim() : '';
|
||||
if (!editorId) return;
|
||||
|
||||
// 尝试寻找现有标签
|
||||
const targetWmath = wmathId ? targetEditor.dom.select(`wmath[data-id="${wmathId}"]`, targetEditor.getBody())[0] : null;
|
||||
const targetEditor = tinymce.get(editorId);
|
||||
if (!targetEditor) return;
|
||||
|
||||
if (targetWmath) {
|
||||
// --- 原有的更新/删除逻辑 ---
|
||||
if (!newLatex) {
|
||||
targetEditor.dom.remove(targetWmath);
|
||||
} else {
|
||||
targetWmath.setAttribute('data-latex', newLatex);
|
||||
if (data.wrapMode === 'inline') {
|
||||
targetWmath.setAttribute('data-wrap', 'inline');
|
||||
} else {
|
||||
targetWmath.setAttribute('data-wrap', 'block');
|
||||
}
|
||||
targetWmath.innerHTML = newLatex;
|
||||
}
|
||||
} else if (newLatex) {
|
||||
// --- ✨ 新增逻辑:如果找不到现有标签且有 latex 内容 ---
|
||||
// 生成一个新的唯一 ID (如果你后端或插件没给的话)
|
||||
const newId = wmathId || 'wmath_' + Date.now();
|
||||
|
||||
// 构建新的 wmath 标签字符串
|
||||
// 这里你可以根据之前选的 wrapMode (块级/行内) 来决定样式
|
||||
const htmlToInsert = `<wmath data-id="${newId}" data-latex="${newLatex}" data-wrap="${data.wrapMode === 'inline' ? 'inline' : 'block'}">${newLatex}</wmath>`;
|
||||
|
||||
// 在当前光标位置插入内容
|
||||
targetEditor.insertContent(htmlToInsert);
|
||||
}
|
||||
const targetWmath = wmathId
|
||||
? targetEditor.dom.select(`wmath[data-id="${wmathId}"]`, targetEditor.getBody())[0]
|
||||
: null;
|
||||
|
||||
// 统一渲染
|
||||
setTimeout(() => {
|
||||
if (typeof renderMathJax === 'function') {
|
||||
renderMathJax(editorId);
|
||||
}
|
||||
}, 10);
|
||||
}
|
||||
});
|
||||
if (targetWmath) {
|
||||
if (!newLatex) {
|
||||
targetEditor.dom.remove(targetWmath);
|
||||
} else {
|
||||
targetWmath.setAttribute('data-latex', newLatex);
|
||||
if (data.wrapMode === 'inline') {
|
||||
targetWmath.setAttribute('data-wrap', 'inline');
|
||||
} else {
|
||||
targetWmath.setAttribute('data-wrap', 'block');
|
||||
}
|
||||
targetWmath.innerHTML = newLatex;
|
||||
}
|
||||
} else if (newLatex) {
|
||||
const newId = wmathId || 'wmath_' + Date.now();
|
||||
|
||||
const htmlToInsert = `<wmath data-id="${newId}" data-latex="${newLatex}" data-wrap="${
|
||||
data.wrapMode === 'inline' ? 'inline' : 'block'
|
||||
}">${newLatex}</wmath>`;
|
||||
|
||||
targetEditor.insertContent(htmlToInsert);
|
||||
}
|
||||
|
||||
// 统一渲染
|
||||
setTimeout(() => {
|
||||
if (typeof renderMathJax === 'function') {
|
||||
renderMathJax(editorId);
|
||||
}
|
||||
}, 10);
|
||||
}
|
||||
});
|
||||
|
||||
// 🚩 标记为已注册,防止重复
|
||||
window._wmath_listener_registered = true;
|
||||
|
||||
// 导出保存位置函数(你可以在按钮点击时调用它)
|
||||
window._recordLatexInsertContext = function (editorInstance) {
|
||||
latexEditorBookmark = editorInstance.selection.getBookmark(2);
|
||||
activeEditorId = editorInstance.id;
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
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 });
|
||||
},
|
||||
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) {
|
||||
var html = this.$commonJS.updateTableStyles(container, this.typesettingType);
|
||||
var editor = window.tinymce.activeEditor; // 将外部 DOM 内容更新到编辑器
|
||||
@@ -920,11 +976,11 @@ console.log('Processed content:', content); // 输出处理后的内容
|
||||
editor.focus(); // 聚焦到编辑器// 触发编辑器内容变化后,如果需要,可能还要设置编辑器的样式
|
||||
},
|
||||
//销毁富文本
|
||||
destroyTinymce() {this.onClear();
|
||||
destroyTinymce() {
|
||||
this.onClear();
|
||||
if (window.tinymce.get(this.tinymceId)) {
|
||||
window.tinymce.get(this.tinymceId).destroy();
|
||||
}
|
||||
|
||||
},
|
||||
//设置内容
|
||||
setContent(value) {
|
||||
@@ -932,11 +988,13 @@ console.log('Processed content:', content); // 输出处理后的内容
|
||||
},
|
||||
//获取内容
|
||||
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(/<strong>/g, '<b>').replace(/<\/strong>/g, '</b>');
|
||||
content = content.replace(/<em>/g, '<i>').replace(/<\/em>/g, '</i>');
|
||||
content = content.replace(/ /g, ' '); // 将所有 替换为空格
|
||||
|
||||
this.$emit('getContent', type, content);
|
||||
},
|
||||
|
||||
|
||||
@@ -20,20 +20,27 @@
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="24">
|
||||
<div class="form-box" style="width: 100%">
|
||||
<el-form ref="articleform" :model="detailDate" label-width="140px">
|
||||
<el-form-item label="Title">
|
||||
<el-form ref="articleform" :model="detailDate" label-width="160px">
|
||||
<el-form-item label="Title : ">
|
||||
<span style="font-weight: bold;color: #333;">{{ detailDate.article }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="Reviewer">
|
||||
<el-form-item label="Reviewer : ">
|
||||
<span>{{ detailDate.reviewer }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="Reviewer email">
|
||||
<el-form-item label="Reviewer email : ">
|
||||
<span>{{ detailDate.reviewer_email }}</span>
|
||||
</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>
|
||||
</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 == 1">Remain anonymous</span>
|
||||
</el-form-item>
|
||||
@@ -144,6 +151,7 @@ export default {
|
||||
article: '',
|
||||
reviewer: '',
|
||||
reviewer_email: '',
|
||||
reviewer_company:'',
|
||||
articlefile: '',
|
||||
articlezip: '',
|
||||
ctime: '',
|
||||
@@ -331,6 +339,7 @@ export default {
|
||||
this.detailDate.article = res.data.article.title;
|
||||
this.detailDate.reviewer = res.data.article_reviewer.realname;
|
||||
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.is_anonymous = res.data.article_reviewer.is_anonymous;
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ export default {
|
||||
if (this.lineStyle.table) {
|
||||
this.tableData = [...this.lineStyle.table];
|
||||
var modalContent = `
|
||||
<div class="wordTableHtml" >
|
||||
<div class="wordTableHtml">
|
||||
<table
|
||||
border="1"
|
||||
style="
|
||||
@@ -84,6 +84,10 @@ export default {
|
||||
modalContent += `</table></div>`;
|
||||
|
||||
this.updatedHtml = modalContent;
|
||||
this.$nextTick(() => {
|
||||
this.$refs.tinymceChild1.initTinymce()
|
||||
})
|
||||
|
||||
}
|
||||
} else {
|
||||
this.updatedHtml = '';
|
||||
@@ -106,10 +110,15 @@ export default {
|
||||
this.$refs.tinymceChild1.getContent(type);
|
||||
},
|
||||
getContent(type, content) {
|
||||
|
||||
|
||||
if (content) {
|
||||
const container = document.createElement('div');
|
||||
container.innerHTML = content;
|
||||
|
||||
this.$commonJS.parseTableToArray(content, (table) => {
|
||||
|
||||
|
||||
this.$emit('getContent', type, { html_data: content, table: table });
|
||||
});
|
||||
} else {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div
|
||||
@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;'"
|
||||
ref="scrollDiv"
|
||||
>
|
||||
@@ -181,24 +181,23 @@
|
||||
</span>
|
||||
<div
|
||||
:class="
|
||||
!isPreview
|
||||
? item.is_h1
|
||||
? 'isTitleH1 pMainH1'
|
||||
: item.is_h2
|
||||
? 'isTitleH2'
|
||||
: item.is_h3
|
||||
? 'isTitleH3'
|
||||
: ''
|
||||
: item.is_h1
|
||||
? 'Ptitle'
|
||||
: ''
|
||||
item.is_h1
|
||||
? 'isTitleH1 pMainH1'
|
||||
: item.is_h2
|
||||
? 'isTitleH2'
|
||||
: item.is_h3
|
||||
? 'isTitleH3'
|
||||
: ''
|
||||
"
|
||||
style="line-height: 24px"
|
||||
>
|
||||
<template v-if="!isPreview">
|
||||
<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 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">
|
||||
@@ -366,6 +365,7 @@
|
||||
:id="'editor' + item.am_id"
|
||||
v-html="highlightText({ am_id: item.am_id, text: item.content }, item.checks ? item.checks : [], item.type)"
|
||||
></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -967,7 +967,7 @@
|
||||
<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_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 class="row-divider" v-if="currentData.type == 0"></div>
|
||||
<div v-if="isEditComment && currentData.type == 0" class="menu-item ai-feat" @click="menuAction('proofreading')">
|
||||
@@ -978,19 +978,19 @@
|
||||
</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>
|
||||
</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>
|
||||
</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>
|
||||
</div>
|
||||
<div
|
||||
class="menu-item menu-link"
|
||||
style="color: #f56c6c"
|
||||
v-if="currentData.type == 0 && currentTag"
|
||||
v-if="currentData.type == 0 && ['figure', 'table'].includes(currentTag)"
|
||||
@click="menuAction('unbindLink')"
|
||||
>
|
||||
<i class="el-icon-link"></i><span>{{ $t('commonTable.UnbindAssociation') }}</span>
|
||||
@@ -1275,6 +1275,7 @@ export default {
|
||||
this.$refs.scrollDiv.addEventListener('scroll', this.divOnScroll, { passive: true });
|
||||
|
||||
document.addEventListener('selectionchange', () => {
|
||||
if(this.isPreview)return;
|
||||
const selection = window.getSelection();
|
||||
if (selection.rangeCount === 0) return;
|
||||
|
||||
@@ -1475,6 +1476,7 @@ export default {
|
||||
this.$forceUpdate();
|
||||
},
|
||||
handleGlobalClick(e) {
|
||||
if(this.isPreview)return;
|
||||
// 如果点在气泡内,不关
|
||||
if (e.target.closest('.bubble-container')) return;
|
||||
|
||||
@@ -1787,8 +1789,7 @@ export default {
|
||||
const el = Array.isArray(r) ? r[0] : r;
|
||||
if (!sc || !el) return;
|
||||
const top = this.topInScroll(el, sc) - 80;
|
||||
console.log('top at line 1491:', top);
|
||||
|
||||
|
||||
sc.scrollTo({ top, behavior: 'smooth' });
|
||||
},
|
||||
|
||||
@@ -1817,8 +1818,7 @@ export default {
|
||||
return doc.body.innerHTML;
|
||||
},
|
||||
async editProofreadingContent(data) {
|
||||
console.log('data at line 1276:', data);
|
||||
|
||||
|
||||
data.revised_content = await this.convertSpacesToNbsp(data.revised_content);
|
||||
this.proofreadingContent = {
|
||||
...data,
|
||||
@@ -1898,7 +1898,7 @@ export default {
|
||||
container.scrollTo({ top: Math.max(0, top), behavior: 'smooth' });
|
||||
},
|
||||
handleClick(tab, event) {
|
||||
console.log(tab, event);
|
||||
|
||||
if (this.isEditComment) {
|
||||
if (tab.index == 0) {
|
||||
this.activeName == 'proofreading';
|
||||
@@ -2001,7 +2001,7 @@ export default {
|
||||
},
|
||||
|
||||
changeSort(type) {
|
||||
console.log('type at line 782:', type);
|
||||
|
||||
if (this.currentId) {
|
||||
this.$emit('changeSort', type, this.currentId);
|
||||
}
|
||||
@@ -2130,6 +2130,7 @@ export default {
|
||||
|
||||
// 3. 核心调用逻辑
|
||||
async handleOpenLink() {
|
||||
|
||||
// 1. 校验是否选中内容
|
||||
const selectedText = this.currentSelection.label || '';
|
||||
if (!selectedText) {
|
||||
@@ -2234,12 +2235,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. 【归一化匹配】:处理转义字符冲突 (< 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) {
|
||||
if (this.currentData.type == 0) {
|
||||
this.$emit('onEditTitle', {
|
||||
|
||||
|
||||
this.$emit('onEditTitle', {
|
||||
mainId: this.currentId,
|
||||
value: value
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
},
|
||||
clearHighlight1() {
|
||||
@@ -2319,7 +2389,7 @@ export default {
|
||||
revokeProofreading(data) {
|
||||
// this.$emit('revokeProofreading', data);
|
||||
var content = this.wordList.find((e) => e.am_id == data.am_id).content;
|
||||
console.log('content at line 1890:', content);
|
||||
|
||||
this.$api
|
||||
.post('api/Proofread/change', {
|
||||
am_id: data.am_id,
|
||||
@@ -2344,10 +2414,10 @@ export default {
|
||||
});
|
||||
},
|
||||
executeProofreading(data) {
|
||||
console.log('data at line 1416:', data);
|
||||
|
||||
// this.$emit('executeProofreading', data);
|
||||
var content = this.wordList.find((e) => e.am_id == data.am_id).content;
|
||||
console.log('content at line 1890:', content);
|
||||
|
||||
this.$api
|
||||
.post('api/Proofread/change', {
|
||||
am_id: data.am_id,
|
||||
@@ -2370,7 +2440,7 @@ export default {
|
||||
});
|
||||
},
|
||||
refreshCurrentData(am_id, newData, type) {
|
||||
console.log('newData at line 2106:', newData);
|
||||
|
||||
var refreshData = { ...this.wordList.find((e) => e.am_id == am_id) };
|
||||
var refreshDataIndex = this.wordList.findIndex((e) => e.am_id == am_id);
|
||||
if (refreshData.type == 0) {
|
||||
@@ -2391,10 +2461,10 @@ export default {
|
||||
}
|
||||
//图片的注解 表格标题和注解 还有表格要单独处理
|
||||
|
||||
console.log('refreshData at line 1293:', refreshData);
|
||||
|
||||
},
|
||||
deleteProofreading(data, index) {
|
||||
console.log('data at line 1599:', data);
|
||||
|
||||
// this.$emit('deleteProofreading', data);
|
||||
if (this.isEditComment) {
|
||||
this.$confirm(this.$t('commonTable.removeProofread'), 'Prompt', {
|
||||
@@ -2470,7 +2540,7 @@ export default {
|
||||
this.$emit('onDrop', e, targetId.slice(6)); // 阻止默认的行为
|
||||
},
|
||||
clearEditor(editorId) {
|
||||
console.log('editorId at line 462:', editorId);
|
||||
|
||||
for (const key in this.editors) {
|
||||
if (this.editors[key]) {
|
||||
// 确保销毁所有编辑器实例
|
||||
@@ -2732,20 +2802,11 @@ export default {
|
||||
if (event && event.stopPropagation) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
if (!this.isPreview) {
|
||||
this.clearHighlight();
|
||||
this.selectedIds = [];
|
||||
this.menuType = type;
|
||||
this.currentTag = '';
|
||||
this.currentTagData = null; // 必须重置,防止带入旧数据
|
||||
this.$set(this, 'currentId', id);
|
||||
|
||||
this.currentIndex = index;
|
||||
this.currentData = data;
|
||||
const clickedTag = event.target.closest('myfigure, mytable');
|
||||
this.currentTag = '';
|
||||
this.currentTagData = null; // 必须重置,防止带入旧数据
|
||||
const clickedTag = event.target.closest('myfigure, mytable, myh3');
|
||||
if (clickedTag) {
|
||||
this.currentTag = clickedTag;
|
||||
this.currentTag = clickedTag.tagName.toLowerCase().replace('my', '');
|
||||
this.currentTagData = {
|
||||
link_id: clickedTag.getAttribute('data-id'),
|
||||
link_type: clickedTag.tagName.toLowerCase().replace('my', ''),
|
||||
@@ -2753,7 +2814,20 @@ export default {
|
||||
fullHtml: clickedTag.outerHTML,
|
||||
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.isMenuVisible = true;
|
||||
|
||||
@@ -2761,6 +2835,11 @@ export default {
|
||||
await this.getProofreadingList([id]); // 建议 await 异步操作
|
||||
this.getPList(id);
|
||||
}
|
||||
}else{
|
||||
if (clickedTag) {
|
||||
this.handleClickJump();
|
||||
}
|
||||
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.isInternalAction = false;
|
||||
@@ -2786,12 +2865,12 @@ export default {
|
||||
this.$emit('editComment', data, type);
|
||||
},
|
||||
getCommentRemark(data) {
|
||||
console.log('data at line 426:', data);
|
||||
|
||||
const items = this.comments[data.am_id];
|
||||
|
||||
// 如果找到了对应的数据项
|
||||
if (items) {
|
||||
console.log(items);
|
||||
|
||||
return items;
|
||||
} else {
|
||||
}
|
||||
@@ -2816,7 +2895,7 @@ export default {
|
||||
return formattedDate;
|
||||
},
|
||||
async goToListComment(data, fn) {
|
||||
console.log('data at line 993:', data);
|
||||
|
||||
await this.goToComment(data.am_id, fn);
|
||||
},
|
||||
divOnScroll() {
|
||||
@@ -2943,7 +3022,10 @@ export default {
|
||||
text = this.highlightText3(item.text, [], type, item.am_id);
|
||||
}
|
||||
}
|
||||
return text;
|
||||
// const finalHtml = text.replace(/<(?!(\/?(span|p|div|table|tr|td|th|b|i|strong|em|ul|ol|li|br|img|myh3|myfigure|mytable|blue|wmath)))/gi, '<');
|
||||
|
||||
return text;
|
||||
|
||||
},
|
||||
// 改造版:DOM 安全高亮
|
||||
// 仅保留 <wmath>…</wmath> 内部,其他用正则匹配高亮
|
||||
@@ -3225,6 +3307,8 @@ export default {
|
||||
html += `<img contenteditable="false" src="${this.imagePath || ''}" alt="" style="width:20px;height:20px;opacity:.6;">`;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return html;
|
||||
},
|
||||
getProofreadingList(arr) {
|
||||
@@ -3359,11 +3443,10 @@ export default {
|
||||
changeTable() {
|
||||
// 获取所有表格
|
||||
const tables = window.tinymce.get(this.tinymceId).getBody().querySelectorAll('table');
|
||||
console.log('tables at line 110:', tables);
|
||||
|
||||
|
||||
// 遍历并设置样式
|
||||
tables.forEach((table) => {
|
||||
console.log('table at line 360:', table);
|
||||
|
||||
const editor = window.tinymce.get(this.tinymceId);
|
||||
editor.dom.setStyles(table, {
|
||||
width: this.typesettingType == 1 ? '17.18cm' : '25.88cm'
|
||||
@@ -3405,11 +3488,11 @@ export default {
|
||||
this.selectedComment = null;
|
||||
},
|
||||
replacePlaceholderImage(ami_id, realImgSrc) {
|
||||
console.log('realImgSrc at line 638:', ami_id, realImgSrc);
|
||||
|
||||
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}"]`);
|
||||
console.log('placeholderImg at line 640:', placeholderImg);
|
||||
|
||||
|
||||
if (placeholderImg) {
|
||||
placeholderImg.src = realImgSrc; // 替换图片 URL
|
||||
@@ -3443,7 +3526,7 @@ export default {
|
||||
|
||||
//获取内容
|
||||
getContent1(type, content) {
|
||||
console.log('content at line 2986:', content);
|
||||
|
||||
content = this.$commonJS.transformHtmlString(content);
|
||||
|
||||
var div = document.createElement('div');
|
||||
@@ -3465,7 +3548,7 @@ export default {
|
||||
|
||||
// 获取最终修改后的 HTML
|
||||
content = div.innerHTML;
|
||||
console.log('content at line 3007:', content);
|
||||
|
||||
this.$api
|
||||
.post('api/Proofread/modify', {
|
||||
am_id: this.proofreadingContent.am_id,
|
||||
@@ -4318,7 +4401,12 @@ wmath {
|
||||
text-shadow: inherit !important;
|
||||
background: transparent !important; /* 防止内部标签背景干扰 */
|
||||
}
|
||||
|
||||
::v-deep myh3 {
|
||||
font-weight: bold !important;
|
||||
}
|
||||
::v-deep myh3 *{
|
||||
font-weight: bold !important;
|
||||
}
|
||||
@keyframes blueGlow {
|
||||
0%,
|
||||
100% {
|
||||
@@ -4347,4 +4435,11 @@ wmath {
|
||||
display: inline-block !important;
|
||||
width: auto !important;
|
||||
}
|
||||
.preview-container{
|
||||
|
||||
::v-deep myfigure,
|
||||
::v-deep mytable {
|
||||
text-shadow: none !important
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -930,7 +930,7 @@ if(newData.ami_id) {
|
||||
},
|
||||
async created() {
|
||||
this.isCollapse = localStorage.getItem('isCollapse') == 'true' ? true : false;
|
||||
console.log('localStorage.getItem', typeof localStorage.getItem('isCollapse'));
|
||||
|
||||
this.isShowEditComment();
|
||||
this.isFresh = false;
|
||||
this.$nextTick(async () => {
|
||||
|
||||
@@ -154,9 +154,11 @@
|
||||
class="status ok"
|
||||
:class="scope.row.refer_type == 'journal' ? getJournalDateno(scope.row.dateno, 'status') : ''"
|
||||
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>
|
||||
</span>
|
||||
@@ -171,7 +173,7 @@
|
||||
<!-- journal 形式 -->
|
||||
<div style="text-align: left" v-if="scope.row.refer_type == 'journal'" class="reference-item">
|
||||
<p>
|
||||
{{ scope.row.author }} {{ scope.row.title }}. <em>{{ scope.row.joura }}</em
|
||||
{{ scope.row.author }} <span v-html="formatTitle(scope.row.title)"></span>. <em>{{ scope.row.joura }}</em
|
||||
>. <span :class="getJournalDateno(scope.row.dateno, 'title')">{{ scope.row.dateno }}</span
|
||||
>.<br />
|
||||
</p>
|
||||
@@ -179,12 +181,13 @@
|
||||
</div>
|
||||
<!-- book 形式 -->
|
||||
<div style="text-align: left" v-if="scope.row.refer_type == 'book'" class="reference-item">
|
||||
<p>{{ scope.row.author }} {{ scope.row.title }}. {{ scope.row.dateno }}. <br /></p>
|
||||
<p>{{ scope.row.author }} <span v-html="formatTitle(scope.row.title)"></span>. {{ scope.row.dateno }}. <br /></p>
|
||||
<a class="doiLink" :href="scope.row.isbn" target="_blank">{{ scope.row.isbn }}</a>
|
||||
</div>
|
||||
<!-- 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>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -569,6 +572,18 @@ export default {
|
||||
}
|
||||
},
|
||||
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) {
|
||||
if (dateno && typeof dateno === 'string') {
|
||||
const hasInvalidColon = !dateno.includes(':') || (dateno.includes(':') && dateno.split(':').pop().trim() === '');
|
||||
|
||||
@@ -361,7 +361,7 @@ export default {
|
||||
this.add_apply = 0;
|
||||
|
||||
break;
|
||||
case 7||16:
|
||||
case 7:
|
||||
// 7文章状态不在审稿中
|
||||
this.add_apply = 1;
|
||||
break;
|
||||
@@ -369,7 +369,8 @@ export default {
|
||||
//拒绝审稿
|
||||
this.add_apply = -1;
|
||||
break;
|
||||
case 13:
|
||||
case 13:
|
||||
case 16:
|
||||
//13 邀请审稿超过5天未同意邀请16同意审稿后14天未进行审稿
|
||||
this.add_apply = 2;
|
||||
break;
|
||||
|
||||
@@ -73,7 +73,7 @@ module.exports = {
|
||||
// target: 'http://zmzm.tougao.dev.com/',//晓玲本地
|
||||
target: 'https://submission.tmrjournals.com/',//正式
|
||||
// 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,
|
||||
pathRewrite: {
|
||||
'^/api': ''
|
||||
|
||||
Reference in New Issue
Block a user