From 1844d2d125d27e99ab65312d9f65c13a255bb414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A7=8B=E4=BA=8E=E5=88=9D=E8=A7=81?= <752204717@qq.com> Date: Wed, 15 Apr 2026 10:39:44 +0800 Subject: [PATCH 01/20] =?UTF-8?q?=E5=AE=A1=E7=A8=BF=E6=8A=A5=E5=91=8A?= =?UTF-8?q?=E5=AD=97=E6=95=B0=E7=BB=9F=E8=AE=A1=20=E5=8A=A0=E5=85=A5?= =?UTF-8?q?=E9=99=90=E5=88=B6=20=E6=8E=92=E9=99=A4=20=E7=A9=BA=E6=A0=BC?= =?UTF-8?q?=E4=B9=8B=E7=B1=BB=E7=9A=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/index.js | 4 +- src/common/js/commonJS.js | 33 +++++++++++- .../page/components/reviewArticle/author.vue | 51 +++++++++---------- .../page/components/reviewArticle/index.vue | 50 +++++++++--------- 4 files changed, 82 insertions(+), 56 deletions(-) diff --git a/src/api/index.js b/src/api/index.js index 487fb66..525753d 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/common/js/commonJS.js b/src/common/js/commonJS.js index 60bb1ab..eae4459 100644 --- a/src/common/js/commonJS.js +++ b/src/common/js/commonJS.js @@ -1244,7 +1244,38 @@ str = str.replace(regex, function (match, content, offset, fullString) { }, - + getCleanTextForCount(html) { + if (!html) return ""; + + // 创建临时容器解析 HTML + const tempDiv = document.createElement('div'); + tempDiv.innerHTML = html; + + // A. 特殊处理 wmath:只拿它里面的公式文本,扔掉里面生成的 mjx-container 等标签 + const wmaths = tempDiv.querySelectorAll('wmath'); + wmaths.forEach(wm => { + // textContent 会拿到最原始的公式字符,忽略内部所有标签 + const textNode = document.createTextNode(wm.textContent); + wm.parentNode.replaceChild(textNode, wm); + }); + + // B. 获取现在的 HTML 内容 + let result = tempDiv.innerHTML; + + // C. 去掉特定排版标签的“壳”(保留里面的文字) + // 包含 b, strong, br, em, i, sup, sub 等 + result = result.replace(/<(p|div|b|strong|br|em|i|sup|sub)[^>]*>/gi, ""); + result = result.replace(/<\/(p|div|b|strong|br|em|i|sup|sub)>/gi, ""); + + + + // E. 彻底“脱水”:去掉 HTML 实体、换行符、所有空格 + result = result.replace(/ /ig, ""); + result = result.replace(/[\r\n\t]/g, ""); + result = result.replace(/\s+/g, ""); + + return result; + }, diff --git a/src/components/page/components/reviewArticle/author.vue b/src/components/page/components/reviewArticle/author.vue index c990abd..070732e 100644 --- a/src/components/page/components/reviewArticle/author.vue +++ b/src/components/page/components/reviewArticle/author.vue @@ -17,9 +17,6 @@ :form="baseQuestionform" @update="(e) => (questionform = e)" > - - - @@ -134,7 +131,6 @@ export default { recommend: [{ required: true, message: 'please select', trigger: 'blur' }] }; } - }, questionSubmit() { if (this.questionform.is_anonymous == '' && this.questionform.is_anonymous != '0') { @@ -161,30 +157,29 @@ export default { } let Char_Cter = null; // 验证相加的字数 - if (this.isNewForm) { - Char_Cter = [ - this.questionform.qu5contents, - this.questionform.qu6contents, - this.questionform.qu7contents, - this.questionform.qu8contents, - this.questionform.qu9contents, - this.questionform.qu10contents, - this.questionform.qu11contents, - this.questionform.qu12contents, - this.questionform.qu13contents, - this.questionform.qu14contents, - this.questionform.comment - ].join(' '); - } else { - Char_Cter = [ - this.questionform.qu9contents, - this.questionform.qu10contents, - this.questionform.qu11contents, - this.questionform.qu12contents, - this.questionform.qu13contents, - this.questionform.comment - ].join(' '); - } + const contents = this.isNewForm + ? [ + this.questionform.qu5contents, + this.questionform.qu6contents, + this.questionform.qu7contents, + this.questionform.qu8contents, + this.questionform.qu9contents, + this.questionform.qu10contents, + this.questionform.qu11contents, + this.questionform.qu12contents, + this.questionform.qu13contents, + this.questionform.qu14contents, + this.questionform.comment + ] + : [ + this.questionform.qu9contents, + this.questionform.qu10contents, + this.questionform.qu11contents, + this.questionform.qu12contents, + this.questionform.qu13contents, + this.questionform.comment + ]; + Char_Cter = this.$commonJS.getCleanTextForCount(contents.join(' ')); if (new RegExp('[\\u4E00-\\u9FFF]+', 'g').test(Char_Cter)) { //中文 diff --git a/src/components/page/components/reviewArticle/index.vue b/src/components/page/components/reviewArticle/index.vue index 9d759b3..40c1a70 100644 --- a/src/components/page/components/reviewArticle/index.vue +++ b/src/components/page/components/reviewArticle/index.vue @@ -342,6 +342,7 @@ export default { return content; }, + async questionSubmit() { if (this.questionform.is_anonymous == '' && this.questionform.is_anonymous != '0') { @@ -368,30 +369,29 @@ export default { } let Char_Cter = null; // 验证相加的字数 - if (this.isNewForm) { - Char_Cter = [ - this.questionform.qu5contents, - this.questionform.qu6contents, - this.questionform.qu7contents, - this.questionform.qu8contents, - this.questionform.qu9contents, - this.questionform.qu10contents, - this.questionform.qu11contents, - this.questionform.qu12contents, - this.questionform.qu13contents, - this.questionform.qu14contents, - this.questionform.comment - ].join(' '); - } else { - Char_Cter = [ - this.questionform.qu9contents, - this.questionform.qu10contents, - this.questionform.qu11contents, - this.questionform.qu12contents, - this.questionform.qu13contents, - this.questionform.comment - ].join(' '); - } + const contents = this.isNewForm ? [ + this.questionform.qu5contents, + this.questionform.qu6contents, + this.questionform.qu7contents, + this.questionform.qu8contents, + this.questionform.qu9contents, + this.questionform.qu10contents, + this.questionform.qu11contents, + this.questionform.qu12contents, + this.questionform.qu13contents, + this.questionform.qu14contents, + this.questionform.comment +] : [ + this.questionform.qu9contents, + this.questionform.qu10contents, + this.questionform.qu11contents, + this.questionform.qu12contents, + this.questionform.qu13contents, + this.questionform.comment +]; +Char_Cter = this.$commonJS.getCleanTextForCount(contents.join(' ')); + + if (new RegExp('[\\u4E00-\\u9FFF]+', 'g').test(Char_Cter)) { //中文 @@ -447,7 +447,7 @@ if(this.questionform.confident != ''){ confidentStr = await this.abstractFormat(this.questionform.confident); } - +return this.$refs.question.validate((valid) => { if (valid) { From ec74b6e38c3b47210fc4ac3da58c16d025c5943f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A7=8B=E4=BA=8E=E5=88=9D=E8=A7=81?= <752204717@qq.com> Date: Wed, 15 Apr 2026 10:47:09 +0800 Subject: [PATCH 02/20] =?UTF-8?q?=E5=AE=A1=E7=A8=BF=E6=8A=A5=E5=91=8A?= =?UTF-8?q?=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/page/components/reviewArticle/index.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/page/components/reviewArticle/index.vue b/src/components/page/components/reviewArticle/index.vue index 40c1a70..0cbbf96 100644 --- a/src/components/page/components/reviewArticle/index.vue +++ b/src/components/page/components/reviewArticle/index.vue @@ -447,7 +447,7 @@ if(this.questionform.confident != ''){ confidentStr = await this.abstractFormat(this.questionform.confident); } -return + this.$refs.question.validate((valid) => { if (valid) { From 64b1d20b3291c70a562b046d9124181375643db5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A7=8B=E4=BA=8E=E5=88=9D=E8=A7=81?= <752204717@qq.com> Date: Wed, 15 Apr 2026 13:09:08 +0800 Subject: [PATCH 03/20] =?UTF-8?q?=E6=8E=92=E7=89=88=E6=8B=96=E6=8B=BD?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/page/GenerateCharts.vue | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/components/page/GenerateCharts.vue b/src/components/page/GenerateCharts.vue index 653bb6e..4896df4 100644 --- a/src/components/page/GenerateCharts.vue +++ b/src/components/page/GenerateCharts.vue @@ -1679,13 +1679,13 @@ export default { }, async onDrop(event, dataId) { - const loading = this.$loading({ + if (event.dataTransfer.getData('image')) { + const loading = this.$loading({ lock: true, text: 'Loading...', spinner: 'el-icon-loading', background: 'rgba(0, 0, 0, 0.7)' }); - if (event.dataTransfer.getData('image')) { const draggedImage = JSON.parse(event.dataTransfer.getData('image')); const draggedImageIndex = JSON.parse(event.dataTransfer.getData('imageIndex')); this.$nextTick(async () => { @@ -1712,7 +1712,13 @@ export default { this.$message.error(err.msg); }); }); - } else { + } else if(event.dataTransfer.getData('table')) { + const loading = this.$loading({ + lock: true, + text: 'Loading...', + spinner: 'el-icon-loading', + background: 'rgba(0, 0, 0, 0.7)' + }); const draggedtable = JSON.parse(event.dataTransfer.getData('table')); this.$nextTick(async () => { @@ -1739,6 +1745,8 @@ export default { this.$message.error(err.msg); }); }); + }else{ + } }, getCommentList() { From 1e2e8146cc6cece6c1af51b9abc8e06b154b536b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A7=8B=E4=BA=8E=E5=88=9D=E8=A7=81?= <752204717@qq.com> Date: Thu, 16 Apr 2026 11:02:01 +0800 Subject: [PATCH 04/20] =?UTF-8?q?=E5=AE=A1=E7=A8=BF=E6=A0=A1=E9=AA=8C?= =?UTF-8?q?=E7=A9=BA=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/js/commonJS.js | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/src/common/js/commonJS.js b/src/common/js/commonJS.js index eae4459..3f15913 100644 --- a/src/common/js/commonJS.js +++ b/src/common/js/commonJS.js @@ -1246,35 +1246,28 @@ str = str.replace(regex, function (match, content, offset, fullString) { getCleanTextForCount(html) { if (!html) return ""; - - // 创建临时容器解析 HTML const tempDiv = document.createElement('div'); tempDiv.innerHTML = html; - // A. 特殊处理 wmath:只拿它里面的公式文本,扔掉里面生成的 mjx-container 等标签 + // 1. 处理公式 (保留公式文本内容) const wmaths = tempDiv.querySelectorAll('wmath'); wmaths.forEach(wm => { - // textContent 会拿到最原始的公式字符,忽略内部所有标签 - const textNode = document.createTextNode(wm.textContent); + const textNode = document.createTextNode(" " + wm.textContent + " "); wm.parentNode.replaceChild(textNode, wm); }); - // B. 获取现在的 HTML 内容 - let result = tempDiv.innerHTML; + // 2. 移除所有引用标签 [1], [2] (防止用户靠狂刷引用来凑字数) + const refs = tempDiv.querySelectorAll('span.reference-link, a.ref'); // 根据你系统的 class 名调整 + refs.forEach(r => r.remove()); - // C. 去掉特定排版标签的“壳”(保留里面的文字) - // 包含 b, strong, br, em, i, sup, sub 等 - result = result.replace(/<(p|div|b|strong|br|em|i|sup|sub)[^>]*>/gi, ""); - result = result.replace(/<\/(p|div|b|strong|br|em|i|sup|sub)>/gi, ""); + // 3. 获取纯文本 (textContent 是浏览器原生方法,能处理所有标签及其属性) + let text = tempDiv.textContent || tempDiv.innerText || ""; - - - // E. 彻底“脱水”:去掉 HTML 实体、换行符、所有空格 - result = result.replace(/ /ig, ""); - result = result.replace(/[\r\n\t]/g, ""); - result = result.replace(/\s+/g, ""); - - return result; + // 4. 标准化空格:将 HTML 实体、换行、多个空格统一转为一个空格 + return text.replace(/ /ig, " ") + .replace(/[\r\n\t]+/g, " ") + .replace(/\s+/g, " ") + .trim(); }, From 8fbcf39a251479fa7b9bdcc5390c7d5ddfe35d16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A7=8B=E4=BA=8E=E5=88=9D=E8=A7=81?= <752204717@qq.com> Date: Fri, 17 Apr 2026 10:36:48 +0800 Subject: [PATCH 05/20] =?UTF-8?q?=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/index.js | 4 +- src/components/common/Sidebar.vue | 153 +++++---- src/components/common/langs/en.js | 53 ++++ src/components/common/langs/zh.js | 53 ++++ src/components/page/countryManagement.vue | 362 ++++++++++++++++++++++ src/components/page/expertDatabase.vue | 70 ++++- src/router/index.js | 11 +- 7 files changed, 614 insertions(+), 92 deletions(-) create mode 100644 src/components/page/countryManagement.vue 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/Sidebar.vue b/src/components/common/Sidebar.vue index 3e4417e..0d93f07 100644 --- a/src/components/common/Sidebar.vue +++ b/src/components/common/Sidebar.vue @@ -64,8 +64,8 @@ - - @@ -286,9 +301,7 @@ export default { }, batchPartitionToApplyBaseRows() { return (this.batchPartitionPreviewRows || []).filter( - (r) => - r._row && - String(r._row.partition != null ? r._row.partition : '') !== String(r.partition) + (r) => r._row && String(r._row.partition != null ? r._row.partition : '') !== String(r.partition) ); }, batchPartitionEffectiveToApplyRows() { @@ -603,7 +616,12 @@ export default { } const lower = key.toLowerCase(); return ( - rows.find((r) => String(r.en_name || '').trim().toLowerCase() === lower) || + rows.find( + (r) => + String(r.en_name || '') + .trim() + .toLowerCase() === lower + ) || rows.find((r) => String(r.zh_name || '').trim() === key) || null ); diff --git a/src/components/page/mailboxMouldDetail.vue b/src/components/page/mailboxMouldDetail.vue index 5358d77..899c88d 100644 --- a/src/components/page/mailboxMouldDetail.vue +++ b/src/components/page/mailboxMouldDetail.vue @@ -100,6 +100,7 @@ v-model="form.body" :journalList="journalList" :journalId="form.journalId" + :language="form.lang" placeholder="" /> From ca1b10c418850de171412726eaa9810d0c49709a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A7=8B=E4=BA=8E=E5=88=9D=E8=A7=81?= <752204717@qq.com> Date: Fri, 24 Apr 2026 15:05:57 +0800 Subject: [PATCH 12/20] =?UTF-8?q?=E6=BB=91=E5=8A=A8=E9=80=89=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/page/components/table/word.vue | 204 ++++++++++++++---- 1 file changed, 164 insertions(+), 40 deletions(-) diff --git a/src/components/page/components/table/word.vue b/src/components/page/components/table/word.vue index 9a62071..9454e7c 100644 --- a/src/components/page/components/table/word.vue +++ b/src/components/page/components/table/word.vue @@ -1208,10 +1208,16 @@ export default { hasChange: false, hasInit: false, selectedIds: [], + isMouseSelecting: false, + _selectionSyncToCheckboxesTimer: null, + _onDocumentSelectionChange: null, + _onDocumentMouseUp: null, + _onManuscriptMouseDown: null, displayList: [], currentTypeText: '', tinymceId: this.id || 'vue-tinymce-' + +new Date() + }; }, // this.$nextTick(() => window.tinymce.get(this.tinymceId).setContent(newVal)); @@ -1274,51 +1280,60 @@ export default { }); this.$refs.scrollDiv.addEventListener('scroll', this.divOnScroll, { passive: true }); - document.addEventListener('selectionchange', () => { - if(this.isPreview)return; - const selection = window.getSelection(); - if (selection.rangeCount === 0) return; + // document.addEventListener('selectionchange', () => { + // if(this.isPreview)return; + // const selection = window.getSelection(); + // if (selection.rangeCount === 0) return; - const range = selection.getRangeAt(0); - // 依然保留 trim() 后的文本判断,用来决定是否显示气泡 - const plainText = selection.toString().trim(); + // const range = selection.getRangeAt(0); + // // 依然保留 trim() 后的文本判断,用来决定是否显示气泡 + // const plainText = selection.toString().trim(); - if (plainText !== '' && selection.rangeCount > 0) { - // --- 1. 获取包含标签的 HTML 内容 --- - const fragment = range.cloneContents(); - const tempDiv = document.createElement('div'); - tempDiv.appendChild(fragment); - // 关键点:这个 label 变量现在包含了完整的 HTML 结构(如 ) - const htmlLabel = tempDiv.innerHTML; - const allPMainElements = this.getInvolvedPMain(range); - const allIds = [...new Set(allPMainElements.map((el) => el.getAttribute('data-id')))]; - if (allIds.length > 0) { - this.updateBubblePosition(range); - const rootItem = this.wordList.find((item) => item.am_id == allIds[0]); + // if (plainText !== '' && selection.rangeCount > 0) { + // // --- 1. 获取包含标签的 HTML 内容 --- + // const fragment = range.cloneContents(); + // const tempDiv = document.createElement('div'); + // tempDiv.appendChild(fragment); + // // 关键点:这个 label 变量现在包含了完整的 HTML 结构(如 ) + // const htmlLabel = tempDiv.innerHTML; + // const allPMainElements = this.getInvolvedPMain(range); + // const allIds = [...new Set(allPMainElements.map((el) => el.getAttribute('data-id')))]; + // if (allIds.length > 0) { + // this.updateBubblePosition(range); + // const rootItem = this.wordList.find((item) => item.am_id == allIds[0]); - this.currentSelection = { - // 将 label 设置为包含标签的 HTML 字符串 - label: htmlLabel, - mainId: allIds[0], - index: this.wordList.indexOf(rootItem), + // this.currentSelection = { + // // 将 label 设置为包含标签的 HTML 字符串 + // label: htmlLabel, + // mainId: allIds[0], + // index: this.wordList.indexOf(rootItem), - content: rootItem ? rootItem.content : '' - }; + // content: rootItem ? rootItem.content : '' + // }; - this.currentId = allIds[0]; - this.currentData = rootItem; - } - } else { - this.currentTag = ''; - this.currentTagData = {}; - this.currentSelection = { - label: '', - mainId: '', - index: 0, - content: {} - }; - } - }); + // this.currentId = allIds[0]; + // this.currentData = rootItem; + // } + // } else { + // this.currentTag = ''; + // this.currentTagData = {}; + // this.currentSelection = { + // label: '', + // mainId: '', + // index: 0, + // content: {} + // }; + // } + // }); + this._onDocumentSelectionChange = this.handleDocumentSelectionChange.bind(this); + this._onDocumentMouseUp = this.handleDocumentMouseUp.bind(this); + this._onManuscriptMouseDown = this.handleManuscriptMouseDown.bind(this); + document.addEventListener('selectionchange', this._onDocumentSelectionChange); + document.addEventListener('mouseup', this._onDocumentMouseUp); + if (this.$refs.scroll) { + this.$refs.scroll.addEventListener('mousedown', this._onManuscriptMouseDown); + } + }, activated() { // 主动触发 MathJax 渲染 @@ -1378,6 +1393,115 @@ export default { return rangePs; }, + handleManuscriptMouseDown(event) { + if (this.isPreview) return; + const root = this.$refs && this.$refs.scroll; + if (!root) return; + if (root.contains(event.target)) { + this.isMouseSelecting = true; + } + }, + handleDocumentMouseUp() { + this.isMouseSelecting = false; + }, + handleDocumentSelectionChange() { + if (this.isPreview) return; + const selection = window.getSelection(); + if (!selection || selection.rangeCount === 0) return; + + const range = selection.getRangeAt(0); + const plainText = selection.toString().trim(); + + if (plainText !== '' && selection.rangeCount > 0) { + const fragment = range.cloneContents(); + const tempDiv = document.createElement('div'); + tempDiv.appendChild(fragment); + const htmlLabel = tempDiv.innerHTML; + const allPMainElements = this.getInvolvedPMain(range); + const allIds = [...new Set(allPMainElements.map((el) => el.getAttribute('data-id')))]; + if (allIds.length > 0) { + this.updateBubblePosition(range); + const rootItem = this.wordList.find((item) => item.am_id == allIds[0]); + + this.currentSelection = { + label: htmlLabel, + mainId: allIds[0], + index: this.wordList.indexOf(rootItem), + content: rootItem ? rootItem.content : '' + }; + + this.currentId = allIds[0]; + this.currentData = rootItem; + } + } else { + this.currentTag = ''; + this.currentTagData = {}; + this.currentSelection = { + label: '', + mainId: '', + index: 0, + content: {} + }; + } + this.scheduleSyncSelectedIdsFromRange(); + }, + scheduleSyncSelectedIdsFromRange() { + if (this._selectionSyncToCheckboxesTimer) { + clearTimeout(this._selectionSyncToCheckboxesTimer); + } + this._selectionSyncToCheckboxesTimer = setTimeout(() => { + this.syncSelectedIdsFromRangeInternal(); + }, 80); + }, + syncSelectedIdsFromRangeInternal() { + if (this.isPreview || this.isInternalAction) return; + const scrollRoot = this.$refs && this.$refs.scroll; + if (!scrollRoot) return; + + const selection = window.getSelection(); + if (!selection || selection.rangeCount === 0 || selection.isCollapsed) return; + const range = selection.getRangeAt(0); + const common = range.commonAncestorContainer; + const commonElement = common && common.nodeType === 1 ? common : common && common.parentElement; + if (!commonElement || !scrollRoot.contains(commonElement)) return; + + const nodes = Array.from(scrollRoot.querySelectorAll('.drop-target[main-id]')); + const touchedMainIds = []; + nodes.forEach((node) => { + const id = node.getAttribute('main-id'); + if (!id || id === 'References') return; + try { + if (range.intersectsNode(node)) { + touchedMainIds.push(id); + } + } catch (e) {} + }); + if (!touchedMainIds.length) return; + + const indexMap = {}; + this.wordList.forEach((item, idx) => { + if (item && item.am_id != null) { + indexMap[String(item.am_id)] = idx; + } + }); + const indices = [...new Set(touchedMainIds.map((id) => indexMap[String(id)]).filter((v) => Number.isInteger(v)))]; + if (!indices.length) return; + const lo = Math.min(...indices); + const hi = Math.max(...indices); + const rangeIds = this.wordList + .slice(lo, hi + 1) + .map((item) => (item && item.am_id != null ? item.am_id : null)) + .filter((id) => id != null); + if (!rangeIds.length) return; + + const existingSet = new Set(this.selectedIds || []); + rangeIds.forEach((id) => existingSet.add(id)); + const ordered = this.wordList + .map((item) => (item && item.am_id != null ? item.am_id : null)) + .filter((id) => id != null && existingSet.has(id)); + this.selectedIds = ordered; + this.$forceUpdate(); + }, handleUnbindLink(type) { const rootItem = this.wordList.find((item) => item.am_id == this.currentTagData.main_id); From 0c9ff0fe68f25dd8bf31baf3c325ffc493be5edb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A7=8B=E4=BA=8E=E5=88=9D=E8=A7=81?= <752204717@qq.com> Date: Tue, 28 Apr 2026 11:12:15 +0800 Subject: [PATCH 13/20] =?UTF-8?q?=E4=B8=93=E5=AE=B6=E5=BA=93=E9=80=80?= =?UTF-8?q?=E8=AE=A2=E7=8A=B6=E6=80=81+=E4=BF=AE=E6=94=B9=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E9=A1=B5=E6=95=B0=E6=8D=AE=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/index.js | 4 +- src/components/common/langs/en.js | 12 ++- src/components/common/langs/zh.js | 12 ++- src/components/page/autoPromotionLogs.vue | 4 +- src/components/page/expertDatabase.vue | 101 ++++++++++++++++++++++ 5 files changed, 125 insertions(+), 8 deletions(-) diff --git a/src/api/index.js b/src/api/index.js index 487fb66..525753d 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 adbad11..1496380 100644 --- a/src/components/common/langs/en.js +++ b/src/components/common/langs/en.js @@ -310,7 +310,8 @@ const en = { baseInfo: 'Base Information', country: 'Country', affiliation: 'Affiliation', - researchAreas: 'Research areas' + researchAreas: 'Research areas', + unsubscribeStatus: 'Subscription status' }, emptyMark: '-', fields: { @@ -327,7 +328,14 @@ const en = { detailCellEmpty: 'N/A', noFieldDetail: 'No publication details for these fields', exportWarn: 'Please select a research area, enter a keyword, or enter a field before exporting.', - exportFailed: 'Export failed' + exportFailed: 'Export failed', + unsubscribeNormal: 'Subscribed', + unsubscribeUnsubscribed: 'Unsubscribed', + unsubscribeSwitchOn: 'Unsub', + unsubscribeSwitchOff: 'Subscribed', + unsubscribeMissingId: 'Missing expert ID, unable to switch unsubscribe status', + unsubscribeUpdateSuccess: 'Unsubscribe status updated', + unsubscribeUpdateFailed: 'Failed to update unsubscribe status' }, countryManagement: { title: 'Country Management', diff --git a/src/components/common/langs/zh.js b/src/components/common/langs/zh.js index 3358a51..08dc441 100644 --- a/src/components/common/langs/zh.js +++ b/src/components/common/langs/zh.js @@ -299,7 +299,8 @@ const zh = { baseInfo: '基础信息', country: '国家', affiliation: '单位', - researchAreas: '研究领域' + researchAreas: '研究领域', + unsubscribeStatus: '订阅状态' }, emptyMark: '-', fields: { @@ -316,7 +317,14 @@ const zh = { detailCellEmpty: '暂无', noFieldDetail: '暂无领域对应的文献信息', exportWarn: '请选择研究领域或输入关键词或领域 field 后再导出。', - exportFailed: '导出失败' + exportFailed: '导出失败', + unsubscribeNormal: '已订阅', + unsubscribeUnsubscribed: '已退订', + unsubscribeSwitchOn: '退订', + unsubscribeSwitchOff: '已订阅', + unsubscribeMissingId: '缺少专家 ID,无法切换退订状态', + unsubscribeUpdateSuccess: '退订状态更新成功', + unsubscribeUpdateFailed: '退订状态更新失败' }, countryManagement: { title: '国家信息维护', diff --git a/src/components/page/autoPromotionLogs.vue b/src/components/page/autoPromotionLogs.vue index 0635b9a..c5cf550 100644 --- a/src/components/page/autoPromotionLogs.vue +++ b/src/components/page/autoPromotionLogs.vue @@ -381,7 +381,7 @@ export default { selectedStyleName: '', // 列表数据 - query: { keyword: '', state: 'all', pageIndex: 1, pageSize: 15 }, + query: { keyword: '', state: 'all', pageIndex: 1, pageSize: 10 }, list: [], total: 0, @@ -1035,7 +1035,7 @@ export default { journal_id: String(this.selectedJournalId || ''), factory_id: String(this.routePromotionFactoryId || ''), page: Number(this.query.pageIndex || 1), - per_page: Number(this.query.pageSize || 15) + per_page: Number(this.query.pageSize || 10) }; if (this.query.state !== 'all' && this.query.state !== '' && this.query.state != null) { params.state = String(this.query.state); diff --git a/src/components/page/expertDatabase.vue b/src/components/page/expertDatabase.vue index 8ed496a..71e6b4f 100644 --- a/src/components/page/expertDatabase.vue +++ b/src/components/page/expertDatabase.vue @@ -77,6 +77,32 @@ + + + diff --git a/src/components/common/common.vue b/src/components/common/common.vue index a1781ec..9bac70a 100644 --- a/src/components/common/common.vue +++ b/src/components/common/common.vue @@ -2,14 +2,14 @@ //记得切换 //正式 -// 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/'; -const baseUrl = '/api' +// const mediaUrl = 'https://submission.tmrjournals.com/public/'; +// // const mediaUrl = 'http://zmzm.tougao.dev.com/public/'; +// const baseUrl = '/api' //测试环境 diff --git a/src/components/page/JournalManagement/JournalManagement/common.vue b/src/components/page/JournalManagement/JournalManagement/common.vue index 0ae93f0..9ff0bfb 100644 --- a/src/components/page/JournalManagement/JournalManagement/common.vue +++ b/src/components/page/JournalManagement/JournalManagement/common.vue @@ -263,7 +263,39 @@ + + +
+
+
+ + + + +
+
+ +
+ + Add - - + +
+
+ +
+ +
@@ -657,6 +694,17 @@ export default { this.$message.error(res.msg); } }, + async handleAvatarSuccessYboard(res, file) { + if (res.code == 0) { + this.detailForm.wechat_yboard_qrcode = res.upurl; + this.$forceUpdate(); + } else { + this.$message.error(res.msg); + } + }, + handleAvatarErrorYboard(res, file) { + // no-op + }, handleAvatarError2(res, file) { // this.$message.error(res); }, @@ -883,7 +931,9 @@ export default { epassword: data.epassword, kfen: data.kfen, fee: data.fee, + databases: data.databases || data.database_inclusion || '', editor_qrcode: data.editor_qrcode, + wechat_yboard_qrcode: data.wechat_yboard_qrcode || data.yboard_qrcode, scope: data.scope, abstract_chinese: data.abstract_chinese, publish_author: data.publish_author, @@ -1369,6 +1419,29 @@ export default { border-radius: 110px; } +/* Wechat Name + Apply Youth Board QR:两列对齐到右侧 */ +.wechat-name-split__inner { + display: flex; + align-items: flex-start; + gap: 16px; +} + +.wechat-name-split__left { + flex: 1; + min-width: 200px; +} + +.wechat-name-split__right { + width: 160px; +} + +.yboard-qrcode-side__label { + font-size: 12px; + color: #666; + text-align: center; + margin-bottom: 8px; +} + .portrait .ptmark { position: absolute; top: 0; diff --git a/src/components/page/YouthBoardSubmitSuccess.vue b/src/components/page/YouthBoardSubmitSuccess.vue new file mode 100644 index 0000000..928d110 --- /dev/null +++ b/src/components/page/YouthBoardSubmitSuccess.vue @@ -0,0 +1,238 @@ + + + + + diff --git a/src/components/page/YouthEditorialBoardRegistration.vue b/src/components/page/YouthEditorialBoardRegistration.vue new file mode 100644 index 0000000..73b02bd --- /dev/null +++ b/src/components/page/YouthEditorialBoardRegistration.vue @@ -0,0 +1,598 @@ + + + + + diff --git a/src/components/page/youthApplyList.vue b/src/components/page/youthApplyList.vue index 9b84261..390ac1c 100644 --- a/src/components/page/youthApplyList.vue +++ b/src/components/page/youthApplyList.vue @@ -187,6 +187,7 @@