Files
lingniu-vehicle-ingest/vehicle-map/index.html
T

263 lines
14 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
<title>羚牛氢能 - 车辆网络 | Lingniu H2 Executive Cockpit</title>
<!-- Google Fonts: Inter & JetBrains Mono -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@500;600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="styles.css?v=__ASSET_VERSION__">
<!-- 高德地图 (AutoNavi AMap) Web JS API v2.0 Configuration -->
<script type="text/javascript">
window._AMapSecurityConfig = {
securityJsCode: '0b54a41143bec162788d01deba851340',
}
</script>
<script type="text/javascript" src="https://webapi.amap.com/maps?v=2.0&key=1868920ac8ff6b6f88dbe9fa2609c183&plugin=AMap.Scale,AMap.ToolBar,AMap.Marker"></script>
</head>
<body class="theme-white">
<!-- APPLE LIQUID GLASS EXECUTIVE COCKPIT WRAPPER -->
<div class="liquid-cockpit-wrapper">
<!-- 1. TOP FLOATING NAVIGATION BAR -->
<header class="liquid-header floating-glass">
<div class="header-left">
<div class="brand-block" title="羚牛氢能 Lingniu Link">
<!-- Official Lingniu Hydrogen Logo (logo_light.svg) -->
<div class="brand-logo-switcher">
<img class="brand-logo-svg" id="brandLogo" src="logo_light.svg" width="150" height="36" alt="羚牛氢能">
<div class="brand-logo-en" id="brandLogoEnglish" hidden aria-label="Lingniu Hydrogen Mobility">
<span class="brand-mark-crop"><img src="logo_light.svg" alt=""></span>
<img src="logo_en.svg?v=20260804045500" alt="Lingniu Hydrogen Mobility">
</div>
</div>
</div>
<div class="brand-divider"></div>
<div class="cockpit-title-wrap">
<h1 class="cockpit-title" id="dashboardTitle" data-i18n="vehicleModeTitle">车辆网络</h1>
</div>
</div>
<!-- Top Three Clean Operational KPI Capsules -->
<div class="header-kpi-group">
<div class="kpi-glass-capsule">
<span class="capsule-lbl" id="kpiTotalLabel" data-i18n="kpiTotalFleet">车辆总数</span>
<span class="capsule-val" id="kpiFleetTotal">-- <small data-i18n="unitVehicles"></small></span>
</div>
<div class="kpi-glass-capsule primary-capsule">
<span class="capsule-lbl" id="kpiActiveLabel" data-i18n="kpiOnlineFleet">当前在线运行</span>
<span class="capsule-val" id="kpiFleetOnline">-- <small data-i18n-append="onlinePct"></small></span>
</div>
<div class="kpi-glass-capsule">
<span class="capsule-lbl" id="kpiActivityLabel" data-i18n="kpiDailyMileage">今日运营里程</span>
<span class="capsule-val" id="kpiDailyDist">-- <small>km</small></span>
</div>
</div>
<!-- Header Controls: Mode Switcher, Theme Switcher & Language Switcher -->
<div class="header-controls">
<div class="glass-segmented-control">
<button class="segment-btn active" id="btnModeStation" onclick="switchMode('station')" data-i18n="btnStation">加氢站</button>
<button class="segment-btn is-locked" id="btnModeVehicle" onclick="switchMode('vehicle')" data-i18n="btnVehicle">车辆</button>
</div>
<!-- Bilingual ZH / EN Switcher -->
<div class="glass-segmented-control lang-switcher-bw">
<button class="segment-btn lang-zh-btn active" onclick="setLanguage('zh')"></button>
<button class="segment-btn lang-en-btn" onclick="setLanguage('en')">EN</button>
</div>
<!-- Professional Vector SVG Theme Switcher (DEFAULT: LIGHT MODE) -->
<div class="theme-switcher-bw">
<button class="bw-btn theme-dark-btn" title="深色模式 (Dark Mode)" onclick="setTheme('theme-dark')">
<svg class="bw-svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
</svg>
<span data-i18n="themeDark">深色</span>
</button>
<button class="bw-btn theme-white-btn active" title="浅色模式 (Light Mode)" onclick="setTheme('theme-white')">
<svg class="bw-svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
<span data-i18n="themeLight">浅色</span>
</button>
</div>
<button class="access-trigger" id="accessTrigger" type="button" onclick="toggleOperationsAccess()" data-i18n="authEntry">运营授权</button>
<div class="time-widget" id="clockTime">19:04:00</div>
</div>
</header>
<!-- 2. MAIN BODY (CENTER MAP CANVAS + RIGHT SIDEBAR) -->
<main class="cockpit-main-grid">
<!-- SPATIAL AMAP 3D CANVAS LAYER -->
<section class="map-spatial-container floating-glass">
<!-- Map Floating Status Pill -->
<div class="map-top-bar">
<div class="status-glass-pill">
<span class="pulse-ring"></span>
<span id="mapStatusText">正在同步开放平台数据…</span>
</div>
</div>
<div class="map-explore-toolbar" aria-label="地图筛选与定位">
<button class="locate-btn" id="locateDeviceBtn" type="button" onclick="locateDevice()" aria-label="定位到我的位置" title="定位到我的位置">
<svg viewBox="0 0 24 24" aria-hidden="true">
<circle cx="12" cy="12" r="3"></circle>
<path d="M12 2v3M12 19v3M2 12h3M19 12h3"></path>
<circle cx="12" cy="12" r="8"></circle>
</svg>
<span id="locateDeviceLabel" data-i18n="btnLocate">定位</span>
</button>
<div class="explore-search-shell">
<label class="entity-search-field" for="entitySearch">
<svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="11" cy="11" r="7"></circle><path d="m20 20-3.6-3.6"></path></svg>
<input id="entitySearch" type="search" autocomplete="off" placeholder="搜索位置、站点、车牌或 VIN" aria-label="搜索位置、站点、车牌或 VIN" oninput="handleExploreInput(this.value)" onfocus="openExploreSuggestions()" onkeydown="handleExploreSearchKeydown(event)">
<button class="search-clear-btn" id="searchClearBtn" type="button" onclick="clearNameFilter()" aria-label="清除名称筛选" hidden>×</button>
</label>
<div class="explore-suggestions" id="exploreSuggestions" role="listbox" aria-label="搜索建议" hidden></div>
</div>
<div class="filter-chip-rail" id="filterChipRail" aria-label="当前筛选" hidden></div>
<span class="filter-result-meta" id="filterResultMeta" aria-live="polite">全部 0</span>
<span class="location-feedback" id="locationFeedback" role="status" hidden></span>
</div>
<!-- AMap 3D Canvas -->
<div class="amap-canvas-box">
<div id="amapContainer"></div>
<article class="map-detail-card" id="mapDetailCard" aria-live="polite" hidden>
<div class="detail-card-accent" id="detailCardAccent"></div>
<div class="detail-card-header">
<div class="detail-title-wrap">
<span class="detail-type-pill" id="detailTypePill">车辆</span>
<h2 id="detailTitle"></h2>
<p id="detailSubtitle"></p>
</div>
<div class="detail-card-actions">
<button class="detail-navigate-btn" id="detailNavigateBtn" type="button" onclick="navigateToSelectedEntity()" aria-label="导航" title="导航" hidden>
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M20.7 3.3 14.4 20.1a1.2 1.2 0 0 1-2.2.1l-2.6-5.8-5.8-2.6a1.2 1.2 0 0 1 .1-2.2l16.8-6.3Z"></path><path d="m9.5 14.5 4.9-4.9"></path></svg>
</button>
<button class="detail-close-btn" type="button" onclick="closeEntityDetails()" aria-label="关闭详情">×</button>
</div>
</div>
<dl class="detail-grid" id="detailGrid"></dl>
<button class="detail-expand-btn" id="detailExpandBtn" type="button" onclick="toggleEntityDetails()" hidden>展开详情</button>
</article>
<!-- Bottom Right Floating Controls -->
<div class="map-action-controls">
<button class="glass-btn" onclick="resetMapView()" data-i18n="btnResetView">复位视角</button>
<button class="glass-btn" onclick="togglePitchView()" data-i18n="btn3dView">3D/2D 视角</button>
<button class="glass-btn" id="filterBtn" onclick="clearProvinceFilter()" data-i18n="btnNationalView">全国视图</button>
</div>
</div>
<!-- Map Footer Bar -->
<div class="map-bottom-info">
<span id="mapFooterGis" data-i18n="mapFooterGis">高质感地图引擎: 羚牛氢能GIS (AMap 3D Engine)</span>
<span id="mapFooterStatus" data-i18n="mapFooterStatus">系统状态: 稳定连接 (AES-256)</span>
<span id="selectedRegionHint" data-i18n="hintNational">视角: 全国运营态势</span>
</div>
</section>
<!-- RIGHT SIDEBAR (2 LIQUID GLASS CARDS) -->
<aside class="sidebar-operations">
<!-- Card 1: vehicles show total / driving / idle; offline is supporting information -->
<div class="glass-panel sidebar-card">
<div class="panel-header">
<span class="panel-title" id="panelStatusTitle">车辆运营状态分布</span>
<span class="panel-tag">STATUS</span>
</div>
<div class="status-glass-grid3">
<div class="glass-cell cell-running">
<div class="cell-num" id="statusValue1">-- <small data-i18n="unitVehicles"></small></div>
<div class="cell-label"><span class="status-dot dot-mint"></span> <span id="statusLabel1" data-i18n="statusRunning">运行中</span> <span id="statusPct1"></span></div>
</div>
<div class="glass-cell cell-stopped">
<div class="cell-num" id="statusValue2">-- <small data-i18n="unitVehicles"></small></div>
<div class="cell-label"><span class="status-dot dot-blue"></span> <span id="statusLabel2" data-i18n="statusStopped">静止中</span> <span id="statusPct2"></span></div>
</div>
<div class="glass-cell cell-offline">
<div class="cell-num" id="statusValue3">-- <small data-i18n="unitVehicles"></small></div>
<div class="cell-label"><span class="status-dot dot-sub"></span> <span id="statusLabel3" data-i18n="statusOffline">离线</span> <span id="statusPct3"></span></div>
</div>
</div>
<!-- Apple Style Segmented Progress Track -->
<div class="liquid-progress-bar">
<div class="seg seg-running" style="width: 52.9%;"></div>
<div class="seg seg-stopped" style="width: 30.4%;"></div>
</div>
</div>
<!-- Card 2: 重点区域 TOP 排名 (Liquid Glass Ranking List) -->
<div class="glass-panel sidebar-card flex-fill-auto">
<div class="panel-header">
<div class="panel-heading-stack">
<span class="panel-title" id="panelRankTitle">车辆累计里程 TOP 排名</span>
<span class="viewport-meta" id="rankViewportMeta" hidden></span>
</div>
<div class="glass-tab-control">
<button class="gtab active" id="rankPrimaryTab" onclick="switchRankTab('primary')">按数量</button>
<button class="gtab" id="rankSecondaryTab" onclick="switchRankTab('secondary')">按里程</button>
</div>
</div>
<div class="liquid-ranking-list" id="rankingListBox">
<!-- Dynamic Ranking Rows -->
</div>
</div>
</aside>
</main>
</div>
<dialog class="access-dialog" id="accessDialog" aria-labelledby="accessDialogTitle">
<form class="access-dialog-card" method="dialog" onsubmit="event.preventDefault(); authorizeOperationsAccess();">
<div class="access-dialog-icon" aria-hidden="true"></div>
<div class="access-dialog-heading">
<h2 id="accessDialogTitle" data-i18n="authTitle">进入运营数据</h2>
<p id="accessDialogHint" data-i18n="authDescription">车辆全量信息与加氢量仅向获得授权的用户展示。</p>
</div>
<p class="access-session-note" data-i18n="authExpiry">本次授权有效期为 30 分钟,到期后将自动恢复为公开站点视图。</p>
<label class="access-code-field" for="accessCodeInput">
<span data-i18n="authCodeLabel">访问码</span>
<input id="accessCodeInput" type="password" autocomplete="current-password" enterkeyhint="done" data-i18n-placeholder="authCodePlaceholder" placeholder="输入访问码">
</label>
<p class="access-dialog-error" id="accessDialogError" role="alert" hidden></p>
<div class="access-dialog-actions">
<button type="button" class="access-cancel-btn" onclick="closeAccessDialog()" data-i18n="authCancel">暂不授权</button>
<button type="submit" class="access-submit-btn" id="accessSubmitBtn" data-i18n="authSubmit">验证并进入</button>
</div>
</form>
</dialog>
<!-- 生产发布包不携带 node_modules;固定版本的 CDN 让中文地点保持拼音/首字母搜索能力。 -->
<script src="https://cdn.jsdelivr.net/npm/pinyin-pro@3.28.2/dist/index.js" crossorigin="anonymous"></script>
<script src="app.js?v=__ASSET_VERSION__"></script>
</body>
</html>