Spaces:
Sleeping
Sleeping
Download web/index.html from MarcoXL/node-graph-viewer: direct link, hf CLI and curl.
- Browser
- Download file 15.9 kB
-
https://huggingface.co/spaces/MarcoXL/node-graph-viewer/resolve/main/web/index.html
- Command line
-
hf download hf://spaces/MarcoXL/node-graph-viewer/web/index.html
-
curl -L -o index.html https://huggingface.co/spaces/MarcoXL/node-graph-viewer/resolve/main/web/index.html
15.9 kB
| <html lang="zh-CN"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <title>SetVL Node Graph Viewer</title> | |
| <link rel="stylesheet" href="styles.css"> | |
| </head> | |
| <body> | |
| <div class="topographic-grid" aria-hidden="true"></div> | |
| <!-- 界面文字的中英两份都在 app.js 的 I18N 表里。标了 data-i18n* 的地方由 | |
| applyLang() 替换,这里写的中文只是脚本跑起来之前的初始值。 --> | |
| <header class="topbar"> | |
| <div class="brand"> | |
| <div class="brand-mark" aria-hidden="true">SG</div> | |
| <h1>Node Graph Viewer<em data-i18n="brand.readonly">SetVL · 只读</em></h1> | |
| </div> | |
| <!-- 全库读数:一行内用竖线断开,不再单独占一条 progress-strip --> | |
| <div class="readout" role="group" aria-label="全库统计" data-i18n-aria-label="stats.aria"> | |
| <b id="statScenes">—</b><span data-i18n="stats.scenes">场景</span> | |
| <i aria-hidden="true"></i> | |
| <b id="statItems">—</b><span data-i18n="stats.nodes">节点</span> | |
| <i aria-hidden="true"></i> | |
| <b id="statQueue">—</b><span data-i18n="stats.edges">边</span> | |
| <i aria-hidden="true"></i> | |
| <span class="readout-origins" id="originBreakdown" title="边按 §1-§4 分类" data-i18n-title="stats.byOrigin"> | |
| <em class="o-corridor" data-i18n="origin.corridor"><b id="countCorridor">—</b>同走廊</em> | |
| <em class="o-road" data-i18n="origin.road_route"><b id="countRoad">—</b>路网可达</em> | |
| <em class="o-short" data-i18n="origin.short_link"><b id="countShort">—</b>短直连</em> | |
| <em class="o-merge" data-i18n="origin.component_merge"><b id="countMerge">—</b>分量合并</em> | |
| </span> | |
| </div> | |
| <div class="origin-meter" id="originMeter" aria-hidden="true"><span id="progressBar"></span></div> | |
| <span class="readout-label" id="progressLabel">—</span> | |
| <button class="icon-button" id="helpButton" title="帮助与快捷键" aria-label="帮助与快捷键" | |
| data-i18n-title="help.title" data-i18n-aria-label="help.title">?</button> | |
| <!-- 语言切换。两个按钮各用自己的语言写,不随界面翻译——不懂另一种语言的人也认得出 --> | |
| <div class="lang-switch" role="group" aria-label="语言 / Language"> | |
| <button type="button" id="langZh" lang="zh-CN">中文</button> | |
| <button type="button" id="langEn" lang="en">EN</button> | |
| </div> | |
| </header> | |
| <main class="app-shell"> | |
| <!-- 01 队列 ---------------------------------------------------------> | |
| <aside class="queue-panel"> | |
| <div class="panel-heading"> | |
| <p class="section-index">01 / BROWSE</p> | |
| <h2 id="panelTitle" data-i18n="panel.scenes">场景浏览</h2> | |
| </div> | |
| <div class="mode-switch" role="group" aria-label="列表模式" data-i18n-aria-label="mode.aria"> | |
| <button type="button" id="modeScenes" class="active" data-i18n="mode.scenes">全部场景</button> | |
| <button type="button" id="modeQueue" data-i18n="mode.queue">带信号的</button> | |
| </div> | |
| <div class="filter-stack"> | |
| <!-- 一级:搜索。常驻,最宽,视觉重量最大。 --> | |
| <div class="search-wrap"> | |
| <svg class="search-icon" viewBox="0 0 16 16" aria-hidden="true"> | |
| <circle cx="7" cy="7" r="4.5" fill="none" stroke="currentColor" stroke-width="1.4"/> | |
| <path d="M10.4 10.4 L14 14" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/> | |
| </svg> | |
| <input id="searchInput" type="search" placeholder="scene_id 片段、城市…" data-i18n-placeholder="search.scenes"> | |
| </div> | |
| <!-- 二级:最常用的两个,压成一行紧凑控件 --> | |
| <div class="filter-row"> | |
| <label class="ctl"><span>City</span> | |
| <select id="cityFilter"><option value="" data-i18n="opt.all">全部</option></select> | |
| </label> | |
| <label class="ctl"><span>Sort</span> | |
| <select id="orderFilter"> | |
| <option value="scene_id">ID</option> | |
| <option value="nodes_desc" data-i18n="order.nodesDesc">节点多→少</option> | |
| <option value="nodes_asc" data-i18n="order.nodesAsc">节点少→多</option> | |
| </select> | |
| </label> | |
| <button type="button" class="filter-toggle" id="filterToggle" | |
| aria-expanded="false" aria-controls="filterDrawer" data-i18n="filter.toggle"> | |
| 筛选<b class="filter-count" id="filterCount" hidden>0</b> | |
| <svg viewBox="0 0 10 6" aria-hidden="true"><path d="M1 1l4 4 4-4" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> | |
| </button> | |
| </div> | |
| <!-- 已激活的筛选以 token 回显:抽屉收起时状态依然可见、可单独撤销 --> | |
| <div class="token-row" id="activeTokens" hidden></div> | |
| <!-- 三级:抽屉。默认收起,把纵向空间让给列表 --> | |
| <div class="filter-drawer" id="filterDrawer" hidden> | |
| <div class="drawer-group" id="sceneFilters"> | |
| <p class="drawer-title" data-i18n="drawer.scenes">场景</p> | |
| <div class="filter-row"> | |
| <label class="ctl"><span>Min nodes</span> | |
| <input id="minNodes" type="number" min="1" max="38" placeholder="—"> | |
| </label> | |
| <label class="ctl"><span data-i18n="f.edited">状态</span> | |
| <select id="editedFilter"> | |
| <option value="" data-i18n="opt.all">全部</option> | |
| <option value="1" data-i18n="edited.yes">已人工改过</option> | |
| <option value="0" data-i18n="edited.no">未改动</option> | |
| </select> | |
| </label> | |
| </div> | |
| <div class="chip-row" id="sceneChips"> | |
| <label class="chip"><input id="fOrphan" type="checkbox"><span data-i18n="chip.orphan">含孤儿节点</span></label> | |
| <label class="chip"><input id="fNoted" type="checkbox"><span data-i18n="chip.noted">含带标记的边</span></label> | |
| </div> | |
| <div class="filter-row"> | |
| <label class="ctl"><span data-i18n="f.origin">含某类边</span> | |
| <select id="originFilter"> | |
| <option value="" data-i18n="opt.all">全部</option> | |
| <option value="corridor" data-i18n="sec.corridor">§1 同走廊</option> | |
| <option value="road_route" data-i18n="sec.road_route">§2 路网可达</option> | |
| <option value="short_link" data-i18n="sec.short_link">§3 短直连</option> | |
| <option value="component_merge" data-i18n="sec.component_merge">§4 分量合并</option> | |
| </select> | |
| </label> | |
| </div> | |
| </div> | |
| <div class="drawer-group" id="queueFilters" hidden> | |
| <p class="drawer-title" data-i18n="drawer.queue">信号队列</p> | |
| <div class="filter-row"> | |
| <label class="ctl"><span>Kind</span> | |
| <select id="kindFilter"> | |
| <option value="" data-i18n="kind.all">节点 + 边</option> | |
| <option value="node" data-i18n="kind.node">只看节点</option> | |
| <option value="edge" data-i18n="kind.edge">只看边</option> | |
| </select> | |
| </label> | |
| </div> | |
| <div class="filter-row"> | |
| <label class="ctl"><span data-i18n="f.signal">标记</span> | |
| <select id="signalFilter"> | |
| <option value="" data-i18n="sig.all">全部标记</option> | |
| <option value="orphan" data-i18n="sig.orphan">§6 孤儿节点</option> | |
| <option value="water_crossed" data-i18n="sig.water">§0 跨水</option> | |
| <option value="building_crossed" data-i18n="sig.building">§0 穿建筑</option> | |
| <option value="no_road_path" data-i18n="sig.noRoad">无道路通路</option> | |
| <option value="long_detour" data-i18n="sig.detour">§4 红边绕远</option> | |
| </select> | |
| </label> | |
| <label class="ctl"><span data-i18n="f.reviewed">已复核</span> | |
| <select id="showReviewedSel"> | |
| <option value="" data-i18n="rev.exclude">不含</option> | |
| <option value="1" data-i18n="rev.include">含已复核</option> | |
| </select> | |
| </label> | |
| </div> | |
| </div> | |
| <button type="button" class="drawer-reset" id="filterReset" data-i18n="filter.reset">清空全部筛选</button> | |
| </div> | |
| </div> | |
| <div class="list-meter"><span id="listCount">—</span></div> | |
| <div class="queue-list" id="queueList" role="listbox" aria-label="Review queue"></div> | |
| <div class="queue-footer"> | |
| <button class="quiet-button" id="pagePrev">←</button> | |
| <button class="quiet-button" id="previousButton"><kbd>K</kbd> Prev</button> | |
| <button class="quiet-button" id="nextButton">Next <kbd>J</kbd></button> | |
| <button class="quiet-button" id="pageNext">→</button> | |
| </div> | |
| </aside> | |
| <!-- 02 证据 ---------------------------------------------------------> | |
| <section class="evidence-panel"> | |
| <div class="scene-header"> | |
| <div> | |
| <div class="scene-title-row"> | |
| <h2 id="sceneTitle" data-i18n="scene.none">未选择</h2> | |
| <span class="scene-city" id="sceneCity">—</span> | |
| </div> | |
| <p class="scene-id" id="sceneId">—</p> | |
| </div> | |
| <div class="scene-metrics"> | |
| <div><span>Nodes</span><strong id="mNodes">—</strong></div> | |
| <div><span>Edges</span><strong id="mEdges">—</strong></div> | |
| <div><span>Corridors</span><strong id="mCorridors">—</strong></div> | |
| <div><span>Orphans</span><strong id="mOrphans">—</strong></div> | |
| </div> | |
| </div> | |
| <div class="evidence-grid"> | |
| <article class="image-card"> | |
| <div class="image-card-head"> | |
| <span class="image-kind">Scene Graph</span> | |
| <div class="map-card-tools"> | |
| <div class="basemap-switch" role="group" aria-label="边的画法" data-i18n-aria-label="edgeStyle.aria"> | |
| <button type="button" id="edgeStraight" class="active" title="直线连接(默认,更醒目)" data-i18n-title="edgeStyle.straight">LINE</button> | |
| <button type="button" id="edgeRoad" title="沿道路走线" data-i18n-title="edgeStyle.road">ROAD</button> | |
| </div> | |
| <div class="basemap-switch" role="group" aria-label="底图切换" data-i18n-aria-label="basemap.aria"> | |
| <button type="button" id="baseSat" class="active">SAT</button> | |
| <button type="button" id="baseMap">MAP</button> | |
| </div> | |
| <div class="map-controls" aria-label="电子地图缩放" data-i18n-aria-label="mapZoom.aria"> | |
| <button type="button" id="mapZoomIn" title="放大" data-i18n-title="zoom.in">+</button> | |
| <button type="button" id="mapZoomOut" title="缩小" data-i18n-title="zoom.out">−</button> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="image-stage satellite-stage" id="satelliteStage"> | |
| <img id="satelliteImage" alt="satellite"> | |
| <div class="street-map" id="streetMap" aria-hidden="true"> | |
| <div class="map-tile-layer" id="mapTileLayer"></div> | |
| </div> | |
| <svg class="graph-svg" id="graphSvg" viewBox="0 0 400 400" preserveAspectRatio="none"></svg> | |
| </div> | |
| <div class="image-caption"> | |
| <span class="legend"> | |
| <span data-i18n="sec.corridor"><i class="lg-corridor"></i>§1 同走廊</span> | |
| <span data-i18n="sec.road_route"><i class="lg-road"></i>§2 路网可达</span> | |
| <span data-i18n="sec.short_link"><i class="lg-short"></i>§3 短直连</span> | |
| <span data-i18n="sec.component_merge"><i class="lg-merge"></i>§4 分量合并</span> | |
| <span data-i18n="legend.orphan"><i class="lg-orphan"></i>孤儿</span> | |
| </span> | |
| </div> | |
| </article> | |
| <div class="ground-stack"> | |
| <article class="image-card ground-card"> | |
| <div class="image-card-head compact"> | |
| <div class="node-label anchor-label" id="anchorBadge">—</div> | |
| <span class="image-kind" id="anchorKind">Node</span> | |
| </div> | |
| <div class="ground-grid" id="anchorGrid" aria-label="四个朝向的街景" data-i18n-aria-label="ground.aria"></div> | |
| <div class="image-caption mono" id="anchorCaption">—</div> | |
| </article> | |
| <article class="image-card ground-card" id="targetCard"> | |
| <div class="image-card-head compact"> | |
| <div class="node-label target-label" id="targetBadge">—</div> | |
| <span class="image-kind">Target</span> | |
| </div> | |
| <div class="ground-grid" id="targetGrid" aria-label="四个朝向的街景" data-i18n-aria-label="ground.aria"></div> | |
| <div class="image-caption mono" id="targetCaption">—</div> | |
| </article> | |
| </div> | |
| </div> | |
| <div class="context-rail"> | |
| <div> | |
| <span class="image-kind">Scene Nodes</span> | |
| <p data-i18n="rail.hint">点击可切换到该节点</p> | |
| </div> | |
| <div class="node-thumbnails" id="nodeThumbnails"></div> | |
| <div class="corridor-legend" id="corridorLegend"></div> | |
| </div> | |
| <section class="graph-card" aria-labelledby="graphTitle"> | |
| <div class="graph-head"> | |
| <div> | |
| <p class="section-index">SCENE ADJACENCY</p> | |
| <h3 id="graphTitle" data-i18n="adj.title">节点邻接矩阵</h3> | |
| </div> | |
| <div class="graph-counts"> | |
| <span data-i18n="adj.corridor"><b id="gCorridor">—</b> 同走廊</span> | |
| <span data-i18n="adj.road"><b id="gRoad">—</b> 路网</span> | |
| <span data-i18n="adj.short"><b id="gShort">—</b> 直连</span> | |
| <span data-i18n="adj.merge"><b id="gMerge">—</b> 合并</span> | |
| </div> | |
| </div> | |
| <p class="graph-rule" data-i18n="adj.rule">每一格是一条无向边,颜色对应它的来源。点击格子或右侧列表可直接检查该条边。</p> | |
| <div class="graph-body"> | |
| <div><table class="adjacency-table" id="adjacencyTable"></table></div> | |
| <div class="graph-edge-list" id="edgeList"></div> | |
| </div> | |
| </section> | |
| </section> | |
| <!-- 03 判定 ---------------------------------------------------------> | |
| <aside class="inspector-panel"> | |
| <div class="panel-heading inspector-heading"> | |
| <div> | |
| <p class="section-index">03 / PROPERTIES</p> | |
| <h2 id="decisionTitle" data-i18n="insp.title">属性</h2> | |
| </div> | |
| <span class="relation-id" id="itemId">—</span> | |
| </div> | |
| <div id="inspectorBody"><p class="empty-note" data-i18n="insp.pick">从左侧队列选一条,或在图上点节点/边。</p></div> | |
| </aside> | |
| </main> | |
| <dialog id="helpDialog"> | |
| <div class="dialog-head"> | |
| <h3 data-i18n="help.heading">快捷键</h3> | |
| <button class="icon-button" id="helpClose" aria-label="关闭" data-i18n-aria-label="help.close">×</button> | |
| </div> | |
| <div class="dialog-body"> | |
| <div class="shortcut-grid"> | |
| <kbd>J</kbd><span data-i18n="help.j">队列下一条</span> | |
| <kbd>K</kbd><span data-i18n="help.k">队列上一条</span> | |
| <kbd>B</kbd><span data-i18n="help.b">切换卫星图 / 电子地图</span> | |
| <kbd>E</kbd><span data-i18n="help.e">切换边的画法:沿路走线 / 直线</span> | |
| <kbd>H</kbd><span data-i18n-html="help.h">把当前节点的四个朝向依次放大看(<kbd>Shift</kbd>+<kbd>H</kbd> 反向)</span> | |
| <span class="keys"><kbd>[</kbd> <kbd>]</kbd></span><span data-i18n="help.page">列表上一页 / 下一页</span> | |
| <kbd>Q</kbd><span data-i18n="help.q">切换「全部场景」/「带信号的」</span> | |
| <kbd>?</kbd><span data-i18n="help.help">打开本帮助</span> | |
| </div> | |
| </div> | |
| </dialog> | |
| <div class="lightbox" id="lightbox"><img id="lightboxImage" alt=""></div> | |
| <div id="toast" class="toast"></div> | |
| <script src="app.js"></script> | |
| </body> | |
| </html> | |