5.1 KiB
5.1 KiB
Globe v6 修复计划 — 最终版
TL;DR (For humans)
两个紧急修复:背面剔除 + 国境线恢复。预计 50 行变更。
P1. 背面剔除修复
原因: updatePulses 中 arcGroup.quaternion 与 rotation 不同步,导致方向判断错误。
修复: 用 localToWorld 替代 applyQuaternion
在 templates/tianxuan/globe.html 的 updatePulses 函数中:
// 删除:
// var arcQuat = arcGroup.quaternion;
// midPt.applyQuaternion(arcQuat);
// 在函数开头添加:
arcGroup.updateMatrixWorld(true);
// 在循环内改为:
var midPt = d.curve.getPoint(0.5);
arcGroup.localToWorld(midPt);
var isFront = midPt.dot(camDir) < -0.08;
P2. 国境线恢复
步骤 1: 创建 static/tianxuan/world_borders.js
创建文件含 10 国精简轮廓(中国/美国/俄罗斯/加拿大/巴西/澳大利亚/印度/英国/日本/法国)。 每国 10-20 个 [lat,lon] 坐标点。
重要: 中国坐标需包含台湾和南海九段线示意。 台湾坐标: 25°N,121°E 左右。
步骤 2: 恢复 globe.html 中的 borderGroup
在 scene.add(gridGroup) 之后添加:
// ── World borders (loaded from static file) ──
var borderGroup = new THREE.Group();
var borderMat = new THREE.LineBasicMaterial({ color: 0x88dd88, transparent: true, opacity: 0.3, depthTest: false });
function renderBorders(borders) {
if (!borders) return;
for (var c = 0; c < borders.length; c++) {
var pts = [];
for (var p = 0; p < borders[c].length; p++) {
var lat = borders[c][p][0], lon = borders[c][p][1];
var phi = (90 - lat) * Math.PI / 180;
var theta = (lon + 180) * Math.PI / 180;
pts.push(new THREE.Vector3(5.01 * Math.sin(phi) * Math.cos(theta), 5.01 * Math.cos(phi), 5.01 * Math.sin(phi) * Math.sin(theta)));
}
if (pts.length > 2) {
borderGroup.add(new THREE.Line(new THREE.BufferGeometry().setFromPoints(pts), borderMat));
}
}
}
if (typeof worldBorders !== 'undefined') renderBorders(worldBorders);
scene.add(borderGroup);
步骤 3: 恢复加载脚本
在 three.min.js 之后添加:
<script src="{% static 'tianxuan/world_borders.js' %}"></script>
步骤 4: 恢复复选框
在 toggle 区域恢复:
<label style="font-size:0.85rem;cursor:pointer;">
<input type="checkbox" id="toggleGrid" checked onchange="gridGroup.visible = this.checked;">
经纬网格
</label>
<label style="font-size:0.85rem;cursor:pointer;">
<input type="checkbox" id="toggleBorders" checked onchange="borderGroup.visible = this.checked;">
国境线
</label>
步骤 5: 添加 borderGroup 到 animate/惯性旋转
earth.rotation.y += inertiaY; arcGroup.rotation.y += inertiaY; gridGroup.rotation.y += inertiaY; borderGroup.rotation.y += inertiaY;
earth.rotation.x += inertiaX; arcGroup.rotation.x += inertiaX; gridGroup.rotation.x += inertiaX; borderGroup.rotation.x += inertiaX;
Todos
- 1. 创建
static/tianxuan/world_borders.js(10国精简轮廓) - 2. globe.html: 修复背面剔除 (localToWorld)
- 3. globe.html: 恢复 borderGroup (渲染 + 加载 + 复选框 + 旋转)
- 4. config.yaml: 添加
":ips": ipv4,":ipd": ipv4 - 5. type_classifier.py: 名称模式增加
:ips:ipd - 6. entity_detector.py: ENTITY_KEYWORDS 增加
:ips:ipd - 7. views.py globe_view: 列检测增加
:ips:ipd
P4. 用户数据列名适配 (:ips, :ipd)
问题: 用户的源IP列名是 :ips,目标IP列名是 :ipd。
当前代码的IP检测靠名称模式匹配 _ip/src_ip/dst_ip,完全匹配不到。
需要修改的文件:
1. config.yaml — 添加列覆盖
columns:
":ips": ipv4
":ipd": ipv4
2. analysis/type_classifier.py — 名称模式增加 :ips :ipd
在 _NAME_TYPE_MAP 中添加:
(re.compile(r'^:ips$|^:ipd$', re.I), DataType.IPv4),
3. analysis/entity_aggregator.py — 关键词增加 :ips :ipd
_DST_IP_KEYWORDS 和 _SNI_KEYWORDS 逻辑可能需要扩展,但更关键的是 entity_detector 的 ENTITY_KEYWORDS。
4. analysis/entity_detector.py — 关键词增加 :ips :ipd
ENTITY_KEYWORDS: frozenset[str] = frozenset({
'src_ip', 'dst_ip', ':ips', ':ipd', 'source_ip', ...
})
5. analysis/views.py — globe_view 中的列检测
当前 globe_view 用 'src_ip' in c.lower() 检测IP列。
需要增加 ':ips' 和 ':ipd' 的检测。
紧急修补 (Traceback截断)
问题: views.py 中所有 run.error_message = tb[:500] 截断到 500 字符,无法调试。
修复: 搜索 views.py 中所有 tb[:数字] → 改为 tb(不截断)
# 全局替换 ALL:
tb[:500] → tb
tb[:5000] → tb
涉及的代码位置:
_background_process(line ~385)_run_analysis_worker(line ~527)- 任何其他
tb[:500]出现处
Final Verification Wave ✅
- F1. pytest tests -q → 121 pass
- F2. 清理: 删除临时文件
- F3. 完整端到端测试: 启动服务 → 上传 CSV → 预处理 → 手动分析 → 聚类 → 地球
依赖
全部独立,可并行执行。