## 1. 用户管理:角色过滤(页面总共只有三种角色,默认罗列全部太吵) 前端加角色下拉 + 后端 `GET /users` 新增 `role` 参数(0/1/2,越界当作不过滤)。 后端把 `build_user_list_where` 从**二元穷举 match 重构为条件累加** —— 加第三个过滤器时穷举会涨到 8 分支且极易漏。同时修一个潜在坑: **OR 条件必须整体加括号**,否则 `phone LIKE ? OR name LIKE ?` 与 `organization_id = ?` 用 AND 混排时会变成 `(A AND phone LIKE ?) OR name LIKE ?`,把组织/角色过滤整个击穿 (搜个姓名就跨组织串数据)。 新增 6 个守门单测(含"占位符个数必须与 bind 次数一致"的反证), 已自证能失败:去掉 OR 括号 → 2 个用例 FAILED,还原 → 6 passed。 ## 2. 数据范围:仅操作员(role=0)可配 按用户口径: - **总管理员**:豁免范围限制,不需要配; - **企业管理员**:天然管理本组织全部设备,配项目级范围反而有歧义; - **操作员**:才需要设置可管理的项目。 前端对该按钮按 `record.role !== 0` 置灰并加 title 说明。 **创建/编辑时操作员必须选组织**(没有企业归属就看不到任何设备),校验文案也分开提示。 ## 3. 柜子详情:透出电表读数 接口早已返回 `meter_wh`/`meter_at`,但**前端从没接过**(用户看不到)。 现加到详情页基本信息行(IMEI/ICCID/名称 之后),Wh → kWh 展示并附收到时刻; `null` = 从未上报过,显示 `-` 而**不是 0 度**。 ## ⛔ 表号:系统里没有,做不了 全仓搜不到 `meter_no`/`meter_id`/`meter_sn`/`表号`,协议里 `cabinet.meter` 只是读数(Wh),**没有电表编号字段**。这需要硬件侧在协议里加字段, 平台无法单方面补。 ## ⚠️ 我这次犯的流程错误(已修正) 改了 Rust 代码后**只跑了 cargo check/test,没重新 `zigbuild` release 产物**, `deploy -SkipBuild` 于是把几小时前的旧二进制发上去了 —— 第一次实测角色过滤 三种角色全返回、监控词。重建后才通过。 **教训:改 Rust 后必须重建 release 产物再发。** ## 验收 - `cargo check --all-targets` 两服务:**0 error / 0 warning** - `cargo test --bin pms-api`:**210 passed**(204 + 6 新) - web `npm run typecheck`:exit 0 - **角色过滤实测**(测试环境,临时超管+自签 JWT,用完即删): ``` role=0 → 2 人,role 集合 [0] OK role=1 → 1 人,role 集合 [1] OK role=2 → 2 人,role 集合 [2] OK 不带 role → [0,1,2] OK role=0 + keyword → 1 人 OK(keyword 单独查命中 0,证明不是靠关键字通过) role=9 越界 → 5 人 OK(当作不过滤) ``` - 已发布测试 + 生产(四服务 active、0 ERROR、消费链探测通过、二进制时间戳已核对)
447 lines
17 KiB
HTML
447 lines
17 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<!-- 全站统一 favicon:与 web 管理端同源(logo/favicon.svg) -->
|
||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||
<title>艾动智能 — 智能充电柜矩阵系统</title>
|
||
<!-- 社交分享(og / Twitter):此前完全缺失,链接被分享时没有预览图 -->
|
||
<meta property="og:type" content="website">
|
||
<meta property="og:site_name" content="艾动智能">
|
||
<meta property="og:title" content="艾动智能 — 为换电场景打造的下一代智能充电">
|
||
<meta property="og:description" content="36 仓独立直流快充,4G 远程实时管控,多重安全防护体系。从硬件到云端,全栈自研的智能充电解决方案。">
|
||
<meta property="og:image" content="https://app.anzhizhichong.com/og-image.jpg">
|
||
<meta property="og:image:width" content="1200">
|
||
<meta property="og:image:height" content="630">
|
||
<meta property="og:url" content="https://app.anzhizhichong.com/">
|
||
<meta name="twitter:card" content="summary_large_image">
|
||
<meta name="twitter:title" content="艾动智能 — 为换电场景打造的下一代智能充电">
|
||
<meta name="twitter:description" content="36 仓独立直流快充,4G 远程实时管控,多重安全防护体系。从硬件到云端,全栈自研。">
|
||
<meta name="twitter:image" content="https://app.anzhizhichong.com/og-image.jpg">
|
||
<style>
|
||
/* ==========================================================================
|
||
艾动智能 · 产品介绍页(单屏不滚动 / 明亮浅色)
|
||
—— 设计口径见 AGENTS.md「操作规则」:偏好明亮浅色、单屏不滚动,⛔ 不做暗色科技风
|
||
—— 品牌色直接取自 logo:logo/纯色横向.svg 的 .cls-1 = #0366e6
|
||
========================================================================== */
|
||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||
|
||
:root {
|
||
--brand: #0366e6; /* 取自 logo 的蓝,全站强调色统一用它 */
|
||
--brand-dark: #0354c4; /* hover 加深 */
|
||
--brand-soft: #eaf2fe; /* 极浅蓝底,用于标签/弱化背景 */
|
||
--ink: #0F1419; /* 主标题 */
|
||
--body: #454B58; /* 正文 */
|
||
--muted: #8B92A5; /* 辅助文字 */
|
||
--line: rgba(15,20,25,0.08);
|
||
}
|
||
|
||
html, body {
|
||
height: 100%;
|
||
overflow: hidden; /* 单屏不滚动(AGENTS.md 口径) */
|
||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans SC", sans-serif;
|
||
color: var(--body);
|
||
-webkit-font-smoothing: antialiased;
|
||
}
|
||
|
||
a { color: inherit; text-decoration: none; }
|
||
|
||
/* ===== 整体:上 / 中 / 下 三块,中块自适应 ===== */
|
||
.layout { display: flex; flex-direction: column; height: 100vh; }
|
||
|
||
/* ===== 背景:浅色渐变 + 右侧 3D 舞台 =====
|
||
柜子由 Three.js 实时渲染在透明 canvas 上,"浮"在这层浅色渐变上 ——
|
||
⛔ 不存在图片硬边界(这正是之前"贴图感"的根因)。
|
||
3D 不可用(WebGL 缺失/脚本异常)时,JS 会给 <body> 加 .no3d 类,
|
||
由 .stage-fallback 展示静态主视觉图,页面照常可用。 */
|
||
.bg {
|
||
position: fixed; inset: 0; z-index: 0; pointer-events: none;
|
||
background:
|
||
radial-gradient(1100px 760px at 74% 42%, rgba(3,102,230,0.070), transparent 66%),
|
||
radial-gradient(900px 640px at 92% 86%, rgba(3,102,230,0.045), transparent 70%),
|
||
linear-gradient(to right, #ffffff 0%, #f7f9fc 46%, #eef3fa 100%);
|
||
}
|
||
/* 3D 舞台:右侧,柜子在其中居中。
|
||
⚠️ 上下留 84px 内边距 —— 顶天顶地会显得拥挤、压迫,留白才有"产品感"。 */
|
||
.stage {
|
||
position: fixed; z-index: 1;
|
||
top: 84px; right: 0; bottom: 84px;
|
||
width: min(52vw, 940px);
|
||
pointer-events: auto;
|
||
}
|
||
.stage canvas {
|
||
display: block; width: 100%; height: 100%;
|
||
/* 兜底:WebGL 的 alpha 合成在部分环境会失败(实测 antialias:false + 软件渲染下
|
||
canvas 未绘制区域变成黑块)。给画布自身铺一层浅色背景 ——
|
||
alpha 正常时透出下面的页面渐变;失败时也只是一片浅色,绝不会露黑。 */
|
||
background: linear-gradient(155deg, #ffffff 0%, #f5f8fd 52%, #e8f0fa 100%);
|
||
}
|
||
/* 静态回落图:默认隐藏,仅 .no3d 时显示 */
|
||
.stage-fallback {
|
||
position: absolute; inset: 0;
|
||
background: url("hero-full.jpg") no-repeat center center;
|
||
background-size: cover;
|
||
display: none;
|
||
}
|
||
body.no3d .stage-fallback { display: block; }
|
||
body.no3d .stage canvas { display: none; }
|
||
/* 左侧轻纱:保证毛玻璃上的文字对比度(3D 模式下也要) */
|
||
.scrim {
|
||
position: fixed; inset: 0; z-index: 1; pointer-events: none;
|
||
background: linear-gradient(to right,
|
||
rgba(255,255,255,0.60) 0%,
|
||
rgba(255,255,255,0.30) 34%,
|
||
rgba(255,255,255,0.04) 54%,
|
||
transparent 66%);
|
||
}
|
||
|
||
/* ===== TOP: 顶部导航 =====
|
||
⚠️ pointer-events 的坑:.top/.mid/.bot 都是**通栏**容器,子元素只占一侧,
|
||
但容器自身会横跨整个宽度并把鼠标事件吃掉 —— 右侧 3D canvas 就收不到
|
||
拖拽/滚轮了(OrbitControls 装在 canvas 上)。所以通栏容器一律
|
||
pointer-events:none,只让真正可交互的子元素恢复 auto。 */
|
||
.top {
|
||
position: relative; z-index: 4;
|
||
flex-shrink: 0;
|
||
display: flex; align-items: center; justify-content: space-between;
|
||
padding: 14px 48px;
|
||
pointer-events: none;
|
||
}
|
||
.top-brand { display: flex; align-items: center; pointer-events: auto; }
|
||
/* 横版锁标 1511.75×413.59(≈3.65:1);48px 高 ⇒ 约 175px 宽 */
|
||
.logo { height: 46px; width: auto; display: block; }
|
||
|
||
.top-links { display: flex; align-items: center; gap: 6px; pointer-events: auto; }
|
||
.top-link {
|
||
font-size: 13px; font-weight: 500; color: var(--body);
|
||
padding: 8px 16px; border-radius: 8px; transition: all .2s;
|
||
}
|
||
.top-link:hover { background: var(--brand-soft); color: var(--brand); }
|
||
.top-link--cta { background: var(--ink); color: #fff; }
|
||
.top-link--cta:hover { background: #23272F; color: #fff; }
|
||
|
||
/* ===== MID: 浅色渐变上叠一块毛玻璃文案面板 =====
|
||
⚠️ 容器通栏但 pointer-events:none(否则挡住右侧 3D 的鼠标事件),
|
||
只让 .copy 面板自身可交互。 */
|
||
.mid {
|
||
position: relative; z-index: 3;
|
||
flex: 1; min-height: 0;
|
||
display: flex; align-items: center;
|
||
padding: 0 56px;
|
||
pointer-events: none;
|
||
}
|
||
|
||
/* ---- 毛玻璃面板 ----
|
||
半透明白底 + 背景模糊:背后的柜子与渐变会隐约透出来,
|
||
边界从"贴图的硬边"变成"玻璃的质感"——这是消除突兀感的关键。 */
|
||
.copy {
|
||
width: min(720px, 44vw);
|
||
padding: 40px 44px;
|
||
display: flex; flex-direction: column; gap: 20px;
|
||
background: rgba(255,255,255,0.56);
|
||
-webkit-backdrop-filter: blur(26px) saturate(1.5);
|
||
backdrop-filter: blur(26px) saturate(1.5);
|
||
border: 1px solid rgba(255,255,255,0.72);
|
||
border-radius: 22px;
|
||
box-shadow:
|
||
0 24px 60px rgba(15,20,25,0.10),
|
||
0 2px 8px rgba(15,20,25,0.04),
|
||
inset 0 1px 0 rgba(255,255,255,0.85);
|
||
pointer-events: auto; /* 面板自身要能选中文字/点按钮 */
|
||
}
|
||
|
||
/* 小标签:品牌蓝 + 呼吸圆点 */
|
||
.tag {
|
||
display: inline-flex; align-items: center; gap: 8px;
|
||
padding: 6px 14px 6px 12px;
|
||
background: var(--brand-soft);
|
||
border: 1px solid rgba(3,102,230,0.16);
|
||
border-radius: 100px;
|
||
font-size: 13px; font-weight: 600; color: var(--brand);
|
||
width: fit-content;
|
||
}
|
||
.tag .dot {
|
||
width: 7px; height: 7px; border-radius: 50%;
|
||
background: var(--brand);
|
||
box-shadow: 0 0 0 0 rgba(3,102,230,0.45);
|
||
animation: pulse 2.4s ease-out infinite;
|
||
}
|
||
@keyframes pulse {
|
||
0% { box-shadow: 0 0 0 0 rgba(3,102,230,0.40); }
|
||
70% { box-shadow: 0 0 0 7px rgba(3,102,230,0); }
|
||
100% { box-shadow: 0 0 0 0 rgba(3,102,230,0); }
|
||
}
|
||
|
||
h1 {
|
||
font-size: clamp(38px, 4.2vw, 58px);
|
||
font-weight: 800;
|
||
line-height: 1.18;
|
||
letter-spacing: -0.02em;
|
||
color: var(--ink);
|
||
}
|
||
h1 .accent { color: var(--brand); }
|
||
|
||
.subhead {
|
||
font-size: clamp(15px, 1.25vw, 17px);
|
||
font-weight: 400;
|
||
line-height: 1.8;
|
||
color: var(--body);
|
||
max-width: 500px;
|
||
}
|
||
|
||
/* 能力标签:只放 stats 里没有的,避免信息重复 */
|
||
.pills { display: flex; flex-wrap: wrap; gap: 8px; }
|
||
.pill {
|
||
padding: 5px 13px;
|
||
background: #fff;
|
||
border: 1px solid var(--line);
|
||
border-radius: 100px;
|
||
font-size: 13px; font-weight: 500; color: var(--body);
|
||
box-shadow: 0 1px 2px rgba(15,20,25,0.03);
|
||
}
|
||
|
||
/* 行动按钮(此前只有 CSS、HTML 里从未渲染过)*/
|
||
.ctas { display: flex; align-items: center; gap: 12px; margin-top: 2px; }
|
||
.btn {
|
||
display: inline-flex; align-items: center; gap: 8px;
|
||
padding: 13px 26px;
|
||
font-size: 15px; font-weight: 600;
|
||
border-radius: 10px; transition: all .2s;
|
||
white-space: nowrap;
|
||
}
|
||
.btn-primary {
|
||
background: var(--brand); color: #fff;
|
||
box-shadow: 0 6px 20px rgba(3,102,230,0.24);
|
||
}
|
||
.btn-primary:hover {
|
||
background: var(--brand-dark);
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 10px 26px rgba(3,102,230,0.30);
|
||
}
|
||
.btn-ghost { color: var(--body); border: 1.5px solid rgba(15,20,25,0.13); background: #fff; }
|
||
.btn-ghost:hover { border-color: var(--brand); color: var(--brand); }
|
||
.btn .arrow { transition: transform .2s; }
|
||
.btn-primary:hover .arrow { transform: translateX(3px); }
|
||
|
||
/* 数据条 */
|
||
.stats {
|
||
display: flex; gap: 40px;
|
||
padding-top: 18px; margin-top: 4px;
|
||
border-top: 1px solid var(--line);
|
||
}
|
||
.stat-num {
|
||
font-size: 30px; font-weight: 800; color: var(--ink);
|
||
line-height: 1.1; letter-spacing: -0.01em;
|
||
font-variant-numeric: tabular-nums; /* 数字等宽,四个数据对齐 */
|
||
}
|
||
.stat-num .unit { font-size: 15px; font-weight: 700; color: var(--muted); margin-left: 2px; }
|
||
.stat-label { font-size: 12px; font-weight: 500; color: var(--muted); margin-top: 5px; }
|
||
|
||
/* ===== BOT: 底部备案 ===== */
|
||
.bot {
|
||
position: relative; z-index: 2;
|
||
flex-shrink: 0;
|
||
text-align: center; padding: 14px;
|
||
font-size: 12px; color: var(--muted);
|
||
}
|
||
.bot a { color: var(--brand); }
|
||
.bot a:hover { text-decoration: underline; }
|
||
|
||
/* ===== 自适应:窄屏时收紧,保证仍然单屏不滚动 ===== */
|
||
@media (max-width: 1180px) {
|
||
.mid { padding: 0 32px; }
|
||
.copy { width: min(640px, 60vw); padding: 32px 34px; }
|
||
.stage { width: min(64vw, 760px); }
|
||
.stats { gap: 26px; }
|
||
.stat-num { font-size: 26px; }
|
||
}
|
||
/* 更窄/更矮时:面板占满,3D 舞台退到背后并减弱轻纱 */
|
||
@media (max-width: 820px), (max-height: 600px) {
|
||
.copy { width: 100%; padding: 26px 26px; }
|
||
.stage { width: 100%; opacity: 0.55; }
|
||
.scrim {
|
||
background: linear-gradient(to right,
|
||
rgba(255,255,255,0.74) 0%, rgba(255,255,255,0.44) 55%, transparent 88%);
|
||
}
|
||
}
|
||
/* 用户偏好减少动效时,关掉自动旋转(JS 里也会读) */
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.tag .dot { animation: none; }
|
||
}
|
||
|
||
/* ==========================================================================
|
||
移动端适配(竖屏 / 窄屏)
|
||
桌面的「fixed 右侧舞台 + 通栏轻纱 + 单屏不滚动」在竖屏上会挤爆,
|
||
这里改成:3D 变成顶部 hero 块,文案在下面正常流式排列,页面可滚动。
|
||
========================================================================== */
|
||
@media (max-width: 860px) {
|
||
/* 桌面是单屏不滚动;移动端内容多,必须允许纵向滚动 */
|
||
html, body { height: auto; overflow-x: hidden; overflow-y: auto; }
|
||
.layout { height: auto; min-height: 100vh; }
|
||
body { -webkit-text-size-adjust: 100%; }
|
||
|
||
/* 顶部导航收紧 */
|
||
.top { padding: 12px 18px; }
|
||
.logo { height: 34px; }
|
||
.top-link { padding: 6px 12px; font-size: 12px; }
|
||
.top-link--cta { padding: 7px 14px; }
|
||
|
||
/* 3D 变成顶部 hero 块:有界、不固定、给足高度 */
|
||
.stage {
|
||
position: relative;
|
||
top: auto; right: auto; bottom: auto;
|
||
width: 100%;
|
||
height: 46vh;
|
||
min-height: 280px;
|
||
max-height: 460px;
|
||
}
|
||
/* 单指拖拽旋转模型,不要拿去滚页面(舞台是有界块,周围仍可滚动) */
|
||
.stage canvas { touch-action: none; }
|
||
/* 通栏轻纱在移动端会糊掉 hero,去掉;背景改简洁浅色渐变 */
|
||
.scrim { display: none; }
|
||
.bg {
|
||
background: linear-gradient(to bottom, #ffffff 0%, #f4f7fc 60%, #eaf0f9 100%);
|
||
}
|
||
|
||
/* 文案面板:通栏、贴住 hero 底部 */
|
||
.mid { padding: 0 16px; margin-top: 6px; align-items: flex-start; }
|
||
.copy {
|
||
width: 100%;
|
||
padding: 26px 22px;
|
||
border-radius: 18px;
|
||
/* 移动端毛玻璃成本高(backdrop-filter + 3D 重绘),改用更实的白底保证可读 */
|
||
background: rgba(255,255,255,0.90);
|
||
-webkit-backdrop-filter: none;
|
||
backdrop-filter: none;
|
||
}
|
||
|
||
h1 { font-size: clamp(28px, 7.6vw, 40px); line-height: 1.22; }
|
||
.subhead { font-size: 14px; line-height: 1.75; }
|
||
.pill { font-size: 12px; padding: 4px 11px; }
|
||
.btn { padding: 12px 20px; font-size: 14px; }
|
||
.stats { gap: 18px 22px; flex-wrap: wrap; }
|
||
.stat-num { font-size: 22px; }
|
||
.stat-num .unit { font-size: 13px; }
|
||
.stat-label { font-size: 11px; }
|
||
.bot { padding: 16px 12px 20px; font-size: 11px; }
|
||
}
|
||
|
||
/* 极窄屏(老手机 / 分屏)*/
|
||
@media (max-width: 380px) {
|
||
.stage { height: 38vh; min-height: 220px; }
|
||
.copy { padding: 20px 16px; }
|
||
.stats { gap: 14px 18px; }
|
||
.stat-num { font-size: 19px; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<div class="bg"></div>
|
||
<div class="scrim" aria-hidden="true"></div>
|
||
|
||
<div class="layout">
|
||
|
||
<!-- 上:顶部导航 -->
|
||
<div class="top">
|
||
<div class="top-brand">
|
||
<!-- 横版锁标(图标 + "艾动智能"字样,文字已转为路径、无字体依赖)-->
|
||
<img class="logo" src="logo.svg" alt="艾动智能">
|
||
</div>
|
||
<div class="top-links">
|
||
<a href="/doc/" class="top-link">开发文档</a>
|
||
<a href="/pms/" class="top-link top-link--cta">管理后台</a>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 3D 舞台:桌面端 fixed 到右侧;移动端变为顶部 hero 块(见媒体查询)。
|
||
柜子由 Three.js 实时渲染;不可用时回落静态图。 -->
|
||
<div class="stage" id="stage">
|
||
<div class="stage-fallback" aria-hidden="true"></div>
|
||
<canvas id="cabinet-canvas"></canvas>
|
||
</div>
|
||
|
||
<script type="importmap">
|
||
{
|
||
"imports": {
|
||
"three": "./vendor/three.module.min.js",
|
||
"three/addons/": "./vendor/addons/"
|
||
}
|
||
}
|
||
</script>
|
||
<script type="module">
|
||
// 3D 就绪/失败都要有明确信号:失败则 <body> 加 .no3d,展示静态主视觉图
|
||
const fail = (why) => {
|
||
document.body.classList.add('no3d');
|
||
console.warn('[cabinet3d] 回落到静态图:', why);
|
||
};
|
||
try {
|
||
// 无 WebGL 直接回落,不必加载 700KB 的 three
|
||
const probe = document.createElement('canvas');
|
||
if (!(probe.getContext('webgl2') || probe.getContext('webgl'))) {
|
||
fail('浏览器不支持 WebGL');
|
||
} else {
|
||
import('./cabinet3d.js')
|
||
.then(() => {
|
||
if (window.__cabinet3d && window.__cabinet3d.ok) {
|
||
document.body.classList.add('ready3d');
|
||
} else {
|
||
fail('场景未就绪');
|
||
}
|
||
})
|
||
.catch((e) => fail(e));
|
||
}
|
||
} catch (e) {
|
||
fail(e);
|
||
}
|
||
</script>
|
||
|
||
<div class="mid">
|
||
<div class="copy">
|
||
<div class="tag"><span class="dot"></span>智能充电矩阵系统</div>
|
||
|
||
<h1>为换电场景打造的<br><span class="accent">下一代智能充电</span></h1>
|
||
|
||
<p class="subhead">
|
||
36 仓独立直流快充,4G 远程实时管控,多重安全防护体系。<br>
|
||
从硬件到云端,全栈自研的智能充电解决方案。
|
||
</p>
|
||
|
||
<!-- 只放 stats 未覆盖的能力点,"36仓独立"已由下方数据条表达,不再重复 -->
|
||
<div class="pills">
|
||
<span class="pill">多重防护</span>
|
||
<span class="pill">4G 在线</span>
|
||
<span class="pill">BMS 适配</span>
|
||
</div>
|
||
|
||
<!-- 首屏行动按钮 -->
|
||
<div class="ctas">
|
||
<a href="/pms/" class="btn btn-primary">
|
||
进入管理后台
|
||
<svg class="arrow" width="16" height="16" viewBox="0 0 24 24" fill="none"
|
||
stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M5 12h14M13 6l6 6-6 6"/>
|
||
</svg>
|
||
</a>
|
||
<a href="/doc/" class="btn btn-ghost">开发文档</a>
|
||
</div>
|
||
|
||
<div class="stats">
|
||
<div><div class="stat-num">36</div><div class="stat-label">独立仓体</div></div>
|
||
<div><div class="stat-num"><0.5<span class="unit">s</span></div><div class="stat-label">指令响应</div></div>
|
||
<div><div class="stat-num">8000<span class="unit">h</span></div><div class="stat-label">MTBF</div></div>
|
||
<div><div class="stat-num">99<span class="unit">%</span></div><div class="stat-label">可用率</div></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 下:备案 -->
|
||
<div class="bot">
|
||
© 2026 艾动智能 · <a href="https://beian.miit.gov.cn/" target="_blank" rel="noopener">苏ICP备2025198376号-1</a>
|
||
</div>
|
||
</div>
|
||
|
||
</body>
|
||
</html>
|