Merge branch 'master' of https://git.nuttyreading.com/wangjinlei/tougao_web into Editorial-Board

This commit is contained in:
2025-11-25 09:56:37 +08:00
3 changed files with 263 additions and 239 deletions

View File

@@ -19,8 +19,8 @@ const service = axios.create({
// baseURL: 'https://submission.tmrjournals.com/', //正式 记得切换 // baseURL: 'https://submission.tmrjournals.com/', //正式 记得切换
// baseURL: 'http://www.tougao.com/', //测试本地 记得切换 // baseURL: 'http://www.tougao.com/', //测试本地 记得切换
// baseURL: 'http://192.168.110.110/tougao/public/index.php/', // baseURL: 'http://192.168.110.110/tougao/public/index.php/',
baseURL: '/api', //本地 // baseURL: '/api', //本地
// baseURL: '/', //正式 baseURL: '/', //正式
}); });

View File

@@ -173,7 +173,7 @@
<span class="el-icon-info help"></span> <span class="el-icon-info help"></span>
<div> <div>
<h4>Any questions/Help</h4> <h4>Any questions/Help</h4>
<p class="mt20">Should you encounter any issues, please feel free to contact us at {{ journalInfo.email }}</p> <p class="mt20">Should you encounter any issues, please feel free to contact us at {{ journalInfo.email }}.</p>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,6 +1,6 @@
<template> <template>
<div style="min-width: 1280px" class="articleListEditorA"> <div style="min-width: 1280px" class="articleListEditorA">
<div class="handle-box" > <div class="handle-box">
<div class="handle-item"> <div class="handle-item">
<el-select style="width: 280px" v-model="query.journal_id" @change="chageJour" placeholder="Journal" size="small"> <el-select style="width: 280px" v-model="query.journal_id" @change="chageJour" placeholder="Journal" size="small">
<el-option key="all" label="All journals" value="all"></el-option> <el-option key="all" label="All journals" value="all"></el-option>
@@ -9,15 +9,22 @@
<el-select <el-select
size="small" size="small"
v-model="query.state" v-model="query.state"
@change="getdate()" @change="changeState"
placeholder="Status" placeholder="Status"
style="width: 200px" style="width: 200px"
popper-class="state-select" popper-class="state-select"
:popper-append-to-body="true" :popper-append-to-body="true"
> >
<el-option key="all" label="processing MS" value="all"></el-option> <el-option key="all" label="processing MS" value="all"></el-option>
<el-option v-for="(item,index) in statusList" class="state-select-option" :key="item.key" :label="$t(`artstate.state${item.key}`)" :value="item.key"> </el-option> <el-option
v-for="(item, index) in statusList"
class="state-select-option"
:key="item.key"
:label="$t(`artstate.state${item.key}`)"
:value="item.key"
>
</el-option>
<!-- <el-option :key="0" :label="$t('artstate.state0')" :value="0" class="state-select-option"></el-option> <!-- <el-option :key="0" :label="$t('artstate.state0')" :value="0" class="state-select-option"></el-option>
<el-option :key="1" :label="$t('artstate.state1')" :value="1" class="state-select-option"></el-option> <el-option :key="1" :label="$t('artstate.state1')" :value="1" class="state-select-option"></el-option>
<el-option :key="2" :label="$t('artstate.state2')" :value="2" class="state-select-option"></el-option> <el-option :key="2" :label="$t('artstate.state2')" :value="2" class="state-select-option"></el-option>
@@ -30,7 +37,13 @@
<el-option :key="3" :label="$t('artstate.state3')" :value="3" class="state-select-option"></el-option> --> <el-option :key="3" :label="$t('artstate.state3')" :value="3" class="state-select-option"></el-option> -->
</el-select> </el-select>
<el-select size="small" v-model="query.country" @change="getdate()" placeholder="Please select country" style="width: 200px"> <el-select
size="small"
v-model="query.country"
@change="changeCountry"
placeholder="Please select country"
style="width: 200px"
>
<el-option key="all" label="All country" value="all"></el-option> <el-option key="all" label="All country" value="all"></el-option>
<el-option :key="1" label="China" :value="1"></el-option> <el-option :key="1" label="China" :value="1"></el-option>
<el-option :key="2" label="International" :value="2"></el-option> <el-option :key="2" label="International" :value="2"></el-option>
@@ -104,13 +117,13 @@
</b> </b>
<span style="float: right"> <span style="float: right">
<span class="labelTitle" style="font-weight: 500; font-size: 13px;">Plagiarism Check :</span> <span class="labelTitle" style="font-weight: 500; font-size: 13px">Plagiarism Check :</span>
<font style="margin-right: 16px; font-size: 13px; font-weight: 700"> {{ item.repetition }} % </font> <font style="margin-right: 16px; font-size: 13px; font-weight: 700"> {{ item.repetition }} % </font>
</span> </span>
<span style="margin: 0 10px; float: right">| </span> <span style="margin: 0 10px; float: right">| </span>
<span style="float: right"> <span style="float: right">
<span class="labelTitle" style="font-weight: 500; font-size: 13px;">Status :</span> <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"> <font style="margin-right: 15px; font-size: 13px; letter-spacing: -0.5px; font-weight: 700">
{{ stateFormat(item.state) }} {{ stateFormat(item.state) }}
</font> </font>
@@ -124,7 +137,8 @@
</el-badge> </el-badge>
</div> </div>
<div style="display: flex; width: 100%"> <div style="display: flex; width: 100%">
<span style="color: #666b7a;font-size: 13px; margin: 2px 5px 0 0; width: 65px !important; display: inline-block" <span
style="color: #666b7a; font-size: 13px; margin: 2px 5px 0 0; width: 65px !important; display: inline-block"
>Remarks :</span >Remarks :</span
> >
<font <font
@@ -154,7 +168,7 @@
<b style="font-size: 13px; letter-spacing: -0.5px; margin-right: 10px">AI scoring</b> <b style="font-size: 13px; letter-spacing: -0.5px; margin-right: 10px">AI scoring</b>
<el-popover placement="top-start" title="" width="540" trigger="hover"> <el-popover placement="top-start" title="" width="540" trigger="hover">
<span <span
style="cursor: pointer; color: #db890e; margin-right: 6px; font-weight: bold; font-size: 14px;" style="cursor: pointer; color: #db890e; margin-right: 6px; font-weight: bold; font-size: 14px"
slot="reference" slot="reference"
>{{ item.scoring }}</span >{{ item.scoring }}</span
> >
@@ -253,7 +267,7 @@
<i class="el-icon-refresh refreshBtn" @click="refreshScore(item)"></i> <i class="el-icon-refresh refreshBtn" @click="refreshScore(item)"></i>
</div> </div>
<div style="margin-top: -2px;font-size: 13px" > <div style="margin-top: -2px; font-size: 13px">
<div v-if="item.reportList.length > 0" style="text-align: left"> <div v-if="item.reportList.length > 0" style="text-align: left">
<div <div
v-for="(v, i) in item.showAll ? item.reportList : item.reportList.slice(0, 1)" v-for="(v, i) in item.showAll ? item.reportList : item.reportList.slice(0, 1)"
@@ -274,7 +288,7 @@
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
" "
>{{ v.realname || v.email ||'-' }} >{{ v.realname || v.email || '-' }}
</span> </span>
<svg <svg
@click="linkEmail(item, v.art_aut_id)" @click="linkEmail(item, v.art_aut_id)"
@@ -321,8 +335,8 @@
</div> </div>
</div> </div>
<div v-if="item.state != 0" class="reviewer_decision reviewer_decision1" style="margin-top: 0px"> <div v-if="item.state != 0" class="reviewer_decision reviewer_decision1" style="margin-top: 0px">
<div style="display: flex; align-items: center" > <div style="display: flex; align-items: center">
<div style="" v-if="item.state==6"> <div style="" v-if="item.state == 6">
<span <span
v-if="item.is_buy == 0" v-if="item.is_buy == 0"
style=" style="
@@ -363,11 +377,12 @@
</span> </span>
</div> --> </div> -->
</div> </div>
<p style="cursor: pointer; color: #006699;font-size: 13px"> <p style="cursor: pointer; color: #006699; font-size: 13px">
<span @click="loadReviewData(item)">Review decision <i class="el-icon-view"></i></span> <span @click="loadReviewData(item)">Review decision <i class="el-icon-view"></i></span>
</p> </p>
<el-button style="padding: 4px 6px !important" <el-button
style="padding: 4px 6px !important"
v-if="item.state == 6" v-if="item.state == 6"
@click="changeEnter(item)" @click="changeEnter(item)"
size="mini" size="mini"
@@ -879,7 +894,7 @@
<p v-if="currentArticleData" class="reviewer-decision-title"> <p v-if="currentArticleData" class="reviewer-decision-title">
{{ currentArticleData.title }} {{ currentArticleData.title }}
</p> </p>
<!-- <div v-if="currentArticleData&&currentArticleData.state!=0" style="overflow: hidden;"> <!-- <div v-if="currentArticleData&&currentArticleData.state!=0" style="overflow: hidden;">
<span style="float: right;"> <span style="float: right;">
@@ -889,170 +904,155 @@
</span> </span>
</div> --> </div> -->
<div class="art_author_" style="padding: 0;" v-if="reviewList.length > 0"> <div class="art_author_" style="padding: 0" v-if="reviewList.length > 0">
<div class="fixCard reviewer_decision" style="position: relative">
<div class="fixCard reviewer_decision" style="position: relative"> <div class="overflow-x-auto">
<div class="overflow-x-auto"> <!-- 上面的表格代码放在这里 -->
<!-- 上面的表格代码放在这里 -->
<table class="review_table"> <table class="review_table">
<thead> <thead>
<tr> <tr>
<th class="review_table_index">No.</th> <th class="review_table_index">No.</th>
<th>Name <span style="color: #888">( score )</span> </th> <th>Name <span style="color: #888">( score )</span></th>
<!-- 补充表头文本,原代码是空,建议加上 --> <!-- 补充表头文本,原代码是空,建议加上 -->
<th>1<sup>st</sup> review</th> <th>1<sup>st</sup> review</th>
<!-- 表头按最大重复次数遍历生成2nd、3rd...列 --> <!-- 表头按最大重复次数遍历生成2nd、3rd...列 -->
<template v-for="(_, index1) in maxRepeatReviewCount()"> <template v-for="(_, index1) in maxRepeatReviewCount()">
<th>{{ index1 + 2 }}<sup>nd</sup> review</th> <th>{{ index1 + 2 }}<sup>nd</sup> review</th>
</template> </template>
<!-- <th>final state</th> --> <!-- <th>final state</th> -->
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<!-- 遍历每个评审者 --> <!-- 遍历每个评审者 -->
<tr v-for="(iken, reviewerIndex) in reviewList"> <tr v-for="(iken, reviewerIndex) in reviewList">
<td class="review_table_index"> <td class="review_table_index">Reviewer {{ reviewerIndex + 1 }}</td>
Reviewer {{ reviewerIndex + 1 }} <td style="position: relative; cursor: pointer">
<span style="">{{ iken.realname }}</span>
<span
</td> v-if="iken.state != 0"
<td style="position: relative; cursor: pointer"> style="color: rgb(219, 137, 14); font-weight: 700; margin-left: 10px; font-size: 14px"
>( {{ iken.rated }} )</span
>
<span style="">{{ iken.realname }}</span> <span
<span v-if="iken.state != 0" v-if="iken.state != 0"
style=" style="color: #006699; float: right; margin-top: 2px"
color: rgb(219, 137, 14); @click="handleClick(iken)"
font-weight: 700; >Detail</span
margin-left: 10px; >
font-size: 14px; </td>
" <!-- 1st review原逻辑不变 -->
>( {{ iken.rated }} )</span <td style="cursor: pointer">
> <span style="display: inline-block; margin-left: 4px; margin-right: 8px">
<span v-if="iken.state != 0" <font
style="color: #006699;float: right;margin-top: 2px" v-if="iken.recommend == 1 || iken.recommend == 2"
@click="handleClick(iken)" style="
>Detail</span width: 12px;
> height: 12px;
</td> display: block;
<!-- 1st review原逻辑不变 --> border-radius: 10px;
<td style="cursor: pointer"> background-color: #67c23a;
<span style="display: inline-block; margin-left: 4px; margin-right: 8px"> "
<font >
v-if="iken.recommend == 1 || iken.recommend == 2" </font>
style=" <font
width: 12px; v-if="iken.recommend == 3 || iken.recommend == 4"
height: 12px; style="
display: block; width: 12px;
border-radius: 10px; height: 12px;
background-color: #67c23a; display: block;
" border-radius: 10px;
> background-color: #f56c6c;
</font> "
<font >
v-if="iken.recommend == 3 || iken.recommend == 4" </font>
style=" <font
width: 12px; v-if="iken.state == 0"
height: 12px; style="
display: block; width: 12px;
border-radius: 10px; height: 12px;
background-color: #f56c6c; display: block;
" border-radius: 10px;
> background-color: #ccc;
</font> "
<font >
v-if="iken.state == 0" </font>
style=" </span>
width: 12px; <span v-if="iken.recommend == 1">Minor</span>
height: 12px; <span v-else-if="iken.recommend == 2">Major</span>
display: block; <span v-else-if="iken.recommend == 3">reject and resubmission</span>
border-radius: 10px; <span v-else-if="iken.recommend == 4">Reject</span>
background-color: #ccc; </td>
" <!-- 关键按最大重复次数遍历而非仅遍历当前iken.repeat -->
> <template v-for="(_1, index1) in maxRepeatReviewCount()">
</font> <td>
</span> <!-- 补全逻辑判断当前评审者的repeat中是否有第index1条数据 -->
<span v-if="iken.recommend == 1">Minor</span> <span
<span v-else-if="iken.recommend == 2">Major</span> v-if="Array.isArray(iken.repeat) && iken.repeat[index1]"
<span v-else-if="iken.recommend == 3">reject and resubmission</span> style="cursor: pointer"
<span v-else-if="iken.recommend == 4">Reject</span> @click="handleClick(iken)"
</td> >
<!-- 关键按最大重复次数遍历而非仅遍历当前iken.repeat --> <span style="display: inline-block; margin-left: 4px; margin-right: 8px">
<template v-for="(_1, index1) in maxRepeatReviewCount()"> <font
<td> v-if="iken.repeat[index1].recommend == 1"
<!-- 补全逻辑判断当前评审者的repeat中是否有第index1条数据 --> style="
<span width: 12px;
v-if="Array.isArray(iken.repeat) && iken.repeat[index1]" height: 12px;
style="cursor: pointer" display: block;
@click="handleClick(iken)" border-radius: 10px;
> background-color: #67c23a;
<span style="display: inline-block; margin-left: 4px; margin-right: 8px"> "
<font >
v-if="iken.repeat[index1].recommend == 1" </font>
style=" <font
width: 12px; v-if="iken.repeat[index1].recommend == 2"
height: 12px; style="
display: block; width: 12px;
border-radius: 10px; height: 12px;
background-color: #67c23a; display: block;
" border-radius: 10px;
> background-color: #f56c6c;
</font> "
<font >
v-if="iken.repeat[index1].recommend == 2" </font>
style=" <font
width: 12px; v-if="iken.repeat[index1].recommend == 3"
height: 12px; style="
display: block; width: 12px;
border-radius: 10px; height: 12px;
background-color: #f56c6c; display: block;
" border-radius: 10px;
> background-color: #006699;
</font> "
<font >
v-if="iken.repeat[index1].recommend == 3" </font>
style=" </span>
width: 12px; <!-- 有数据按原逻辑显示Accept/Reject等 -->
height: 12px; <span v-if="iken.repeat[index1].recommend == 1">Accept</span>
display: block; <span v-else-if="iken.repeat[index1].recommend == 2">Reject</span>
border-radius: 10px; <span v-else-if="iken.repeat[index1].recommend == 3">Revision</span>
background-color: #006699; <span v-else>No reply</span>
" </span>
> <span v-else>
</font> <!-- 无数据:补全空内容(可自定义为“-”“无”等) -->
</span>
<!-- 有数据按原逻辑显示Accept/Reject等 --> <span>-</span>
<span v-if="iken.repeat[index1].recommend == 1">Accept</span> </span>
<span v-else-if="iken.repeat[index1].recommend == 2">Reject</span> </td>
<span v-else-if="iken.repeat[index1].recommend == 3">Revision</span> </template>
<span v-else>No reply</span> </tr>
</span> </tbody>
<span v-else> </table>
<!-- 无数据:补全空内容(可自定义为“-”“无”等) --> </div>
</div>
<span >-</span> </div>
<div v-if="currentArticleData && currentArticleData.state != 0" style="overflow: hidden">
</span> <span style="float: right">
</td>
</template>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div v-if="currentArticleData&&currentArticleData.state!=0" style="overflow: hidden;">
<span style="float: right;">
<span style="font-size: 14px; margin-top: 10px; margin-right: 10px; text-align: right; font-weight: 400"> <span style="font-size: 14px; margin-top: 10px; margin-right: 10px; text-align: right; font-weight: 400">
Average score : <b style="font-size: 18px; color: #db890e">{{ avegeCount(reviewList) }}</b> Average score : <b style="font-size: 18px; color: #db890e">{{ avegeCount(reviewList) }}</b>
</span> </span>
</span> </span>
</div>
</div>
</div> </div>
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
@@ -1074,46 +1074,37 @@ export default {
components: { components: {
timetalk, timetalk,
commonRemarkList, commonRemarkList,
articleEditorDetail, articleEditorDetail
}, },
props: ['journals'], props: ['journals'],
data() { data() {
return { return {
statusList:[ currentSearchForm: {},
statusList: [
{ {
key:0, key: 0
}, },
{ {
key:1, key: 1
}, },
{ {
key:2, key: 2
}, },
{ {
key:4, key: 4
}, },
{ {
key:8, key: 8
}, },
{ {
key:6, key: 6
}, },
{ {
key:5, key: 5
}, },
{ {
key:3, key: 3
}
},
], ],
reviewList: [], reviewList: [],
finalList: [], finalList: [],
@@ -1716,7 +1707,7 @@ export default {
}; };
} }
this.aiReview[0] = aiReview; this.aiReview[0] = aiReview;
}) })
.catch((err) => { .catch((err) => {
loading.close(); loading.close();
this.$message.error('AI analysis failed'); this.$message.error('AI analysis failed');
@@ -1748,8 +1739,7 @@ export default {
} else { } else {
this.creatAI(data, i, loading); this.creatAI(data, i, loading);
} }
})
})
.catch((err) => { .catch((err) => {
loading.close(); loading.close();
// this.$message.error('AI analysis failed'); // this.$message.error('AI analysis failed');
@@ -1892,7 +1882,7 @@ export default {
}) })
.then((res) => { .then((res) => {
console.log(res); console.log(res);
this.getdate(); this.getdate(this.currentSearchForm);
}) })
.catch((err) => { .catch((err) => {
console.log(err); console.log(err);
@@ -1909,32 +1899,46 @@ export default {
} }
}); });
}, },
changeCountry() {
this.currentSearchForm={}
this.query.title='';
this.query.accept_sn='';
this.query.page=1;
this.query.size=20;
this.$forceUpdate()
this.getdate();
},
// 改变期刊 // 改变期刊
chageJour() { chageJour() {
this.currentSearchForm={}
this.query.title='';
this.query.accept_sn='';
this.query.page=1;
this.query.size=20
this.$forceUpdate()
this.getdate(); this.getdate();
// this.$api
// .post('api/Special/getSpecial', {
// journal_id: this.query.journal_id
// })
// .then((res) => {
// this.itemGuest = res.data.specials;
// this.query.special_num = 0;
// this.getdate();
// })
// .catch((err) => {
// console.log(err);
// });
}, },
// 改变状态 // 改变状态
changeState() { changeState() {
if (this.query.act == 1) { // if (this.query.act == 1) {
this.statList = [0, 1, 2, 4, 6]; // this.statList = [0, 1, 2, 4, 6];
this.query.state = 0; // this.query.state = 0;
} else { // } else {
this.statList = [3, 5]; // this.statList = [3, 5];
this.query.state = 3; // this.query.state = 3;
} // }
this.currentSearchForm={}
this.query.title='';
this.query.accept_sn='';
this.query.page=1;
this.query.size=20
this.$forceUpdate()
this.getdate(); this.getdate();
}, },
handleReset() { handleReset() {
this.query = { this.query = {
@@ -1953,10 +1957,34 @@ export default {
}, },
handleSearch1(type) { handleSearch1(type) {
if (type == 'title') { if (type == 'title') {
this.query = {
account: localStorage.getItem('U_name'),
journal_id: 'all',
accept_sn: '',
title: this.query.title,
state: 'all',
country: 'all',
page: 1,
size: 20
};
this.getdate({ this.getdate({
title: this.query.title title: this.query.title
}); });
} else if (type == 'accept_sn') { } else if (type == 'accept_sn') {
this.query = {
account: localStorage.getItem('U_name'),
journal_id: 'all',
accept_sn: this.query.accept_sn,
title: '',
state: 'all',
country: 'all',
page: 1,
size: 20
};
this.getdate({ this.getdate({
accept_sn: this.query.accept_sn accept_sn: this.query.accept_sn
}); });
@@ -1964,7 +1992,7 @@ export default {
}, },
// 获取数据 // 获取数据
async getdate(options) { async getdate(options) {
console.log('options at line 1917:', options) console.log('options at line 1917:', options);
const loading = this.$loading({ const loading = this.$loading({
lock: true, lock: true,
text: 'Loading...', text: 'Loading...',
@@ -1977,21 +2005,19 @@ export default {
} else { } else {
data = { data = {
account: this.query.account, account: this.query.account,
size: this.query.size, size: this.query.size,
page: this.query.page page: this.query.page
}; };
} }
this.currentSearchForm = { ...data };
if (this.query.state != 'all') { if (this.query.state != 'all') {
data.state = this.query.state; data.state = this.query.state;
data.state = this.query.state;
} }
if (this.query.journal_id != 'all') { if (this.query.journal_id != 'all') {
data.journal_id = this.query.journal_id; data.journal_id = this.query.journal_id;
} }
if (this.query.country != 'all') { if (this.query.country != 'all') {
data.country = this.query.country; data.country = this.query.country;
} }
this.$api this.$api
.post('api/Workbench/lists', data) .post('api/Workbench/lists', data)
@@ -2059,7 +2085,6 @@ export default {
}); });
// 新开窗口跳转(第二个参数 '_blank' 表示新窗口) // 新开窗口跳转(第二个参数 '_blank' 表示新窗口)
window.open(routeData.href, '_blank'); window.open(routeData.href, '_blank');
}, },
articleEditorialBoard(row) { articleEditorialBoard(row) {
this.$router.push({ this.$router.push({
@@ -3179,7 +3204,6 @@ export default {
.articleBaseInfo .labelTitle { .articleBaseInfo .labelTitle {
color: #333; color: #333;
font-weight: bold; font-weight: bold;
} }
.articleTopBaseInfo .labelTitle { .articleTopBaseInfo .labelTitle {
color: #fff !important; color: #fff !important;
@@ -3338,7 +3362,7 @@ td {
margin-left: auto; margin-left: auto;
flex-wrap: nowrap; flex-wrap: nowrap;
width: 100%; width: 100%;
justify-content: space-around justify-content: space-around;
} }
.reportIcon { .reportIcon {
float: left; float: left;
@@ -3387,12 +3411,12 @@ td {
border: 1px solid #ed444494 !important; border: 1px solid #ed444494 !important;
} }
.sticky-header { .sticky-header {
position: sticky; position: sticky;
top: -10px; top: -10px;
z-index: 999; z-index: 999;
background: #fff; background: #fff;
padding: 10px 0 0; padding: 10px 0 0;
border-bottom: 1px solid #f0f0f0; border-bottom: 1px solid #f0f0f0;
/* box-shadow: 0 2px 8px rgba(0,0,0,0.1); */ /* box-shadow: 0 2px 8px rgba(0,0,0,0.1); */
} }
</style> </style>