Commit Graph

135 Commits

Author SHA1 Message Date
TianXuan Developer 4c8cb6d187 feat: GeoIP City分块 partad 2026-07-23 23:47:24 +08:00
TianXuan Developer 4936bd72ae feat: GeoIP City分块 partac 2026-07-23 23:46:52 +08:00
TianXuan Developer f2120175af feat: GeoIP City分块 partab 2026-07-23 23:46:29 +08:00
TianXuan Developer 45429ef6f3 feat: GeoIP分块 — ASN(5MB) + City首尾块(9MB+6MB) 2026-07-23 23:45:28 +08:00
TianXuan Developer e0a7400bd7 feat: 高精度离线GeoIP — MMDB支持 + 中文路径修复 + 分块自解压
- geoip.py: 修复中文路径 str()→Path 编码问题 (maxminddb Latin-1 bug)
- geoip.py: 启动自动重组geoip_chunks分块 + gunzip解压
- scripts/setup_geoip.py: 手动重组/解压脚本
- .gitignore: 忽略解压后的 .mmdb 文件

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 23:42:38 +08:00
TianXuan Developer 0f84497c82 fix: 边线点击优化 — 双层线结构 + hover 高亮
- 每条边由底层粗透明线(12px)和上层可见线组成
- 粗透明线捕获点击,命中区域扩大10倍以上
- 线宽 2-6px(按通信频次),不透明度 0.45-0.80
- hover 时高亮:加粗+亮红+不透明
- tooltip 提示点击查看详情
- highlightNodeEdges 同步使用双层线

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 23:20:26 +08:00
TianXuan Developer 2f7173637a fix: 静态资源路径改用 Django {% static %} 模板变量,确保离线部署兼容 2026-07-23 23:17:59 +08:00
TianXuan Developer f0a4fed7cf feat: 离线矢量世界地图 — TopoJSON 三精度 + 在线瓦片兜底
Natural Earth 三精度级别离线矢量地图:
- 10m (精细): 90KB — 完整海岸线+岛屿,2%简化
- 50m (标准): 533KB — 主要海岸线+国界
- 110m (基础): 54KB — 大陆轮廓

自动优先级: 10m → 50m → 110m → CartoDB在线瓦片
使用 topojson-client 库将 TopoJSON 转为 Leaflet GeoJSON 图层
矢量渲染,任意缩放级别清晰,经纬度天然对齐

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 23:13:05 +08:00
TianXuan Developer d4ec81a1dd feat: 修复世界地图 + 丰富节点/边数据 + 完善交互与导出
地图:
- 改用 CartoDB Positron 瓦片图层 (L.tileLayer),替代无效的 L.imageOverlay
- 复制 vendor 文件到项目级 static 目录

后端 (views.py):
- 新增 host 列别名 (host/hostname/host_name/remote_host/peer_name)
- _cluster_network 为每个 IP 收集 host、org、text、peer_ips 元数据
- 节点新增 host/org/texts/peer_ips/peer_count 字段
- 边新增 src/dst host/org/city/country/cluster + peak_hours/time_count 始终存在
- node_detail 返回 node_texts 和 enriched edges (peer_host/org/city)

前端 (simple_analysis.html):
- 实现 loadClusterDetail/showClusterDetailPanel 缺失函数
- renderCharts 在 goStep(4) 中调用
- 节点详情面板增强: host、org、text、对端 IP 列表
- 边详情面板增强: 端点 host/org/city/country、高峰时段
- 导出 CSV 增强: 节点新增 host/org/asn/peer_count/connected_ips,边新增全部端点字段
- Tooltip 新增 host 和 org 显示

测试: 更新 Playwright 测试适配两阶段上传 + 新 UI,全部 30 项通过

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 23:04:27 +08:00
TianXuan Developer 8322728de4 fix: CSS background world map + retry loop for container dimensions
- Map container gets SVG world map as CSS background-image
  (visible even before Leaflet initializes)
- Retry loop (max 5s) waits for container offsetHeight > 10
- zoomAnimation: false for faster init
- Console.log on successful map creation
- Verified: 550px height, 292 markers, background OK

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 22:08:20 +08:00
TianXuan Developer dedb3fc0ae test: Playwright self-test passes all 8 checks + fix Beijing time
- Self-test: page load -> upload -> cluster -> map -> node click -> edge -> export
- All pass: 600 rows, 542 nodes, 535 markers, 300 edges, 542/500 CSV rows
- Fix toBeijing to handle .00000 microsecond timestamps

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 22:02:11 +08:00
TianXuan Developer 66e3649152 feat: static SVG world map + large clickable points + edge detail
- Generate high-quality SVG world map (static, no tiles)
- Points: radius 7, white border, high-contrast subnet colors
- Node click: show detail panel + highlight edges on map
- Highlighted edges: clickable, show edge detail panel
- Edge detail: Beijing time, avg bytes, src/dst IP clickable
- Map init: requestAnimationFrame ensures container has dimensions
- Cleanup: remove polygon-based continent drawing code

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 21:58:02 +08:00
TianXuan Developer 04d49101d7 fix: robust map init via requestAnimationFrame + edge click detail panel
- Map init: requestAnimationFrame loop until container has dimensions
- Visible continent colors: darker fill (#d5dce3) and outline (#9aa8b8)
- Container background: #e8ecf2 for visibility even without data
- Edge click: L.DomEvent.stopPropagation, sticky tooltips
- Edge detail panel: Beijing time conversion, avg bytes per communication
- Save/restore edge layers when node highlighting
- Steps back to display:none (reliable, map inits via rAF)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 21:47:35 +08:00
TianXuan Developer 0e31328598 fix: visible map + node-click edge highlighting
- Step visibility: use visibility:hidden instead of display:none
  so map container always has dimensions for Leaflet init
- Simplify initMap: no more retry loop, always succeeds
- Node click: show related edges in panel, highlight on map
- Edge click: click edges in panel to show edge detail
- closeDetail: remove highlighted edges, restore edge toggle
- Edge rows in panel: hover effect, click to highlight+detail

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 21:42:56 +08:00
TianXuan Developer e3a7cc20d0 test: Playwright E2E test for V3 simple analysis + fix initFilterBuilder
- Add comprehensive E2E test: upload → cluster → map → node/edge click → export
- Fix goStep initFilterBuilder guard (was !SA.colNames.length, now always called)
- All 9 test sections pass: upload, cluster, map, node click, edge display, edge click, dual export, charts

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 21:31:22 +08:00
TianXuan Developer 427890d6fb fix: robust map init — wait for container to have dimensions
- Check container.offsetHeight before initializing Leaflet map
- Retry up to 10 times (150ms intervals) until container is visible
- Fix grid line coordinate order (lat,lon)
- Add try-catch around continent drawing
- Call invalidateSize() after initialization

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 20:59:53 +08:00
TianXuan Developer be1150e67c fix: real continent outlines, subnet-colored markers, click interaction
- Replace rough SVG with Leaflet polygon continents (recognizable shapes)
- Color markers by /24 subnet hash instead of cluster IDs
- Remove count bubbles and cluster numbers from map
- Fix click handlers with stopPropagation + bubblingMouseEvents:false
- Tooltips show IP, subnet, city, country, ISP
- Legend shows community size + subnet info

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 20:41:31 +08:00
TianXuan Developer f065efab26 perf: static world map overlay + grid clustering + GeoIP status
Major performance improvements for map visualization:
- Replace tile-based map with inline SVG world map (zero network requests)
- Grid-based marker clustering: merge nearby markers into count bubbles
- Adaptive cell size by zoom level, max 300 edge lines
- Remove all tile caching code (Cache API, CachedTileLayer, etc.)
- Add /simple/geoip-status/ API endpoint
- Debug panel shows GeoIP source and MMDB hint
- min_freq slider on edge control auto-refreshes

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 20:32:21 +08:00
TianXuan Developer 15e4c5e699 refactor: remove noise concept — all nodes assigned to clusters
- Backend: unclusterable nodes get their own single-node cluster (never -1)
- min_cluster_size slider starts at 1 instead of 3
- Remove n_noise, all_noise, is_noise from responses and UI
- Solo clusters shown as '独立节点' with lighter color
- Remove noise toggle from legend, simplify map rendering

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 20:21:27 +08:00
TianXuan Developer 8ba00b1240 fix: auto-scroll to results after upload/filter/cluster
- Upload result: scrollIntoView after success
- Filter preview: scrollIntoView after apply
- Cluster result: scrollIntoView after analysis
- All action buttons stay above scrollable content areas

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 20:12:02 +08:00
TianXuan Developer 5c1dd359d1 fix: keep interactive controls above scrollable content
- File list: max-height 180px with overflow scroll
- Cluster cards grid: max-height 400px with overflow scroll
- Step 3: navigation buttons moved above cluster cards
- Step 4: export/reset buttons moved above charts
- All long content areas now scroll internally, controls always visible

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 20:05:31 +08:00
TianXuan Developer 4220e045ae refactor: simple card-based filter builder replacing AND/OR/NOT tree
Replace complex tree filter builder with intuitive card-based design:
- Top-level AND/OR toggle buttons: 全部满足(且) / 任一满足(或)
- Each condition: [Column] [Op] [Value] [☐ 取反] [✕]
- Groups as clearly bordered cards with own AND/OR toggle
- Human-readable description line: cnam 等于 'google' 且 (isrs 等于 '+' 或 cnrs 等于 '+')
- Remove confusing WHERE/AND/OR logic tags and () wrap button
- Unified serializeFilter() for both main and preset builders

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 19:57:32 +08:00
TianXuan Developer c190484dbc fix: lazy column-value scan for preset filter via scan_id
- quick_scan now keeps temp files for subsequent single-column streaming queries
- column_values API supports scan_id mode: streaming read of one column, low memory
- upload_csv reuses scan files via scan_id to avoid duplicate disk writes
- Frontend onFilterColChange uses scan_id when session not yet available

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 19:48:25 +08:00
TianXuan Developer a68c8f4ebb merge: V3 refactor into master (stable) 2026-07-23 19:35:48 +08:00
TianXuan Developer 32c15f5365 feat: v3 refactor with MMDB GeoIP, network clustering, node/edge viz, offline tile cache, dual export
- GeoIP: MMDB (GeoLite2-City + ASN) support with text fallback
- Upload: two-phase flow with advanced preset filter builder
- Clustering: IP communication network community discovery (/24 + HDBSCAN)
- Map: per-IP node rendering, node click detail, edge click detail
- Offline: Cache API tile caching with fallback
- Export: node table + edge table CSV download
- Fix: null-guard DOM operations throughout

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 19:35:45 +08:00
TianXuan Developer df1f208cd1 docs: requirements.md, offline toast, showWarning in base
- Add requirements.md documenting all changes
- Add showWarning() to base.html with .toast-warning CSS
- Add offline tile fallback message when all providers fail
- All vendor assets local, GeoIP from local file

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 13:34:53 +08:00
TianXuan Developer 5423a360ec cleanup: remove preset builder, restore simple preset fields
- Revert preset panel to original cnrs/isrs/cnam/snam simple fields
- Remove applyPresetFilter, addPresetGroup, addPresetCondition,
  resetPreset, populatePresetBuilder, applyFilterPreset functions
- Remove mode='preset' backend code
- Remove root-format support from upload preset (no longer needed)
- Remove preset template buttons from filter action bar
- Keep: value dropdown with top-50, filter groups, tree-format advanced filter

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 13:24:45 +08:00
TianXuan Developer 6f6581d38d fix: operator change handler enables/disables value dropdown
- Add onFilterOpChange handler on <select class=sa-filter-op>
- When operator is is_empty/not_empty: disable value select, show '— 无值 —'
- When switching back to eq/neq/contains/etc: re-enable and re-fetch values
- Fixes issue where changing operator before selecting column left value
  dropdown disabled permanently
- Remove operator check from onFilterColChange (now handled separately)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 13:14:03 +08:00
TianXuan Developer ab31471bd3 feat: value dropdown with top-50 by count + preset builder UI
Backend:
- advanced_filter supports mode='preset' — overwrites entry['df'] so
  preset filtering becomes the base data for subsequent steps

Frontend - Filter rows:
- Replace <input>+<datalist> with <select class=sa-filter-val>
- onFilterColChange populates dropdown with top 50 distinct values
  sorted by count, displayed as "value (count)"
- Disables value select for is_empty/not_empty operators

Frontend - Upload preset:
- Replace JSON textarea with full condition builder (addFilterCondition/
  addFilterGroup) — same format as advanced filter in Step 2
- Builder appears after upload with columns populated
- '应用预设筛选' button POSTs to filter/advanced/ with mode='preset'
- '清除预设' resets the builder
- Remove old upload-time preset_filters collection (now post-upload)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 13:04:23 +08:00
TianXuan Developer ac0c7fb117 refactor: upload preset uses tree format, preset group as buttons
Backend:
- upload_csv supports preset_filters.root (tree format via _build_tree_condition)
- Falls back to old flat fields for backward compatibility

Frontend:
- Upload preset panel: replace cnrs/isrs/cnam/snam fields with JSON textarea
- Preset group: change <select> dropdown to visible buttons (fixes no-dropdown issue)
- applyFilterPreset now takes string arg instead of event
- restorePreset reads/writes root JSON from localStorage

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 12:54:47 +08:00
TianXuan Developer 14fc0c8ea1 feat: filter preset templates for common boolean patterns
- Add '预设组' dropdown with two predefined templates:
  1. cnrs=+ OR isrs=+  (OR group for success conditions)
  2. cnam is empty AND (cnrs=+ OR isrs=+) (AND+OR nesting)
- applyFilterPreset() builds full UI tree with conditions + groups
- Presets auto-populate column, operator, and value fields

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 12:48:23 +08:00
TianXuan Developer 8eacb38e9e feat: nested boolean group support in filter builder (parentheses logic)
Backend:
- Add _build_tree_condition() recursive function supporting AND/OR/NOT groups
- Modify advanced_filter to accept 'root' tree format alongside legacy flat format
- Tree supports arbitrary nesting depth: {type, logic, items}

Frontend:
- Add addFilterGroup() — creates visual ( ) group with own logic selector
- Add wrapRowInGroup() — wraps existing row into a group via [()]
- Add serializeFilterTree() — recursive JSON serialization
- Update applyAdvancedFilter to POST tree format
- Update updateFilterLogicTags for nested group labeling
- Switch filter row elements from IDs to class-based selectors
- CSS for group visual nesting (dashed left border, indentation)

Now supports: cnam='google' AND (isrs='+' OR cnrs='+')

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 12:42:17 +08:00
TianXuan Developer b844c4f92f feat: filter value suggestions from actual upload data
- Add GET /simple/column-values/ API returning distinct values for any column
  (top 50 values with counts, from the uploaded DataFrame via polars)
- Update frontend onFilterColChange to fetch real data instead of hardcoded hints
- Wire datalist ID per filter row for <input list=''> binding

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 12:31:50 +08:00
TianXuan Developer 298dd42cf6 feat: alphabetical column sort + value suggestion dropdown in filter builder
- Sort column selector alphabetically (a-z) in condition builder
- Add datalist-based value suggestions per column type
  (cnrs/isrs → +/-, proto → TCP/UDP/ICMP, tls_ver → 0303/0304, etc.)
- Remove redundant initFilterBuilder column population (now inline in addFilterCondition)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 12:28:16 +08:00
TianXuan Developer c5d9889a22 refactor: remove CNAM auto-selection from upload step
- Remove CNAM frequency display, auto-selection, and related CSS from upload UI
- Remove renderCnamList, selectCnam, runFilter functions (dead code)
- Remove topCnam from SA state object
- Keep preset filter cnam field for manual pre-filtering
- Users now use Step 2 advanced filter instead
- Update Playwright test assertion

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 12:24:38 +08:00
TianXuan Developer d81171cc1d test: Playwright E2E test for simple-analysis v2 + fix template JS syntax
- Fix extra closing brace in simple_analysis.html that broke all inline JS
- Add Playwright E2E test covering upload→filter→cluster→map→edges
- Add debug support script for Playwright issue isolation
- Use small 20-row test CSV for fast test execution
- All 31 assertions pass: page load, CSV upload, advanced filter,
  HDBSCAN clustering, Leaflet map, edge relationships

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 12:08:24 +08:00
TianXuan Developer f798c39b13 fix: null safety for all DOM operations, preset filter optional
- Add safe setText() helper with null check
- Make setBusy() null-safe for all DOM lookups
- Make preset filter elements optional (try/catch)
- Add null checks for all textContent assignments
- Remove emoji from error messages to avoid encoding issues
- Clarify preset filter UI labels

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 11:51:24 +08:00
TianXuan Developer e57339b67f feat: rich UI for v2 — preset filter, advanced filter builder, debug panel, edge overlays
Frontend improvements:
- Fixed sticky action bar with step indicator and nav buttons
- Collapsible preset filter panel with localStorage memory
- Advanced filter builder with AND/OR/NOT condition rows
- Filter builder auto-populates column names from upload
- Debug info panel (collapsible) with real-time stats
- Edge relationship layer with freq slider and toggle
- Enhanced point tooltips with IP sample and coordinate info
- Anti-duplicate button debounce via setBusy() helper

Backend:
- Add ip_sample to cluster_map for tooltip display
- Increase default cluster_selection_epsilon to 0.05

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 11:45:17 +08:00
TianXuan Developer 55f3b3637a feat: offline GeoIP, advanced filter, performance tuning, enriched viz
Major v2 improvements to simple analysis module:

Backend:
- Column name normalization with 50+ column alias mapping
- Offline GeoIP integration (reuses analysis.geoip module,
  no dependency on CSV lat/lon columns)
- Advanced filter builder with AND/OR/NOT conditions
- Edge relationship computation (IP pair frequency)
- HDBSCAN with GeoIP-derived coordinates + float32 memory opt
- DBSCAN fallback when HDBSCAN produces all-noise
- Jitter for duplicate GeoIP coordinates (city-level overlap)
- All-noise graceful handling (visualize all points as noise)
- Cluster detail with GeoIP city/ISP/org attributes

Deps: geoip2==5.3.0, maxminddb==3.1.1 added to requirements.txt

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 11:39:54 +08:00
TianXuan Developer c8de2c8fe8 chore: remove unused DBSCAN import, sync with beta 2026-07-23 11:29:02 +08:00
PM-pinou 7d6d29475d fix: classify cnrs/isrs as BOOL_ENUM for proper boolean cleaning (blank→False, +→True) 2026-07-22 23:39:37 +08:00
PM-pinou 38e8985718 Merge branch 'master' of https://gitea.cattysteve.top/HJQ/tianxuan into beta 2026-07-22 23:38:45 +08:00
PM-pinou 035d22b234 fix: make all entity_values unique by appending row index to support bulk_create with ignore_conflicts 2026-07-22 23:17:09 +08:00
PM-pinou 0d92a5a170 fix: unique entity_value fallback to prevent bulk_create ignore_conflicts from skipping duplicates 2026-07-22 23:14:00 +08:00
PM-pinou c1db7ad7eb fix: fallback entity value when column is empty to ensure all UMAP profiles are saved 2026-07-22 23:11:32 +08:00
TianXuan Developer 9f6e388ece chore: vendor Leaflet + Chart.js locally for offline/China use
- Download Leaflet CSS, JS, and marker images to static/vendor/
- Download Chart.js 4.4.7 to static/vendor/
- Switch template from CDN (unpkg/cdnjs) to local static assets
- Map now works fully offline without external CDN dependencies

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-22 23:06:35 +08:00
TianXuan Developer 67013cf29b fix: replace OSM tiles with ArcGIS for China network compatibility
- Switch primary tile provider from OpenStreetMap (blocked in China)
  to ArcGIS World Street Map (certified working)
- Add fallback chain: ArcGIS -> ArcGIS Gray -> OSM
- Auto-detect tile failures and fall back to next provider
- Clean up init sequence for reliable map rendering

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-22 23:02:17 +08:00
TianXuan Developer eaf6cb4e67 Merge remote-tracking branch 'origin/master' into feature/simple-analysis 2026-07-22 22:55:20 +08:00
PM-pinou 2c5aece65d fix: streaming load_from_db with fetchmany(10000) instead of fetchall() (fixes OOM on 4M rows) 2026-07-22 22:39:51 +08:00
TianXuan Developer 46013afa74 feat: add simple analysis module with global map visualization
- Add independent 'simple_analysis' Django app with full workflow:
  1. Upload/merge CSV files with auto column detection
  2. Filter by cnam + cnrs + isrs (optional)
  3. Clustering via HDBSCAN+haversine (geo) or /24 subnet (IP)
  4. Interactive Leaflet global map with cluster-colored data points
- Integrate into nav bar, settings, and URL routing without
  modifying existing analysis logic
- Cluster detail panel with IPs, top dst IPs, TLS/cipher profiles
- Chart.js bar/pie charts for cluster size distribution
- E2E Playwright tests for all workflow steps
- Support multiple CSV upload with diagonal_relaxed merge

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-22 22:39:16 +08:00