This commit is contained in:
2025-11-17 17:00:14 +08:00
parent a4eaf0d5cb
commit ef0e8e83e0
40 changed files with 10582 additions and 3381 deletions

View File

@@ -8,8 +8,8 @@
</div>
<div class="container">
<el-row :gutter="10">
<el-col :span="16">
<div class="form-box">
<el-col :span="20">
<div class="form-box" style="width: 100%;">
<el-form ref="articleform" :model="detailDate" label-width="130px">
<el-form-item label="Article">
<span>{{ detailDate.article }}</span>
@@ -23,15 +23,176 @@
<el-form-item label="CreateTime">
<span>{{ formatDate(detailDate.ctime) }}</span>
</el-form-item>
<el-form-item label="Status">
<el-form-item label="Disclose name or anonymous" label-width="200px">
<span v-if="reviewList.length > 0&&reviewList[0].is_anonymous == 0">Disclose name</span>
<span v-if="reviewList.length > 0&&reviewList[0].is_anonymous == 1">Remain anonymous</span>
</el-form-item>
<!-- <el-form-item label="Status">
<span>{{ mystate(detailDate.state) }}</span>
<el-button style="margin-left: 10px" type="text" @click="dialogFormVisible = true" icon="el-icon-view"
>See Feedback</el-button
>
</el-form-item>
</el-form-item> -->
<el-form-item v-if="canRepeat == 1">
<el-button type="primary" @click="createRevision">Re-review</el-button>
</el-form-item>
<div v-if="reviewList.length > 0" style="margin-top: 40px;">
<div class="clearfix fsheader">
<h4>Peer-review Archive</h4>
</div>
<!-- 初审 -->
<div class="art_author_">
<div class="fixCard reviewer_decision" style="position: relative">
<div class="overflow-x-auto">
<table class="review_table">
<thead>
<tr>
<th></th>
<!-- 表头遍历评审者 -->
<template v-for="(iken, reviewerIndex) in reviewList">
<th>Status
</th>
<th>Time
</th>
<th>Response time
</th>
<th>Comments
</th>
</template>
</tr>
</thead>
<tbody>
<!-- 遍历评审轮次1st + 重复轮次 -->
<tr >
<td>1<sup>st</sup> review</td>
<!-- 遍历每个评审者的1st评审结果 -->
<template v-for="(iken, reviewerIndex) in reviewList">
<td style="cursor: pointer;">
<span style="display: inline-block; margin-left: 4px; margin-right: 8px">
<font
v-if="iken.recommend == 1 || iken.recommend == 2"
style="
width: 12px;
height: 12px;
display: block;
border-radius: 10px;
background-color: #67c23a;
"
>
</font>
<font
v-if="iken.recommend == 3|| iken.recommend == 4"
style="
width: 12px;
height: 12px;
display: block;
border-radius: 10px;
background-color: #f56c6c;
"
>
</font>
</span>
<span v-if="iken.recommend == 1">Minor</span>
<span v-else-if="iken.recommend == 2">Major</span>
<span v-else-if="iken.recommend == 3">reject and resubmission</span>
<span v-else-if="iken.recommend == 4">Reject</span>
</td>
<td>
<p style="line-height: 30px;" v-if="iken.ctime > 0">{{ iken.ctime | formatDatehms }}</p>
<p v-else style="" class="stime">Response time: Re-reviewing...</p>
</td> <td></td>
<td style="">
<el-button
style="margin-left: 10px"
type="text"
@click="showUnderReview(iken.question)"
icon="el-icon-view"
>Details</el-button
>
</td>
</template>
</tr>
<!-- 遍历重复评审轮次2nd3rd... -->
<template v-for="(round, index1) in maxRepeatReviewCount()">
<tr>
<td>{{ index1 + 2 }}<sup>nd</sup> review</td>
<!-- 遍历每个评审者在该轮次的结果 -->
<template v-for="(iken, reviewerIndex) in reviewList">
<td style="">
<span style="cursor: pointer"
v-if="Array.isArray(iken.repeat) && iken.repeat[index1]"
>
<span style="display: inline-block; margin-left: 4px; margin-right: 8px">
<font
v-if="iken.repeat[index1].recommend == 1"
style="
width: 12px;
height: 12px;
display: block;
border-radius: 10px;
background-color: #67c23a;
"
>
</font>
<font
v-if="iken.repeat[index1].recommend == 2"
style="
width: 12px;
height: 12px;
display: block;
border-radius: 10px;
background-color: #f56c6c;
"
>
</font>
<font
v-if="iken.repeat[index1].recommend == 3"
style="
width: 12px;
height: 12px;
display: block;
border-radius: 10px;
background-color: #006699;
"
>
</font>
</span>
<span v-if="iken.repeat[index1].recommend == 1">Accept</span>
<span v-else-if="iken.repeat[index1].recommend == 2">Reject</span>
<span v-else-if="iken.repeat[index1].recommend == 3">Revision</span>
<span v-else>No reply</span>
</span>
<span v-else>-</span>
</td>
<td>
<p style="line-height: 30px;" v-if="iken.repeat[index1].ctime > 0">{{ iken.repeat[index1].ctime | formatDatehms }}</p>
</td>
<td><p style="line-height: 30px;" v-if="iken.repeat[index1].stime > 0">{{ iken.repeat[index1].stime | formatDatehms }}</p>
<p v-else style="" class="stime">Re-reviewing...</p></td>
<td>
<el-button v-if="[1,2,3].includes(iken.repeat[index1].recommend)"
style="margin-left: 10px"
type="text"
@click="showSecondReview(iken.repeat[index1].question)"
icon="el-icon-view"
>Details</el-button
>
</td>
</template>
</tr>
</template>
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- <el-form-item label="Article file">
<el-popover placement="right" width="350" trigger="click">
<el-table :data="articlefileList">
@@ -751,6 +912,7 @@ export default {
FdialogFormVisible: false,
dialogFormVisible1: false,
recordList: [],
reviewList: [],
journal_id: null,
baseUrl: this.Common.baseUrl,
mediaUrl: this.Common.mediaUrl,
@@ -812,11 +974,44 @@ export default {
created: function () {
this.getDate();
this.initFileList();
this.initquesion();
this.getHistoryList();
},
computed: {},
methods: {
maxRepeatReviewCount() {
if (!this.reviewList || !Array.isArray(this.reviewList)) return null; // 边界处理无数据返回null
// 遍历所有评审者找到repeat数组长度最大的那条数据
const maxItem = this.reviewList.reduce((maxItem, currentItem) => {
// 计算当前项的repeat长度非数组则视为0
const currentLen = Array.isArray(currentItem.repeat) ? currentItem.repeat.length : 0;
// 计算当前最大项的repeat长度非数组则视为0
const maxLen = Array.isArray(maxItem.repeat) ? maxItem.repeat.length : 0;
// 如果当前项长度更大,则更新最大项
return currentLen > maxLen ? currentItem : maxItem;
}, {}); // 初始值设为一个空对象
// console.log('maxItem at line 2142:', maxItem.repeat.length)
return maxItem && maxItem.repeat ? maxItem.repeat.length : 0;
},
getReviewList() {
this.$api
.post('api/Finalreview/getArticleFinalReview', {
article_id: this.articleId
})
.then(async (res) => {
if (res.status == 1) {
if (res.status == 1) {
// this.reviewList = res.data.review.filter(e=>e.art_rev_id==this.questionform.art_rev_id);
}
}
})
.catch((err) => {});
},
// 显示复审对话框
showSecondReview(item) {
this.FdialogFormVisible = true;
@@ -853,18 +1048,73 @@ export default {
this.FdialogFormVisible = false;
this.ReReviewQuestion = {};
},
// 2. 定义所有必需字段(确保所有数据结构统一)
// 3. 核心函数:提取第一个元素,剩余放入 repeat
splitQuestion(questionArr = []) {
const requiredFields = [
'rev_qu_id', 'art_rev_id', 'type',
'art_rev_rep_id', 'recommend', 'score', 'state',
'reviewer_id', 'realname', 'ctime', 'stime','is_anonymous'
];
// 解构数组firstItem 取第一个元素restItems 取剩余所有元素
const [firstItem = {}, ...restItems] = questionArr;
// 工具函数:补全单个对象的必需字段(空值用 null 填充)
const completeFields = (item) => {
console.log('item at line 1056:', item)
const result = {question:item};
requiredFields.forEach(field => {
result[field] = item[field] ? item[field]: '';
});
return result;
};
// 补全第一个元素的字段
const firstCompleted = completeFields(firstItem);
// 补全剩余元素的字段,存入 repeat 数组
const repeat = restItems.map(item => completeFields(item));
// 返回结果:按需选择格式(二选一)
return {...firstCompleted, repeat: repeat}
},
// 获取历史审稿列表
getHistoryList() {
async getHistoryList() {
this.loading = true;
this.$api
.post('api/Reviewer/getReviewerRepeatDetail', {
art_rev_id: this.$route.query.id
})
.then((res) => {
.then(async(res) => {
this.loading = false;
if (res.code == 0) {
// this.reviewList=[{...res.data.art_rev_info}]
if (res.data.art_rev_info.question && res.data.art_rev_info.question[0] != null) {
this.recordList = res.data.art_rev_info.question.reverse();
// 4. 调用函数得到结果
this.reviewList = [await this.splitQuestion(res.data.art_rev_info.question)];
if(this.reviewList.length>0){
this.$api
.post('api/Workbench/updateArticleState', {
article_id: res.data.article_info.article_id,
act_p_id: this.$route.query.id,
type: '1,2',
account: localStorage.getItem('U_name')
})
}
console.log('at line 1094:', this.reviewList)
// this.recordList = res.data.art_rev_info.question.reverse();
}
} else {
this.$message.error(res.msg);
@@ -937,6 +1187,7 @@ export default {
this.canRepeat = res.can_repeat;
this.journal_id = res.journal_id;
this.articleId = res.article_id;
this.getReviewList()
})
.catch((err) => {
console.log(err);
@@ -1039,6 +1290,15 @@ export default {
this.$message.error('服务器上传错误' + res.msg);
}
},
handleClick(item) {
console.log('item at line 1228:', item);
this.$router.push({
path: 'articleReviewerDetail',
query: {
id: item.art_rev_id
}
});
},
formatDate(timestamp) {
var date = new Date(timestamp * 1000); //时间戳为10位需*1000时间戳为13位的话不需乘1000
var Y = date.getFullYear() + '-';
@@ -1101,5 +1361,41 @@ export default {
}
::v-deep .el-dialog__body{
padding: 10px 20px 20px !important;
}.review_table {
width: 100%;
background-color: #fff;
/* margin-top: 10px; */
border-collapse: collapse; /* 合并表格边框 */
}
.review_table th,
td {
padding: 6px;
min-width: 70px;
border: 1px solid #ddd;
text-align: left;
}
.review_table th {
font-size: 14px;
background-color: #f0f0f0;
}
.review_table td {
font-size: 14px;
/* background-color: #f0f0f0; */
}
.review_table th:first-child, .review_table td:first-child {
width: 100px;
/* 内容过长时自动换行 */
word-wrap: break-word;
/* 强制在单词内换行(针对长单词) */
word-break: break-all;
}
.review_table tr:hover {
/* background-color: #fff; */
}
.overflow-x-auto {
overflow-x: auto;
}
</style>