在 Vue 3 项目中接入 Mitac 神达主板工具,本质上是把硬件管理能力嵌入到现代前端工程体系里。Mitac 作为服务器与工业主板供应商,其配套工具通常通过本地 HTTP 服务、WebSocket 或专属命令行程序暴露传感器数据、风扇转速、温度以及固件信息。这些接口往往没有完整的 TypeScript 类型声明,也不会自动适配浏览器的同源策略。如果只是在组件里用 fetch 拉一次数据,页面刷新或网络抖动后连接就会失效,更无法支撑多组件共享硬件状态。所以要把它当作一个正式的基础设施模块来设计,而不是临时脚本。

接下来从运行环境、数据访问层、状态管理以及构建部署几个层面,拆解一套可落地的工程化集成方案。
一、先梳理 Mitac 工具的运行依赖与接口约束
神达主板工具通常以系统服务形式安装在目标机器上,例如 Windows 下的 C:\Program Files\Mitac\MitacService.exe,或 Linux 环境中的 /opt/mitac/mitacd。这类服务默认监听 127.0.0.1 的某个端口,提供 REST 和 WebSocket 两类通道。REST 适合一次性查询设备信息,WebSocket 适合接收温度和风扇转速等高频推送。在 Vue 3 工程的开发阶段,前端跑在 localhost:5173,直接请求 127.0.0.1:8080 会遇到跨域限制,所以需要借助 Vite 的代理能力。
接口返回的数据结构往往来自底层 C++ 实现,字段名可能是缩写,如 temp1、fan_rpm、vcore。直接把这些字段暴露给组件会让模板难以维护,也容易在硬件型号变化时产生大量重复修改。工程化接入的第一步就是把接口契约固定下来,通过 TypeScript 接口定义统一的业务模型。这样后续无论服务端返回什么原始字段,都在数据访问层完成映射,组件只依赖清晰的类型。
还需要确认工具的认证方式。部分 Mitac 工具要求请求头携带 X-Mitac-Token,或者只允许本机回环地址访问。如果要在局域网其他设备上查看面板,必须配置服务端的监听地址和访问白名单,但这属于后端安全范畴,前端应保持令牌管理独立于业务组件。
// types/mitac.ts
export interface RawSensorData {
temp1: number;
fan_rpm: number[];
vcore: number;
board_id: string;
}
export interface MitacSensorReading {
temperature: number;
fanSpeed: number[];
coreVoltage: number;
boardId: string;
}
export function normalizeSensor(raw: RawSensorData): MitacSensorReading {
return {
temperature: raw.temp1,
fanSpeed: raw.fan_rpm ?? [],
coreVoltage: raw.vcore,
boardId: raw.board_id,
};
}
二、封装统一的数据访问层与连接生命周期
数据访问层是集成方案的核心。不要在每个组件里创建独立的 WebSocket 或 fetch 调用,那样会导致连接数不可控,组件卸载时也容易遗忘清理。可以封装一个 useMitacClient 组合式函数,负责建立连接、维护心跳、自动重连,并返回响应式的数据引用。这样组件只需要调用 useMitacClient 并解构数据即可。
连接管理需要特别注意浏览器标签页切换。当页面不可见时,高频推送仍然在消耗资源,可以根据 visibilitychange 事件暂停或恢复 WebSocket 连接。心跳方面,如果服务端超过 15 秒没有下发任何帧,客户端应主动发送 ping 帧;若连续三次未收到 pong,则触发重连。重连延迟采用指数退避,避免服务端刚重启时被大量连接冲击。
// composables/useMitacClient.ts
import { ref, onMounted, onBeforeUnmount } from 'vue';
export function useMitacClient(url: string) {
const temperature = ref(0);
const fanSpeed = ref<number[]>([]);
const connected = ref(false);
let socket: WebSocket | null = null;
let retryDelay = 1000;
let heartbeatTimer: number | undefined;
function connect() {
socket = new WebSocket(url);
socket.onopen = () => {
connected.value = true;
retryDelay = 1000;
startHeartbeat();
};
socket.onmessage = (event) => {
const raw = JSON.parse(event.data);
temperature.value = raw.temp1;
fanSpeed.value = raw.fan_rpm ?? [];
};
socket.onclose = () => {
connected.value = false;
clearInterval(heartbeatTimer);
setTimeout(connect, retryDelay);
retryDelay = Math.min(retryDelay * 2, 10000);
};
}
function startHeartbeat() {
clearInterval(heartbeatTimer);
heartbeatTimer = window.setInterval(() => {
if (socket?.readyState === WebSocket.OPEN) {
socket.send(JSON.stringify({ type: 'ping' }));
}
}, 15000);
}
onMounted(connect);
onBeforeUnmount(() => {
clearInterval(heartbeatTimer);
socket?.close();
});
return { temperature, fanSpeed, connected };
}
数据访问层还应该暴露 reconnect 方法和状态,方便用户手动恢复连接。对 REST 查询可以设计一个带缓存和超时的 request 函数,避免重复请求。比如多个组件同时需要主板信息时,用同一份 Promise 缓存,减少对 Mitac 服务的压力。
三、用 Pinia 驱动监控面板组件
当数据访问层稳定后,下一步是把硬件状态放进全局 store。Pinia 的轻量特性很适合这类中等复杂度的实时数据。store 中维护 temperature、fanSpeed、connected 等状态,并在初始化时调用 useMitacClient 建立连接。组件只负责渲染,不直接触碰 WebSocket 细节。这样做的好处是,多个页面或面板共享同一份连接,切换路由时也不会断开。
// stores/mitac.ts
import { defineStore } from 'pinia';
import { useMitacClient } from '@/composables/useMitacClient';
export const useMitacStore = defineStore('mitac', () => {
const { temperature, fanSpeed, connected } = useMitacClient('ws://127.0.0.1:8080/ws');
return { temperature, fanSpeed, connected };
});
监控面板组件可以使用 <template> 中的插值直接展示数据。为了提升可读性,温度和电压应做单位换算或保留小数位,风扇转速用数组渲染。遇到数据短暂缺失时,用占位符而不是整块消失,避免视觉跳动。也可以在组件内使用 computed 对风扇转速求平均值,给用户一个直观的健康度指标。
组件示例:
<template>
<div class="mitac-panel">
<div class="status">
<span>连接状态:{{ connected ? '已连接' : '重连中' }}</span>
</div>
<div class="sensor">
<p>核心温度:{{ temperature.toFixed(1) }} °C</p>
<p>核心电压:{{ coreVoltage.toFixed(3) }} V</p>
<p>风扇转速:{{ fanSpeed.join(', ') }} RPM</p>
</div>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { useMitacStore } from '@/stores/mitac';
const store = useMitacStore();
const coreVoltage = computed(() => store.coreVoltage ?? 0);
</script>
如果接口长时间不可用,组件应当显示一个明确的错误状态并给出重试按钮。把连接状态暴露给 UI 层后,用户能够理解并不是前端卡死,而是硬件服务未响应。对于多语言或部署在内网不同位置的项目,面板文案可以抽离到 i18n 模块中。
四、构建代理、错误降级与部署细节
开发环境跨域问题用 Vite 代理可以快速解决。在 vite.config.ts 中把 /mitac-api 前缀转发到本机 Mitac 服务,同时把 WebSocket 的 /mitac-ws 也代理过去。生产环境如果前端与 Mitac 服务部署在同一台机器上,可以使用相对路径,让反向代理统一处理;如果分离部署,则需要配置 CORS 或网关。
// vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()],
server: {
proxy: {
'/mitac-api': {
target: 'http://127.0.0.1:8080',
changeOrigin: true,
},
'/mitac-ws': {
target: 'ws://127.0.0.1:8080',
ws: true,
},
},
},
});
错误降级是工程化中容易被忽略的一环。可以建立错误级别:warning 级别仅提示部分传感器数据缺失,error 级别表示连接完全断开。针对两种级别设计不同的 UI 反馈,而不是一律弹窗。日志模块可以记录最近 20 条原始数据样本,在排查硬件兼容性问题时非常有用,但要注意敏感信息脱敏。
部署到神达主板所在的工控机或服务器时,前端静态资源一般由 Nginx 托管。需要确保 Nginx 配置中 WebSocket 升级头正确转发,否则连接会静默失败。Windows 环境下如果用 IIS,还要处理 WebSocket 协议模块的安装。路径方面,如果前端资源放在 C:\inetpub\wwwroot\mitac-panel,务必检查目录权限,避免 IIS 无法读取静态文件。
最后,把整套集成方案沉淀为可复用的 npm 包或内部模板,可以减少下一个项目的重复配置。将类型定义、数据访问层、Pinia store 和 UI 组件按照职责拆分,每个模块单独测试。这样即使后续更换主板型号或升级 Mitac 工具版本,也只需要调整数据映射层,组件和 store 保持不变。