一、作品介绍
现在农业在互联网的不断发展下,给到了农业生产带来了很多新的思路,本次毕业设计作品是在团队+自己敬爱的指导周老师+学长+本人(当然还要感谢我的母校,培养我很简单,管饱就好,哈哈哈),在诸多的指导帮助下设计出来的,设计不易,供大家码农朋友提供参考学习,本人来自于普通的农村家庭。也希望自己的作品能够为以后的乡村建设提供一份美丽的答卷。
对于我们的传统农业生产方式,对于农田的参数检测、病虫害预警、远程管控等的实时效果能力达不到,对于现在的农作物而言,我们知道,农作物最重要的生长标准环境就是农地里的光照、温湿度、病虫害等等的因素,但是我们现在的传统生产方式是远远达不到要求的,对于监管来说,达不到时效性,就没有生产性可言,而且现在的乡村,存在着农田分配不均匀、人工管理耗时费力等等,诸多的因素下,设计了本农业智能田地系统,实现的是可以通过远程操作农田设备,比如小型机器人、喷洒车等等,实现远程操作。
二、开发环境
毕业设计之Vue+WebSocket+ECharts+服务器的智能农业管理系统
开发语言:Java
框架:Vue3
数据库:mysql 5.6
数据库工具:Navicat11
开发软件:visual studio code
前端框架:vue.js+ECharts-Element-ui
三、系统功能截图
1.登录界面
当用户需要登录的时候,用户可以通过使用账号密码操作登录到系统,登录需要进行验证,当用户登录账号密码不对的时候会有错误提示。
2.设备管理
该界面给到向用户展示届满,罗列了一系列农田设备得到的数据信息,向我们用户提供数据,“搜索”button,可以由系统向数据库信息那边进行数据校验对比,在数据库得到数据索引即可对数据进行排序罗列出来。
3.配置管理界面
集体向用户展示现场农田传回来的设备的配置信息,用户可以实时监管看农田设备的数据信息,看看哪里有没有损坏什么的,比如设备运行的日期、分、设备号等等。
4.历史数据
本设计通过使用百度地图插件等处理,配合远程摄像头等操作,向用户展示地图现场传回的地理位置数据信息,该部分模块还配有温湿度折线图,采用的是ECharts可视化图表进行现场温湿度(近一周)的功能展示。
5.数据分析
用户通过点击导航栏,进入“数据分析”界面,展现界面模块数据分析现场传回病虫害图片展示、病虫害占比率以饼图展示、文本框形式展示最新病虫害信息以及未来十五天预测信息等。
6. 权限管理
智能农业管理系统权限管理界面,用户点击左边导航栏,进入“权限管理”界面,用户可以对任意模块权限进行管理;还可以进行超级管理员、管路员、用户分配权限增删改查功能。
7.远程管理
四、部分关键代码
login.vue
<template> <div class="login_container"> <!-- 登录模块盒子 --> <div class="login-box"> <!-- 图片盒子 --> <div class="avatar_box"> <img src="../assets/1234.png" alt=""> <h3 class="text">云 智 舟</h3> </div> <!-- 登陆表单区域 --> <el-form label-width="0px" class="login_form" :model="loginForm" :rules="loginFormRules" ref="loginFormRef"> <!-- :model数据绑定对象,绑定到login from这个表单中,rules表单的验证规则对象 --> <!-- 用户登录 --> <el-form-item prop="username"> <el-input prefix-icon="el-icon-user-solid" v-model="loginForm.username" size="mini" ></el-input> <!-- v-model双向绑定,绑定到用户名 --> </el-form-item> <!-- 密码 --> <el-form-item prop="password"> <el-input prefix-icon="el-icon-lock" v-model="loginForm.password" type="password" size="mini" ></el-input> <!-- v-model双向绑定,绑定到用户登录密码,type="password可以使得密码隐藏"--> </el-form-item> <!-- 按钮区域 --> <el-form-item class="btns"> <el-button type="primary" @click="login" size="mini" >登录</el-button> <!-- 为登录绑定一个单击事件,名为login --> <el-button type="info" @click="resetLoginForm" size="mini">重置</el-button> <!-- click绑定单击事件,名为resetloginfrom --> </el-form-item> </el-form> </div> </div> </template> <script> import {Login} from '../network/login' export default { data () { return { // 登录表单的数据绑定对象 loginForm: { username: '', password: '' }, // 表单的验证规则对象 loginFormRules: { // 验证用户名是否合法 username: [ { required: true, message: '请输入登录名称', trigger: 'blur' }, { min: 3, max: 10, message: '长度在 3 到 10 个字符', trigger: 'blur' } // trigger便是失去焦点后出发这一次验证 ], // 验证密码是否合法 password: [ { required: true, message: '请输入登录密码', trigger: 'blur' }, { min: 3, max: 15, message: '长度在 3 到 15 个字符', trigger: 'blur' } ] } } }, methods: { // 点击重置按钮,重置表单 resetLoginForm () { this.$refs.loginFormRef.resetFields() }, login () { this.$refs.loginFormRef.validate( valid => { if (!valid) {return this.$message.error('用户名密码不正确')} Login(this.loginForm).then( res => { console.log(res); if (res.code !== 0) {return this.$message.error('登录失败')} this.$message.success('登陆成功') window.sessionStorage.setItem('token', res.token) this.$router.push('/home') }).catch( error => { console.log(error); }) // const { data: res } = await this..post('login', this.loginForm) // if (res.meta.status !== 200) return this.$message.error('登录失败') // this.$message.success('登陆成功') // // console.log(res) // window.sessionStorage.setItem('token', res.data.token) // this.$router.push('/home') // validate回调函数,完成登录表单前的预校验 // 将登陆成功以后的token,保存到客户端的sessionstorage中 // 项目中除了登陆之外的其他api接口,必须将token保存到客户端 // this.$router.push('/home)是通过编程式导航跳转到后台,路由地址为/home }) } } } </script>
home.vue
<template> <div class="login_container"> <!-- 登录模块盒子 --> <div class="login-box"> <!-- 图片盒子 --> <div class="avatar_box"> <img src="../assets/1234.png" alt=""> <h3 class="text">云 智 舟</h3> </div> <!-- 登陆表单区域 --> <el-form label-width="0px" class="login_form" :model="loginForm" :rules="loginFormRules" ref="loginFormRef"> <!-- :model数据绑定对象,绑定到login from这个表单中,rules表单的验证规则对象 --> <!-- 用户登录 --> <el-form-item prop="username"> <el-input prefix-icon="el-icon-user-solid" v-model="loginForm.username" size="mini" ></el-input> <!-- v-model双向绑定,绑定到用户名 --> </el-form-item> <!-- 密码 --> <el-form-item prop="password"> <el-input prefix-icon="el-icon-lock" v-model="loginForm.password" type="password" size="mini" ></el-input> <!-- v-model双向绑定,绑定到用户登录密码,type="password可以使得密码隐藏"--> </el-form-item> <!-- 按钮区域 --> <el-form-item class="btns"> <el-button type="primary" @click="login" size="mini" >登录</el-button> <!-- 为登录绑定一个单击事件,名为login --> <el-button type="info" @click="resetLoginForm" size="mini">重置</el-button> <!-- click绑定单击事件,名为resetloginfrom --> </el-form-item> </el-form> </div> </div> </template> <script> import {Login} from '../network/login' export default { data () { return { // 登录表单的数据绑定对象 loginForm: { username: '', password: '' }, // 表单的验证规则对象 loginFormRules: { // 验证用户名是否合法 username: [ { required: true, message: '请输入登录名称', trigger: 'blur' }, { min: 3, max: 10, message: '长度在 3 到 10 个字符', trigger: 'blur' } // trigger便是失去焦点后出发这一次验证 ], // 验证密码是否合法 password: [ { required: true, message: '请输入登录密码', trigger: 'blur' }, { min: 3, max: 15, message: '长度在 3 到 15 个字符', trigger: 'blur' } ] } } }, methods: { // 点击重置按钮,重置表单 resetLoginForm () { this.$refs.loginFormRef.resetFields() }, login () { this.$refs.loginFormRef.validate( valid => { if (!valid) {return this.$message.error('用户名密码不正确')} Login(this.loginForm).then( res => { console.log(res); if (res.code !== 0) {return this.$message.error('登录失败')} this.$message.success('登陆成功') window.sessionStorage.setItem('token', res.token) this.$router.push('/home') }).catch( error => { console.log(error); }) // const { data: res } = await this..post('login', this.loginForm) // if (res.meta.status !== 200) return this.$message.error('登录失败') // this.$message.success('登陆成功') // // console.log(res) // window.sessionStorage.setItem('token', res.data.token) // this.$router.push('/home') // validate回调函数,完成登录表单前的预校验 // 将登陆成功以后的token,保存到客户端的sessionstorage中 // 项目中除了登陆之外的其他api接口,必须将token保存到客户端 // this.$router.push('/home)是通过编程式导航跳转到后台,路由地址为/home }) } } } </script> <style lang="less" scoped> .login_container { background-color: #2b4b6b; height: 100%; } .login-box { width: 360px; height: 240px; background-color: #fff; border-radius: 3px; position: absolute; left: 50%; //距离左侧50% top: 50%; // 距离顶部505 transform: translate(-50%, -50%); //横轴上移动50%,纵移动50% } .avatar_box { height: 100px; width: 100px; border: 1px solid #eee; border-radius: 50%; padding: 10px; box-shadow: 0 0 10px #eee; position: absolute; left: 50%; top:-40%; transform: translate(-50%); background-color: rgb(32, 181, 201); img { width: 100%; height: 100%; border-radius: 50%; background-color: #eee; } } .login_form { position: absolute; bottom: 0; width: 100%; padding: 0 20px; box-sizing: border-box; } .btns { display: flex; justify-content: flex-end; } .text { text-align: center; margin-top: 10px; font-size: 20px; font-family: 宋体; } </style>
equip.vue
</template> <script> import {getTable,getdetail} from '../../network/equip' // import { Login } from '../../network/login' export default { data () { return { //搜索的id id:null, SeriesNumber:'', queryInfo: { formart: 'josn', pagenum: 1, pagesize: 3, }, total:7, input: '', input2: '', input3: '', coordinate: '', // 表格中的开关 // valueswitch: true, // 定义tablelist这个为一个数组 TableList: [], // 控制对话框的显示与隐藏 ToMoreVisible: false, value: '', value2: '', // checked: false, currentPage1: 5, currentPage2: 5, currentPage3: 5, currentPage4: 5, } }, // 创建一个表格数据 created () { this.getTableList() }, mounted () { }, methods: { // 获取表格数据 getTableList(){ getTable(this.queryInfo).then(res => { this.TableList = res.results console.log(res); }).catch(err => { console.log(err); }) }, // 搜索框获取到表格里面的数据 getssList(){ getdetail(this.SeriesNumber).then(res => { // this.getssList.push() // 方法为:先清空,后push出去this.tablelist = [],再this.tablelist.push(res) this.TableList = [] this.TableList.push(res) console.log(res) }).catch(err => { console.log(err); }) }, // 监听pagesize改变的事件 handleSizeChange (newSize) { // console.log(newSize) this.queryInfo.pagesize = newSize this.getTableList() }, // 监听页码值改变的事件 handleCurrentChange (newPage) { this.queryInfo.pagenum = newPage this.getTableList() console.log(newPage) }, // 点击跳转到配置管理的事件 todeploy () { this.$router.push('/deploy') }, // 点击跳转到远程管理界面 toremote () { this.$router.push('/remote') }, } } </script>
deloy.vue
<template> <div> <el-row class="rowstyle"> <el-col :span="3"><el-button type="primary" size="medium">参数获取</el-button></el-col> <el-col :span="3" ><el-button type="primary" size="medium">参数配置</el-button></el-col> </el-row> <!-- 设置一个卡片视图 --> <el-card style="width:100%;margin-top:20px"> <el-table :data="tableData" style="width: 100%"> <el-table-column prop="date" label="日期" width="180"></el-table-column> <el-table-column prop="name" label="姓名" width="180"></el-table-column> <el-table-column prop="address" label="地址"></el-table-column> <el-table-column width="180"> <template> <el-select v-model="value" placeholder="选择设备" class="select1"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option> </el-select> </template></el-table-column> <el-table-column width="180"> <el-button type="info" size="mini"><a href="javascript:location.reload()" style="text-decoration:none">刷新</a></el-button> </el-table-column> </el-table> </el-card> <!-- 表单 --> <el-form label-width="80px" style="margin-top:20px" :data="DataList"> <el-row :gutter="80"> <el-col :span="8"> <el-form-item label="序号:"> <el-select v-model="value" placeholder="请选择序号"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="名称:"> <el-select v-model="value1" placeholder="请选择设备号"> <el-option v-for="item in options1" :key="item.value1" :label="item.label1" :value="item.value1"> </el-option> </el-select> </el-form-item> </el-col> </div> </template> <script> import {getData} from '../../network/deploy' export default { data () { return { input: '', options: [{ }], value: '', value1: '', tableData: [{ name: '王小明', date: '2010010', address: '2021年5月28日' }] } }, created () { this.getDataList() }, methods: { // 获取表格数据 getDataList(){ getData().then(res => { this.DataList = res console.log(res); }).catch(err => { console.log(err); }) } } } </script>
history.vue
<template> <div> <el-row class="rowstyle"> <el-col :span="3"><el-button type="primary" size="medium">参数获取</el-button></el-col> <el-col :span="3" ><el-button type="primary" size="medium">参数配置</el-button></el-col> </el-row> <!-- 设置一个卡片视图 --> <el-card style="width:100%;margin-top:20px"> <el-table :data="tableData" style="width: 100%"> <el-table-column prop="date" label="日期" width="180"></el-table-column> <el-table-column prop="name" label="姓名" width="180"></el-table-column> <el-table-column prop="address" label="地址"></el-table-column> <el-table-column width="180"> <template> <el-select v-model="value" placeholder="选择设备" class="select1"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option> </el-select> </template></el-table-column> <el-table-column width="180"> <el-button type="info" size="mini"><a href="javascript:location.reload()" style="text-decoration:none">刷新</a></el-button> </el-table-column> </el-table> </el-card> <!-- 表单 --> <el-form label-width="80px" style="margin-top:20px" :data="DataList"> <el-row :gutter="80"> <el-col :span="8"> <el-form-item label="序号:"> <el-select v-model="value" placeholder="请选择序号"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select> </el-form-item> </el-col <el-col :span="8"> <el-form-item label="名称:"> <el-select v-model="value1" placeholder="请选择设备号"> <el-option v-for="item in options1" :key="item.value1" :label="item.label1" :value="item.value1"> </el-option> </el-select> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="类型:"> <el-select v-model="value" placeholder="请选择类型号"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select></el-form-item </el-col> </el-row> </el-form> <el-button class="save">保存</el-button><el-button class="recover">恢复默认</el-button> </div </template> <script> import {getData} from '../../network/deploy' export default { data () { return { input: '', address: '2021年5月28日' }] } }, created () { this.getDataList() }, methods: { // 获取表格数据 getDataList(){ getData().then(res => { this.DataList = res console.log(res); }).catch(err => { console.log(err); }) } } } </script>
power.vue
<template> <div> <el-table :data="tableData" style="width: 100%" height="350" border stripe> <el-table-column type="index"></el-table-column> <el-table-column prop="powername" label="权限名称" width="200"></el-table-column> <el-table-column prop="poweraddress" label="位置" width="120"></el-table-column> <el-table-column prop="level" label="权限等级" width="350"> <template> <el-tag closable @click="remove">超级管理员</el-tag> <el-tag type="success" closable @click="remove">管理员</el-tag> <el-tag type="warning" closable @click="remove">用户</el-tag> </template> </el-table-column> <el-table-column label="操作" width="400"> <template> <el-button type="primary" icon="el-icon-edit" size="mini">查看</el-button> <el-button type="danger" icon="el-icon-delete" size="mini">删除</el-button> <el-button type="warning" icon="el-icon-setting" size="mini" @click="showsetpowerdialog">分配添加</el-button> </template> </el-table-column> </el-table> <!-- 添加分配对话框 --> <el-dialog title="添加分配" :visible.sync="setpowerdialogVisible" width="50%"> <span>您所要添加分配的权限</span> <span slot="footer" class="dialog-footer"> <el-button @click="setpowerdialogVisible = false">取 消</el-button> <el-button type="primary" @click="setpowerdialogVisible = false">确 定</el-button> </span> </el-dialog> </div> </template> <script> export default { data () { return { tableData: [{ powername: '设备管理权限', poweraddress: 'equip', level: '' }, { powername: '配置管理权限', poweraddress: 'deploy', level: '' }, { powername: '历史数据权限', poweraddress: 'history', level: '' }, { powername: '数据分析权限', poweraddress: 'analysis', level: '' }, { powername: '权限管理权限', poweraddress: 'power', level: '' }, { powername: '远程管理权限', poweraddress: 'remote', level: '' }], // 控制对话框的显示与隐藏 setpowerdialogVisible: false } }, created () {}, methods: { async remove () { // 根据弹框删除 const confirmResult = await this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).catch(err => err) if (confirmResult !== 'comfirm') { return this.$message.info('取消删除') } console.log('确认了删除') }, // 展示分配添加对话框 showsetpowerdialog () { this.setpowerdialogVisible = true } } } </script> <style lang="less" scoped> </style>
remote.vue
<script> // 引入video样式 import 'video.js/dist/video-js.css' import 'vue-video-player/src/custom-theme.css' export default { data () { const self = this return { //喷杀控制显示隐藏 PS:true, // 摄像头部分的显示与隐藏 camera:false, // 视频流 playerOptions: { playbackRates: [0.7, 1.0, 1.5, 2.0], // 播放速度 autoplay: false, // 如果true,浏览器准备好时开始回放。 controls: true, // 控制条 preload: 'auto', // 视频预加载 muted: false, // 默认情况下将会消除任何音频。 loop: false, // 导致视频一结束就重新开始。 language: 'zh-CN', aspectRatio: '16:9', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3") fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。 sources: [{ type: 'video/mp4', src: ''// 你所放置的视频的地址,最好是放在服务器上 }], poster: 'http://192.168.1.2:8081/', // 你的封面地址(覆盖在视频上面的图片) width: document.documentElement.clientWidth, notSupportedMessage: '此视频暂无法播放,请稍后再试' // 允许覆盖Video.js无法播放媒体源时显示的默认信息。 }, input: '', // 地图部分代码 center: [121.59996, 31.197646], lng: 0, lat: 0, loaded: false, plugin: [ { enableHighAccuracy: true, timeout: 100, maximumAge: 0, convert: true, showButton: true, buttonPosition: 'RB', showMarker: true, showCircle: true, panToLocation: true, zoomToAccuracy: true, extensions: 'all', pName: 'Geolocation', events: { init (o) { // o 是高德地图定位插件实例 o.getCurrentPosition((status, result) => { console.log(result) if (result && result.position) { self.lng = result.position.lng self.lat = result.position.lat self.center = [self.lng, self.lat] self.loaded = true self.$nextTick() } }) } } } ] } }, methods:{ PsIsShow(){ this.PS = true }, cameraisshow(){ this.camera = !this.camera } } } </script>
总结:工程我会放在“资源”一栏,大家可以供参考,谢谢!