一、作品介绍
现在农业在互联网的不断发展下,给到了农业生产带来了很多新的思路,本次毕业设计作品是在团队+自己敬爱的指导周老师+学长+本人(当然还要感谢我的母校,培养我很简单,管饱就好,哈哈哈),在诸多的指导帮助下设计出来的,设计不易,供大家码农朋友提供参考学习,本人来自于普通的农村家庭。也希望自己的作品能够为以后的乡村建设提供一份美丽的答卷。
对于我们的传统农业生产方式,对于农田的参数检测、病虫害预警、远程管控等的实时效果能力达不到,对于现在的农作物而言,我们知道,农作物最重要的生长标准环境就是农地里的光照、温湿度、病虫害等等的因素,但是我们现在的传统生产方式是远远达不到要求的,对于监管来说,达不到时效性,就没有生产性可言,而且现在的乡村,存在着农田分配不均匀、人工管理耗时费力等等,诸多的因素下,设计了本农业智能田地系统,实现的是可以通过远程操作农田设备,比如小型机器人、喷洒车等等,实现远程操作。
二、开发环境
毕业设计之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>
总结:工程我会放在“资源”一栏,大家可以供参考,谢谢!
版权归原作者 丘比特惩罚陆 所有, 如有侵权,请联系我们删除。