@@ -890,6 +901,8 @@ export default {
refSelectorSource: 'commonContent',
/** 表格抽屉内合并稿防抖:按全文首次出现顺序更新 articleCiteIdOrder,避免角标停留在列表序号 [38] */
_tableReorderTimer: null,
+ /** 最近一次 getReferList 返回的 p_refer_id 顺序;与当前 chanFerForm 不一致时回写 batchUpdateRefer */
+ _lastReferListApiOrder: null,
/** 打开选择器时若带 currentRefIds(编辑已有引用),排序用「传值计算的顺序」;关闭后清空 */
refSelectorContextIds: [],
/** 选择参考文献弹窗:按 # 序号快速勾选,如 [5, 6, 10-15] */
@@ -1496,6 +1509,7 @@ export default {
p_article_id: this.p_article_id
})
.then((res) => {
+ this._lastReferListApiOrder = this.referIdOrderSnapshot(res.data && res.data.refers).slice();
this.chanFerForm = res.data.refers;
this.chanFerFormRepeatList = Object.values(res.data.repeat || {});
for (let i = 0; i < this.chanFerForm.length; i++) {
@@ -1522,6 +1536,8 @@ export default {
}
/** getReferList 会整表覆盖 chanFerForm,需再按正文首次出现顺序对齐,否则下方列表与 [n] 脱节 */
this.applyRefOrderAfterFetchReferList();
+ /** 正文序与接口序不一致时回写(Main_List 未就绪时可能无变化,getDate 后会再比一次) */
+ this.scheduleTryBatchSyncReferOrderIfOutOfSync();
});
})
.catch((err) => {
@@ -1774,6 +1790,69 @@ export default {
if (sig(next) === sig(refs)) return;
this.chanFerForm = next;
},
+ /**
+ * 将当前 chanFerForm 全文同步到后端(顺序 + 各字段内容与 getReferList 行结构一致)。
+ * 接口:api/References/batchUpdateRefer:p_article_id + list(JSON 字符串,文献对象数组,顺序即保存序)
+ */
+ syncBatchReferenceOrderToServer() {
+ const pid = this.p_article_id;
+ if (pid == null || pid === '') return Promise.resolve();
+ const refs = Array.isArray(this.chanFerForm) ? this.chanFerForm : [];
+ if (refs.length === 0) return Promise.resolve();
+ let listJson;
+ try {
+ listJson = JSON.stringify(JSON.parse(JSON.stringify(refs)));
+ } catch (e) {
+ return Promise.resolve();
+ }
+ return this.$api
+ .post('api/References/batchUpdateRefer', {
+ p_article_id: String(pid),
+ list: listJson
+ })
+ .then((res) => {
+ const ok = res && (res.code === 0 || res.code === 1 || res.status === 1);
+ if (ok) {
+ this._lastReferListApiOrder = this.referIdOrderSnapshot(this.chanFerForm).slice();
+ }
+ if (!ok && res && (res.msg || res.message)) {
+ console.warn('[batchUpdateRefer]', res.msg || res.message);
+ }
+ return res;
+ })
+ .catch((err) => {
+ console.warn('[batchUpdateRefer] request failed', err);
+ });
+ },
+ /** 从 getReferList 原始 refers 提取 p_refer_id 顺序(字符串,便于比较) */
+ referIdOrderSnapshot(refs) {
+ return (Array.isArray(refs) ? refs : [])
+ .map((r) => (r && r.p_refer_id != null ? String(r.p_refer_id) : ''))
+ .filter(Boolean);
+ },
+ /** 当前 chanFerForm 顺序与 _lastReferListApiOrder 不一致则调用 batchUpdateRefer */
+ tryBatchSyncReferOrderIfOutOfSync() {
+ if (this._lastReferListApiOrder == null) return;
+ const track = this._lastReferListApiOrder.map(String);
+ const cur = this.referIdOrderSnapshot(this.chanFerForm);
+ if (cur.length === 0) return;
+ const same = track.length === cur.length && track.every((id, i) => id === cur[i]);
+ if (!same) {
+ this.syncBatchReferenceOrderToServer();
+ }
+ },
+ /**
+ * 等 applyRefOrder / syncRefOrder / 表格抽屉内 nextTick 跑完后再比对顺序。
+ */
+ scheduleTryBatchSyncReferOrderIfOutOfSync() {
+ this.$nextTick(() => {
+ this.$nextTick(() => {
+ this.$nextTick(() => {
+ this.tryBatchSyncReferOrderIfOutOfSync();
+ });
+ });
+ });
+ },
extractBracketCiteNumbersFromText(raw) {
const out = [];
if (!raw || typeof raw !== 'string') return out;
@@ -2278,6 +2357,9 @@ export default {
/** 以接口回写后的 Main_List 再对齐一次;稿面 word 会由 contentList 监听触发 syncRefOrder */
this.$nextTick(() => {
this.reorderReferencesFromMainListBody(null, null);
+ this.$nextTick(() => {
+ this.syncBatchReferenceOrderToServer();
+ });
});
} else {
loading.close();
@@ -3294,6 +3376,8 @@ export default {
/** 正文加载后按 Main_List 扫出全文首次出现顺序,写入 articleCiteIdOrder,弹窗角标与稿面一致 */
this.$nextTick(() => {
this.reorderReferencesFromMainListBody(null, null);
+ /** getReferList 早于 Main_List 时在此才完成正文序重排,与接口序不一致则回写 */
+ this.scheduleTryBatchSyncReferOrderIfOutOfSync();
});
loading.close();
});
@@ -3519,6 +3603,9 @@ export default {
if (w && typeof w.syncRefOrder === 'function') {
w.syncRefOrder();
}
+ this.$nextTick(() => {
+ this.syncBatchReferenceOrderToServer();
+ });
});
} else {
this.$message.error(res.msg);
@@ -3571,6 +3658,9 @@ export default {
if (w && typeof w.syncRefOrder === 'function') {
w.syncRefOrder();
}
+ this.$nextTick(() => {
+ this.syncBatchReferenceOrderToServer();
+ });
});
} else {
this.$message.error(res.msg);
diff --git a/src/components/page/PreIngestedEditor.vue b/src/components/page/PreIngestedEditor.vue
index 9153fbb..0c6ca2f 100644
--- a/src/components/page/PreIngestedEditor.vue
+++ b/src/components/page/PreIngestedEditor.vue
@@ -332,11 +332,11 @@ export default {
// refName: 'setFiveRef',
// rongCont: 'Modify the article body.'
// },
- {
- name: 'Text Proofread',
- refName: 'setThreeRef',
- rongCont: 'HTML layout.'
- }
+ // {
+ // name: 'Text Proofread',
+ // refName: 'setThreeRef',
+ // rongCont: 'HTML layout.'
+ // }
// {
// name: 'Create Build',
// refName: 'setSevenRef',
diff --git a/src/components/page/comArtHtmlCreatNew.vue b/src/components/page/comArtHtmlCreatNew.vue
index 0d923d8..67cf1b4 100644
--- a/src/components/page/comArtHtmlCreatNew.vue
+++ b/src/components/page/comArtHtmlCreatNew.vue
@@ -218,6 +218,8 @@ export default {
refSelectorIsEdit: false,
refSelectedRows: [],
refSelectorSource: 'commonContent',
+ /** 最近一次 getReferList 返回的 p_refer_id 顺序;与当前 chanFerForm 不一致时回写 batchUpdateRefer */
+ _lastReferListApiOrder: null,
/** 打开选择器时若带 currentRefIds(编辑已有引用),排序用「传值计算的顺序」;关闭后清空 */
refSelectorContextIds: [],
/** 选择参考文献弹窗:按 # 序号快速勾选,如 [5, 6, 10-15] */
@@ -448,6 +450,7 @@ export default {
p_article_id: this.p_article_id
})
.then((res) => {
+ this._lastReferListApiOrder = this.referIdOrderSnapshot(res.data && res.data.refers).slice();
this.chanFerForm = res.data.refers;
this.chanFerFormRepeatList = Object.values(res.data.repeat || {});
for (let i = 0; i < this.chanFerForm.length; i++) {
@@ -474,6 +477,7 @@ export default {
}
/** getReferList 会整表覆盖 chanFerForm,需再按正文首次出现顺序对齐,否则下方列表与 [n] 脱节 */
this.applyRefOrderAfterFetchReferList();
+ this.scheduleTryBatchSyncReferOrderIfOutOfSync();
});
})
.catch((err) => {
@@ -647,6 +651,64 @@ export default {
if (sig(next) === sig(refs)) return;
this.chanFerForm = next;
},
+ /**
+ * 将当前 chanFerForm 全文同步到后端(顺序 + 各字段)。
+ * 接口:api/References/batchUpdateRefer:p_article_id + list(JSON 字符串,文献对象数组)
+ */
+ syncBatchReferenceOrderToServer() {
+ const pid = this.p_article_id;
+ if (pid == null || pid === '') return Promise.resolve();
+ const refs = Array.isArray(this.chanFerForm) ? this.chanFerForm : [];
+ if (refs.length === 0) return Promise.resolve();
+ let listJson;
+ try {
+ listJson = JSON.stringify(JSON.parse(JSON.stringify(refs)));
+ } catch (e) {
+ return Promise.resolve();
+ }
+ return this.$api
+ .post('api/References/batchUpdateRefer', {
+ p_article_id: String(pid),
+ list: listJson
+ })
+ .then((res) => {
+ const ok = res && (res.code === 0 || res.code === 1 || res.status === 1);
+ if (ok) {
+ this._lastReferListApiOrder = this.referIdOrderSnapshot(this.chanFerForm).slice();
+ }
+ if (!ok && res && (res.msg || res.message)) {
+ console.warn('[batchUpdateRefer]', res.msg || res.message);
+ }
+ return res;
+ })
+ .catch((err) => {
+ console.warn('[batchUpdateRefer] request failed', err);
+ });
+ },
+ referIdOrderSnapshot(refs) {
+ return (Array.isArray(refs) ? refs : [])
+ .map((r) => (r && r.p_refer_id != null ? String(r.p_refer_id) : ''))
+ .filter(Boolean);
+ },
+ tryBatchSyncReferOrderIfOutOfSync() {
+ if (this._lastReferListApiOrder == null) return;
+ const track = this._lastReferListApiOrder.map(String);
+ const cur = this.referIdOrderSnapshot(this.chanFerForm);
+ if (cur.length === 0) return;
+ const same = track.length === cur.length && track.every((id, i) => id === cur[i]);
+ if (!same) {
+ this.syncBatchReferenceOrderToServer();
+ }
+ },
+ scheduleTryBatchSyncReferOrderIfOutOfSync() {
+ this.$nextTick(() => {
+ this.$nextTick(() => {
+ this.$nextTick(() => {
+ this.tryBatchSyncReferOrderIfOutOfSync();
+ });
+ });
+ });
+ },
/** 编辑弹窗内正文一变立即按全文合并稿重排参考文献(不再防抖,选中/输入后列表马上跟正文一致) */
scheduleReorderFromEditModal(html) {
if (!this.editVisible || !this.currentContent || this.currentContent.am_id == null) return;
@@ -1066,6 +1128,9 @@ export default {
/** 以接口回写后的 Main_List 再对齐一次;稿面 word 会由 contentList 监听触发 syncRefOrder */
this.$nextTick(() => {
this.reorderReferencesFromMainListBody(null, null);
+ this.$nextTick(() => {
+ this.syncBatchReferenceOrderToServer();
+ });
});
} else {
loading.close();
@@ -2078,6 +2143,10 @@ export default {
if (this.$refs.catalogue) {
await this.$refs.catalogue.getCatalogueList();
}
+ this.$nextTick(() => {
+ this.reorderReferencesFromMainListBody(null, null);
+ this.scheduleTryBatchSyncReferOrderIfOutOfSync();
+ });
loading.close();
});
// }, 1000);
@@ -2304,6 +2373,9 @@ export default {
if (w && typeof w.syncRefOrder === 'function') {
w.syncRefOrder();
}
+ this.$nextTick(() => {
+ this.syncBatchReferenceOrderToServer();
+ });
});
} else {
this.$message.error(res.msg);
@@ -2356,6 +2428,9 @@ export default {
if (w && typeof w.syncRefOrder === 'function') {
w.syncRefOrder();
}
+ this.$nextTick(() => {
+ this.syncBatchReferenceOrderToServer();
+ });
});
} else {
this.$message.error(res.msg);
diff --git a/src/components/page/components/Tinymce/index.vue b/src/components/page/components/Tinymce/index.vue
index d164e6e..855de9b 100644
--- a/src/components/page/components/Tinymce/index.vue
+++ b/src/components/page/components/Tinymce/index.vue
@@ -134,6 +134,37 @@ export default {
hasReferencesForAutoLink() {
const refs = Array.isArray(this.chanFerForm) ? this.chanFerForm : [];
return refs.some((r) => r && r.p_refer_id != null && String(r.p_refer_id).trim() !== '');
+ },
+ /**
+ * 表格编辑器专用:接口文献行的 old_index(0 起)+1 = 单元格里 [n] 对应的全局显示序号,再映射到 p_refer_id。
+ * 无 old_index 时返回空对象,自动匹配回退为正文 citeMap。
+ */
+ tableBracketNumToRefIdMap() {
+ const refs = Array.isArray(this.chanFerForm) ? this.chanFerForm : [];
+ const map = {};
+ refs.forEach((r) => {
+ if (!r || r.p_refer_id == null) return;
+ const oi = r.old_index != null && r.old_index !== '' ? r.old_index : r.oldIndex;
+ if (oi == null || oi === '') return;
+ const n = Number(oi);
+ if (Number.isNaN(n)) return;
+ map[n + 1] = String(r.p_refer_id);
+ });
+ return map;
+ },
+ /** p_refer_id → 表格角标序号(old_index+1),用于表格内渲染 [n] 与排序 */
+ tableRefIdToBracketNum() {
+ const refs = Array.isArray(this.chanFerForm) ? this.chanFerForm : [];
+ const m = {};
+ refs.forEach((r) => {
+ if (!r || r.p_refer_id == null) return;
+ const oi = r.old_index != null && r.old_index !== '' ? r.old_index : r.oldIndex;
+ if (oi == null || oi === '') return;
+ const num = Number(oi);
+ if (Number.isNaN(num)) return;
+ m[String(r.p_refer_id)] = num + 1;
+ });
+ return m;
}
},
data() {
@@ -271,7 +302,7 @@ export default {
.map((s) => s.trim())
.filter(Boolean);
},
- /** 与 word.vue renderCiteLabels:tooltip 行按引用序号排序 */
+ /** 与 word.vue renderCiteLabels:合并角标 id 按 citeMap 序号排序 */
sortAutociteIdsByCiteNumber(ids) {
const uniq = [...new Set(ids.map(String))];
const map = this.citeMap || {};
@@ -316,10 +347,62 @@ export default {
});
return map;
},
- /** 解析 [1]、[1,2]、[1–4] 等括号内数字列表(不含方括号) */
+ /** 自动匹配 [n]:表格内用 old_index+1 映射;mytable 之后段落仍用全局 citeMap */
+ _getBracketNumToIdMaps() {
+ const globalMap = this.buildNumToRefIdMap();
+ if (this.type !== 'table') {
+ return { primary: globalMap, afterTable: globalMap };
+ }
+ const tm = this.tableBracketNumToRefIdMap || {};
+ const has = Object.keys(tm).length > 0;
+ return {
+ primary: has ? tm : globalMap,
+ afterTable: globalMap
+ };
+ },
+ sortAutociteIdsByTableBracketNumber(ids) {
+ const uniq = [...new Set(ids.map(String))];
+ const numById = this.tableRefIdToBracketNum || {};
+ return uniq.sort((a, b) => {
+ const na = numById[a];
+ const nb = numById[b];
+ const ha = na != null && na !== '' && !Number.isNaN(Number(na));
+ const hb = nb != null && nb !== '' && !Number.isNaN(Number(nb));
+ if (ha && hb) return Number(na) - Number(nb);
+ if (ha) return -1;
+ if (hb) return 1;
+ return String(a).localeCompare(String(b));
+ });
+ },
+ _sortAutociteIdsForDisplay(ids) {
+ if (this.type === 'table' && Object.keys(this.tableBracketNumToRefIdMap || {}).length > 0) {
+ return this.sortAutociteIdsByTableBracketNumber(ids);
+ }
+ return this.sortAutociteIdsByCiteNumber(ids);
+ },
+ _sortIdsAfterBracketMatch(ids, tableOffset) {
+ if (
+ this.type === 'table' &&
+ tableOffset === 0 &&
+ Object.keys(this.tableBracketNumToRefIdMap || {}).length > 0
+ ) {
+ return this.sortAutociteIdsByTableBracketNumber(ids);
+ }
+ return this.sortAutociteIdsByCiteNumber(ids);
+ },
+ /** 解析 [1]、[1,2]、[1–4]、[1, 2–3, 4] 等括号内数字列表(不含方括号) */
parseBracketInnerToNumbers(inner) {
if (!inner || typeof inner !== 'string') return [];
const t = inner.trim().replace(/,/g, ',');
+ // 先按逗号拆段,再对每段解析单号或区间;避免 parseInt('41-42') 只得到 41
+ if (/[,,]/.test(t)) {
+ const parts = t.split(/[,,]/).map((s) => String(s).trim()).filter(Boolean);
+ const out = [];
+ parts.forEach((part) => {
+ out.push(...this.parseBracketInnerToNumbers(part));
+ });
+ return out;
+ }
const range = t.match(/^(\d+)\s*[-–—]\s*(\d+)$/);
if (range) {
const a = Number(range[1]);
@@ -331,12 +414,6 @@ export default {
for (let i = lo; i <= hi; i++) out.push(i);
return out;
}
- if (/[,,]/.test(t)) {
- return t
- .split(/[,,]/)
- .map((x) => parseInt(String(x).trim(), 10))
- .filter((n) => !Number.isNaN(n));
- }
const n = parseInt(t, 10);
return Number.isNaN(n) ? [] : [n];
},
@@ -352,8 +429,8 @@ export default {
this.$message.warning(this.$t('wordCite.noRefs'));
return { replaced: 0 };
}
- const numToId = this.buildNumToRefIdMap();
- if (Object.keys(numToId).length === 0) {
+ const maps = this._getBracketNumToIdMaps();
+ if (Object.keys(maps.primary).length === 0) {
this.$message.warning(this.$t('wordCite.noRefs'));
return { replaced: 0 };
}
@@ -362,7 +439,7 @@ export default {
if (!body) return { replaced: 0 };
let replaced = 0;
ed.undoManager.transact(() => {
- replaced = this._replaceBracketCitesInDocOrder(body, doc, numToId, { tableOffset: 0 });
+ replaced = this._replaceBracketCitesInDocOrder(body, doc, maps, { tableOffset: 0 });
});
this.renderAutociteInEditor(ed);
ed.fire('change');
@@ -377,8 +454,8 @@ export default {
return;
}
const refs = Array.isArray(this.chanFerForm) ? this.chanFerForm : [];
- const numToId = this.buildNumToRefIdMap();
- if (refs.length && Object.keys(numToId).length) {
+ const maps = this._getBracketNumToIdMaps();
+ if (refs.length && Object.keys(maps.primary).length) {
this.$message.info(this.$t('wordCite.matchBracketRefsNone'));
}
},
@@ -418,9 +495,9 @@ export default {
* 按文档顺序遍历,使「表格链接」后任意后续段落里的 [n] 都能用上该表的最大全局序号偏移。
* 旧实现只在同一父节点下、MYTABLE 与后续文本为兄弟时才生效,MYTABLE 在上一段、角标在下一段时会失效。
*/
- _replaceBracketCitesInDocOrder(node, doc, numToId, state) {
+ _replaceBracketCitesInDocOrder(node, doc, maps, state) {
if (node.nodeType === 3) {
- return this._processTextNodeForBracketCites(node, doc, numToId, state.tableOffset);
+ return this._processTextNodeForBracketCites(node, doc, maps, state.tableOffset);
}
if (node.nodeType !== 1) return 0;
const name = node.nodeName;
@@ -431,7 +508,7 @@ export default {
if (isMytable) {
let total = 0;
Array.from(node.childNodes).forEach((c) => {
- total += this._replaceBracketCitesInDocOrder(c, doc, numToId, state);
+ total += this._replaceBracketCitesInDocOrder(c, doc, maps, state);
});
const tid = (node.getAttribute && node.getAttribute('data-id')) || '';
const map = this.tableLinkCiteMaxMap || {};
@@ -443,11 +520,12 @@ export default {
}
let total = 0;
Array.from(node.childNodes).forEach((c) => {
- total += this._replaceBracketCitesInDocOrder(c, doc, numToId, state);
+ total += this._replaceBracketCitesInDocOrder(c, doc, maps, state);
});
return total;
},
- _processTextNodeForBracketCites(textNode, doc, numToId, tableOffset = 0) {
+ _processTextNodeForBracketCites(textNode, doc, maps, tableOffset = 0) {
+ const numToId = tableOffset > 0 ? maps.afterTable : maps.primary;
const text = textNode.textContent;
const re = /\[([\d\s,,\-–—]+)\]/g;
let m;
@@ -465,11 +543,24 @@ export default {
skippedSpecial++;
continue;
}
+ // 任一序号在参考文献中无对应(含超出列表、tableOffset 后仍无效)则整段不转换,避免部分匹配
+ const mapNo = (n) => (n > 0 && tableOffset > 0 ? n + tableOffset - 1 : n);
+ if (
+ !nums.length ||
+ nums.some((n) => {
+ const mappedNo = mapNo(n);
+ return !numToId[mappedNo];
+ })
+ ) {
+ pieces.push({ type: 'text', s: text.slice(lastIndex, m.index) });
+ pieces.push({ type: 'text', s: m[0] });
+ lastIndex = m.index + m[0].length;
+ continue;
+ }
const ids = [];
const seen = new Set();
nums.forEach((n) => {
- // 表格链接后的局部序号从 tableMax+1 开始接续:1->max+1, 2->max+2 ...
- const mappedNo = n > 0 && tableOffset > 0 ? n + tableOffset - 1 : n;
+ const mappedNo = mapNo(n);
const id = numToId[mappedNo];
if (id && !seen.has(id)) {
seen.add(id);
@@ -478,7 +569,7 @@ export default {
});
pieces.push({ type: 'text', s: text.slice(lastIndex, m.index) });
if (ids.length > 0) {
- const sorted = this.sortAutociteIdsByCiteNumber(ids);
+ const sorted = this._sortIdsAfterBracketMatch(ids, tableOffset);
pieces.push({ type: 'cite', ids: sorted });
replaced++;
} else {
@@ -517,8 +608,8 @@ export default {
if (!body) return;
const allAutocites = Array.from(
ed.dom && typeof ed.dom.select === 'function'
- ? ed.dom.select('mycite', body)
- : body.querySelectorAll('mycite')
+ ? ed.dom.select('mycite,autocite', body)
+ : body.querySelectorAll('mycite, autocite')
);
if (!allAutocites.length) return;
@@ -530,23 +621,30 @@ export default {
});
const citeMap = this.citeMap || {};
+ const tableNums = this.tableRefIdToBracketNum || {};
+ const useTableBracketNums = this.type === 'table' && Object.keys(this.tableBracketNumToRefIdMap || {}).length > 0;
allAutocites.forEach((el) => {
ed.dom.setAttrib(el, 'contenteditable', 'false');
el.style.display = '';
- const sortedAll = this.sortAutociteIdsByCiteNumber(
- this.parseAutociteDataIds(el.getAttribute('data-id'))
- );
+ const sortedAll = this._sortAutociteIdsForDisplay(this.parseAutociteDataIds(el.getAttribute('data-id')));
const validIds = sortedAll.filter((id) => refMap[String(id)]);
if (validIds.length < sortedAll.length) {
ed.dom.setAttrib(el, 'data-id', validIds.length ? validIds.join(',') : '');
}
- const sortedIds = validIds.length ? this.sortAutociteIdsByCiteNumber(validIds) : [];
+ const sortedIds = validIds.length ? this._sortAutociteIdsForDisplay(validIds) : [];
const parts = sortedIds.map((id) => {
const ref = refMap[String(id)];
- const no = ref ? citeMap[String(id)] : null;
- const num = no != null && no !== '' ? String(no) : null;
+ const noCite = ref ? citeMap[String(id)] : null;
+ const noTable =
+ useTableBracketNums && tableNums[String(id)] != null ? tableNums[String(id)] : null;
+ const num =
+ noTable != null && noTable !== '' && !Number.isNaN(Number(noTable))
+ ? String(noTable)
+ : noCite != null && noCite !== ''
+ ? String(noCite)
+ : null;
return { id, ref, num };
});
@@ -556,22 +654,6 @@ export default {
.map(Number);
const label = numsForLabel.length > 0 ? this.formatCiteNumbers(numsForLabel) : '';
- const lines = parts
- .filter((p) => p.ref)
- .map((p) => {
- const ref = p.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 numLabel = p.num;
- if (numLabel) {
- return `[${numLabel}] ${content}\nDOI: ${doi}`;
- }
- return `${content}\nDOI: ${doi}`;
- });
-
if (!label) {
ed.dom.remove(el);
return;
@@ -579,8 +661,18 @@ export default {
el.textContent = `[${label}]`;
el.style.display = '';
- ed.dom.setAttrib(el, 'title', lines.join('\n'));
+ if (el.removeAttribute) el.removeAttribute('title');
ed.dom.setAttrib(el, 'data-cite-missing', null);
+ if (String(el.tagName || '').toLowerCase() === 'autocite') {
+ const doc = ed.getDoc();
+ const nu = doc.createElement('mycite');
+ nu.setAttribute('data-id', el.getAttribute('data-id') || '');
+ nu.setAttribute('contenteditable', 'false');
+ const st = el.getAttribute('style');
+ if (st) nu.setAttribute('style', st);
+ nu.textContent = el.textContent;
+ el.parentNode.replaceChild(nu, el);
+ }
});
this.padAutociteCaretPlaceholder(ed);
},
@@ -589,7 +681,7 @@ export default {
const doc = ed.getDoc();
const body = doc.body;
if (!body) return;
- body.querySelectorAll('mycite').forEach((el) => {
+ body.querySelectorAll('mycite, autocite').forEach((el) => {
const next = el.nextSibling;
if (next === null) {
el.parentNode.appendChild(doc.createTextNode('\u200b'));
@@ -658,8 +750,10 @@ export default {
/** TinyMCE 会剔除「空」的行内标签;空 mycite 必须在入编辑器前占位,否则合并引用 [1–3] 等整段消失 */
normalizeAutociteHtmlForEditor(html) {
if (!html || typeof html !== 'string') return html;
+ // 历史库/表格里可能为
,与 mycite 统一,否则 renderAutociteInEditor 扫不到、无效 id 会残留
+ let out = html.replace(/<\/autocite>/gi, '').replace(/]*)>[\s\S]*?<\/mycite>/gi, '');
+ out = out.replace(/]*)>[\s\S]*?<\/mycite>/gi, '');
// 外侧:连续空格 / 合并为单个 ,避免「普通空格 + 」叠成大缝
out = out.replace(/(?:\s| | )+(?=)(?:\s| | )+/gi, ' ');
@@ -1018,7 +1112,7 @@ export default {
valid_elements:
this.type == 'table'
? '*[*]'
- : `img[src|alt|width|height],strong,em,sub,sup,blue,table,b,i,myfigure,mytable,wmath,mycite[data-id|contenteditable|title|data-cite-missing|style]${this.valid_elements}`, // 允许的标签和属性
+ : `img[src|alt|width|height],strong,em,sub,sup,blue,table,b,i,myfigure,mytable,wmath,mycite[data-id|contenteditable|data-cite-missing|style]${this.valid_elements}`, // 允许的标签和属性(mycite 不使用 title 悬停)
// valid_elements: '*[*]', // 允许所有 HTML 标签
noneditable_editable_class: 'MathJax',
height: this.height,
@@ -1205,7 +1299,7 @@ export default {
});
ed.on('click', function (e) {
- const autociteEl = e.target.closest('mycite');
+ const autociteEl = e.target.closest('mycite') || e.target.closest('autocite');
if (autociteEl) {
const dataIds = _this.parseAutociteDataIds(autociteEl.getAttribute('data-id'));
_this._refBookmark = ed.selection.getBookmark(2);
diff --git a/src/components/page/components/table/word.vue b/src/components/page/components/table/word.vue
index cdd131f..0ece3eb 100644
--- a/src/components/page/components/table/word.vue
+++ b/src/components/page/components/table/word.vue
@@ -997,23 +997,9 @@