Merge branch 'master' of https://git.nuttyreading.com/wangjinlei/tougao_web into similarity-check
This commit is contained in:
@@ -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: '/', //正式
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -50,10 +50,22 @@ const en = {
|
||||
plagiarismNotChecked: 'Not checked',
|
||||
plagiarismChecking: 'Checking…',
|
||||
plagiarismRecheck: 'Re-check',
|
||||
plagiarismDuplicateCheck: 'Re-check',
|
||||
plagiarismCheckFailed: 'Failed to start plagiarism check.',
|
||||
plagiarismStatusFailed: 'Failed to load plagiarism status.',
|
||||
plagiarismNoReportUrl: 'Report link is not available yet.',
|
||||
plagiarismReportDetailFailed: 'Could not load manuscript details. Please try again.',
|
||||
plagiarismListTitle: 'Plagiarism check history',
|
||||
plagiarismAutoCheck: 'Auto plagiarism check',
|
||||
plagiarismRefresh: 'Refresh',
|
||||
plagiarismEmptyList: 'No plagiarism checks yet',
|
||||
plagiarismSimilarity: 'Similarity',
|
||||
plagiarismFile: 'File',
|
||||
plagiarismPreviewPdf: 'Preview report',
|
||||
plagiarismReportLink: 'Report',
|
||||
plagiarismNoPdfLink: 'No link',
|
||||
plagiarismPreviewClose: 'Close',
|
||||
plagiarismPreviewOpenTab: 'Open in new tab',
|
||||
},
|
||||
menu: {
|
||||
main: 'Personal Center',
|
||||
@@ -1363,6 +1375,8 @@ const en = {
|
||||
factoryExpertYoungBoard: 'Young editorial board',
|
||||
factoryExpertAuthor: 'Author',
|
||||
factoryExpertDb: 'Expert database',
|
||||
factoryExpertYoungBoardBefore2025: 'Young board (before 2025)',
|
||||
factoryExpertAuthorBefore2025: 'Author (before 2025)',
|
||||
factoryExpertJump: 'View',
|
||||
factoryOfficialEmailTip: 'For this type, the system uses the official sender email by default. No account selection is required.',
|
||||
factoryScenario: 'Scenario',
|
||||
|
||||
@@ -48,10 +48,22 @@ const zh = {
|
||||
plagiarismNotChecked: '未检测',
|
||||
plagiarismChecking: '正在检测…',
|
||||
plagiarismRecheck: '重新查重',
|
||||
plagiarismDuplicateCheck: '重复检查',
|
||||
plagiarismCheckFailed: '查重任务启动失败。',
|
||||
plagiarismStatusFailed: '获取查重状态失败。',
|
||||
plagiarismNoReportUrl: '报告链接暂不可用。',
|
||||
plagiarismReportDetailFailed: '获取稿件详情失败,请稍后重试。',
|
||||
plagiarismListTitle: '自动查重记录',
|
||||
plagiarismAutoCheck: '自动查重',
|
||||
plagiarismRefresh: '刷新',
|
||||
plagiarismEmptyList: '暂无查重记录',
|
||||
plagiarismSimilarity: '相似度',
|
||||
plagiarismFile: '文件',
|
||||
plagiarismPreviewPdf: '预览报告',
|
||||
plagiarismReportLink: '报告',
|
||||
plagiarismNoPdfLink: '无链接',
|
||||
plagiarismPreviewClose: '关闭',
|
||||
plagiarismPreviewOpenTab: '新窗口打开',
|
||||
},
|
||||
menu: {
|
||||
main: '个人中心',
|
||||
@@ -1344,6 +1356,8 @@ const zh = {
|
||||
factoryExpertYoungBoard: '青年编委',
|
||||
factoryExpertAuthor: '作者',
|
||||
factoryExpertDb: 'expert库',
|
||||
factoryExpertYoungBoardBefore2025: '2025前青年编委',
|
||||
factoryExpertAuthorBefore2025: '2025前作者',
|
||||
factoryExpertJump: '查看',
|
||||
factoryOfficialEmailTip: '此类型默认使用系统官方邮箱发送,无需选择邮箱账号。',
|
||||
factoryScenario: '场景',
|
||||
|
||||
@@ -1005,6 +1005,77 @@
|
||||
</a>
|
||||
<el-button type="text" @click="changeRepe" icon="el-icon-edit">Change</el-button>
|
||||
</div>
|
||||
<div v-if="plagiarismListReady" class="plagiarism-check-shell">
|
||||
<el-button
|
||||
v-if="!plagiarismList.length"
|
||||
class="plagiarism-auto-check-btn"
|
||||
icon="el-icon-search"
|
||||
:loading="plagiarismSubmitLoading"
|
||||
@click="submitPlagiarismCheck"
|
||||
>
|
||||
{{ $t('articleListEditor.plagiarismAutoCheck') }}
|
||||
</el-button>
|
||||
<div
|
||||
v-else
|
||||
class="plagiarism-check-block"
|
||||
v-loading="plagiarismListLoading"
|
||||
element-loading-background="transparent"
|
||||
>
|
||||
<div class="plagiarism-check-header">
|
||||
<span class="plagiarism-check-title">{{ $t('articleListEditor.plagiarismListTitle') }}</span>
|
||||
<div class="plagiarism-check-actions">
|
||||
<!-- <el-button
|
||||
type="text"
|
||||
size="mini"
|
||||
icon="el-icon-document-checked"
|
||||
:loading="plagiarismSubmitLoading"
|
||||
@click="submitPlagiarismCheck"
|
||||
>
|
||||
{{ $t('articleListEditor.plagiarismDuplicateCheck') }}
|
||||
</el-button> -->
|
||||
<el-button
|
||||
type="text"
|
||||
size="mini"
|
||||
icon="el-icon-refresh"
|
||||
:loading="plagiarismListLoading"
|
||||
@click="fetchPlagiarismList(true)"
|
||||
>
|
||||
{{ $t('articleListEditor.plagiarismRefresh') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="plagiarism-check-list-wrap">
|
||||
<div
|
||||
v-for="row in plagiarismList"
|
||||
:key="row.check_id || row.id"
|
||||
class="plagiarism-check-row"
|
||||
:title="row.source_file_name || ''"
|
||||
>
|
||||
<span class="plagiarism-sim-dot" :class="getPlagiarismSimilarityLevel(row)"></span>
|
||||
<span class="plagiarism-sim-pct" :class="getPlagiarismSimilarityLevel(row)">
|
||||
{{ formatPlagiarismSimilarity(row) }}
|
||||
</span>
|
||||
<span class="plagiarism-sim-date">{{ formatPlagiarismDate(row) }}</span>
|
||||
<span class="plagiarism-sim-state" :class="getPlagiarismStateClass(row)">
|
||||
{{ formatPlagiarismStateLabel(row) }}
|
||||
</span>
|
||||
<span class="plagiarism-sim-report">
|
||||
<a
|
||||
v-if="hasPlagiarismPdf(row)"
|
||||
href="javascript:;"
|
||||
class="plagiarism-report-preview"
|
||||
:title="$t('articleListEditor.plagiarismPreviewOpenTab')"
|
||||
@click.prevent="openPlagiarismReportPage(row)"
|
||||
>
|
||||
{{ $t('articleListEditor.plagiarismPreviewPdf') }}
|
||||
<i class="el-icon-link"></i>
|
||||
</a>
|
||||
<span v-else class="plagiarism-check-no-pdf">{{ $t('articleListEditor.plagiarismNoPdfLink') }}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span style="display: inline-block; vertical-align: top; margin-top: 7px">Manuscript : </span>
|
||||
<el-upload
|
||||
@@ -1200,6 +1271,31 @@
|
||||
<el-button type="primary" @click="saveRepe">Save</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
:title="plagiarismPdfPreviewTitle"
|
||||
:visible.sync="plagiarismPdfPreviewVisible"
|
||||
width="90%"
|
||||
top="4vh"
|
||||
append-to-body
|
||||
custom-class="plagiarism-pdf-preview-dialog"
|
||||
@closed="onPlagiarismPdfPreviewClosed"
|
||||
>
|
||||
<div v-loading="plagiarismPdfPreviewLoading" class="plagiarism-pdf-preview-body">
|
||||
<iframe
|
||||
v-if="plagiarismPdfPreviewUrl"
|
||||
:src="plagiarismPdfPreviewUrl"
|
||||
class="plagiarism-pdf-preview-iframe"
|
||||
frameborder="0"
|
||||
@load="plagiarismPdfPreviewLoading = false"
|
||||
></iframe>
|
||||
</div>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button size="small" @click="plagiarismPdfPreviewVisible = false">{{ $t('articleListEditor.plagiarismPreviewClose') }}</el-button>
|
||||
<el-button size="small" type="primary" v-if="plagiarismPdfPreviewUrl" @click="openPlagiarismPdfInNewTab">
|
||||
{{ $t('articleListEditor.plagiarismPreviewOpenTab') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
title="Resubmit the manuscript"
|
||||
:visible.sync="resubmitVisible"
|
||||
@@ -1808,7 +1904,16 @@ export default {
|
||||
is_figure_copyright: '',
|
||||
figurecopyright_file: '',
|
||||
plagiarismDetailPollTimer: null,
|
||||
plagiarismDetailPending: false
|
||||
plagiarismDetailPending: false,
|
||||
plagiarismList: [],
|
||||
plagiarismListLoading: false,
|
||||
plagiarismListReady: false,
|
||||
plagiarismPollTimer: null,
|
||||
plagiarismSubmitLoading: false,
|
||||
plagiarismPdfPreviewVisible: false,
|
||||
plagiarismPdfPreviewUrl: '',
|
||||
plagiarismPdfPreviewTitle: '',
|
||||
plagiarismPdfPreviewLoading: false
|
||||
};
|
||||
},
|
||||
async created() {
|
||||
@@ -1818,6 +1923,17 @@ export default {
|
||||
this.getWordimgList();
|
||||
this.getWordTablesList();
|
||||
this.getFinalList();
|
||||
this.startPlagiarismPolling();
|
||||
},
|
||||
activated() {
|
||||
this.startPlagiarismPolling(false);
|
||||
},
|
||||
deactivated() {
|
||||
this.stopPlagiarismPolling();
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.stopPlagiarismPolling();
|
||||
this.detailStopPlagiarismPolling();
|
||||
},
|
||||
computed: {
|
||||
// coverLetterUrl: function() {
|
||||
@@ -2943,8 +3059,7 @@ export default {
|
||||
closeResubmit() {
|
||||
(this.resubmitVisible = false), this.$refs['resubmitJournal'].resetFields();
|
||||
},
|
||||
|
||||
/* ---------- Crossref plagiarism(详情页右侧) ---------- */
|
||||
/* ---------- Crossref plagiarism(详情页 Repetition 行) ---------- */
|
||||
detailPlagiarismArticleKey() {
|
||||
return String(this.form.articleId || this.editform.articleId || this.$route.query.id || '');
|
||||
},
|
||||
@@ -3116,14 +3231,196 @@ export default {
|
||||
full = base ? `${base}/${path}` : `/${path}`;
|
||||
}
|
||||
window.open(full, '_blank');
|
||||
},
|
||||
|
||||
/* ---------- 自动查重列表 ---------- */
|
||||
startPlagiarismPolling(resetList) {
|
||||
this.stopPlagiarismPolling();
|
||||
if (resetList !== false) {
|
||||
this.plagiarismListReady = false;
|
||||
this.plagiarismList = [];
|
||||
}
|
||||
this.fetchPlagiarismList(false);
|
||||
this.plagiarismPollTimer = setInterval(() => {
|
||||
this.fetchPlagiarismList(false);
|
||||
}, 3 * 60 * 1000);
|
||||
},
|
||||
stopPlagiarismPolling() {
|
||||
if (this.plagiarismPollTimer) {
|
||||
clearInterval(this.plagiarismPollTimer);
|
||||
this.plagiarismPollTimer = null;
|
||||
}
|
||||
},
|
||||
async submitPlagiarismCheck() {
|
||||
const articleId = String((this.editform && this.editform.articleId) || this.$route.query.id || '').trim();
|
||||
if (!articleId) {
|
||||
this.$message.warning(this.$t('articleListEditor.plagiarismReportDetailFailed'));
|
||||
return;
|
||||
}
|
||||
this.plagiarismSubmitLoading = true;
|
||||
try {
|
||||
const res = await this.$api.post('api/Plagiarism/submit', { article_id: articleId });
|
||||
if (res && Number(res.code) === 0) {
|
||||
this.$message.success((res && res.msg) || this.$t('articleListEditor.plagiarismChecking'));
|
||||
await this.fetchPlagiarismList(true);
|
||||
} else {
|
||||
this.$message.error((res && res.msg) || this.$t('articleListEditor.plagiarismCheckFailed'));
|
||||
}
|
||||
} catch (e) {
|
||||
this.$message.error(this.$t('articleListEditor.plagiarismCheckFailed'));
|
||||
} finally {
|
||||
this.plagiarismSubmitLoading = false;
|
||||
}
|
||||
},
|
||||
async fetchPlagiarismList(manual) {
|
||||
const articleId = String((this.editform && this.editform.articleId) || this.$route.query.id || '').trim();
|
||||
if (!articleId) {
|
||||
this.plagiarismListReady = true;
|
||||
return;
|
||||
}
|
||||
if (manual && this.plagiarismList.length) {
|
||||
this.plagiarismListLoading = true;
|
||||
}
|
||||
try {
|
||||
const res = await this.$api.post('api/Plagiarism/getList', { article_id: articleId });
|
||||
if (res && Number(res.code) === 0) {
|
||||
const payload = res.data || {};
|
||||
const list = Array.isArray(payload.list) ? payload.list : Array.isArray(payload) ? payload : [];
|
||||
this.plagiarismList = list;
|
||||
} else if (manual) {
|
||||
this.$message.error((res && res.msg) || this.$t('articleListEditor.plagiarismStatusFailed'));
|
||||
}
|
||||
} catch (e) {
|
||||
if (manual) {
|
||||
this.$message.error(this.$t('articleListEditor.plagiarismStatusFailed'));
|
||||
}
|
||||
} finally {
|
||||
this.plagiarismListLoading = false;
|
||||
this.plagiarismListReady = true;
|
||||
}
|
||||
},
|
||||
formatPlagiarismState(state) {
|
||||
const s = String(state != null ? state : '').trim();
|
||||
if (!s) return '-';
|
||||
return s;
|
||||
},
|
||||
formatPlagiarismStateLabel(row) {
|
||||
if (!row || typeof row !== 'object') return '—';
|
||||
const label = String(row.state_label || row.stateLabel || '').trim();
|
||||
if (label) return label;
|
||||
const s = row.state;
|
||||
if (s == null || String(s).trim() === '') return '—';
|
||||
return this.formatPlagiarismState(s);
|
||||
},
|
||||
getPlagiarismStateClass(row) {
|
||||
const s = Number(row && row.state);
|
||||
if (s === 1) return 'state-uploading';
|
||||
if (s === 2 || s === 3) return 'state-done';
|
||||
if (s === 4 || s === 5) return 'state-fail';
|
||||
return '';
|
||||
},
|
||||
getPlagiarismSimilarityScore(row) {
|
||||
if (!row || typeof row !== 'object') return null;
|
||||
const raw = row.similarity_score != null ? row.similarity_score : row.similarity;
|
||||
if (raw == null || String(raw).trim() === '') return null;
|
||||
const n = Number(raw);
|
||||
return isNaN(n) ? null : n;
|
||||
},
|
||||
formatPlagiarismSimilarity(row) {
|
||||
const n = this.getPlagiarismSimilarityScore(row);
|
||||
return n == null ? '—' : n + '%';
|
||||
},
|
||||
/** Crossref 相似度色块:0 绿、1–29 蓝、30+ 橙 */
|
||||
getPlagiarismSimilarityLevel(row) {
|
||||
const n = this.getPlagiarismSimilarityScore(row);
|
||||
if (n == null) return 'sim-unknown';
|
||||
if (n <= 0) return 'sim-zero';
|
||||
if (n < 30) return 'sim-low';
|
||||
return 'sim-high';
|
||||
},
|
||||
formatPlagiarismDate(row) {
|
||||
if (!row || typeof row !== 'object') return '—';
|
||||
const raw =
|
||||
row.finish_time ||
|
||||
row.finished_at ||
|
||||
row.update_time ||
|
||||
row.ctime ||
|
||||
row.create_time ||
|
||||
row.created_at ||
|
||||
'';
|
||||
if (raw == null || String(raw).trim() === '') return '—';
|
||||
const s = String(raw).trim();
|
||||
if (/^\d+$/.test(s)) {
|
||||
const num = Number(s);
|
||||
const ts = num > 1e12 ? num : num * 1000;
|
||||
try {
|
||||
return this.formatDate(Math.floor(ts / 1000));
|
||||
} catch (e) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
const d = new Date(s.replace(/-/g, '/'));
|
||||
if (!isNaN(d.getTime())) {
|
||||
const pad = (v) => String(v).padStart(2, '0');
|
||||
return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate());
|
||||
}
|
||||
return s.length > 10 ? s.slice(0, 10) : s;
|
||||
},
|
||||
resolvePlagiarismPdfUrl(row) {
|
||||
if (!row || typeof row !== 'object') return '';
|
||||
const raw = String(row.viewer_url || row.local_pdf_url || row.localPdfUrl || '').trim();
|
||||
if (!raw) return '';
|
||||
if (/^https?:\/\//i.test(raw)) return raw;
|
||||
|
||||
let path = raw.replace(/^\/+/, '');
|
||||
if (!/^public\//i.test(path)) {
|
||||
const media = String(this.mediaUrl || '/public/').replace(/\/+$/, '');
|
||||
if (/^https?:\/\//i.test(media)) {
|
||||
return media + '/' + path;
|
||||
}
|
||||
path = (media.startsWith('/') ? media : '/' + media) + '/' + path;
|
||||
} else {
|
||||
path = '/' + path;
|
||||
}
|
||||
path = path.replace(/\/+/g, '/');
|
||||
|
||||
if (typeof window !== 'undefined' && window.location && window.location.origin && path.startsWith('/')) {
|
||||
return window.location.origin + path;
|
||||
}
|
||||
return path;
|
||||
},
|
||||
hasPlagiarismPdf(row) {
|
||||
return !!this.resolvePlagiarismPdfUrl(row);
|
||||
},
|
||||
openPlagiarismReportPage(row) {
|
||||
const url = this.resolvePlagiarismPdfUrl(row);
|
||||
if (!url) return;
|
||||
window.open(url, '_blank', 'noopener,noreferrer');
|
||||
},
|
||||
openPlagiarismPdfPreview(row) {
|
||||
const url = this.resolvePlagiarismPdfUrl(row);
|
||||
if (!url) return;
|
||||
const name = row && row.source_file_name ? String(row.source_file_name) : 'report.pdf';
|
||||
const id = row && row.check_id != null ? row.check_id : '';
|
||||
this.plagiarismPdfPreviewTitle =
|
||||
this.$t('articleListEditor.plagiarismPreviewPdf') + (id ? ' #' + id : '') + ' - ' + name;
|
||||
this.plagiarismPdfPreviewUrl = url;
|
||||
this.plagiarismPdfPreviewLoading = true;
|
||||
this.plagiarismPdfPreviewVisible = true;
|
||||
},
|
||||
onPlagiarismPdfPreviewClosed() {
|
||||
this.plagiarismPdfPreviewUrl = '';
|
||||
this.plagiarismPdfPreviewTitle = '';
|
||||
this.plagiarismPdfPreviewLoading = false;
|
||||
},
|
||||
openPlagiarismPdfInNewTab() {
|
||||
if (!this.plagiarismPdfPreviewUrl) return;
|
||||
window.open(this.plagiarismPdfPreviewUrl, '_blank', 'noopener');
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.opname = this.$route.query.mark;
|
||||
this.resubmitJournal.manuscriptId = this.$route.query.id;
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.detailStopPlagiarismPolling();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -3183,6 +3480,169 @@ export default {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.plagiarism-check-shell {
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
.plagiarism-check-block >>> .el-loading-mask {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
.plagiarism-auto-check-btn.el-button {
|
||||
display: block;
|
||||
width: 200px;
|
||||
border: none;
|
||||
color: #fff;
|
||||
font-size: 13px;
|
||||
margin-left: 75px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.3px;
|
||||
padding: 11px 20px;
|
||||
border-radius: 4px;
|
||||
background: linear-gradient(135deg, #2ec4b6 0%, #0d9b8f 45%, #0a7f76 100%);
|
||||
box-shadow: 0 2px 8px rgba(13, 155, 143, 0.35);
|
||||
transition: opacity 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
.plagiarism-auto-check-btn.el-button:hover,
|
||||
.plagiarism-auto-check-btn.el-button:focus {
|
||||
color: #fff;
|
||||
background: linear-gradient(135deg, #3dd4c6 0%, #14b0a3 45%, #0e948a 100%);
|
||||
box-shadow: 0 4px 12px rgba(13, 155, 143, 0.45);
|
||||
}
|
||||
.plagiarism-auto-check-btn.el-button.is-loading {
|
||||
background: linear-gradient(135deg, #2ec4b6 0%, #0d9b8f 45%, #0a7f76 100%);
|
||||
}
|
||||
.plagiarism-check-block {
|
||||
margin: 0 0 10px 0;
|
||||
padding: 10px 12px;
|
||||
background: #f8fafc;
|
||||
border: 1px solid #e8edf3;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.plagiarism-check-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.plagiarism-check-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.plagiarism-check-actions .el-button {
|
||||
padding: 0 6px;
|
||||
}
|
||||
.plagiarism-check-title {
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
font-weight: 500;
|
||||
}
|
||||
.plagiarism-check-list-wrap {
|
||||
min-height: 32px;
|
||||
}
|
||||
.plagiarism-check-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 6px 0;
|
||||
border-top: 1px solid #eef1f5;
|
||||
font-size: 12px;
|
||||
line-height: 20px;
|
||||
}
|
||||
.plagiarism-check-row:first-child {
|
||||
border-top: none;
|
||||
padding-top: 0;
|
||||
}
|
||||
.plagiarism-sim-dot {
|
||||
flex-shrink: 0;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 1px;
|
||||
}
|
||||
.plagiarism-sim-dot.sim-zero {
|
||||
background: #00a99d;
|
||||
}
|
||||
.plagiarism-sim-dot.sim-low {
|
||||
background: #0070c0;
|
||||
}
|
||||
.plagiarism-sim-dot.sim-high {
|
||||
background: #c87f0a;
|
||||
}
|
||||
.plagiarism-sim-dot.sim-unknown {
|
||||
background: #c0c4cc;
|
||||
}
|
||||
.plagiarism-sim-pct {
|
||||
flex-shrink: 0;
|
||||
min-width: 36px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.plagiarism-sim-pct.sim-zero {
|
||||
color: #00a99d;
|
||||
}
|
||||
.plagiarism-sim-pct.sim-low {
|
||||
color: #0070c0;
|
||||
}
|
||||
.plagiarism-sim-pct.sim-high {
|
||||
color: #c87f0a;
|
||||
}
|
||||
.plagiarism-sim-pct.sim-unknown {
|
||||
color: #909399;
|
||||
}
|
||||
.plagiarism-sim-date {
|
||||
flex-shrink: 0;
|
||||
color: #909399;
|
||||
}
|
||||
.plagiarism-sim-state {
|
||||
flex: 1;
|
||||
min-width: 48px;
|
||||
color: #909399;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.plagiarism-sim-state.state-uploading {
|
||||
color: #e6a23c;
|
||||
}
|
||||
.plagiarism-sim-state.state-done {
|
||||
color: #67c23a;
|
||||
}
|
||||
.plagiarism-sim-state.state-fail {
|
||||
color: #f56c6c;
|
||||
}
|
||||
.plagiarism-sim-report {
|
||||
flex-shrink: 0;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 6px;
|
||||
}
|
||||
.plagiarism-report-preview {
|
||||
color: #409eff;
|
||||
text-decoration: none;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.plagiarism-report-preview:hover {
|
||||
text-decoration: underline;
|
||||
color: #66b1ff;
|
||||
}
|
||||
.plagiarism-report-preview .el-icon-link {
|
||||
font-size: 14px;
|
||||
}
|
||||
.plagiarism-check-no-pdf {
|
||||
color: #f56c6c;
|
||||
font-size: 12px;
|
||||
}
|
||||
.plagiarism-pdf-preview-body {
|
||||
min-height: 70vh;
|
||||
}
|
||||
.plagiarism-pdf-preview-iframe {
|
||||
width: 100%;
|
||||
height: 70vh;
|
||||
border: none;
|
||||
background: #f5f7fa;
|
||||
}
|
||||
.el-upload__tip {
|
||||
display: inline-block;
|
||||
line-height: 32px;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
<div class="page-header-actions">
|
||||
<el-button type="warning" plain size="small" @click="openFactoryBatchImportDialog">
|
||||
<el-button type="warning" plain size="small" @click="openFactoryBatchImportDialog" style="display: none;">
|
||||
{{ $t('autoPromotion.factoryBatchImportBtn') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
@@ -1221,6 +1221,8 @@ export default {
|
||||
if (t === '3') return this.$t('autoPromotion.factoryExpertYoungBoard');
|
||||
if (t === '4') return this.$t('autoPromotion.factoryExpertAuthor');
|
||||
if (t === '5') return this.$t('autoPromotion.factoryExpertDb');
|
||||
if (t === '6') return this.$t('autoPromotion.factoryExpertYoungBoardBefore2025');
|
||||
if (t === '7') return this.$t('autoPromotion.factoryExpertAuthorBefore2025');
|
||||
return '-';
|
||||
},
|
||||
getJournalDisplayTasks(journal) {
|
||||
|
||||
@@ -490,6 +490,8 @@ export default {
|
||||
if (t === '3') return this.$t('autoPromotion.factoryExpertYoungBoard');
|
||||
if (t === '4') return this.$t('autoPromotion.factoryExpertAuthor');
|
||||
if (t === '5') return this.$t('autoPromotion.factoryExpertDb');
|
||||
if (t === '6') return this.$t('autoPromotion.factoryExpertYoungBoardBefore2025');
|
||||
if (t === '7') return this.$t('autoPromotion.factoryExpertAuthorBefore2025');
|
||||
return '-';
|
||||
},
|
||||
getStatusType(status) {
|
||||
|
||||
@@ -354,8 +354,9 @@
|
||||
chief: null,
|
||||
board: null,
|
||||
young: null,
|
||||
youngBefore2025: null,
|
||||
authorBefore2025: null,
|
||||
author: null,
|
||||
reviewer: null,
|
||||
expertDb: null
|
||||
},
|
||||
expertTypeCountsLoading: false,
|
||||
@@ -432,6 +433,22 @@
|
||||
count: counts.young,
|
||||
jump: { path: '/youthList', queryKey: 'journal_id' }
|
||||
},
|
||||
{
|
||||
value: '6',
|
||||
label: this.$t('autoPromotion.factoryExpertYoungBoardBefore2025'),
|
||||
desc: this.$t('autoPromotion.factoryExpertYoungBoardBefore2025'),
|
||||
icon: 'el-icon-time',
|
||||
count: counts.youngBefore2025,
|
||||
jump: { path: '/youthList', queryKey: 'journal_id' }
|
||||
},
|
||||
{
|
||||
value: '7',
|
||||
label: this.$t('autoPromotion.factoryExpertAuthorBefore2025'),
|
||||
desc: this.$t('autoPromotion.factoryExpertAuthorBefore2025'),
|
||||
icon: 'el-icon-document',
|
||||
count: counts.authorBefore2025,
|
||||
jump: { path: '/partyListCorr', queryKey: 'journal_id' }
|
||||
},
|
||||
{
|
||||
value: '4',
|
||||
label: this.$t('autoPromotion.factoryExpertAuthor'),
|
||||
@@ -884,12 +901,28 @@
|
||||
this.availableFields = [];
|
||||
this.factoryFieldIds = [];
|
||||
this.selectedEmailIds = [];
|
||||
this.expertTypeCounts = { chief: null, board: null, young: null, author: null, reviewer: null, expertDb: null };
|
||||
this.expertTypeCounts = {
|
||||
chief: null,
|
||||
board: null,
|
||||
young: null,
|
||||
youngBefore2025: null,
|
||||
authorBefore2025: null,
|
||||
author: null,
|
||||
expertDb: null
|
||||
};
|
||||
this.syncActiveStep();
|
||||
return;
|
||||
}
|
||||
// 切换期刊时:先清空旧人数并立即触发 loading
|
||||
this.expertTypeCounts = { chief: null, board: null, young: null, author: null, reviewer: null, expertDb: null };
|
||||
this.expertTypeCounts = {
|
||||
chief: null,
|
||||
board: null,
|
||||
young: null,
|
||||
youngBefore2025: null,
|
||||
authorBefore2025: null,
|
||||
author: null,
|
||||
expertDb: null
|
||||
};
|
||||
this.fetchExpertTypeCounts();
|
||||
await this.loadAccounts(val);
|
||||
await Promise.all([
|
||||
@@ -907,6 +940,7 @@
|
||||
const payload = {
|
||||
from: 'promotionFactory',
|
||||
journal_id: journalId != null && journalId !== '' ? String(journalId) : '',
|
||||
expert_type: opt && opt.value != null ? String(opt.value) : '',
|
||||
ts: Date.now(),
|
||||
targetPath: String(jump.path || '')
|
||||
};
|
||||
@@ -939,19 +973,21 @@
|
||||
return sum;
|
||||
};
|
||||
|
||||
const [boardRes, youngRes, authorRes, reviewerRes, expertDbRes] = await Promise.all([
|
||||
const yboardBase = {
|
||||
journal_id: journalId,
|
||||
pageIndex: 1,
|
||||
pageSize: 1,
|
||||
keywords: '',
|
||||
fieldkey: '',
|
||||
order_remark: 0
|
||||
};
|
||||
const [boardRes, youngRes, youngBefore2025Res, authorRes, authorBefore2025Res, expertDbRes] = await Promise.all([
|
||||
this.$api.post('api/Board/getBoards', { journal_id: journalId }).catch(() => null),
|
||||
this.$api
|
||||
.post('api/User/getYboardlist', {
|
||||
journal_id: journalId,
|
||||
type: 1,
|
||||
year: 0,
|
||||
pageIndex: 1,
|
||||
pageSize: 1,
|
||||
keywords: '',
|
||||
fieldkey: '',
|
||||
order_remark: 0
|
||||
})
|
||||
.post('api/User/getYboardlist', Object.assign({}, yboardBase, { type: 1, year: 0 }))
|
||||
.catch(() => null),
|
||||
this.$api
|
||||
.post('api/User/getYboardlist', Object.assign({}, yboardBase, { type: 6, year: 0 }))
|
||||
.catch(() => null),
|
||||
this.$api
|
||||
.post('api/User/authorDatabase', {
|
||||
@@ -962,12 +998,12 @@
|
||||
})
|
||||
.catch(() => null),
|
||||
this.$api
|
||||
.post('api/Reviewer/getReviewerListByJournal', {
|
||||
username: localStorage.getItem('U_name'),
|
||||
journalId: journalId,
|
||||
class: 0,
|
||||
pageIndex: 1,
|
||||
pageSize: 1
|
||||
.post('api/User/authorDatabase', {
|
||||
journal_id: journalId,
|
||||
type: 7,
|
||||
keywords: '',
|
||||
page: 1,
|
||||
limit: 1
|
||||
})
|
||||
.catch(() => null),
|
||||
this.$api
|
||||
@@ -978,7 +1014,15 @@
|
||||
.catch(() => null)
|
||||
]);
|
||||
|
||||
const next = { chief: null, board: null, young: null, author: null, reviewer: null, expertDb: null };
|
||||
const next = {
|
||||
chief: null,
|
||||
board: null,
|
||||
young: null,
|
||||
youngBefore2025: null,
|
||||
authorBefore2025: null,
|
||||
author: null,
|
||||
expertDb: null
|
||||
};
|
||||
|
||||
if (boardRes && boardRes.code === 0 && boardRes.data && boardRes.data.boards) {
|
||||
const b = boardRes.data.boards || {};
|
||||
@@ -991,11 +1035,14 @@
|
||||
if (youngRes && youngRes.code === 0) {
|
||||
next.young = safeCount(youngRes.data && youngRes.data.count);
|
||||
}
|
||||
if (youngBefore2025Res && youngBefore2025Res.code === 0) {
|
||||
next.youngBefore2025 = safeCount(youngBefore2025Res.data && youngBefore2025Res.data.count);
|
||||
}
|
||||
if (authorRes && authorRes.code === 0) {
|
||||
next.author = safeCount(authorRes.data && authorRes.data.count);
|
||||
}
|
||||
if (reviewerRes && reviewerRes.code === 0) {
|
||||
next.reviewer = safeCount(reviewerRes.total);
|
||||
if (authorBefore2025Res && authorBefore2025Res.code === 0) {
|
||||
next.authorBefore2025 = safeCount(authorBefore2025Res.data && authorBefore2025Res.data.count);
|
||||
}
|
||||
if (expertDbRes && expertDbRes.code === 0) {
|
||||
const total = (expertDbRes.data && (expertDbRes.data.total || expertDbRes.data.count)) || expertDbRes.total;
|
||||
|
||||
@@ -90,7 +90,7 @@ export default {
|
||||
expert_title: "Prof", // 专家职称 (如 Prof./Dr.)
|
||||
expert_name: "John Doe", // 专家姓名
|
||||
expert_field: "Biomedical Engineering", // 专家研究领域
|
||||
representative_work_title: "Advanced Applications of AI in Medical Imaging", // 专家代表作标题
|
||||
representative_work_title: "Advanced Applications of AI in Medical Imaging.", // 专家代表作标题
|
||||
ai_content_analysis: "【AI分析文章,一句话总结】", // AI solicitation rationale
|
||||
ai_advised_topics: "Based on your research expertise, we would particularly welcome submissions on topics such as 【这里是AI针对学者领域给特定约稿主题】, or other closely related areas that align with your work.", // AI suggested directions
|
||||
|
||||
|
||||
Reference in New Issue
Block a user