飞道的博客

【物联网小程序】零基础用uniapp快速开发实现MQTT设备中心附后台接口

329人阅读  评论(0)

效果

工具:HbuilderX uniapp版本+微信开发者工具
项目需求:实现MQTT设备的uniapp前台显示(后台用springboot开发)
代码地址:
后台接口地址:http://121.36.196.247:8082/swagger-ui.html
演示代码:http://121.36.196.247:8083/h5/#/



后台接口地址:http://121.36.196.247:8082/swagger-ui.html

主要代码

api.js

const BASE_URL = 'http://121.36.196.247:8082'
export const myRequest = (options) => {
	return new Promise((resolve, reject) => {
		uni.request({
			url: BASE_URL + options.url,
			method: options.method || 'GET',
			data: options.data || {},
			success: (res) => {
				resolve(res)
				if (res.statusCode == 200) {
					if (res.data.state != 0) {
						uni.showToast({
							title: '访问异常!请联系管理员'
						})
					} 
				} else {
					return uni.showToast({
						title: '网络正在繁忙。。。'
					})
				}

			},
			fail: (err) => {
				uni.showToast({
					title: '请求接口失败'
				})
				reject(err)
			}
		})
	})
}

data.vue

<template>
	<view>
		<view class="content1"><text>设备Id:{
  {pointId}}</text></view>

		<view class="search-data-time">
			<view class=".search-data-time-right"><text>{
  {time}}</text></view>
		</view>
		<view class="index">
			<view class="new_box" style="margin-top: 20upx;">
				<view class="bbox">
					<view class="list-box">
						<view class="list-ed">

							<view class="list-left">

								<view class="list-name">
									增碳剂
								</view>

							</view>
							<view class="list-right">
								<text class="list-p2">{
  {dataList.smp_ID}}</text>
							</view>
						</view>
					</view>

				</view>
			</view>
			<view class="new_box" style="margin-top: 20upx;">
				<view class="bbox">
					<view class="list-box">
						<view class="list-ed">

							<view class="list-left">

								<view class="list-name">
									金属添加剂
								</view>

							</view>
							<view class="list-right">
								<text class="list-p2">{
  {dataList.smp_NAME}}</text>
							</view>
						</view>
					</view>

				</view>
			</view>
			<view class="new_box" style="margin-top: 20upx;">
				<view class="bbox">
					<view class="list-box">
						<view class="list-ed">

							<view class="list-left">

								<view class="list-name">样品称重
								</view>

							</view>
							<view class="list-right">
								<text class="list-p2">{
  {dataList.smp_WT}}</text>
							</view>
						</view>
					</view>

				</view>
			</view>
			<view class="new_box" style="margin-top: 20upx;">
				<view class="bbox">
					<view class="list-box">
						<view class="list-ed">

							<view class="list-left">

								<view class="list-name">样品碳含量
								</view>

							</view>
							<view class="list-right">
								<text class="list-p2">{
  {dataList.c_RES}}(%)</text>
							</view>
						</view>
					</view>

				</view>
			</view>
			<view class="new_box" style="margin-top: 20upx;">
				<view class="bbox">
					<view class="list-box">
						<view class="list-ed">

							<view class="list-left">

								<view class="list-name">样品硫含量
								</view>

							</view>
							<view class="list-right">
								<text class="list-p2">{
  {dataList.s_RES}}(%)</text>
							</view>
						</view>
					</view>

				</view>
			</view>
			<view class="new_box" style="margin-top: 20upx;">
				<view class="bbox">
					<view class="list-box">
						<view class="list-ed">

							<view class="list-left">

								<view class="list-name">气室压力
								</view>

							</view>
							<view class="list-right">
								<text class="list-p2">{
  {dataList.ch_PRESS}}(kpa)</text>
							</view>
						</view>
					</view>

				</view>
			</view>

		</view>

	</view>
</template>

<script>
	export default {
		components: {},
		data() {
			return {
				// pointName: "",
				pointId: '', //默认站点数据
				time: "", //时间
				dataList: [], //实时数据对象,
			}
		},
		methods: {

			async getPoints() {
				await this.$myRuquest({
					url: '/api/wxdata/selectRedisRtd?id=' + this.pointId
				}).then(res => {

					console.log(res)
					var strtime = res.data.data.dataTime
					var nian = strtime.slice(0, 4);
					var yue = strtime.slice(4, 6);
					var ri = strtime.slice(6, 8);
					var shi = strtime.slice(8, 10);
					var fen = strtime.slice(10, 12);
					var miao = strtime.slice(12, 14);
					this.time = nian + "-" + yue + "-" + ri + " " + shi + ":" + fen + ":" + miao;
					this.dataList = res.data.data
					console.log("实时数据查询成功")
				})


			}

		},
		onLoad(options) {
			this.pointId = options.pointId; //传过来的参数
			console.log("跳转过来了:::::::" + this.pointId);
			this.getPoints();
		}




	}
</script>

<style>
	.content1 {
		height: 60upx;
		background-color: #007AFF;

	}

	.content1 text {
		color: #F8F8F8;
		font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
		margin-left: 10upx;
	}

	/* 搜索框 */
	.search-ico,
	.search-ico-1 {
		width: 50upx;
		height: 50upx;
	}

	.search-ico {
		margin-left: 20upx;
	}

	.search-ico-1 {
		margin-right: 20upx;
	}

	.search-text {
		font-size: 14px;
		background-color: #FFFFFF;
		height: 60upx;
		width: 480upx;
	}

	.search-block {
		display: flex;
		flex-direction: row;
		/* padding-left: 60upx; */
		position: relative;

	}

	.search-ico-wapper {
		background-color: #FFFFFF;
		display: flex;
		flex-direction: column;
		padding: 0upx 0upx 0upx 0upx;
		width: 350upx;
	}

	.search-ico-wapper1 {
		background-color: #FFFFFF;
		display: flex;
		flex-direction: column;
		padding: 0upx 0upx 0upx 360upx;
		width: auto;
		float: right;
	}


	page {
		background-color: #eee;
	}

	.search-data-time {
		height: 40upx;

	}

	.search-data-time-right {
		width: 400upx;
		margin-left: 390upx;
	}

	.search-data-time-right text {
		color: #808080;
	}

	.list-box {
		display: flex;
		flex-direction: column;
		background-color: #fff;
		margin: 0upx 16upx 16upx 16upx;
		padding: 16upx;
		border-radius: 10upx;
		height: 60upx;
	}

	.list-ed {
		display: flex;
		flex-direction: row;
		justify-content: center;
		align-items: center;
	}

	.list-left {
		margin-left: 10upx;
		display: flex;
		flex-direction: column;
		width: 800upx;
		height: 60upx;
	}


	.list-right {
		display: flex;
		flex-direction: column;
		width: 510upx;
		height: 60upx;
	}


	.btn-point {
		width: 200rpx;
		height: 60rpx;
		display: flex;
		margin-top: 25rpx;
		margin-right: 10rpx;
		line-height: 50rpx;
		justify-content: center;
		border-radius: 25px;
		/* 这里可以改成渐变: background:linear-gradient(to right, #FFDE28,#FF3228) */
		background-color: #ff5500;
		font-size: 28rpx;
	}

	.noadsop {
		width: 120upx;
		height: 32upx;
	}


	.list-name {

		overflow: hidden;
		text-overflow: ellipsis;
		display: -webkit-box;
		-webkit-line-clamp: 2;
		margin-bottom: 15upx;
		margin-top: 10upx;
		font-size: 30upx;
	}

	.list-p2 {
		overflow: hidden;
		text-overflow: ellipsis;
		display: -webkit-box;
		-webkit-line-clamp: 1;
		margin-bottom: 15upx;
		margin-top: 10upx;
		margin-right: 0upx;
		color: #808080;

	}


	.list-da {
		display: flex;
		flex-wrap: nowrap;
		flex-direction: row;
		font-size: 26upx;
	}

	.list-da view {
		width: 50%;
	}

	.list-da view text {
		color: red;
	}
</style>

point.vue

<template>
	<view>
		<view class="content1"></view>
		<view class="search-block">
			<view class="search-ico-wapper">
				<!-- <image src="../../static/icon/search-active.png" class="search-ico" mode=""></image> -->
			</view>
			<input type="text" value="" focus v-model="Number" @input="onKeyNumberInput" placeholder="请输入设备编号"
			 class="search-text" maxlength="10" />
			<view class="search-ico-wapper1">
				<image src="../../static/icon/search-active.png" class="search-ico-1" mode=""></image>
			</view>
		</view>
		<view class="shadow">
		</view>

		<view class="index">
			<view class="new_box" style="margin-top: 20upx;" v-for="point in pointList" :key="point.id" @click="goDataDetail(point.id)">
				<view class="bbox">
					<view class="list-box">
						<view class="list-ed">

							<view class="list-left">

								<view class="list-name">{
  {point.number}}</view>
								<view class="list-da">
									<text class="list-p2">{
  {point.name}}</text>

								</view>
							</view>
							<view class="list-right">
								<button type="primary" class="btn-point" >点我查看</button>

							</view>
						</view>
					</view>

				</view>
			</view>
		</view>
		
		<view class="isOver" v-if="flag">----------我是有底线的----------</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				Cpage: 1, //当前页码
				flag:false,
				totalPages: 1, //总共页数
				Number: "",
				pointList: [] //企业站点集合
			}
		},
		methods: {
			//模糊搜索
			onKeyNumberInput: function(event) {
				this.Number = event.target.value
				this.pointList = []; //清空
				this.getPoints();//调用站点数据查询

			},

			//查询站点数据
			async getPoints() {
				//传递的参数封装成对象;

				let emsg = {
					"number": this.Number,
					"page": this.Cpage,
					"size":10,//默认10条
				}
				const res = await this.$myRuquest({
					url: '/api/wxapoint/pageByNumber',
					methods: 'post',
					data: emsg,
					dataType: 'json'
				})				
				if(res.data.data.records){
				    this.pointList =  [...this.pointList, ...res.data.data.records];
				    this.totalPages=res.data.data.total;
				}
				console.log(res.data.data)
				console.log("站点查询成功");
				
			},
			//跳转实时数据
			goDataDetail(item) {
				uni.navigateTo({
					url: '/pages/data/data?pointId=' + item,
					success(res) {
						console.log(res);
					},
					fail(err) {
						console.log(err);
					}
				});
			}
		},
		onLoad() {
			this.getPoints();
		},
		//上拉加载更多
		onReachBottom() {
			console.log("this.pointList.length" + this.pointList.length);
			if (this.Cpage * 10 > this.pointList.length) return this.flag = true;
			this.Cpage++;
			this.getPoints();
			// console.log("=触底了。。。。。==" + this.flag)
		},
		//下拉刷新
		onPullDownRefresh() {
			this.pointList = []
			this.Cpage = 1
			this.flag = false
			setTimeout(() => {
				this.getPoints(() => {
					uni.stopPullDownRefresh()
				})
			}, 1000)
		},
	}
</script>

<style>
	.content1 {
		height: 60upx;
		background-color: #007AFF;
	}
	.isOver{;
		width:a
	}


	/* 搜索框 */
	.search-ico,
	.search-ico-1 {
		width: 50upx;
		height: 50upx;
	}

	.search-text {
		font-size: 14px;
		background-color: #FFFFFF;
		height: 60upx;
		width: 480upx;
	}

	.search-block {
		display: flex;
		flex-direction: row;
		padding-left: 60upx;
		position: relative;
		top: -32upx;
	}

	.search-ico-wapper {
		background-color: #FFFFFF;
		display: flex;
		flex-direction: column;
		justify-content: center;
		padding: 0upx 0upx 0upx 40upx;
		border-bottom-left-radius: 18px;
		border-top-left-radius: 18px;
	}

	.search-ico-wapper1 {
		background-color: #FFFFFF;
		display: flex;
		flex-direction: column;
		justify-content: center;
		padding: 0upx 40upx 0upx 0upx;
		border-bottom-right-radius: 18px;
		border-top-right-radius: 18px;
	}

	.shadow {
		width: 638upx;
		height: auto;
		border-radius: 18px;
		-moz-box-shadow: 0 0 10px #e6e6e6;
		-webkit-box-shadow: 0 0 10px #e6e6e6;
		box-shadow: 0 0 10px #e6e6e6;
		position: relative;
		top: auto;
		left: 60upx;
	}

	page {
		background-color: #eee;
	}

	/* 已选择 */
	.selde {
		border: 1px solid red;
		background: red;
		color: #FFFFFF;
		border-radius: 20upx;
		display: flex;
		flex-direction: row;
		justify-content: center;
		align-items: center;
		font-size: 20upx;
		padding: 0 10upx;
	}

	.selde-q {
		width: 18upx;
		height: 18upx;
		border-radius: 50%;
		background: #FFFFFF;
		margin-left: 6upx;
	}

	.noselde-q {
		border: 1px solid #959595;
		width: 16upx;
		height: 16upx;
		border-radius: 50%;
		background: #FFFFFF;
		margin-left: 6upx;
	}

	.list-box {
		display: flex;
		flex-direction: column;
		background-color: #fff;
		margin: 0upx 16upx 16upx 16upx;
		padding: 16upx;
		border-radius: 10upx;
		height: 170upx;
	}

	.list-ed {
		display: flex;
		flex-direction: row;
		justify-content: center;
		align-items: center;
	}

	.list-left {
		margin-left: 10upx;
		display: flex;
		flex-direction: column;
		width: 800upx;
		height: auto;
	}


	.list-right {
		display: flex;
		flex-direction: column;
		width: 510upx;
		height: 180upx;
	}


	.btn-point {
		width: 200rpx;
		height: 60rpx;
		display: flex;
		margin-top: 25rpx;
		margin-right: 10rpx;
		line-height: 50rpx;
		justify-content: center;
		border-radius: 25px;
		/* 这里可以改成渐变: background:linear-gradient(to right, #FFDE28,#FF3228) */
		background-color: #ff5500;
		font-size: 28rpx;
	}

	.noadsop {
		width: 120upx;
		height: 32upx;
	}

	.list-head {
		display: flex;
		justify-content: flex-end;
		margin-bottom: 10upx;
	}

	.list-name {
		overflow: hidden;
		text-overflow: ellipsis;
		display: -webkit-box;
		-webkit-line-clamp: 2;
		margin-bottom: 15upx;
		margin-top: 5upx;
		font-size: 30upx;
	}

	.list-p2 {
		overflow: hidden;
		text-overflow: ellipsis;
		display: -webkit-box;
		-webkit-line-clamp: 2;
		margin-bottom: 15upx;
		margin-top: 5upx;
		color: #808080;

	}

	.list-right button {
		margin-top: 60upx;
	}

	.list-da {
		display: flex;
		flex-wrap: nowrap;
		flex-direction: row;
		font-size: 26upx;
	}

	.list-da view {
		width: 50%;
	}

	.list-da view text {
		color: red;
	}
</style>

思路

请参考我的博客
1.uniapp一周实战(一)
2.uniapp一周实战(二)
3.上线——H5打包

物联网系列

一、用netty做一个环保hj212协议即时通讯工具

二、零基础用uniapp快速开发实现MQTT设备中心附后台接口
三、MQTT服务器搭建实现物联网通讯
四、springboot + rabbitmq 做智能家居以及web显示未读消息


转载:https://blog.csdn.net/weixin_44106334/article/details/112812884
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场