3. 看板前端技术栈选型与工程初始化
农业远程监控看板的本质是一个“长时间在线、持续刷新、多图表并存”的数据密集型单页应用。它需要周期性拉取大棚温湿度、土壤墒情、光照、CO₂浓度、设备开关状态等数据,并以卡片、曲线、仪表盘、告警列表等形式呈现。因此,前端技术栈的选型不能只看“流行度”,而要看它是否适合长期维护、是否便于类型约束、是否具备快速的构建与热更新能力。本节围绕 Vue 3 + TypeScript + Vite + ESLint 这一组合展开,完成从项目骨架到首页路由与布局框架的初始化。
一、选型判断:为什么是这套组合
框架层面,Vue 3 的组合式 API 让“数据采集—状态管理—视图渲染”这条链路更容易按业务域拆分。例如把温湿度轮询逻辑封装成 useSensorPolling(),把告警判定封装成 useAlarmRules(),在多个看板页面中复用,而不必依赖 mixin 或全局事件总线。React 同样可行,但本课程选择 Vue 3,主要因为其模板语法对图表容器、布局栅格的表达更直观,团队上手成本更低。
TypeScript 的价值在农业监控场景中尤为明显:传感器数据结构字段多、单位易混(温度 ℃ 与湿度 %RH、土壤含水率 % 与 EC 值 mS/cm),用接口把字段和单位固定下来,可以在编译期拦截“把湿度当温度渲染”这类错误。Vite 提供毫秒级冷启动与按需编译,配合 vite.config.ts 中的代理配置,可在开发阶段直接请求后端网关,规避跨域问题。ESLint 则统一代码风格并捕获未使用变量、隐式 any 等隐患。
二、工程初始化:从零到可运行骨架
使用 Vite 官方脚手架创建项目,选择 Vue + TypeScript 模板。命令执行后按提示输入项目名(示例为 agri-dashboard),并选择 TypeScript 与 ESLint 选项:
npm create vite@latest agri-dashboard -- --template vue-ts
cd agri-dashboard
npm install
npm install -D eslint @eslint/js eslint-plugin-vue typescript-eslint
npm install vue-router@4 axios echarts
安装完成后,先确认 package.json 中的脚本可用:dev 启动开发服务器,build 执行 vue-tsc --noEmit && vite build,lint 执行 ESLint 检查。建议把 build 中的类型检查保留,这样在打包阶段就能发现接口字段拼写错误,而不是等到运行时白屏。
三、环境变量与代理配置
农业现场的数据网关通常部署在局域网内(例如 192.168.1.50:8080),而开发机运行在 localhost:5173,直接请求会触发跨域。做法是在项目根目录建立环境变量文件,并在 Vite 配置中声明代理。
# .env.development
VITE_API_BASE=/api
VITE_POLL_INTERVAL=5000
# .env.production
VITE_API_BASE=https://agri.example.com/api
VITE_POLL_INTERVAL=10000
// vite.config.ts
import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd())
return {
plugins: [vue()],
server: {
port: 5173,
proxy: {
'/api': {
target: 'http://192.168.1.50:8080',
changeOrigin: true,
rewrite: (p) => p.replace(/^\/api/, '')
}
}
}
}
})
注意两点:其一,只有以 VITE_ 开头的变量才会暴露给客户端代码,切勿把密钥写入其中;其二,rewrite 是否保留 /api 前缀取决于后端路由约定,本例中后端接口本身不带 /api,因此需要去掉。配置完成后重启开发服务器,在浏览器访问 /api/sensors 应能看到网关返回的 JSON,而不是 404 或 CORS 报错,这就是代理生效的判断依据。
四、类型定义与首页路由布局
先为传感器数据建立类型契约,放在 src/types/sensor.ts。字段与单位必须写清楚,避免后续图表误用:
export interface SensorReading {
greenhouseId: string
temperature: number // 单位 ℃
humidity: number // 单位 %RH
soilMoisture: number // 单位 %
lightLux: number // 单位 lx
co2Ppm: number // 单位 ppm
timestamp: string // ISO 8601
}
接着配置路由。首页作为看板总览,采用“顶栏 + 左侧导航 + 内容区”的经典布局,把布局组件作为父路由,具体页面作为子路由渲染到 <router-view> 中:
// src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
import DashboardLayout from '@/layouts/DashboardLayout.vue'
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
component: DashboardLayout,
children: [
{ path: '', name: 'overview', component: () => import('@/views/Overview.vue') },
{ path: 'greenhouse/:id', name: 'greenhouse', component: () => import('@/views/GreenhouseDetail.vue') }
]
}
]
})
export default router
布局组件 DashboardLayout.vue 用 CSS Grid 划分区域:顶栏固定高度 56px,侧栏宽 200px,内容区自适应。顶栏放置系统名称、当前时间与连接状态指示灯;侧栏放置“总览、大棚列表、告警中心、历史曲线”导航项;内容区通过 <router-view> 承载页面。这样后续新增页面只需在子路由中注册,布局无需改动。
五、初始化验收清单
骨架搭好后,用下面几项快速判断工程是否真正可用,而不是“看起来能跑”:
- 执行
npm run dev后访问首页,能看到顶栏、侧栏与内容区三块布局,且无控制台报错。 - 在
Overview.vue中写一个临时请求,调用axios.get(import.meta.env.VITE_API_BASE + '/sensors'),Network 面板显示请求经代理转发并返回 200。 - 故意把
SensorReading中某字段名拼错,执行npm run build,vue-tsc应报类型错误,证明类型检查链路有效。 - 执行
npm run lint,确认 ESLint 能识别.vue与.ts文件并给出规则结果。
VITE_POLL_INTERVAL),开发环境用 5 秒便于观察数据变化,生产环境放宽到 10 秒以上,降低网关与现场设备的压力。农业传感器本身采样频率有限,过密的轮询并不会带来更多有效信息。至此,项目已具备可运行的路由骨架、类型契约、代理通道与代码质量工具链。后续的图表组件、告警逻辑与数据轮询,都将在这个骨架上按业务域逐步挂载,而不是在初始化阶段一次性堆满。