From 95b52b4d06becd0e103201f85ac496846ad2b6de 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, 2 Apr 2026 10:56:37 +0800
Subject: [PATCH] =?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/components/common/langs/en.js | 7 +-
src/components/common/langs/zh.js | 7 +-
src/components/page/GenerateCharts.vue | 74 ++++++++-
.../page/components/Tinymce/index.vue | 141 ++++++++++++++++--
.../page/components/table/content.vue | 26 +++-
5 files changed, 234 insertions(+), 21 deletions(-)
diff --git a/src/components/common/langs/en.js b/src/components/common/langs/en.js
index 121ff73..30e97d0 100644
--- a/src/components/common/langs/en.js
+++ b/src/components/common/langs/en.js
@@ -1152,7 +1152,12 @@ colTitle: 'Template title',
placeholder: 'Please enter email content'
},
wordCite: {
- notFoundById: 'No reference found for citation ID {id}'
+ notFoundById: 'No reference found for citation ID {id}',
+ selectRef: 'Select Reference',
+ reference: 'Reference',
+ cancel: 'Cancel',
+ confirm: 'Confirm',
+ remove: 'Remove'
}
diff --git a/src/components/common/langs/zh.js b/src/components/common/langs/zh.js
index 88aea53..a6d16ba 100644
--- a/src/components/common/langs/zh.js
+++ b/src/components/common/langs/zh.js
@@ -1137,7 +1137,12 @@ const zh = {
placeholder: '请输入邮件内容'
},
wordCite: {
- notFoundById: '未查询到编号{id}相关参考文献'
+ notFoundById: '未查询到编号{id}相关参考文献',
+ selectRef: '选择参考文献',
+ reference: '参考文献',
+ cancel: '取消',
+ confirm: '确认',
+ remove: '移除'
}
diff --git a/src/components/page/GenerateCharts.vue b/src/components/page/GenerateCharts.vue
index dccd520..1e0601c 100644
--- a/src/components/page/GenerateCharts.vue
+++ b/src/components/page/GenerateCharts.vue
@@ -388,6 +388,8 @@
:value="currentContent.content"
@getContent="getContent"
@openLatexEditor="openLatexEditor"
+ @openRefSelector="handleOpenRefSelector"
+ :chanFerForm="chanFerForm"
v-if="editVisible"
ref="commonContent"
style="margin-left: -115px"
@@ -422,6 +424,8 @@
@getContent="getContent"
type="content"
@openLatexEditor="openLatexEditor"
+ @openRefSelector="handleOpenRefSelector"
+ :chanFerForm="chanFerForm"
v-if="addContentVisible"
ref="addContent"
style="margin-left: -115px"
@@ -439,6 +443,40 @@
+
+
+
+
+
+
+ {{ scope.row.refer_frag || [scope.row.author, scope.row.title, scope.row.joura, scope.row.dateno].filter(Boolean).join(' ') || '-' }}
+
+
+
+
+ {{ scope.row.doilink || scope.row.doi || scope.row.isbn || '-' }}
+
+
+
+
+
@@ -576,7 +614,11 @@ export default {
exegesis: "The following contents','are necessary for the generation phase, please do not delete them!!!",
p_article_id: null,
chanFerForm: [],
- chanFerFormRepeatList: []
+ chanFerFormRepeatList: [],
+ refSelectorVisible: false,
+ refSelectorCurrentRefId: null,
+ refSelectedRow: null,
+ refSelectorSource: 'commonContent'
};
},
components: {
@@ -685,6 +727,36 @@ export default {
console.log(err);
});
},
+ handleOpenRefSelector(data) {
+ this.refSelectorCurrentRefId = data && data.currentRefId ? data.currentRefId : null;
+ this.refSelectedRow = null;
+ if (this.editVisible) {
+ this.refSelectorSource = 'commonContent';
+ } else if (this.addContentVisible) {
+ this.refSelectorSource = 'addContent';
+ }
+ this.refSelectorVisible = true;
+ },
+ handleRefCurrentChange(row) {
+ this.refSelectedRow = row;
+ },
+ handleConfirmRefCite() {
+ if (!this.refSelectedRow) return;
+ const ref = this.$refs[this.refSelectorSource];
+ if (ref) {
+ ref.insertAutocite(this.refSelectedRow.p_refer_id);
+ }
+ this.refSelectorVisible = false;
+ this.refSelectedRow = null;
+ },
+ handleRemoveRefCite() {
+ const ref = this.$refs[this.refSelectorSource];
+ if (ref) {
+ ref.removeAutocite();
+ }
+ this.refSelectorVisible = false;
+ this.refSelectedRow = null;
+ },
ChanFerMashUp(e) {
this.$api
.post('api/Production/referHB', e)
diff --git a/src/components/page/components/Tinymce/index.vue b/src/components/page/components/Tinymce/index.vue
index 3e5a49c..cfa1c18 100644
--- a/src/components/page/components/Tinymce/index.vue
+++ b/src/components/page/components/Tinymce/index.vue
@@ -63,6 +63,21 @@ export default {
},
articleId: {
default: ''
+ },
+ chanFerForm: {
+ type: Array,
+ default: () => []
+ }
+ },
+ computed: {
+ citeMap() {
+ const map = {};
+ 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) map[key] = idx + 1;
+ });
+ return map;
}
},
data() {
@@ -129,17 +144,22 @@ export default {
},
watch: {
value: {
-
handler(val) {
-
-
- if (!this.hasChange && this.hasInit) {
- this.$nextTick(() => {
- window.tinymce.get(this.tinymceId).setContent(val);
- });
- }
+ if (!this.hasChange && this.hasInit) {
+ this.$nextTick(() => {
+ window.tinymce.get(this.tinymceId).setContent(val);
+ });
+ }
+ },
+ immediate: true
},
- immediate: true
+ chanFerForm: {
+ handler() {
+ if (this.editorInstance) {
+ this.renderAutociteInEditor(this.editorInstance);
+ }
+ },
+ deep: true
}
},
mounted() {
@@ -163,6 +183,60 @@ export default {
this.destroyTinymce();
},
methods: {
+ renderAutociteInEditor(ed) {
+ const body = ed.getBody();
+ if (!body) return;
+ const autocites = body.querySelectorAll('autocite');
+ const refs = Array.isArray(this.chanFerForm) ? this.chanFerForm : [];
+ const refMap = {};
+ refs.forEach((item) => {
+ const key = item && item.p_refer_id != null ? String(item.p_refer_id) : '';
+ if (key) refMap[key] = item;
+ });
+
+ autocites.forEach((el) => {
+ ed.dom.setAttrib(el, 'contenteditable', 'false');
+ const dataId = el.getAttribute('data-id');
+ const num = this.citeMap[String(dataId)];
+ el.textContent = num != null ? `[${num}]` : '[?]';
+
+ const ref = refMap[String(dataId)];
+ if (ref) {
+ 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 || '';
+ const tip = `[${num || '?'}] ${content}${doi ? '\nDOI: ' + doi : ''}`;
+ ed.dom.setAttrib(el, 'title', tip);
+ } else {
+ ed.dom.setAttrib(el, 'title', this.$t('wordCite.notFoundById', { id: num != null ? num : dataId }));
+ }
+ });
+ },
+ insertAutocite(refId) {
+ const ed = this.editorInstance;
+ if (!ed) return;
+ if (this._editingAutocite) {
+ this._editingAutocite.setAttribute('data-id', refId);
+ const num = this.citeMap[String(refId)];
+ this._editingAutocite.textContent = num != null ? `[${num}]` : '[?]';
+ this._editingAutocite = null;
+ ed.fire('change');
+ } else {
+ if (this._refBookmark) {
+ ed.selection.moveToBookmark(this._refBookmark);
+ }
+ const num = this.citeMap[String(refId)];
+ const label = num != null ? `[${num}]` : '[?]';
+ const html = `${label}`;
+ ed.insertContent(html);
+ }
+ },
+ removeAutocite() {
+ const ed = this.editorInstance;
+ if (!ed || !this._editingAutocite) return;
+ ed.dom.remove(this._editingAutocite);
+ this._editingAutocite = null;
+ ed.fire('change');
+ },
handleSetContent(val) {
if (!this.editorInstance) return;
@@ -497,9 +571,9 @@ export default {
window.tinymce.init({
..._this.tinymceOtherInit,
trim_span_elements: false, // 禁止修剪内联标签周围的空格
- extended_valid_elements: 'blue[*]',
- custom_elements: 'blue',
- valid_children: '+blue[#text|i|em|b|strong|span],+body[blue],+p[blue]',
+ extended_valid_elements: 'blue[*],autocite[*]',
+ custom_elements: 'blue,autocite',
+ valid_children: '+blue[#text|i|em|b|strong|span],+body[blue|autocite],+p[blue|autocite]',
inline: false, // 使用 iframe 模式
selector: `#${this.tinymceId}`,
@@ -509,7 +583,7 @@ export default {
valid_elements:
this.type == 'table'
? '*[*]'
- : `img[src|alt|width|height],strong,em,sub,sup,blue,table,b,i,myfigure,mytable,wmath${this.valid_elements}`, // 允许的标签和属性
+ : `img[src|alt|width|height],strong,em,sub,sup,blue,table,b,i,myfigure,mytable,wmath,autocite[data-id|contenteditable|title]${this.valid_elements}`, // 允许的标签和属性
// valid_elements: '*[*]', // 允许所有 HTML 标签
noneditable_editable_class: 'MathJax',
height: this.height,
@@ -541,6 +615,22 @@ export default {
font-weight: bold !important;
}
+ autocite {
+ display: inline-block;
+ color: rgb(0, 130, 170);
+ font-weight: bold;
+ cursor: pointer;
+ padding: 0 2px;
+ border-radius: 3px;
+ background-color: rgba(0, 130, 170, 0.08);
+ user-select: all;
+ font-size: 12px;
+ }
+ autocite:hover {
+ background-color: rgba(0, 130, 170, 0.2);
+ text-shadow: 0 0 3px rgba(0, 130, 170, 0.3);
+ }
+
@keyframes blueGlow {
0%,
100% {
@@ -626,7 +716,27 @@ export default {
let currentPasteImages = [];
_this.$commonJS.initEditorButton(_this, ed);
var currentWmathElement = null;
+
+ ed.ui.registry.addButton('insertRef', {
+ text: 'Ref',
+ tooltip: 'Insert Reference',
+ onAction: function () {
+ _this._refBookmark = ed.selection.getBookmark(2);
+ _this._editingAutocite = null;
+ _this.$emit('openRefSelector', { currentRefId: null });
+ }
+ });
+
ed.on('click', function (e) {
+ const autociteEl = e.target.closest('autocite');
+ if (autociteEl) {
+ const dataId = autociteEl.getAttribute('data-id');
+ _this._refBookmark = ed.selection.getBookmark(2);
+ _this._editingAutocite = autociteEl;
+ _this.$emit('openRefSelector', { currentRefId: dataId });
+ return;
+ }
+
const wmathElement = e.target.closest('wmath');
if (wmathElement) {
currentWmathElement = wmathElement; // 保存当前点击的元素
@@ -791,14 +901,15 @@ export default {
const editorBody = ed.getBody();
ed.dom.select('wmath', editorBody).forEach(function (wmathElement) {
ed.dom.setAttrib(wmathElement, 'contenteditable', 'false');
- // ed.dom.addClass(wmathElement, 'non-editable-wmath');
});
+ _this.renderAutociteInEditor(ed);
e.content = e.content.replace(//g, '').replace(/<\/strong>/g, '');
e.content = e.content.replace(//g, '').replace(/<\/em>/g, '');
});
ed.on('GetContent', function (e) {
e.content = e.content.replace(//g, '').replace(/<\/b>/g, '');
- e.content = e.content.replace(//g, '').replace(/<\/i>/g, '');
+ e.content = e.content.replace(//g, '').replace(/<\/em>/g, '');
+ e.content = e.content.replace(/]*)>[^<]*<\/autocite>/gi, '');
});
},
paste_preprocess: function (plugin, args) {
diff --git a/src/components/page/components/table/content.vue b/src/components/page/components/table/content.vue
index bd9782b..71c1def 100644
--- a/src/components/page/components/table/content.vue
+++ b/src/components/page/components/table/content.vue
@@ -12,11 +12,13 @@
:isAutomaticUpdate="isAutomaticUpdate"
@getContent="getContent"
@openLatexEditor="openLatexEditor"
+ @openRefSelector="openRefSelector"
@updateChange="updateChange"
:value="value"
+ :chanFerForm="chanFerForm"
:typesettingType="typesettingType"
class="paste-area text-container"
- :toolbar="!isAutomaticUpdate?['bold italic |customBlue removeBlue|LateX| myuppercase myuppercasea Line MoreSymbols|subscript superscript|clearButton|searchreplace']:['bold italic |customBlue removeBlue| myuppercase myuppercasea Line MoreSymbols|subscript superscript|clearButton|searchreplace']"
+ :toolbar="toolbarConfig"
style="
/* white-space: pre-line; */
line-height: 12px;
@@ -36,10 +38,20 @@