feat: restore source parity and harden agent runtime

This commit is contained in:
2026-06-22 11:17:26 +08:00
parent e33f08277b
commit 0793eb82d6
596 changed files with 168879 additions and 290 deletions
@@ -0,0 +1,149 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
数据源聚合(polymerizationType
1 / select — 列表
2 / group — 分组
3 / summary — 汇总(summaryType: sum|avg|max|min|count
"""
from __future__ import annotations
from dataclasses import dataclass
from decimal import Decimal
from typing import Any, Dict, List, Optional
from online_dev.report_manager.engine.parent_cells import _get_nested_value, resolve_field_path
@dataclass
class BindData:
value: Any
data_list: List[Dict[str, Any]]
def _field_name(cell: Dict[str, Any]) -> str:
custom = cell.get("custom") or {}
return str(custom.get("field") or custom.get("bindField") or "")
def _poly_type(cell: Dict[str, Any]) -> str:
custom = cell.get("custom") or {}
raw = custom.get("polymerizationType")
if raw is None:
return "1"
return str(raw)
def _summary_type(cell: Dict[str, Any]) -> str:
custom = cell.get("custom") or {}
return str(custom.get("summaryType") or "sum").lower()
def _group_type(cell: Dict[str, Any]) -> str:
custom = cell.get("custom") or {}
return str(custom.get("groupType") or "default")
def _dataset_name(cell: Dict[str, Any]) -> str:
custom = cell.get("custom") or {}
name = str(
custom.get("dataSetName") or custom.get("dataSet") or custom.get("alias") or ""
)
if name:
return name
field = str(custom.get("field") or custom.get("bindField") or "")
if "." in field:
return field.split(".", 1)[0]
return ""
def build_bind_list(cell: Dict[str, Any], rows: List[Dict[str, Any]]) -> List[BindData]:
poly = _poly_type(cell)
field = resolve_field_path(_field_name(cell), _dataset_name(cell))
prop = field.split(".")[-1] if "." in field else field
if poly == "3":
return [_summary_bind(cell, rows, field)]
if poly == "2":
return _group_bind(rows, prop, _group_type(cell))
return _list_bind(rows, field)
def _list_bind(rows: List[Dict[str, Any]], field: str) -> List[BindData]:
out: List[BindData] = []
for row in rows:
val = _get_nested_value(row, field)
out.append(BindData(value=val, data_list=[row]))
if not out:
out.append(BindData(value="", data_list=[{}]))
return out
def _group_bind(
rows: List[Dict[str, Any]], prop: str, group_type: str
) -> List[BindData]:
if group_type == "adjacent":
return _group_adjacent(rows, prop)
ordered: Dict[Any, List[Dict[str, Any]]] = {}
for row in rows:
key = _get_nested_value(row, prop)
if key is None:
key = ""
ordered.setdefault(key, []).append(row)
return [
BindData(value=k, data_list=ordered[k]) for k in ordered.keys()
]
def _group_adjacent(rows: List[Dict[str, Any]], prop: str) -> List[BindData]:
out: List[BindData] = []
bucket: List[Dict[str, Any]] = []
last_key: Any = object()
for row in rows:
key = _get_nested_value(row, prop)
if key is None:
key = ""
if bucket and key != last_key:
out.append(BindData(value=last_key, data_list=bucket))
bucket = []
bucket.append(row)
last_key = key
if bucket:
out.append(BindData(value=last_key, data_list=bucket))
if not out:
out.append(BindData(value="", data_list=[{}]))
return out
def _summary_bind(cell: Dict[str, Any], rows: List[Dict[str, Any]], field: str) -> BindData:
st = _summary_type(cell)
nums: List[Decimal] = []
for row in rows:
v = _get_nested_value(row, field)
try:
nums.append(Decimal(str(v)))
except Exception:
pass
if st == "count":
val: Any = len(rows)
elif st == "avg":
val = float(sum(nums) / len(nums)) if nums else 0
elif st == "max":
val = float(max(nums)) if nums else 0
elif st == "min":
val = float(min(nums)) if nums else 0
else:
val = float(sum(nums)) if nums else 0
return BindData(value=val, data_list=rows)
def expand_span(bind: BindData, cell: Dict[str, Any]) -> int:
"""该 bind 在向下/向右扩展时占用的行/列数。"""
poly = _poly_type(cell)
if poly == "3":
return 1
if poly == "2":
return 1
return max(1, len(bind.data_list))