根据标签autoCite显示参考文献

This commit is contained in:
2026-04-01 17:30:40 +08:00
parent 3f53a6c7d0
commit 1f29fb5baf
9 changed files with 2223 additions and 21 deletions

View File

@@ -19,8 +19,8 @@ const service = axios.create({
// baseURL: 'https://submission.tmrjournals.com/', //正式 记得切换 // baseURL: 'https://submission.tmrjournals.com/', //正式 记得切换
// baseURL: 'http://www.tougao.com/', //测试本地 记得切换 // baseURL: 'http://www.tougao.com/', //测试本地 记得切换
// baseURL: 'http://192.168.110.110/tougao/public/index.php/', // baseURL: 'http://192.168.110.110/tougao/public/index.php/',
// baseURL: '/api', //本地 baseURL: '/api', //本地
baseURL: '/', //正式 // baseURL: '/', //正式
}); });

View File

@@ -1150,6 +1150,9 @@ colTitle: 'Template title',
tmrEmailEditor: { tmrEmailEditor: {
preview: 'Preview', preview: 'Preview',
placeholder: 'Please enter email content' placeholder: 'Please enter email content'
},
wordCite: {
notFoundById: 'No reference found for citation ID {id}'
} }

View File

@@ -1135,6 +1135,9 @@ const zh = {
tmrEmailEditor: { tmrEmailEditor: {
preview: '预览效果', preview: '预览效果',
placeholder: '请输入邮件内容' placeholder: '请输入邮件内容'
},
wordCite: {
notFoundById: '未查询到编号{id}相关参考文献'
} }

View File

@@ -75,7 +75,7 @@
<template slot="catalogue1"> <template slot="catalogue1">
<catalogue <catalogue
v-if="Main_List.length > 0" v-if="Main_List.length > 0"
:content="Main_List" :content="catalogueContent"
:articleId="articleId" :articleId="articleId"
ref="catalogue" ref="catalogue"
@goToListComment="goToListComment" @goToListComment="goToListComment"
@@ -94,6 +94,7 @@
ref="commonWord" ref="commonWord"
:value="htmlContent" :value="htmlContent"
:contentList="Main_List" :contentList="Main_List"
:chanFerForm="chanFerForm"
:comments="comments" :comments="comments"
:wordStyle="wordStyle" :wordStyle="wordStyle"
@onDrop="onDrop" @onDrop="onDrop"
@@ -127,6 +128,18 @@
<template slot="comment"> <template slot="comment">
<div style="" class="commentList annotations"></div> <div style="" class="commentList annotations"></div>
</template> </template>
<template slot="refrences">
<edit-public-ref-table-only
v-if="p_article_id"
ref="editPublicRefTableOnly"
:chanFerForm="chanFerForm"
:chanFerFormRepeatList="chanFerFormRepeatList"
:p_article_id="p_article_id"
@ChanFerMashUp="ChanFerMashUp"
@refrashComp="fetchReferList"
@changeRefer="fetchReferList"
/>
</template>
</common-word> </common-word>
</div> </div>
</div> </div>
@@ -437,6 +450,7 @@ import { mediaUrl } from '@/common/js/commonJS.js'; // 引入通用逻辑
import Tinymce from '@/components/page/components/Tinymce'; import Tinymce from '@/components/page/components/Tinymce';
import bottomTinymce from '@/components/page/components/Tinymce'; import bottomTinymce from '@/components/page/components/Tinymce';
import catalogue from '@/components/page/components/table/catalogue.vue'; import catalogue from '@/components/page/components/table/catalogue.vue';
import editPublicRefTableOnly from './editPublicRefTableOnly.vue';
export default { export default {
data() { data() {
return { return {
@@ -559,18 +573,31 @@ export default {
pictVisible: false, pictVisible: false,
typesettingType: 1, typesettingType: 1,
imagesList: [], imagesList: [],
exegesis: "The following contents'<b></b>,<i></i>'are necessary for the generation phase, please do not delete them!!!" exegesis: "The following contents'<b></b>,<i></i>'are necessary for the generation phase, please do not delete them!!!",
p_article_id: null,
chanFerForm: [],
chanFerFormRepeatList: []
}; };
}, },
components: { components: {
Tinymce, Tinymce,
bottomTinymce, bottomTinymce,
catalogue catalogue,
editPublicRefTableOnly
}, },
computed: { computed: {
combinedValue() { catalogueContent() {
// 将两个值组合成一个新的值,可以是字符串、数组、对象等 const base = Array.isArray(this.Main_List) ? this.Main_List : [];
// return `${this.isFirstComponentLoaded}-${this.isWordComponentLoaded}`; 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: { watch: {
@@ -597,6 +624,7 @@ export default {
async created() { async created() {
localStorage.removeItem('scrollPosition'); localStorage.removeItem('scrollPosition');
this.isShowEditComment(); this.isShowEditComment();
this.loadPreacceptArticleDetail();
this.getDate(); this.getDate();
this.getCommentList(); this.getCommentList();
}, },
@@ -615,11 +643,62 @@ export default {
}, },
async activated() { async activated() {
this.isShowEditComment(); this.isShowEditComment();
this.loadPreacceptArticleDetail();
this.getDate(); this.getDate();
this.getCommentList(); this.getCommentList();
}, },
methods: { 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) { openAddTable(content) {
this.editVisible = false; this.editVisible = false;
this.threeVisible = true; this.threeVisible = true;
@@ -655,6 +734,11 @@ export default {
loadedWord() { loadedWord() {
this.isWordComponentLoaded = true; this.isWordComponentLoaded = true;
this.$nextTick(() => {
if (this.$refs.editPublicRefTableOnly) {
this.$refs.editPublicRefTableOnly.init();
}
});
}, },
// 监听第一个兄弟组件加载完毕 // 监听第一个兄弟组件加载完毕
// onFirstComponentLoaded(imagesList) { // onFirstComponentLoaded(imagesList) {

View File

@@ -1337,7 +1337,7 @@ export default {
// 5----重新获取加载参考文献 // 5----重新获取加载参考文献
changeRefer(val) { changeRefer(val) {
console.log('重新获取参考文献');
this.$api this.$api
.post('api/Production/getReferList', { .post('api/Production/getReferList', {
p_article_id: this.p_article_id p_article_id: this.p_article_id
@@ -1348,7 +1348,7 @@ export default {
for (var i = 0; i < this.chanFerForm.length; i++) { for (var i = 0; i < this.chanFerForm.length; i++) {
this.chanFerForm[i].edit_mark = 1; this.chanFerForm[i].edit_mark = 1;
} }
console.log(this.chanFerForm);
}) })
.catch((err) => { .catch((err) => {
console.log(err); console.log(err);

View File

@@ -1433,7 +1433,7 @@ export default {
// 5----重新获取加载参考文献 // 5----重新获取加载参考文献
changeRefer(val) { changeRefer(val) {
console.log('重新获取参考文献');
this.$api this.$api
.post('api/Production/getReferList', { .post('api/Production/getReferList', {
p_article_id: this.p_article_id p_article_id: this.p_article_id
@@ -1444,7 +1444,7 @@ export default {
for (var i = 0; i < this.chanFerForm.length; i++) { for (var i = 0; i < this.chanFerForm.length; i++) {
this.chanFerForm[i].edit_mark = 1; this.chanFerForm[i].edit_mark = 1;
} }
console.log(this.chanFerForm);
}) })
.catch((err) => { .catch((err) => {
console.log(err); console.log(err);

View File

@@ -369,7 +369,8 @@
</div> </div>
</div> </div>
</template> </template>
<!-- <slot name="refrences"></slot> --> <div main-id="References"></div>
<slot name="refrences"></slot>
</div> </div>
<el-tabs <el-tabs
@@ -1072,6 +1073,13 @@ export default {
return []; return [];
} }
}, },
chanFerForm: {
type: Array,
default() {
return [];
}
},
comments: { comments: {
type: [Array, Object], // 允许数组或对象 type: [Array, Object], // 允许数组或对象
@@ -1244,6 +1252,44 @@ export default {
} }
}, },
computed: { computed: {
citeMap() {
// 1) 优先使用参考文献列表顺序(与右侧 References 一致)
const mapFromRefs = {};
const refs = Array.isArray(this.chanFerForm) ? this.chanFerForm : [];
refs.forEach((row, idx) => {
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 = /<autocite\s+data-id="(\d+)"/gi;
const paragraphs =
Array.isArray(this.wordList) && this.wordList.length > 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() { sortedProofreadingList() {
const order = [2, 1, 3]; const order = [2, 1, 3];
const rank = { 2: 0, 1: 1, 3: 2 }; const rank = { 2: 0, 1: 1, 3: 2 };
@@ -1355,6 +1401,59 @@ export default {
this.editors = {}; this.editors = {};
}, },
methods: { 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+data-id="(\d+)"\s*><\/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}&#10;DOI: ${doi}`;
});
return `<blue title="${lines.join('&#10;')}">[${label}]<span style="display:none">${groupMatch}</span></blue>`;
});
},
getInvolvedPMain(range) { getInvolvedPMain(range) {
// 1. 找到起始节点所属的 .pMain // 1. 找到起始节点所属的 .pMain
let startNode = range.startContainer; let startNode = range.startContainer;
@@ -3042,7 +3141,7 @@ export default {
const src = String(text || ''); const src = String(text || '');
// 1) 用一个全局、区分大小写不敏感的 wmath 提取正则 // 1) 用一个全局、区分大小写不敏感的 wmath 提取正则
const wmathRe = /<wmath\b[^>]*>[\s\S]*?<\/wmath\s*>/gi; const wmathRe = /<(wmath|autocite)\b[^>]*>[\s\S]*?<\/(wmath|autocite)\s*>/gi;
// 2) 把原文切成: [非wmath片段, wmath片段, 非wmath片段, wmath片段, ...] // 2) 把原文切成: [非wmath片段, wmath片段, 非wmath片段, wmath片段, ...]
const parts = []; const parts = [];
@@ -3133,7 +3232,7 @@ export default {
>${rawHit}</span>`; >${rawHit}</span>`;
html = html.split(ph).join(span); html = html.split(ph).join(span);
}); });
html = this.renderCiteLabels(html);
// 6) 空文本占位图(沿用你的逻辑,且不会影响 wmath // 6) 空文本占位图(沿用你的逻辑,且不会影响 wmath
if (type === 0 && html.trim() === '') { if (type === 0 && html.trim() === '') {
html += `<img contenteditable="false" src="${ html += `<img contenteditable="false" src="${
@@ -3148,7 +3247,7 @@ export default {
const escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); const escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
// 1) 切分出 wmath 与非 wmath 片段 // 1) 切分出 wmath 与非 wmath 片段
const wmathRe = /<wmath\b[^>]*>[\s\S]*?<\/wmath\s*>/gi; const wmathRe = /<(wmath|autocite)\b[^>]*>[\s\S]*?<\/(wmath|autocite)\s*>/gi;
const parts = []; const parts = [];
let lastIdx = 0, let lastIdx = 0,
m; m;
@@ -3218,7 +3317,7 @@ export default {
// 用 split/join 精确回填,避免再走正则 // 用 split/join 精确回填,避免再走正则
html = html.split(ph).join(span); html = html.split(ph).join(span);
}); });
html = this.renderCiteLabels(html);
// 6) 空文本时按你原逻辑补图标(不会影响 wmath // 6) 空文本时按你原逻辑补图标(不会影响 wmath
if (type === 0 && html.trim() === '') { if (type === 0 && html.trim() === '') {
html += `<img contenteditable="false" src="${this.imagePath || ''}" alt="" style="width:20px;height:20px;opacity:.6;">`; html += `<img contenteditable="false" src="${this.imagePath || ''}" alt="" style="width:20px;height:20px;opacity:.6;">`;
@@ -3231,7 +3330,7 @@ export default {
const escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); const escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
// 1) 切分出 wmath 与非 wmath 片段 // 1) 切分出 wmath 与非 wmath 片段
const wmathRe = /<wmath\b[^>]*>[\s\S]*?<\/wmath\s*>/gi; const wmathRe = /<(wmath|autocite)\b[^>]*>[\s\S]*?<\/(wmath|autocite)\s*>/gi;
const parts = []; const parts = [];
let lastIdx = 0, let lastIdx = 0,
m; m;
@@ -3301,7 +3400,7 @@ export default {
// 用 split/join 精确回填,避免再走正则 // 用 split/join 精确回填,避免再走正则
html = html.split(ph).join(span); html = html.split(ph).join(span);
}); });
html = this.renderCiteLabels(html);
// 6) 空文本时按你原逻辑补图标(不会影响 wmath // 6) 空文本时按你原逻辑补图标(不会影响 wmath
if (type === 0 && html.trim() === '') { if (type === 0 && html.trim() === '') {
html += `<img contenteditable="false" src="${this.imagePath || ''}" alt="" style="width:20px;height:20px;opacity:.6;">`; html += `<img contenteditable="false" src="${this.imagePath || ''}" alt="" style="width:20px;height:20px;opacity:.6;">`;
@@ -4192,7 +4291,7 @@ export default {
top: 26px; top: 26px;
left: 0px; left: 0px;
} }
/deep/.rightTabs .first-pane-width { ::v-deep .rightTabs .first-pane-width {
width: 200px; /* 规定第一个面板内容的宽度 */ width: 200px; /* 规定第一个面板内容的宽度 */
} }
.arrow-group { .arrow-group {

File diff suppressed because it is too large Load Diff

View File

@@ -124,7 +124,7 @@ export default {
}, },
// 5----重新获取加载参考文献 // 5----重新获取加载参考文献
changeRefer(val) { changeRefer(val) {
console.log('重新获取参考文献')
this.$api this.$api
.post('api/Production/getReferList', { .post('api/Production/getReferList', {
'p_article_id': this.p_article_id 'p_article_id': this.p_article_id