diff --git a/src/api/index.js b/src/api/index.js index 525753d..487fb66 100644 --- a/src/api/index.js +++ b/src/api/index.js @@ -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: '/', //正式 }); diff --git a/src/components/common/langs/en.js b/src/components/common/langs/en.js index 94acad6..8b91dc4 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', @@ -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', diff --git a/src/components/common/langs/zh.js b/src/components/common/langs/zh.js index 5c98152..181d2a4 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: '个人中心', @@ -1344,6 +1356,8 @@ const zh = { factoryExpertYoungBoard: '青年编委', factoryExpertAuthor: '作者', factoryExpertDb: 'expert库', + factoryExpertYoungBoardBefore2025: '2025前青年编委', + factoryExpertAuthorBefore2025: '2025前作者', factoryExpertJump: '查看', factoryOfficialEmailTip: '此类型默认使用系统官方邮箱发送,无需选择邮箱账号。', factoryScenario: '场景', diff --git a/src/components/page/articleDetailEditor.vue b/src/components/page/articleDetailEditor.vue index 4118a82..47e0411 100644 --- a/src/components/page/articleDetailEditor.vue +++ b/src/components/page/articleDetailEditor.vue @@ -1005,6 +1005,77 @@ Change +
+ + {{ $t('articleListEditor.plagiarismAutoCheck') }} + +
+
+ {{ $t('articleListEditor.plagiarismListTitle') }} +
+ + + {{ $t('articleListEditor.plagiarismRefresh') }} + +
+
+
+
+ + + {{ formatPlagiarismSimilarity(row) }} + + {{ formatPlagiarismDate(row) }} + + {{ formatPlagiarismStateLabel(row) }} + + + + {{ $t('articleListEditor.plagiarismPreviewPdf') }} + + + {{ $t('articleListEditor.plagiarismNoPdfLink') }} + +
+
+
+
Manuscript : Save + +
+ +
+ + {{ $t('articleListEditor.plagiarismPreviewClose') }} + + {{ $t('articleListEditor.plagiarismPreviewOpenTab') }} + + +
{ + 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(); } }; @@ -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; diff --git a/src/components/page/autoPromotion.vue b/src/components/page/autoPromotion.vue index 4ba7c57..c884b68 100644 --- a/src/components/page/autoPromotion.vue +++ b/src/components/page/autoPromotion.vue @@ -15,7 +15,7 @@
- + {{ $t('autoPromotion.factoryBatchImportBtn') }} 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; diff --git a/src/components/page/components/email/TmrEmailEditor.vue b/src/components/page/components/email/TmrEmailEditor.vue index ac2e1af..2574353 100644 --- a/src/components/page/components/email/TmrEmailEditor.vue +++ b/src/components/page/components/email/TmrEmailEditor.vue @@ -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