/** * 表格弹窗预览:将单元格内空 mycite 转为可见 [n],与 word.vue renderCiteLabels 一致(纯函数,无 Vue 依赖) */ export function 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(', '); } export function sortAutociteIdsByCiteNumber(ids, citeMap) { const map = citeMap || {}; const uniq = [...new Set(ids.map(String))]; return uniq.sort((a, b) => { const na = map[a]; const nb = map[b]; const ha = na != null && na !== ''; const hb = nb != null && nb !== ''; if (ha && hb) return Number(na) - Number(nb); if (ha) return -1; if (hb) return 1; return String(a).localeCompare(String(b)); }); } /** * @param {Array} refs - chanFerForm,项含 p_refer_id * @param {Array} bodyCiteIdOrder - 正文首次出现顺序;空则按列表行序 1..n */ export function buildCiteMapFromRefs(refs, bodyCiteIdOrder) { const refList = Array.isArray(refs) ? refs : []; const refIdSet = new Set( refList.map((r) => (r && r.p_refer_id != null ? String(r.p_refer_id) : '')).filter(Boolean) ); let orderedIds = []; if (Array.isArray(bodyCiteIdOrder) && bodyCiteIdOrder.length > 0) { orderedIds = bodyCiteIdOrder.map(String); } if (orderedIds.length === 0) { const map = {}; refList.forEach((row, idx) => { const key = row && row.p_refer_id != null ? String(row.p_refer_id) : ''; if (key) map[key] = idx + 1; }); return map; } const filtered = []; orderedIds.forEach((id) => { if (refIdSet.has(id) && !filtered.includes(id)) filtered.push(id); }); const map = {}; filtered.forEach((id, idx) => { map[id] = idx + 1; }); let next = filtered.length + 1; refList.forEach((r) => { const key = r && r.p_refer_id != null ? String(r.p_refer_id) : ''; if (!key || map[key] != null) return; map[key] = next++; }); return map; } function escAttr(s) { return String(s || '') .replace(/&/g, '&') .replace(/"/g, '"') .replace(/ 显示序号 */ export function renderCiteLabelsInHtml(html, refs, citeMap) { if (!html || typeof html !== 'string') return html || ''; if (!Array.isArray(refs) || refs.length === 0) return html; /** 与稿面一致:历史/表格 JSON 中可能为 */ let h = html.replace(/<\/autocite>/gi, '').replace(/ { const key = item && item.p_refer_id != null ? String(item.p_refer_id) : ''; if (key) acc[key] = item; return acc; }, {}); let normalized = h.replace(/]*\/?>[\s\S]*?(?:<\/mycite>)?/gi, (fullTag) => { const attrMatch = fullTag.match(/\bdata-id\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+))/i); const dataId = (attrMatch && (attrMatch[1] || attrMatch[2] || attrMatch[3])) || ''; if (!dataId) return ''; return ``; }); const citeGroupRe = /(?:<\/mycite>\s*)+/gi; normalized = normalized.replace(citeGroupRe, (groupMatch) => { const ids = []; const innerRe = /<\/mycite>/gi; let m; while ((m = innerRe.exec(groupMatch)) !== null) { m[1].split(',').forEach((part) => { const id = part.trim(); if (id) ids.push(id); }); } const sortedAll = sortAutociteIdsByCiteNumber(ids, citeMap); const validIds = sortedAll.filter((id) => refMap[id]); const sortedIds = validIds.length ? sortAutociteIdsByCiteNumber(validIds, citeMap) : []; const map = citeMap || {}; const parts = sortedIds.map((id) => { const ref = refMap[id]; const no = ref ? map[id] : null; const num = no != null && no !== '' ? String(no) : null; return { id, ref, num }; }); const numsForLabel = parts .map((p) => p.num) .filter((n) => n != null && n !== '') .map(Number); const label = numsForLabel.length > 0 ? formatCiteNumbers(numsForLabel) : ''; if (!label) { return ''; } const dataIdAttr = escAttr(sortedIds.join(',')); return `[${label}]`; }); return normalized.replace(/]*data-id=""[^>]*>[\s\S]*?<\/mycite>/gi, ''); } export function applyCiteLabelsToTableRows(rows, refs, citeMap) { if (!Array.isArray(rows) || !rows.length) return rows; if (!Array.isArray(refs) || refs.length === 0) return rows; return rows.map((row) => { if (!Array.isArray(row)) return row; const nextRow = row.map((cell) => { if (!cell || typeof cell !== 'object') return cell; const t = cell.text; const lower = typeof t === 'string' ? t.toLowerCase() : ''; if (!lower || (!lower.includes('mycite') && !lower.includes('autocite'))) return cell; const next = renderCiteLabelsInHtml(t, refs, citeMap); if (next === t) return cell; return { ...cell, text: next }; }); // TableUtils.addRowIdToData 会给数组行对象挂 rowId,渲染 oddColor 依赖它,不能在 map 后丢失 if (row.rowId != null) { nextRow.rowId = row.rowId; } return nextRow; }); }