mirror of
https://gitee.com/beecue/fastbee.git
synced 2025-12-17 16:36:03 +08:00
Merge remote-tracking branch 'origin/master'
# Conflicts: # springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java # springboot/wumei-iot/src/main/java/com/ruoyi/iot/mqtt/EmqxService.java # springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/config/TDengineConfig.java # springboot/wumei-iot/src/main/resources/mapper/tdengine/DatabaseMapper.xml # springboot/wumei-iot/src/main/resources/mapper/tdengine/TDDeviceLogMapper.xml
This commit is contained in:
@@ -24,7 +24,7 @@
|
|||||||
- EMQ管理: Mqtt客户端、监听器、消息主题、消息订阅、插件管理、规则引擎、资源
|
- EMQ管理: Mqtt客户端、监听器、消息主题、消息订阅、插件管理、规则引擎、资源
|
||||||
- 硬件 SDK: 支持WIFI和MQTT连接、物模型响应、实时监测、定时上报监测数据、AES加密、NTP时间等
|
- 硬件 SDK: 支持WIFI和MQTT连接、物模型响应、实时监测、定时上报监测数据、AES加密、NTP时间等
|
||||||
- 物模型管理: 属性(设备状态和监测数据),功能(执行特定任务),事件(设备主动上报给云端)
|
- 物模型管理: 属性(设备状态和监测数据),功能(执行特定任务),事件(设备主动上报给云端)
|
||||||
- 其他(开发中):第三方登录,设备分享、设备告警、场景联动(进度50%),智能音箱、多租户、APP界面自定义(进度40%),时序数据库、分布式集群部署、Granfa监控(进度30%),视频流处理、桌面端模拟器/监控、安卓端模拟器/监控(进度20%)
|
- 其他(开发中):第三方登录,设备分享、设备告警、场景联动(进度50%); 智能音箱、多租户、APP界面自定义(进度40%); 时序数据库、分布式集群部署、Granfa监控(进度30%); 视频流处理、桌面端模拟器/监控、安卓端模拟器/监控(进度20%)
|
||||||
|
|
||||||
|
|
||||||
### 四、技术栈
|
### 四、技术栈
|
||||||
@@ -74,7 +74,7 @@
|
|||||||
* [权限管理系统ruoyi-vue](https://gitee.com/y_project/RuoYi-Vue)
|
* [权限管理系统ruoyi-vue](https://gitee.com/y_project/RuoYi-Vue)
|
||||||
* [Mqtt消息服务器EMQX4.0](https://github.com/emqx/emqx)
|
* [Mqtt消息服务器EMQX4.0](https://github.com/emqx/emqx)
|
||||||
* [ESP8266 Core For Arduino](https://github.com/esp8266/Arduino)
|
* [ESP8266 Core For Arduino](https://github.com/esp8266/Arduino)
|
||||||
* [uCharts高性能跨平台图标库](https://www.ucharts.cn)
|
* [uCharts高性能跨平台图表库](https://www.ucharts.cn)
|
||||||
##### Docker快速安装
|
##### Docker快速安装
|
||||||
* Mysql中创建wumei-smart数据库,[导入Sql脚本](https://gitee.com/kerwincui/wumei-smart/tree/master/springboot/sql)
|
* Mysql中创建wumei-smart数据库,[导入Sql脚本](https://gitee.com/kerwincui/wumei-smart/tree/master/springboot/sql)
|
||||||
* 修改命令中的Mysql配置,并执行
|
* 修改命令中的Mysql配置,并执行
|
||||||
@@ -104,8 +104,8 @@ kerwincui/wumei-smart:1.1
|
|||||||
|
|
||||||
##### 项目贡献者
|
##### 项目贡献者
|
||||||
|
|
||||||
|[小驿物联](https://gitee.com/iot-xiaoyi) |[Guanshubiao](https://gitee.com/guanshubiao)|[CrazyDull](https://gitee.com/crazyDull) |[Kami0314](https://github.com/kami0314)|
|
|[小驿物联](https://gitee.com/iot-xiaoyi) |[Guanshubiao](https://gitee.com/guanshubiao)|[CrazyDull](https://gitee.com/crazyDull) |[Kami0314](https://github.com/kami0314)|[YBZX](https://github.com/YBZX)
|
||||||
|--|--|--|--|
|
|--|--|--|--|--|
|
||||||
|
|
||||||
| [SXH](https://gitee.com/sixiaohu) | [Redamancy_zxp](https://gitee.com/redamancy-zxp) | [LEE](https://gitee.com/yueming188) | [LemonTree](https://gitee.com/fishhunterplus) | [Tang](https://gitee.com/mexiaotang)
|
| [SXH](https://gitee.com/sixiaohu) | [Redamancy_zxp](https://gitee.com/redamancy-zxp) | [LEE](https://gitee.com/yueming188) | [LemonTree](https://gitee.com/fishhunterplus) | [Tang](https://gitee.com/mexiaotang)
|
||||||
|--|--|--|--|--|
|
|--|--|--|--|--|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#### 四、通过赞助、贡献代码、推广可以加入项目内部,里面包含移动端源码和更多相关教程,并且获得一年的免费更新。目前项目还在完善,教程暂无,赞助费暂定1500元。可以通过官网[http://wumei.live/](http://wumei.live/) 注册账号,联系作者加入项目内部。
|
#### 四、通过赞助、贡献代码、推广可以加入项目内部,里面包含移动端源码和更多相关教程,并且获得一年的免费更新。目前项目还在完善,教程暂无,赞助费暂定1500元。可以通过官网[http://wumei.live/](http://wumei.live/) 注册账号,联系作者加入项目内部。
|
||||||
|
|
||||||
##### 项目开发交流群:【946029159】,作者QQ: 【164770707】
|
##### 项目开发交流群:【946029159】,项目互助交流群:【1073236354】,作者QQ: 【164770707】
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
## 硬件端树莓派SDK说明
|
||||||
|
|
||||||
|
#### 一、运行环境
|
||||||
|
- Python 3.7.2 (其他python3的版本一般也可以)
|
||||||
|
- 开发板:树莓派4b(没有加入硬件相关代码,安装好python3环境,win下,linux下都能运行)
|
||||||
|
- 库 需要安装库
|
||||||
|
|
||||||
|
1. mqtt库
|
||||||
|
|
||||||
|
```
|
||||||
|
pip install paho-mqtt
|
||||||
|
```
|
||||||
|
|
||||||
|
2. ase加密库
|
||||||
|
|
||||||
|
```
|
||||||
|
# 前面两个卸载命令是为了防止一些安装环境问题
|
||||||
|
pip uninstall crypto
|
||||||
|
pip uninstall pycryptodome
|
||||||
|
pip install pycryptodome
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
3. 报错缺少xx库,命令
|
||||||
|
|
||||||
|
```
|
||||||
|
pip install xx
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#### 二、运行程序
|
||||||
|
|
||||||
|
```
|
||||||
|
python3 main_sdk.py
|
||||||
|
|
||||||
|
# 备注:程序运行依赖aes.py文件,保证该文件和main_sdk.py在同一目录
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### 三、开发参考资料:
|
||||||
|
|
||||||
|
- [Eclipse Paho MQTT Python Client 使用手册](https://www.cooooder.com/archives/20210303)
|
||||||
|
- 更多参考资料,下载目录中的文本文件查看
|
||||||
|
|
||||||
|
|||||||
210
sdk/RaspberryPi/aes.py
Normal file
210
sdk/RaspberryPi/aes.py
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
from Crypto.Cipher import AES
|
||||||
|
import base64
|
||||||
|
import binascii
|
||||||
|
|
||||||
|
|
||||||
|
# 数据类
|
||||||
|
class MData():
|
||||||
|
def __init__(self, data = b"",characterSet='utf-8'):
|
||||||
|
# data肯定为bytes
|
||||||
|
self.data = data
|
||||||
|
self.characterSet = characterSet
|
||||||
|
|
||||||
|
def saveData(self,FileName):
|
||||||
|
with open(FileName,'wb') as f:
|
||||||
|
f.write(self.data)
|
||||||
|
|
||||||
|
def fromString(self,data):
|
||||||
|
self.data = data.encode(self.characterSet)
|
||||||
|
return self.data
|
||||||
|
|
||||||
|
def fromBase64(self,data):
|
||||||
|
self.data = base64.b64decode(data.encode(self.characterSet))
|
||||||
|
return self.data
|
||||||
|
|
||||||
|
def fromHexStr(self,data):
|
||||||
|
self.data = binascii.a2b_hex(data)
|
||||||
|
return self.data
|
||||||
|
|
||||||
|
def toString(self):
|
||||||
|
return self.data.decode(self.characterSet)
|
||||||
|
|
||||||
|
def toBase64(self):
|
||||||
|
return base64.b64encode(self.data).decode() #decode()转成字符串形式,否则为字节型数据
|
||||||
|
|
||||||
|
def toHexStr(self):
|
||||||
|
return binascii.b2a_hex(self.data).decode()
|
||||||
|
|
||||||
|
def toBytes(self):
|
||||||
|
return self.data
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
try:
|
||||||
|
return self.toString()
|
||||||
|
except Exception:
|
||||||
|
return self.toBase64()
|
||||||
|
|
||||||
|
|
||||||
|
### 封装类
|
||||||
|
class AEScryptor():
|
||||||
|
def __init__(self,key,mode,iv = '',paddingMode= "NoPadding",characterSet ="utf-8"):
|
||||||
|
'''
|
||||||
|
构建一个AES对象
|
||||||
|
key: 秘钥,字节型数据
|
||||||
|
mode: 使用模式,只提供两种,AES.MODE_CBC, AES.MODE_ECB
|
||||||
|
iv: iv偏移量,字节型数据
|
||||||
|
paddingMode: 填充模式,默认为NoPadding, 可选NoPadding,ZeroPadding,PKCS5Padding,PKCS7Padding
|
||||||
|
characterSet: 字符集编码
|
||||||
|
'''
|
||||||
|
self.key = key
|
||||||
|
self.mode = mode
|
||||||
|
self.iv = iv
|
||||||
|
self.characterSet = characterSet
|
||||||
|
self.paddingMode = paddingMode
|
||||||
|
self.data = ""
|
||||||
|
|
||||||
|
def __ZeroPadding(self,data):
|
||||||
|
data += b'\x00'
|
||||||
|
while len(data) % 16 != 0:
|
||||||
|
data += b'\x00'
|
||||||
|
return data
|
||||||
|
|
||||||
|
def __StripZeroPadding(self,data):
|
||||||
|
data = data[:-1]
|
||||||
|
while len(data) % 16 != 0:
|
||||||
|
data = data.rstrip(b'\x00')
|
||||||
|
if data[-1] != b"\x00":
|
||||||
|
break
|
||||||
|
return data
|
||||||
|
|
||||||
|
def __PKCS5_7Padding(self,data):
|
||||||
|
needSize = 16-len(data) % 16
|
||||||
|
if needSize == 0:
|
||||||
|
needSize = 16
|
||||||
|
return data + needSize.to_bytes(1,'little')*needSize
|
||||||
|
|
||||||
|
def __StripPKCS5_7Padding(self,data):
|
||||||
|
paddingSize = data[-1]
|
||||||
|
return data.rstrip(paddingSize.to_bytes(1,'little'))
|
||||||
|
|
||||||
|
def __paddingData(self,data):
|
||||||
|
if self.paddingMode == "NoPadding":
|
||||||
|
if len(data) % 16 == 0:
|
||||||
|
return data
|
||||||
|
else:
|
||||||
|
return self.__ZeroPadding(data)
|
||||||
|
elif self.paddingMode == "ZeroPadding":
|
||||||
|
return self.__ZeroPadding(data)
|
||||||
|
elif self.paddingMode == "PKCS5Padding" or self.paddingMode == "PKCS7Padding":
|
||||||
|
return self.__PKCS5_7Padding(data)
|
||||||
|
else:
|
||||||
|
print("不支持Padding")
|
||||||
|
|
||||||
|
def __stripPaddingData(self,data):
|
||||||
|
if self.paddingMode == "NoPadding":
|
||||||
|
return self.__StripZeroPadding(data)
|
||||||
|
elif self.paddingMode == "ZeroPadding":
|
||||||
|
return self.__StripZeroPadding(data)
|
||||||
|
|
||||||
|
elif self.paddingMode == "PKCS5Padding" or self.paddingMode == "PKCS7Padding":
|
||||||
|
return self.__StripPKCS5_7Padding(data)
|
||||||
|
else:
|
||||||
|
print("不支持Padding")
|
||||||
|
|
||||||
|
def setCharacterSet(self,characterSet):
|
||||||
|
'''
|
||||||
|
设置字符集编码
|
||||||
|
characterSet: 字符集编码
|
||||||
|
'''
|
||||||
|
self.characterSet = characterSet
|
||||||
|
|
||||||
|
def setPaddingMode(self,mode):
|
||||||
|
'''
|
||||||
|
设置填充模式
|
||||||
|
mode: 可选NoPadding,ZeroPadding,PKCS5Padding,PKCS7Padding
|
||||||
|
'''
|
||||||
|
self.paddingMode = mode
|
||||||
|
|
||||||
|
def decryptFromBase64(self,entext):
|
||||||
|
'''
|
||||||
|
从base64编码字符串编码进行AES解密
|
||||||
|
entext: 数据类型str
|
||||||
|
'''
|
||||||
|
mData = MData(characterSet=self.characterSet)
|
||||||
|
self.data = mData.fromBase64(entext)
|
||||||
|
return self.__decrypt()
|
||||||
|
|
||||||
|
def decryptFromHexStr(self,entext):
|
||||||
|
'''
|
||||||
|
从hexstr编码字符串编码进行AES解密
|
||||||
|
entext: 数据类型str
|
||||||
|
'''
|
||||||
|
mData = MData(characterSet=self.characterSet)
|
||||||
|
self.data = mData.fromHexStr(entext)
|
||||||
|
return self.__decrypt()
|
||||||
|
|
||||||
|
def decryptFromString(self,entext):
|
||||||
|
'''
|
||||||
|
从字符串进行AES解密
|
||||||
|
entext: 数据类型str
|
||||||
|
'''
|
||||||
|
mData = MData(characterSet=self.characterSet)
|
||||||
|
self.data = mData.fromString(entext)
|
||||||
|
return self.__decrypt()
|
||||||
|
|
||||||
|
def decryptFromBytes(self,entext):
|
||||||
|
'''
|
||||||
|
从二进制进行AES解密
|
||||||
|
entext: 数据类型bytes
|
||||||
|
'''
|
||||||
|
self.data = entext
|
||||||
|
return self.__decrypt()
|
||||||
|
|
||||||
|
def encryptFromString(self,data):
|
||||||
|
'''
|
||||||
|
对字符串进行AES加密
|
||||||
|
data: 待加密字符串,数据类型为str
|
||||||
|
'''
|
||||||
|
self.data = data.encode(self.characterSet)
|
||||||
|
return self.__encrypt()
|
||||||
|
|
||||||
|
def __encrypt(self):
|
||||||
|
if self.mode == AES.MODE_CBC:
|
||||||
|
aes = AES.new(self.key,self.mode,self.iv)
|
||||||
|
elif self.mode == AES.MODE_ECB:
|
||||||
|
aes = AES.new(self.key,self.mode)
|
||||||
|
else:
|
||||||
|
print("不支持这种模式")
|
||||||
|
return
|
||||||
|
|
||||||
|
data = self.__paddingData(self.data)
|
||||||
|
enData = aes.encrypt(data)
|
||||||
|
return MData(enData)
|
||||||
|
|
||||||
|
def __decrypt(self):
|
||||||
|
if self.mode == AES.MODE_CBC:
|
||||||
|
aes = AES.new(self.key,self.mode,self.iv)
|
||||||
|
elif self.mode == AES.MODE_ECB:
|
||||||
|
aes = AES.new(self.key,self.mode)
|
||||||
|
else:
|
||||||
|
print("不支持这种模式")
|
||||||
|
return
|
||||||
|
data = aes.decrypt(self.data)
|
||||||
|
# mData = MData(self.__stripPaddingData(data),characterSet=self.characterSet)
|
||||||
|
# return mData()
|
||||||
|
return MData(self.__stripPaddingData(data),characterSet=self.characterSet)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
key = b"1234567812345678"
|
||||||
|
iv = b"0000000000000000"
|
||||||
|
aes = AEScryptor(key,AES.MODE_CBC,iv,paddingMode= "ZeroPadding",characterSet='utf-8')
|
||||||
|
|
||||||
|
data = "好好学习"
|
||||||
|
rData = aes.encryptFromString(data)
|
||||||
|
print("密文:",rData.toBase64())
|
||||||
|
rData = aes.decryptFromBase64(rData.toBase64())
|
||||||
|
print("明文:",rData)
|
||||||
|
# ————————————————
|
||||||
|
# 版权声明:本文为CSDN博主「Hello_wshuo」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
|
||||||
|
# 原文链接:https://blog.csdn.net/chouzhou9701/article/details/122019967
|
||||||
335
sdk/RaspberryPi/main_sdk.py
Normal file
335
sdk/RaspberryPi/main_sdk.py
Normal file
@@ -0,0 +1,335 @@
|
|||||||
|
# /***********************************************************
|
||||||
|
# * author: xiaoY [物美智能 wumei-smart]
|
||||||
|
# * create: 2022-05-10
|
||||||
|
# * email:qimint@outlook.com
|
||||||
|
# * source:https://github.com/kerwincui/wumei-smart
|
||||||
|
# * board:raspberry 4b
|
||||||
|
# ***********************************************************/
|
||||||
|
|
||||||
|
import time
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
from aes import AEScryptor,AES
|
||||||
|
import paho.mqtt.client as mqtt
|
||||||
|
import random
|
||||||
|
import threading #导入线程模块,用作定时器
|
||||||
|
|
||||||
|
#################################################################
|
||||||
|
# 需要连接好外部网络
|
||||||
|
#################################################################
|
||||||
|
|
||||||
|
# 作为python的AES的iv,应该为16位,字节型数据
|
||||||
|
wumei_iv = b"wumei-smart-open"
|
||||||
|
|
||||||
|
# NTP地址(用于获取时间,可选的修改为自己部署项目的地址)
|
||||||
|
ntpServer = "http://120.24.218.158:8080/iot/tool/ntp?deviceSendTime="
|
||||||
|
|
||||||
|
# 设备信息配置
|
||||||
|
deviceNum = "DW43CI6RM8GMG23H"
|
||||||
|
userId = "1"
|
||||||
|
productId = "4"
|
||||||
|
firmwareVersion = "1.0"
|
||||||
|
# Mqtt配置
|
||||||
|
mqttHost = "120.24.218.158"
|
||||||
|
|
||||||
|
mqttPort = 1883
|
||||||
|
mqttUserName = "wumei-smart"
|
||||||
|
mqttPwd = "P261I5G3RY3MCIGG"
|
||||||
|
# 作为python的AES的key,应该为16位,字节型数据
|
||||||
|
mqttSecret = b"K2IB784BM0O01GG6"
|
||||||
|
|
||||||
|
monitorCount =5 #发布监测数据的最大次数
|
||||||
|
# 使用esp8266单片机时,服务器传来的间隔单位为毫秒,本程序由于定时运行需要的是秒,将转化为秒,如需毫秒运行,自行更改程序
|
||||||
|
monitorInterval =5 # 发布监测数据的间隔,默认5秒
|
||||||
|
|
||||||
|
g_rc=-1 # 连接成功标志位
|
||||||
|
|
||||||
|
global t2 #全局变量,管理定时监测
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 订阅的主题
|
||||||
|
prefix = "/" + productId + "/" + deviceNum
|
||||||
|
sOtaTopic = prefix + "/ota/get"
|
||||||
|
sNtpTopic = prefix + "/ntp/get"
|
||||||
|
sPropertyTopic = prefix + "/property/get"
|
||||||
|
sFunctionTopic = prefix + "/function/get"
|
||||||
|
sPropertyOnline = prefix + "/property-online/get"
|
||||||
|
sFunctionOnline = prefix + "/function-online/get"
|
||||||
|
sMonitorTopic = prefix + "/monitor/get"
|
||||||
|
# 发布的主题
|
||||||
|
pInfoTopic = prefix + "/info/post"
|
||||||
|
pNtpTopic = prefix + "/ntp/post"
|
||||||
|
pPropertyTopic = prefix + "/property/post"
|
||||||
|
pFunctionTopic = prefix + "/function/post"
|
||||||
|
pMonitorTopic = prefix + "/monitor/post"
|
||||||
|
pEventTopic = prefix + "/event/post"
|
||||||
|
|
||||||
|
# 初始化
|
||||||
|
# 连接(客户端ID = 设备编号 & 产品ID)
|
||||||
|
clientId = deviceNum + "&" + productId
|
||||||
|
client=mqtt.Client(clientId)
|
||||||
|
|
||||||
|
#加密 (AES-CBC-128-pkcs5padding)
|
||||||
|
def encrypt(plain_data,wumei_key,wumei_iv):
|
||||||
|
aes=AEScryptor(wumei_key,AES.MODE_CBC,wumei_iv,paddingMode="PKCS5Padding",characterSet='utf-8')
|
||||||
|
rData=aes.encryptFromString(plain_data)
|
||||||
|
printMsg("密码(已加密):"+rData.toBase64())
|
||||||
|
return rData.toBase64()
|
||||||
|
|
||||||
|
#回调函数。当尝试与MQTT broker 建立连接时,触发该函数。
|
||||||
|
#client 是本次连接的客户端实例。
|
||||||
|
#userdata 是用户的信息,一般为空。但如果有需要,也可以通过 user_data_set 函数设置。
|
||||||
|
#flags 保存服务器响应标志的字典
|
||||||
|
#rc 是响应码。
|
||||||
|
# 0: 连接成功
|
||||||
|
# 1: 连接失败-不正确的协议版本
|
||||||
|
# 2: 连接失败-无效的客户端标识符
|
||||||
|
# 3: 连接失败-服务器不可用
|
||||||
|
# 4: 连接失败-错误的用户名或密码
|
||||||
|
# 5: 连接失败-未授权
|
||||||
|
# 6-255: 未定义.
|
||||||
|
#一般情况下,我们只需要关注rc响应码是否为0就可以了。
|
||||||
|
def on_connect(client,userdata,flags,rc):
|
||||||
|
if rc==0:
|
||||||
|
printMsg("连接成功")
|
||||||
|
# 放在on_connect下可以保证重连重新订阅
|
||||||
|
# 订阅(OTA、NTP、属性、功能、实时监测)
|
||||||
|
|
||||||
|
client.subscribe(sOtaTopic, 1)
|
||||||
|
client.subscribe(sNtpTopic, 1)
|
||||||
|
client.subscribe(sPropertyTopic, 1)
|
||||||
|
client.subscribe(sFunctionTopic, 1)
|
||||||
|
client.subscribe(sPropertyOnline, 1)
|
||||||
|
client.subscribe(sFunctionOnline, 1)
|
||||||
|
client.subscribe(sMonitorTopic, 1)
|
||||||
|
|
||||||
|
printMsg("订阅主题:" + sOtaTopic)
|
||||||
|
printMsg("订阅主题:" + sNtpTopic)
|
||||||
|
printMsg("订阅主题:" + sPropertyTopic)
|
||||||
|
printMsg("订阅主题:" + sFunctionTopic)
|
||||||
|
printMsg("订阅主题:" + sPropertyOnline)
|
||||||
|
printMsg("订阅主题:" + sFunctionOnline)
|
||||||
|
printMsg("订阅主题:" + sMonitorTopic)
|
||||||
|
# 发布设备信息
|
||||||
|
publishInfo()
|
||||||
|
global g_rc
|
||||||
|
g_rc=0
|
||||||
|
else:
|
||||||
|
printMsg("连接失败,rc="+str(rc))
|
||||||
|
printMsg("3秒后重连...")
|
||||||
|
time.sleep(3)
|
||||||
|
connectMqtt()
|
||||||
|
|
||||||
|
# 物模型-属性处理
|
||||||
|
def processProperty(payload):
|
||||||
|
data=json.loads(payload)
|
||||||
|
for item in data:
|
||||||
|
# 匹配云端定义的属性(不包含属性中的监测数据)
|
||||||
|
id = item["id"]
|
||||||
|
value=item["value"]
|
||||||
|
printMsg(str(id)+":"+str(value))
|
||||||
|
# 最后发布属性,服务端订阅存储(重要)
|
||||||
|
publishProperty(json.dumps(data))
|
||||||
|
|
||||||
|
# 物模型-功能处理
|
||||||
|
def processFunction(payload):
|
||||||
|
data=json.loads(payload)
|
||||||
|
for item in data:
|
||||||
|
# 匹配云端定义的功能
|
||||||
|
id = item["id"]
|
||||||
|
value=item["value"]
|
||||||
|
if(id=="switch"):
|
||||||
|
printMsg("开关 switch:"+ str(value))
|
||||||
|
elif(id=="gear"):
|
||||||
|
printMsg("档位 gear:"+ str(value))
|
||||||
|
elif(id=="light_color"):
|
||||||
|
printMsg("灯光颜色 light_color:"+ str(value))
|
||||||
|
elif(id=="message"):
|
||||||
|
printMsg("屏显消息 message:"+ str(value))
|
||||||
|
elif(id=="report_monitor"):
|
||||||
|
msg=randomPropertyData();
|
||||||
|
printMsg("订阅到上报监测数据指令,上报数据:")
|
||||||
|
printMsg(msg)
|
||||||
|
publishProperty(msg)
|
||||||
|
# 最后发布属性,服务端订阅存储(重要)
|
||||||
|
publishProperty(json.dumps(data))
|
||||||
|
|
||||||
|
# 回调函数,在客户端订阅的主题上接收到消息时调用,“message”变量是一个MQTT消息描述所有消息特征
|
||||||
|
def on_message(client,userdata,msg):
|
||||||
|
printMsg("接收数据:"+msg.topic+" "+str(msg.payload))
|
||||||
|
if(msg.topic==sOtaTopic):
|
||||||
|
printMsg("订阅到设备升级指令...")
|
||||||
|
elif(msg.topic==sNtpTopic):
|
||||||
|
printMsg("订阅到NTP时间...");
|
||||||
|
jsonData=json.loads(msg.payload)
|
||||||
|
deviceSendTime = jsonData["deviceSendTime"]
|
||||||
|
serverSendTime = jsonData["serverSendTime"]
|
||||||
|
serverRecvTime = jsonData["serverRecvTime"]
|
||||||
|
deviceRecvTime = round(time.time()*1000)
|
||||||
|
now = (serverSendTime + serverRecvTime + deviceRecvTime - deviceSendTime) / 2
|
||||||
|
printMsg("当前时间:"+str(round(now)))
|
||||||
|
elif(msg.topic==sPropertyTopic or msg.topic==sPropertyOnline):
|
||||||
|
printMsg("订阅到属性指令...")
|
||||||
|
processProperty(msg.payload)
|
||||||
|
elif(msg.topic==sFunctionTopic or msg.topic==sFunctionOnline):
|
||||||
|
printMsg("订阅到功能指令...")
|
||||||
|
processFunction(msg.payload)
|
||||||
|
elif(msg.topic==sMonitorTopic):
|
||||||
|
# python全局变量的使用
|
||||||
|
global t2
|
||||||
|
global monitorCount
|
||||||
|
global monitorInterval
|
||||||
|
printMsg("订阅到实时监测指令...")
|
||||||
|
jsonData=json.loads(msg.payload)
|
||||||
|
monitorCount = jsonData["count"]
|
||||||
|
monitorInterval = jsonData["interval"]/1000
|
||||||
|
t2.cancel()
|
||||||
|
t2=threading.Timer(monitorInterval,timing_publishMonitor)
|
||||||
|
t2.start()
|
||||||
|
|
||||||
|
# 1.发布设备信息
|
||||||
|
def publishInfo():
|
||||||
|
# rssi值 树莓派中暂时不处理wifi信号问题
|
||||||
|
# 信号强度(信号极好4格[-55— 0],信号好3格[-70— -55],信号一般2格[-85— -70],信号差1格[-100— -85])
|
||||||
|
# status值 (1-未激活,2-禁用,3-在线,4-离线)
|
||||||
|
doc={"rssi":1,"firmwareVersion":firmwareVersion,"status":3,"userId":userId}
|
||||||
|
# client.publish('raspberry/topic',payload=i,qos=0,retain=False)
|
||||||
|
jsonData=json.dumps(doc)
|
||||||
|
printMsg("发布设备信息:"+pInfoTopic+" "+jsonData)
|
||||||
|
client.publish(pInfoTopic,jsonData)
|
||||||
|
|
||||||
|
# 2.发布时钟同步信,用于获取当前时间(可选)
|
||||||
|
def publishNtp():
|
||||||
|
data={"deviceSendTime":round(time.time()*1000)}
|
||||||
|
jsonData=json.dumps(data)
|
||||||
|
printMsg("发布NTP信息"+jsonData)
|
||||||
|
client.publish(pNtpTopic,jsonData)
|
||||||
|
|
||||||
|
# 3.发布属性
|
||||||
|
# msg 接收格式json
|
||||||
|
def publishProperty(msg):
|
||||||
|
printMsg("发布属性:" + msg)
|
||||||
|
client.publish(pPropertyTopic, msg)
|
||||||
|
|
||||||
|
# 4.发布功能
|
||||||
|
def publishFunction( msg):
|
||||||
|
printMsg("发布功能:" + msg)
|
||||||
|
client.publish(pFunctionTopic, msg)
|
||||||
|
|
||||||
|
# 5.发布事件
|
||||||
|
def publishEvent():
|
||||||
|
objTmeperature={"id":"height_temperature","value":40,"remark":"温度过高警告"}
|
||||||
|
objException={"id":"exception","value":"异常消息,消息内容XXXXXXXX","remark":"设备发生错误"}
|
||||||
|
data=[objTmeperature,objException]
|
||||||
|
jsonData=json.dumps(data)
|
||||||
|
printMsg("发布事件:"+jsonData)
|
||||||
|
client.publish(pEventTopic,jsonData)
|
||||||
|
|
||||||
|
# 6.发布实时监测数据
|
||||||
|
def publishMonitor():
|
||||||
|
msg=randomPropertyData()
|
||||||
|
# 发布为实时监测数据,不会存储
|
||||||
|
printMsg("发布实时监测数据:"+msg)
|
||||||
|
client.publish(pMonitorTopic,msg)
|
||||||
|
|
||||||
|
# 随机生成监测值
|
||||||
|
def randomPropertyData():
|
||||||
|
# 匹配云端定义的监测数据,随机数代替监测结果
|
||||||
|
# random.randint(0,10) #生成数据包括0,10
|
||||||
|
# random.uniform(30,60)生成数据为浮点型
|
||||||
|
objTmeperature={"id":"temperature","value":str(round(random.uniform(10,30),2)),"remark":""}
|
||||||
|
objHumidity={"id":"humidity","value":str(round(random.uniform(30,60),2)),"remark":""}
|
||||||
|
objCo2={"id":"co2","value":str(random.randint(400,1000)),"remark":""}
|
||||||
|
objBrightness={"id":"brightness","value":str(random.randint(1000,10000)),"remark":""}
|
||||||
|
printMsg("随机生成监测数据值:")
|
||||||
|
data=[objTmeperature,objHumidity,objCo2,objBrightness]
|
||||||
|
print(json.dumps(data))
|
||||||
|
return json.dumps(data)
|
||||||
|
|
||||||
|
#连接mqtt
|
||||||
|
def connectMqtt():
|
||||||
|
printMsg("连接Mqtt服务器")
|
||||||
|
# 生成mqtt认证密码(密码 = mqtt密码 & 用户ID & 过期时间)
|
||||||
|
password = generationPwd()
|
||||||
|
encryptPassword=encrypt(password,mqttSecret,wumei_iv)
|
||||||
|
# 生成mqtt认证密码(密码 = mqtt密码 & 用户ID & 过期时间)
|
||||||
|
client.username_pw_set(mqttUserName,encryptPassword)
|
||||||
|
client.on_connect=on_connect
|
||||||
|
client.on_message=on_message
|
||||||
|
client.connect(mqttHost,mqttPort,10)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#打印提示信息
|
||||||
|
def printMsg(msg):
|
||||||
|
print("[{}] {}".format(time.strftime("%Y-%m-%d %H:%M:%S"),msg))
|
||||||
|
# 生成密码
|
||||||
|
def generationPwd():
|
||||||
|
try:
|
||||||
|
doc=json.loads(getTime())
|
||||||
|
except:
|
||||||
|
printMsg("Json解析失败")
|
||||||
|
exit()
|
||||||
|
deviceSendTime = doc["deviceSendTime"]
|
||||||
|
serverSendTime = doc["serverSendTime"]
|
||||||
|
serverRecvTime = doc["serverRecvTime"]
|
||||||
|
deviceRecvTime = round(time.time()*1000)
|
||||||
|
now = (serverSendTime + serverRecvTime + deviceRecvTime - deviceSendTime) / 2
|
||||||
|
expireTime = int(now + 1 * 60 * 60 * 1000)
|
||||||
|
password = mqttPwd + "&" + userId + "&" + str(expireTime)
|
||||||
|
printMsg("密码(未加密):" + password)
|
||||||
|
return password
|
||||||
|
# HTTP获取时间
|
||||||
|
def getTime():
|
||||||
|
try:
|
||||||
|
r=requests.get(ntpServer+str(round(time.time()*1000)))
|
||||||
|
if(r.status_code>0):
|
||||||
|
if(r.status_code==200 or r.status_code==301):
|
||||||
|
printMsg("获取时间成功,data:"+r.text)
|
||||||
|
return r.text
|
||||||
|
else:
|
||||||
|
printMsg("获取时间失败,error:"+r.status_code)
|
||||||
|
except:
|
||||||
|
printMsg("连接Http失败")
|
||||||
|
|
||||||
|
|
||||||
|
def timing_publishProperty():
|
||||||
|
printMsg("执行定时上报")
|
||||||
|
#发布事件
|
||||||
|
publishEvent()
|
||||||
|
#发布时钟同步
|
||||||
|
publishNtp()
|
||||||
|
# 发布属性(监测值)
|
||||||
|
msg=randomPropertyData()
|
||||||
|
publishProperty(msg)
|
||||||
|
t1=threading.Timer(60,timing_publishProperty)
|
||||||
|
t1.start()
|
||||||
|
def timing_publishMonitor():
|
||||||
|
global monitorCount
|
||||||
|
monitorCount=monitorCount-1
|
||||||
|
printMsg("执行监测")
|
||||||
|
publishMonitor()
|
||||||
|
if(monitorCount>0):
|
||||||
|
t2=threading.Timer(monitorInterval,timing_publishMonitor)
|
||||||
|
t2.start()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
connectMqtt()
|
||||||
|
client.loop_start()
|
||||||
|
printMsg("等待连接MQTT")
|
||||||
|
while(g_rc!=0):
|
||||||
|
print("-",end=" ")
|
||||||
|
time.sleep(1)
|
||||||
|
t1=threading.Timer(60,timing_publishProperty)
|
||||||
|
t1.setDaemon(True) #当主线程被关闭后,子线程也关闭
|
||||||
|
t1.start()
|
||||||
|
t2=threading.Timer(monitorInterval,timing_publishMonitor)
|
||||||
|
t2.setDaemon(True) #当主线程被关闭后,子线程也关闭
|
||||||
|
t2.start()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
time.sleep(10) #定时上报、检测上报都是线程执行,主线程可以做自己的任务
|
||||||
|
|
||||||
26
sdk/RaspberryPi/更多参考教程.txt
Normal file
26
sdk/RaspberryPi/更多参考教程.txt
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
Eclipse Paho MQTT Python Client 使用手册
|
||||||
|
https://www.cooooder.com/archives/20210303
|
||||||
|
|
||||||
|
Python 实现AES加密
|
||||||
|
https://zhuanlan.zhihu.com/p/261694311
|
||||||
|
|
||||||
|
python实现AES加密解密
|
||||||
|
https://blog.csdn.net/chouzhou9701/article/details/122019967
|
||||||
|
|
||||||
|
使用python time()方法
|
||||||
|
http://www.py.cn/jishu/jichu/20424.html
|
||||||
|
|
||||||
|
python 线程定时器Timer
|
||||||
|
https://zhuanlan.zhihu.com/p/91412537
|
||||||
|
|
||||||
|
浅谈Python的格式化输出
|
||||||
|
https://www.jb51.net/article/225609.htm
|
||||||
|
|
||||||
|
Python Request库入门
|
||||||
|
https://www.jianshu.com/p/d78982126318
|
||||||
|
|
||||||
|
Python JSON
|
||||||
|
https://www.runoob.com/python/python-json.html
|
||||||
|
|
||||||
|
Python random() 函数
|
||||||
|
https://www.runoob.com/python/func-number-random.html
|
||||||
@@ -1,21 +1,34 @@
|
|||||||
package com.ruoyi.framework.config;
|
package com.ruoyi.framework.config;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Arrays;
|
import javax.servlet.*;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
import com.alibaba.druid.pool.DruidDataSource;
|
||||||
|
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
|
||||||
|
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
|
||||||
|
import com.alibaba.druid.util.Utils;
|
||||||
|
import com.ruoyi.common.enums.DataSourceType;
|
||||||
|
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||||
|
import com.ruoyi.framework.config.properties.DruidProperties;
|
||||||
|
import com.ruoyi.framework.datasource.DynamicDataSource;
|
||||||
import org.apache.ibatis.io.VFS;
|
import org.apache.ibatis.io.VFS;
|
||||||
import org.apache.ibatis.session.SqlSessionFactory;
|
import org.apache.ibatis.session.SqlSessionFactory;
|
||||||
import org.mybatis.spring.SqlSessionFactoryBean;
|
import org.mybatis.spring.SqlSessionFactoryBean;
|
||||||
import org.mybatis.spring.SqlSessionTemplate;
|
import org.mybatis.spring.SqlSessionTemplate;
|
||||||
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
|
import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.boot.jdbc.DataSourceBuilder;
|
||||||
|
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Primary;
|
import org.springframework.context.annotation.Primary;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.core.io.DefaultResourceLoader;
|
import org.springframework.core.io.DefaultResourceLoader;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
@@ -34,8 +47,8 @@ import com.ruoyi.common.utils.StringUtils;
|
|||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
public class MyBatisConfig
|
@MapperScan(basePackages = {"com.ruoyi.iot.mapper", "com.ruoyi.system.mapper", "com.ruoyi.quartz.mapper", "com.ruoyi.generator.mapper"}, sqlSessionTemplateRef = "mysqlSqlSessionTemplate")
|
||||||
{
|
public class MyBatisConfig {
|
||||||
@Autowired
|
@Autowired
|
||||||
private Environment env;
|
private Environment env;
|
||||||
|
|
||||||
@@ -119,10 +132,11 @@ public class MyBatisConfig
|
|||||||
|
|
||||||
@Bean(name = "mysqlSessionFactory")
|
@Bean(name = "mysqlSessionFactory")
|
||||||
@Primary
|
@Primary
|
||||||
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception
|
public SqlSessionFactory sqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dataSource) throws Exception
|
||||||
{
|
{
|
||||||
String typeAliasesPackage = env.getProperty("mybatis.typeAliasesPackage");
|
String typeAliasesPackage = "com.ruoyi.**.domain";//env.getProperty("mybatis.typeAliasesPackage");
|
||||||
String mapperLocations = env.getProperty("mybatis.mapperLocations");
|
String mapperLocations = "classpath:mapper/iot/*Mapper.xml,classpath:mapper/system/*Mapper.xml,classpath:mapper/quartz/*Mapper.xml";
|
||||||
|
// String typeAliasesPackage = "com.ruoyi.**.domain";
|
||||||
String configLocation = env.getProperty("mybatis.configLocation");
|
String configLocation = env.getProperty("mybatis.configLocation");
|
||||||
typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage);
|
typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage);
|
||||||
VFS.addImplClass(SpringBootVFS.class);
|
VFS.addImplClass(SpringBootVFS.class);
|
||||||
@@ -146,4 +160,5 @@ public class MyBatisConfig
|
|||||||
public SqlSessionTemplate mysqlSqlSessionTemplate(@Qualifier("mysqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
|
public SqlSessionTemplate mysqlSqlSessionTemplate(@Qualifier("mysqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
|
||||||
return new SqlSessionTemplate(sqlSessionFactory);
|
return new SqlSessionTemplate(sqlSessionFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -138,13 +138,13 @@ public class ToolController extends BaseController {
|
|||||||
// 设备端
|
// 设备端
|
||||||
String[] clientInfo = clientid.split("&");
|
String[] clientInfo = clientid.split("&");
|
||||||
if (clientInfo.length != 2) {
|
if (clientInfo.length != 2) {
|
||||||
// 设备未加密认证
|
// 设备简单认证
|
||||||
String deviceNum = clientInfo[0];
|
String deviceNum = clientInfo[0];
|
||||||
Device device = deviceService.selectShortDeviceBySerialNumber(deviceNum);
|
Device device = deviceService.selectShortDeviceBySerialNumber(deviceNum);
|
||||||
if (device !=null && mqttConfig.getusername().equals(username) && mqttConfig.getpassword().equals(password)) {
|
if (device !=null && mqttConfig.getusername().equals(username) && mqttConfig.getpassword().equals(password)) {
|
||||||
System.out.println("-----------认证成功,clientId:" + clientid + "---------------");
|
System.out.println("-----------认证成功,clientId:" + clientid + "---------------");
|
||||||
ProductAuthorize authorize = new ProductAuthorize(null, device.getProductId(), device.getDeviceId(), device.getSerialNumber(), 1L, "admin");
|
// ProductAuthorize authorize = new ProductAuthorize(null, device.getProductId(), device.getDeviceId(), device.getSerialNumber(), 1L, "admin");
|
||||||
authorizeService.boundProductAuthorize(authorize);
|
// authorizeService.boundProductAuthorize(authorize);
|
||||||
return ResponseEntity.ok().body("ok");
|
return ResponseEntity.ok().body("ok");
|
||||||
}
|
}
|
||||||
return returnUnauthorized(clientid, username, password, "认证信息有误");
|
return returnUnauthorized(clientid, username, password, "认证信息有误");
|
||||||
@@ -178,16 +178,16 @@ public class ToolController extends BaseController {
|
|||||||
// 设备状态验证 (1-未激活,2-禁用,3-在线,4-离线)
|
// 设备状态验证 (1-未激活,2-禁用,3-在线,4-离线)
|
||||||
if (model.getDeviceId() != null && model.getDeviceId() != 0 && model.getStatus() != 2) {
|
if (model.getDeviceId() != null && model.getDeviceId() != 0 && model.getStatus() != 2) {
|
||||||
System.out.println("-----------认证成功,clientId:" + clientid + "---------------");
|
System.out.println("-----------认证成功,clientId:" + clientid + "---------------");
|
||||||
ProductAuthorize authorize = new ProductAuthorize(null, model.getProductId(), model.getDeviceId(), model.getSerialNumber(), 1L, "admin");
|
// ProductAuthorize authorize = new ProductAuthorize(null, model.getProductId(), model.getDeviceId(), model.getSerialNumber(), 1L, "admin");
|
||||||
authorizeService.boundProductAuthorize(authorize);
|
// authorizeService.boundProductAuthorize(authorize);
|
||||||
return ResponseEntity.ok().body("ok");
|
return ResponseEntity.ok().body("ok");
|
||||||
} else {
|
} else {
|
||||||
// 自动添加设备
|
// 自动添加设备
|
||||||
int result = deviceService.insertDeviceAuto(deviceNum, userId, productId);
|
int result = deviceService.insertDeviceAuto(deviceNum, userId, productId);
|
||||||
if (result == 1) {
|
if (result == 1) {
|
||||||
System.out.println("-----------认证成功,clientId:" + clientid + "---------------");
|
System.out.println("-----------认证成功,clientId:" + clientid + "---------------");
|
||||||
ProductAuthorize authorize = new ProductAuthorize(null, model.getProductId(), model.getDeviceId(), model.getSerialNumber(), 1L, "admin");
|
// ProductAuthorize authorize = new ProductAuthorize(null, model.getProductId(), model.getDeviceId(), model.getSerialNumber(), 1L, "admin");
|
||||||
authorizeService.boundProductAuthorize(authorize);
|
// authorizeService.boundProductAuthorize(authorize);
|
||||||
return ResponseEntity.ok().body("ok");
|
return ResponseEntity.ok().body("ok");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package com.ruoyi.iot.init;
|
||||||
|
|
||||||
|
|
||||||
|
//import com.ruoyi.mysql.config.TDengineConfig;
|
||||||
|
|
||||||
|
//import com.ruoyi.iot.tdengine.config.TDengineConfig;
|
||||||
|
import com.alibaba.druid.pool.DruidDataSource;
|
||||||
|
import com.ruoyi.iot.tdengine.config.TDengineConfig;
|
||||||
|
import com.ruoyi.iot.domain.DeviceLog;
|
||||||
|
import com.ruoyi.iot.mapper.DeviceMapper;
|
||||||
|
import com.ruoyi.iot.tdengine.mapper.TDDeviceLogMapper;
|
||||||
|
import org.mybatis.spring.SqlSessionTemplate;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.boot.ApplicationArguments;
|
||||||
|
import org.springframework.boot.ApplicationRunner;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类名: ApplicationStarted
|
||||||
|
* 描述: TODO
|
||||||
|
* 时间: 2022/5/18,0018 1:41
|
||||||
|
* 开发人: wxy
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class ApplicationStarted implements ApplicationRunner {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationStarted.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TDengineConfig dengineConfig;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TDDeviceLogMapper deviceLogMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeviceMapper deviceMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(ApplicationArguments args) {
|
||||||
|
deviceMapper.selectDeviceByDeviceId(0L);
|
||||||
|
System.out.println("初始化MySql链接成功");
|
||||||
|
initTDengine();
|
||||||
|
System.out.println("初始化TDengine链接成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Method
|
||||||
|
* @Description 开始初始化加载系统参数,创建数据库和超级表
|
||||||
|
* @Param null
|
||||||
|
* @return
|
||||||
|
* @date 2022/5/22,0022 14:27
|
||||||
|
* @author wxy
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void initTDengine() {
|
||||||
|
try {
|
||||||
|
String dbName = dengineConfig.getDbName();
|
||||||
|
int db = deviceLogMapper.createDB(dbName);
|
||||||
|
deviceLogMapper.createSTable(dbName);
|
||||||
|
|
||||||
|
System.out.println(db);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
System.out.println("ERROR");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.ruoyi.iot.log.service;
|
||||||
|
|
||||||
|
import com.ruoyi.iot.domain.DeviceLog;
|
||||||
|
|
||||||
|
import com.ruoyi.iot.model.MonitorModel;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @package iot.iot.log
|
||||||
|
* 类名: LogService
|
||||||
|
* 描述: 设备日志记录接口
|
||||||
|
* 时间: 2022/5/19,0019 18:04
|
||||||
|
* 开发人: admin
|
||||||
|
*/
|
||||||
|
public interface ILogService {
|
||||||
|
|
||||||
|
int saveDeviceLog(DeviceLog deviceLog);
|
||||||
|
|
||||||
|
List<DeviceLog> selectDeviceLogList(DeviceLog deviceLog);
|
||||||
|
|
||||||
|
List<MonitorModel> selectMonitorList(DeviceLog deviceLog);
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
package com.ruoyi.iot.log.service.factory;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.ruoyi.framework.config.MyBatisConfig;
|
||||||
|
import com.ruoyi.iot.log.service.impl.MySqlLogServiceImpl;
|
||||||
|
import com.ruoyi.iot.log.service.impl.TdengineLogServiceImpl;
|
||||||
|
import com.ruoyi.iot.model.MonitorModel;
|
||||||
|
import com.ruoyi.iot.tdengine.config.TDengineConfig;
|
||||||
|
import com.ruoyi.iot.domain.DeviceLog;
|
||||||
|
import com.ruoyi.iot.log.service.ILogService;
|
||||||
|
import com.ruoyi.iot.mapper.DeviceLogMapper;
|
||||||
|
import com.ruoyi.iot.tdengine.mapper.TDDeviceLogMapper;
|
||||||
|
import com.ruoyi.iot.util.SnowflakeIdWorker;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类名: DeviceLogServiceImpl
|
||||||
|
* 描述: TODO
|
||||||
|
* 时间: 2022/5/19,0019 18:09
|
||||||
|
* 开发人: wxy
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class LogServiceFactory {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ILogService getLogService() {
|
||||||
|
//先获取TDengine的配置,检测TDengine是否已经配置
|
||||||
|
if (containBean(TDengineConfig.class)) {
|
||||||
|
TDengineConfig tDengineConfig = applicationContext.getBean(TDengineConfig.class);
|
||||||
|
TDDeviceLogMapper tDDeviceLogMapper = applicationContext.getBean(TDDeviceLogMapper.class);
|
||||||
|
ILogService logService = new TdengineLogServiceImpl(tDengineConfig, tDDeviceLogMapper);
|
||||||
|
return logService;
|
||||||
|
} else if (containBean(MyBatisConfig.class)) {
|
||||||
|
//没有配置TDengine,那么使用MySQL的日志配置
|
||||||
|
DeviceLogMapper deviceLogMapper = applicationContext.getBean( DeviceLogMapper.class);
|
||||||
|
ILogService logService = new MySqlLogServiceImpl(deviceLogMapper);
|
||||||
|
return logService;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Method containBean
|
||||||
|
* @Description 根据类判断是否有对应bean
|
||||||
|
* @Param 类
|
||||||
|
* @return
|
||||||
|
* @date 2022/5/22,0022 14:12
|
||||||
|
* @author wxy
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private boolean containBean(@Nullable Class<?> T) {
|
||||||
|
String[] beans = applicationContext.getBeanNamesForType(T);
|
||||||
|
if (beans == null || beans.length == 0) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.ruoyi.iot.log.service.impl;
|
||||||
|
|
||||||
|
import com.ruoyi.iot.domain.DeviceLog;
|
||||||
|
import com.ruoyi.iot.log.service.ILogService;
|
||||||
|
import com.ruoyi.iot.mapper.DeviceLogMapper;
|
||||||
|
import com.ruoyi.iot.model.MonitorModel;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类名: MySqlLogServiceImpl
|
||||||
|
* 描述: MySQL存储日志实现类
|
||||||
|
* 时间: 2022/5/22,0022 13:37
|
||||||
|
* 开发人: admin
|
||||||
|
*/
|
||||||
|
public class MySqlLogServiceImpl implements ILogService {
|
||||||
|
|
||||||
|
private DeviceLogMapper deviceLogMapper;
|
||||||
|
|
||||||
|
public MySqlLogServiceImpl(DeviceLogMapper _deviceLogMapper){
|
||||||
|
this.deviceLogMapper=_deviceLogMapper;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int saveDeviceLog(DeviceLog deviceLog) {
|
||||||
|
return deviceLogMapper.insertDeviceLog(deviceLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DeviceLog> selectDeviceLogList(DeviceLog deviceLog) {
|
||||||
|
return deviceLogMapper.selectDeviceLogList(deviceLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<MonitorModel> selectMonitorList(DeviceLog deviceLog) {
|
||||||
|
return deviceLogMapper.selectMonitorList(deviceLog);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package com.ruoyi.iot.log.service.impl;
|
||||||
|
|
||||||
|
import com.ruoyi.iot.domain.DeviceLog;
|
||||||
|
import com.ruoyi.iot.log.service.ILogService;
|
||||||
|
import com.ruoyi.iot.model.MonitorModel;
|
||||||
|
import com.ruoyi.iot.tdengine.config.TDengineConfig;
|
||||||
|
import com.ruoyi.iot.tdengine.mapper.TDDeviceLogMapper;
|
||||||
|
import com.ruoyi.iot.util.SnowflakeIdWorker;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.annotation.Primary;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类名: TdengineLogServiceImpl
|
||||||
|
* 描述: TDengine存储日志数据实现类
|
||||||
|
* 时间: 2022/5/22,0022 13:38
|
||||||
|
* 开发人: admin
|
||||||
|
*/
|
||||||
|
public class TdengineLogServiceImpl implements ILogService {
|
||||||
|
|
||||||
|
private ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
private TDDeviceLogMapper tdDeviceLogMapper;
|
||||||
|
|
||||||
|
private TDengineConfig tDengineConfig;
|
||||||
|
|
||||||
|
private SnowflakeIdWorker snowflakeIdWorker;
|
||||||
|
|
||||||
|
private String dbName;
|
||||||
|
|
||||||
|
public TdengineLogServiceImpl(TDengineConfig _tDengineConfig,TDDeviceLogMapper _tdDeviceLogMapper) {
|
||||||
|
this.tdDeviceLogMapper = _tdDeviceLogMapper;
|
||||||
|
this.tDengineConfig = _tDengineConfig;
|
||||||
|
snowflakeIdWorker=new SnowflakeIdWorker(1);
|
||||||
|
this.dbName=_tDengineConfig.getDbName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int saveDeviceLog(DeviceLog deviceLog) {
|
||||||
|
long logId = snowflakeIdWorker.nextId();
|
||||||
|
deviceLog.setLogId(logId);
|
||||||
|
return tdDeviceLogMapper.save(dbName,deviceLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DeviceLog> selectDeviceLogList(DeviceLog deviceLog) {
|
||||||
|
return tdDeviceLogMapper.selectDeviceLogList(dbName,deviceLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<MonitorModel> selectMonitorList(DeviceLog deviceLog) {
|
||||||
|
return tdDeviceLogMapper.selectMonitorList(dbName,deviceLog);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -79,7 +79,7 @@ public class EmqxClient {
|
|||||||
token.waitForCompletion();
|
token.waitForCompletion();
|
||||||
}catch (Exception e){
|
}catch (Exception e){
|
||||||
logger.error("=====>>>>>mqtt连接失败 message={}",e.getMessage());
|
logger.error("=====>>>>>mqtt连接失败 message={}",e.getMessage());
|
||||||
throw new ServiceException("mqtt客户端连接错误"+e.getMessage());
|
// e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,7 +98,7 @@ public class EmqxClient {
|
|||||||
logger.debug("====>>>mqtt客户端启动成功");
|
logger.debug("====>>>mqtt客户端启动成功");
|
||||||
}catch (MqttException e){
|
}catch (MqttException e){
|
||||||
logger.error("mqtt客户端连接错误 error={}",e.getMessage());
|
logger.error("mqtt客户端连接错误 error={}",e.getMessage());
|
||||||
throw new ServiceException("mqtt客户端连接错误"+e.getMessage());
|
// e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,16 @@ package com.ruoyi.iot.mqtt;
|
|||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.ruoyi.iot.domain.Device;
|
import com.ruoyi.iot.domain.Device;
|
||||||
import com.ruoyi.iot.domain.DeviceLog;
|
import com.ruoyi.iot.domain.DeviceLog;
|
||||||
import com.ruoyi.iot.tdengine.service.ILogService;
|
import com.ruoyi.iot.log.service.ILogService;
|
||||||
import com.ruoyi.iot.model.NtpModel;
|
import com.ruoyi.iot.model.NtpModel;
|
||||||
import com.ruoyi.iot.model.ThingsModels.IdentityAndName;
|
import com.ruoyi.iot.model.ThingsModels.IdentityAndName;
|
||||||
|
import com.ruoyi.iot.model.ThingsModels.ThingsModelValueItem;
|
||||||
import com.ruoyi.iot.model.ThingsModels.ThingsModelValueRemarkItem;
|
import com.ruoyi.iot.model.ThingsModels.ThingsModelValueRemarkItem;
|
||||||
import com.ruoyi.iot.model.ThingsModels.ThingsModelValuesInput;
|
import com.ruoyi.iot.model.ThingsModels.ThingsModelValuesInput;
|
||||||
|
import com.ruoyi.iot.service.IDeviceLogService;
|
||||||
import com.ruoyi.iot.service.IDeviceService;
|
import com.ruoyi.iot.service.IDeviceService;
|
||||||
import org.eclipse.paho.client.mqttv3.MqttAsyncClient;
|
import org.eclipse.paho.client.mqttv3.MqttAsyncClient;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttClient;
|
||||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||||
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package com.ruoyi.iot.tdengine.config;
|
|||||||
|
|
||||||
import com.alibaba.druid.pool.DruidDataSource;
|
import com.alibaba.druid.pool.DruidDataSource;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import com.ruoyi.iot.tdengine.dao.TDDeviceLogMapper;
|
import com.ruoyi.iot.tdengine.mapper.TDDeviceLogMapper;
|
||||||
import org.apache.ibatis.session.SqlSessionFactory;
|
import org.apache.ibatis.session.SqlSessionFactory;
|
||||||
import org.mybatis.spring.SqlSessionFactoryBean;
|
import org.mybatis.spring.SqlSessionFactoryBean;
|
||||||
import org.mybatis.spring.SqlSessionTemplate;
|
import org.mybatis.spring.SqlSessionTemplate;
|
||||||
@@ -31,7 +31,7 @@ import java.util.List;
|
|||||||
* 开发人: wxy
|
* 开发人: wxy
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@MapperScan(basePackages = {"com.ruoyi.iot.tdengine.dao"}, sqlSessionTemplateRef = "tdengineSqlSessionTemplate")
|
@MapperScan(basePackages = {"com.ruoyi.iot.tdengine.mapper"}, sqlSessionTemplateRef = "tdengineSqlSessionTemplate")
|
||||||
@ConditionalOnProperty(name = "spring.datasource.druid.tdengine-server.enabled", havingValue = "true")
|
@ConditionalOnProperty(name = "spring.datasource.druid.tdengine-server.enabled", havingValue = "true")
|
||||||
public class TDengineConfig {
|
public class TDengineConfig {
|
||||||
|
|
||||||
@@ -64,6 +64,16 @@ public class TDengineConfig {
|
|||||||
return new SqlSessionTemplate(sqlSessionFactory);
|
return new SqlSessionTemplate(sqlSessionFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @Bean
|
||||||
|
// @ConditionalOnProperty(name = "spring.datasource.druid.tdengine-server.enabled", havingValue = "true")
|
||||||
|
// public TDDeviceLogMapper genTdengineLogMapper(@Qualifier("tDengineDataSource") TDDeviceLogMapper mapper) {
|
||||||
|
// if(this.deviceLogMapper==null){
|
||||||
|
// this.deviceLogMapper=mapper;
|
||||||
|
// }
|
||||||
|
// return this.deviceLogMapper;
|
||||||
|
// }
|
||||||
|
|
||||||
public TDDeviceLogMapper getTDengineLogMapper() {
|
public TDDeviceLogMapper getTDengineLogMapper() {
|
||||||
return deviceLogMapper;
|
return deviceLogMapper;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.ruoyi.iot.tdengine.mapper;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @package com.ruoyi.mysql.mysql.tdengine
|
||||||
|
* 类名: DatabaseMapper
|
||||||
|
* 描述: TODO
|
||||||
|
* 时间: 2022/5/16,0016 1:27
|
||||||
|
* 开发人: wxy
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public interface DatabaseMapper {
|
||||||
|
|
||||||
|
int createDB();
|
||||||
|
|
||||||
|
int dropDatabase();
|
||||||
|
|
||||||
|
int useDatabase();
|
||||||
|
|
||||||
|
int createTable();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.ruoyi.iot.tdengine.mapper;
|
||||||
|
|
||||||
|
import com.ruoyi.iot.domain.DeviceLog;
|
||||||
|
import com.ruoyi.iot.model.MonitorModel;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.lang.management.MonitorInfo;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @package com.ruoyi.mysql.mysql.tdengine
|
||||||
|
* 类名: DatabaseMapper
|
||||||
|
* 描述: TODO
|
||||||
|
* 时间: 2022/5/16,0016 1:27
|
||||||
|
* 开发人: wxy
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public interface TDDeviceLogMapper {
|
||||||
|
|
||||||
|
|
||||||
|
int createDB( String database);
|
||||||
|
|
||||||
|
int createSTable(String database);
|
||||||
|
|
||||||
|
int createTable(String database,String deviceId);
|
||||||
|
|
||||||
|
int save(@Param("database") String database,@Param("device") DeviceLog deviceLog);
|
||||||
|
|
||||||
|
List<DeviceLog> selectSTable(String database,DeviceLog deviceLog);
|
||||||
|
|
||||||
|
int delete(String dbName, DeviceLog deviceLog);
|
||||||
|
|
||||||
|
// List<DeviceLog> selectLogListByPage(String dbName, Integer pageSize, Integer pageNum, String deviceNum, Date beginDate, Date endDate);
|
||||||
|
|
||||||
|
List<DeviceLog> selectLogList(String dbName, Long deviceId, String serialNumber, Long isMonitor, Long logType, Date beginDate, Date endDate);
|
||||||
|
|
||||||
|
List<MonitorModel> selectMonitorList(@Param("database") String database, @Param("device") DeviceLog deviceLog);
|
||||||
|
|
||||||
|
List<DeviceLog> selectDeviceLogList(@Param("database") String database,@Param("device") DeviceLog deviceLog);
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
<!DOCTYPE mapper
|
<!DOCTYPE mapper
|
||||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="com.ruoyi.iot.tdengine.dao.DatabaseMapper">
|
<mapper namespace="com.ruoyi.iot.tdengine.mapper.DatabaseMapper">
|
||||||
|
|
||||||
<!-- 创建数据库-->
|
<!-- 创建数据库-->
|
||||||
<update id="createDB" parameterType="java.lang.String">
|
<update id="createDB" parameterType="java.lang.String">
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<!DOCTYPE mapper
|
<!DOCTYPE mapper
|
||||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="com.ruoyi.iot.tdengine.dao.TDDeviceLogMapper">
|
<mapper namespace="com.ruoyi.iot.tdengine.mapper.TDDeviceLogMapper">
|
||||||
|
|
||||||
<resultMap id="BaseResultMap" type="com.ruoyi.iot.domain.DeviceLog">
|
<resultMap id="BaseResultMap" type="com.ruoyi.iot.domain.DeviceLog">
|
||||||
<id column="ts" property="ts"/>
|
<id column="ts" property="ts"/>
|
||||||
|
|||||||
BIN
vue/src/assets/images/code.jpg
Normal file
BIN
vue/src/assets/images/code.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 61 KiB |
@@ -1,5 +1,45 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="app-container home">
|
<div class="app-container home">
|
||||||
|
<el-row :gutter="40" style="margin-bottom:10px;">
|
||||||
|
<el-col :xs="24" :sm="24" :md="24" :lg="14" :xl="14">
|
||||||
|
<el-card shadow="hover" style="margin:-10px;margin-bottom:20px;font-size:14px;min-height:170px;">
|
||||||
|
<div style="font-size:16px;font-weight:bold;margin-bottom:18px;">物美智能生活物联网平台</div>
|
||||||
|
<div style="display:table;margin-bottom:10px;">
|
||||||
|
<div style="width:70px;font-weight: bold;display:table-cell;">个人用户:</div>
|
||||||
|
<div style="display:table-cell;line-height:22px;"><b style="color:#F56C6C">可用于个人学习和使用,非商业用途。</b>不提供移动端源码,后期可以通过两种方式使用移动端:1.免费托管设备到平台;2.使用移动端开放的接口连接自己搭建的系统。</div>
|
||||||
|
</div>
|
||||||
|
<div style="display:table;">
|
||||||
|
<div style="width:70px;font-weight: bold;display:table-cell;">企业用户:</div>
|
||||||
|
<div style="display:table-cell;line-height:22px;"><b style="color:#F56C6C">可用于商业用途,并提供移动端源码,通过赞助方式获取企业授权。</b>但是不能低价或批量转售源码,不能随意分发源码。目前赞助费为1500元,项目不断完善后会对应增加费用。</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="24" :md="24" :lg="10" :xl="10">
|
||||||
|
<el-card shadow="hover" style="margin:-10px;margin-bottom:20px;font-size:14px;min-height:170px;">
|
||||||
|
<div style="float:left;width:170px;">
|
||||||
|
<el-image style="width:154px;" :src="require('@/assets/images/code.jpg')"></el-image>
|
||||||
|
</div>
|
||||||
|
<div style="float:left;">
|
||||||
|
<div style="font-size:16px;font-weight:bold;margin:16px 0;">微信扫一扫,查看小程序端</div>
|
||||||
|
<div style="display:table;margin-bottom:10px;">
|
||||||
|
<div style="width:70px;font-weight: bold;display:table-cell;">官方网站</div>
|
||||||
|
<div style="display:table-cell;">
|
||||||
|
<span>www.wumei.live</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="display:table;margin-bottom:15px;">
|
||||||
|
<div style="width:70px;font-weight: bold;display:table-cell;">系统源码</div>
|
||||||
|
<div style="display:table-cell;">
|
||||||
|
<el-link target="_blank" href="https://gitee.com/kerwincui/wumei-smart" type="danger">Gitee源码</el-link>
|
||||||
|
<el-link target="_blank" href="https://github.com/kerwincui/wumei-smart" style="margin-left:20px;">Github源码</el-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
<el-row :gutter="40" style="margin-bottom:80px;">
|
<el-row :gutter="40" style="margin-bottom:80px;">
|
||||||
<el-col :xs="24" :sm="24" :md="24" :lg="14" :xl="14">
|
<el-col :xs="24" :sm="24" :md="24" :lg="14" :xl="14">
|
||||||
<el-card style="margin:-10px;" shadow="hover" body-style="background-color:#F8F8F8;">
|
<el-card style="margin:-10px;" shadow="hover" body-style="background-color:#F8F8F8;">
|
||||||
@@ -141,13 +181,6 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
<div style="margin:-21px;margin-top:100px;bottom:0;border:1px solid #ccc;padding:10px;margin-bottom:-21px;">
|
|
||||||
<div>
|
|
||||||
<el-link href="http://wumei.live" target="_blank" type="primary" style="margin-left:20px;">开源生活物联网平台 >></el-link>
|
|
||||||
<el-link href="https://github.com/kerwincui/wumei-smart" target="_blank" type="danger" style="margin-left:30px;">Github源码 >></el-link>
|
|
||||||
<el-link href="https://gitee.com/kerwincui/wumei-smart" target="_blank" type="success" style="margin-left:30px;">码云源码 >></el-link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div style="padding: 6px">
|
<div style="padding: 6px">
|
||||||
<el-card v-show="showSearch" style="margin-bottom: 6px">
|
<el-card v-show="showSearch" style="margin-bottom: 6px">
|
||||||
<div style="height:50px; color:#F56C6C;margin-left:20px;">该功能下个版本发布</div>
|
|
||||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px" style="margin-bottom:-20px;">
|
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px" style="margin-bottom:-20px;">
|
||||||
<el-form-item label="客户端ID" prop="clientId">
|
<el-form-item label="客户端ID" prop="clientId">
|
||||||
<el-input v-model="queryParams.clientId" placeholder="请输入客户端ID" clearable size="small" @keyup.enter.native="handleQuery" />
|
<el-input v-model="queryParams.clientId" placeholder="请输入客户端ID" clearable size="small" @keyup.enter.native="handleQuery" />
|
||||||
@@ -14,6 +13,7 @@
|
|||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||||
|
<el-tag type="danger" style="margin-left:15px;">该功能暂不可用,后面版本发布</el-tag>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|||||||
@@ -392,6 +392,7 @@ export default {
|
|||||||
mqttSubscribe(list) {
|
mqttSubscribe(list) {
|
||||||
// 订阅当前页面设备状态和实时监测
|
// 订阅当前页面设备状态和实时监测
|
||||||
let topics = [];
|
let topics = [];
|
||||||
|
// 订阅数太多,会导致emqx连接中断或者订阅缓慢
|
||||||
for (let i = 0; i < list.length; i++) {
|
for (let i = 0; i < list.length; i++) {
|
||||||
let topicStatus = "/" + list[i].productId + "/" + list[i].serialNumber + "/status/post";
|
let topicStatus = "/" + list[i].productId + "/" + list[i].serialNumber + "/status/post";
|
||||||
let topicMonitor = "/" + list[i].productId + "/" + list[i].serialNumber + "/monitor/post";
|
let topicMonitor = "/" + list[i].productId + "/" + list[i].serialNumber + "/monitor/post";
|
||||||
@@ -451,9 +452,9 @@ export default {
|
|||||||
this.queryParams.params["endActiveTime"] = this.daterangeActiveTime[1];
|
this.queryParams.params["endActiveTime"] = this.daterangeActiveTime[1];
|
||||||
}
|
}
|
||||||
// 判断是否是admin角色
|
// 判断是否是admin角色
|
||||||
if (this.$store.state.user.roles.indexOf("admin") === -1) {
|
// if (this.$store.state.user.roles.indexOf("admin") === -1) {
|
||||||
this.queryParams.userId = this.$store.state.user.userId
|
// this.queryParams.userId = this.$store.state.user.userId
|
||||||
}
|
// }
|
||||||
listDeviceShort(this.queryParams).then(response => {
|
listDeviceShort(this.queryParams).then(response => {
|
||||||
this.deviceList = response.rows;
|
this.deviceList = response.rows;
|
||||||
this.total = response.total;
|
this.total = response.total;
|
||||||
@@ -519,6 +520,7 @@ export default {
|
|||||||
// 筛选监测数据
|
// 筛选监测数据
|
||||||
this.monitorThings = thingsModel.properties.filter(item => item.isMonitor == 1);
|
this.monitorThings = thingsModel.properties.filter(item => item.isMonitor == 1);
|
||||||
// 监测数据集合初始化
|
// 监测数据集合初始化
|
||||||
|
this.dataList=[];
|
||||||
for (let i = 0; i < this.monitorThings.length; i++) {
|
for (let i = 0; i < this.monitorThings.length; i++) {
|
||||||
this.dataList.push({
|
this.dataList.push({
|
||||||
id: this.monitorThings[i].id,
|
id: this.monitorThings[i].id,
|
||||||
|
|||||||
@@ -23,15 +23,14 @@ export default {
|
|||||||
watch: {
|
watch: {
|
||||||
// 获取到父组件传递的值
|
// 获取到父组件传递的值
|
||||||
publish: function (val, oldVal) {
|
publish: function (val, oldVal) {
|
||||||
this.mqttPublish(val.topic, val.message,val.name);
|
this.mqttPublish(val.topic, val.message, val.name);
|
||||||
},
|
},
|
||||||
subscribes: function (val, oldVal) {
|
subscribes: function (val, oldVal) {
|
||||||
this.connectMqtt(val);
|
this.connectMqtt(val);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {};
|
||||||
};
|
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
|
||||||
@@ -39,12 +38,13 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
/** 连接Mqtt */
|
/** 连接Mqtt */
|
||||||
connectMqtt(subscribeTopics) {
|
connectMqtt(subscribeTopics) {
|
||||||
|
let randomClientId='web-' + Math.random().toString(16).substr(2);
|
||||||
let options = {
|
let options = {
|
||||||
username: "wumei-smart",
|
username: "wumei-smart",
|
||||||
password: getToken(),
|
password: getToken(),
|
||||||
cleanSession: false,
|
cleanSession: false,
|
||||||
keepAlive: 30,
|
keepAlive: 30,
|
||||||
clientId: 'web-' + Math.random().toString(16).substr(2),
|
clientId: randomClientId,
|
||||||
connectTimeout: 10000
|
connectTimeout: 10000
|
||||||
}
|
}
|
||||||
// 配置Mqtt地址
|
// 配置Mqtt地址
|
||||||
@@ -53,8 +53,9 @@ export default {
|
|||||||
console.log("mqtt地址:", url);
|
console.log("mqtt地址:", url);
|
||||||
this.client = mqtt.connect(url, options);
|
this.client = mqtt.connect(url, options);
|
||||||
this.client.on("connect", (e) => {
|
this.client.on("connect", (e) => {
|
||||||
console.log("成功连接服务器:", e);
|
console.log("客户端:"+randomClientId+",成功连接服务器:", e);
|
||||||
// 订阅主题
|
// 订阅主题
|
||||||
|
if (subscribeTopics != '' && subscribeTopics.length > 0) {
|
||||||
this.client.subscribe(subscribeTopics, {
|
this.client.subscribe(subscribeTopics, {
|
||||||
qos: 1
|
qos: 1
|
||||||
}, (err) => {
|
}, (err) => {
|
||||||
@@ -65,6 +66,7 @@ export default {
|
|||||||
console.log('消息订阅失败!')
|
console.log('消息订阅失败!')
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
// 重新连接
|
// 重新连接
|
||||||
this.reconnectMqtt()
|
this.reconnectMqtt()
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
<div style="padding: 6px">
|
<div style="padding: 6px">
|
||||||
<el-card v-show="showSearch" style="margin-bottom: 6px">
|
<el-card v-show="showSearch" style="margin-bottom: 6px">
|
||||||
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px" style="margin-bottom: -20px">
|
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px" style="margin-bottom: -20px">
|
||||||
<el-form-item label="客户端" prop="categoryName">
|
<el-form-item label="客户端" prop="clientid">
|
||||||
<el-input v-model="queryParams.categoryName" placeholder="请输入客户端ID" clearable size="small" @keyup.enter.native="handleQuery" />
|
<el-input v-model="queryParams.clientid" placeholder="请输入客户端ID" clearable size="small" @keyup.enter.native="handleQuery" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
<el-table-column label="会话创建时间" align="center" prop="created_at" />
|
<el-table-column label="会话创建时间" align="center" prop="created_at" />
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="150">
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="150">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button size="small" type="danger" v-if="scope.row.connected" style="padding: 5px" v-hasPermi="['monitor:client:edit']" @click="handleDelete(scope.row)">
|
<el-button size="small" type="danger" v-if="scope.row.connected" style="padding: 5px" v-hasPermi="['iot:product:remove']" @click="handleDelete(scope.row)">
|
||||||
<svg-icon icon-class="disconnect" /> 断开连接
|
<svg-icon icon-class="disconnect" /> 断开连接
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
@@ -53,16 +53,14 @@
|
|||||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams._page" :limit.sync="queryParams._limit" @pagination="getList" />
|
<pagination v-show="total > 0" :total="total" :page.sync="queryParams._page" :limit.sync="queryParams._limit" @pagination="getList" />
|
||||||
|
|
||||||
<!-- MQTT客户端详细 -->
|
<!-- MQTT客户端详细 -->
|
||||||
<el-dialog :title="title" :visible.sync="open" width="50%" append-to-body>
|
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
|
||||||
<el-tabs v-model="activeName" tab-position="top" style="padding: 10px">
|
<el-tabs v-model="activeName" tab-position="top" style="padding: 10px">
|
||||||
<el-tab-pane name="basic">
|
<el-tab-pane name="basic">
|
||||||
<span slot="label">基本信息</span>
|
<span slot="label">基本信息</span>
|
||||||
<el-form ref="form" :model="form" label-width="120px" size="mini">
|
<el-descriptions class="margin-top" :column="2" border size="medium">
|
||||||
|
|
||||||
<el-descriptions class="margin-top" title="基本信息" :column="4" direction="vertical">
|
|
||||||
<el-descriptions-item label="节点">{{form.node }}</el-descriptions-item>
|
<el-descriptions-item label="节点">{{form.node }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="客户端ID">{{form.clientid}}</el-descriptions-item>
|
<el-descriptions-item label="客户端ID">{{form.clientid}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="Clean Session">{{form.clean_start}}</el-descriptions-item>
|
<el-descriptions-item label="清除Session">{{form.clean_start}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="会话过期间隔(秒)">{{form.expiry_interval}}</el-descriptions-item>
|
<el-descriptions-item label="会话过期间隔(秒)">{{form.expiry_interval}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="用户名">{{form.username}}</el-descriptions-item>
|
<el-descriptions-item label="用户名">{{form.username}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="协议类型">{{form.proto_ver}}</el-descriptions-item>
|
<el-descriptions-item label="协议类型">{{form.proto_ver}}</el-descriptions-item>
|
||||||
@@ -93,14 +91,11 @@
|
|||||||
<el-descriptions-item label="接收的PUBLISH报文数量">{{form.recv_msg}}</el-descriptions-item>
|
<el-descriptions-item label="接收的PUBLISH报文数量">{{form.recv_msg}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="接收的字节数量">{{form.recv_oct}}</el-descriptions-item>
|
<el-descriptions-item label="接收的字节数量">{{form.recv_oct}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="接收的MQTT报文数量">{{form.recv_pkt}}</el-descriptions-item>
|
<el-descriptions-item label="接收的MQTT报文数量">{{form.recv_pkt}}</el-descriptions-item>
|
||||||
|
|
||||||
<el-descriptions-item label="发送的TCP报文数量">{{form.send_cnt}}</el-descriptions-item>
|
<el-descriptions-item label="发送的TCP报文数量">{{form.send_cnt}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="发送的PUBLISH报文数量">{{form.send_msg}}</el-descriptions-item>
|
<el-descriptions-item label="发送的PUBLISH报文数量">{{form.send_msg}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="发送的字节数量">{{form.send_oct}}</el-descriptions-item>
|
<el-descriptions-item label="发送的字节数量">{{form.send_oct}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="发送的MQTT报文数量">{{form.send_pkt}}</el-descriptions-item>
|
<el-descriptions-item label="发送的MQTT报文数量">{{form.send_pkt}}</el-descriptions-item>
|
||||||
|
|
||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
</el-form>
|
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane name="subscribe">
|
<el-tab-pane name="subscribe">
|
||||||
@@ -190,6 +185,7 @@ export default {
|
|||||||
queryParams: {
|
queryParams: {
|
||||||
_limit: 10,
|
_limit: 10,
|
||||||
_page: 1,
|
_page: 1,
|
||||||
|
clientid:null,
|
||||||
},
|
},
|
||||||
// 表单参数
|
// 表单参数
|
||||||
form: {},
|
form: {},
|
||||||
|
|||||||
@@ -14,10 +14,10 @@
|
|||||||
<el-table-column label="描述" align="left" prop="description" />
|
<el-table-column label="描述" align="left" prop="description" />
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="150">
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="150">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button size="small" type="success" style="padding:5px;" @click="loadMqttPlugin(scope.row.name)" v-if="!scope.row.active" v-hasPermi="['monitor:online:edit']">
|
<el-button size="small" type="success" style="padding:5px;" @click="loadMqttPlugin(scope.row.name)" v-if="!scope.row.active" v-hasPermi="['iot:product:remove']">
|
||||||
<svg-icon icon-class="start" /> 启动
|
<svg-icon icon-class="start" /> 启动
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button size="small" type="danger" style="padding:5px;" @click="unloadMqttPlugin(scope.row.name)" v-else v-hasPermi="['monitor:online:edit']">
|
<el-button size="small" type="danger" style="padding:5px;" @click="unloadMqttPlugin(scope.row.name)" v-else v-hasPermi="['iot:product:remove']">
|
||||||
<svg-icon icon-class="stop" /> 停止
|
<svg-icon icon-class="stop" /> 停止
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -12,19 +12,16 @@
|
|||||||
<el-table v-loading="loading" :data="resourceList">
|
<el-table v-loading="loading" :data="resourceList">
|
||||||
<el-table-column label="ID" align="center" header-align="center" prop="id">
|
<el-table-column label="ID" align="center" header-align="center" prop="id">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-link :underline="false" type="primary">{{ scope.row.id }}</el-link>
|
<el-link :underline="false" type="primary" @click="handleQuery(scope.row)">{{ scope.row.id }}</el-link>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="资源类型" align="center" prop="type" />
|
<el-table-column label="资源类型" align="center" prop="type" />
|
||||||
<el-table-column label="备注" align="center" prop="description" />
|
<el-table-column label="备注" align="center" prop="description" />
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
<el-table-column label="操作" align="center" width="200">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button size="small" type="text" style="padding: 5px" v-hasPermi="['monitor:resource:query']" @click="handleQuery(scope.row)">
|
<el-button size="small" type="text" icon="el-icon-connection" style="padding: 5px" v-hasPermi="['monitor:resource:checkStatus']" @click="checkStatus(scope.row)">状态
|
||||||
查看
|
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button size="small" type="text" icon="el-icon-delete" style="padding: 5px" v-hasPermi="['monitor:resource:delete']" @click="handleDelete(scope.row)">删除
|
<el-button size="small" type="text" icon="el-icon-delete" style="padding: 5px" v-hasPermi="['iot:product:remove']" @click="handleDelete(scope.row)">删除
|
||||||
</el-button>
|
|
||||||
<el-button size="small" type="text" icon="el-icon-delete" style="padding: 5px" v-hasPermi="['monitor:resource:checkStatus']" @click="checkStatus(scope.row)">状态
|
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -32,7 +29,7 @@
|
|||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<!-- 资源详细 -->
|
<!-- 资源详细 -->
|
||||||
<el-dialog title="资源详细" :visible.sync="openView" width="50%" append-to-body>
|
<el-dialog title="资源详细" :visible.sync="openView" width="800px" append-to-body>
|
||||||
<el-form ref="form" :model="form" label-width="180px" size="mini">
|
<el-form ref="form" :model="form" label-width="180px" size="mini">
|
||||||
<el-card style="padding-bottom: 10px">
|
<el-card style="padding-bottom: 10px">
|
||||||
<div slot="header" class="clearfix">
|
<div slot="header" class="clearfix">
|
||||||
@@ -96,22 +93,18 @@
|
|||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- 测试重连 -->
|
<!-- 测试重连 -->
|
||||||
<el-dialog title="检测状态" :visible.sync="openStatusView" width="40%" append-to-body>
|
<el-dialog title="检测状态" :visible.sync="openStatusView" width="600px" append-to-body>
|
||||||
<el-form ref="statusForm" :model="statusForm" label-width="180px" size="mini">
|
<el-form ref="statusForm" :model="statusForm" label-width="180px" size="mini" v-if="statusForm.status[0]">
|
||||||
<el-row>
|
|
||||||
<el-col :span="12" v-if="statusForm.status[0]">
|
|
||||||
{{ statusForm.status[0].node }}
|
{{ statusForm.status[0].node }}
|
||||||
<el-tag type="success" v-if="statusForm.status[0].is_alive == true" style="margin-left: 10px">可用</el-tag>
|
<el-tag type="success" v-if="statusForm.status[0].is_alive == true" style="margin-left: 10px">可用</el-tag>
|
||||||
<el-tag type="danger" v-if="statusForm.status[0].is_alive == false" style="margin-left: 10px">不可用</el-tag>
|
<el-tag type="danger" v-if="statusForm.status[0].is_alive == false" style="margin-left: 10px">不可用</el-tag>
|
||||||
<el-button size="small" type="primary" icon="el-icon-connection" style="padding: 5px; margin-left: 10px" v-hasPermi="['monitor:resource:connect']" @click="checkNode(statusForm.id)">重新连接
|
<el-button size="small" type="primary" icon="el-icon-connection" style="padding: 5px; margin-left: 10px" v-hasPermi="['monitor:resource:connect']" @click="checkNode(statusForm.id)">重新连接
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- 添加资源 -->
|
<!-- 添加资源 -->
|
||||||
<el-dialog title="资源管理" :visible.sync="openAddView" width="50%" append-to-body :before-close="cancel">
|
<el-dialog title="资源管理" :visible.sync="openAddView" width="800px" append-to-body :before-close="cancel">
|
||||||
<el-form ref="addResourceForm" :model="addResourceForm" label-width="180px" :rules="rule">
|
<el-form ref="addResourceForm" :model="addResourceForm" label-width="180px" :rules="rule">
|
||||||
<el-card style="padding-bottom: 10px">
|
<el-card style="padding-bottom: 10px">
|
||||||
<div slot="header" class="clearfix">
|
<div slot="header" class="clearfix">
|
||||||
|
|||||||
@@ -10,37 +10,34 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-table v-loading="loading" :data="rulesList">
|
<el-table v-loading="loading" :data="rulesList">
|
||||||
<el-table-column label="ID" align="center" header-align="center" prop="id">
|
<el-table-column label="ID" align="center" header-align="center" prop="id" width="150">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-link :underline="false" type="primary">{{scope.row.id }}</el-link>
|
<el-link :underline="false" type="primary" @click="handleQuery(scope.row)">{{scope.row.id }}</el-link>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="主题" align="center" prop="for" width="120">
|
<el-table-column label="主题" align="center" prop="for">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<p v-for="(topic, index) in scope.row.for" :key="index">
|
<p v-for="(topic, index) in scope.row.for" :key="index">
|
||||||
<el-tag type="success">{{ topic }}</el-tag>
|
<el-tag type="warning">{{ topic }}</el-tag>
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="SQL" align="center" prop="rawsql" />
|
<el-table-column label="SQL" align="center" prop="rawsql" />
|
||||||
<el-table-column label="响应动作" align="center" prop="actions">
|
<el-table-column label="响应动作" align="center" prop="actions" width="250">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<p v-for="(action, index) in scope.row.actions" :key="index">
|
<p v-for="(action, index) in scope.row.actions" :key="index">
|
||||||
<el-tag type="success">{{ action.name }}</el-tag>
|
<el-tag type="success">{{ action.name }}</el-tag>
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="已命中" align="center" prop="matched">
|
<el-table-column label="已命中" align="center" prop="matched" width="100">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ scope.row.metrics[0].matched }}
|
{{ scope.row.metrics[0].matched }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="150">
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="100">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button size="small" type="text" style="padding: 5px" v-hasPermi="['monitor:rules:query']" @click="handleQuery(scope.row)">
|
<el-button size="small" type="danger" icon="el-icon-delete" style="padding: 5px" v-hasPermi="['iot:product:remove']" @click="handleDelete(scope.row)">删除
|
||||||
查看
|
|
||||||
</el-button>
|
|
||||||
<el-button size="small" type="text" icon="el-icon-delete" style="padding: 5px" v-hasPermi="['monitor:rules:delete']" @click="handleDelete(scope.row)">删除
|
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -48,7 +45,7 @@
|
|||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<!-- 规则引擎详细 -->
|
<!-- 规则引擎详细 -->
|
||||||
<el-dialog title="规则引擎详细" :visible.sync="openView" width="50%" append-to-body>
|
<el-dialog title="规则引擎详细" :visible.sync="openView" width="800px" append-to-body>
|
||||||
<el-form ref="form" :model="form" label-width="120px" size="mini">
|
<el-form ref="form" :model="form" label-width="120px" size="mini">
|
||||||
<el-card style="padding-bottom: 10px">
|
<el-card style="padding-bottom: 10px">
|
||||||
<div slot="header" class="clearfix">
|
<div slot="header" class="clearfix">
|
||||||
@@ -107,20 +104,18 @@
|
|||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- 添加规则引擎 -->
|
<!-- 添加规则引擎 -->
|
||||||
<el-dialog title="资源管理" :visible.sync="openAddView" width="60%" append-to-body :before-close="cancel">
|
<el-dialog title="添加规则引擎" :visible.sync="openAddView" width="1000px" append-to-body :before-close="cancel">
|
||||||
<el-form ref="form" :model="form" label-width="180px">
|
<el-card style="margin-bottom:10px;">
|
||||||
<el-card style="padding-bottom: 10px">
|
|
||||||
<div slot="header" class="clearfix">
|
<div slot="header" class="clearfix">
|
||||||
<span>
|
<span style="font-size:16px;font-weight:bold;">条件</span>
|
||||||
<h2>条件</h2>
|
<span style="font-size:12px;margin-left:12px;">使用 SQL 定义规则条件与数据处理方式</span>
|
||||||
<h6>使用 SQL 定义规则条件与数据处理方式</h6>
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<el-row :gutter="50">
|
<el-form ref="form" :model="form" label-width="90px">
|
||||||
<el-col :span="12">
|
<el-row :gutter="30">
|
||||||
|
<el-col :span="13">
|
||||||
<el-form-item prop="sql_example">
|
<el-form-item prop="sql_example">
|
||||||
<span slot="label"> 规则 SQL: </span>
|
<span slot="label"> 规则 SQL: </span>
|
||||||
<CodeMirrorEditor :value="form.sql_example" myMode="text/x-mysql" height="420" />
|
<CodeMirrorEditor :value="form.sql_example" myMode="text/x-mysql" height="400" style="border:1px solid #ddd;" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="sql_example">
|
<el-form-item prop="sql_example">
|
||||||
<span slot="label"> 备注: </span>
|
<span slot="label"> 备注: </span>
|
||||||
@@ -129,57 +124,23 @@
|
|||||||
<el-form-item prop="SQLtest">
|
<el-form-item prop="SQLtest">
|
||||||
<span slot="label">
|
<span slot="label">
|
||||||
SQL测试:
|
SQL测试:
|
||||||
<el-tooltip content="自定义模拟数据进行 SQL 命令测试,仅用于测试功能" placement="top">
|
|
||||||
<i class="el-icon-question"></i>
|
|
||||||
</el-tooltip>
|
|
||||||
</span>
|
</span>
|
||||||
<el-switch v-model="form.SQLtest" active-text="" inactive-text="" :active-value="true" :inactive-value="false" active-color="#13ce66">
|
<el-switch v-model="form.SQLtest" active-text="" inactive-text="" :active-value="true" :inactive-value="false" active-color="#13ce66">
|
||||||
</el-switch>
|
</el-switch>
|
||||||
|
<span style="font-size:12px;margin-left:10px;">自定义模拟数据进行 SQL 命令测试,仅用于测试功能</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<div v-if="form.SQLtest">
|
|
||||||
<el-form-item prop="test_columns.username" v-if="form.test_columns">
|
|
||||||
<span slot="label"> username: </span>
|
|
||||||
<el-input v-model="form.test_columns.username" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item prop="test_columns.topic" v-if="form.test_columns">
|
|
||||||
<span slot="label"> topic: </span>
|
|
||||||
<el-input v-model="form.test_columns.topic" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item prop="test_columns.qos" v-if="form.test_columns">
|
|
||||||
<span slot="label"> qos: </span>
|
|
||||||
<el-input v-model="form.test_columns.qos" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item prop="test_columns.clientid" v-if="form.test_columns">
|
|
||||||
<span slot="label"> clientid: </span>
|
|
||||||
<el-input v-model="form.test_columns.clientid" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item prop="test_columns.payload" v-if="form.test_columns">
|
|
||||||
<span slot="label"> payload: </span>
|
|
||||||
<CodeMirrorEditor :value="form.test_columns.payload" myMode="application/json" height="150" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item v-if="form.test_columns">
|
|
||||||
<el-button @click="testConnect" type="success" size="mini">测 试</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item v-if="form.test_columns">
|
|
||||||
<span slot="label"> 测试结果: </span>
|
|
||||||
<textarea style="width: 497px; height: 70px" v-model="content">
|
|
||||||
</textarea>
|
|
||||||
</el-form-item>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="10">
|
<el-col :span="11">
|
||||||
<div class="sql-tips">
|
<div class="sql-tips">
|
||||||
<div class="title">编写 SQL 进行条件过滤与数据处理</div>
|
<div>编写 SQL 进行条件过滤与数据处理</div>
|
||||||
<div class="el-scrollbar">
|
<div class="doc-wrapper">
|
||||||
<div class="doc-wrapper" style="margin-bottom: -17px; margin-right: -17px">
|
|
||||||
<div class="el-scrollbar__view">
|
|
||||||
<div>
|
|
||||||
<p>
|
<p>
|
||||||
EMQ X
|
EMQ X
|
||||||
在消息发布、事件触发时将触发规则引擎,满足触发条件的规则将执行各自的
|
在消息发布、事件触发时将触发规则引擎,满足触发条件的规则将执行各自的
|
||||||
SQL 语句筛选并处理消息和事件的上下文信息。
|
SQL 语句筛选并处理消息和事件的上下文信息。
|
||||||
</p>
|
</p>
|
||||||
<p class="item">
|
<p>
|
||||||
规则引擎借助响应动作可将特定主题的消息处理结果存储到数据库,发送到
|
规则引擎借助响应动作可将特定主题的消息处理结果存储到数据库,发送到
|
||||||
HTTP Server,转发到消息队列 Kafka 或
|
HTTP Server,转发到消息队列 Kafka 或
|
||||||
RabbitMQ,重新发布到新的主题甚至是另一个 Broker
|
RabbitMQ,重新发布到新的主题甚至是另一个 Broker
|
||||||
@@ -198,7 +159,7 @@
|
|||||||
<div class="code">
|
<div class="code">
|
||||||
<code>SELECT payload.x as x FROM "t/a"</code>
|
<code>SELECT payload.x as x FROM "t/a"</code>
|
||||||
</div>
|
</div>
|
||||||
<p class="item">
|
<p>
|
||||||
规则引擎使用 $events/ 开头的虚拟主题(事件主题)处理
|
规则引擎使用 $events/ 开头的虚拟主题(事件主题)处理
|
||||||
EMQ X
|
EMQ X
|
||||||
内置事件,内置事件提供更精细的消息控制和客户端动作处理能力,可用在
|
内置事件,内置事件提供更精细的消息控制和客户端动作处理能力,可用在
|
||||||
@@ -216,19 +177,50 @@
|
|||||||
<p>规则引擎和 SQL 语句的详细教程参见 EMQ X 文档。</p>
|
<p>规则引擎和 SQL 语句的详细教程参见 EMQ X 文档。</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-card>
|
<el-row v-if="form.SQLtest" style="background-color:#f8f8f8;margin:-20px;">
|
||||||
|
<el-col :span="13">
|
||||||
|
<el-form-item prop="test_columns.username" v-if="form.test_columns">
|
||||||
|
<span slot="label"> username </span>
|
||||||
|
<el-input v-model="form.test_columns.username" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="test_columns.topic" v-if="form.test_columns">
|
||||||
|
<span slot="label"> topic</span>
|
||||||
|
<el-input v-model="form.test_columns.topic" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="test_columns.payload" v-if="form.test_columns">
|
||||||
|
<span slot="label"> payload</span>
|
||||||
|
<CodeMirrorEditor :value="form.test_columns.payload" myMode="application/json" height="150" style="border:1px solid #ddd;" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="11">
|
||||||
|
<el-form-item prop="test_columns.clientid" v-if="form.test_columns">
|
||||||
|
<span slot="label"> clientid </span>
|
||||||
|
<el-input v-model="form.test_columns.clientid" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="test_columns.qos" v-if="form.test_columns">
|
||||||
|
<span slot="label"> qos </span>
|
||||||
|
<el-input v-model="form.test_columns.qos" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item v-if="form.test_columns">
|
||||||
|
<span slot="label"> 测试结果: </span>
|
||||||
|
<el-input type="textarea" v-model="content" :rows="4"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item v-if="form.test_columns">
|
||||||
|
<el-button @click="testConnect" type="success" size="mini" style="width:100px;">测 试</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
<el-card style="padding-bottom: 10px">
|
<el-card style="padding-bottom: 10px">
|
||||||
<div slot="header" class="clearfix">
|
<div slot="header" class="clearfix">
|
||||||
<span>
|
<div slot="header" class="clearfix">
|
||||||
<h2>响应动作</h2>
|
<span style="font-size:16px;font-weight:bold;">响应动作</span>
|
||||||
<h6>处理命中规则的消息</h6>
|
<span style="font-size:12px;margin-left:12px;">处理命中规则的消息</span>
|
||||||
</span>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-table ref="singleTable" :data="actions" highlight-current-row>
|
<el-table ref="singleTable" :data="actions" highlight-current-row>
|
||||||
<el-table-column property="name" label="类型"> </el-table-column>
|
<el-table-column property="name" label="类型"> </el-table-column>
|
||||||
@@ -254,10 +246,10 @@
|
|||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- 添加响应动作 -->
|
<!-- 添加响应动作 -->
|
||||||
<el-dialog title="响应动作" :visible.sync="openAddActionView" width="40%" append-to-body :before-close="cancelAction">
|
<el-dialog title="响应动作" :visible.sync="openAddActionView" width="600px" append-to-body :before-close="cancelAction">
|
||||||
<el-form ref="actionForm" :model="actionForm" label-width="180px" v-if="actionForm.actions" :rules="ruleActions">
|
<el-form ref="actionForm" :model="actionForm" label-width="180px" v-if="actionForm.actions" :rules="ruleActions">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="20">
|
<el-col>
|
||||||
<el-form-item prop="actions.title">
|
<el-form-item prop="actions.title">
|
||||||
<span slot="label">
|
<span slot="label">
|
||||||
动作:
|
动作:
|
||||||
@@ -486,8 +478,7 @@ export default {
|
|||||||
//检查 (调试)表单参数
|
//检查 (调试)表单参数
|
||||||
inspectForm: {},
|
inspectForm: {},
|
||||||
//消息重新发布表单参数
|
//消息重新发布表单参数
|
||||||
republishForm: {
|
republishForm: {},
|
||||||
},
|
|
||||||
//桥接数据到 MQTT Broker表单参数
|
//桥接数据到 MQTT Broker表单参数
|
||||||
data_to_mqtt_broker_Form: {
|
data_to_mqtt_broker_Form: {
|
||||||
resources: [],
|
resources: [],
|
||||||
@@ -672,7 +663,7 @@ export default {
|
|||||||
this.$refs[formName].validate((valid) => {
|
this.$refs[formName].validate((valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
param.$resource = this.data_to_mqtt_broker_Form.resourceId;
|
param.$resource = this.data_to_mqtt_broker_Form.resourceId;
|
||||||
if(this.data_to_mqtt_broker_Form.params.payload_tmpl != null){
|
if (this.data_to_mqtt_broker_Form.params.payload_tmpl != null) {
|
||||||
param.payload_tmpl =
|
param.payload_tmpl =
|
||||||
this.data_to_mqtt_broker_Form.params.payload_tmpl.default;
|
this.data_to_mqtt_broker_Form.params.payload_tmpl.default;
|
||||||
}
|
}
|
||||||
@@ -689,7 +680,7 @@ export default {
|
|||||||
this.$refs[formName].validate((valid) => {
|
this.$refs[formName].validate((valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
param.$resource = this.data_to_webserver_Form.resourceId;
|
param.$resource = this.data_to_webserver_Form.resourceId;
|
||||||
if(this.data_to_webserver_Form.params.payload_tmpl != null){
|
if (this.data_to_webserver_Form.params.payload_tmpl != null) {
|
||||||
param.payload_tmpl =
|
param.payload_tmpl =
|
||||||
this.data_to_webserver_Form.params.payload_tmpl.default;
|
this.data_to_webserver_Form.params.payload_tmpl.default;
|
||||||
}
|
}
|
||||||
@@ -762,54 +753,18 @@ export default {
|
|||||||
.sql-tips {
|
.sql-tips {
|
||||||
border: 4px dashed #d8d8d8;
|
border: 4px dashed #d8d8d8;
|
||||||
color: #71737d;
|
color: #71737d;
|
||||||
}
|
font-size: 12px;
|
||||||
|
padding: 10px;
|
||||||
.sql-tips {
|
|
||||||
padding: 20px 0;
|
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
font-size: 15px;
|
height: 510px;
|
||||||
max-height: 480px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sql-tips .title {
|
|
||||||
padding: 0 20px 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-scrollbar {
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
margin-right: -10px;
|
||||||
}
|
|
||||||
|
|
||||||
.sql-tips .doc-wrapper {
|
|
||||||
max-height: 400px;
|
|
||||||
padding: 0 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sql-tips .el-scrollbar__wrap {
|
|
||||||
overflow-x: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-scrollbar__wrap {
|
|
||||||
overflow: scroll;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
display: block;
|
|
||||||
margin-block-start: 1em;
|
|
||||||
margin-block-end: 1em;
|
|
||||||
margin-inline-start: 0px;
|
|
||||||
margin-inline-end: 0px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.code {
|
.code {
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.code {
|
|
||||||
background-color: hsla(0, 0%, 87%, 0.8);
|
background-color: hsla(0, 0%, 87%, 0.8);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,24 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<el-form v-show="showSearch" ref="queryForm" :inline="true" :model="queryParams" label-width="85px">
|
<el-form v-show="showSearch" ref="queryForm" :inline="true" :model="queryParams" label-width="85px">
|
||||||
<el-form-item label="第三方平台" prop="platform">
|
<el-form-item label="第三方平台" prop="platform">
|
||||||
<el-select v-model="queryParams.platform" clearable placeholder="请选择第三方平台" size="small">
|
<el-select v-model="queryParams.platform" clearable placeholder="请选择平台" size="small">
|
||||||
<el-option
|
<el-option v-for="dict in dict.type.iot_social_platform" :key="dict.value" :label="dict.label" :value="dict.value" />
|
||||||
v-for="dict in dict.type.iot_social_platform"
|
|
||||||
:key="dict.value"
|
|
||||||
:label="dict.label"
|
|
||||||
:value="dict.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="状态" prop="status">
|
<el-form-item label="状态" prop="status">
|
||||||
<el-select v-model="queryParams.status" clearable placeholder="请选择 0:启用 ,1:禁用" size="small">
|
<el-select v-model="queryParams.status" clearable placeholder="请选择状态" size="small">
|
||||||
<el-option
|
<el-option v-for="dict in dict.type.iot_social_platform_status" :key="dict.value" :label="dict.label" :value="dict.value" />
|
||||||
v-for="dict in dict.type.iot_social_platform_status"
|
|
||||||
:key="dict.value"
|
|
||||||
:label="dict.label"
|
|
||||||
:value="dict.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
@@ -29,167 +19,92 @@
|
|||||||
|
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button
|
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['iot:platform:add']">新增
|
||||||
type="primary"
|
|
||||||
plain
|
|
||||||
icon="el-icon-plus"
|
|
||||||
size="mini"
|
|
||||||
@click="handleAdd"
|
|
||||||
v-hasPermi="['iot:platform:add']"
|
|
||||||
>新增
|
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button
|
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate" v-hasPermi="['iot:platform:edit']">修改
|
||||||
type="success"
|
|
||||||
plain
|
|
||||||
icon="el-icon-edit"
|
|
||||||
size="mini"
|
|
||||||
:disabled="single"
|
|
||||||
@click="handleUpdate"
|
|
||||||
v-hasPermi="['iot:platform:edit']"
|
|
||||||
>修改
|
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button
|
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['iot:platform:remove']">删除
|
||||||
type="danger"
|
|
||||||
plain
|
|
||||||
icon="el-icon-delete"
|
|
||||||
size="mini"
|
|
||||||
:disabled="multiple"
|
|
||||||
@click="handleDelete"
|
|
||||||
v-hasPermi="['iot:platform:remove']"
|
|
||||||
>删除
|
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button
|
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['iot:platform:export']">导出
|
||||||
type="warning"
|
|
||||||
plain
|
|
||||||
icon="el-icon-download"
|
|
||||||
size="mini"
|
|
||||||
@click="handleExport"
|
|
||||||
v-hasPermi="['iot:platform:export']"
|
|
||||||
>导出
|
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="platformList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="platformList" @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center"/>
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
<el-table-column align="center" label="平台主键" prop="socialPlatformId" width="75"/>
|
<el-table-column align="center" label="平台名称" prop="platform">
|
||||||
<el-table-column align="center" label="平台名称" prop="platform" width="95">
|
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<dict-tag :options="dict.type.iot_social_platform" :value="scope.row.platform"/>
|
<dict-tag :options="dict.type.iot_social_platform" :value="scope.row.platform" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column align="center" label="状态" prop="status" width="75">
|
<el-table-column align="center" label="状态" prop="status" width="75">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<dict-tag :options="dict.type.iot_social_platform_status" :value="scope.row.status"/>
|
<dict-tag :options="dict.type.iot_social_platform_status" :value="scope.row.status" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="平台申请Id" align="center" prop="clientId"/>
|
<el-table-column label="平台申请ID" align="center" prop="clientId" />
|
||||||
<el-table-column label="平台密钥" align="center" prop="secretKey" :show-overflow-tooltip="true"/>
|
<el-table-column label="跳转地址" align="center" prop="redirectUri" width="180" :show-overflow-tooltip="true" />
|
||||||
<el-table-column label="跳转地址" align="center" prop="redirectUri" width="180" :show-overflow-tooltip="true"/>
|
<el-table-column align="center" label="绑定登录uri" prop="bindUri" :show-tooltip-when-overflow="true" :render-header="(h,column)=>renderHeaderMethods(h,column,columnTips.bindId)" />
|
||||||
|
<el-table-column align="center" label="跳转登录uri" prop="redirectLoginUri" :show-tooltip-when-overflow="true" :render-header="(h,column)=>renderHeaderMethods(h,column,columnTips.redirectLogin)" />
|
||||||
<el-table-column align="center" label="绑定登录uri" prop="bindUri" :show-tooltip-when-overflow="true"
|
<el-table-column align="center" label="错误提示uri" prop="errorMsgUri" :show-tooltip-when-overflow="true" :render-header="(h,column)=>renderHeaderMethods(h,column,columnTips.errorId)" />
|
||||||
:render-header="(h,column)=>renderHeaderMethods(h,column,columnTips.bindId)"/>
|
|
||||||
<el-table-column align="center" label="跳转登录uri" prop="redirectLoginUri" :show-tooltip-when-overflow="true"
|
|
||||||
:render-header="(h,column)=>renderHeaderMethods(h,column,columnTips.redirectLogin)"/>
|
|
||||||
<el-table-column align="center" label="错误提示uri" prop="errorMsgUri" :show-tooltip-when-overflow="true"
|
|
||||||
:render-header="(h,column)=>renderHeaderMethods(h,column,columnTips.errorId)"/>
|
|
||||||
<el-table-column align="center" label="备注" prop="remark" width="75" :show-tooltip-when-overflow="true"/>
|
|
||||||
<el-table-column align="center" label="创建者" prop="createBy"/>
|
|
||||||
<el-table-column align="center" label="创建时间" prop="createTime" width="100">
|
<el-table-column align="center" label="创建时间" prop="createTime" width="100">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
|
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column align="center" label="更新者" prop="updateBy"/>
|
|
||||||
<el-table-column align="center" label="更新时间" prop="updateTime" width="100">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span>{{ parseTime(scope.row.updateTime, '{y}-{m}-{d}') }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button
|
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['iot:platform:edit']">修改
|
||||||
size="mini"
|
|
||||||
type="text"
|
|
||||||
icon="el-icon-edit"
|
|
||||||
@click="handleUpdate(scope.row)"
|
|
||||||
v-hasPermi="['iot:platform:edit']"
|
|
||||||
>修改
|
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['iot:platform:remove']">删除
|
||||||
size="mini"
|
|
||||||
type="text"
|
|
||||||
icon="el-icon-delete"
|
|
||||||
@click="handleDelete(scope.row)"
|
|
||||||
v-hasPermi="['iot:platform:remove']"
|
|
||||||
>删除
|
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<pagination
|
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
|
||||||
v-show="total>0"
|
|
||||||
:total="total"
|
|
||||||
:page.sync="queryParams.pageNum"
|
|
||||||
:limit.sync="queryParams.pageSize"
|
|
||||||
@pagination="getList"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- 添加或修改第三方登录平台控制对话框 -->
|
<!-- 添加或修改第三方登录平台控制对话框 -->
|
||||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
<el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
|
||||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
<el-form ref="form" :model="form" :rules="rules" label-width="140px">
|
||||||
<el-form-item label="第三方平台" prop="platform">
|
<el-form-item label="第三方平台名称" prop="platform">
|
||||||
<el-select v-model="form.platform" placeholder="请选择第三方平台">
|
<el-select v-model="form.platform" placeholder="请选择第三方平台">
|
||||||
<el-option
|
<el-option v-for="dict in dict.type.iot_social_platform" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
|
||||||
v-for="dict in dict.type.iot_social_platform"
|
|
||||||
:key="dict.value"
|
|
||||||
:label="dict.label"
|
|
||||||
:value="dict.value"
|
|
||||||
></el-option>
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label=" 0:启用 ,1:禁用" prop="status">
|
<el-form-item label="第三方平台状态" prop="status">
|
||||||
<el-select v-model="form.status" placeholder="请选择 0:启用 ,1:禁用">
|
<el-select v-model="form.status" placeholder="请选择状态">
|
||||||
<el-option
|
<el-option v-for="dict in dict.type.iot_social_platform_status" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
|
||||||
v-for="dict in dict.type.iot_social_platform_status"
|
|
||||||
:key="dict.value"
|
|
||||||
:label="dict.label"
|
|
||||||
:value="dict.value"
|
|
||||||
></el-option>
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="第三方平台申请Id" prop="clientId">
|
<el-form-item label="第三方平台申请ID" prop="clientId">
|
||||||
<el-input v-model="form.clientId" placeholder="请输入第三方平台申请Id"/>
|
<el-input v-model="form.clientId" placeholder="请输入第三方平台申请Id" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="第三方平台密钥" prop="secretKey">
|
<el-form-item label="第三方平台密钥" prop="secretKey">
|
||||||
<el-input v-model="form.secretKey" placeholder="请输入第三方平台密钥"/>
|
<el-input v-model="form.secretKey" placeholder="请输入第三方平台密钥" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="用户认证后跳转地址" prop="redirectUri">
|
<el-form-item label="用户认证跳转地址" prop="redirectUri">
|
||||||
<el-input v-model="form.redirectUri" placeholder="请输入用户认证后跳转地址"/>
|
<el-input v-model="form.redirectUri" placeholder="请输入用户认证后跳转地址" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="删除标记位(0代表存在,2代表删除)" prop="delFlag">
|
<el-form-item label="绑定注册登录URI" prop="bindUri">
|
||||||
<el-input v-model="form.delFlag" placeholder="请输入删除标记位(0代表存在,2代表删除)"/>
|
<el-input v-model="form.bindUri" placeholder="请输入绑定注册登录uri,http://localhost/login?bindId=" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="跳转登录URI" prop="redirectLoginUri">
|
||||||
|
<el-input v-model="form.redirectLoginUri" placeholder="请输入跳转登录uri,http://localhost/login?loginId=" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="错误提示URI" prop="errorMsgUri">
|
||||||
|
<el-input v-model="form.errorMsgUri" placeholder="请输入错误提示uri,http://localhost/login?errorId=" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="备注" prop="remark">
|
<el-form-item label="备注" prop="remark">
|
||||||
<el-input v-model="form.remark" placeholder="请输入内容" type="textarea"/>
|
<el-input v-model="form.remark" placeholder="请输入内容" type="textarea" />
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="绑定注册登录uri,http://localhost/login?bindId=" prop="bindUri">
|
|
||||||
<el-input v-model="form.bindUri" placeholder="请输入绑定注册登录uri,http://localhost/login?bindId="/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="跳转登录uri,http://localhost/login?loginId=" prop="redirectLoginUri">
|
|
||||||
<el-input v-model="form.redirectLoginUri" placeholder="请输入跳转登录uri,http://localhost/login?loginId="/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="错误提示uri,http://localhost/login?errorId=" prop="errorMsgUri">
|
|
||||||
<el-input v-model="form.errorMsgUri" placeholder="请输入错误提示uri,http://localhost/login?errorId="/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div slot="footer" class="dialog-footer">
|
<div slot="footer" class="dialog-footer">
|
||||||
@@ -197,11 +112,17 @@
|
|||||||
<el-button @click="cancel">取 消</el-button>
|
<el-button @click="cancel">取 消</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {addPlatform, delPlatform, getPlatform, listPlatform, updatePlatform} from "@/api/iot/platform";
|
import {
|
||||||
|
addPlatform,
|
||||||
|
delPlatform,
|
||||||
|
getPlatform,
|
||||||
|
listPlatform,
|
||||||
|
updatePlatform
|
||||||
|
} from "@/api/iot/platform";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Platform",
|
name: "Platform",
|
||||||
@@ -242,30 +163,46 @@ export default {
|
|||||||
form: {},
|
form: {},
|
||||||
// 表单校验
|
// 表单校验
|
||||||
rules: {
|
rules: {
|
||||||
platform: [
|
platform: [{
|
||||||
{required: true, message: "第三方平台不能为空", trigger: "change"}
|
required: true,
|
||||||
],
|
message: "第三方平台不能为空",
|
||||||
status: [
|
trigger: "change"
|
||||||
{required: true, message: " 0:启用 ,1:禁用不能为空", trigger: "change"}
|
}],
|
||||||
],
|
status: [{
|
||||||
clientId: [
|
required: true,
|
||||||
{required: true, message: "第三方平台申请Id不能为空", trigger: "blur"}
|
message: " 0:启用 ,1:禁用不能为空",
|
||||||
],
|
trigger: "change"
|
||||||
secretKey: [
|
}],
|
||||||
{required: true, message: "第三方平台密钥不能为空", trigger: "blur"}
|
clientId: [{
|
||||||
],
|
required: true,
|
||||||
redirectUri: [
|
message: "第三方平台申请Id不能为空",
|
||||||
{required: true, message: "用户认证后跳转地址不能为空", trigger: "blur"}
|
trigger: "blur"
|
||||||
],
|
}],
|
||||||
bindUri: [
|
secretKey: [{
|
||||||
{required: true, message: "绑定注册登录uri,http://localhost/login?bindId=不能为空", trigger: "blur"}
|
required: true,
|
||||||
],
|
message: "第三方平台密钥不能为空",
|
||||||
redirectLoginUri: [
|
trigger: "blur"
|
||||||
{required: true, message: "跳转登录uri,http://localhost/login?loginId=不能为空", trigger: "blur"}
|
}],
|
||||||
],
|
redirectUri: [{
|
||||||
errorMsgUri: [
|
required: true,
|
||||||
{required: true, message: "错误提示uri,http://localhost/login?errorId=不能为空", trigger: "blur"}
|
message: "用户认证后跳转地址不能为空",
|
||||||
]
|
trigger: "blur"
|
||||||
|
}],
|
||||||
|
bindUri: [{
|
||||||
|
required: true,
|
||||||
|
message: "绑定注册登录uri,http://localhost/login?bindId=不能为空",
|
||||||
|
trigger: "blur"
|
||||||
|
}],
|
||||||
|
redirectLoginUri: [{
|
||||||
|
required: true,
|
||||||
|
message: "跳转登录uri,http://localhost/login?loginId=不能为空",
|
||||||
|
trigger: "blur"
|
||||||
|
}],
|
||||||
|
errorMsgUri: [{
|
||||||
|
required: true,
|
||||||
|
message: "错误提示uri,http://localhost/login?errorId=不能为空",
|
||||||
|
trigger: "blur"
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -273,7 +210,9 @@ export default {
|
|||||||
this.getList();
|
this.getList();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
renderHeaderMethods(h, {column}, content) {
|
renderHeaderMethods(h, {
|
||||||
|
column
|
||||||
|
}, content) {
|
||||||
return h(
|
return h(
|
||||||
'div', [
|
'div', [
|
||||||
h('span', column.label),
|
h('span', column.label),
|
||||||
@@ -300,14 +239,12 @@ export default {
|
|||||||
this.total = response.total;
|
this.total = response.total;
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
,
|
|
||||||
// 取消按钮
|
// 取消按钮
|
||||||
cancel() {
|
cancel() {
|
||||||
this.open = false;
|
this.open = false;
|
||||||
this.reset();
|
this.reset();
|
||||||
}
|
},
|
||||||
,
|
|
||||||
// 表单重置
|
// 表单重置
|
||||||
reset() {
|
reset() {
|
||||||
this.form = {
|
this.form = {
|
||||||
@@ -317,7 +254,6 @@ export default {
|
|||||||
clientId: null,
|
clientId: null,
|
||||||
secretKey: null,
|
secretKey: null,
|
||||||
redirectUri: null,
|
redirectUri: null,
|
||||||
delFlag: null,
|
|
||||||
createBy: null,
|
createBy: null,
|
||||||
createTime: null,
|
createTime: null,
|
||||||
updateTime: null,
|
updateTime: null,
|
||||||
@@ -328,34 +264,29 @@ export default {
|
|||||||
errorMsgUri: null
|
errorMsgUri: null
|
||||||
};
|
};
|
||||||
this.resetForm("form");
|
this.resetForm("form");
|
||||||
}
|
},
|
||||||
,
|
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
handleQuery() {
|
handleQuery() {
|
||||||
this.queryParams.pageNum = 1;
|
this.queryParams.pageNum = 1;
|
||||||
this.getList();
|
this.getList();
|
||||||
}
|
},
|
||||||
,
|
|
||||||
/** 重置按钮操作 */
|
/** 重置按钮操作 */
|
||||||
resetQuery() {
|
resetQuery() {
|
||||||
this.resetForm("queryForm");
|
this.resetForm("queryForm");
|
||||||
this.handleQuery();
|
this.handleQuery();
|
||||||
}
|
},
|
||||||
,
|
|
||||||
// 多选框选中数据
|
// 多选框选中数据
|
||||||
handleSelectionChange(selection) {
|
handleSelectionChange(selection) {
|
||||||
this.ids = selection.map(item => item.socialPlatformId)
|
this.ids = selection.map(item => item.socialPlatformId)
|
||||||
this.single = selection.length !== 1
|
this.single = selection.length !== 1
|
||||||
this.multiple = !selection.length
|
this.multiple = !selection.length
|
||||||
}
|
},
|
||||||
,
|
|
||||||
/** 新增按钮操作 */
|
/** 新增按钮操作 */
|
||||||
handleAdd() {
|
handleAdd() {
|
||||||
this.reset();
|
this.reset();
|
||||||
this.open = true;
|
this.open = true;
|
||||||
this.title = "添加第三方登录平台控制";
|
this.title = "添加第三方登录平台控制";
|
||||||
}
|
},
|
||||||
,
|
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
handleUpdate(row) {
|
handleUpdate(row) {
|
||||||
this.reset();
|
this.reset();
|
||||||
@@ -365,8 +296,7 @@ export default {
|
|||||||
this.open = true;
|
this.open = true;
|
||||||
this.title = "修改第三方登录平台控制";
|
this.title = "修改第三方登录平台控制";
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
,
|
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
submitForm() {
|
submitForm() {
|
||||||
this.$refs["form"].validate(valid => {
|
this.$refs["form"].validate(valid => {
|
||||||
@@ -386,8 +316,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
,
|
|
||||||
/** 删除按钮操作 */
|
/** 删除按钮操作 */
|
||||||
handleDelete(row) {
|
handleDelete(row) {
|
||||||
const socialPlatformIds = row.socialPlatformId || this.ids;
|
const socialPlatformIds = row.socialPlatformId || this.ids;
|
||||||
@@ -396,10 +325,8 @@ export default {
|
|||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.getList();
|
this.getList();
|
||||||
this.$modal.msgSuccess("删除成功");
|
this.$modal.msgSuccess("删除成功");
|
||||||
}).catch(() => {
|
}).catch(() => {});
|
||||||
});
|
},
|
||||||
}
|
|
||||||
,
|
|
||||||
/** 导出按钮操作 */
|
/** 导出按钮操作 */
|
||||||
handleExport() {
|
handleExport() {
|
||||||
this.download('iot/platform/export', {
|
this.download('iot/platform/export', {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="login">
|
<div class="login">
|
||||||
|
|
||||||
<div style="width:520px;padding:20px;">
|
<div style="width:520px;padding:20px;">
|
||||||
<el-row :gutter="10">
|
<el-row :gutter="10">
|
||||||
@@ -18,60 +18,52 @@
|
|||||||
</h3>
|
</h3>
|
||||||
<el-form-item prop="username">
|
<el-form-item prop="username">
|
||||||
<el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号">
|
<el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号">
|
||||||
<svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon"/>
|
<svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" />
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="password">
|
<el-form-item prop="password">
|
||||||
<el-input v-model="loginForm.password" type="password" auto-complete="off" placeholder="密码"
|
<el-input v-model="loginForm.password" type="password" auto-complete="off" placeholder="密码" @keyup.enter.native="handleLogin">
|
||||||
@keyup.enter.native="handleLogin">
|
<svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" />
|
||||||
<svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon"/>
|
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="code" v-if="captchaOnOff">
|
<el-form-item prop="code" v-if="captchaOnOff">
|
||||||
<el-input v-model="loginForm.code" auto-complete="off" placeholder="验证码" style="width: 63%"
|
<el-input v-model="loginForm.code" auto-complete="off" placeholder="验证码" style="width: 63%" @keyup.enter.native="handleLogin">
|
||||||
@keyup.enter.native="handleLogin">
|
<svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" />
|
||||||
<svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon"/>
|
|
||||||
</el-input>
|
</el-input>
|
||||||
<div class="login-code">
|
<div class="login-code">
|
||||||
<img :src="codeUrl" @click="getCode" class="login-code-img"/>
|
<img :src="codeUrl" @click="getCode" class="login-code-img" />
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;color:#000;">记住密码</el-checkbox>
|
<el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;color:#000;">记住密码</el-checkbox>
|
||||||
<el-form-item style="width:100%;">
|
<el-form-item style="width:100%;">
|
||||||
<el-button v-if="!bindAccount" :loading="loading" size="medium" type="primary" style="width:100%;"
|
<el-button v-if="!bindAccount" :loading="loading" size="medium" type="primary" style="width:100%;" @click.native.prevent="handleLogin">
|
||||||
@click.native.prevent="handleLogin">
|
|
||||||
<span v-if="!loading">登 录</span>
|
<span v-if="!loading">登 录</span>
|
||||||
<span v-else>登 录 中...</span>
|
<span v-else>登 录 中...</span>
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button v-else :loading="loading" size="medium" type="primary" style="width:100%;"
|
<el-button v-else :loading="loading" size="medium" type="primary" style="width:100%;" @click.native.prevent="handleLogin">
|
||||||
@click.native.prevent="handleLogin">
|
|
||||||
<span v-if="!loading">绑定</span>
|
<span v-if="!loading">绑定</span>
|
||||||
<span v-else>绑 定 中...</span>
|
<span v-else>绑 定 中...</span>
|
||||||
</el-button>
|
</el-button>
|
||||||
<div style="margin-top:20px;" v-if="!bindAccount">
|
<div style="margin-top:30px;" v-if="!bindAccount">
|
||||||
<div v-if="!bindAccount" style=";text-align: center ">
|
<div v-if="!bindAccount" style="float:left;">
|
||||||
|
<span style="color:#fff;margin-right:10px;">第三方登录</span>
|
||||||
<el-button type="success" circle title="微信登录" size="small" @click="authLogin">
|
<el-button type="success" circle title="微信登录" size="small" @click="authLogin">
|
||||||
<svg-icon icon-class="wechat"/>
|
<svg-icon icon-class="wechat" />
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
<el-button type="danger" circle title="QQ登录" size="small" @click="qqLogin">
|
<el-button type="danger" circle title="QQ登录" size="small" @click="qqLogin">
|
||||||
<svg-icon icon-class="qq"/>
|
<svg-icon icon-class="qq" />
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="primary" circle title="支付宝登录" size="small" @click="authLogin">
|
<el-button type="primary" circle title="支付宝登录" size="small" @click="authLogin">
|
||||||
<svg-icon icon-class="zhifubao"/>
|
<svg-icon icon-class="zhifubao" />
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div style="float:right;" v-if="register">
|
||||||
<a style="margin-right:20px;color:#222" target="_blank" href="http://wumei.live">返回官网</a>
|
<router-link style="color:#333;font-size:16px;" :to='{path:"/register",query: this.$route.query }'>立即注册>>
|
||||||
|
|
||||||
<div style="float: right;margin-top:10px;" v-if="register">
|
|
||||||
|
|
||||||
<router-link style="color:#fff;font-size:16px;" :to='{path:"/register",query: this.$route.query }'>立即注册
|
|
||||||
>>
|
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -79,10 +71,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- 底部 -->
|
<!-- 底部 -->
|
||||||
<div class="el-login-footer">
|
<div class="el-login-footer">
|
||||||
<span>Copyright © 2018-2021 <a target="_blank"
|
<span>Copyright © 2018-2021 <a target="_blank" href="http://wumei.live">wumei smart</a> All Rights Reserved.</span>
|
||||||
href="http://wumei.live">wumei smart</a> All Rights Reserved.</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -155,7 +146,6 @@ export default {
|
|||||||
this.redirectLogin(loginId);
|
this.redirectLogin(loginId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
redirectLogin(loginId) {
|
redirectLogin(loginId) {
|
||||||
@@ -163,8 +153,7 @@ export default {
|
|||||||
this.$store.dispatch("RedirectLogin", loginId).then(() => {
|
this.$store.dispatch("RedirectLogin", loginId).then(() => {
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
path: this.redirect || "/"
|
path: this.redirect || "/"
|
||||||
}).catch(() => {
|
}).catch(() => {});
|
||||||
});
|
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
if (this.captchaOnOff) {
|
if (this.captchaOnOff) {
|
||||||
@@ -198,8 +187,7 @@ export default {
|
|||||||
checkErrorMsg() {
|
checkErrorMsg() {
|
||||||
let errorId = this.$route.query.errorId;
|
let errorId = this.$route.query.errorId;
|
||||||
if (errorId !== undefined && errorId !== null) {
|
if (errorId !== undefined && errorId !== null) {
|
||||||
getErrorMsg(errorId).then(res => {
|
getErrorMsg(errorId).then(res => {}).catch(err => {
|
||||||
}).catch(err => {
|
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
query: {}
|
query: {}
|
||||||
})
|
})
|
||||||
@@ -262,8 +250,7 @@ export default {
|
|||||||
this.$store.dispatch("Login", this.loginForm).then(() => {
|
this.$store.dispatch("Login", this.loginForm).then(() => {
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
path: this.redirect || "/"
|
path: this.redirect || "/"
|
||||||
}).catch(() => {
|
}).catch(() => {});
|
||||||
});
|
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
if (this.captchaOnOff) {
|
if (this.captchaOnOff) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="register">
|
<div class="register">
|
||||||
|
|
||||||
<div style="width:520px;padding:20px;">
|
<div style="width:520px;padding:20px;">
|
||||||
<el-row :gutter="10">
|
<el-row :gutter="10">
|
||||||
@@ -10,78 +10,61 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
|
||||||
<el-form ref="registerForm" :model="registerForm" :rules="registerRules" class="register-form"
|
<el-form ref="registerForm" :model="registerForm" :rules="registerRules" class="register-form" style="z-index:1000">
|
||||||
style="z-index:1000">
|
|
||||||
<h3 class="title" v-if="!bindAccount">注册账号</h3>
|
<h3 class="title" v-if="!bindAccount">注册账号</h3>
|
||||||
<h3 class="title" v-else>注册绑定物美智能账户</h3>
|
<h3 class="title" v-else>注册绑定物美智能账户</h3>
|
||||||
<el-form-item prop="username">
|
<el-form-item prop="username">
|
||||||
<el-input v-model="registerForm.username" type="text" auto-complete="off" placeholder="账号">
|
<el-input v-model="registerForm.username" type="text" auto-complete="off" placeholder="账号">
|
||||||
<svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon"/>
|
<svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" />
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="phonenumber">
|
<el-form-item prop="phonenumber">
|
||||||
<el-input v-model="registerForm.phonenumber" type="text" auto-complete="off" placeholder="手机号码">
|
<el-input v-model="registerForm.phonenumber" type="text" auto-complete="off" placeholder="手机号码">
|
||||||
<svg-icon slot="prefix" icon-class="phone" class="el-input__icon input-icon"/>
|
<svg-icon slot="prefix" icon-class="phone" class="el-input__icon input-icon" />
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="password">
|
<el-form-item prop="password">
|
||||||
<el-input v-model="registerForm.password" type="password" auto-complete="off" placeholder="密码"
|
<el-input v-model="registerForm.password" type="password" auto-complete="off" placeholder="密码" @keyup.enter.native="handleRegister">
|
||||||
@keyup.enter.native="handleRegister">
|
<svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" />
|
||||||
<svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon"/>
|
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="confirmPassword">
|
<el-form-item prop="confirmPassword">
|
||||||
<el-input v-model="registerForm.confirmPassword" type="password" auto-complete="off" placeholder="确认密码"
|
<el-input v-model="registerForm.confirmPassword" type="password" auto-complete="off" placeholder="确认密码" @keyup.enter.native="handleRegister">
|
||||||
@keyup.enter.native="handleRegister">
|
<svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" />
|
||||||
<svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon"/>
|
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="code" v-if="captchaOnOff">
|
<el-form-item prop="code" v-if="captchaOnOff">
|
||||||
<el-input v-model="registerForm.code" auto-complete="off" placeholder="验证码" style="width: 63%"
|
<el-input v-model="registerForm.code" auto-complete="off" placeholder="验证码" style="width: 63%" @keyup.enter.native="handleRegister">
|
||||||
@keyup.enter.native="handleRegister">
|
<svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" />
|
||||||
<svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon"/>
|
|
||||||
</el-input>
|
</el-input>
|
||||||
<div class="register-code">
|
<div class="register-code">
|
||||||
<img :src="codeUrl" @click="getCode" class="register-code-img"/>
|
<img :src="codeUrl" @click="getCode" class="register-code-img" />
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item style="width:100%;">
|
<el-form-item style="width:100%;">
|
||||||
<el-button v-if="!bindAccount" :loading="loading" size="medium" type="primary" style="width:100%;"
|
<el-button v-if="!bindAccount" :loading="loading" size="medium" type="primary" style="width:100%;" @click.native.prevent="handleRegister">
|
||||||
@click.native.prevent="handleRegister">
|
|
||||||
<span v-if="!loading">注 册</span>
|
<span v-if="!loading">注 册</span>
|
||||||
<span v-else>注 册 中...</span>
|
<span v-else>注 册 中...</span>
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button v-else :loading="loading" size="medium" type="primary" style="width:100%;"
|
<el-button v-else :loading="loading" size="medium" type="primary" style="width:100%;" @click.native.prevent="handleRegister">
|
||||||
@click.native.prevent="handleRegister">
|
|
||||||
<span v-if="!loading">绑 定</span>
|
<span v-if="!loading">绑 定</span>
|
||||||
<span v-else>绑 定 中...</span>
|
<span v-else>绑 定 中...</span>
|
||||||
</el-button>
|
</el-button>
|
||||||
<div style="margin-top:20px;">
|
<div style="margin-top:30px;">
|
||||||
|
<div v-if="!bindAccount" style=" margin-bottom: 10px;text-align: center ;float:left;">
|
||||||
<div v-if="!bindAccount" style=" margin-bottom: 10px;text-align: center ">
|
<span style="color:#fff;margin-right:10px;">第三方登录</span>
|
||||||
<!-- <span style="color:#fff;margin-right:10px; float: left">快速登录</span>-->
|
|
||||||
|
|
||||||
<el-button type="success" circle title="微信登录" size="small" @click="authLogin">
|
<el-button type="success" circle title="微信登录" size="small" @click="authLogin">
|
||||||
<svg-icon icon-class="wechat"/>
|
<svg-icon icon-class="wechat" />
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
<el-button type="danger" circle title="QQ登录" size="small" @click="qqLogin">
|
<el-button type="danger" circle title="QQ登录" size="small" @click="qqLogin">
|
||||||
<svg-icon icon-class="qq"/>
|
<svg-icon icon-class="qq" />
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="primary" circle title="支付宝登录" size="small" @click="authLogin">
|
<el-button type="primary" circle title="支付宝登录" size="small" @click="authLogin">
|
||||||
<svg-icon icon-class="zhifubao"/>
|
<svg-icon icon-class="zhifubao" />
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<router-link style="float:left;color:#fff;font-size:16px;"
|
<router-link style="float:right;color:#333;font-size:16px;" :to='{path:"/login",query: this.$route.query }'>已有账户登录 >>
|
||||||
:to='{path:"/login",query: this.$route.query }'>使用已有账户登录 >>
|
|
||||||
</router-link>
|
</router-link>
|
||||||
|
|
||||||
<div style="float: right">
|
|
||||||
<a style="margin-right:20px;" target="_blank" href="http://wumei.live">返回官网</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
@@ -91,15 +74,16 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- 底部 -->
|
<!-- 底部 -->
|
||||||
<div class="el-register-footer">
|
<div class="el-register-footer">
|
||||||
<span>Copyright © 2018-2021 <a target="_blank"
|
<span>Copyright © 2018-2021 <a target="_blank" href="http://wumei.live">wumei smart</a> All Rights Reserved.</span>
|
||||||
href="http://wumei.live">wumei smart</a> All Rights Reserved.</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
getCodeImg, checkBindId, bindRegister
|
getCodeImg,
|
||||||
|
checkBindId,
|
||||||
|
bindRegister
|
||||||
} from "@/api/login";
|
} from "@/api/login";
|
||||||
import {
|
import {
|
||||||
register
|
register
|
||||||
@@ -269,8 +253,7 @@ export default {
|
|||||||
type: 'success'
|
type: 'success'
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.$router.push("/login");
|
this.$router.push("/login");
|
||||||
}).catch(() => {
|
}).catch(() => {});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user