Files
ai-agent-admin/backend-fastapi/online_dev/report_manager/engine/merge_recalc.py
T

84 lines
2.9 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""扩展后 mergeData 行偏移重算"""
from __future__ import annotations
import copy
from typing import Any, Dict, List, Tuple
def _int(v: Any, default: int = 0) -> int:
try:
return int(v)
except (TypeError, ValueError):
return default
def compute_row_insertions(
before: Dict[str, Any],
after: Dict[str, Any],
) -> Dict[str, List[Tuple[int, int]]]:
"""
对比扩展前后 cellData 行数,推断每个 sheet 在各行插入的额外行数。
返回 sheet_id -> [(anchor_row, rows_added), ...](按 anchor_row 升序)。
"""
insertions: Dict[str, List[Tuple[int, int]]] = {}
before_sheets = (before or {}).get("sheets") or {}
after_sheets = (after or {}).get("sheets") or {}
for sheet_id, after_sheet in after_sheets.items():
before_sheet = before_sheets.get(sheet_id) or {}
before_rows = sorted(int(k) for k in (before_sheet.get("cellData") or {}).keys())
after_rows = sorted(int(k) for k in (after_sheet.get("cellData") or {}).keys())
if len(after_rows) <= len(before_rows):
continue
added = len(after_rows) - len(before_rows)
# 默认在最后一个原数据行之后插入(legacy down band 常见模式)
anchor = before_rows[-1] if before_rows else 0
insertions.setdefault(sheet_id, []).append((anchor, added))
return insertions
def recalculate_merge_data(
snapshot: Dict[str, Any],
row_insertions: Dict[str, List[Tuple[int, int]]],
) -> Dict[str, Any]:
"""按行插入量下移 merge 区域(仅处理 startRow/endRow)。"""
if not row_insertions:
return snapshot
result = copy.deepcopy(snapshot)
sheets = result.get("sheets") or {}
for sheet_id, inserts in row_insertions.items():
sheet = sheets.get(sheet_id)
if not sheet:
continue
merge_list = sheet.get("mergeData") or []
if not merge_list:
continue
sorted_inserts = sorted(inserts, key=lambda x: x[0])
new_merges: List[Any] = []
for region in merge_list:
if not isinstance(region, dict):
new_merges.append(region)
continue
start_row = _int(region.get("startRow"), 0)
end_row = _int(region.get("endRow"), start_row)
shift = 0
for anchor, delta in sorted_inserts:
if start_row > anchor:
shift += delta
if shift:
region = {**region, "startRow": start_row + shift, "endRow": end_row + shift}
new_merges.append(region)
sheet["mergeData"] = new_merges
return result
def apply_merge_recalc_after_expand(
original_snapshot: Dict[str, Any],
expanded_snapshot: Dict[str, Any],
) -> Dict[str, Any]:
insertions = compute_row_insertions(original_snapshot, expanded_snapshot)
return recalculate_merge_data(expanded_snapshot, insertions)