mirror of
https://gitee.com/beecue/fastbee.git
synced 2025-12-17 08:25:53 +08:00
Merge branch 'master' into json_social_login
This commit is contained in:
38
README.md
38
README.md
@@ -6,13 +6,14 @@
|
||||
#### 2. 设备接入使用EMQX消息服务器,加密认证;后端采用Spring boot;前端采用Vue;移动端采用Uniapp;数据库采用Mysql和Redis;设备端支持ESP32、ESP8266、树莓派等;系统架构图如下:
|
||||
<img src="https://oscimg.oschina.net/oscnet/up-98eefff896394066a60d664b875a3d05d1d.png" max-width="800" />
|
||||
|
||||
#### 3. 案例展示
|
||||
| Wifi通断器 | 信息牌 | 桌面小电视 | 雾霾/粉尘/空气检测仪
|
||||
| :---- | :---------- |:---------- |:---------- |
|
||||
|  |  |  | 
|
||||
| 【小驿物联】<br /> 1. 手机、电脑远程控制<br /> 2. 遥控配对、清码和控制<br /> 3. 空气温湿度实时监测<br />4. 雷达感应和报警<br /> 5. 供电电压220V和5V<br /> 6. 控制阻性负载2500W,感性负载250W家用设备开关。 | 【更多设备等您加入】<br />待定 | 【更多设备等您加入】<br />待定 | 【小驿物联】<br />1. PM2.5雾霾监测<br />2. PM10粉尘监测<br /> 3. 空气质量监测 <br />4. TFT彩色屏幕
|
||||
#### 3. 项目可用于个人学习和使用,商业用途需要赞助项目,获得授权。[查看详情 >>](https://gitee.com/kerwincui/wumei-smart/blob/master/app/README.md)
|
||||
|
||||
#### 4. 案例展示
|
||||
| Wifi通断器 | 信息牌 | 桌面小电视 | 雾霾/粉尘/空气检测仪
|
||||
| :----: | :----------: |:----------: |:----------: |
|
||||
|  |  |  | 
|
||||
| 【小驿物联】 | 待定 | 待定 | 【小驿物联】
|
||||
|
||||
#### 4. 项目可用于个人学习和使用,商业用途需要赞助项目,获得授权。[查看详情 >>](https://gitee.com/kerwincui/wumei-smart/blob/master/app/README.md)
|
||||
|
||||
|
||||
### 二、功能
|
||||
@@ -20,16 +21,11 @@
|
||||
- 系统监控: 操作日志、登录日志、系统日志、在线用户、服务监控、连接池监控、缓存监控等
|
||||
- 产品管理: 产品、产品物模型、产品分类、产品固件、授权码等
|
||||
- 设备管理: 控制、分组、定时、日志、统计、定位、OTA升级、影子模式、实时监测、加密认证等
|
||||
- EMQ管理: Mqtt客户端、监听器、消息主题、消息订阅、插件管理
|
||||
- EMQ管理: Mqtt客户端、监听器、消息主题、消息订阅、插件管理、规则引擎、资源
|
||||
- 硬件 SDK: 支持WIFI和MQTT连接、物模型响应、实时监测、定时上报监测数据、AES加密、NTP时间等
|
||||
- 物模型管理: 属性(设备状态和监测数据),功能(执行特定任务),事件(设备主动上报给云端)
|
||||
- 其他(开发中):第三方登录,设备分享、设备告警、场景联动(进度50%),智能音箱、多租户、APP界面自定义(进度40%),时序数据库、分布式集群部署、Granfa监控(进度30%),视频流处理、桌面端模拟器/监控、安卓端模拟器/监控(进度20%),App和小程序(正在开发中......)
|
||||
|
||||
### 三、计划开发功能
|
||||
- 设备分享、设备告警、场景联动(进度50%)
|
||||
- 智能音箱、多租户、APP界面自定义(进度40%)
|
||||
- 时序数据库、分布式集群部署、Granfa监控(进度30%)
|
||||
- 视频流处理、桌面端模拟器/监控、安卓端模拟器/监控(进度0%)
|
||||
- App和小程序(正在开发中......)
|
||||
|
||||
### 四、技术栈
|
||||
* 服务端
|
||||
@@ -44,12 +40,6 @@
|
||||
* 硬件端
|
||||
- 相关技术: ESP-IDF、Arduino、FreeRTOS等
|
||||
- 开发工具:Visual Studio Code 和 Arduino
|
||||
* 安卓端模拟器/监控
|
||||
- 相关技术:android
|
||||
- 开发工具:Android Studio
|
||||
* 电脑端模拟器/监控
|
||||
- 相关技术:WPF
|
||||
- 开发工具:Visual Studio
|
||||
|
||||
### 五、硬件接入
|
||||
1. 设备认证
|
||||
@@ -72,9 +62,9 @@
|
||||
app ----------------------- [获取App源码](https://gitee.com/kerwincui/wumei-smart/tree/master/app)<br />
|
||||
|
||||
###### 移动端适配多端
|
||||
|安卓|IOS|微信小程序|支付宝小程序|百度小程序|字节小程序|QQ小程序|快应用|
|
||||
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
|
||||
|√|√|√|未测试|未测试|未测试|未测试|未测试|
|
||||
|安卓|IOS|微信小程序|其他平台|
|
||||
| :---: | :---: | :---: | :---: |
|
||||
|√|√|√|未测试|
|
||||
|
||||
|
||||
### 七、相关文档
|
||||
@@ -109,8 +99,8 @@ kerwincui/wumei-smart:1.1
|
||||
* [演示地址>>](https://iot.wumei.live/)
|
||||
|
||||
##### 项目贡献者
|
||||
|[小驿物联](https://gitee.com/iot-xiaoyi) |[guanshubiao](https://gitee.com/guanshubiao)|[crazyDull](https://gitee.com/crazyDull) |[kami0314](https://github.com/kami0314)| [sxh](https://gitee.com/sixiaohu) | [redamancy_zxp](https://gitee.com/redamancy-zxp)
|
||||
|--|--|--|--|--|--|
|
||||
|[小驿物联](https://gitee.com/iot-xiaoyi) |[guanshubiao](https://gitee.com/guanshubiao)|[crazyDull](https://gitee.com/crazyDull) |[kami0314](https://github.com/kami0314)| [sxh](https://gitee.com/sixiaohu) | [redamancy_zxp](https://gitee.com/redamancy-zxp) | [LEE](https://gitee.com/yueming188)
|
||||
|--|--|--|--|--|--|--|
|
||||
|
||||
|
||||
### 九、部分图片
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
Target Server Version : 50734
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 17/04/2022 00:41:41
|
||||
Date: 22/04/2022 01:33:54
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
@@ -161,7 +161,7 @@ CREATE TABLE `QRTZ_SCHEDULER_STATE` (
|
||||
-- ----------------------------
|
||||
-- Records of QRTZ_SCHEDULER_STATE
|
||||
-- ----------------------------
|
||||
INSERT INTO `QRTZ_SCHEDULER_STATE` VALUES ('RuoyiScheduler', 'DESKTOP-KKH3KAT1650125174799', 1650127309379, 15000);
|
||||
INSERT INTO `QRTZ_SCHEDULER_STATE` VALUES ('RuoyiScheduler', 'DESKTOP-KKH3KAT1650559591596', 1650562435320, 15000);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for QRTZ_SIMPLE_TRIGGERS
|
||||
@@ -238,7 +238,7 @@ CREATE TABLE `QRTZ_TRIGGERS` (
|
||||
-- ----------------------------
|
||||
-- Records of QRTZ_TRIGGERS
|
||||
-- ----------------------------
|
||||
INSERT INTO `QRTZ_TRIGGERS` VALUES ('RuoyiScheduler', 'TASK_CLASS_NAME1', 'DEFAULT', 'TASK_CLASS_NAME1', 'DEFAULT', NULL, 1650162000000, -1, 5, 'WAITING', 'CRON', 1650125184000, 0, NULL, 1, '');
|
||||
INSERT INTO `QRTZ_TRIGGERS` VALUES ('RuoyiScheduler', 'TASK_CLASS_NAME1', 'DEFAULT', 'TASK_CLASS_NAME1', 'DEFAULT', NULL, 1650594000000, -1, 5, 'WAITING', 'CRON', 1650559600000, 0, NULL, 1, '');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for gen_table
|
||||
@@ -1023,6 +1023,76 @@ CREATE TABLE `iot_scene` (
|
||||
-- Records of iot_scene
|
||||
-- ----------------------------
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for iot_social_platform
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `iot_social_platform`;
|
||||
CREATE TABLE `iot_social_platform` (
|
||||
`social_platform_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '第三方登录平台主键',
|
||||
`platform` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '第三方登录平台',
|
||||
`status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT ' 0:启用 ,1:禁用',
|
||||
`client_id` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '第三方平台申请Id',
|
||||
`secret_key` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '第三方平台密钥',
|
||||
`redirect_uri` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户认证后跳转地址',
|
||||
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT '删除标记位(0代表存在,1代表删除)',
|
||||
`create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建者',
|
||||
`create_time` datetime(0) NOT NULL COMMENT '创建时间',
|
||||
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
|
||||
`update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新者',
|
||||
`remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
|
||||
`bind_uri` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '绑定注册登录uri,http://localhost/login?bindId=',
|
||||
`redirect_login_uri` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '跳转登录uri,http://localhost/login?loginId=',
|
||||
`error_msg_uri` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '错误提示uri,http://localhost/login?errorId=',
|
||||
PRIMARY KEY (`social_platform_id`) USING BTREE,
|
||||
UNIQUE INDEX `iot_social_platform_platform_uindex`(`platform`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '第三方登录平台控制' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of iot_social_platform
|
||||
-- ----------------------------
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for iot_social_user
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `iot_social_user`;
|
||||
CREATE TABLE `iot_social_user` (
|
||||
`social_user_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '第三方系统用户表主键',
|
||||
`uuid` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '第三方系统的唯一ID',
|
||||
`source` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '第三方用户来源',
|
||||
`access_token` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户的授权令牌',
|
||||
`expire_in` int(11) NULL DEFAULT NULL COMMENT '第三方用户的授权令牌的有效期(部分平台可能没有)',
|
||||
`refresh_token` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '刷新令牌(部分平台可能没有)',
|
||||
`open_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '第三方用户的 open id(部分平台可能没有)',
|
||||
`uid` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '第三方用户的 ID(部分平台可能没有)',
|
||||
`access_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '个别平台的授权信息(部分平台可能没有)',
|
||||
`union_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '第三方用户的 union id(部分平台可能没有)',
|
||||
`scope` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '第三方用户授予的权限(部分平台可能没有)',
|
||||
`token_type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '个别平台的授权信息(部分平台可能没有)',
|
||||
`id_token` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'id token(部分平台可能没有)',
|
||||
`mac_algorithm` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '小米平台用户的附带属性(部分平台可能没有)',
|
||||
`mac_key` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '小米平台用户的附带属性(部分平台可能没有)',
|
||||
`code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户的授权code(部分平台可能没有)',
|
||||
`oauth_token` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'Twitter平台用户的附带属性(部分平台可能没有)',
|
||||
`oauth_token_secret` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'Twitter平台用户的附带属性(部分平台可能没有)',
|
||||
`create_time` datetime(0) NOT NULL COMMENT '创建时间',
|
||||
`create_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建者',
|
||||
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
|
||||
`update_by` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新者',
|
||||
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT '删除标记位(0代表存在,2代表删除)',
|
||||
`status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT '绑定状态(0:未绑定,1:绑定)',
|
||||
`sys_user_id` int(11) NULL DEFAULT NULL COMMENT '用户ID',
|
||||
`username` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户名',
|
||||
`nickname` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户昵称',
|
||||
`avatar` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户头像',
|
||||
`gender` tinyint(4) NULL DEFAULT NULL COMMENT '用户性别',
|
||||
UNIQUE INDEX `iot_social_user_pk`(`social_user_id`) USING BTREE,
|
||||
UNIQUE INDEX `iot_social_user_unique_key`(`uuid`, `source`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of iot_social_user
|
||||
-- ----------------------------
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for iot_things_model
|
||||
-- ----------------------------
|
||||
@@ -1087,7 +1157,7 @@ CREATE TABLE `iot_things_model_template` (
|
||||
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
|
||||
`remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注',
|
||||
PRIMARY KEY (`template_id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 18 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '物模型模板' ROW_FORMAT = Dynamic;
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 21 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '物模型模板' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of iot_things_model_template
|
||||
@@ -1562,12 +1632,11 @@ CREATE TABLE `sys_logininfor` (
|
||||
`msg` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '提示消息',
|
||||
`login_time` datetime(0) NULL DEFAULT NULL COMMENT '访问时间',
|
||||
PRIMARY KEY (`info_id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 109 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统访问记录' ROW_FORMAT = Dynamic;
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 111 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统访问记录' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of sys_logininfor
|
||||
-- ----------------------------
|
||||
INSERT INTO `sys_logininfor` VALUES (108, 'admin', '127.0.0.1', '内网IP', 'Chrome 10', 'Windows 10', '0', '退出成功', '2022-04-17 00:40:43');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for sys_menu
|
||||
@@ -1810,7 +1879,7 @@ CREATE TABLE `sys_oper_log` (
|
||||
`error_msg` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '错误消息',
|
||||
`oper_time` datetime(0) NULL DEFAULT NULL COMMENT '操作时间',
|
||||
PRIMARY KEY (`oper_id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 226 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '操作日志记录' ROW_FORMAT = Dynamic;
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 234 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '操作日志记录' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of sys_oper_log
|
||||
@@ -2186,12 +2255,8 @@ CREATE TABLE `sys_user` (
|
||||
-- ----------------------------
|
||||
-- Records of sys_user
|
||||
-- ----------------------------
|
||||
INSERT INTO `sys_user` VALUES (1, 103, 'admin', '物美智能管理员', '00', '164770707@qq.com', '15888888888', '0', '', '$2a$10$0Duw0QB6s7YnQEaNSdSVWeXHMmSa090pG15ZXpf.CQEzEhgxyr7IO', '0', '0', '127.0.0.1', '2022-04-16 22:36:03', 'admin', '2021-12-15 21:36:18', '', '2022-04-16 22:36:03', '管理员');
|
||||
INSERT INTO `sys_user` VALUES (2, 100, 'wumei-tenant', '物美智能租户', '00', '15666666@qq.com', '15666666666', '0', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '2', '27.23.210.211', '2022-01-15 21:00:33', 'admin', '2021-12-15 21:36:18', 'admin', '2022-03-09 17:04:33', '租户');
|
||||
INSERT INTO `sys_user` VALUES (3, 100, 'common', '普通用户', '00', '', '', '0', '', '$2a$10$kKeZptrTnSlm0fencX4U2eq.QiaukDs.DckiUsMCwVTxh0IS2LRQ.', '0', '2', '127.0.0.1', '2022-04-10 15:10:47', 'admin', '2022-03-09 16:49:19', 'admin', '2022-04-10 15:10:47', '普通用户');
|
||||
INSERT INTO `sys_user` VALUES (1, 103, 'admin', '物美智能管理员', '00', '164770707@qq.com', '15888888888', '0', '', '$2a$10$0Duw0QB6s7YnQEaNSdSVWeXHMmSa090pG15ZXpf.CQEzEhgxyr7IO', '0', '0', '127.0.0.1', '2022-04-22 00:50:41', 'admin', '2021-12-15 21:36:18', '', '2022-04-22 00:50:41', '管理员');
|
||||
INSERT INTO `sys_user` VALUES (118, 100, 'wumei', '游客账号', '00', '', '', '0', '', '$2a$10$kKeZptrTnSlm0fencX4U2eq.QiaukDs.DckiUsMCwVTxh0IS2LRQ.', '0', '0', '127.0.0.1', '2022-03-15 23:25:38', 'admin', '2022-03-09 16:49:19', 'admin', '2022-03-15 23:25:38', NULL);
|
||||
INSERT INTO `sys_user` VALUES (119, 100, 'wumei-user', '物美-用户A', '00', '', '', '0', '', '$2a$10$bkep9sszOTEgVPSZWx7P1ONPPC8dMvYY9ujFF7dJTrFVXfKZYdRBO', '0', '2', '', NULL, 'admin', '2022-04-15 14:09:00', 'admin', '2022-04-15 14:09:16', NULL);
|
||||
INSERT INTO `sys_user` VALUES (120, NULL, 'wumei-one', 'wumei-one', '00', '', 'wumei-one', '0', '', '$2a$10$lWyuVQQlP3TDSm1nqsW1V.KBbFX57jk3b9NlOtBE/.F2oTVWjqYrO', '0', '2', '127.0.0.1', '2022-04-15 14:12:41', '', '2022-04-15 14:12:24', '', '2022-04-15 14:12:40', NULL);
|
||||
INSERT INTO `sys_user` VALUES (121, 100, 'wumei-tenant-one', '物美租户壹', '00', '', '15888888880', '0', '', '$2a$10$BAWId9C2Nrcwklzl1Ikoau4iqL8XRGvfRjq6Wl.PXWpzwAw0sXMdK', '0', '0', '127.0.0.1', '2022-04-16 12:37:50', 'admin', '2022-04-15 16:21:25', '', '2022-04-16 12:37:49', NULL);
|
||||
INSERT INTO `sys_user` VALUES (122, 100, 'wumei-tenant-two', '物美租户贰', '00', '', '15988888880', '0', '', '$2a$10$1zMlbW7hGpzA59gpzWGO/ObeASziQ296evjMjHrYdZnxKBLU4WUum', '0', '0', '127.0.0.1', '2022-04-16 12:48:57', 'admin', '2022-04-15 16:22:08', '', '2022-04-16 12:48:57', NULL);
|
||||
INSERT INTO `sys_user` VALUES (123, 100, 'wumei-user-one', '物美用户壹', '00', '', '13988888880', '0', '', '$2a$10$691RJMXZ9HM4sgNTExLPfO5Nw6J6cWgCvcoF9V.jKMnPk5o/8c9VS', '0', '0', '127.0.0.1', '2022-04-16 12:42:29', 'admin', '2022-04-15 16:22:37', 'admin', '2022-04-16 12:42:29', NULL);
|
||||
|
||||
@@ -1,58 +1,57 @@
|
||||
# 数据源配置
|
||||
spring:
|
||||
datasource:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
druid:
|
||||
# 主库数据源
|
||||
master:
|
||||
url: jdbc:mysql://localhost/wumei-smart?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
username: root
|
||||
password: wumei-smart
|
||||
# password: 123456
|
||||
# 从库数据源
|
||||
slave:
|
||||
# 从数据源开关/默认关闭
|
||||
enabled: false
|
||||
url:
|
||||
username:
|
||||
password:
|
||||
# 初始连接数
|
||||
initialSize: 5
|
||||
# 最小连接池数量
|
||||
minIdle: 10
|
||||
# 最大连接池数量
|
||||
maxActive: 20
|
||||
# 配置获取连接等待超时的时间
|
||||
maxWait: 60000
|
||||
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
|
||||
timeBetweenEvictionRunsMillis: 60000
|
||||
# 配置一个连接在池中最小生存的时间,单位是毫秒
|
||||
minEvictableIdleTimeMillis: 300000
|
||||
# 配置一个连接在池中最大生存的时间,单位是毫秒
|
||||
maxEvictableIdleTimeMillis: 900000
|
||||
# 配置检测连接是否有效
|
||||
validationQuery: SELECT 1 FROM DUAL
|
||||
testWhileIdle: true
|
||||
testOnBorrow: false
|
||||
testOnReturn: false
|
||||
webStatFilter:
|
||||
enabled: true
|
||||
statViewServlet:
|
||||
enabled: true
|
||||
# 设置白名单,不填则允许所有访问
|
||||
allow:
|
||||
url-pattern: /druid/*
|
||||
# 控制台管理用户名和密码
|
||||
login-username: wumei-smart
|
||||
login-password: wumei-smart
|
||||
filter:
|
||||
stat:
|
||||
enabled: true
|
||||
# 慢SQL记录
|
||||
log-slow-sql: true
|
||||
slow-sql-millis: 1000
|
||||
merge-sql: true
|
||||
wall:
|
||||
config:
|
||||
multi-statement-allow: true
|
||||
datasource:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
druid:
|
||||
# 主库数据源
|
||||
master:
|
||||
url: jdbc:mysql://localhost/wumei-smart?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
username: root
|
||||
password: admin
|
||||
# 从库数据源
|
||||
slave:
|
||||
# 从数据源开关/默认关闭
|
||||
enabled: false
|
||||
url:
|
||||
username:
|
||||
password:
|
||||
# 初始连接数
|
||||
initialSize: 5
|
||||
# 最小连接池数量
|
||||
minIdle: 10
|
||||
# 最大连接池数量
|
||||
maxActive: 20
|
||||
# 配置获取连接等待超时的时间
|
||||
maxWait: 60000
|
||||
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
|
||||
timeBetweenEvictionRunsMillis: 60000
|
||||
# 配置一个连接在池中最小生存的时间,单位是毫秒
|
||||
minEvictableIdleTimeMillis: 300000
|
||||
# 配置一个连接在池中最大生存的时间,单位是毫秒
|
||||
maxEvictableIdleTimeMillis: 900000
|
||||
# 配置检测连接是否有效
|
||||
validationQuery: SELECT 1 FROM DUAL
|
||||
testWhileIdle: true
|
||||
testOnBorrow: false
|
||||
testOnReturn: false
|
||||
webStatFilter:
|
||||
enabled: true
|
||||
statViewServlet:
|
||||
enabled: true
|
||||
# 设置白名单,不填则允许所有访问
|
||||
allow:
|
||||
url-pattern: /druid/*
|
||||
# 控制台管理用户名和密码
|
||||
login-username: wumei-smart
|
||||
login-password: wumei-smart
|
||||
filter:
|
||||
stat:
|
||||
enabled: true
|
||||
# 慢SQL记录
|
||||
log-slow-sql: true
|
||||
slow-sql-millis: 1000
|
||||
merge-sql: true
|
||||
wall:
|
||||
config:
|
||||
multi-statement-allow: true
|
||||
|
||||
@@ -48,9 +48,9 @@ spring:
|
||||
servlet:
|
||||
multipart:
|
||||
# 单个文件大小
|
||||
max-file-size: 10MB
|
||||
max-file-size: 10MB
|
||||
# 设置总上传的文件大小
|
||||
max-request-size: 20MB
|
||||
max-request-size: 20MB
|
||||
# 服务模块
|
||||
devtools:
|
||||
restart:
|
||||
@@ -65,8 +65,7 @@ spring:
|
||||
# 数据库索引
|
||||
database: 0
|
||||
# 密码
|
||||
# password: wumei-smart
|
||||
# password: 123456
|
||||
password: wumei-smart
|
||||
# 连接超时时间
|
||||
timeout: 10s
|
||||
lettuce:
|
||||
@@ -83,7 +82,7 @@ spring:
|
||||
mqtt:
|
||||
username: wumei-smart # 账号
|
||||
password: wumei-smart # 密码
|
||||
host-url: tcp://localhost:1883 # mqtt连接tcp地址
|
||||
host-url: tcp://localhost:1883 # mqtt连接tcp地址
|
||||
client-id: ${random.int} # 客户端Id,不能相同,采用随机数 ${random.value}
|
||||
default-topic: test # 默认主题
|
||||
timeout: 30000 # 超时时间
|
||||
@@ -134,4 +133,4 @@ xss:
|
||||
# 排除链接(多个用逗号分隔)
|
||||
excludes: /system/notice
|
||||
# 匹配链接
|
||||
urlPatterns: /system/*,/monitor/*,/tool/*
|
||||
urlPatterns: /system/*,/monitor/*,/tool/*
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
"@riophae/vue-treeselect": "0.4.0",
|
||||
"axios": "0.24.0",
|
||||
"clipboard": "2.0.6",
|
||||
"codemirror": "^5.65.2",
|
||||
"core-js": "3.19.1",
|
||||
"echarts": "^5.3.1",
|
||||
"element-ui": "2.15.6",
|
||||
@@ -48,13 +49,19 @@
|
||||
"js-beautify": "1.13.0",
|
||||
"js-cookie": "3.0.1",
|
||||
"jsencrypt": "3.2.1",
|
||||
"jshint": "^2.13.4",
|
||||
"jsonlint": "^1.6.3",
|
||||
"less-loader": "^10.2.0",
|
||||
"mqtt": "^4.3.3",
|
||||
"nprogress": "0.2.0",
|
||||
"quill": "^1.3.7",
|
||||
"screenfull": "5.0.2",
|
||||
"script-loader": "^0.7.2",
|
||||
"sortablejs": "1.10.2",
|
||||
"sql-formatter": "^4.0.2",
|
||||
"vue": "2.6.12",
|
||||
"vue-clipboard2": "^0.3.3",
|
||||
"vue-codemirror": "^4.0.6",
|
||||
"vue-count-to": "1.0.13",
|
||||
"vue-cropper": "0.5.5",
|
||||
"vue-json-viewer": "^2.2.21",
|
||||
|
||||
@@ -122,3 +122,257 @@ export function getMqttStats() {
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
//断开客户端连接
|
||||
export function eliminateClient(clientId){
|
||||
var url = "/api/v4/clients/"+clientId;
|
||||
return axios({
|
||||
method: 'delete',
|
||||
url: url,
|
||||
auth: {
|
||||
username: username,
|
||||
password: password
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
//查看客户端详情
|
||||
export function getClientDetails(clientId){
|
||||
var url = "/api/v4/clients/"+clientId;
|
||||
return axios({
|
||||
method: 'get',
|
||||
url: url,
|
||||
auth: {
|
||||
username: username,
|
||||
password: password
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
//查看集群下指定客户端的订阅信息
|
||||
export function getSubscriptionsByClientId(clientId){
|
||||
var url = "/api/v4/subscriptions/"+clientId;
|
||||
return axios({
|
||||
method: 'get',
|
||||
url: url,
|
||||
auth: {
|
||||
username: username,
|
||||
password: password
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
//取消该客户端订阅
|
||||
export function unsubscribe(query){
|
||||
var url = "/api/v4/mqtt/unsubscribe";
|
||||
return axios({
|
||||
method: 'post',
|
||||
url: url,
|
||||
auth: {
|
||||
username: username,
|
||||
password: password
|
||||
},
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
//添加该客户端订阅
|
||||
export function addSubscribe(query){
|
||||
var url = "/api/v4/mqtt/subscribe";
|
||||
return axios({
|
||||
method: 'post',
|
||||
url: url,
|
||||
auth: {
|
||||
username: username,
|
||||
password: password
|
||||
},
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
//获取所有规则引擎的动作
|
||||
export function getRules(ruleid){
|
||||
let url = "";
|
||||
if(typeof(ruleid) == 'undefined' || ruleid == '' ||ruleid == null){
|
||||
url = "/api/v4/rules";
|
||||
}else{
|
||||
url = "/api/v4/rules/"+ruleid;
|
||||
}
|
||||
return axios({
|
||||
method: 'get',
|
||||
url: url,
|
||||
auth: {
|
||||
username: username,
|
||||
password: password
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//删除规则
|
||||
export function deleteRule(ruleid){
|
||||
var url = "/api/v4/rules/"+ruleid;
|
||||
return axios({
|
||||
method: 'delete',
|
||||
url: url,
|
||||
auth: {
|
||||
username: username,
|
||||
password: password
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//获取资源列表或详情
|
||||
export function getResources(resourceid){
|
||||
let url = "";
|
||||
if(typeof(resourceid) == 'undefined' || resourceid == '' ||resourceid == null){
|
||||
url = "/api/v4/resources";
|
||||
}else{
|
||||
url = "/api/v4/resources/"+resourceid;
|
||||
}
|
||||
return axios({
|
||||
method: 'get',
|
||||
url: url,
|
||||
auth: {
|
||||
username: username,
|
||||
password: password
|
||||
},
|
||||
})
|
||||
}
|
||||
//获取资源状态
|
||||
export function getResourcesStatus(resourceid){
|
||||
let url = "/api/v4/resources/"+resourceid;
|
||||
return axios({
|
||||
method: 'get',
|
||||
url: url,
|
||||
auth: {
|
||||
username: username,
|
||||
password: password
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
//连接资源
|
||||
export function getConnectResource(resourceid){
|
||||
let url = "/api/v4/resources/"+resourceid;
|
||||
return axios({
|
||||
method: 'post',
|
||||
url: url,
|
||||
auth: {
|
||||
username: username,
|
||||
password: password
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
//删除资源
|
||||
export function deleteResource(resourceid){
|
||||
let url = "/api/v4/resources/"+resourceid;
|
||||
return axios({
|
||||
method: 'delete',
|
||||
url: url,
|
||||
auth: {
|
||||
username: username,
|
||||
password: password
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//获取资源类型
|
||||
export function getResourcesType(){
|
||||
let url = "/api/v4/resource_types";
|
||||
return axios({
|
||||
method: 'get',
|
||||
url: url,
|
||||
auth: {
|
||||
username: username,
|
||||
password: password
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//资源测试连接
|
||||
export function getResourcesConnect(query){
|
||||
let url = "/api/v4/resources?test=true";
|
||||
return axios({
|
||||
method: 'post',
|
||||
url: url,
|
||||
auth: {
|
||||
username: username,
|
||||
password: password
|
||||
},
|
||||
data: query
|
||||
})
|
||||
}
|
||||
//新增资源
|
||||
export function saveResources(query){
|
||||
let url = "/api/v4/resources";
|
||||
return axios({
|
||||
method: 'post',
|
||||
url: url,
|
||||
auth: {
|
||||
username: username,
|
||||
password: password
|
||||
},
|
||||
data: query
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
//获取规则消息类型
|
||||
export function getRulesEvent(){
|
||||
let url = "/api/v4/rule_events";
|
||||
return axios({
|
||||
method: 'get',
|
||||
url: url,
|
||||
auth: {
|
||||
username: username,
|
||||
password: password
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
//获取响应动作类型
|
||||
export function getActionsEvent(){
|
||||
let url = "/api/v4/actions";
|
||||
return axios({
|
||||
method: 'get',
|
||||
url: url,
|
||||
auth: {
|
||||
username: username,
|
||||
password: password
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//新增规则引擎
|
||||
export function saveRule(query){
|
||||
let url = "/api/v4/rules";
|
||||
return axios({
|
||||
method: 'post',
|
||||
url: url,
|
||||
auth: {
|
||||
username: username,
|
||||
password: password
|
||||
},
|
||||
data: query
|
||||
})
|
||||
}
|
||||
//测试规则引擎
|
||||
export function testConnectRule(query){
|
||||
let url = "/api/v4/rules?test=true";
|
||||
return axios({
|
||||
method: 'post',
|
||||
url: url,
|
||||
auth: {
|
||||
username: username,
|
||||
password: password
|
||||
},
|
||||
data: query
|
||||
})
|
||||
}
|
||||
|
||||
129
vue/src/components/Codemirror/index.vue
Normal file
129
vue/src/components/Codemirror/index.vue
Normal file
@@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<div class="json-editor">
|
||||
<textarea ref="textarea" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import sqlFormatter from "sql-formatter";
|
||||
import CodeMirror from "codemirror";
|
||||
import "codemirror/lib/codemirror.css";
|
||||
import "codemirror/mode/sql/sql.js";
|
||||
// 替换主题这里需修改名称
|
||||
import "codemirror/theme/idea.css";
|
||||
// 支持代码自动补全
|
||||
import "codemirror/addon/hint/show-hint.css";
|
||||
import "codemirror/addon/hint/show-hint.js";
|
||||
import "codemirror/addon/hint/anyword-hint.js";
|
||||
|
||||
// JSON代码高亮需要由JavaScript插件支持
|
||||
import "codemirror/mode/javascript/javascript.js";
|
||||
|
||||
// 支持各种代码折叠
|
||||
import "codemirror/addon/fold/foldgutter.css";
|
||||
import "codemirror/addon/fold/foldcode.js";
|
||||
import "codemirror/addon/fold/foldgutter.js";
|
||||
import "codemirror/addon/fold/brace-fold.js";
|
||||
import "codemirror/addon/fold/comment-fold.js";
|
||||
|
||||
// 支持括号自动匹配
|
||||
import "codemirror/addon/edit/matchbrackets.js";
|
||||
import "codemirror/addon/edit/closebrackets.js";
|
||||
|
||||
// 行注释
|
||||
import "codemirror/addon/comment/comment.js";
|
||||
// JSON错误检查
|
||||
import "codemirror/addon/lint/lint.css";
|
||||
import "codemirror/addon/lint/lint.js";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
value: '',
|
||||
height: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
myMode: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
editor: false,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
value(value) {
|
||||
const editorValue = this.editor.getValue();
|
||||
if (value !== editorValue) {
|
||||
if (typeof this.value !== "undefined") {
|
||||
this.editor.setValue(this.value);
|
||||
} else {
|
||||
this.editor.setValue("");
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.editor = CodeMirror.fromTextArea(this.$refs.textarea, {
|
||||
mode: this.myMode, //语言
|
||||
smartIndent: true, // 是否智能缩进
|
||||
styleActiveLine: true, // 当前行高亮
|
||||
lineNumbers: true, // 是否显示行数
|
||||
indentUnit: 2, // 缩进单位,默认2
|
||||
gutters: [
|
||||
"CodeMirror-linenumbers",
|
||||
"CodeMirror-foldgutter",
|
||||
"CodeMirror-lint-markers", // CodeMirror-lint-markers是实现语法报错功能
|
||||
],
|
||||
lint: true,
|
||||
//lineWrapping: true, // 自动换行
|
||||
matchBrackets: true, // 括号匹配显示
|
||||
autoCloseBrackets: true, // 输入和退格时成对
|
||||
readOnly: false, // 只读
|
||||
foldGutter: true,
|
||||
autoRefresh: true,
|
||||
});
|
||||
//代码自动提示功能,记住使用cursorActivity事件不要使用change事件,这是一个坑,那样页面直接会卡死
|
||||
this.editor.on("inputRead", () => {
|
||||
this.editor.showHint();
|
||||
});
|
||||
debugger;
|
||||
this.editor.setSize("auto", this.height);
|
||||
if (typeof this.value !== "undefined") {
|
||||
this.editor.setValue(this.value);
|
||||
} else {
|
||||
this.editor.setValue("");
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getValue() {
|
||||
return this.editor.getValue();
|
||||
},
|
||||
// formatSql() {
|
||||
// /*(sql编辑器内容绑定content参数) 将sql内容进行格式后放入编辑器中*/
|
||||
// this.content = sqlFormatter.format(this.content);
|
||||
// },
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.json-editor {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.json-editor >>> .CodeMirror {
|
||||
font-size: 14px;
|
||||
/* overflow-y:auto; */
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.json-editor >>> .CodeMirror-scroll {
|
||||
}
|
||||
|
||||
.json-editor >>> .cm-s-rubyblue span.cm-string {
|
||||
color: #f08047;
|
||||
}
|
||||
</style>
|
||||
@@ -40,6 +40,10 @@ import echarts from 'echarts'
|
||||
// 一键复制粘贴板组件
|
||||
import VueClipboard from 'vue-clipboard2'
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 全局方法挂载
|
||||
Vue.prototype.getDicts = getDicts
|
||||
Vue.prototype.getConfigKey = getConfigKey
|
||||
@@ -65,6 +69,7 @@ Vue.use(plugins)
|
||||
Vue.use(VueMeta)
|
||||
DictData.install()
|
||||
|
||||
|
||||
/**
|
||||
* If you don't want to use mock-server
|
||||
* you want to use MockJs for mock api
|
||||
|
||||
@@ -31,8 +31,6 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 设备信息
|
||||
deviceInfo: {},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
@@ -47,11 +45,11 @@ export default {
|
||||
cleanSession: false,
|
||||
keepAlive: 30,
|
||||
clientId: 'web-' + Math.random().toString(16).substr(2),
|
||||
connectTimeout: 60000
|
||||
connectTimeout: 10000
|
||||
}
|
||||
// 配置Mqtt地址
|
||||
//let url = "wss://iot.wumei.live/mqtt"
|
||||
let url = "ws://" + window.location.hostname + ":8083/mqtt";
|
||||
let url = "wss://iot.wumei.live/mqtt"
|
||||
// let url = "ws://" + window.location.hostname + ":8083/mqtt";
|
||||
console.log("mqtt地址:", url);
|
||||
this.client = mqtt.connect(url, options);
|
||||
this.client.on("connect", (e) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div style="padding: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;">
|
||||
<div style="padding: 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-item label="客户端" prop="categoryName">
|
||||
<el-input v-model="queryParams.categoryName" placeholder="请输入客户端ID" clearable size="small" @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
@@ -12,21 +12,21 @@
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<el-card style="padding-bottom:100px;">
|
||||
<el-card style="padding-bottom: 100px">
|
||||
<el-table v-loading="loading" :data="clientList">
|
||||
<el-table-column label="客户端ID" align="left" header-align="center" prop="clientid">
|
||||
<template slot-scope="scope">
|
||||
<el-link :underline="false" type="primary">{{scope.row.clientid}}</el-link>
|
||||
<el-link :underline="false" type="primary" @click.native="handleOpen(scope.row)">{{ scope.row.clientid }}</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="节点" align="center" prop="node" width="120" />
|
||||
<el-table-column label="IP地址" align="center" prop="ip_address" />
|
||||
<el-table-column label="类型" align="center" prop="type">
|
||||
<template slot-scope="scope">
|
||||
<el-tag type="danger" v-if="scope.row.clientid.indexOf('server')==0">服务端</el-tag>
|
||||
<el-tag type="success" v-else-if="scope.row.clientid.indexOf('web')==0">Web端</el-tag>
|
||||
<el-tag type="warning" v-else-if="scope.row.clientid.indexOf('phone')==0">移动端</el-tag>
|
||||
<el-tag type="info" v-else-if="scope.row.clientid.indexOf('test')==0">测试端</el-tag>
|
||||
<el-tag type="danger" v-if="scope.row.clientid.indexOf('server') == 0">服务端</el-tag>
|
||||
<el-tag type="success" v-else-if="scope.row.clientid.indexOf('web') == 0">Web端</el-tag>
|
||||
<el-tag type="warning" v-else-if="scope.row.clientid.indexOf('phone') == 0">移动端</el-tag>
|
||||
<el-tag type="info" v-else-if="scope.row.clientid.indexOf('test') == 0">测试端</el-tag>
|
||||
<el-tag type="primary" v-else>设备端</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -43,46 +43,137 @@
|
||||
<el-table-column label="会话创建时间" align="center" prop="created_at" />
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="150">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="small" type="danger" v-if="scope.row.connected" style="padding:5px;" v-hasPermi="['monitor:online:edit']">
|
||||
<el-button size="small" type="danger" v-if="scope.row.connected" style="padding: 5px" v-hasPermi="['monitor:client:edit']" @click="handleDelete(scope.row)">
|
||||
<svg-icon icon-class="disconnect" /> 断开连接
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<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" />
|
||||
|
||||
<!-- 添加或修改产品分类对话框 -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" label-width="80px">
|
||||
<el-form-item label="分类名称" prop="categoryName">
|
||||
<el-input v-model="form.categoryName" placeholder="请输入产品分类名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="显示顺序" prop="orderNum">
|
||||
<el-input v-model="form.orderNum" placeholder="请输入显示顺序" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="cancel">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
<!-- MQTT客户端详细 -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="50%" append-to-body>
|
||||
<el-tabs v-model="activeName" tab-position="top" style="padding: 10px">
|
||||
<el-tab-pane name="basic">
|
||||
<span slot="label">基本信息</span>
|
||||
<el-form ref="form" :model="form" label-width="120px" size="mini">
|
||||
|
||||
<el-descriptions class="margin-top" title="基本信息" :column="4" direction="vertical">
|
||||
<el-descriptions-item label="节点">{{form.node }}</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="会话过期间隔(秒)">{{form.expiry_interval}}</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.created_at}}</el-descriptions-item>
|
||||
<el-descriptions-item label="订阅数量">{{ form.subscriptions_cnt }}/{{form.max_subscriptions}}</el-descriptions-item>
|
||||
<el-descriptions-item label="IP地址">{{form.ip_address}}</el-descriptions-item>
|
||||
<el-descriptions-item label="端口">{{form.port}}</el-descriptions-item>
|
||||
<el-descriptions-item label="最大订阅数量">{{form.max_subscriptions}}</el-descriptions-item>
|
||||
<el-descriptions-item label="飞行窗口">{{ form.inflight }}/{{ form.max_inflight }}</el-descriptions-item>
|
||||
<el-descriptions-item label="心跳(秒)">{{form.keepalive}}</el-descriptions-item>
|
||||
<el-descriptions-item label="是否为桥接">{{form.is_bridge}}</el-descriptions-item>
|
||||
<el-descriptions-item label="最大飞行窗口">{{form.max_inflight}}</el-descriptions-item>
|
||||
<el-descriptions-item label="消息队列">{{ form.mqueue_len }}/{{ form.max_mqueue }}</el-descriptions-item>
|
||||
<el-descriptions-item label="连接时间">{{form.connected_at}}</el-descriptions-item>
|
||||
<el-descriptions-item label="连接状态">
|
||||
<div v-if="form.connected == true" style="color: green">
|
||||
已连接
|
||||
</div>
|
||||
<div v-else-if="form.connected == false" style="color: red">
|
||||
已断开
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="最大消息队列">{{form.max_mqueue}}</el-descriptions-item>
|
||||
<el-descriptions-item label="未确认的PUBREC数据包计数">{{form.awaiting_rel}}</el-descriptions-item>
|
||||
<el-descriptions-item label="Zone">{{form.zone}}</el-descriptions-item>
|
||||
<el-descriptions-item label="最大未确认的PUBREC数据包计数">{{form.max_awaiting_rel}}</el-descriptions-item>
|
||||
<el-descriptions-item label="接收的TCP报文数量">{{form.recv_cnt}}</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="接收的MQTT报文数量">{{form.recv_pkt}}</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="发送的字节数量">{{form.send_oct}}</el-descriptions-item>
|
||||
<el-descriptions-item label="发送的MQTT报文数量">{{form.send_pkt}}</el-descriptions-item>
|
||||
|
||||
</el-descriptions>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane name="subscribe">
|
||||
<span slot="label">订阅列表</span>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-refresh" size="mini" @click="handleRefresh" v-hasPermi="['monitor:subscribe:refresh']">刷新</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="success" plain icon="el-icon-plus" size="mini" :disabled="single" @click="handleAdd" v-hasPermi="['monitor:subscribe:add']">添加订阅</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-table v-loading="loadSubscribeing" :data="subscribeList">
|
||||
<el-table-column label="主题" align="center" prop="topic" />
|
||||
<el-table-column label="QoS" align="center" prop="qos" />
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="150">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="small" type="danger" style="padding: 5px" v-hasPermi="['monitor:subscribe:delete']" @click="handleUnsubscribe(scope.row)">
|
||||
<svg-icon icon-class="disconnect" /> 取消订阅
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-dialog>
|
||||
|
||||
</el-card>
|
||||
|
||||
<!-- 添加或修改订阅对话框 -->
|
||||
<el-dialog title="添加订阅" :visible.sync="subscribeOpen" width="800px" append-to-body>
|
||||
<el-form ref="subscribeForm" :model="subscribeForm" :rules="rules" label-width="60px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="主题" prop="topic">
|
||||
<el-input v-model="subscribeForm.topic" placeholder="请输入主题" />
|
||||
</el-form-item>
|
||||
<el-form-item label="Qos" prop="qos">
|
||||
<el-select v-model="subscribeForm.qos" placeholder="请选择消息类型">
|
||||
<el-option key="0" label="0" value="0"></el-option>
|
||||
<el-option key="1" label="1" value="1"></el-option>
|
||||
<el-option key="2" label="2" value="2"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">添 加 订 阅</el-button>
|
||||
<el-button @click="cancelSubscribe">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
listMqttClient
|
||||
} from "@/api/iot/emqx"
|
||||
listMqttClient,
|
||||
eliminateClient,
|
||||
getClientDetails,
|
||||
getSubscriptionsByClientId,
|
||||
unsubscribe,
|
||||
addSubscribe,
|
||||
} from "@/api/iot/emqx";
|
||||
|
||||
export default {
|
||||
name: "Category",
|
||||
data() {
|
||||
return {
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
loadSubscribeing: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
@@ -93,6 +184,8 @@ export default {
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 是否显示添加订阅弹出层
|
||||
subscribeOpen: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
_limit: 10,
|
||||
@@ -100,22 +193,54 @@ export default {
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 选中选项卡
|
||||
activeName: "basic",
|
||||
//订阅列表数据
|
||||
subscribeList: [],
|
||||
//订阅数据
|
||||
subscribe: {
|
||||
topic: "",
|
||||
clientid: "",
|
||||
},
|
||||
//添加订阅表单参数
|
||||
subscribeForm: {
|
||||
qos: "0",
|
||||
},
|
||||
//客户端ID
|
||||
clientid: "",
|
||||
// 表单校验
|
||||
rules: {
|
||||
topic: [{
|
||||
required: true,
|
||||
message: "主题不能为空",
|
||||
trigger: "blur",
|
||||
}, ],
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
|
||||
},
|
||||
methods: {
|
||||
/** 查询客户端列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
listMqttClient(this.queryParams).then(response => {
|
||||
listMqttClient(this.queryParams).then((response) => {
|
||||
this.clientList = response.data.data;
|
||||
this.total = response.data.meta.count;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 查询客户端订阅列表 */
|
||||
getSubscribeList(clientid) {
|
||||
this.clientid = clientid;
|
||||
this.loadSubscribeing = true;
|
||||
getSubscriptionsByClientId(clientid).then((res) => {
|
||||
this.subscribeList = res.data.data;
|
||||
this.loadSubscribeing = false;
|
||||
});
|
||||
},
|
||||
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false;
|
||||
@@ -131,6 +256,76 @@ export default {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
}
|
||||
/** 断开客户端连接 */
|
||||
handleDelete(row) {
|
||||
const clientid = row.clientid;
|
||||
this.$modal
|
||||
.confirm('是否确认删除MQTT客户端编号为"' + clientid + '"的数据项?')
|
||||
.then(function () {
|
||||
return eliminateClient(clientid);
|
||||
})
|
||||
.then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
//取消主题订阅
|
||||
handleUnsubscribe(row) {
|
||||
const clientid = row.clientid;
|
||||
const topic = row.topic;
|
||||
this.$modal
|
||||
.confirm('是否确认取消订阅主题为"' + topic + '"的数据项?')
|
||||
.then(function () {
|
||||
const param = {};
|
||||
param.topic = topic;
|
||||
param.clientid = clientid;
|
||||
return unsubscribe(param);
|
||||
})
|
||||
.then(() => {
|
||||
this.getSubscribeList(clientid);
|
||||
this.$modal.msgSuccess("取消订阅成功");
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
//查看客户端详情
|
||||
handleOpen(row) {
|
||||
const clientid = row.clientid;
|
||||
this.getSubscribeList(clientid);
|
||||
getClientDetails(clientid).then((response) => {
|
||||
this.form = response.data.data[0];
|
||||
this.open = true;
|
||||
this.title = "详情";
|
||||
});
|
||||
},
|
||||
//刷新订阅列表
|
||||
handleRefresh() {
|
||||
this.getSubscribeList(this.clientid);
|
||||
},
|
||||
//添加订阅
|
||||
handleAdd() {
|
||||
this.subscribeOpen = true;
|
||||
},
|
||||
//提交添加订阅表单
|
||||
submitForm() {
|
||||
this.subscribeForm.clientid = this.clientid;
|
||||
console.log(this.subscribeForm);
|
||||
this.$refs["subscribeForm"].validate((valid) => {
|
||||
if (valid) {
|
||||
addSubscribe(this.subscribeForm).then((response) => {
|
||||
this.$modal.msgSuccess("新增订阅成功");
|
||||
this.subscribeOpen = false;
|
||||
this.getSubscribeList(this.clientid);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
cancelSubscribe() {
|
||||
this.subscribeOpen = false;
|
||||
this.resetForm("subscribeForm");
|
||||
//刷新列表
|
||||
this.getSubscribeList(this.clientid);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
867
vue/src/views/iot/emqx/resource.vue
Normal file
867
vue/src/views/iot/emqx/resource.vue
Normal file
@@ -0,0 +1,867 @@
|
||||
<template>
|
||||
<div style="padding: 6px">
|
||||
<el-card style="padding-bottom: 100px">
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="success" plain icon="el-icon-refresh" size="mini" @click="getList" v-hasPermi="['monitor:resource:refresh']">刷新</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="addResource" v-hasPermi="['monitor:resource:add']">新增</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-table v-loading="loading" :data="resourceList">
|
||||
<el-table-column label="ID" align="center" header-align="center" prop="id">
|
||||
<template slot-scope="scope">
|
||||
<el-link :underline="false" type="primary">{{ scope.row.id }}</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="资源类型" align="center" prop="type" />
|
||||
<el-table-column label="备注" align="center" prop="description" />
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="small" type="text" style="padding: 5px" v-hasPermi="['monitor:resource:query']" @click="handleQuery(scope.row)">
|
||||
查看
|
||||
</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>
|
||||
<el-button size="small" type="text" icon="el-icon-delete" style="padding: 5px" v-hasPermi="['monitor:resource:checkStatus']" @click="checkStatus(scope.row)">状态
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<!-- 资源详细 -->
|
||||
<el-dialog title="资源详细" :visible.sync="openView" width="50%" append-to-body>
|
||||
<el-form ref="form" :model="form" label-width="180px" size="mini">
|
||||
<el-card style="padding-bottom: 10px">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>基础信息</span>
|
||||
</div>
|
||||
<el-row>
|
||||
<el-col :span="20">
|
||||
<el-form-item label="ID:">{{ form.id }}</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="20">
|
||||
<el-form-item label="资源类型:">{{ form.type }}</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="20">
|
||||
<el-form-item label="备注:">{{ form.description }}</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
<el-card style="padding-bottom: 10px; margin-top: 10px">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>配置信息</span>
|
||||
</div>
|
||||
<el-row>
|
||||
<el-col :span="20">
|
||||
<el-form-item label="reconnect_interval:">{{ form.config.reconnect_interval}}</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="20">
|
||||
<el-form-item label="pool_size:">{{ form.config.pool_size }}</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="20">
|
||||
<el-form-item label="mountpoint:">{{ form.config.mountpoint}}</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="20">
|
||||
<el-form-item label="disk_cache:">{{ form.config.disk_cache }}</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="20">
|
||||
<el-form-item label="batch_size:">{{ form.config.batch_size }}</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="20">
|
||||
<el-form-item label="address:">{{ form.config.address}}</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="openView = false" type="success">确 认</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 测试重连 -->
|
||||
<el-dialog title="检测状态" :visible.sync="openStatusView" width="40%" append-to-body>
|
||||
<el-form ref="statusForm" :model="statusForm" label-width="180px" size="mini">
|
||||
<el-row>
|
||||
<el-col :span="12" v-if="statusForm.status[0]">
|
||||
{{ 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="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>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 添加资源 -->
|
||||
<el-dialog title="资源管理" :visible.sync="openAddView" width="50%" append-to-body :before-close="cancel">
|
||||
<el-form ref="addResourceForm" :model="addResourceForm" label-width="180px" :rules="rule">
|
||||
<el-card style="padding-bottom: 10px">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>择取资源类型</span>
|
||||
</div>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="资源类型" prop="resource.title">
|
||||
<el-select v-model="addResourceForm.resource.title" @change="selectTitle" placeholder="请选择资源类型">
|
||||
<el-option v-for="(resource, index) in addResourceForm.resource" :key="index" :label="resource.title.zh" :value="resource.name"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item>
|
||||
<el-button type="success" @click="testConnect('addResourceForm')">测试连接</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-form>
|
||||
<el-form ref="EMQXForm" :model="EMQXForm" label-width="180px" :rules="ruleEMQX">
|
||||
<el-card style="padding-bottom: 10px; margin-top: 10px" v-if="EMQXForm.params" v-show="openEMQXView">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>具体信息</span>
|
||||
</div>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="10">
|
||||
<el-form-item prop="params.address.default">
|
||||
<span slot="label">
|
||||
<el-tooltip :content="EMQXForm.params.address.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
EMQ X节点名称:
|
||||
</span>
|
||||
<el-input v-model="EMQXForm.params.address.default" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="params.pool_size.default">
|
||||
<span slot="label">
|
||||
<el-tooltip :content="EMQXForm.params.pool_size.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
连接池大小:
|
||||
</span>
|
||||
<el-input v-model="EMQXForm.params.pool_size.default" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<el-form-item prop="params.mountpoint.default">
|
||||
<span slot="label">
|
||||
<el-tooltip :content="EMQXForm.params.mountpoint.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
桥接挂载点:
|
||||
</span>
|
||||
<el-input v-model="EMQXForm.params.mountpoint.default" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="EMQreconnect_interval">
|
||||
<span slot="label">
|
||||
<el-tooltip :content="EMQXForm.params.reconnect_interval.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
重连间隔:
|
||||
</span>
|
||||
<el-input v-model="EMQXForm.params.reconnect_interval.default" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<el-form-item prop="EMQbatch_size">
|
||||
<span slot="label">
|
||||
<el-tooltip :content="EMQXForm.params.batch_size.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
批处理大小:
|
||||
</span>
|
||||
<el-input v-model="EMQXForm.params.batch_size.default" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注:">
|
||||
<el-input v-model="EMQXForm.description" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<el-form-item prop="EMQdisk_cache">
|
||||
<span slot="label">
|
||||
<el-tooltip :content="EMQXForm.params.disk_cache.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
磁盘缓存:
|
||||
</span>
|
||||
<el-select v-model="EMQXForm.params.disk_cache.default">
|
||||
<el-option v-for="(enums, index) in EMQXForm.params.disk_cache.enum" :key="index" :label="enums" :value="enums"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-form>
|
||||
<el-form ref="MQTTForm" :model="MQTTForm" label-width="180px" :rules="ruleMQTT">
|
||||
<el-card style="padding-bottom: 10px; margin-top: 10px" v-if="MQTTForm.params" v-show="openMQTTView">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>具体信息</span>
|
||||
</div>
|
||||
<el-row>
|
||||
<el-col :span="10">
|
||||
<el-form-item prop="params.address.default">
|
||||
<span slot="label">
|
||||
<el-tooltip :content="MQTTForm.params.address.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
远程broker地址:
|
||||
</span>
|
||||
<el-input v-model="MQTTForm.params.address.default" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<span slot="label">
|
||||
<el-tooltip :content="MQTTForm.params.disk_cache.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
磁盘缓存:
|
||||
</span>
|
||||
<el-select v-model="MQTTForm.params.disk_cache.default">
|
||||
<el-option v-for="(enums, index) in MQTTForm.params.disk_cache.enum" :key="index" :label="enums" :value="enums"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<el-form-item>
|
||||
<span slot="label">
|
||||
<el-tooltip :content="MQTTForm.params.proto_ver.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
协议版本:
|
||||
</span>
|
||||
<el-select v-model="MQTTForm.params.proto_ver.default">
|
||||
<el-option v-for="(enums, index) in MQTTForm.params.proto_ver.enum" :key="index" :label="enums" :value="enums"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<span slot="label">
|
||||
<el-tooltip :content="MQTTForm.params.clientid.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
客户端ID:
|
||||
</span>
|
||||
<el-input v-model="MQTTForm.params.clientid.default" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<el-form-item>
|
||||
<span slot="label">
|
||||
<el-tooltip :content="MQTTForm.params.username.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
用户名:
|
||||
</span>
|
||||
<el-input v-model="MQTTForm.params.username.default" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="params.mountpoint.default">
|
||||
<span slot="label">
|
||||
<el-tooltip :content="MQTTForm.params.mountpoint.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
桥接挂载点:
|
||||
</span>
|
||||
<el-input v-model="MQTTForm.params.mountpoint.default" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<el-form-item>
|
||||
<span slot="label">
|
||||
<el-tooltip :content="MQTTForm.params.password.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
密码:
|
||||
</span>
|
||||
<el-input v-model="MQTTForm.params.password.default" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="params.keepalive.default">
|
||||
<span slot="label">
|
||||
<el-tooltip :content="MQTTForm.params.keepalive.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
心跳间隔:
|
||||
</span>
|
||||
<el-input v-model="MQTTForm.params.keepalive.default" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="10">
|
||||
<el-form-item>
|
||||
<span slot="label">
|
||||
<el-tooltip :content="MQTTForm.params.reconnect_interval.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
重连间隔:
|
||||
</span>
|
||||
<el-input v-model="MQTTForm.params.reconnect_interval.default" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<span slot="label">
|
||||
<el-tooltip :content="MQTTForm.params.bridge_mode.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
桥接模式:
|
||||
</span>
|
||||
<el-select v-model="MQTTForm.params.bridge_mode.default">
|
||||
<el-option key="false" label="false" value="false"></el-option>
|
||||
<el-option key="true" label="true" value="true"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="10">
|
||||
<el-form-item>
|
||||
<span slot="label">
|
||||
<el-tooltip :content="MQTTForm.params.retry_interval.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
重传间隔:
|
||||
</span>
|
||||
<el-input v-model="MQTTForm.params.retry_interval.default" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="params.ssl.default">
|
||||
<span slot="label">
|
||||
<el-tooltip :content="MQTTForm.params.ssl.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
Bridge SSL:
|
||||
</span>
|
||||
<el-select v-model="MQTTForm.params.ssl.default">
|
||||
<el-option v-for="(enums, index) in MQTTForm.params.ssl.enum" :key="index" :label="enums" :value="enums"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="10">
|
||||
<el-form-item>
|
||||
<span slot="label">
|
||||
<el-tooltip :content="MQTTForm.params.cacertfile.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
CA证书:
|
||||
</span>
|
||||
<el-input v-model="MQTTForm.params.cacertfile.default" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<span slot="label">
|
||||
<el-tooltip :content="MQTTForm.params.keyfile.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
SSL 密钥文件:
|
||||
</span>
|
||||
<el-input v-model="MQTTForm.params.keyfile.default" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="10">
|
||||
<el-form-item>
|
||||
<span slot="label">
|
||||
<el-tooltip :content="MQTTForm.params.certfile.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
SSL 客户端证书:
|
||||
</span>
|
||||
<el-input v-model="MQTTForm.params.certfile.default" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<span slot="label">
|
||||
<el-tooltip :content="MQTTForm.params.ciphers.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
SSL 加密算法 :
|
||||
</span>
|
||||
<el-input v-model="MQTTForm.params.ciphers.default" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<el-form-item label="备注:">
|
||||
<el-input v-model="MQTTForm.description" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-form>
|
||||
<el-form ref="WebHookForm" :model="WebHookForm" label-width="180px" :rules="ruleWebHook">
|
||||
<el-card style="padding-bottom: 10px; margin-top: 10px" v-if="WebHookForm.params" v-show="openWebView">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>具体信息</span>
|
||||
</div>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="params.url.default">
|
||||
<span slot="label">
|
||||
<el-tooltip :content="WebHookForm.params.url.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
请求 URL:
|
||||
</span>
|
||||
<el-input v-model="WebHookForm.params.url.default" placeholder="http://" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="请求方法:">
|
||||
<span slot="label">
|
||||
<el-tooltip :content="WebHookForm.params.method.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
请求方法:
|
||||
</span>
|
||||
<el-select v-model="WebHookForm.params.method.default">
|
||||
<el-option v-for="(enums, index) in WebHookForm.params.method.enum" :key="index" :label="enums" :value="enums"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="20">
|
||||
<el-form-item label="请求头:" prop="ket_value">
|
||||
<el-row v-for="(item, index) in ket_value" :key="index" style="margin-bottom: 10px">
|
||||
<el-col :span="8">
|
||||
<el-input v-model="item.key" placeholder="键" />
|
||||
</el-col>
|
||||
<el-col :span="12" :offset="1">
|
||||
<el-input v-model="item.value" placeholder="值" />
|
||||
</el-col>
|
||||
<el-col :span="2" :offset="1" v-if="index != 0"><a style="color: #f56c6c" @click="removeHeaderItem(index)">删除</a></el-col>
|
||||
</el-row>
|
||||
<div>
|
||||
+
|
||||
<a style="color: #409eff" @click="addHeader()">添加请求头</a>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="备注:">
|
||||
<el-input v-model="WebHookForm.description" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
<el-button type="success" @click="saveResource('EMQXForm')" v-if="openEMQXView" :loading="showloading">新建</el-button>
|
||||
<el-button type="success" @click="saveResource('MQTTForm')" v-if="openMQTTView" :loading="showloading">新建</el-button>
|
||||
<el-button type="success" @click="saveResource('WebHookForm')" v-if="openWebView" :loading="showloading">新建</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getResources,
|
||||
getResourcesStatus,
|
||||
getConnectResource,
|
||||
deleteResource,
|
||||
getResourcesType,
|
||||
getResourcesConnect,
|
||||
saveResources,
|
||||
} from "@/api/iot/emqx";
|
||||
|
||||
export default {
|
||||
name: "Resource",
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 新建按钮等待效果
|
||||
showloading: false,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 规则表格数据
|
||||
resourceList: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 是否显示详细弹出层
|
||||
openView: false,
|
||||
// 是否显示检测状态弹出层
|
||||
openStatusView: false,
|
||||
// 是否显示添加资源弹出层
|
||||
openAddView: false,
|
||||
// 是否显示EMQX Bridge弹出层
|
||||
openEMQXView: false,
|
||||
// 是否显示MQTT Bridge弹出层
|
||||
openMQTTView: false,
|
||||
// 是否显示WebHook弹出层
|
||||
openWebView: false,
|
||||
//表单数据
|
||||
form: {
|
||||
config: {},
|
||||
},
|
||||
statusForm: {
|
||||
status: [],
|
||||
},
|
||||
//添加资源表单数据
|
||||
addResourceForm: {
|
||||
resource: [],
|
||||
type: "",
|
||||
},
|
||||
//添加EMQX资源表单数据
|
||||
EMQXForm: {
|
||||
description: "",
|
||||
},
|
||||
//添加MQTT资源表单数据
|
||||
MQTTForm: {
|
||||
description: "",
|
||||
},
|
||||
//添加WebHook资源表单数据
|
||||
WebHookForm: {
|
||||
description: "",
|
||||
},
|
||||
ket_value: [],
|
||||
//添加资源表单数据
|
||||
emqxParam: {
|
||||
description: "",
|
||||
name: "",
|
||||
type: "",
|
||||
config: {},
|
||||
},
|
||||
ruleEMQX: {
|
||||
params: {
|
||||
address: {
|
||||
default: [{
|
||||
required: true,
|
||||
message: "请输入EMQ X节点名称",
|
||||
trigger: "blur",
|
||||
}, ],
|
||||
},
|
||||
pool_size: {
|
||||
default: [{
|
||||
required: true,
|
||||
message: "请输入连接池大小",
|
||||
trigger: "blur",
|
||||
}, ],
|
||||
},
|
||||
mountpoint: {
|
||||
default: [{
|
||||
required: true,
|
||||
message: "请输入桥接挂载点",
|
||||
trigger: "blur",
|
||||
}, ],
|
||||
},
|
||||
},
|
||||
},
|
||||
ruleMQTT: {
|
||||
params: {
|
||||
address: {
|
||||
default: [{
|
||||
required: true,
|
||||
message: "请输入远程 broker 地址",
|
||||
trigger: "blur",
|
||||
}, ],
|
||||
},
|
||||
mountpoint: {
|
||||
default: [{
|
||||
required: true,
|
||||
message: "请输入桥接挂载点",
|
||||
trigger: "blur",
|
||||
}, ],
|
||||
},
|
||||
ssl: {
|
||||
default: [{
|
||||
required: true,
|
||||
message: "请选择Bridge SSL",
|
||||
trigger: "change",
|
||||
}, ],
|
||||
},
|
||||
keepalive: {
|
||||
default: [{
|
||||
required: true,
|
||||
message: "请输入心跳间隔",
|
||||
trigger: "blur",
|
||||
}, ],
|
||||
},
|
||||
},
|
||||
},
|
||||
ruleWebHook: {
|
||||
params: {
|
||||
url: {
|
||||
default: [{
|
||||
required: true,
|
||||
message: "请输入请求 URL",
|
||||
trigger: "blur",
|
||||
}, ],
|
||||
},
|
||||
},
|
||||
},
|
||||
rule: {
|
||||
resource: {
|
||||
title: [{
|
||||
required: true,
|
||||
message: "请选择资源类型",
|
||||
trigger: "change"
|
||||
}, ],
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询规则列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
getResources("").then((response) => {
|
||||
this.resourceList = response.data.data;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 查看按钮操作 */
|
||||
handleQuery(row) {
|
||||
this.form = row;
|
||||
this.openView = true;
|
||||
},
|
||||
/** 状态按钮操作 */
|
||||
checkStatus(row) {
|
||||
let resourceId = row.id;
|
||||
getResourcesStatus(resourceId).then((response) => {
|
||||
this.statusForm = response.data.data;
|
||||
this.openStatusView = true;
|
||||
});
|
||||
},
|
||||
//删除按钮操作
|
||||
handleDelete(row) {
|
||||
let resourceId = row.id;
|
||||
this.$modal
|
||||
.confirm('是否确认删除ID为"' + resourceId + '"的规则引擎?')
|
||||
.then(function () {
|
||||
return deleteResource(resourceId);
|
||||
})
|
||||
.then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除资源成功");
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
/** 重新连接资源按钮操作 */
|
||||
checkNode(resourceId) {
|
||||
getConnectResource(resourceId).then((response) => {
|
||||
let code = response.data.code;
|
||||
if (code !== 0) {
|
||||
this.$modal.msgError(response.data.message);
|
||||
} else {
|
||||
this.$modal.msgSuccess("连接资源成功");
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 跳转添加资源页面 */
|
||||
addResource() {
|
||||
getResourcesType().then((res) => {
|
||||
this.addResourceForm.resource = res.data.data;
|
||||
this.EMQXForm.params = res.data.data[0].params;
|
||||
this.MQTTForm.params = res.data.data[1].params;
|
||||
this.WebHookForm.params = res.data.data[2].params;
|
||||
this.openAddView = true;
|
||||
});
|
||||
},
|
||||
|
||||
/** 选择资源类型 */
|
||||
selectTitle(val) {
|
||||
this.addResourceForm.type = val;
|
||||
if ("bridge_rpc" === val) {
|
||||
this.openEMQXView = true;
|
||||
this.openMQTTView = false;
|
||||
this.openWebView = false;
|
||||
} else if ("bridge_mqtt" === val) {
|
||||
this.openEMQXView = false;
|
||||
this.openMQTTView = true;
|
||||
this.openWebView = false;
|
||||
} else if ("web_hook" === val) {
|
||||
this.openEMQXView = false;
|
||||
this.openMQTTView = false;
|
||||
this.openWebView = true;
|
||||
}
|
||||
},
|
||||
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
//初始化
|
||||
this.openEMQXView = false;
|
||||
this.openMQTTView = false;
|
||||
this.openWebView = false;
|
||||
this.openAddView = false;
|
||||
this.EMQXForm = {};
|
||||
this.MQTTForm = {};
|
||||
this.WebHookForm = {};
|
||||
this.addResourceForm.resource = [];
|
||||
this.addResourceForm.description = "";
|
||||
this.$refs['addResourceForm'].resetFields();
|
||||
},
|
||||
|
||||
//测试连接
|
||||
testConnect(formName) {
|
||||
this.$refs[formName].validate((valid) => {
|
||||
if (valid) {
|
||||
this.insertOrTestResourceUtils('test');
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 添加请求头 */
|
||||
addHeader() {
|
||||
this.ket_value.push({
|
||||
key: "",
|
||||
value: "",
|
||||
});
|
||||
},
|
||||
/** 删除请求头 */
|
||||
removeHeaderItem(index) {
|
||||
this.ket_value.splice(index, 1);
|
||||
},
|
||||
|
||||
//新建资源
|
||||
saveResource(formName) {
|
||||
this.showloading = true;
|
||||
//校验表单
|
||||
this.$refs[formName].validate((valid) => {
|
||||
if (valid) {
|
||||
this.insertOrTestResourceUtils('save');
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
// 新增资源或者测试连接公共方法
|
||||
insertOrTestResourceUtils(type) {
|
||||
this.emqxParam.type = this.addResourceForm.type;
|
||||
//判断选择的资源类型
|
||||
if ("bridge_rpc" === this.addResourceForm.type) {
|
||||
this.emqxParam.description = this.EMQXForm.description;
|
||||
this.emqxParam.config.address = this.EMQXForm.params.address.default;
|
||||
this.emqxParam.config.batch_size =
|
||||
this.EMQXForm.params.batch_size.default;
|
||||
this.emqxParam.config.disk_cache =
|
||||
this.EMQXForm.params.disk_cache.default;
|
||||
this.emqxParam.config.mountpoint =
|
||||
this.EMQXForm.params.mountpoint.default;
|
||||
this.emqxParam.config.pool_size =
|
||||
this.EMQXForm.params.pool_size.default;
|
||||
this.emqxParam.config.reconnect_interval =
|
||||
this.EMQXForm.params.reconnect_interval.default;
|
||||
if ("test" == type) {
|
||||
getResourcesConnect(this.emqxParam).then((res) => {
|
||||
let code = res.data.code;
|
||||
if (0 == code) {
|
||||
this.$modal.msgSuccess("连接成功");
|
||||
} else {
|
||||
this.$modal.msgError(res.data.message);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
saveResources(this.emqxParam).then((res) => {
|
||||
this.showloading = false;
|
||||
let code = res.data.code;
|
||||
if (0 == code) {
|
||||
this.$modal.msgSuccess("添加资源成功");
|
||||
this.getList();
|
||||
this.cancel();
|
||||
} else {
|
||||
this.$modal.msgError(res.data.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if ("bridge_mqtt" === this.addResourceForm.type) {
|
||||
this.emqxParam.description = this.MQTTForm.description;
|
||||
this.emqxParam.config.address = this.MQTTForm.params.address.default;
|
||||
this.emqxParam.config.bridge_mode =
|
||||
this.MQTTForm.params.bridge_mode.default;
|
||||
this.emqxParam.config.cacertfile =
|
||||
this.MQTTForm.params.cacertfile.default;
|
||||
this.emqxParam.config.certfile = this.MQTTForm.params.certfile.default;
|
||||
this.emqxParam.config.ciphers = this.MQTTForm.params.ciphers.default;
|
||||
this.emqxParam.config.clientid = this.MQTTForm.params.clientid.default;
|
||||
this.emqxParam.config.disk_cache =
|
||||
this.MQTTForm.params.disk_cache.default;
|
||||
this.emqxParam.config.keepalive =
|
||||
this.MQTTForm.params.keepalive.default;
|
||||
this.emqxParam.config.keyfile = this.MQTTForm.params.keyfile.default;
|
||||
this.emqxParam.config.mountpoint =
|
||||
this.MQTTForm.params.mountpoint.default;
|
||||
this.emqxParam.config.password = this.MQTTForm.params.password.default;
|
||||
this.emqxParam.config.proto_ver =
|
||||
this.MQTTForm.params.proto_ver.default;
|
||||
this.emqxParam.config.reconnect_interval =
|
||||
this.MQTTForm.params.reconnect_interval.default;
|
||||
this.emqxParam.config.retry_interval =
|
||||
this.MQTTForm.params.retry_interval.default;
|
||||
this.emqxParam.config.ssl = this.MQTTForm.params.ssl.default;
|
||||
this.emqxParam.config.username = this.MQTTForm.params.username.default;
|
||||
if ("test" == type) {
|
||||
getResourcesConnect(this.emqxParam).then((res) => {
|
||||
let code = res.data.code;
|
||||
if (0 == code) {
|
||||
this.$modal.msgSuccess("连接成功");
|
||||
} else {
|
||||
this.$modal.msgError(res.data.message);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
saveResources(this.emqxParam).then((res) => {
|
||||
this.showloading = false;
|
||||
let code = res.data.code;
|
||||
if (0 == code) {
|
||||
this.$modal.msgSuccess("添加资源成功");
|
||||
this.getList();
|
||||
this.cancel();
|
||||
} else {
|
||||
this.$modal.msgError(res.data.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if ("web_hook" === this.addResourceForm.type) {
|
||||
this.emqxParam.description = this.WebHookForm.description;
|
||||
this.emqxParam.config.url = this.WebHookForm.params.url.default;
|
||||
this.emqxParam.config.method = this.WebHookForm.params.method.default;
|
||||
|
||||
//解析数据转换成后端需要的数据格式
|
||||
let headers = {};
|
||||
this.ket_value.forEach((item) => {
|
||||
headers[item.key] = item.value;
|
||||
});
|
||||
this.emqxParam.config.headers = headers;
|
||||
if ("test" == type) {
|
||||
getResourcesConnect(this.emqxParam).then((res) => {
|
||||
let code = res.data.code;
|
||||
if (0 == code) {
|
||||
this.$modal.msgSuccess("连接成功");
|
||||
} else {
|
||||
this.$modal.msgError(res.data.message);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
saveResources(this.emqxParam).then((res) => {
|
||||
this.showloading = false;
|
||||
let code = res.data.code;
|
||||
if (0 == code) {
|
||||
this.$modal.msgSuccess("添加资源成功");
|
||||
this.getList();
|
||||
this.cancel();
|
||||
} else {
|
||||
this.$modal.msgError(res.data.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
815
vue/src/views/iot/emqx/rule.vue
Normal file
815
vue/src/views/iot/emqx/rule.vue
Normal file
@@ -0,0 +1,815 @@
|
||||
<template>
|
||||
<div style="padding: 6px">
|
||||
<el-card style="padding-bottom: 100px">
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="success" plain icon="el-icon-refresh" size="mini" @click="getList" v-hasPermi="['monitor:rules:refresh']">刷新</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="getAddRules" v-hasPermi="['monitor:rules:add']">新增</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-table v-loading="loading" :data="rulesList">
|
||||
<el-table-column label="ID" align="center" header-align="center" prop="id">
|
||||
<template slot-scope="scope">
|
||||
<el-link :underline="false" type="primary">{{scope.row.id }}</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="主题" align="center" prop="for" width="120">
|
||||
<template slot-scope="scope">
|
||||
<p v-for="(topic, index) in scope.row.for" :key="index">
|
||||
<el-tag type="success">{{ topic }}</el-tag>
|
||||
</p>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="SQL" align="center" prop="rawsql" />
|
||||
<el-table-column label="响应动作" align="center" prop="actions">
|
||||
<template slot-scope="scope">
|
||||
<p v-for="(action, index) in scope.row.actions" :key="index">
|
||||
<el-tag type="success">{{ action.name }}</el-tag>
|
||||
</p>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="已命中" align="center" prop="matched">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.metrics[0].matched }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="150">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="small" type="text" style="padding: 5px" v-hasPermi="['monitor:rules:query']" @click="handleQuery(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>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<!-- 规则引擎详细 -->
|
||||
<el-dialog title="规则引擎详细" :visible.sync="openView" width="50%" append-to-body>
|
||||
<el-form ref="form" :model="form" label-width="120px" size="mini">
|
||||
<el-card style="padding-bottom: 10px">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>基本信息</span>
|
||||
</div>
|
||||
<el-row>
|
||||
<el-col :span="20">
|
||||
<el-form-item label="主题:">
|
||||
<el-tag type="success" v-for="(topic, index) in form.for" :key="index">{{ topic }}</el-tag>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="20">
|
||||
<el-form-item label="备注:">{{ form.description }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="20">
|
||||
<el-form-item label="规则SQL:">{{ form.rawsql }}</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
<el-card style="padding-bottom: 10px; margin-top: 10px">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>度量指标</span>
|
||||
</div>
|
||||
<el-table :data="form.metrics">
|
||||
<el-table-column label="节点" align="center" prop="node" />
|
||||
<el-table-column label="已命中" align="center" prop="matched" />
|
||||
<el-table-column label="命中速度" align="center" prop="speed" />
|
||||
<el-table-column label="最大命中速度" align="center" prop="speed_max" />
|
||||
<el-table-column label="5分钟平均速度" align="center" prop="speed_last5m" />
|
||||
</el-table>
|
||||
</el-card>
|
||||
<el-card style="padding-bottom: 10px; margin-top: 10px">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>响应动作</span>
|
||||
</div>
|
||||
<el-table :data="form.actions">
|
||||
<el-table-column label="类型" align="center" prop="name" />
|
||||
<el-table-column label="参数" align="center" prop="params">
|
||||
<template slot-scope="scope">
|
||||
{{scope.row.params}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="度量指标" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag type="success">{{ scope.row.metrics[0].node }}</el-tag><br />
|
||||
合计: 成功:<el-tag type="success">{{ scope.row.metrics[0].success }}</el-tag>
|
||||
失败:<el-tag type="danger">{{ scope.row.metrics[0].failed }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="openView = false">关 闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 添加规则引擎 -->
|
||||
<el-dialog title="资源管理" :visible.sync="openAddView" width="60%" append-to-body :before-close="cancel">
|
||||
<el-form ref="form" :model="form" label-width="180px">
|
||||
<el-card style="padding-bottom: 10px">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>
|
||||
<h2>条件</h2>
|
||||
<h6>使用 SQL 定义规则条件与数据处理方式</h6>
|
||||
</span>
|
||||
</div>
|
||||
<el-row :gutter="50">
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="sql_example">
|
||||
<span slot="label"> 规则 SQL: </span>
|
||||
<CodeMirrorEditor :value="form.sql_example" myMode="text/x-mysql" height="420" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="sql_example">
|
||||
<span slot="label"> 备注: </span>
|
||||
<el-input v-model="form.note" placeholder="e.g.消息转发到WebHook" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="SQLtest">
|
||||
<span slot="label">
|
||||
SQL测试:
|
||||
<el-tooltip content="自定义模拟数据进行 SQL 命令测试,仅用于测试功能" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<el-switch v-model="form.SQLtest" active-text="" inactive-text="" :active-value="true" :inactive-value="false" active-color="#13ce66">
|
||||
</el-switch>
|
||||
</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 :span="10">
|
||||
<div class="sql-tips">
|
||||
<div class="title">编写 SQL 进行条件过滤与数据处理</div>
|
||||
<div class="el-scrollbar">
|
||||
<div class="doc-wrapper" style="margin-bottom: -17px; margin-right: -17px">
|
||||
<div class="el-scrollbar__view">
|
||||
<div>
|
||||
<p>
|
||||
EMQ X
|
||||
在消息发布、事件触发时将触发规则引擎,满足触发条件的规则将执行各自的
|
||||
SQL 语句筛选并处理消息和事件的上下文信息。
|
||||
</p>
|
||||
<p class="item">
|
||||
规则引擎借助响应动作可将特定主题的消息处理结果存储到数据库,发送到
|
||||
HTTP Server,转发到消息队列 Kafka 或
|
||||
RabbitMQ,重新发布到新的主题甚至是另一个 Broker
|
||||
集群中,每个规则可以配置多个响应动作。
|
||||
</p>
|
||||
<p>
|
||||
1. 选择发布到 't/#' 主题的消息,并筛选出全部字段:
|
||||
</p>
|
||||
<div class="code">
|
||||
<code>SELECT * FROM "t/#"</code>
|
||||
</div>
|
||||
<p>
|
||||
2. 选择发布到 't/a' 主题的消息,并从 JSON
|
||||
格式的消息内容中筛选出 "x" 字段:
|
||||
</p>
|
||||
<div class="code">
|
||||
<code>SELECT payload.x as x FROM "t/a"</code>
|
||||
</div>
|
||||
<p class="item">
|
||||
规则引擎使用 $events/ 开头的虚拟主题(事件主题)处理
|
||||
EMQ X
|
||||
内置事件,内置事件提供更精细的消息控制和客户端动作处理能力,可用在
|
||||
QoS 1 QoS 2 的消息抵达记录、设备上下线记录等业务中。
|
||||
</p>
|
||||
<p>
|
||||
1. 选择客户端连接事件,筛选 Username 为 'emqx'
|
||||
的设备并获取连接信息:
|
||||
</p>
|
||||
<div class="code">
|
||||
<code>SELECT clientid, connected_at FROM
|
||||
"$events/client_connected" WHERE username =
|
||||
'emqx'</code>
|
||||
</div>
|
||||
<p>规则引擎和 SQL 语句的详细教程参见 EMQ X 文档。</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-form>
|
||||
<el-card style="padding-bottom: 10px">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>
|
||||
<h2>响应动作</h2>
|
||||
<h6>处理命中规则的消息</h6>
|
||||
</span>
|
||||
</div>
|
||||
<el-table ref="singleTable" :data="actions" highlight-current-row>
|
||||
<el-table-column property="name" label="类型"> </el-table-column>
|
||||
<el-table-column property="param" label="参数">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.param }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="danger" @click="deleteAction(scope.$index)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div style="margin-top: 20px">
|
||||
<el-button @click="addActionPage()">添加</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
<el-button type="success" @click="saveRule" :loading="addRuleLoading">新建</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 添加响应动作 -->
|
||||
<el-dialog title="响应动作" :visible.sync="openAddActionView" width="40%" append-to-body :before-close="cancelAction">
|
||||
<el-form ref="actionForm" :model="actionForm" label-width="180px" v-if="actionForm.actions" :rules="ruleActions">
|
||||
<el-row>
|
||||
<el-col :span="20">
|
||||
<el-form-item prop="actions.title">
|
||||
<span slot="label">
|
||||
动作:
|
||||
<el-tooltip :content="prompt" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<el-select v-model="actionForm.actions.title" @change="selectTitle" placeholder="请选择">
|
||||
<el-option v-for="(action, index) in actionForm.actions" :key="index" :label="action.title.zh" :value="action.name"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<el-form ref="republishForm" :model="republishForm" label-width="180px" v-if="republishForm.params" v-show="republishView" :rules="ruleRepublish">
|
||||
<el-row>
|
||||
<el-col :span="20">
|
||||
<el-form-item prop="params.target_topic.default">
|
||||
<span slot="label">
|
||||
目的主题:
|
||||
<el-tooltip :content="republishForm.params.target_topic.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<el-input v-model="republishForm.params.target_topic.default" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="params.target_qos.default">
|
||||
<span slot="label">
|
||||
目的 QoS:
|
||||
<el-tooltip :content="republishForm.params.target_qos.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<el-input v-model="republishForm.params.target_qos.default" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="params.payload_tmpl.default">
|
||||
<span slot="label">
|
||||
消息内容模板:
|
||||
<el-tooltip :content="republishForm.params.payload_tmpl.description.zh" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<textarea style="width: 300px; height: 120px" v-model="republishForm.params.payload_tmpl.default"></textarea>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<el-form ref="data_to_mqtt_broker_Form" :model="data_to_mqtt_broker_Form" label-width="180px" v-if="data_to_mqtt_broker_Form.params" v-show="data_to_mqtt_broker_View" :rules="rule_data_to_mqtt_broker">
|
||||
<el-row>
|
||||
<el-col :span="20">
|
||||
<el-form-item prop="resourceId">
|
||||
<span slot="label"> 关联资源: </span>
|
||||
<el-select v-model="data_to_mqtt_broker_Form.resourceId" placeholder="请选择">
|
||||
<el-option v-for="(
|
||||
resource, index
|
||||
) in data_to_mqtt_broker_Form.resources" :key="index" :label="resource.id" :value="resource.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item prop="params.payload_tmpl.default" v-if="data_to_mqtt_broker_Form.params.payload_tmpl">
|
||||
<span slot="label">
|
||||
消息内容模板:
|
||||
<el-tooltip :content="
|
||||
data_to_mqtt_broker_Form.params.payload_tmpl.description.zh
|
||||
" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<textarea style="width: 300px; height: 120px" v-model="data_to_mqtt_broker_Form.params.payload_tmpl.default"></textarea>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<el-form ref="data_to_webserver_Form" :model="data_to_webserver_Form" label-width="180px" v-if="data_to_webserver_Form.params" v-show="data_to_webserver_View" :rules="rule_data_to_webserver">
|
||||
<el-row>
|
||||
<el-col :span="20">
|
||||
<el-form-item prop="resourceId">
|
||||
<span slot="label"> 关联资源: </span>
|
||||
<el-select v-model="data_to_webserver_Form.resourceId" placeholder="请选择">
|
||||
<el-option v-for="(resource, index) in data_to_webserver_Form.resources" :key="index" :label="resource.id" :value="resource.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item prop="params.payload_tmpl.default" v-if="data_to_webserver_Form.params.payload_tmpl">
|
||||
<span slot="label">
|
||||
消息内容模板:
|
||||
<el-tooltip :content="
|
||||
data_to_webserver_Form.params.payload_tmpl.description.zh
|
||||
" placement="top">
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<textarea style="width: 300px; height: 120px" v-model="data_to_webserver_Form.params.payload_tmpl.default"></textarea>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="cancelAction">取 消</el-button>
|
||||
<el-button type="success" @click="saveAction('republishForm')" v-if="republishView" :loading="showloading">新建</el-button>
|
||||
<el-button type="success" @click="saveAction('data_to_mqtt_broker_Form')" v-if="data_to_mqtt_broker_View" :loading="showloading">新建</el-button>
|
||||
<el-button type="success" @click="saveAction('data_to_webserver_Form')" v-if="data_to_webserver_View" :loading="showloading">新建</el-button>
|
||||
<el-button type="success" @click="saveAction('do_nothing_Form')" v-if="do_nothing_View" :loading="showloading">新建</el-button>
|
||||
<el-button type="success" @click="saveAction('inspectForm')" v-if="inspectView" :loading="showloading">新建</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getRules,
|
||||
deleteRule,
|
||||
getRulesEvent,
|
||||
getActionsEvent,
|
||||
getResources,
|
||||
saveRule,
|
||||
testConnectRule,
|
||||
} from "@/api/iot/emqx";
|
||||
import CodeMirrorEditor from "@/components/Codemirror/index";
|
||||
export default {
|
||||
name: "Rules",
|
||||
components: {
|
||||
CodeMirrorEditor,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
//遮罩层
|
||||
showloading: false,
|
||||
// 遮罩层
|
||||
addRuleLoading: false,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 规则表格数据
|
||||
rulesList: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示详细弹出层
|
||||
openView: false,
|
||||
// 是否显示添加规则弹出层
|
||||
openAddView: false,
|
||||
// 是否显示添加响应动作弹出层
|
||||
openAddActionView: false,
|
||||
//是否显示消息重新发布表单参数
|
||||
republishView: false,
|
||||
//是否显示桥接数据到 MQTT Broker表单参数
|
||||
data_to_mqtt_broker_View: false,
|
||||
//是否显示发送数据到 Web 服务表单参数
|
||||
data_to_webserver_View: false,
|
||||
//是否显示空动作 (调试)表单按钮
|
||||
do_nothing_View: false,
|
||||
//是否显示检查 (调试)表单按钮
|
||||
inspectView: false,
|
||||
// 添加规则表单参数
|
||||
form: {
|
||||
note: "",
|
||||
SQLtest: false,
|
||||
},
|
||||
//测试结果
|
||||
content: "",
|
||||
// 响应动作列表
|
||||
actions: [],
|
||||
//响应动作列表表单参数
|
||||
actionForm: {
|
||||
actions: [],
|
||||
},
|
||||
//动作的提示语
|
||||
prompt: "动作类型",
|
||||
// 响应动作规则
|
||||
ruleActions: {
|
||||
actions: {
|
||||
title: [{
|
||||
required: true,
|
||||
message: "请选择动作类型",
|
||||
trigger: "change"
|
||||
}, ],
|
||||
},
|
||||
},
|
||||
ruleRepublish: {
|
||||
params: {
|
||||
target_topic: {
|
||||
default: [{
|
||||
required: true,
|
||||
message: "请输入目的主题",
|
||||
trigger: "blur"
|
||||
}, ],
|
||||
},
|
||||
target_qos: {
|
||||
default: [{
|
||||
required: true,
|
||||
message: "请输入目的 QoS",
|
||||
trigger: "blur"
|
||||
}, ],
|
||||
},
|
||||
payload_tmpl: {
|
||||
default: [{
|
||||
required: true,
|
||||
message: "请输入消息内容模板",
|
||||
trigger: "blur",
|
||||
}, ],
|
||||
},
|
||||
},
|
||||
},
|
||||
rule_data_to_mqtt_broker: {
|
||||
resourceId: [{
|
||||
required: true,
|
||||
message: "请关联资源类型",
|
||||
trigger: "blur"
|
||||
}, ],
|
||||
},
|
||||
rule_data_to_webserver: {
|
||||
resourceId: [{
|
||||
required: true,
|
||||
message: "请关联资源类型",
|
||||
trigger: "change"
|
||||
}, ],
|
||||
},
|
||||
//空动作 (调试)表单参数
|
||||
do_nothing_Form: {},
|
||||
//检查 (调试)表单参数
|
||||
inspectForm: {},
|
||||
//消息重新发布表单参数
|
||||
republishForm: {
|
||||
},
|
||||
//桥接数据到 MQTT Broker表单参数
|
||||
data_to_mqtt_broker_Form: {
|
||||
resources: [],
|
||||
resourceId: "",
|
||||
},
|
||||
//发送数据到 Web 服务表单参数
|
||||
data_to_webserver_Form: {
|
||||
resources: [],
|
||||
resourceId: "",
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询规则列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
getRules("").then((response) => {
|
||||
this.rulesList = response.data.data;
|
||||
// this.total = response.data.meta.count;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
//初始化
|
||||
this.openAddView = false;
|
||||
this.actions = [];
|
||||
this.$refs["form"].resetFields();
|
||||
},
|
||||
//关闭动作页面
|
||||
cancelAction() {
|
||||
//初始化所有数据
|
||||
this.do_nothing_View = false;
|
||||
this.republishView = false;
|
||||
this.data_to_mqtt_broker_View = false;
|
||||
this.data_to_webserver_View = false;
|
||||
this.inspectView = false;
|
||||
this.openAddActionView = false;
|
||||
|
||||
this.do_nothing_Form = {};
|
||||
this.inspectForm = {};
|
||||
this.republishForm = {};
|
||||
this.data_to_mqtt_broker_Form.resources = [];
|
||||
this.data_to_mqtt_broker_Form.resourceId = "";
|
||||
this.data_to_mqtt_broker_Form = {};
|
||||
this.data_to_webserver_Form.resources = [];
|
||||
this.data_to_webserver_Form.resourceId = "";
|
||||
this.data_to_webserver_Form = {};
|
||||
|
||||
this.actionForm.actions = [];
|
||||
|
||||
this.$refs["actionForm"].resetFields();
|
||||
},
|
||||
/** 查看按钮操作 */
|
||||
handleQuery(row) {
|
||||
let ruleId = row.id;
|
||||
getRules(ruleId).then((response) => {
|
||||
this.form = response.data.data;
|
||||
this.openView = true;
|
||||
});
|
||||
},
|
||||
//删除规则
|
||||
handleDelete(row) {
|
||||
debugger;
|
||||
let ruleId = row.id;
|
||||
this.$modal
|
||||
.confirm('是否确认删除ID为"' + ruleId + '"的规则引擎?')
|
||||
.then(function () {
|
||||
return deleteRule(ruleId);
|
||||
})
|
||||
.then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除规则引擎成功");
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
//跳转到添加规则引擎页面
|
||||
getAddRules() {
|
||||
getRulesEvent().then((res) => {
|
||||
this.form = res.data.data[0];
|
||||
this.openAddView = true;
|
||||
});
|
||||
},
|
||||
//添加响应动作
|
||||
addActionPage() {
|
||||
getActionsEvent().then((res) => {
|
||||
//赋值
|
||||
this.actionForm.actions = res.data.data;
|
||||
this.do_nothing_Form = res.data.data[0];
|
||||
//检查 (调试)表单参数
|
||||
this.inspectForm = res.data.data[2];
|
||||
//消息重新发布表单参数
|
||||
this.republishForm = res.data.data[1];
|
||||
//桥接数据到 MQTT Broker表单参数
|
||||
this.data_to_mqtt_broker_Form = res.data.data[3];
|
||||
//发送数据到 Web 服务表单参数
|
||||
this.data_to_webserver_Form = res.data.data[4];
|
||||
this.openAddActionView = true;
|
||||
});
|
||||
},
|
||||
/** 选择响应动作类型 */
|
||||
selectTitle(val) {
|
||||
if ("do_nothing" === val) {
|
||||
this.data_to_webserver_View = false;
|
||||
this.data_to_mqtt_broker_View = false;
|
||||
this.republishView = false;
|
||||
this.inspectView = false;
|
||||
this.do_nothing_View = true;
|
||||
this.prompt = this.actionForm.actions[0].description.zh;
|
||||
} else if ("republish" === val) {
|
||||
this.data_to_webserver_View = false;
|
||||
this.data_to_mqtt_broker_View = false;
|
||||
this.do_nothing_View = false;
|
||||
this.inspectView = false;
|
||||
this.republishView = true;
|
||||
this.prompt = this.actionForm.actions[1].description.zh;
|
||||
} else if ("inspect" === val) {
|
||||
this.data_to_webserver_View = false;
|
||||
this.data_to_mqtt_broker_View = false;
|
||||
this.do_nothing_View = false;
|
||||
this.republishView = false;
|
||||
this.inspectView = true;
|
||||
this.prompt = this.actionForm.actions[2].description.zh;
|
||||
} else if ("data_to_mqtt_broker" === val) {
|
||||
getResources("").then((res) => {
|
||||
this.data_to_mqtt_broker_Form.resources = res.data.data;
|
||||
this.prompt = this.actionForm.actions[3].description.zh;
|
||||
|
||||
this.data_to_webserver_View = false;
|
||||
this.do_nothing_View = false;
|
||||
this.republishView = false;
|
||||
this.inspectView = false;
|
||||
this.data_to_mqtt_broker_View = true;
|
||||
});
|
||||
} else if ("data_to_webserver" === val) {
|
||||
getResources("").then((res) => {
|
||||
this.data_to_webserver_Form.resources = res.data.data;
|
||||
this.prompt = this.actionForm.actions[4].description.zh;
|
||||
|
||||
this.data_to_mqtt_broker_View = false;
|
||||
this.do_nothing_View = false;
|
||||
this.republishView = false;
|
||||
this.inspectView = false;
|
||||
this.data_to_webserver_View = true;
|
||||
});
|
||||
}
|
||||
},
|
||||
//添加响应动作
|
||||
saveAction(formName) {
|
||||
const action = {};
|
||||
const param = {};
|
||||
if ("do_nothing_Form" === formName) {
|
||||
action.name = this.do_nothing_Form.name;
|
||||
action.params = {};
|
||||
this.actions.push(action);
|
||||
this.cancelAction();
|
||||
} else if ("republishForm" === formName) {
|
||||
//校验表单
|
||||
this.$refs[formName].validate((valid) => {
|
||||
if (valid) {
|
||||
param.payload_tmpl = this.republishForm.params.payload_tmpl.default;
|
||||
param.target_topic = this.republishForm.params.target_topic.default;
|
||||
param.target_qos = this.republishForm.params.target_qos.default;
|
||||
action.name = this.republishForm.name;
|
||||
action.params = param;
|
||||
this.actions.push(action);
|
||||
this.cancelAction();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
} else if ("inspectForm" === formName) {
|
||||
action.name = this.inspectForm.name;
|
||||
action.params = {};
|
||||
this.actions.push(action);
|
||||
this.cancelAction();
|
||||
} else if ("data_to_mqtt_broker_Form" === formName) {
|
||||
//校验表单
|
||||
this.$refs[formName].validate((valid) => {
|
||||
if (valid) {
|
||||
param.$resource = this.data_to_mqtt_broker_Form.resourceId;
|
||||
if(this.data_to_mqtt_broker_Form.params.payload_tmpl != null){
|
||||
param.payload_tmpl =
|
||||
this.data_to_mqtt_broker_Form.params.payload_tmpl.default;
|
||||
}
|
||||
action.params = param;
|
||||
action.name = this.data_to_mqtt_broker_Form.name;
|
||||
this.actions.push(action);
|
||||
this.cancelAction();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
} else if ("data_to_webserver_Form" === formName) {
|
||||
//校验表单
|
||||
this.$refs[formName].validate((valid) => {
|
||||
if (valid) {
|
||||
param.$resource = this.data_to_webserver_Form.resourceId;
|
||||
if(this.data_to_webserver_Form.params.payload_tmpl != null){
|
||||
param.payload_tmpl =
|
||||
this.data_to_webserver_Form.params.payload_tmpl.default;
|
||||
}
|
||||
action.params = param;
|
||||
action.name = this.data_to_webserver_Form.name;
|
||||
this.actions.push(action);
|
||||
this.cancelAction();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
//删除动作参数
|
||||
deleteAction(index) {
|
||||
this.actions.splice(index, 1);
|
||||
},
|
||||
//添加规则引擎
|
||||
saveRule() {
|
||||
this.addRuleLoading = true;
|
||||
this.insertOrTestRule("insert");
|
||||
},
|
||||
testConnect() {
|
||||
this.insertOrTestRule("test");
|
||||
},
|
||||
|
||||
//公共方法
|
||||
insertOrTestRule(type) {
|
||||
//将需要的参数进行赋值
|
||||
const ruleParam = {
|
||||
ctx: {}
|
||||
};
|
||||
ruleParam.description = this.form.note;
|
||||
ruleParam.rawsql = this.form.sql_example;
|
||||
ruleParam.actions = this.actions;
|
||||
ruleParam.ctx.clientid = this.form.test_columns.clientid;
|
||||
ruleParam.ctx.payload = this.form.test_columns.payload;
|
||||
ruleParam.ctx.qos = this.form.test_columns.qos;
|
||||
ruleParam.ctx.topic = this.form.test_columns.topic;
|
||||
ruleParam.ctx.username = this.form.test_columns.username;
|
||||
ruleParam.ctx.clientid = this.form.test_columns.clientid;
|
||||
if ("test" === type) {
|
||||
testConnectRule(ruleParam).then((res) => {
|
||||
const code = res.data.code;
|
||||
if (0 === code) {
|
||||
this.content = JSON.stringify(res.data.data);
|
||||
} else {
|
||||
this.$modal.msgError(res.data.message);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
saveRule(ruleParam).then((res) => {
|
||||
const code = res.data.code;
|
||||
if (0 === code) {
|
||||
this.$modal.msgSuccess("添加规则引擎成功");
|
||||
this.cancel();
|
||||
this.getList();
|
||||
} else {
|
||||
this.$modal.msgError(res.data.message);
|
||||
}
|
||||
this.addRuleLoading = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.sql-tips {
|
||||
border: 4px dashed #d8d8d8;
|
||||
color: #71737d;
|
||||
}
|
||||
|
||||
.sql-tips {
|
||||
padding: 20px 0;
|
||||
border-radius: 4px;
|
||||
font-size: 15px;
|
||||
max-height: 480px;
|
||||
}
|
||||
|
||||
.sql-tips .title {
|
||||
padding: 0 20px 12px;
|
||||
}
|
||||
|
||||
.el-scrollbar {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.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 {
|
||||
line-height: 1.4;
|
||||
padding: 6px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.code {
|
||||
background-color: hsla(0, 0%, 87%, 0.8);
|
||||
}
|
||||
</style>
|
||||
@@ -40,7 +40,7 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
['/api/v4']: {
|
||||
target: `http://localhost:8081`,
|
||||
target: `http://wumei.live:8081`,
|
||||
changeOrigin: true,
|
||||
// logLevel: 'debug',
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user