基于Vue和cube-UI的养殖管理APP毕业设计实战教程
2026/9/15 10:47:21 网站建设 项目流程

简介:面向大学生毕业设计项目实训的Vue养殖类APP项目源码,基于Vue.js与cube-UI组件库开发,适合正在准备毕业设计或希望提升前端实战能力的学生。压缩包大小约5.98MB,主要内容为Vue项目源码,涵盖Vue基础、组件化设计、状态管理、路由配置、API接口调用、cube-UI界面搭建及移动端适配等关键知识点,可帮助读者完整理解移动端应用的开发流程。项目从零实现一个养殖类APP,利用cube-UI快速构建规范美观的界面,同时结合Vuex进行状态管理、Vue Router实现页面导航,并通过axios与后端交互,能有效锻炼从组件拆分到打包部署的全链路能力。已有645人学习下载,适合作为课程设计、毕业设计以及Vue入门后的进阶练习参考。

1. 养殖类APP毕业设计,用Vue+cube-UI做出来的系统为什么能打

毕设答辩时,做商城和订餐系统的同学都被评委追问“你的系统有什么实际意义”,而做养殖管理APP的那个反而轻松过关,因为他的选题直接落到了“猪场管理”这个具体业务上:录投喂记录、看生长曲线、刷环境监控。这类项目用Vue 2 + cube-UI来搭是最稳的组合,cube-UI是滴滴开源的移动端组件库,内置Form、Chart、Slide、Dialog这些业务组件,风格统一,不需要自己拼UI。本文就拿一个典型的养殖APP(猪舍管理)做例子,把工程搭建、数据录入、看板展示、视频监控、打包部署和答辩验证整条链路完整跑一遍,你照着做就能复现一个能演示、能答辩、能扩展的养殖类APP毕业设计项目。

2. 搭建Vue养殖APP工程骨架:环境配置、依赖安装与数据模型

2.1 vue-cli初始化项目并引入cube-UI,注意版本兼容

养殖APP的移动端页面密度高、输入项多,用原生CSS手写表单和弹窗会拖慢进度。cube-UI这类成熟的移动端UI库能直接提供表单校验、日期选择、图表和轮播,所以先别急着写业务代码,把工程和环境配好是第一优先级。

创建一个新的Vue 2项目并接入cube-UI,终端依次执行:

node -v # 确认Node版本,Vue 2 + cube-UI建议用14~16 npm install -g @vue/cli # 安装vue-cli脚手架 vue create livestock-app # 创建项目,选择Vue 2预设 cd livestock-app npm install cube-ui --save vue add cube-ui # 通过插件自动配置按需引入和主题变量

vue add cube-ui会把babel.config.js自动改写为:

module.exports = { presets: ['@vue/cli-plugin-babel/preset'], plugins: [ [ 'cube-ui', { postCompile: true, // 开启后编译,样式按需打包 theme: true // 允许覆盖主题变量(如主色) } ] ] }

这里的关键是postCompile: true:cube-UI的样式会跟随项目的Less变量编译,你可以把主色改成养殖场的绿色或者品牌色,而不是固定用默认蓝色。theme: true配合src/theme/theme.styl里的变量修改,比如$color-primary。如果你不想用插件,也可以直接在main.jsimport Cube from 'cube-ui'; Vue.use(Cube)做全量引入,但那样打包体积会大不少,毕设答辩时如果被问到性能优化,按需引入是更好的回答。

2.2 养殖域的数据表设计与路由结构

做养殖类APP,业务数据模型是最能体现“毕业设计工作量”的部分。以猪舍管理为例,核心实体有四张表,分别是猪舍、批次、投喂记录和健康监测记录。表结构如下:

表名关键字段说明
pest_househouse_id, area, capacity, temperature, humidity猪舍基础信息与实时环境数据
batchbatch_id, house_id, breed, count, start_date养殖批次,关联某猪舍
feedingfeed_id, batch_id, feed_type, amount, feed_time投喂记录,按批次归属
health_recordrecord_id, batch_id, weight, temperature, status抽检体重、体温与健康状态

前端路由按移动端管理APP的常规结构来划分:

  • /home:养殖看板,展示猪舍概览和异常告警
  • /house:猪舍列表,点击进入详情
  • /house/:id:猪舍详情页,包含视频监控和传感器数据
  • /record:投喂记录录入页
  • /alarm:异常告警中心

路由表可以统一写在src/router/index.js里,后续第4章会说明如何在页面间传递批次ID和设备编号。

2.3 用cube-UI的Form组件做投喂记录录入页

录入页是养殖APP的高频页面,饲养员每天要记录多栏猪的投喂情况。cube-UI的Form组件支持字段配置化,把表单项定义成schema对象,页面里只写少量模板代码即可:

<template> <cube-form :model="model" :schema="schema" @submit="submitHandler"></cube-form> </template> <script> export default { data() { const model = { batchId: '', feedType: '', amount: '', feedTime: new Date() } const schema = { fields: [ { type: 'select', modelKey: 'batchId', label: '批次编号', props: { options: [ { text: '2024-03批次', value: 'B001' }, { text: '2024-04批次', value: 'B002' } ] }, rules: { required: true, message: '请选择养殖批次' } }, { type: 'input', modelKey: 'feedType', label: '饲料类型', props: { placeholder: '如:育肥猪配合饲料' }, rules: { required: true, message: '请输入饲料类型' } }, { type: 'input', modelKey: 'amount', label: '投喂量(kg)', props: { type: 'number', placeholder: '请输入投喂量' }, rules: { required: true, message: '请输入投喂量' } } ] } return { model, schema } }, methods: { submitHandler(e) { e.preventDefault() // 通过API提交到后端,成功后弹出提示 this.$createToast({ type: 'correct', txt: '投喂记录已保存', time: 1500 }).show() } } } </script>

这个配置里modelKey对应数据对象中的字段名,rules声明校验规则,props透传给底层原生表单控件。cube-form自带校验拦截,提交时若字段为空会直接给出错误提示,不会触发submitHandler,这让表单开发省掉大量手写if判断。你可以在rule里配置pattern做自定义正则校验,比如投喂量只允许数字和小数点。

3. cube-UI核心组件在养殖看板中的实战:图表、轮播与告警

3.1 用cube-chart绘制体重生长曲线,数据来自批次记录

养殖APP里最有说服力的功能就是生长曲线:把一个批次在不同时间点的平均体重画成折线图,直接反映饲喂方案的效果。cube-UI内置了cube-chart组件,它基于ECharts封装,使用起来比直接操作ECharts简单,在页面中引入后配置typedata即可:

<template> <cube-chart type="line" :data="weightChartData" :options="chartOptions"> </cube-chart> </template> <script> export default { data() { return { weightChartData: { dimensions: ['date'], // 维度字段,作为横轴 measures: ['avgWeight'], // 度量字段,作为纵轴 source: [ { date: '04-01', avgWeight: 12.5 }, { date: '04-15', avgWeight: 21.3 }, { date: '05-01', avgWeight: 33.8 }, { date: '05-15', avgWeight: 47.2 } ] }, chartOptions: { xAxis: { type: 'category' }, yAxis: { name: '体重(kg)' } } } } } </script>

dimensions声明了横轴字段,measures声明纵轴字段,source就是接口返回的原始数据数组。后端只需返回这种二维表结构,前端不用做数据转换。要注意的是,cube-chart在数据更新时是整体重绘,所以如果后续需要追加新的称重数据,直接替换source数组触发响应式更新即可,不需要手动调用ECharts的setOption。为了满足毕设的“数据分析”要求,你还可以在chartOptions里加一个markLine,把目标体重设成参考线,饲养员一眼就能看出当前批次是否达标。

3.2 用cube-slide和cube-scroll搭出养殖场看板首页

看板首页是APP的门面,通常用轮播图放养殖场实景或宣传图,下方用可滚动列表展示猪舍状态卡片。cube-UI的cube-slide组件实现轮播非常轻量,数据数组里放图片地址和跳转配置:

<template> <cube-slide :data="slides" @change="onSlideChange"></cube-slide> </template> <script> export default { data() { return { slides: [ { url: require('../assets/slide1.jpg'), title: '标准化猪舍' }, { url: require('../assets/slide2.jpg'), title: '自动饲喂线' } ] } }, methods: { onSlideChange(index) { console.log('当前轮播索引:', index) } } } </script>

cube-slide支持autoPlayintervalloop属性配置,默认自动轮播并循环播放。猪舍状态列表用cube-scroll包裹,它提供移动端的下拉刷新和上拉加载能力:

<cube-scroll ref="scroll" :data="houseList" @pulling-down="refreshHouses" @pulling-up="loadMoreHouses"> <ul class="house-list"> <li v-for="item in houseList" :key="item.house_id" @click="goDetail(item.house_id)"> <span>{{ item.house_name }}</span> <span>温度 {{ item.temperature }}℃</span> <span>湿度 {{ item.humidity }}%</span> </li> </ul> </cube-scroll>

pulling-downpulling-up事件分别对应下拉刷新和上拉加载,接口请求完成后需要调用this.$refs.scroll.forceUpdate()告知滚动组件数据已更新。这是毕设演示时很容易被忽略的细节:不调用forceUpdate,滚动组件会认为数据没有变化,下拉刷新的loading状态会卡住。

3.3 用Dialog和Toast处理环境异常告警,配合vue路由跳转

养殖中最怕温湿度超标,轻则影响生长速度,重则造成牲畜死亡。APP里可以在看板首页定时轮询环境数据,一旦温度超过阈值就弹出cube-dialog告警,同时用cube-toast做轻提示:

<template> <cube-dialog :visible.sync="alertVisible" title="环境异常告警" content="1号猪舍温度已达到32.5℃,超过设定阈值30℃" @confirm="goHouseDetail"> </cube-dialog> </template> <script> export default { data() { return { alertVisible: false, currentAlertHouse: null } }, methods: { checkEnvironment() { // 模拟接口返回的环境数据 const data = { house_id: 'H001', temperature: 32.5, threshold: 30 } if (data.temperature > data.threshold) { this.currentAlertHouse = data.house_id this.alertVisible = true } }, goHouseDetail() { this.alertVisible = false this.$router.push(`/house/${this.currentAlertHouse}`) } } } </script>

cube-dialogvisible.sync做了双向绑定,关闭按钮和确认按钮都会自动同步状态。confirm事件里跳转路由,把用户带到出问题的猪舍详情页。轻提示场景用this.$createToast即可,比如“保存成功”“网络异常”,它会自动在屏幕上居中显示并在指定时间后消失。实际项目中我一般会把checkEnvironment放到mounted里执行一次,再用setInterval每30秒轮询一次,同时需要在beforeDestroy里清除定时器,避免离开页面后还继续弹告警。

4. 养殖监控与后台联调:vue播放m3u8、路由传参与axios封装

4.1 用video.js在APP里播放养殖场摄像头的m3u8监控流

养殖类APP通常要接入猪舍摄像头做实时监控,摄像头的RTSP流无法直接在浏览器播放,需要先通过流媒体服务(如ZLMediaKit或SRS)转成HLS协议输出m3u8地址。前端播放m3u8最常用的方案是video.js,安装时同时引入hls.js运行时会自动处理:

npm install video.js --save

页面中的播放器代码:

<template> <div> <video ref="videoPlayer" class="video-js vjs-default-skin"></video> </div> </template> <script> import videojs from 'video.js' import 'video.js/dist/video-js.css' export default { data() { return { player: null } }, mounted() { const liveUrl = 'http://your-server:8080/live/house01.m3u8' // 替换为实际m3u8地址 this.player = videojs(this.$refs.videoPlayer, { autoplay: true, controls: true, sources: [{ src: liveUrl, type: 'application/x-mpegURL' }] }) this.player.on('error', () => { this.$createToast({ type: 'warn', txt: '视频流加载失败,请检查网络', time: 2000 }).show() }) }, beforeDestroy() { if (this.player) { this.player.dispose() // 离开页面必须销毁播放器实例 } } } </script>

type: 'application/x-mpegURL'告诉video.js这是一个HLS流,video.js内部会调用hls.js完成分片拉流。答辩时如果评委问“为什么不用flv格式”,你可以回答:HLS基于HTTP协议,天然穿透防火墙,移动端兼容性好,但延迟一般在3到5秒;如果要做低延迟监控,可以改用FLV + flv.js方案,但需要后端配合。另外,dispose()一定不能漏,否则页面切换后播放器后台仍在拉流,既耗流量又导致内存泄漏。在4G弱网环境下,m3u8播放会频繁卡顿,建议在error事件里给用户明确的提示,而不是让画面一直黑屏。

4.2 vue路由参数传递批次ID与设备编号,跨组件同步状态

在养殖APP中,从看板页点击某个猪舍进入详情页,需要把猪舍ID传过去;从猪舍详情进入投喂记录页,需要带批次ID和设备编号。vue-router传递参数分两种方式,一种是路径参数,一种是query参数。典型的写法:

// 带路径参数跳转 this.$router.push({ path: `/house/${houseId}` }) // 带query参数跳转 this.$router.push({ path: '/record', query: { batchId: 'B001', deviceNo: 'CAM-01' } })

在目标组件里分别用this.$route.params.houseIdthis.$route.query.batchId读取。路径参数适合表达层级关系,比如“猪舍下的详情”;query参数适合表达附加条件,比如“从哪个设备跳过来的”。答辩时经常被问到一个问题:如果用query传对象,页面的URL会变得很长且无法序列化函数,所以项目中只传基础字段,复杂对象统一用Vuex或事件总线传递。另外要注意,$route$router是两个对象,$route是当前路由信息,$router是路由实例可以执行跳转,很多新手在这个地方容易写混。

4.3 axios拦截器封装与Spring Boot接口联调

养殖APP的数据最终要落到后端,毕设项目最常配的后端是Spring Boot,前端通过axios加载数据。把axios封装成统一实例,避免每个页面重复写baseURL和错误处理:

// src/api/http.js import axios from 'axios' const service = axios.create({ baseURL: process.env.VUE_APP_BASE_API, // 环境变量区分开发/生产 timeout: 10000 }) // 请求拦截器:统一加token service.interceptors.request.use( config => { const token = localStorage.getItem('token') if (token) { config.headers.Authorization = `Bearer ${token}` } return config }, error => Promise.reject(error) ) // 响应拦截器:统一处理错误码 service.interceptors.response.use( response => { const res = response.data if (res.code !== 0) { // 业务错误统一弹toast this.$createToast({ type: 'warn', txt: res.msg, time: 2000 }) return Promise.reject(new Error(res.msg)) } return res.data }, error => { if (error.response && error.response.status === 401) { // 登录过期跳转登录页 } return Promise.reject(error) } ) export default service

接口定义单独建一个src/api/livestock.js

import request from './http' export function getHouseList(params) { return request({ url: '/api/house/list', method: 'get', params }) } export function getGrowthCurve(batchId) { return request({ url: '/api/batch/growth', method: 'get', params: { batchId } }) } export function saveFeedingRecord(data) { return request({ url: '/api/feeding', method: 'post', data }) }

这样页面里调用getHouseList().then(data => { this.houseList = data })即可,不需要关心axios实例细节。开发调试时建议在Chrome上装Vue Devtools,配合vue.config.js里配置的代理转发,把/api前缀代理到本地Spring Boot端口,能避免跨域问题。如果毕设演示时用手机访问开发机,注意手机和电脑要在同一局域网,且Spring Boot启动时把server.address设为0.0.0.0,否则手机连不上接口。

5. 打包发布、布局异常修复与毕业设计答辩验证技巧

5.1 vue打包后布局异常的排查思路

很多同学开发环境一切正常,npm run build之后部署到服务器,发现页面变形、样式丢失或白屏。第一个要查的是资源路径:默认打包后资源是绝对路径/js/xxx.js,如果部署在子目录下就会404。在vue.config.js里设置:

module.exports = { publicPath: './' // 使用相对路径,适配子目录部署 }

第二个常见问题是cube-UI样式异常:如果你手动引入单个组件而不是走vue add cube-ui的按需编译,打包时可能样式未包含。解决方式是在main.js里显式import 'cube-ui/lib/cube.css',或者回到postCompile方案重新构建。第三个问题是移动端适配的viewport丢失,检查public/index.html里有没有:

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

如果没有viewport标签,移动端页面会按980px宽度渲染,整个布局全部错乱,这是打包后布局异常最常见的原因。如果还用了postcss-px-to-viewport做屏幕适配,打包时要排除node_modules目录,否则cube-UI的组件样式也会被转换,导致间距错乱。

5.2 cube-UI按需加载与性能瘦身

毕设答辩时性能优化是加分项。cube-UI提供了按需加载的babel插件方案,只打包用到的组件,能显著减少vendor.js体积。通过vue add cube-ui安装后,babel配置里已经自动加上了插件,使用时直接:

import { Toast, Dialog, Form } from 'cube-ui'

不需要Vue.use(Cube)全量注册,但每个组件要手动Vue.use(Toast)。除了组件按需,还可以用路由懒加载,让看板页和录入页分离打包,减小首屏加载量:

const Home = () => import('../views/Home.vue') const Record = () => import('../views/Record.vue')

一键构建后查看dist目录里各chunk的体积,如果某个chunk超过300KB,就得考虑是否把ECharts图表抽成懒加载。cube-UI的Chart组件体积较大,只在详情页用了生长曲线的场景下,把详情页改造成异步组件效果很明显。

5.3 答辩现场的演示与验证清单

毕业设计答辩现场最容易翻车,提前准备一份验证清单比较稳妥。第一项是弱网容错,用Chrome DevTools的网络面板设置Slow 3G,打开APP确认页面有加载状态且接口失败时有Toast提示,而不是白屏。第二项是缓存问题,多次登录和退出登录,确认token清理干净。第三项是不同设备适配,找一台iPhone和一台安卓手机,各测一遍录入页的表单对齐、图表缩放和m3u8播放,如果时间有限至少要在Android Chrome和iOS Safari两个浏览器上验证。第四项是打包产物验证,本地跑npm run build后,用http-server dist起服务,再在手机浏览器访问,确认打包后图片能加载、路由刷新不404——如果出现404,在vue.config.js里配置history路由的fallbacktrue。按照这套流程走完,答辩时的演示会顺利很多,评委问“你怎么保证系统稳定性”时,你也能用这些验证细节给出具体回答。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询