This commit is contained in:
2025-11-03 10:14:27 +08:00
parent 4dd5fa6a42
commit b66b390f2c
16 changed files with 5902 additions and 1186 deletions

View File

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

View File

@@ -2,8 +2,8 @@
//记得切换
//正式
// const mediaUrl = '/public/';
// const baseUrl = '/';
const mediaUrl = '/public/';
const baseUrl = '/';
// const mediaUrl = 'https://submission.tmrjournals.com/public/';
// // const mediaUrl = 'http://zmzm.tougao.dev.com/public/';
@@ -11,9 +11,9 @@
//本地(正式环境 )
const mediaUrl = 'https://submission.tmrjournals.com/public/';
// const mediaUrl = 'https://submission.tmrjournals.com/public/';
const baseUrl = '/api';
// const baseUrl = '/api';
//晓玲
// const mediaUrl = 'http://zmzm.tougao.dev.com/public/';

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -493,6 +493,7 @@
<tr v-for="(iken, reviewerIndex) in reviewList">
<td style="position: relative; cursor: pointer">
Reviewer {{ reviewerIndex + 1 }} <span style="color: rgb(219, 137, 14);font-weight: 700;margin-left: 10px;font-size: 14px">( {{ iken.rated }} )</span>
<span style="margin-left: 10px;">{{ iken.realname }}</span>
<span
style="color: #006699; position: absolute; right: 10px; top: 10px"
@click="handleClick(iken)"

View File

@@ -344,7 +344,7 @@
<!-- 文件上传 -->
<div :ref="tabsList[2].refName" class="scroll-item">
<div class="bor_style_onli">
<div class="bor_style_onli" style="height: auto !important;max-height: 700px">
<h4>{{ tabsList[2].name }}</h4>
<el-form label-width="220px">
<el-form-item label="SUB File Upload :">
@@ -514,7 +514,7 @@
<!-- 参考文献 -->
<div :ref="tabsList[3].refName" class="scroll-item">
<div class="bor_style_onli">
<div class="bor_style_onli" >
<h4>{{ tabsList[3].name }}</h4>
<PreIngestedEditorProduce
type="produce"
@@ -649,7 +649,7 @@
<!-- Html排版 -->
<div :ref="tabsList[4].refName" class="scroll-item">
<div class="bor_style_onli">
<div class="bor_style_onli" style="height: auto !important;max-height: 700px">
<h4>{{ tabsList[4].name }}</h4>
<div>
<p style="color: #606266; font-size: 14px; line-height: 21px; margin-bottom: 15px">HTML typesetting and AI proofreading</p>

View File

@@ -1267,12 +1267,7 @@ export default {
}).href,
'_blank'
);
// this.$router.push({
// path: '/GenerateCharts',
// query: {
// id: this.tg_article_id
// }
// });
}
},
htmlLayout() {

View File

@@ -1,126 +1,198 @@
// 关键:让 condition 接收当前表单 f
var stepStatus=[]
// 状态说明:
// 0: 未完成(校验未通过)
// 1: 已完成且已保存(校验通过 + 已保存)
// 2: 正在填写(部分字段填写,但未通过校验)
// 3: 已通过校验但未保存(校验通过 + 未保存)
import { t } from "vxe-table";
var stepStatus = [];
var stepFields = {
// 保持原有字段配置不变...
1: [
{ field: 'journal', required: true },
{ field: 'type', required: true },
{ field: 'manuscirpt', required: true },
{ field: 'title', required: true },
{ field: 'approval', required: true },
// ✅ 这里改:用 (f)=> f.approval === 0
{ field: 'approval_content', required: false, condition: (f) => f.approval === 0 },
{ field: 'approval_file', required: false, condition: (f) => f.approval === 1 },
{ field: 'abstrart', required: true },
{ field: 'majorValueList', required: false, check: (f) => Array.isArray(f.majorValueList) && f.majorValueList.length > 0 }
],
2: [
{ field: 'authorList', required: true, check: (f) => Array.isArray(f.authorList) && f.authorList.length > 0 },
{ field: 'authorEmail', required: true, check: (f) => f.authorList.every(a => a.email) },
{ field: 'authorFirstname', required: true, check: (f) => f.authorList.every(a => a.firstname) },
{ field: 'authorLastname', required: true, check: (f) => f.authorList.every(a => a.lastname) },
{ field: 'authorEmail', required: true, check: (f) => f.authorList.every(a => a.email && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(a.email)) },
{ field: 'authorTitle', required: true, check: (f) => f.authorList.every(a => a.title) },
{ field: 'authorAffiliation', required: true, check: (f) => f.authorList.every(a => a.company) },
{ field: 'authorCountry', required: true, check: (f) => f.authorList.every(a => a.country) },
{ field: 'isSuper', required: true, check: (f) => f.authorList.some(a => a.isSuper) },
{ field: 'isReport', required: true, check: (f) => f.authorList.some(a => a.isReport) }
{ field: 'isReport', required: true, check: (f) => f.authorList.some(a => a.isReport) },
{ field: 'authorAddress', required: false, condition: (f) => f.isReport == 1 },
],
3: [
{ field: 'coverLetter', required: true },
{ field: 'picturesAndTables', required: true },
{ field: 'supplementary', required: false }
{ field: 'manuscirpt', required: true },
{ field: 'is_figure_copyright', required: true },
{ field: 'figurecopyright_file', required: true, condition: (f) => f.is_figure_copyright == 1 },
{ field: 'is_use_ai', required: true },
{ field: 'use_ai_explain', required: false, condition: (f) => f.is_use_ai == '1' },
],
4: [
{ field: 'istransfer', required: true },
{ field: 'checkedjours', required: false, condition: (f) => !!f.istransfer },
{ field: 'becomeRev', required: true },
// 注意this.usercap 在这里可能没有 this 环境,建议改成从 form 里取,如 f.usercap
{ field: 'reviewerInfo', required: false, condition: (f) => f.becomeRev && !(Array.isArray(f.usercap) && f.usercap.includes('reviewer')) },
{ field: 'qualification', required: true },
{ field: 'qualificationFile', required: false, condition: (f) => f.qualification === '2' },
{ field: 'isUseAi', required: true },
{ field: 'useAiExplain', required: false, condition: (f) => f.isUseAi === '1' },
{ field: 'agreechecked', required: true }
{ field: 'majorValueList', required: false, check: (f) => Array.isArray(f.majorValueList) && f.majorValueList.length > 0 },
{
field: 'majorValueListSelectValue',
required: true,
check: (f) => f.majorValueList.every(a => a.selectedValue !== null && Array.isArray(a.selectedValue) && a.selectedValue.length > 0&&a.selectedValue[0]!=null)
},
// { field: 'istransfer', required: true },
// { field: 'checkedjours', required: false, condition: (f) => !!f.istransfer },
// { field: 'becomeRev', required: true },
// { field: 'reviewerInfo', required: false, condition: (f) => f.becomeRev && !(Array.isArray(f.usercap) && f.usercap.includes('reviewer')) },
// { field: 'qualification', required: true },
]
};
async function updateStepStatus(formInput) {
const form = { ...formInput }; // 使用局部 form避免被外部覆盖
console.log('form at line 43:', form)
stepStatus = [
{ step: 1, status: '0' },
{ step: 2, status: '0' },
{ step: 3, status: '0' },
{ step: 4, status: '0' }
// 新增:记录每个步骤是否已保存(可从外部传入或本地存储)
var stepSavedStatus = {
1: false, // 步骤1是否已保存
2: false,
3: false,
4: false
};
export async function updateStepStatus(formInput,saveList) {
const form = { ...formInput };
console.log('form at line 66:', form)
if(!saveList){
saveList = [];
}else if(!Array.isArray(saveList)){
saveList = [];
}else{
for(let i = 1;i<=4;i++){
stepSavedStatus[i] = saveList.includes(i);
}
}
stepStatus = [
{ step: 1, status: '0', isSaved: stepSavedStatus[1] }, // 新增isSaved字段
{ step: 2, status: '0', isSaved: stepSavedStatus[2] },
{ step: 3, status: '0', isSaved: stepSavedStatus[3] },
{ step: 4, status: '0', isSaved: stepSavedStatus[4] }
];
function checkField(field) {
// 1) 条件非必填:若没有 required 且没有 condition直接通过
if (!field.required && !field.condition) return true;
// 2) 有 condition若条件不满足即不需要填直接通过
if (typeof field.condition === 'function' && !field.condition(form)) {
return true;
}
// 3) 自定义检查:优先
if (typeof field.check === 'function') {
return field.check(form);
}
// 4) 常规值检查
const value = form[field.field];
// null/undefined -> 未填
if (value === undefined || value === null) return false;
// 数组 -> 必须非空
if (Array.isArray(value)) return value.length > 0;
// 字符串 -> 非空白
if (typeof value === 'string') return value.trim() !== '';
// 数字 -> 只要有值即可0 也算已填)
if (typeof value === 'number') return true;
// 布尔 -> 只要存在即可
if (typeof value === 'boolean') return true;
// 文件或对象:简单规则,存在即视为已填(可按需加更细规则)
if (typeof value === 'object') return true;
// 其他类型默认未填
return false;
}
function checkStepStatus(step) {
const fields = stepFields[step];
let allFilled = true;
let hasFilled = false;
let allFilled = true;
let hasFilled = false;
for (const field of fields) {
const isFilled = checkField(field);
console.log('isFilled at line 101:', isFilled,'++++++++++',field.field)
if (!isFilled) {
allFilled = false;
} else {
hasFilled = true;
}
}
//0 未完成 1已完成 2正在填写
if (allFilled) return '1';
if (hasFilled) return '2';
return '0';
}
for (let i = 1; i <= 4; i++) {
if (i !== 2) {
stepStatus[i - 1].status = await checkStepStatus(i);
} else if (i === 2 && Array.isArray(form.authorList)&&form.authorList.length>0) {
console.log('form.authorList at line 115:', form.authorList)
stepStatus[i - 1].status = await checkStepStatus(i);
const isSaved = stepSavedStatus[step];
if (allFilled) {
return isSaved ? '1' : '3'; // 校验通过已保存1未保存3
} else {
return hasFilled ? '2' : '0'; // 校验未通过部分填写2未填写0
}
}
return stepStatus;
// 更新步骤状态
for (let i = 1; i <= 4; i++) {
if (i !== 2) {
stepStatus[i - 1].status = await checkStepStatus(i);
} else if (i === 2 && Array.isArray(form.authorList) && form.authorList.length > 0) {
stepStatus[i - 1].status = await checkStepStatus(i);
}
// 同步更新isSaved从全局保存状态获取
stepStatus[i - 1].isSaved = stepSavedStatus[i];
}
let targetStep = null;
const stepList = stepStatus;
for (const step of stepList) {
if (Number(step.status) === 0) {
targetStep = step;
break;
}
}
if (!targetStep) {
for (const step of stepList) {
if (Number(step.status) === 2) {
targetStep = step;
break;
}
}
}
if (!targetStep) {
for (const step of stepList) {
if (Number(step.status) === 3) {
targetStep = step;
break;
}
}
}
if (!targetStep) {
targetStep = [...stepList].sort((a, b) => Number(a.step) - Number(b.step)).pop();
}
console.log("目标步骤:", targetStep);
return { list: stepStatus, current: targetStep };
}
export function markStepAsSaved(step) {
if (Number.isInteger(step) && step >= 1 && step <= 4) {
stepSavedStatus[step] = true;
console.log(`步骤 ${step} 已标记为已保存`);
} else {
console.warn(`无效的步骤号:${step}必须是1-4的整数`);
}
}
/**
* 新增:标记步骤为未保存(补充反向操作)
* @param {number} step - 步骤号1-4
*/
export function markStepAsUnsaved(step) {
if (Number.isInteger(step) && step >= 1 && step <= 4) {
stepSavedStatus[step] = false;
console.log(`步骤 ${step} 已标记为未保存`);
} else {
console.warn(`无效的步骤号:${step}必须是1-4的整数`);
}
}
export default updateStepStatus;

View File

@@ -75,6 +75,11 @@ export default {
type: Array,
default: () => []
},
journal_id: {
type: Number,
default: 0
},
check_item: {
type: Object,
default: () => ({})
@@ -97,6 +102,15 @@ export default {
},
deep: true
},
journal_id: {
handler(newVal) {
if (this.journal_id) {
this.init(this.journal_id);
}
},
deep: true
},
check_item: {
handler(newVal) {
// if (newVal.id) {
@@ -118,7 +132,7 @@ export default {
} else {
this.selectedJournal = null;
}
console.log('this.selectedJournal at line 142:', this.selectedJournal);
},
deep: true
}
@@ -143,7 +157,7 @@ export default {
methods: {
getJournalList() {
this.journals = this.$store.state.journalList;
console.log('this.journals at line 145:', this.journals);
this.$forceUpdate();
},
closeSelection() {
@@ -192,11 +206,15 @@ export default {
},
mounted() {
console.log('at line 194:初始化' )
this.$nextTick(() => {
this.getJournalList();
});
console.log('this.journal_id at line 203:', this.journal_id)
if (this.journal_id) {
this.init(this.journal_id);
}
document.addEventListener('click', this.handleClickOutside);
},
activated() {

View File

@@ -189,7 +189,16 @@
})
.then(res => {
if (res.code == 0) {
this.$router.push('/per_text?Art_id=' + index);
window.open(
this.$router.resolve({
path: '/per_text',
query: {
Art_id: index
}
}).href,
'_blank'
);
// this.$router.push('/per_text?Art_id=' + index);
} else {
this.$message.error(res.msg);
}
@@ -271,7 +280,16 @@
.then(res => {
if (res.code == 0) {
this.$message.success('Successful application!');
this.$router.push('/per_text?Art_id=' + res.data.art_rev_id);
window.open(
this.$router.resolve({
path: '/per_text',
query: {
Art_id: res.data.art_rev_id
}
}).href,
'_blank'
);
// this.$router.push('/per_text?Art_id=' + res.data.art_rev_id);
} else {
this.$message.error(res.msg);
}

View File

@@ -25,12 +25,12 @@
<ul class="ta1_uli ta1_ulicad">
<li v-for="(item,index) in tableData1">
<!-- <h5>{{item.type}}</h5> -->
<router-link :to="{path:'/per_text',query:{Art_id:item.art_rev_id}}">
<div @click="openWindow(item.art_rev_id)" >
<h3><span
style="margin-right: 6px;color: #006699;">{{index+1}}.</span>{{item.article_title}}
</h3>
<el-button type="primary" plain style="float: right;">Review</el-button>
</router-link>
</div>
<h4>
<span>
<font style="color: #006699;">Journal : </font>{{item.journal_title}}.
@@ -233,6 +233,17 @@
this.getData();
},
methods: {
openWindow(art_rev_id) {
window.open(
this.$router.resolve({
path: '/per_text',
query: {
Art_id: art_rev_id
}
}).href,
'_blank'
);
},
// 获取数据
getData() {
this.$api
@@ -337,7 +348,8 @@
})
.then(res => {
if (res.code == 0) {
this.$router.push('/per_text?Art_id=' + index);
this.openWindow(index);
// this.$router.push('/per_text?Art_id=' + index);
} else {
this.$message.error(res.msg);
}
@@ -419,7 +431,8 @@
.then(res => {
if (res.code == 0) {
this.$message.success('Successful application!');
this.$router.push('/per_text?Art_id=' + res.data.art_rev_id);
this.openWindow(res.data.art_rev_id);
// this.$router.push('/per_text?Art_id=' + res.data.art_rev_id);
} else {
this.$message.error(res.msg);
}

View File

@@ -1,28 +1,18 @@
<template>
<div>
<div class="crumbs">
<el-breadcrumb separator="/">
<el-breadcrumb-item>
<i class="el-icon-collection"></i>
<router-link :to="{ path: '/peerewer' }">
<span class="top_dao"> Reviewer Article</span>
</router-link>
>> Reviewer Article Detail
</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div
<div style="background-color: #fafafa;height: 100%;">
<div style="height: 100%;"
class="container_l"
v-loading="loading"
element-loading-text="Loading..."
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.8)"
>
<el-row :gutter="20">
<el-col :span="10">
<el-row :gutter="20" style="height: 100%;">
<el-col :span="10" style="height: 100%;">
<iframe ref="mainiframe" :src="pdfUrl" class="lookpdf" frameborder="0"></iframe>
</el-col>
<el-col :span="14" style="height: 760px; overflow-y: scroll">
<el-col :span="14" style="height: 100%; overflow-y: scroll">
<!-- <el-col :span="24"> -->
<el-card class="box-card">
<div class="tet_list" :model="txt_mess">
@@ -816,7 +806,7 @@ export default {
}
.lookpdf {
height: 760px;
height: 100%;
width: 100%;
}

View File

@@ -185,7 +185,17 @@
},
openWindow(art_rev_id) {
window.open(
this.$router.resolve({
path: '/per_text',
query: {
Art_id: art_rev_id
}
}).href,
'_blank'
);
},
// 同意
saveNow() {
// 二次确认
@@ -200,7 +210,8 @@
.then(res => {
if (res.code == 0) {
this.$message.success('Review now successfully!');
this.$router.push('/per_text?Art_id=' + this.Art_id);
this.openWindow(this.Art_id);
// this.$router.push('/per_text?Art_id=' + this.Art_id);
} else {
this.$message.error(res.msg);
}

View File

@@ -701,7 +701,8 @@ export default new Router({
path: '/per_text', //审稿人文章详情
component: () => import('../components/page/per_text'),
meta: {
title: 'Reviewer article details'
title: 'Reviewer article details',
hideSidebar: true
}
},
{

View File

@@ -75,8 +75,8 @@ module.exports = {
// target: 'http://192.168.110.110/tougao/public/index.php/',
// target: 'http://api.tmrjournals.com/public/index.php/',//正式
// target: 'http://zmzm.tougao.dev.com/',//晓玲
// target: 'https://submission.tmrjournals.com/',//正式
target: 'http://tougaotest.tmrjournals.com/public/index.php/',//测试环境
target: 'https://submission.tmrjournals.com/',//正式
// target: 'http://tougaotest.tmrjournals.com/public/index.php/',//测试环境
changeOrigin: true,
pathRewrite: {
'^/api': ''