feat(query-tool): rewrite frontend with ECharts tree, multi-select, and modular composables

Replace the monolithic useQueryToolData composable and nested Vue component tree
with a modular architecture: useLotResolve, useLotLineage, useLotDetail, and
useEquipmentQuery. Introduce ECharts TreeChart (LR orthogonal layout) for lot
lineage visualization with multi-select support, subtree expansion, zoom/pan,
and serial number normalization. Add unified LineageEngine backend with split
descendant traversal and leaf serial number queries. Archive the query-tool-rewrite
openspec change and sync delta specs to main.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
egg
2026-02-13 15:25:00 +08:00
parent 653900dc15
commit 5b358d71c1
56 changed files with 7458 additions and 6201 deletions

View File

@@ -130,7 +130,20 @@ def test_resolve_full_genealogy_combines_split_and_merge(
result = LineageEngine.resolve_full_genealogy(["A"], {"A": "LOT-A"})
assert result == {"A": {"B", "C", "M1", "M0"}}
assert result["ancestors"] == {"A": {"B", "C", "M1", "M0"}}
assert result["cid_to_name"]["A"] == "LOT-A"
assert result["cid_to_name"]["M0"] == "LOT-M0"
# parent_map should have direct edges only
pm = result["parent_map"]
assert pm["A"] == ["B"]
assert pm["B"] == ["C", "M1"] or set(pm["B"]) == {"C", "M1"}
assert pm["M1"] == ["M0"]
# merge_edges: B → M1 (LOT-B matched merge source)
me = result["merge_edges"]
assert "M1" in me.get("B", [])
assert mock_resolve_split_ancestors.call_count == 2
mock_resolve_merge_sources.assert_called_once()