init: 羚牛车辆数据中心原型 + 部署配置
All checks were successful
ci/woodpecker/manual/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/manual/woodpecker Pipeline was successful
- React 18 + Babel-in-browser SPA 原型,覆盖 8 个画板: 实时地图 / 车辆详情 / 历史查询 / 轨迹回放 / 事件规则 / 通知中心 / ESG 碳减排 / 移动端 - 设计系统:IBM Plex Sans + JetBrains Mono,亮/暗双主题,羚牛绿 #007143 - 数据模型:12 + 40 辆车,TBOX (T) / JT808+1078 (JT) / 双源 (B) - 部署:nginx 静态托管,Dockerfile + woodpecker.yml + docker-compose.yml - 镜像:harbor.lnh2e.com/lingniu-v1/ln-vdc:<branch>-<VERSION> - 容器端口 80,宿主映射 8112,含 /healthz 探活
This commit is contained in:
132
artboards/variant-dense.jsx
Normal file
132
artboards/variant-dense.jsx
Normal file
@@ -0,0 +1,132 @@
|
||||
// artboard-dense.jsx — dense info variation: 4-column with mini-map
|
||||
const ArtboardDense = () => {
|
||||
return (
|
||||
<div className="app">
|
||||
<Sidebar active="map"/>
|
||||
<div style={{flex:1, display:"flex", flexDirection:"column", minWidth:0, position:"relative", zIndex:1}}>
|
||||
<Topbar
|
||||
crumbs={["羚牛车辆数据中心", "运营驾驶舱"]}
|
||||
kpis={[
|
||||
{ lbl:"在线", val:"487", delta:"95%", deltaUp:true },
|
||||
{ lbl:"行驶", val:"312" },
|
||||
{ lbl:"告警P0", val:"2" },
|
||||
{ lbl:"今日里程", val:"24,781 km" },
|
||||
{ lbl:"H₂消耗", val:"482 kg" },
|
||||
{ lbl:"评分", val:"86.4" },
|
||||
]}
|
||||
/>
|
||||
|
||||
<div style={{flex:1, display:"grid", gridTemplateColumns:"1fr 1fr 1fr 1fr", gridTemplateRows:"auto auto 1fr", gap:8, padding:8, minHeight:0}}>
|
||||
{/* KPI cards row */}
|
||||
{[
|
||||
{l:"车辆健康度", v:"94.2", u:"%", c:"var(--accent)", d:[88,90,89,92,91,94,94]},
|
||||
{l:"平均能耗", v:"18.4", u:"kWh/100km", c:"var(--info)", d:[19,18,18.5,18.2,18.4,18.4,18.4]},
|
||||
{l:"H₂利用率", v:"83.1", u:"%", c:"var(--ok)", d:[80,81,82,82,83,83,83.1]},
|
||||
{l:"安全评分", v:"86.4", u:"/100", c:"var(--warn)", d:[85,86,84,87,86,86,86.4]},
|
||||
].map((k,i)=>(
|
||||
<div key={i} className="panel" style={{padding:12}}>
|
||||
<div className="between">
|
||||
<span className="eyebrow">{k.l}</span>
|
||||
<span className="chip ok" style={{fontSize:9}}>▲</span>
|
||||
</div>
|
||||
<div style={{marginTop:6}}>
|
||||
<span className="mono strong" style={{fontSize:24, fontWeight:600}}>{k.v}</span>
|
||||
<span className="muted mono" style={{fontSize:10, marginLeft:3}}>{k.u}</span>
|
||||
</div>
|
||||
<div style={{marginTop:4}}>
|
||||
<LineChart data={k.d} w={220} h={32} color={k.c}/>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
{/* Map spans 2 cols 2 rows */}
|
||||
<div className="panel" style={{gridColumn:"1 / span 2", gridRow:"2 / span 2", overflow:"hidden", position:"relative"}}>
|
||||
<div className="panel-head" style={{position:"absolute", top:0, left:0, right:0, zIndex:2, background:"oklch(0.18 0.020 245 / 0.85)", backdropFilter:"blur(8px)"}}>
|
||||
<Icon name="map" size={13}/><span className="title">实时分布</span>
|
||||
<div className="actions">
|
||||
<span className="chip">热力</span><span className="chip accent">车辆</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{height:"100%"}}>
|
||||
<FleetMap selectedId="浙F07179F" onSelect={()=>{}} showHeatmap/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Status donut */}
|
||||
<div className="panel">
|
||||
<div className="panel-head"><span className="title">车辆状态</span></div>
|
||||
<div style={{padding:10, display:"flex", gap:14, alignItems:"center"}}>
|
||||
<Donut size={90} value={0.61} color="var(--ok)" thick={10} label="312"/>
|
||||
<div className="col gap-2" style={{flex:1, fontSize:11}}>
|
||||
<div className="between"><span className="mid gap-1"><span className="dot ok"/> 行驶</span><span className="mono strong">312</span></div>
|
||||
<div className="between"><span className="mid gap-1"><span className="dot warn"/> 待命</span><span className="mono strong">155</span></div>
|
||||
<div className="between"><span className="mid gap-1"><span className="dot danger"/> 故障</span><span className="mono strong">8</span></div>
|
||||
<div className="between"><span className="mid gap-1"><span className="dot idle"/> 离线</span><span className="mono strong">25</span></div>
|
||||
<div className="between"><span className="muted">维保</span><span className="mono strong">12</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Alerts feed */}
|
||||
<div className="panel">
|
||||
<div className="panel-head"><Icon name="bell" size={13}/><span className="title">实时告警</span><span className="chip danger" style={{marginLeft:"auto"}}>3 NEW</span></div>
|
||||
<div style={{padding:8, display:"flex", flexDirection:"column", gap:6, overflow:"auto", maxHeight:240}}>
|
||||
{[
|
||||
{p:"P0", n:"SOC严重不足", v:"浙F08638F", t:"刚刚"},
|
||||
{p:"P0", n:"右后胎压低", v:"浙F08638F", t:"3m"},
|
||||
{p:"P1", n:"超速预警", v:"浙F02002F", t:"12m"},
|
||||
{p:"P1", n:"H₂下降", v:"浙F07179F", t:"32m"},
|
||||
{p:"P2", n:"急加速", v:"浙F02608F", t:"1h"},
|
||||
].map((a,i)=>(
|
||||
<div key={i} className="between" style={{padding:"6px 8px", background:"var(--bg-2)", borderRadius:4, border:"1px solid var(--border-1)", fontSize:11}}>
|
||||
<div className="mid gap-2">
|
||||
<span className={"chip " + (a.p==="P0"?"danger":a.p==="P1"?"warn":"")}>{a.p}</span>
|
||||
<span className="strong">{a.n}</span>
|
||||
<span className="mono muted">· {a.v}</span>
|
||||
</div>
|
||||
<span className="mono muted" style={{fontSize:10}}>{a.t}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Energy chart */}
|
||||
<div className="panel">
|
||||
<div className="panel-head"><Icon name="bolt" size={13}/><span className="title">能耗 · 24h</span></div>
|
||||
<div style={{padding:12}}>
|
||||
<Bars data={[12,8,6,5,4,4,9,14,22,28,26,24,22,28,30,28,24,20,18,16,14,12,10,8]} w={240} h={80} color="var(--info)"/>
|
||||
<div className="between" style={{marginTop:8, fontSize:11}}>
|
||||
<span className="muted">总计</span>
|
||||
<span className="mono strong">4,562 kWh</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* H2 stations */}
|
||||
<div className="panel">
|
||||
<div className="panel-head"><Icon name="h2" size={13}/><span className="title">补能站</span></div>
|
||||
<div style={{padding:8, fontSize:11}}>
|
||||
{[
|
||||
{n:"#04 朝阳", v:0.78, k:"4号站 · 78%"},
|
||||
{n:"#02 海淀", v:0.42, k:"2号站 · 42%"},
|
||||
{n:"#07 丰台", v:0.91, k:"7号站 · 91%"},
|
||||
{n:"#11 通州", v:0.25, k:"11号站 · 25%"},
|
||||
].map((s,i)=>(
|
||||
<div key={i} style={{marginBottom:8}}>
|
||||
<div className="between" style={{marginBottom:3}}>
|
||||
<span className="mono">{s.k}</span>
|
||||
<span className="mono strong">{Math.round(s.v*100)}%</span>
|
||||
</div>
|
||||
<div className="bar" style={{height:5}}>
|
||||
<i style={{width: s.v*100+"%", background: s.v < 0.3 ? "var(--danger)" : s.v < 0.5 ? "var(--warn)" : "var(--accent)"}}/>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
window.ArtboardDense = ArtboardDense;
|
||||
Reference in New Issue
Block a user