371 lines
20 KiB
Markdown
371 lines
20 KiB
Markdown
# 天璇 (TianXuan) — Agent Knowledge Base
|
||
|
||
## Project Identity
|
||
|
||
| Field | Value |
|
||
|-------|-------|
|
||
| 项目名称 | 天璇 (TianXuan) |
|
||
| 原始名称 | tls-analyzer |
|
||
| 核心功能 | TLS 流数据分析、实体画像、聚类 3D 地球可视化、UMAP/SVD 降维散点图 |
|
||
| Python 版本 | 3.12 (embedded portable at `runtime/python/python.exe`) |
|
||
| Polars 版本 | 1.42.1 (精确锁定) |
|
||
| 数据框架 | Polars (LazyFrame + streaming) |
|
||
| 机器学习 | scikit-learn (HDBSCAN, KMeans, MiniBatchKMeans, IsolationForest), UMAP, TruncatedSVD, StandardScaler |
|
||
| Web 框架 | Django 4.2 + SQLite WAL |
|
||
| 前端 3D | Three.js (603KB, 离线, 地球贴图 1.4MB) |
|
||
| 前端图表 | 纯 Canvas 2D 散点图 / Canvas 地理分布 |
|
||
| LLM 协议 | MCP (stdio transport) + OpenAI 兼容 API |
|
||
| 启动方式 | `run.bat` (双击即用, 非阻塞, 打印 PID 后退出) / `runtime\python\python.exe manage.py runserver` (开发) |
|
||
| 目标设备 | Windows 10 1909+, 8GB RAM, 无独立显卡 (核显), 支持 2500 CSV × 10000 行 × 50~58 列 |
|
||
|
||
## Project Structure
|
||
|
||
```
|
||
天璇/
|
||
├── tianxuan/ Django 项目配置
|
||
│ ├── settings.py ALLOWED_HOSTS 自动检测, LOGGING 文件+stderr
|
||
│ ├── wsgi.py SQLite 启动自修复
|
||
│ ├── urls.py 路由汇总
|
||
│ └── llm_orchestrator.py LLM 编排 (策略式提示词, 自动错误恢复)
|
||
├── analysis/ 核心分析模块 (Django app)
|
||
│ ├── views/ 视图包 (12 模块, 原 views.py 拆分)
|
||
│ │ ├── __init__.py 重导出所有视图函数
|
||
│ │ ├── helpers.py 辅助函数
|
||
│ │ ├── dashboard.py 首页 + 运行记录
|
||
│ │ ├── pipeline.py 管道执行器
|
||
│ │ ├── clustering.py 聚类概览/详情/地球数据
|
||
│ │ ├── entity.py 实体画像页
|
||
│ │ ├── upload.py CSV 上传
|
||
│ │ ├── manual.py 手动分析工作流构建器
|
||
│ │ ├── auto.py LLM 自动分析
|
||
│ │ ├── globe.py 3D 地球数据接口
|
||
│ │ ├── config.py 配置编辑 + LLM 测试
|
||
│ │ ├── log_viewer.py 日志查看器
|
||
│ │ └── tools.py 工具实验室
|
||
│ ├── tools/ 工具包 (17 模块, 30 个 MCP 工具实现)
|
||
│ │ ├── __init__.py 重导出所有 handler
|
||
│ │ ├── _registry.py 工具元数据 (Tool descriptor + get_tools_meta)
|
||
│ │ ├── _dispatch.py 工具调用分发 (handle_call)
|
||
│ │ ├── _helpers.py 共享辅助 (过滤表达式构建/响应截断/数据集决议/数值列检测)
|
||
│ │ ├── load_data.py 工具 1: load_data
|
||
│ │ ├── profile.py 工具 2: profile_data
|
||
│ │ ├── filter.py 工具 3: filter_data
|
||
│ │ ├── preprocess.py 工具 4: preprocess_data
|
||
│ │ ├── clustering.py 工具 5+8: run_clustering, filter_and_cluster
|
||
│ │ ├── evaluate.py 工具 6: evaluate_clustering
|
||
│ │ ├── features.py 工具 7: extract_features (+ UMAP 嵌入)
|
||
│ │ ├── entities.py 工具 9+10: build_entity_profiles, compute_scores
|
||
│ │ ├── anomalies.py 工具 11+12: detect_anomalies, visualize_anomalies
|
||
│ │ ├── export.py 工具 13: export_results
|
||
│ │ ├── analysis.py 工具 14-19: analyze_patterns/temporal/fft/tls_health/geo_distribution/entity_detail
|
||
│ │ ├── diagnostics.py 工具 20-26: validate_data/explore_distributions/find_outliers/diagnose_clustering/compare_datasets/export_debug_sample/repair_schema
|
||
│ │ ├── data_mgmt.py 工具 27-29: list_datasets/drop_dataset/clone_dataset
|
||
│ │ └── distance_matrix.py 工具 30: compute_distance_matrix
|
||
│ ├── tool_registry.py 旧编排层 (薄包装, 重导出 tools/)
|
||
│ ├── mcp_server.py MCP stdio server
|
||
│ ├── data_loader.py CSV 加载底层 (BOM/编码/schema 容错/递归 glob/ZIP 解压)
|
||
│ ├── data_profiler.py 列统计 + 相关性矩阵
|
||
│ ├── data_validator.py 列校验 (缺失/异常值/IP 有效性)
|
||
│ ├── type_classifier.py 值优先类型检测 (MAC/端口/IPv4/URL/HEX/ENUM/LAT_LON/BOOL_ENUM/TIMESTAMP)
|
||
│ ├── geoip.py GeoIP 经纬度查询
|
||
│ ├── ip_clustering.py IP 子网聚类与转换
|
||
│ ├── session_store.py 线程安全单例内存存储
|
||
│ ├── distance.py 距离计算 (IP 子网/地理/Levenshtein/Hamming/FFT 相位)
|
||
│ ├── models.py ORM: AnalysisRun, ClusterResult, EntityProfile, ClusterFeature
|
||
│ ├── urls.py 路由注册
|
||
│ ├── nl_describe.py 自然语言数据描述
|
||
│ ├── profile_util.py 画像工具函数
|
||
│ ├── tls_ref.py TLS 版本/加密套件参考数据
|
||
│ ├── db_utils.py SQLite WAL 工具 + 锁重试
|
||
│ ├── constants.py 全局常量
|
||
│ ├── appdata.py 应用数据路径 (%APPDATA%/TianXuan)
|
||
│ └── management/commands/
|
||
│ ├── start_mcp.py MCP 服务器启动命令
|
||
│ ├── run_pipeline.py 一键 CLI 管道命令
|
||
│ └── import_tlsdb.py TLS 数据库导入
|
||
├── config/ 配置管理
|
||
│ ├── config.yaml 自动生成默认配置 (entity, server, data, clustering, llm)
|
||
│ ├── loader.py Pydantic 配置加载 + 文件修改检测 + 缓存
|
||
│ └── __init__.py
|
||
├── templates/ 页面模板 (13 个 HTML)
|
||
│ ├── base.html 导航: 首页/上传/手动/LLM/记录/地球/配置
|
||
│ ├── analysis/ 分析页面 (6 个)
|
||
│ │ ├── dashboard.html 首页 — 最近运行
|
||
│ │ ├── run_list.html 运行记录列表
|
||
│ │ ├── run_detail.html 运行详情摘要
|
||
│ │ ├── cluster_overview.html 聚类概览 — Canvas 散点图 (PC1/PC2) + 地理分布 + Silhouette
|
||
│ │ ├── cluster_detail.html 簇详情 — 特征实体列表
|
||
│ │ └── entity_profile.html 实体画像 — 特征偏离 + Canvas 单点
|
||
│ └── tianxuan/ 功能页面 (6 个)
|
||
│ ├── upload.html CSV 上传 — 拖拽+多文件删除+进度
|
||
│ ├── manual.html 手动分析 — 工作流构建器 (添加/排序/保存/执行)
|
||
│ ├── auto.html LLM 自动分析 — 实时日志, thinking panel, 工具调用折叠
|
||
│ ├── globe.html 3D 地球 — Three.js 流量弧线 + 经纬线 + 国境线
|
||
│ ├── config.html 配置编辑 — LLM 连通性测试
|
||
│ └── log_viewer.html 日志查看
|
||
├── static/tianxuan/ 离线静态资源
|
||
│ ├── three.min.js Three.js 3D 引擎 (603KB)
|
||
│ ├── earth_atmos_2048.jpg 地球贴图 (1.4MB)
|
||
│ └── world_borders.js 177 国完整国境线 (269KB)
|
||
├── runtime/python/ 便携 Python 3.12 运行时 (~593MB)
|
||
├── scripts/ 工具脚本
|
||
│ ├── gen_test_data.py 简单测试数据生成
|
||
│ ├── gen_complex_test.py 复杂数据生成 (5000 行 含 55% 缺失)
|
||
│ ├── column_survey.py CSV 列结构调查
|
||
│ ├── diagnose_compare.py 跨机日志对比诊断
|
||
│ └── debug_db.py DB 持久化调试
|
||
├── tests/ 测试
|
||
│ ├── test_e2e_full.py 全端到端测试
|
||
│ ├── test_e2e_batch.py 批量端到端测试
|
||
│ ├── start_srv.py 测试服务器启动辅助
|
||
│ └── _test_hdbscan.py HDBSCAN 零样本降级测试
|
||
├── data/ 数据目录
|
||
│ └── geoip_data.txt GeoIP 离线数据库
|
||
├── logs/ 日志输出
|
||
│ └── tianxuan.log 主日志文件
|
||
├── docs/
|
||
│ ├── 工作流.md 完整分析流水线文档
|
||
│ └── 故障诊断手册.md 跨机问题诊断指南
|
||
├── run.bat 用户启动入口 (含 PYTHONUTF8=1)
|
||
├── shell.bat Django shell
|
||
├── update.bat 增量更新
|
||
├── rollback.bat 更新回滚
|
||
├── build.bat 构建打包
|
||
├── TlsDB.csv 参考表头名清单
|
||
├── README.md
|
||
├── AGENTS.md
|
||
└── manage.py
|
||
```
|
||
|
||
## 30 MCP Tools
|
||
|
||
系统现有 **30 个 MCP 工具**, 分四层, 实现于 `analysis/tools/` 包的 14 个 handler 模块:
|
||
|
||
### ⚡ 核心工具 (14 个) — 执行分析, 可修改数据
|
||
|
||
| # | 工具 | 实现模块 | 功能 | 必需参数 |
|
||
|---|------|---------|------|----------|
|
||
| 1 | `load_data` | tools/load_data.py | 加载 CSV 文件 (glob/递归/ZIP 解压/schema 容错) | `csv_glob` |
|
||
| 2 | `profile_data` | tools/profile.py | 数据集概要统计 + 相关性矩阵 | `dataset_id` |
|
||
| 3 | `filter_data` | tools/filter.py | 按条件过滤 (12 操作符 + AND/OR 逻辑) | `dataset_id`, `filters` |
|
||
| 4 | `preprocess_data` | tools/preprocess.py | 预处理 (StandardScaler/OneHot/填充/列删除) | `dataset_id`, `columns` |
|
||
| 5 | `run_clustering` | tools/clustering.py | 执行聚类 (HDBSCAN/KMeans + 自动特征过滤 + 质量评估) | `dataset_id`, `cluster_columns` |
|
||
| 6 | `evaluate_clustering` | tools/evaluate.py | 评估聚类质量 (Silhouette/DB/CH/噪声比/簇大小) | `cluster_result_id`, `dataset_id` |
|
||
| 7 | `extract_features` | tools/features.py | 提取各聚类区分特征 (Z-Score/ANOVA) + UMAP-2D 嵌入 | `dataset_id`, `cluster_result_id` |
|
||
| 8 | `filter_and_cluster` | tools/clustering.py | 一步完成: 过滤 + 自动选数值列 + 聚类 | `dataset_id`, `filters` |
|
||
| 9 | `build_entity_profiles` | tools/entities.py | 自动检测实体列 + 聚合特征 (多列复合键支持) | `dataset_id` |
|
||
| 10 | `compute_scores` | tools/entities.py | 自适应代理/异常/威胁评分 (SVD 权重 + IQR 阈值) | `dataset_id` |
|
||
| 11 | `detect_anomalies` | tools/anomalies.py | Isolation Forest 异常检测 (分块处理大数据集) | `dataset_id` |
|
||
| 12 | `visualize_anomalies` | tools/anomalies.py | UMAP-2D 嵌入 + 聚类可视化 (按风险等级/聚类着色) | `dataset_id` |
|
||
| 13 | `export_results` | tools/export.py | 导出结果到磁盘 (CSV/Parquet/JSON) | `result_id`, `output_path` |
|
||
| - | `export_entities_json` | tools/export.py | 导出实体画像为 JSON (附加工具) | `dataset_id`, `output_path` |
|
||
|
||
### 🔍 分析工具 (6 个) — 只读深潜, 安全随时调用
|
||
|
||
| # | 工具 | 实现模块 | 功能 |
|
||
|---|------|---------|------|
|
||
| 14 | `analyze_patterns` | tools/analysis.py | 流量模式: top 源/目标 IP、端口/TLS 版本/协议分布 |
|
||
| 15 | `analyze_temporal` | tools/analysis.py | 时间维度流量分析: 小时/日流量计数、繁忙/空闲时段 |
|
||
| 16 | `analyze_fft` | tools/analysis.py | FFT 频谱分析: 周期模式、频率特征、周期性评分 |
|
||
| 17 | `analyze_tls_health` | tools/analysis.py | TLS 安全态势: 旧版比例、弱加密、证书问题、SNI 异常 |
|
||
| 18 | `analyze_geo_distribution` | tools/analysis.py | 地理分布: top 来源国家、不可能旅行、ISP 多样性 |
|
||
| 19 | `analyze_entity_detail` | tools/analysis.py | 单实体深度调查: 流/版本/目标/时间模式/异常评分 |
|
||
|
||
### 🩺 诊断工具 (7 个) — 排查问题
|
||
|
||
| # | 工具 | 实现模块 | 功能 |
|
||
|---|------|---------|------|
|
||
| 20 | `validate_data` | tools/diagnostics.py | 数据质量: schema 一致性、缺失率、列类型冲突 |
|
||
| 21 | `explore_distributions` | tools/diagnostics.py | 列分布统计: 唯一值、空值率、min/max/mean/std、直方图 |
|
||
| 22 | `find_outliers` | tools/diagnostics.py | IQR 方法检测数值列统计异常值 |
|
||
| 23 | `diagnose_clustering` | tools/diagnostics.py | 聚类效果差时诊断: 方差/相关分析 + 参数建议 |
|
||
| 24 | `compare_datasets` | tools/diagnostics.py | 对比两数据集: schema 差异、行数变化、值分布偏移 |
|
||
| 25 | `export_debug_sample` | tools/diagnostics.py | 导出原始数据样本 JSON 供外部调试 |
|
||
| 26 | `repair_schema` | tools/diagnostics.py | 修复 schema 不匹配: 列名对齐、大小写合并、填充缺失 |
|
||
|
||
### 📦 数据管理 (3 个)
|
||
|
||
| # | 工具 | 实现模块 | 功能 |
|
||
|---|------|---------|------|
|
||
| 27 | `list_datasets` | tools/data_mgmt.py | 列出所有活跃数据集和结果 |
|
||
| 28 | `drop_dataset` | tools/data_mgmt.py | 删除数据集释放内存 (支持 dataset/cluster/feature 三种类型) |
|
||
| 29 | `clone_dataset` | tools/data_mgmt.py | 浅拷贝数据集 (LazyFrame 查询计划, 不复制数据) |
|
||
|
||
### 🧠 LLM 驱动 (1 个)
|
||
|
||
| # | 工具 | 实现模块 | 功能 |
|
||
|---|------|---------|------|
|
||
| 30 | `compute_distance_matrix` | tools/distance_matrix.py | LLM 编写 Python 距离函数, 逐行执行并返回评分摘要 |
|
||
|
||
**工具注册流程**: `tools/_registry.py` (Tool 元数据) → `tools/_dispatch.py` (分发到对应 handler) → `analysis/mcp_server.py` (暴露 MCP stdio 接口)
|
||
|
||
### 手动分析工作流
|
||
|
||
手动分析页面 (manual.html) 为**工作流构建器**:
|
||
- 添加/移除/重排步骤
|
||
- 每步选择工具 + 填写参数
|
||
- **保存/加载/删除**方案 (存储于 `.omo/plans/<name>.json`)
|
||
- 单步执行 / **全部执行** (自动串行)
|
||
- 执行结果显示在每一步下面
|
||
|
||
### 标准分析流程
|
||
|
||
```
|
||
load_data → filter_data → profile_data → build_entity_profiles → compute_scores → run_clustering → extract_features
|
||
```
|
||
|
||
LLM 自动模式由 `tianxuan/llm_orchestrator.py` 驱动, 策略式提示词: 先 profile 了解数据 → 根据数据决策 → 失败自动诊断 → 重复调用检测 + 自动错误恢复。
|
||
|
||
## Config.Entity
|
||
|
||
`config/loader.py` 中的 Pydantic 模型:
|
||
|
||
```python
|
||
class Entity(BaseModel):
|
||
subnet_masks: list[int] = [] # 子网掩码列表, 如 [24, 28]
|
||
ip_columns: list[str] = ['src_ip', 'dst_ip'] # 需聚合的 IP 列
|
||
```
|
||
|
||
config.yaml 默认配置:
|
||
```yaml
|
||
entity:
|
||
subnet_masks: [24, 28]
|
||
ip_columns: ["src_ip", "dst_ip"]
|
||
```
|
||
|
||
IP 子网聚合逻辑位于 `analysis/ip_clustering.py`, `tools/entities.py::_handle_build_entity_profiles` 在 group_by 前对 IP 列自动应用子网掩码。
|
||
|
||
---
|
||
|
||
## Architecture
|
||
|
||
- **views 包拆分**: 原单体 `views.py` (2000+ 行) 拆分为 12 个模块: dashboard, pipeline, clustering, entity, upload, manual, auto, globe, config, log_viewer, tools, helpers
|
||
- **tools 包拆分**: 原 `tool_registry.py` 拆分为 17 个模块 (14 个 handler + 3 个基础设施: _registry/_dispatch/_helpers)
|
||
- **tuple 替代 frozenset**: 避免跨机 PYTHONHASHSEED 差异
|
||
- **PYTHONUTF8=1**: 跨机编码一致性 (run.bat 内置)
|
||
- **类型安全聚合**: 聚合前检查 dtype, 非数值列 cast
|
||
- **sync_to_async ORM**: 异步上下文中 Django ORM 安全调用
|
||
- **纯 Canvas 图表**: 零外部 JS 依赖 (散点图/地理分布/Silhouette 柱状图)
|
||
- **上传目录隔离**: `%APPDATA%/TianXuan/data/uploads/`, 与项目路径无关
|
||
- **通用数值清理 _coerce_to_float**: 处理 `+` / `-` / 空白 / N/A 等伪值
|
||
- **值优先类型检测**: config → 值 → 名称 → STRING (type_classifier.py)
|
||
- **地球深度测试**: depthTest: true, depthWrite: false, r=5.5
|
||
- **完整国境线**: Natural Earth 110m, 177 国 286 多边形 269KB
|
||
- **UMAP 降维**: extract_features 中为实体数据计算 UMAP-2D 嵌入, 存储到 EntityProfile 表 (embedding_x/embedding_y), 训练 10K 样本 + 批量变换 1K 批次
|
||
- **TruncatedSVD**: 聚类时特征 > 50 维自动降维; compute_scores 中学习自适应评分权重
|
||
- **LLM 驱动距离计算**: compute_distance_matrix 工具允许 LLM 编写 Python 函数在受限命名空间 (math, numpy) 中逐行执行
|
||
- **距离计算多策略**: tools/distance_matrix.py 中的 compute_distance_matrix 和 analysis/distance.py 中的 IP 子网/地理/Levenshtein/Hamming/FFT 相位距离
|
||
|
||
---
|
||
|
||
## Testing Protocol
|
||
|
||
### 运行测试
|
||
|
||
```bash
|
||
# 端到端测试 (自动启动后端、模拟前端行为、监控 stderr)
|
||
runtime\python\python.exe tests\test_e2e_full.py
|
||
runtime\python\python.exe tests\test_e2e_batch.py
|
||
|
||
# HDBSCAN 零样本降级测试
|
||
runtime\python\python.exe tests\_test_hdbscan.py
|
||
```
|
||
|
||
### 跨机一致性测试
|
||
|
||
```bash
|
||
# 两台机器各自执行
|
||
runtime\python\python.exe manage.py run_pipeline data\complex_test.csv
|
||
|
||
# 对比日志
|
||
runtime\python\python.exe scripts\diagnose_compare.py log_a.txt log_b.txt
|
||
```
|
||
|
||
### DB 持久化测试
|
||
|
||
```bash
|
||
runtime\python\python.exe scripts\debug_db.py
|
||
# 期望: n_features=30 db_saved=True
|
||
# 验证: AnalysisRun, ClusterFeature 表有数据
|
||
```
|
||
|
||
### LLM 编排测试
|
||
|
||
```bash
|
||
runtime\python\python.exe scripts\test_llm_full.py
|
||
```
|
||
|
||
### 生成测试数据
|
||
|
||
```bash
|
||
# 简单数据
|
||
runtime\python\python.exe scripts\gen_test_data.py --rows 1000
|
||
|
||
# Globe 模式 (IP 在真实 GeoIP 范围)
|
||
runtime\python\python.exe scripts\gen_test_data.py --globe
|
||
|
||
# 复杂数据 (5000 行 4 列含 55% 缺失)
|
||
runtime\python\python.exe scripts\gen_complex_test.py --rows 5000
|
||
```
|
||
|
||
### 列结构调查
|
||
|
||
```bash
|
||
runtime\python\python.exe scripts\column_survey.py --csv "data/*.csv"
|
||
```
|
||
|
||
---
|
||
|
||
## Polars Version Compatibility
|
||
|
||
| API | 旧版 (<1.0) | 新版 (>=1.0) |
|
||
|-----|-----------|-----------|
|
||
| mode | `pl.mode()` | `pl.col(col).mode()` |
|
||
| encoding | `encoding='utf-8'` | `encoding='utf8'` |
|
||
| value_counts col | `'index'` | 原列名 |
|
||
| streaming | `collect(streaming=True)` | `collect(engine='streaming')` |
|
||
| truth value | `if series:` | `if series.item():` |
|
||
|
||
## 32B LLM Optimization
|
||
|
||
- **Step guidance**: 每步告诉模型下一步做什么, 减少 32B 模型推理发散
|
||
- **Truncation**: 工具结果截断 1200 chars (避免上下文窗口溢出)
|
||
- **Timeout**: 90s (32B 推理更慢)
|
||
- **Max steps**: 15
|
||
- **Tool description**: 一行简洁描述 (中文)
|
||
- **策略式提示词**: 先 profile → 根据数据决策 → 失败自动诊断 → 重复调用检测 + 自动错误恢复
|
||
- **工具结果自动截断**: `_truncate_response()` 确保单次返回不超过 64 KB, 长列表/矩阵自动压缩
|
||
|
||
---
|
||
|
||
## Operating Procedures
|
||
|
||
1. **非阻塞启动后端** — `run.bat` 使用 `start /B` 启动 Django, 打印 PID 后退出, 不阻塞终端。日志写入 `logs/tianxuan.log`。
|
||
|
||
2. **全量测试** — 所有改动完成后, 运行完整 E2E 测试: 生成测试 CSV, 上传前端, 验证全流水线。
|
||
|
||
3. **更新文档和 Git** — 测试通过后: 更新 AGENTS.md, 提交所有更改, 清理临时文件和残留进程。不留脏状态 (孤儿进程、临时文件、未提交更改)。
|
||
|
||
4. **同步依赖** — 使用 `git pull` 同步最新代码, 然后 `runtime\python\python.exe -m pip install -r requirements.txt` 安装新依赖。每次新工作会话前执行。
|
||
|
||
5. **编码前缀** — 所有终端命令加 `chcp 65001` 避免 Opencode 编码错误。PowerShell/CMD 编码问题是命令失败的首要原因。
|
||
|
||
6. **Python UTF-8** — 运行 Python 时始终加 `set PYTHONUTF8=1`。确保跨机 Unicode 处理一致, 防止编码漂移。
|
||
|
||
## 近期变更 (beta-clean 分支)
|
||
|
||
- views.py (2000+ 行单体) → `analysis/views/` 包 (13 模块)
|
||
- tool_registry.py (3000+ 行) → `analysis/tools/` 包 (18 模块)
|
||
- 默认聚类算法改为 AgglomerativeClustering
|
||
- 移除实体概念,直接对原始行聚类 (entity_value = row_N)
|
||
- cluster_detail 显示原始数据行而非实体画像
|
||
- run_detail 新增全域 SVD 特征分析 + LLM 工作流时间线
|
||
- 3D 地球侧栏复用 `/globe/?embed=1`(iframe + postMessage 联动)
|
||
- UI 全面中文化
|
||
- 非阻塞启动 (run.bat 打印 PID 后退出)
|
||
|
||
## 待办
|
||
|
||
- [ ] **前端 UI 验证**: 打开 `prototype_cluster_ui.html` 查看交互设计是否符合要求
|
||
- [ ] **更新前端原型**后,将验证通过的交互逻辑合并到正式模板
|