参考文献
This commit is contained in:
@@ -737,6 +737,10 @@ import bottomTinymce from '@/components/page/components/Tinymce';
|
||||
import catalogue from '@/components/page/components/table/catalogue.vue';
|
||||
import editPublicRefTableOnly from './editPublicRefTableOnly.vue';
|
||||
import { extractAutociteIdsFromHtmlString } from '@/utils/autociteHtml.js';
|
||||
import {
|
||||
collectCiteHtmlSourcesForMainListItem,
|
||||
extractAutociteOrderFromMainList
|
||||
} from '@/utils/autociteMainListOrder.js';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -1030,7 +1034,7 @@ export default {
|
||||
if (draft == null || draft === '') {
|
||||
return this.articleCiteIdOrder;
|
||||
}
|
||||
const order = this.extractAutociteOrderFromMainList(this.Main_List, this.currentContent.am_id, draft);
|
||||
const order = extractAutociteOrderFromMainList(this.Main_List, this.currentContent.am_id, draft);
|
||||
return order.length > 0 ? order : this.articleCiteIdOrder;
|
||||
},
|
||||
/**
|
||||
@@ -1045,7 +1049,7 @@ export default {
|
||||
const citeMap = this.buildDisplayCiteMap(order || []);
|
||||
list.forEach((p) => {
|
||||
if (!p || Number(p.type) !== 2) return;
|
||||
const candidates = this.collectCiteHtmlSourcesForMainListItem(p);
|
||||
const candidates = collectCiteHtmlSourcesForMainListItem(p);
|
||||
const ids = [];
|
||||
candidates.forEach((raw) => {
|
||||
extractAutociteIdsFromHtmlString(raw).forEach((id) => {
|
||||
@@ -1073,7 +1077,6 @@ export default {
|
||||
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] */
|
||||
@@ -1085,7 +1088,12 @@ export default {
|
||||
if (draft == null || draft === '') {
|
||||
return this.articleCiteIdOrder;
|
||||
}
|
||||
const order = this.extractAutociteOrderFromMainList(this.Main_List, this.lineStyle.am_id, draft);
|
||||
/** 正文里 <mytable> 指向本表时,展开用当前抽屉合并稿,角标与「全文该 mytable 之前」顺序一致 */
|
||||
const citeOpts = {
|
||||
tableDraftAmId: this.lineStyle.am_id,
|
||||
tableDraftHtml: draft
|
||||
};
|
||||
const order = extractAutociteOrderFromMainList(this.Main_List, this.lineStyle.am_id, draft, citeOpts);
|
||||
return order.length > 0 ? order : this.articleCiteIdOrder;
|
||||
}
|
||||
},
|
||||
@@ -1535,9 +1543,10 @@ export default {
|
||||
* 按 Main_List 各段正文中 mycite 首次出现顺序重排参考文献。
|
||||
* draftAmId + draftHtml:合并「当前将保存的这一段」后再扫全文(点 Save 时与保存后一致);
|
||||
* 传 (null, null) 表示完全以 Main_List 已存 content 为准。
|
||||
* citeOptions:Edit Table 时传入 { tableDraftAmId, tableDraftHtml },使正文 mytable 展开与抽屉稿一致。
|
||||
*/
|
||||
reorderReferencesFromMainListBody(draftAmId, draftHtml) {
|
||||
const order = this.extractAutociteOrderFromMainList(this.Main_List, draftAmId, draftHtml);
|
||||
reorderReferencesFromMainListBody(draftAmId, draftHtml, citeOptions) {
|
||||
const order = extractAutociteOrderFromMainList(this.Main_List, draftAmId, draftHtml, citeOptions || {});
|
||||
if (order.length > 0) {
|
||||
this.handleReorderReferencesByBody(order);
|
||||
}
|
||||
@@ -1587,7 +1596,11 @@ export default {
|
||||
this.reorderReferencesFromMainListBody(null, null);
|
||||
return;
|
||||
}
|
||||
this.reorderReferencesFromMainListBody(this.lineStyle.am_id, html);
|
||||
const citeOpts = {
|
||||
tableDraftAmId: this.lineStyle.am_id,
|
||||
tableDraftHtml: html
|
||||
};
|
||||
this.reorderReferencesFromMainListBody(this.lineStyle.am_id, html, citeOpts);
|
||||
},
|
||||
scheduleFlushReorderFromTableModal() {
|
||||
if (!this.threeVisible || !this.lineStyle || this.lineStyle.am_id == null) return;
|
||||
@@ -1743,77 +1756,6 @@ export default {
|
||||
if (sig(next) === sig(refs)) return;
|
||||
this.chanFerForm = next;
|
||||
},
|
||||
/**
|
||||
* 单条 Main_List 段内、与稿面阅读顺序一致的 HTML 片段(用于统计 mycite 顺序)。
|
||||
* 表格段:标题 → 表体(html_data 或逐单元格 text)→ Note;图段:标题 → 说明。
|
||||
*/
|
||||
collectCiteHtmlSourcesForMainListItem(p, draftAmId, draftHtml) {
|
||||
if (draftAmId != null && p && p.am_id == draftAmId && draftHtml != null) {
|
||||
return [draftHtml];
|
||||
}
|
||||
const out = [];
|
||||
const typ = p != null && p.type != null ? Number(p.type) : NaN;
|
||||
if (typ === 2 && p.table) {
|
||||
const t = p.table;
|
||||
if (typeof t.title === 'string' && t.title.trim()) out.push(t.title);
|
||||
if (typeof t.html_data === 'string' && t.html_data.trim()) {
|
||||
out.push(t.html_data);
|
||||
} else {
|
||||
const pushRows = (rows) => {
|
||||
if (!Array.isArray(rows)) return;
|
||||
rows.forEach((row) => {
|
||||
if (!Array.isArray(row)) return;
|
||||
row.forEach((cell) => {
|
||||
if (cell && typeof cell.text === 'string' && cell.text) out.push(cell.text);
|
||||
});
|
||||
});
|
||||
};
|
||||
pushRows(t.tableHeader);
|
||||
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) {
|
||||
const img = p.image;
|
||||
if (typeof img.title === 'string' && img.title.trim()) out.push(img.title);
|
||||
if (typeof img.note === 'string' && img.note.trim()) out.push(img.note);
|
||||
if (out.length === 0) {
|
||||
if (p && typeof p.content === 'string' && p.content.trim()) out.push(p.content);
|
||||
if (p && typeof p.text === 'string' && p.text.trim()) out.push(p.text);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
if (p && typeof p.text === 'string' && p.text.trim()) out.push(p.text);
|
||||
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;
|
||||
@@ -1842,20 +1784,6 @@ export default {
|
||||
}
|
||||
return out;
|
||||
},
|
||||
/** 与 word.vue 一致:从各段 HTML 中按出现顺序收集 autocite(含表格单元格、表题、表注、图题图注) */
|
||||
extractAutociteOrderFromMainList(mainList, draftAmId, draftHtml) {
|
||||
const list = Array.isArray(mainList) ? mainList : [];
|
||||
const order = [];
|
||||
list.forEach((p) => {
|
||||
const candidates = this.collectCiteHtmlSourcesForMainListItem(p, draftAmId, draftHtml);
|
||||
candidates.forEach((raw) => {
|
||||
extractAutociteIdsFromHtmlString(raw).forEach((id) => {
|
||||
if (!order.includes(id)) order.push(id);
|
||||
});
|
||||
});
|
||||
});
|
||||
return order;
|
||||
},
|
||||
/** 编辑弹窗内正文一变立即按全文合并稿重排参考文献(不再防抖,选中/输入后列表马上跟正文一致) */
|
||||
scheduleReorderFromEditModal(html) {
|
||||
if (!this.editVisible || !this.currentContent || this.currentContent.am_id == null) return;
|
||||
@@ -1866,7 +1794,7 @@ export default {
|
||||
/** 立即按全文合并稿重排参考文献顺序(插入引用后调用,避免编号长期停留在列表序号 [8]) */
|
||||
flushReorderFromEditModal(html) {
|
||||
if (!this.editVisible || !this.currentContent || this.currentContent.am_id == null) return;
|
||||
let order = this.extractAutociteOrderFromMainList(this.Main_List, this.currentContent.am_id, html);
|
||||
let order = extractAutociteOrderFromMainList(this.Main_List, this.currentContent.am_id, html);
|
||||
if (order.length === 0 && html && /(autocite|mycite)/i.test(html)) {
|
||||
order = extractAutociteIdsFromHtmlString(html);
|
||||
}
|
||||
|
||||
@@ -82,6 +82,7 @@ import bottomTinymce from '@/components/page/components/Tinymce';
|
||||
import catalogue from '@/components/page/components/table/catalogue.vue';
|
||||
import editPublicRefTableOnly from './editPublicRefTableOnly.vue';
|
||||
import { extractAutociteIdsFromHtmlString } from '@/utils/autociteHtml.js';
|
||||
import { extractAutociteOrderFromMainList } from '@/utils/autociteMainListOrder.js';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -327,7 +328,7 @@ export default {
|
||||
if (draft == null || draft === '') {
|
||||
return this.articleCiteIdOrder;
|
||||
}
|
||||
const order = this.extractAutociteOrderFromMainList(this.Main_List, this.currentContent.am_id, draft);
|
||||
const order = extractAutociteOrderFromMainList(this.Main_List, this.currentContent.am_id, draft);
|
||||
return order.length > 0 ? order : this.articleCiteIdOrder;
|
||||
}
|
||||
},
|
||||
@@ -508,7 +509,7 @@ export default {
|
||||
* 传 (null, null) 表示完全以 Main_List 已存 content 为准。
|
||||
*/
|
||||
reorderReferencesFromMainListBody(draftAmId, draftHtml) {
|
||||
const order = this.extractAutociteOrderFromMainList(this.Main_List, draftAmId, draftHtml);
|
||||
const order = extractAutociteOrderFromMainList(this.Main_List, draftAmId, draftHtml);
|
||||
if (order.length > 0) {
|
||||
this.handleReorderReferencesByBody(order);
|
||||
}
|
||||
@@ -646,65 +647,6 @@ export default {
|
||||
if (sig(next) === sig(refs)) return;
|
||||
this.chanFerForm = next;
|
||||
},
|
||||
/**
|
||||
* 单条 Main_List 段内、与稿面阅读顺序一致的 HTML 片段(用于统计 mycite 顺序)。
|
||||
* 表格段:标题 → 表体(html_data 或逐单元格 text)→ Note;图段:标题 → 说明。
|
||||
*/
|
||||
collectCiteHtmlSourcesForMainListItem(p, draftAmId, draftHtml) {
|
||||
if (draftAmId != null && p && p.am_id == draftAmId && draftHtml != null) {
|
||||
return [draftHtml];
|
||||
}
|
||||
const out = [];
|
||||
const typ = p != null && p.type != null ? Number(p.type) : NaN;
|
||||
if (typ === 2 && p.table) {
|
||||
const t = p.table;
|
||||
if (typeof t.title === 'string' && t.title.trim()) out.push(t.title);
|
||||
if (typeof t.html_data === 'string' && t.html_data.trim()) {
|
||||
out.push(t.html_data);
|
||||
} else {
|
||||
const pushRows = (rows) => {
|
||||
if (!Array.isArray(rows)) return;
|
||||
rows.forEach((row) => {
|
||||
if (!Array.isArray(row)) return;
|
||||
row.forEach((cell) => {
|
||||
if (cell && typeof cell.text === 'string' && cell.text) out.push(cell.text);
|
||||
});
|
||||
});
|
||||
};
|
||||
pushRows(t.tableHeader);
|
||||
pushRows(t.tableContent);
|
||||
}
|
||||
if (typeof t.note === 'string' && t.note.trim()) out.push(t.note);
|
||||
return out;
|
||||
}
|
||||
if (typ === 1 && p.image) {
|
||||
const img = p.image;
|
||||
if (typeof img.title === 'string' && img.title.trim()) out.push(img.title);
|
||||
if (typeof img.note === 'string' && img.note.trim()) out.push(img.note);
|
||||
if (out.length === 0) {
|
||||
if (p && typeof p.content === 'string' && p.content.trim()) out.push(p.content);
|
||||
if (p && typeof p.text === 'string' && p.text.trim()) out.push(p.text);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
if (p && typeof p.text === 'string' && p.text.trim()) out.push(p.text);
|
||||
if (p && typeof p.content === 'string' && p.content.trim()) out.push(p.content);
|
||||
return out;
|
||||
},
|
||||
/** 与 word.vue 一致:从各段 HTML 中按出现顺序收集 autocite(含表格单元格、表题、表注、图题图注) */
|
||||
extractAutociteOrderFromMainList(mainList, draftAmId, draftHtml) {
|
||||
const list = Array.isArray(mainList) ? mainList : [];
|
||||
const order = [];
|
||||
list.forEach((p) => {
|
||||
const candidates = this.collectCiteHtmlSourcesForMainListItem(p, draftAmId, draftHtml);
|
||||
candidates.forEach((raw) => {
|
||||
extractAutociteIdsFromHtmlString(raw).forEach((id) => {
|
||||
if (!order.includes(id)) order.push(id);
|
||||
});
|
||||
});
|
||||
});
|
||||
return order;
|
||||
},
|
||||
/** 编辑弹窗内正文一变立即按全文合并稿重排参考文献(不再防抖,选中/输入后列表马上跟正文一致) */
|
||||
scheduleReorderFromEditModal(html) {
|
||||
if (!this.editVisible || !this.currentContent || this.currentContent.am_id == null) return;
|
||||
@@ -715,7 +657,7 @@ export default {
|
||||
/** 立即按全文合并稿重排参考文献顺序(插入引用后调用,避免编号长期停留在列表序号 [8]) */
|
||||
flushReorderFromEditModal(html) {
|
||||
if (!this.editVisible || !this.currentContent || this.currentContent.am_id == null) return;
|
||||
let order = this.extractAutociteOrderFromMainList(this.Main_List, this.currentContent.am_id, html);
|
||||
let order = extractAutociteOrderFromMainList(this.Main_List, this.currentContent.am_id, html);
|
||||
if (order.length === 0 && html && /mycite/i.test(html)) {
|
||||
order = extractAutociteIdsFromHtmlString(html);
|
||||
}
|
||||
|
||||
@@ -436,7 +436,6 @@ export default {
|
||||
const tid = (node.getAttribute && node.getAttribute('data-id')) || '';
|
||||
const map = this.tableLinkCiteMaxMap || {};
|
||||
const tableMax = Number(map[String(tid)]);
|
||||
console.log('[autolink/mytable]', { tid, tableMax, map });
|
||||
if (!Number.isNaN(tableMax) && tableMax > 0) {
|
||||
state.tableOffset = tableMax;
|
||||
}
|
||||
@@ -472,13 +471,6 @@ export default {
|
||||
// 表格链接后的局部序号从 tableMax+1 开始接续:1->max+1, 2->max+2 ...
|
||||
const mappedNo = n > 0 && tableOffset > 0 ? n + tableOffset - 1 : n;
|
||||
const id = numToId[mappedNo];
|
||||
console.log('[autolink/map]', {
|
||||
rawBracket: m[0],
|
||||
n,
|
||||
tableOffset,
|
||||
mappedNo,
|
||||
id
|
||||
});
|
||||
if (id && !seen.has(id)) {
|
||||
seen.add(id);
|
||||
ids.push(id);
|
||||
@@ -545,14 +537,12 @@ export default {
|
||||
const sortedAll = this.sortAutociteIdsByCiteNumber(
|
||||
this.parseAutociteDataIds(el.getAttribute('data-id'))
|
||||
);
|
||||
/** 已删除的文献 id 从角标中忽略,并写回 data-id,仅保留仍存在于列表中的 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 parts = sortedIds.map((id) => {
|
||||
const ref = refMap[String(id)];
|
||||
const no = ref ? citeMap[String(id)] : null;
|
||||
@@ -564,8 +554,7 @@ export default {
|
||||
.map((p) => p.num)
|
||||
.filter((n) => n != null && n !== '')
|
||||
.map(Number);
|
||||
const label =
|
||||
numsForLabel.length > 0 ? this.formatCiteNumbers(numsForLabel) : '';
|
||||
const label = numsForLabel.length > 0 ? this.formatCiteNumbers(numsForLabel) : '';
|
||||
|
||||
const lines = parts
|
||||
.filter((p) => p.ref)
|
||||
@@ -583,7 +572,6 @@ export default {
|
||||
return `${content}\nDOI: ${doi}`;
|
||||
});
|
||||
|
||||
/** 无可展示序号或全部 id 已失效时,直接移除节点,不保留空标签 */
|
||||
if (!label) {
|
||||
ed.dom.remove(el);
|
||||
return;
|
||||
@@ -592,7 +580,6 @@ export default {
|
||||
el.textContent = `[${label}]`;
|
||||
el.style.display = '';
|
||||
ed.dom.setAttrib(el, 'title', lines.join('\n'));
|
||||
/** 不再使用 data-cite-missing 红底提示,角标样式与普通引用一致 */
|
||||
ed.dom.setAttrib(el, 'data-cite-missing', null);
|
||||
});
|
||||
this.padAutociteCaretPlaceholder(ed);
|
||||
|
||||
@@ -1076,6 +1076,7 @@ import { TableUtils } from '@/common/js/TableUtils';
|
||||
import { debounce, throttle } from '@/common/js/debounce';
|
||||
import { tableStyle, commonWordStyle } from '@/utils/tinymceStyles';
|
||||
import { extractAutociteIdsFromHtmlString } from '@/utils/autociteHtml.js';
|
||||
import { extractAutociteOrderFromMainList } from '@/utils/autociteMainListOrder.js';
|
||||
export default {
|
||||
name: 'tinymce',
|
||||
components: {},
|
||||
@@ -2531,22 +2532,9 @@ renderCiteLabels(html) {
|
||||
}, 0);
|
||||
},
|
||||
syncRefOrder() {
|
||||
const root = this.$refs.scrollDiv;
|
||||
if (!root) return;
|
||||
const nodes = root.querySelectorAll('mycite');
|
||||
const seen = new Set();
|
||||
const order = [];
|
||||
nodes.forEach((el) => {
|
||||
const raw = el.getAttribute('data-id') || '';
|
||||
raw.split(',').forEach((part) => {
|
||||
const id = part.trim();
|
||||
if (!id) return;
|
||||
if (!seen.has(id)) {
|
||||
seen.add(id);
|
||||
order.push(id);
|
||||
}
|
||||
});
|
||||
});
|
||||
/** 与 GenerateCharts extractAutociteOrderFromMainList 一致:Main_List 顺序 + 正文内 mytable 处插入表内引用后再计后续角标(勿用 DOM 中 mycite 顺序,否则稿面与弹窗不一致) */
|
||||
const list = this.contentList || [];
|
||||
const order = extractAutociteOrderFromMainList(list, null, null);
|
||||
const prev = this.bodyCiteIdOrder || [];
|
||||
const sameBody =
|
||||
order.length === prev.length && order.every((id, i) => String(id) === String(prev[i]));
|
||||
|
||||
161
src/utils/autociteMainListOrder.js
Normal file
161
src/utils/autociteMainListOrder.js
Normal file
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
* Main_List 全文首次出现顺序(与 Edit Content / 稿面 / 底部参考文献列表共用)。
|
||||
* 正文中 <mytable> 占位处需先插入对应表格段在 Main_List 中的表题/表体/表注引用,再计其后的 mycite。
|
||||
*/
|
||||
import { extractAutociteIdsFromHtmlString } from '@/utils/autociteHtml.js';
|
||||
|
||||
export function 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) => collectCiteStringsDeep(item, out, depth + 1));
|
||||
return;
|
||||
}
|
||||
if (typeof source === 'object') {
|
||||
Object.keys(source).forEach((k) => {
|
||||
const v = source[k];
|
||||
collectCiteStringsDeep(v, out, depth + 1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function collectCiteHtmlSourcesForMainListItem(p, draftAmId, draftHtml) {
|
||||
if (draftAmId != null && p && p.am_id == draftAmId && draftHtml != null) {
|
||||
return [draftHtml];
|
||||
}
|
||||
const out = [];
|
||||
const typ = p != null && p.type != null ? Number(p.type) : NaN;
|
||||
if (typ === 2 && p.table) {
|
||||
const t = p.table;
|
||||
if (typeof t.title === 'string' && t.title.trim()) out.push(t.title);
|
||||
if (typeof t.html_data === 'string' && t.html_data.trim()) {
|
||||
out.push(t.html_data);
|
||||
} else {
|
||||
const pushRows = (rows) => {
|
||||
if (!Array.isArray(rows)) return;
|
||||
rows.forEach((row) => {
|
||||
if (!Array.isArray(row)) return;
|
||||
row.forEach((cell) => {
|
||||
if (cell && typeof cell.text === 'string' && cell.text) out.push(cell.text);
|
||||
});
|
||||
});
|
||||
};
|
||||
pushRows(t.tableHeader);
|
||||
pushRows(t.tableContent);
|
||||
}
|
||||
if (typeof t.note === 'string' && t.note.trim()) out.push(t.note);
|
||||
collectCiteStringsDeep(t, out);
|
||||
return out;
|
||||
}
|
||||
if (typ === 1 && p.image) {
|
||||
const img = p.image;
|
||||
if (typeof img.title === 'string' && img.title.trim()) out.push(img.title);
|
||||
if (typeof img.note === 'string' && img.note.trim()) out.push(img.note);
|
||||
if (out.length === 0) {
|
||||
if (p && typeof p.content === 'string' && p.content.trim()) out.push(p.content);
|
||||
if (p && typeof p.text === 'string' && p.text.trim()) out.push(p.text);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
if (p && typeof p.text === 'string' && p.text.trim()) out.push(p.text);
|
||||
if (p && typeof p.content === 'string' && p.content.trim()) out.push(p.content);
|
||||
return out;
|
||||
}
|
||||
|
||||
export function findMainListTableByLinkId(mainList, rawId) {
|
||||
if (rawId == null || String(rawId).trim() === '') return null;
|
||||
const sid = String(rawId).trim();
|
||||
const list = Array.isArray(mainList) ? mainList : [];
|
||||
return (
|
||||
list.find((p) => {
|
||||
if (!p || Number(p.type) !== 2) return false;
|
||||
if (String(p.amt_id) === sid) return true;
|
||||
if (String(p.am_id) === sid) return true;
|
||||
if (p.p_main_table_id != null && String(p.p_main_table_id) === sid) return true;
|
||||
if (p.table && p.table.amt_id != null && String(p.table.amt_id) === sid) return true;
|
||||
if (p.table && p.table.am_id != null && String(p.table.am_id) === sid) return true;
|
||||
if (p.table && p.table.p_main_table_id != null && String(p.table.p_main_table_id) === sid)
|
||||
return true;
|
||||
if (p.table && p.table.table_id != null && String(p.table.table_id) === sid) return true;
|
||||
return false;
|
||||
}) || null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {object} [options]
|
||||
* @param {number|string|null} [options.tableDraftAmId] 正在编辑的表格段 am_id(Edit Table 抽屉)
|
||||
* @param {string|null} [options.tableDraftHtml] 与该表对应的 Title+表体+Note 合并稿;正文里 mytable 展开到该表时用此稿替代 Main_List 已存内容,使「全文 mytable 之前」的序号与抽屉内一致
|
||||
*/
|
||||
export function extractAutociteOrderFromDraftHtmlWithInlineTables(html, mainList, options = {}) {
|
||||
const order = [];
|
||||
const pushUnique = (id) => {
|
||||
if (id && !order.includes(id)) order.push(id);
|
||||
};
|
||||
const pushFromRaw = (raw) => {
|
||||
extractAutociteIdsFromHtmlString(raw).forEach((id) => pushUnique(id));
|
||||
};
|
||||
if (!html || typeof html !== 'string') return order;
|
||||
|
||||
const re = /<mytable\b[^>]*>[\s\S]*?<\/mytable>/gi;
|
||||
let last = 0;
|
||||
let m;
|
||||
while ((m = re.exec(html)) !== null) {
|
||||
const before = html.slice(last, m.index);
|
||||
if (before) pushFromRaw(before);
|
||||
|
||||
const openEnd = html.indexOf('>', m.index) + 1;
|
||||
const openTag = html.slice(m.index, openEnd);
|
||||
const dm = openTag.match(/\bdata-id\s*=\s*["']([^"']*)["']/i);
|
||||
const tid = dm ? String(dm[1]).trim() : '';
|
||||
const tableP = findMainListTableByLinkId(mainList, tid);
|
||||
if (tableP) {
|
||||
const useDraft =
|
||||
options.tableDraftAmId != null &&
|
||||
options.tableDraftHtml != null &&
|
||||
String(tableP.am_id) === String(options.tableDraftAmId);
|
||||
const sources = useDraft
|
||||
? [options.tableDraftHtml]
|
||||
: collectCiteHtmlSourcesForMainListItem(tableP, null, null);
|
||||
sources.forEach((raw) => pushFromRaw(raw));
|
||||
}
|
||||
|
||||
last = m.index + m[0].length;
|
||||
}
|
||||
const after = html.slice(last);
|
||||
if (after) pushFromRaw(after);
|
||||
|
||||
return order;
|
||||
}
|
||||
|
||||
export function extractAutociteOrderFromMainList(mainList, draftAmId, draftHtml, options = {}) {
|
||||
const list = Array.isArray(mainList) ? mainList : [];
|
||||
const order = [];
|
||||
list.forEach((p) => {
|
||||
if (draftAmId != null && p && p.am_id == draftAmId && draftHtml != null) {
|
||||
extractAutociteOrderFromDraftHtmlWithInlineTables(draftHtml, list, options).forEach((id) => {
|
||||
if (!order.includes(id)) order.push(id);
|
||||
});
|
||||
return;
|
||||
}
|
||||
const candidates = collectCiteHtmlSourcesForMainListItem(p, draftAmId, draftHtml);
|
||||
candidates.forEach((raw) => {
|
||||
if (typeof raw === 'string' && /<mytable\b/i.test(raw)) {
|
||||
extractAutociteOrderFromDraftHtmlWithInlineTables(raw, list, options).forEach((id) => {
|
||||
if (!order.includes(id)) order.push(id);
|
||||
});
|
||||
} else {
|
||||
extractAutociteIdsFromHtmlString(raw).forEach((id) => {
|
||||
if (!order.includes(id)) order.push(id);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
return order;
|
||||
}
|
||||
Reference in New Issue
Block a user