This commit is contained in:
2025-10-15 15:08:39 +08:00
parent c3d0aa9f4f
commit 171ddf4761
6 changed files with 2167 additions and 300 deletions

59
src/common/js/debounce.js Normal file
View File

@@ -0,0 +1,59 @@
let timeout = null
/**
* 防抖原理一定时间内只有最后一次操作再过wait毫秒后才执行函数
*
* @param {Function} func 要执行的回调函数
* @param {Number} wait 延时的时间
* @param {Boolean} immediate 是否立即执行
* @return null
*/
function debounce(func, wait = 500, immediate = false) {
// 清除定时器
if (timeout !== null) clearTimeout(timeout)
// 立即执行,此类情况一般用不到
if (immediate) {
const callNow = !timeout
timeout = setTimeout(() => {
timeout = null
}, wait)
if (callNow) typeof func === 'function' && func()
} else {
// 设置定时器当最后一次操作后timeout不会再被清除所以在延时wait毫秒后执行func回调方法
timeout = setTimeout(() => {
typeof func === 'function' && func()
}, wait)
}
}
function throttle(fn, delay = 1000, immediate = false) {
console.log("进入节流对象")
let timer
let status = false // 是否为重复点击状态
return function () {
let _this = this
let args = arguments
if (immediate) {
console.log("立即执行参数 执行一次方法")
fn.apply(_this, args)
immediate = false
return
}
if (status) {
console.log("当前点击状态为正在重复点击,请稍等片刻后在点击执行")
return
}
console.log("执行节流:当前执行了一次点击方法")
fn.apply(_this, args)
status = true // 修改状态
timer = setTimeout(() => {
console.log("规定时间到,重置状态,可以重新调用")
status = false
}, delay)
}
}
export {
debounce,
throttle
}

View File

@@ -363,6 +363,9 @@ const en = {
add: 'Add', add: 'Add',
delete: 'Delete', delete: 'Delete',
reply: 'Reply', reply: 'Reply',
execute: 'Execute',
revoke: 'Revoke',
solve: 'Solve', solve: 'Solve',
cancelsolve: 'Cancel resolved', cancelsolve: 'Cancel resolved',
Resolved: 'Resolved', Resolved: 'Resolved',
@@ -382,6 +385,8 @@ const en = {
exportImg: 'Export PNG', exportImg: 'Export PNG',
PaperRotation: 'Paper Rotation', PaperRotation: 'Paper Rotation',
removeAnnotations: 'Are you sure you want to delete this Annotation?', removeAnnotations: 'Are you sure you want to delete this Annotation?',
removeProofread
: 'Are you sure to delete this suggestion?',
removeContent: 'Are you sure you want to delete this content?', removeContent: 'Are you sure you want to delete this content?',
reContent: 'Are you sure you want to restore this content?', reContent: 'Are you sure you want to restore this content?',
uploadImageInfo: 'Figures can only upload files in JPG, JPEG, and PNG formats!', uploadImageInfo: 'Figures can only upload files in JPG, JPEG, and PNG formats!',

View File

@@ -354,6 +354,8 @@ const zh = {
commonTable: { commonTable: {
add: '新增', add: '新增',
delete: '删除', delete: '删除',
execute: '执行',
revoke: '撤回',
reply: '答复', reply: '答复',
solve: '解决', solve: '解决',
cancelsolve: '取消解决', cancelsolve: '取消解决',
@@ -374,6 +376,7 @@ const zh = {
exportImg: '导出 图片', exportImg: '导出 图片',
PaperRotation: '纸张方向', PaperRotation: '纸张方向',
removeAnnotations: '确定要删除这条批注吗?', removeAnnotations: '确定要删除这条批注吗?',
removeProofread: '确定要删除这条建议吗?',
removeContent: '确定要删除这条内容吗?', removeContent: '确定要删除这条内容吗?',
reContent: '确定要恢复这条内容吗?', reContent: '确定要恢复这条内容吗?',
uploadImageInfo: 'Figures 只能上传 JPG、JPEG 和 PNG 格式的文件', uploadImageInfo: 'Figures 只能上传 JPG、JPEG 和 PNG 格式的文件',

View File

@@ -88,7 +88,7 @@
</div> --> </div> -->
<common-word <common-word
:key="new Date().getTime()"
v-if="htmlContent" v-if="htmlContent"
ref="commonWord" ref="commonWord"
:value="htmlContent" :value="htmlContent"
@@ -101,6 +101,7 @@
@loaded="loadedWord" @loaded="loadedWord"
@onEdit="onEdit" @onEdit="onEdit"
@addContent="onAddContent" @addContent="onAddContent"
@changeSort="changeSort" @changeSort="changeSort"
@onDelete="onDelete" @onDelete="onDelete"
@onDeletes="onDeletes" @onDeletes="onDeletes"
@@ -111,6 +112,10 @@
@cancelSolveComment="cancelSolveComment" @cancelSolveComment="cancelSolveComment"
@replyComment="replyComment" @replyComment="replyComment"
@deleteComment="deleteComment" @deleteComment="deleteComment"
@editProofreading="editProofreading"
@revokeProofreading="revokeProofreading"
@executeProofreading="executeProofreading"
@deleteProofreading="deleteProofreading"
@onEditTitle="onEditTitle" @onEditTitle="onEditTitle"
@onAddRow="onAddRow" @onAddRow="onAddRow"
@changeComment="changeComment" @changeComment="changeComment"
@@ -269,16 +274,22 @@
> >
<div style="display: flex; flex-wrap: wrap; gap: 10px; justify-content: start"> <div style="display: flex; flex-wrap: wrap; gap: 10px; justify-content: start">
<div v-for="(item, i) in uploadWordTables" class="uploadWordTableBox"> <div v-for="(item, i) in uploadWordTables" class="uploadWordTableBox">
<el-button @click="addUploadWordTable(item)" size="mini" class="insertTable"> 插入 </el-button> <el-button @click="addUploadWordTable(item)" size="mini" class="insertTable"> 插入 </el-button>
<div class="thumbnailTableBox wordTableHtml table_Box pMain myeditabledivTable drop-target"> <div class="thumbnailTableBox wordTableHtml table_Box pMain myeditabledivTable drop-target">
<p style="font-size: 12px;padding: 10px;box-sizing: border-box;">Table {{ i + 1 }}</p> <p style="font-size: 12px; padding: 10px; box-sizing: border-box">Table {{ i + 1 }}</p>
<table border="1" :style="`width: 800px;zoom:${zoomNum};border-collapse: collapse; text-align: center`"> <table border="1" :style="`width: 800px;zoom:${zoomNum};border-collapse: collapse; text-align: center`">
<tr <tr
v-for="(row, i) in item.table_data" v-for="(row, i) in item.table_data"
:key="i" :key="i"
:class="{ 'table-header-row': isHeaderRow(i, item.table_data) }" :class="{ 'table-header-row': isHeaderRow(i, item.table_data) }"
> >
<td style="font-size: 20px;"v-for="(cell, i1) in row" :key="i1" :colspan="`${cell.colspan || 1}`" :rowspan="`${cell.rowspan || 1}`"> <td
style="font-size: 20px"
v-for="(cell, i1) in row"
:key="i1"
:colspan="`${cell.colspan || 1}`"
:rowspan="`${cell.rowspan || 1}`"
>
<span v-html="cell.text"></span> <span v-html="cell.text"></span>
</td> </td>
</tr> </tr>
@@ -393,6 +404,7 @@
</el-button> </el-button>
</span> </span>
</el-dialog> </el-dialog>
<common-late-x v-if="showLateX" @close="showLateX = false" @save="saveLateX" :LateXInfo="LateXInfo"></common-late-x> <common-late-x v-if="showLateX" @close="showLateX = false" @save="saveLateX" :LateXInfo="LateXInfo"></common-late-x>
</div> </div>
</template> </template>
@@ -407,7 +419,7 @@ import bottomTinymce from '@/components/page/components/Tinymce';
export default { export default {
data() { data() {
return { return {
zoomNum:(window.innerWidth * 0.38) / 850, zoomNum: (window.innerWidth * 0.38) / 850,
uploadWordTables: [], uploadWordTables: [],
tablesHtmlVisible: false, tablesHtmlVisible: false,
tablesHtml: '', tablesHtml: '',
@@ -425,6 +437,7 @@ export default {
articleId: this.$route.query.id, articleId: this.$route.query.id,
isShowComment: false, isShowComment: false,
urlList: { urlList: {
executeProofreading: 'api/Proofread/change',
delete: 'api/Preaccept/delArticleMains', delete: 'api/Preaccept/delArticleMains',
addRow: 'api/Preaccept/addBlankRow', addRow: 'api/Preaccept/addBlankRow',
addComment: 'api/Preaccept/createArticleMainCheckForEditor', addComment: 'api/Preaccept/createArticleMainCheckForEditor',
@@ -508,6 +521,8 @@ export default {
}, },
txtVisible: false, txtVisible: false,
addContentVisible: false, addContentVisible: false,
editProofreadingContentVisible: false,
proofreadingContent: {},
addContent: {}, addContent: {},
lineStyle: {}, lineStyle: {},
lineStyle1: {}, lineStyle1: {},
@@ -555,7 +570,10 @@ export default {
} }
} }
}, },
created() { async created() {
// await this.$api.post('api/Proofread/proofRead', {
// article_id: this.$route.query.id
// });
localStorage.removeItem('scrollPosition'); localStorage.removeItem('scrollPosition');
this.isShowEditComment(); this.isShowEditComment();
this.getDate(); this.getDate();
@@ -563,14 +581,16 @@ export default {
// this.loadDictionary().catch(console.error); // this.loadDictionary().catch(console.error);
}, },
mounted() {}, mounted() {},
activated() { async activated() {
// await this.$api.post('api/Proofread/proofRead', {
// article_id: this.$route.query.id
// });
this.isShowEditComment(); this.isShowEditComment();
this.getDate(); this.getDate();
this.getCommentList(); this.getCommentList();
}, },
methods: { methods: {
async copyArray(data) { async copyArray(data) {
try { try {
// 将数组内容转换为字符串,使用换行符分隔 // 将数组内容转换为字符串,使用换行符分隔
@@ -585,7 +605,7 @@ export default {
} }
}, },
openLatexEditor(data) { openLatexEditor(data) {
this.showLateX = true; this.showLateX = true;
this.LateXInfo = data; this.LateXInfo = data;
}, },
isShowEditComment() { isShowEditComment() {
@@ -626,6 +646,9 @@ export default {
handleSaveAddContent() { handleSaveAddContent() {
this.$refs.addContent.getTinymceContent('addcontent'); this.$refs.addContent.getTinymceContent('addcontent');
}, },
handleSaveEditProofreadingContent() {
this.$refs.addContent.getTinymceContent('addcontent');
},
async getContent(type, content) { async getContent(type, content) {
if (type == 'content') { if (type == 'content') {
@@ -1136,24 +1159,22 @@ export default {
}); });
// 处理文件上传并传递回调函数 // 处理文件上传并传递回调函数
this.$commonJS.handleFileUpload(event, function (tables) { this.$commonJS.handleFileUpload(event, function (tables) {
console.log('tables at line 1138:', tables) console.log('tables at line 1138:', tables);
if(tables.length == 0){ if (tables.length == 0) {
loading.close() loading.close();
that.$message({ that.$message({
type: 'warning', type: 'warning',
message: 'No table found!' message: 'No table found!'
}); });
return false return false;
} }
// 使用 Promise.all 等待所有表格解析完成 // 使用 Promise.all 等待所有表格解析完成
Promise.all( Promise.all(
tables.map((table) => { tables.map((table) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// 解析每个表格 // 解析每个表格
that.$commonJS.parseTableToArray(table, (tableList) => { that.$commonJS.parseTableToArray(table, (tableList) => {
resolve({ table_data: tableList, html_data: '' }); resolve({ table_data: tableList, html_data: '' });
}); });
}); });
@@ -1162,25 +1183,24 @@ export default {
.then((result) => { .then((result) => {
// 所有表格的解析完成后,处理结果 // 所有表格的解析完成后,处理结果
that.uploadWordTables = result; that.uploadWordTables = result;
loading.close() loading.close();
that.tablesHtmlVisible = true; that.tablesHtmlVisible = true;
}) })
.catch((error) => { .catch((error) => {
loading.close() loading.close();
console.error('Error processing tables:', error); console.error('Error processing tables:', error);
}); });
}); });
const file = event.target.files[0]; const file = event.target.files[0];
if (file) { if (file) {
// 处理文件逻辑 // 处理文件逻辑
} }
// 关键:重置 input 的值 // 关键:重置 input 的值
event.target.value = ''; event.target.value = '';
}, },
async onAddRow(mainId) { async onAddRow(mainId) {
await this.$api await this.$api
.post(this.urlList.addRow, { .post(this.urlList.addRow, {
am_id: mainId, am_id: mainId,
@@ -1211,6 +1231,59 @@ export default {
this.$message.error(err.msg); this.$message.error(err.msg);
}); });
}, },
async executeProofreading(data) {
console.log('data at line 1225:', data);
await this.$api
.post(this.urlList.executeProofreading, {
am_id: data.am_id,
record_id: data.id,
state: 1,
article_id: this.$route.query.id
})
.then(async (res) => {
if (res.status == 1) {
this.getDate();
this.getCommentList();
} else {
this.$message.error(res.msg);
}
})
.catch((err) => {
this.$message.error(err.msg);
});
},
async revokeProofreading(data) {
console.log('data at line 1225:', data);
await this.$api
.post(this.urlList.executeProofreading, {
am_id: data.am_id,
record_id: data.id,
state: 2,
article_id: this.$route.query.id
})
.then(async (res) => {
if (res.status == 1) {
this.getDate();
this.getCommentList();
} else {
this.$message.error(res.msg);
}
})
.catch((err) => {
this.$message.error(err.msg);
});
},
async editProofreading(data) {
console.log('data at line 1225:', data);
},
deleteProofreading(data, index) {
console.log('comment at line 480:', data);
},
async cancelSolveComment(data) { async cancelSolveComment(data) {
await this.$api await this.$api
.post(this.urlList.cancelSolveComment, { .post(this.urlList.cancelSolveComment, {
@@ -1330,6 +1403,7 @@ export default {
this.currentId = dataId; this.currentId = dataId;
}, },
async onDrop(event, dataId) { async onDrop(event, dataId) {
if (event.dataTransfer.getData('image')) { if (event.dataTransfer.getData('image')) {
const draggedImage = JSON.parse(event.dataTransfer.getData('image')); const draggedImage = JSON.parse(event.dataTransfer.getData('image'));
@@ -1514,11 +1588,14 @@ export default {
}, },
// 获取数据 // 获取数据
async getDate() { async getDate() {
// await this.$api.post('api/Proofread/proofRead', {
// article_id: this.$route.query.id
// });
this.imagesList = []; this.imagesList = [];
let urlLInk = ''; let urlLInk = '';
let urlTask = {}; let urlTask = {};
if (this.Art_Id != undefined) { if (this.Art_Id != undefined) {
urlLInk = 'api/Preaccept/getArticleMains'; urlLInk = 'api/Preaccept/getArticleMainsNew';
urlTask.article_id = this.Art_Id; urlTask.article_id = this.Art_Id;
} }
@@ -1737,7 +1814,7 @@ export default {
} }
}; };
var cleanedTableList = content.table ? content.table : []; var cleanedTableList = content.table ? content.table : [];
cleanedTableList = cleanTableData(content.table); cleanedTableList = cleanTableData(content.table);
var strTitle = this.lineStyle1.title ? this.lineStyle1.title : ''; var strTitle = this.lineStyle1.title ? this.lineStyle1.title : '';
@@ -2204,10 +2281,10 @@ export default {
::v-deep .wordTableHtml table span blue { ::v-deep .wordTableHtml table span blue {
color: rgb(0, 130, 170) !important; color: rgb(0, 130, 170) !important;
} }
::v-deep .wordTableHtml table span blue sup{ ::v-deep .wordTableHtml table span blue sup {
color: rgb(0, 130, 170) !important; color: rgb(0, 130, 170) !important;
} }
::v-deep .wordTableHtml table span blue sub{ ::v-deep .wordTableHtml table span blue sub {
color: rgb(0, 130, 170) !important; color: rgb(0, 130, 170) !important;
} }
.toolbar { .toolbar {
@@ -2295,7 +2372,7 @@ export default {
width: 38vw; width: 38vw;
position: relative; position: relative;
height: auto; height: auto;
overflow: hidden; overflow: hidden;
padding: 10px; padding: 10px;
box-sizing: border-box; box-sizing: border-box;
box-shadow: rgba(0, 0, 0, 0.1) 0px 2px 12px 0px; box-shadow: rgba(0, 0, 0, 0.1) 0px 2px 12px 0px;
@@ -2304,13 +2381,13 @@ overflow: hidden;
margin-bottom: 0; margin-bottom: 0;
padding: 15px; padding: 15px;
} }
.uploadWordTableBox .insertTable{ .uploadWordTableBox .insertTable {
/* display: none; */ /* display: none; */
position: absolute; position: absolute;
right: 10px; right: 10px;
} }
.uploadWordTableBox:hover { .uploadWordTableBox:hover {
background-color: #0066990d; background-color: #0066990d;
/* display: block !important; */ /* display: block !important; */
} }
</style> </style>

View File

@@ -11,6 +11,9 @@
<el-dropdown-item divided <el-dropdown-item divided
><p @click="EditDetail(data)"><i class="el-icon-edit"></i>Topics</p> ><p @click="EditDetail(data)"><i class="el-icon-edit"></i>Topics</p>
</el-dropdown-item> </el-dropdown-item>
<!-- <el-dropdown-item divided
><p @click="handleClickAb(data)"><i class="el-icon-edit"></i>Abstract</p>
</el-dropdown-item> -->
       
<el-dropdown-item divided> <el-dropdown-item divided>
<p @click="ChoseRelated(data)"><i class="el-icon-tickets"></i>Relevant</p> <p @click="ChoseRelated(data)"><i class="el-icon-tickets"></i>Relevant</p>
@@ -26,7 +29,12 @@
<slot></slot> <slot></slot>
<span @click="EditDetail(data)" class="onlineOperationsButton"><i class="el-icon-edit"></i>Topics</span> <span @click="EditDetail(data)" class="onlineOperationsButton"><i class="el-icon-edit"></i>Topics</span>
<span @click="ChoseRelated(data)" class="onlineOperationsButton"><i class="el-icon-tickets"></i>Relevant</span> <span @click="ChoseRelated(data)" class="onlineOperationsButton"><i class="el-icon-tickets"></i>Relevant</span>
<span @click="htmlWeChatPreview(data)" class="onlineOperationsButton" v-if="['Article', 'Review', 'Mini Review'].includes(data.type)"><i class="el-icon-tickets"></i>Public Micro</span> <span
@click="htmlWeChatPreview(data)"
class="onlineOperationsButton"
v-if="['Article', 'Review', 'Mini Review'].includes(data.type)"
><i class="el-icon-tickets"></i>Public Micro</span
>
</div> </div>
<!-- 修改信息 --> <!-- 修改信息 -->
@@ -46,6 +54,29 @@
<!-- <el-button type="primary" @click="saveEdit">OK</el-button> --> <!-- <el-button type="primary" @click="saveEdit">OK</el-button> -->
</span> </span>
</el-dialog> </el-dialog>
<!-- 修改信息 -->
<el-dialog title="" :visible.sync="EditAbVisible" width="1200px" :close-on-click-modal="false">
<el-form ref="editMes" :model="detailMes" label-width="120px">
<el-form-item label="Title :">
<p v-html="detailMes.title"></p>
</el-form-item>
<div style="margin: 30px 0px 0 0">
<el-form ref="Abs_Form" :model="detailMes" label-width="150px" style="margin-top: 30px">
<el-form-item label="Abstract :" prop="abstract">
<quill-editor ref="myTextEditor" v-model="detailMes.abstract" :options="editorOption"> </quill-editor>
</el-form-item>
</el-form>
<div style="text-align: center; margin: 25px 0 0 0">
<el-button type="primary" @click="ZsSaveAbs" style="width: 300px; margin-right: 20px"> Save Abstract </el-button>
</div>
</div>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="EditAbVisible = false" plain>Cancel</el-button>
<!-- <el-button type="primary" @click="saveEdit">OK</el-button> -->
</span>
</el-dialog>
<!-- 话题信息 --> <!-- 话题信息 -->
<el-dialog title="" :visible.sync="topicVisible" width="550px"> <el-dialog title="" :visible.sync="topicVisible" width="550px">
@@ -140,6 +171,12 @@
</template> </template>
<script> <script>
import 'quill/dist/quill.core.css';
import 'quill/dist/quill.snow.css';
import 'quill/dist/quill.bubble.css';
import { quillEditor } from 'vue-quill-editor';
import commonHtmlWeChatPreview from '@/components/page/components/htmlWeChatPreview/index.vue'; import commonHtmlWeChatPreview from '@/components/page/components/htmlWeChatPreview/index.vue';
import { Loading } from 'element-ui'; import { Loading } from 'element-ui';
import { watch } from 'vue'; import { watch } from 'vue';
@@ -147,10 +184,15 @@ import { watch } from 'vue';
export default { export default {
props: ['data', 'type'], props: ['data', 'type'],
components: { components: {
commonHtmlWeChatPreview commonHtmlWeChatPreview,
quillEditor
}, },
data() { data() {
return { return {
editorOption: {
placeholder: 'Please enter...'
},
detailMes: {},
tg_article_id: 0, tg_article_id: 0,
html_type: null, html_type: null,
htmlContent: '', htmlContent: '',
@@ -242,6 +284,7 @@ export default {
}, },
HtmlMes: {}, HtmlMes: {},
EditVisible: false, EditVisible: false,
EditAbVisible: false,
RelatVisible: false, RelatVisible: false,
topicVisible: false, topicVisible: false,
HtmlVisible: false, HtmlVisible: false,
@@ -271,9 +314,13 @@ export default {
return this.baseUrl + 'api/Production/up_last_artFile'; return this.baseUrl + 'api/Production/up_last_artFile';
} }
}, },
methods: { methods: {
fresh(){ ZsSaveAbs() {
this.$emit('fresh') this.EditAbVisible = false;
},
fresh() {
this.$emit('fresh');
}, },
htmlWeChatPreview(data) { htmlWeChatPreview(data) {
console.log('data at line 189:', data); console.log('data at line 189:', data);
@@ -441,6 +488,21 @@ this.$emit('fresh')
this.EditVisible = true; this.EditVisible = true;
}, 500); }, 500);
}, },
// 稿件信息完善编辑
handleClickAb(row) {
this.detailMes.article_id = row.article_id;
this.detailMes.title = row.title;
this.detailMes.sort = row.sort;
this.detailMes.abstract = '';
this.detailMes.journal_special_id = row.journal_special_id;
// this.topListData(row.article_id);
setTimeout(() => {
this.EditAbVisible = true;
}, 500);
},
// 话题列表 // 话题列表
topListData(e) { topListData(e) {

File diff suppressed because it is too large Load Diff