diff --git a/src/components/common/langs/en.js b/src/components/common/langs/en.js index c713f3d..4abb1a9 100644 --- a/src/components/common/langs/en.js +++ b/src/components/common/langs/en.js @@ -1159,6 +1159,10 @@ colTitle: 'Template title', }, tmrEmailEditor: { preview: 'Preview', + previewWithVariables: 'Preview (showing variables)', + previewWithVariablesTitle: 'Preview (showing variables)', + previewWithVariablesHint: 'The expert data is an example, used for variablespelling check only.', + close: 'Close', placeholder: 'Please enter email content' }, wordCite: { diff --git a/src/components/common/langs/zh.js b/src/components/common/langs/zh.js index 446f8f0..044f036 100644 --- a/src/components/common/langs/zh.js +++ b/src/components/common/langs/zh.js @@ -1144,6 +1144,10 @@ const zh = { }, tmrEmailEditor: { preview: '预览效果', + previewWithVariables: '预览(示例变量)', + previewWithVariablesTitle: '预览效果(已替换示例变量)', + previewWithVariablesHint: '专家数据仅为示例,仅用于变量拼写检查。', + close: '关闭', placeholder: '请输入邮件内容' }, wordCite: { diff --git a/src/components/page/components/email/TmrEmailEditor.vue b/src/components/page/components/email/TmrEmailEditor.vue index 7fd0ebd..a1aaaa1 100644 --- a/src/components/page/components/email/TmrEmailEditor.vue +++ b/src/components/page/components/email/TmrEmailEditor.vue @@ -4,9 +4,14 @@
- +
+ + +
-
+
+
@@ -47,6 +54,14 @@ export default { type: String, default: '' }, + journalList: { + type: Array, + default: [] + }, + journalId: { + + default: '' + }, placeholder: { type: String, default: '' @@ -54,7 +69,28 @@ export default { }, data() { return { - showModal: false + showModal: false, + /** 为 true 时预览会用 variableMockData 替换正文中的 {{变量名}} */ + previewWithMockVariables: false, + /** + * 预览「带变量」时的假数据。键名须与模板里 {{键名}} 完全一致(含中文键)。 + * 可对照本地变量清单维护,例如:约稿变量清单表格.docx + */ + variableMockData: { + // 以下为示例占位,请按实际模板增删改: + + + submission_url: "https://submission.tmrjournals.com/", // 投稿系统链接 + eic_name: "Zhang San", // 主编姓名 + editor_name: "Alice Wong" ,// 责任编辑姓名 + expert_title: "Prof", // 专家职称 (如 Prof./Dr.) + expert_name: "John Doe", // 专家姓名 + expert_field: "Biomedical Engineering", // 专家研究领域 + // representative_work_title: "Advanced Applications of AI in Medical Imaging", // 专家代表作标题 + // ai_content_analysis: "", // AI 约稿理由分析 + + + } } }, computed: { @@ -66,12 +102,65 @@ export default { if (!this.value) return ''; return this.extractContent(this.value); }, - // 用于预览的 HTML,保持与输出一致 + modalPreviewTitle() { + if (this.previewWithMockVariables) { + return this.$t('tmrEmailEditor.previewWithVariablesTitle'); + } + return this.$t('tmrEmailEditor.preview'); + }, + // 用于预览的 HTML;带变量模式会先替换 {{...}} htmlContentForPreview() { - return this.value || ''; + let html = this.value || ''; + if (this.previewWithMockVariables) { + html = this.applyVariableMocks(html); + } + return html; } }, methods: { + openPreview(withMockVariables) { + this.previewWithMockVariables = !!withMockVariables; + this.showModal = true; + }, + closePreviewModal() { + this.showModal = false; + this.previewWithMockVariables = false; + }, + /** + * 将 HTML 中的 {{ key }} 替换为 variableMockData[key];未配置的键保持原样。 + */ + applyVariableMocks(html) { + if (!html) return ''; + const oneMonthLater = new Date(); +oneMonthLater.setMonth(oneMonthLater.getMonth() + 1); +// 格式化为 YYYY-MM-DD +const deadlineStr = oneMonthLater.toISOString().split('T')[0]; + + + const journal_info=this.journalList.find(e=>e.journal_id==this.journalId) + + const map = { + ...this.variableMockData, + journal_abbr: journal_info.jabbr, // 期刊缩写 + journal_name: journal_info.title,// 期刊全称 + journal_url: journal_info.website, // 期刊官网链接 + journal_email: journal_info.email, // 期刊官方邮箱 + indexing_databases: "ESCI, Scopus, ROAD", // 收录数据库 + special_support_deadline:deadlineStr + } || {}; + + + + return html.replace(/\{\{\s*([^}]+?)\s*\}\}/g, (full, rawKey) => { + const key = String(rawKey).trim(); + if (!key) return full; + if (Object.prototype.hasOwnProperty.call(map, key) && map[key] != null && map[key] !== '') { + const val = map[key]; + return typeof val === 'string' ? val : String(val); + } + return full; + }); + }, /** * 核心:剥离外层容器和换行符 * 将
line1
line2
还原为 line1\nline2 @@ -125,6 +214,14 @@ export default { padding-bottom: 8px; } +.header-actions { + display: flex; + flex-wrap: wrap; + gap: 8px; + justify-content: flex-end; + flex-shrink: 0; +} + .preview-trigger-btn { background: #fff; border: 1px solid #dcdfe6; @@ -246,4 +343,15 @@ export default { } .confirm-btn:hover { background: #66b1ff; } + +.preview-with-vars-btn { + border-style: dashed; +} + +.mock-preview-hint { + margin: 0 0 12px; + font-size: 12px; + color: red; + line-height: 1.5; +} \ No newline at end of file diff --git a/src/components/page/mailboxMouldDetail.vue b/src/components/page/mailboxMouldDetail.vue index b508853..3f5ba0f 100644 --- a/src/components/page/mailboxMouldDetail.vue +++ b/src/components/page/mailboxMouldDetail.vue @@ -98,6 +98,8 @@
{{ $t('mailboxMouldDetail.emailBody') }}:
@@ -172,8 +174,9 @@ export default { .then(res => { const list = res || []; const mapped = (Array.isArray(list) ? list : []).map(j => ({ + ...j, journal_id: j.journal_id || j.id, - title: j.title || j.name || '' + title: j.title || j.name || '', })); this.journalList = mapped; if (fromRouteJournalId) {