From 1f29fb5baf042c856542a8a7fbffc7b31594d182 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, 1 Apr 2026 17:30:40 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E6=A0=87=E7=AD=BEautoCite?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E5=8F=82=E8=80=83=E6=96=87=E7=8C=AE?= 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 | 3 + src/components/common/langs/zh.js | 3 + src/components/page/GenerateCharts.vue | 96 +- src/components/page/PreIngestedEditor.vue | 4 +- .../page/PreIngestedEditorProduce.vue | 4 +- src/components/page/components/table/word.vue | 115 +- .../page/editPublicRefTableOnly.vue | 2013 +++++++++++++++++ src/components/page/publishRefernceEditor.vue | 2 +- 9 files changed, 2223 insertions(+), 21 deletions(-) create mode 100644 src/components/page/editPublicRefTableOnly.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/langs/en.js b/src/components/common/langs/en.js index 6867b42..121ff73 100644 --- a/src/components/common/langs/en.js +++ b/src/components/common/langs/en.js @@ -1150,6 +1150,9 @@ colTitle: 'Template title', tmrEmailEditor: { preview: 'Preview', placeholder: 'Please enter email content' + }, + wordCite: { + notFoundById: 'No reference found for citation ID {id}' } diff --git a/src/components/common/langs/zh.js b/src/components/common/langs/zh.js index a57f900..88aea53 100644 --- a/src/components/common/langs/zh.js +++ b/src/components/common/langs/zh.js @@ -1135,6 +1135,9 @@ const zh = { tmrEmailEditor: { preview: '预览效果', placeholder: '请输入邮件内容' + }, + wordCite: { + notFoundById: '未查询到编号{id}相关参考文献' } diff --git a/src/components/page/GenerateCharts.vue b/src/components/page/GenerateCharts.vue index 653bb6e..dccd520 100644 --- a/src/components/page/GenerateCharts.vue +++ b/src/components/page/GenerateCharts.vue @@ -75,7 +75,7 @@ + @@ -437,6 +450,7 @@ import { mediaUrl } from '@/common/js/commonJS.js'; // 引入通用逻辑 import Tinymce from '@/components/page/components/Tinymce'; import bottomTinymce from '@/components/page/components/Tinymce'; import catalogue from '@/components/page/components/table/catalogue.vue'; +import editPublicRefTableOnly from './editPublicRefTableOnly.vue'; export default { data() { return { @@ -559,18 +573,31 @@ export default { pictVisible: false, typesettingType: 1, imagesList: [], - exegesis: "The following contents','are necessary for the generation phase, please do not delete them!!!" + exegesis: "The following contents','are necessary for the generation phase, please do not delete them!!!", + p_article_id: null, + chanFerForm: [], + chanFerFormRepeatList: [] }; }, components: { Tinymce, bottomTinymce, - catalogue + catalogue, + editPublicRefTableOnly }, computed: { - combinedValue() { - // 将两个值组合成一个新的值,可以是字符串、数组、对象等 - // return `${this.isFirstComponentLoaded}-${this.isWordComponentLoaded}`; + catalogueContent() { + const base = Array.isArray(this.Main_List) ? this.Main_List : []; + if (!Array.isArray(this.chanFerForm) || this.chanFerForm.length === 0) return base; + return [ + ...base, + { + am_id: 'References', + content: 'References', + is_h1: 1, + is_h2: 0 + } + ]; } }, watch: { @@ -597,6 +624,7 @@ export default { async created() { localStorage.removeItem('scrollPosition'); this.isShowEditComment(); + this.loadPreacceptArticleDetail(); this.getDate(); this.getCommentList(); }, @@ -615,11 +643,62 @@ export default { }, async activated() { this.isShowEditComment(); + this.loadPreacceptArticleDetail(); this.getDate(); this.getCommentList(); }, methods: { + loadPreacceptArticleDetail() { + if (!this.articleId) return; + this.$api + .post('api/Article/getPreacceptArticleDetail', { article_id: this.articleId }) + .then((res) => { + const pid = res.data && res.data.production && res.data.production.p_article_id; + this.p_article_id = pid; + if (pid != null && pid !== '') { + if (!this.Art_P_Id) this.Art_P_Id = pid; + this.fetchReferList(); + } + }) + .catch(() => {}); + }, + fetchReferList() { + if (!this.p_article_id) return; + this.$api + .post('api/Production/getReferList', { + p_article_id: this.p_article_id + }) + .then((res) => { + this.chanFerForm = res.data.refers; + this.chanFerFormRepeatList = Object.values(res.data.repeat || {}); + for (let i = 0; i < this.chanFerForm.length; i++) { + this.chanFerForm[i].edit_mark = 1; + } + this.$nextTick(() => { + if (this.$refs.editPublicRefTableOnly) { + this.$refs.editPublicRefTableOnly.init(); + } + }); + }) + .catch((err) => { + console.log(err); + }); + }, + ChanFerMashUp(e) { + this.$api + .post('api/Production/referHB', e) + .then((res) => { + if (res.code == 0) { + this.fetchReferList(); + } else { + this.$message.error(res.msg); + } + }) + .catch((err) => { + this.$message.error(err); + }); + }, openAddTable(content) { this.editVisible = false; this.threeVisible = true; @@ -655,6 +734,11 @@ export default { loadedWord() { this.isWordComponentLoaded = true; + this.$nextTick(() => { + if (this.$refs.editPublicRefTableOnly) { + this.$refs.editPublicRefTableOnly.init(); + } + }); }, // 监听第一个兄弟组件加载完毕 // onFirstComponentLoaded(imagesList) { diff --git a/src/components/page/PreIngestedEditor.vue b/src/components/page/PreIngestedEditor.vue index 9c07386..9153fbb 100644 --- a/src/components/page/PreIngestedEditor.vue +++ b/src/components/page/PreIngestedEditor.vue @@ -1337,7 +1337,7 @@ export default { // 5----重新获取加载参考文献 changeRefer(val) { - console.log('重新获取参考文献'); + this.$api .post('api/Production/getReferList', { p_article_id: this.p_article_id @@ -1348,7 +1348,7 @@ export default { for (var i = 0; i < this.chanFerForm.length; i++) { this.chanFerForm[i].edit_mark = 1; } - console.log(this.chanFerForm); + }) .catch((err) => { console.log(err); diff --git a/src/components/page/PreIngestedEditorProduce.vue b/src/components/page/PreIngestedEditorProduce.vue index 73c5579..08bbb74 100644 --- a/src/components/page/PreIngestedEditorProduce.vue +++ b/src/components/page/PreIngestedEditorProduce.vue @@ -1433,7 +1433,7 @@ export default { // 5----重新获取加载参考文献 changeRefer(val) { - console.log('重新获取参考文献'); + this.$api .post('api/Production/getReferList', { p_article_id: this.p_article_id @@ -1444,7 +1444,7 @@ export default { for (var i = 0; i < this.chanFerForm.length; i++) { this.chanFerForm[i].edit_mark = 1; } - console.log(this.chanFerForm); + }) .catch((err) => { console.log(err); diff --git a/src/components/page/components/table/word.vue b/src/components/page/components/table/word.vue index 9a62071..27d66fa 100644 --- a/src/components/page/components/table/word.vue +++ b/src/components/page/components/table/word.vue @@ -369,7 +369,8 @@ - +
+ { + const key = row && row.p_refer_id != null ? String(row.p_refer_id) : ''; + if (key) mapFromRefs[key] = idx + 1; + }); + if (Object.keys(mapFromRefs).length > 0) return mapFromRefs; + + // 2) 兜底:按正文首次出现顺序编号 + const order = []; + const re = / 0 + ? this.wordList + : Array.isArray(this.contentList) + ? this.contentList + : []; + + paragraphs.forEach((p) => { + const candidates = []; + if (p && typeof p.text === 'string') candidates.push(p.text); + if (p && typeof p.content === 'string') candidates.push(p.content); + candidates.forEach((raw) => { + re.lastIndex = 0; + let m; + while ((m = re.exec(raw)) !== null) { + if (!order.includes(m[1])) order.push(m[1]); + } + }); + }); + + return order.reduce((acc, id, idx) => { + acc[id] = idx + 1; + return acc; + }, {}); + }, sortedProofreadingList() { const order = [2, 1, 3]; const rank = { 2: 0, 1: 1, 3: 2 }; @@ -1355,6 +1401,59 @@ export default { this.editors = {}; }, methods: { +// 1. 引用序号合并算法 (1,2,3 -> 1-3) +formatCiteNumbers(nums) { + if (!nums || !nums.length) return ""; + const sorted = [...new Set(nums)].sort((a, b) => a - b); + const result = []; + let i = 0; + while (i < sorted.length) { + let j = i; + while (j < sorted.length - 1 && sorted[j + 1] === sorted[j] + 1) j++; + if (j - i >= 2) { + result.push(`${sorted[i]}-${sorted[j]}`); + } else { + for (let k = i; k <= j; k++) result.push(sorted[k]); + } + i = j + 1; + } + return result.join(', '); +}, + +// 2. 最终引用标签渲染器 (将 autocite 转换为 [n]) +renderCiteLabels(html) { + // 匹配连续的引用标签 + const citeGroupRe = /(<\/autocite>\s*)+/gi; + return html.replace(citeGroupRe, (groupMatch) => { + const ids = [...groupMatch.matchAll(/data-id="(\d+)"/gi)].map((m) => String(m[1])); + const refList = Array.isArray(this.chanFerForm) ? this.chanFerForm : []; + const refMap = refList.reduce((acc, item) => { + const key = item && item.p_refer_id != null ? String(item.p_refer_id) : ''; + if (key) acc[key] = item; + return acc; + }, {}); + + const nums = ids.map((id) => this.citeMap && this.citeMap[id]).filter((n) => n != null); + const label = nums.length > 0 ? this.formatCiteNumbers(nums) : '?'; + + const lines = ids.map((id) => { + const no = this.citeMap && this.citeMap[id] != null ? this.citeMap[id] : '?'; + const ref = refMap[id]; + if (!ref) { + return this.$t('wordCite.notFoundById', { id: no === '?' ? id : no }); + } + + const content = + ref.refer_frag || + [ref.author, ref.title, ref.joura, ref.dateno].filter(Boolean).join(' ').trim() || + '[?]'; + const doi = ref.doilink || ref.isbn || ref.doi || '[?]'; + return `[${no}] ${content} DOI: ${doi}`; + }); + + return `[${label}]${groupMatch}`; + }); +}, getInvolvedPMain(range) { // 1. 找到起始节点所属的 .pMain let startNode = range.startContainer; @@ -3042,7 +3141,7 @@ export default { const src = String(text || ''); // 1) 用一个全局、区分大小写不敏感的 wmath 提取正则 - const wmathRe = /]*>[\s\S]*?<\/wmath\s*>/gi; + const wmathRe = /<(wmath|autocite)\b[^>]*>[\s\S]*?<\/(wmath|autocite)\s*>/gi; // 2) 把原文切成: [非wmath片段, wmath片段, 非wmath片段, wmath片段, ...] const parts = []; @@ -3133,7 +3232,7 @@ export default { >${rawHit}`; html = html.split(ph).join(span); }); - + html = this.renderCiteLabels(html); // 6) 空文本占位图(沿用你的逻辑,且不会影响 wmath) if (type === 0 && html.trim() === '') { html += ``; @@ -3231,7 +3330,7 @@ export default { const escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // 1) 切分出 wmath 与非 wmath 片段 - const wmathRe = /]*>[\s\S]*?<\/wmath\s*>/gi; + const wmathRe = /<(wmath|autocite)\b[^>]*>[\s\S]*?<\/(wmath|autocite)\s*>/gi; const parts = []; let lastIdx = 0, m; @@ -3301,7 +3400,7 @@ export default { // 用 split/join 精确回填,避免再走正则 html = html.split(ph).join(span); }); - + html = this.renderCiteLabels(html); // 6) 空文本时按你原逻辑补图标(不会影响 wmath) if (type === 0 && html.trim() === '') { html += ``; @@ -4192,7 +4291,7 @@ export default { top: 26px; left: 0px; } -/deep/.rightTabs .first-pane-width { +::v-deep .rightTabs .first-pane-width { width: 200px; /* 规定第一个面板内容的宽度 */ } .arrow-group { diff --git a/src/components/page/editPublicRefTableOnly.vue b/src/components/page/editPublicRefTableOnly.vue new file mode 100644 index 0000000..1290d4d --- /dev/null +++ b/src/components/page/editPublicRefTableOnly.vue @@ -0,0 +1,2013 @@ + + + + + diff --git a/src/components/page/publishRefernceEditor.vue b/src/components/page/publishRefernceEditor.vue index 856d89c..b731d60 100644 --- a/src/components/page/publishRefernceEditor.vue +++ b/src/components/page/publishRefernceEditor.vue @@ -124,7 +124,7 @@ export default { }, // 5----重新获取加载参考文献 changeRefer(val) { - console.log('重新获取参考文献') + this.$api .post('api/Production/getReferList', { 'p_article_id': this.p_article_id