参考文献的暂存

This commit is contained in:
2026-04-09 09:39:58 +08:00
parent c4b86be0d5
commit 7527a6ef54
4 changed files with 188 additions and 35 deletions

View File

@@ -412,6 +412,7 @@
@openRefSelector="handleOpenRefSelector"
:chanFerForm="chanFerForm"
:body-cite-id-order="editModalBodyCiteOrder"
:table-link-cite-max-map="tableLinkCiteMaxMap"
@editorInput="onEditModalEditorInput"
v-if="editVisible"
ref="commonContent"
@@ -1032,6 +1033,49 @@ export default {
const order = this.extractAutociteOrderFromMainList(this.Main_List, this.currentContent.am_id, draft);
return order.length > 0 ? order : this.articleCiteIdOrder;
},
/**
* mytable(data-id) -> 该表格中已出现引用的最大全局序号
* 用于正文链接表格后,后续 [2,3] 按“表内最大序号之后”继续映射(如 33,34
*/
tableLinkCiteMaxMap() {
const out = {};
const list = Array.isArray(this.Main_List) ? this.Main_List : [];
if (!list.length) return out;
const order = Array.isArray(this.editModalBodyCiteOrder) ? this.editModalBodyCiteOrder : this.articleCiteIdOrder;
const citeMap = this.buildDisplayCiteMap(order || []);
list.forEach((p) => {
if (!p || Number(p.type) !== 2) return;
const candidates = this.collectCiteHtmlSourcesForMainListItem(p);
const ids = [];
candidates.forEach((raw) => {
extractAutociteIdsFromHtmlString(raw).forEach((id) => {
if (!ids.includes(id)) ids.push(id);
});
});
const numsFromIds = ids
.map((id) => Number(citeMap[String(id)]))
.filter((n) => !Number.isNaN(n) && n > 0);
// 兜底:有些表格仍是纯文本 [34](未转 mycite这里直接取括号数字最大值参与 max
const numsFromPlain = [];
candidates.forEach((raw) => {
this.extractBracketCiteNumbersFromText(raw).forEach((n) => numsFromPlain.push(n));
});
const nums = [...numsFromIds, ...numsFromPlain];
const max = nums.length ? Math.max(...nums) : 0;
if (max <= 0) return;
if (p.am_id != null) out[String(p.am_id)] = max;
if (p.amt_id != null) out[String(p.amt_id)] = max;
if (p.p_main_table_id != null) out[String(p.p_main_table_id)] = max;
if (p.table) {
if (p.table.amt_id != null) out[String(p.table.amt_id)] = max;
if (p.table.am_id != null) out[String(p.table.am_id)] = max;
if (p.table.p_main_table_id != null) out[String(p.table.p_main_table_id)] = max;
if (p.table.table_id != null) out[String(p.table.table_id)] = max;
}
});
console.log('[tableLinkCiteMaxMap]', out);
return out;
},
/** 表格抽屉内角标:与 Edit Content 同源,按 Main_List + Title/表/Note 合并稿做全文首次出现排序,避免仍用 articleCiteIdOrder 列表下标 [38] */
tableModalBodyCiteOrder() {
if (!this.threeVisible || !this.lineStyle || this.lineStyle.am_id == null) {
@@ -1728,6 +1772,8 @@ export default {
pushRows(t.tableContent);
}
if (typeof t.note === 'string' && t.note.trim()) out.push(t.note);
// 兜底:不同接口版本的表体字段名不一致,深度扫描 table 对象里所有可能含引用的字符串字段。
this.collectCiteStringsDeep(t, out);
return out;
}
if (typ === 1 && p.image) {
@@ -1744,6 +1790,58 @@ export default {
if (p && typeof p.content === 'string' && p.content.trim()) out.push(p.content);
return out;
},
/**
* 递归收集对象中的字符串字段,覆盖 html/text/content 等异构字段名。
* 仅保留看起来可能包含引用信息的片段,避免噪音过大。
*/
collectCiteStringsDeep(source, out, depth = 0) {
if (!source || depth > 6) return;
if (typeof source === 'string') {
const s = source.trim();
if (!s) return;
const maybeCite = /<(?:mycite|autocite)\b/i.test(s) || /\[[\d\s,\-–—]+\]/.test(s);
if (maybeCite) out.push(s);
return;
}
if (Array.isArray(source)) {
source.forEach((item) => this.collectCiteStringsDeep(item, out, depth + 1));
return;
}
if (typeof source === 'object') {
Object.keys(source).forEach((k) => {
const v = source[k];
this.collectCiteStringsDeep(v, out, depth + 1);
});
}
},
extractBracketCiteNumbersFromText(raw) {
const out = [];
if (!raw || typeof raw !== 'string') return out;
const text = raw.replace(/<[^>]+>/g, ' ');
const re = /\[([\d\s,\-–—]+)\]/g;
let m;
while ((m = re.exec(text)) !== null) {
const inner = String(m[1] || '').trim().replace(//g, ',');
if (!inner) continue;
const range = inner.match(/^(\d+)\s*[-–—]\s*(\d+)$/);
if (range) {
const a = Number(range[1]);
const b = Number(range[2]);
if (!Number.isNaN(a) && !Number.isNaN(b)) {
const lo = Math.min(a, b);
const hi = Math.max(a, b);
for (let i = lo; i <= hi; i++) out.push(i);
}
continue;
}
inner
.split(',')
.map((x) => parseInt(String(x).trim(), 10))
.filter((n) => !Number.isNaN(n) && n > 0)
.forEach((n) => out.push(n));
}
return out;
},
/** 与 word.vue 一致:从各段 HTML 中按出现顺序收集 autocite含表格单元格、表题、表注、图题图注 */
extractAutociteOrderFromMainList(mainList, draftAmId, draftHtml) {
const list = Array.isArray(mainList) ? mainList : [];
@@ -2172,12 +2270,21 @@ export default {
this.saveContent(newContent, mainId);
},
handleConfirmLink(selectedMedia) {
const targetId = selectedMedia.select.amt_id || selectedMedia.select.ami_id;
const select = (selectedMedia && selectedMedia.select) || {};
// 不同列表来源字段不一致:表可能是 amt_id / am_id图可能是 ami_id / am_id
const targetId =
select.amt_id ||
select.ami_id ||
select.am_id ||
select.p_main_table_id ||
select.table_id ||
(select.table &&
(select.table.amt_id || select.table.am_id || select.table.p_main_table_id || select.table.table_id));
const type = selectedMedia.type;
const tagName = `my${type}`;
let originalContent = selectedMedia.linkData.content;
const label = selectedMedia.linkData.label;
if (!label || !originalContent) return;
if (!label || !originalContent || targetId == null || targetId === '') return;
const isAlreadyTagged = label.startsWith('<my') && label.endsWith('>');
let newContent = '';
if (isAlreadyTagged) {