小程序管理端中,充电桩监控功能的实现
2026-01-09 · 技术解析

实时监控功能是奥升充电系统中,很受管理者喜欢的一个功能。通过它,管理者可以在小程序端随时查看站点的运营情况,了解充电桩的实时状态。

监控界面

一、轮询更新状态

为什么不用WebSocket?

实时监控为什么不使用WebSocket这种"实时"技术呢?这里有几个重要考虑:

第一,够用就好。实时监控功能,主要是查看充电桩的实时状态,不涉及双向交互通信的情况,只需要单向拉取充电桩的状态。而且,用户对实时性要求不高,5秒频率的更新是可接受的。

第二,资源消耗。WebSocket需要维持长连接,对小程序的内存和电量消耗较大。而轮询方式只在需要时请求数据,更加节能。

第三,兼容性。不同小程序平台对WebSocket的支持程度不一,轮询作为最基础的HTTP请求,兼容性最好。

轮询的具体实现

我们来看代码中的轮询实现:

const loadingCountdown = ref(5000) // 5秒间隔
const refreshGunTimer = ref<any>(null)
const responseTime = ref('')

// 刷新枪状态
const stat = ref({})
const refreshConnectorList = async () => {
  clearTimeout(refreshGunTimer.value)
  if (!stationId.value) return

  try {
    const res = await getPileStatus(stationId.value)
    equipmentList.value = res.data.equipmentList
    stat.value = res.data
    responseTime.value = dayjs().format('YYYY-MM-DD HH:mm:ss')

    refreshGunTimer.value = setTimeout(() => {
      refreshConnectorList()
    }, loadingCountdown.value)
  } catch (e) {
    console.error(e)
  }
}

// ... 其他代码 ...

onUnmounted(() => {
  clearTimeout(refreshGunTimer.value)
})

关键设计点:

  1. 5秒间隔:这个时间间隔是经过实践验证的。太短会增加服务器压力,太长会影响用户体验。
  2. 错误处理:即使某次请求失败,也不会影响后续的轮询,系统会继续尝试。
  3. 内存管理:在组件卸载时会清理定时器,避免内存泄漏。

二、卡片式布局:设备状态的合理展示

设计理念

监控界面最重要的就是信息清晰易读:关键信息明确,详细数据可查。我们采用卡片式设计,每个充电桩一张卡片,每个充电枪一个状态点。

这种设计有几个好处:

信息层次清晰:充电桩→枪,层级分明
状态一目了然:通过颜色,快速识别充电状态
操作便捷:点击枪即可查看详情

实现代码解析

<view v-if="stationId" class="p-2 flex flex-wrap gap-2">
  <view v-for="e in equipmentList" :key="e.equipmentId" class="pile-card">
    <view class="pile-title">{{ e.equipmentName || e.equipmentId }}</view>
    <view class="gun-grid">
      <view
        v-for="(connector, index) in e.connectorList"
        :key="index"
        class="gun-item"
        @click="gunCard(connector, e)"
      >
        <view class="status-indicator">
          <view class="status-dot" :class="['status-' + connector.connectorStatus]">
            <text v-if="connector.connectorStatus == 3">{{ connector.soc * 100 }}</text>
          </view>
        </view>
        <view class="gun-name">
          {{ connector.connectorName || connector.connectorId.slice(-2) }}
        </view>
      </view>
    </view>
  </view>
</view>

技术要点:

  1. 条件渲染:只有选择了站点才显示设备列表,避免不必要的渲染。
  2. 动态样式:通过:class绑定状态类,实现颜色动态变化。
  3. 事件处理:点击枪位触发详情展示,交互自然。

状态颜色系统

状态颜色采用类似信号灯的颜色,减少认知成本:

.status-0 { background-color: #999 !important; }     // 离线
.status-1 { background-color: #07c160 !important; }  // 空闲
.status-2 { background-color: #239ad8 !important; }  // 插枪
.status-3 { background-color: #0066ff !important; }  // 充电中
.status-4 { background-color: #ff9900 !important; }  // 已锁定
.status-255 { background-color: #ff0000 !important; } // 故障

这种颜色编码让运维人员能够快速识别问题设备,提高工作效率。

三、浮动面板:优雅的交互设计

界面

设计思考

浮动面板是移动端一种典型的交互模式。它的优势在于:

不需要跳转:查看详情时,不需要跳转页面,可以快速切换节点;
操作自然:从底部滑出符合用户手势习惯;
信息分层:概览和详情分离,界面清爽。

技术实现

<wd-floating-panel
  v-if="selectedConnector.connectorId"
  v-model:height="height"
  :anchors="anchors"
  safeAreaInsetBottom
  custom-class="bg-page"
>
  <ConnectorDetail :connector="selectedConnector" />
</wd-floating-panel>

关键参数说明:

  • v-model:height:双向绑定面板高度,实现拖动调节
  • :anchors:预设停靠点,提供标准的交互体验
  • safeAreaInsetBottom:适配全面屏设备的安全区域

停靠点设置

onMounted(() => {
  windowHeight.value = uni.getSystemInfoSync().windowHeight
  anchors.value = [150, Math.round(0.4 * windowHeight.value), Math.round(1 * windowHeight.value)]
  height.value = anchors.value[0]
})

这里设置了三个停靠位置:

  1. 最小高度,可看到枪的当前信息;
  2. 40%高度,可显示出统计信息与最近的几条日志;
  3. 全屏显示完整信息,底部可再点击“更多日志”,查看完整设备日志进行问题排查。

这种设计可以让用户根据需要自由调节。

四、总结

这个实时监控系统的设计体现了几个重要的工程原则:

  1. 适用性:根据功能需要来选择技术实现方式,够用就好。
  2. 简化信息:通过信息灯颜色、浮动面板等设计,让复杂的信息变得直观易懂。
  3. 性能考虑:请求频率以及定时器清理,做好性能与内存的管理优化。

这种设计思路不仅适用于充电桩监控,对于任何需要实时状态监控的系统都有很好的参考价值。