diff --git a/src/components/common/langs/en.js b/src/components/common/langs/en.js
index 2893300..4af9fc9 100644
--- a/src/components/common/langs/en.js
+++ b/src/components/common/langs/en.js
@@ -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',
diff --git a/src/components/common/langs/zh.js b/src/components/common/langs/zh.js
index df7475c..d76edac 100644
--- a/src/components/common/langs/zh.js
+++ b/src/components/common/langs/zh.js
@@ -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: '个人中心',
diff --git a/src/components/page/articleDetailEditor.vue b/src/components/page/articleDetailEditor.vue
index 386334b..e88aefc 100644
--- a/src/components/page/articleDetailEditor.vue
+++ b/src/components/page/articleDetailEditor.vue
@@ -947,6 +947,77 @@
Change
+
+
+ {{ $t('articleListEditor.plagiarismAutoCheck') }}
+
+
+
Manuscript :
Save
+
+
+
+
+
+
{
+ 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() {
@@ -2921,6 +3219,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;
diff --git a/src/components/page/components/autoPromotion/PromotionFactoryTaskDialog.vue b/src/components/page/components/autoPromotion/PromotionFactoryTaskDialog.vue
index 1b68bf9..e2aa124 100644
--- a/src/components/page/components/autoPromotion/PromotionFactoryTaskDialog.vue
+++ b/src/components/page/components/autoPromotion/PromotionFactoryTaskDialog.vue
@@ -432,6 +432,14 @@
count: counts.young,
jump: { path: '/youthList', queryKey: 'journal_id' }
},
+ {
+ value: '6',
+ label: this.$t('autoPromotion.factoryExpertReviewer'),
+ desc: this.$t('autoPromotion.factoryExpertReviewer'),
+ icon: 'el-icon-s-check',
+ count: counts.reviewer,
+ jump: { path: '/reviewerList', queryKey: 'journal_id' }
+ },
{
value: '4',
label: this.$t('autoPromotion.factoryExpertAuthor'),
@@ -447,14 +455,6 @@
icon: 'el-icon-collection',
count: counts.expertDb,
jump: { path: '/expertDatabase', queryKey: 'journal_id' }
- },
- {
- value: '6',
- label: this.$t('autoPromotion.factoryExpertReviewer'),
- desc: this.$t('autoPromotion.factoryExpertReviewer'),
- icon: 'el-icon-s-check',
- count: counts.reviewer,
- jump: { path: '/reviewerList', queryKey: 'journal_id' }
}
];
},