wenhongquan %!s(int64=2) %!d(string=hai) anos
pai
achega
42e68dfd47

+ 2 - 2
ruoyi-admin/src/main/resources/application-dev.yml

@@ -102,13 +102,13 @@ spring:
 spring:
   redis:
     # 地址
-    host: ${REDIS_HOST:60.204.209.152}
+    host: ${REDIS_HOST:localhost}
     # 端口,默认为6379
     port: ${REDIS_PORT:6379}
     # 数据库索引
     database: ${REDIS_DB:0}
     # 密码(如没有密码请注释掉)
-    password: ${REDIS_PWD:123456}
+#    password: ${REDIS_PWD:}
     # 连接超时时间
     timeout: 10s
     # 是否开启ssl

+ 1 - 1
ruoyi-admin/src/main/resources/application.yml

@@ -102,7 +102,7 @@ sa-token:
   timeout: 86400
   # 多端不同 token 有效期 可查看 LoginHelper.loginByDevice 方法自定义
   # token最低活跃时间 (指定时间无操作就过期) 单位: 秒
-  active-timeout: 1800
+  active-timeout: 36000
   # 允许动态设置 token 有效期
   dynamic-active-timeout: true
   # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)

+ 1 - 13
ruoyi-system/src/main/java/com/ruoyi/data/domain/bo/TblMqttBo.java

@@ -24,27 +24,23 @@ import com.ruoyi.common.core.domain.BaseEntity;
 public class TblMqttBo extends BaseEntity {
 
     /**
-     * 
+     *
      */
-    @NotNull(message = "不能为空", groups = { EditGroup.class })
     private Long id;
 
     /**
      * 协议名称
      */
-    @NotBlank(message = "协议名称不能为空", groups = { AddGroup.class, EditGroup.class })
     private String protocolName;
 
     /**
      * 协议描述
      */
-    @NotBlank(message = "协议描述不能为空", groups = { AddGroup.class, EditGroup.class })
     private String protocolDesc;
 
     /**
      * 协议类型
      */
-    @NotBlank(message = "协议类型不能为空", groups = { AddGroup.class, EditGroup.class })
     private String protocolType;
 
     /**
@@ -56,19 +52,16 @@ public class TblMqttBo extends BaseEntity {
     /**
      * Mqtt主题
      */
-    @NotBlank(message = "Mqtt主题不能为空", groups = { AddGroup.class, EditGroup.class })
     private String serverTopic;
 
     /**
      * 账号
      */
-    @NotBlank(message = "账号不能为空", groups = { AddGroup.class, EditGroup.class })
     private String account;
 
     /**
      * 密码
      */
-    @NotBlank(message = "密码不能为空", groups = { AddGroup.class, EditGroup.class })
     private String password;
 
     /**
@@ -80,31 +73,26 @@ public class TblMqttBo extends BaseEntity {
     /**
      * 备注
      */
-    @NotBlank(message = "备注不能为空", groups = { AddGroup.class, EditGroup.class })
     private String remark;
 
     /**
      * 创建人
      */
-    @NotBlank(message = "创建人不能为空", groups = { AddGroup.class, EditGroup.class })
     private String creator;
 
     /**
      * 创建时间
      */
-    @NotNull(message = "创建时间不能为空", groups = { AddGroup.class, EditGroup.class })
     private Date ctime;
 
     /**
      * 更新人
      */
-    @NotBlank(message = "更新人不能为空", groups = { AddGroup.class, EditGroup.class })
     private String modifier;
 
     /**
      * 更新时间
      */
-    @NotNull(message = "更新时间不能为空", groups = { AddGroup.class, EditGroup.class })
     private Date utime;
 
 

+ 44 - 0
ruoyi-ui-vue3/src/api/data/mqtttopic.js

@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 查询mqtt配置列表
+export function listMqttTopic(query) {
+  return request({
+    url: '/data/mqttTopic/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询mqtt配置详细
+export function getMqttTopic(id) {
+  return request({
+    url: '/data/mqttTopic/' + id,
+    method: 'get'
+  })
+}
+
+// 新增mqtt配置
+export function addMqttTopic(data) {
+  return request({
+    url: '/data/mqttTopic',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改mqtt配置
+export function updateMqttTopic(data) {
+  return request({
+    url: '/data/mqttTopic',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除mqtt配置
+export function delMqttTopic(id) {
+  return request({
+    url: '/data/mqttTopic/' + id,
+    method: 'delete'
+  })
+}

+ 21 - 6
ruoyi-ui-vue3/src/views/device/device/index.vue

@@ -1,6 +1,6 @@
 <template>
   <div style="padding: 10px 15px">
-    <el-card class="box-card">
+    <el-card class="box-card" >
       <div style="display: flex; flex-direction: row; justify-content: space-between">
         <div>
           <div
@@ -38,11 +38,11 @@
         <el-col :span="24" style="padding-left: 10px">
           <el-table :data="devicetabledata" :border="true">
             <el-table-column type="selection" width="55"></el-table-column>
-            <el-table-column label="设备名称"></el-table-column>
-            <el-table-column label="型号"></el-table-column>
-            <el-table-column label="设备类型"></el-table-column>
-            <el-table-column label="生产厂商"></el-table-column>
-            <el-table-column label="制造商"></el-table-column>
+            <el-table-column prop="name" label="设备名称"></el-table-column>
+            <el-table-column prop="model" label="型号"></el-table-column>
+            <el-table-column prop="type" label="设备类型"></el-table-column>
+            <el-table-column prop="manufacturer" label="生产厂商"></el-table-column>
+            <el-table-column prop="producer" label="制造商"></el-table-column>
             <el-table-column label="操作">
               <template #default="scope">
                 <div>
@@ -84,6 +84,8 @@
 
 <script setup lang="ts" name="Units">
 import { ref } from "vue";
+import {listEquipment} from "@/api/data/equipment"
+
 
 const searchform = ref({
   devicename: "",
@@ -94,6 +96,19 @@ const gettbheight = () => {
 };
 
 const devicetabledata = ref([1]);
+
+
+
+const getalldata = ()=>{
+  listEquipment({}).then((res) => {
+    devicetabledata.value = res.rows;
+  });
+
+}
+getalldata();
+
+
+
 </script>
 
 <style lang="scss" scoped>

+ 455 - 0
ruoyi-ui-vue3/src/views/mqtt/index.vue

@@ -0,0 +1,455 @@
+<template>
+  <div style="padding: 10px 15px">
+    <el-row>
+      <el-col :span="16" style="padding-right: 10px" >
+        <el-card class="box-card">
+          <template #header>
+            <div class="card-header">
+              <span>Mqtt连接列表</span>
+               <el-button type="primary" @click="addlink">添加</el-button>
+            </div>
+
+          </template>
+          <el-table
+            @current-change="handleCurrentChange"   highlight-current-row
+            :data="tabledata"
+            ref="tableref"
+            border
+            style="width: 100%">
+            <el-table-column
+              prop="serverAddress"
+              label="连接地址">
+            </el-table-column>
+            <el-table-column
+              prop="account"
+              label="用户名"
+              width="100">
+            </el-table-column>
+            <el-table-column
+              prop="password"
+              label="密码"
+              width="100">
+            </el-table-column>
+
+            <el-table-column
+              prop="uuid"
+              label="客户端ID"
+              width="100">
+            </el-table-column>
+
+            <el-table-column
+              prop="status"
+              label="状态"
+              width="100">
+              <template #default="scope">
+                <span v-if="scope.row.status === 1">
+                  <el-tag type="success">启用</el-tag>
+                </span>
+                <span v-else>
+                  <el-tag type="danger">禁用</el-tag>
+                </span>
+              </template>
+            </el-table-column>
+            <el-table-column
+              prop="remark"
+              label="备注"
+              width="120"
+             >
+            </el-table-column>
+            <el-table-column
+              prop="name"
+              label="操作"
+              width="150">
+              <template #default="scope">
+
+                <el-button link @click="editlink(scope.row)">
+                  <el-tooltip effect="dark" content="编辑">
+                    <el-icon>
+                      <Edit />
+                    </el-icon>
+                  </el-tooltip>
+                </el-button>
+                <el-button link v-if="scope.row.status == 0" @click="doedit(scope.row,1)">
+                  <el-tooltip effect="dark" content="启用" >
+                    <el-icon>
+                      <VideoPlay />
+                    </el-icon>
+                  </el-tooltip>
+                </el-button>
+                <el-button link v-if="scope.row.status == 1"  @click="doedit(scope.row,0)" >
+                  <el-tooltip effect="dark" content="停止" >
+                    <el-icon>
+                      <VideoPause />
+                    </el-icon>
+                  </el-tooltip>
+                </el-button>
+                <el-popconfirm title="确定删除该连接?"  @confirm="dellink(scope.row)">
+                  <template #reference>
+                    <el-button link
+                    ><el-tooltip effect="dark" content="删除"
+                    ><el-icon><Delete /></el-icon></el-tooltip
+                    ></el-button>
+                  </template>
+                </el-popconfirm>
+              </template>
+            </el-table-column>
+          </el-table>
+
+
+        </el-card>
+      </el-col>
+      <el-col :span="8"  >
+        <el-card class="box-card">
+          <template #header>
+            <div class="card-header">
+              <span>主题列表</span>
+              <el-button type="primary" @click="addtopic">添加</el-button>
+            </div>
+
+
+          </template>
+          <el-table :data="topictable" border style="width: 100%">
+            <el-table-column
+              prop="name"
+              label="名称"
+            >
+            </el-table-column>
+            <el-table-column
+              prop="qos"
+              label="QOS"
+            >
+            </el-table-column>
+            <el-table-column
+              prop="status"
+              label="操作"
+            >
+              <template #default="scope">
+                <el-button link @click="edittopic(scope.row)">
+                  <el-tooltip effect="dark" content="编辑">
+                    <el-icon>
+                      <Edit />
+                    </el-icon>
+                  </el-tooltip>
+                </el-button>
+                <el-popconfirm title="确定删除该主题?"  @confirm="deltopic(scope.row)">
+                  <template #reference>
+                    <el-button link
+                    ><el-tooltip effect="dark" content="删除"
+                    ><el-icon><Delete /></el-icon></el-tooltip
+                    ></el-button>
+                  </template>
+                </el-popconfirm>
+              </template>
+            </el-table-column>
+
+          </el-table>
+
+        </el-card>
+      </el-col>
+
+    </el-row>
+    <el-dialog v-model="mqtteditshow" :title="`${showtype==2?'编辑':'添加'}MQTT连接`" width="30%" top="10%">
+      <el-descriptions column="1">
+        <el-descriptions-item >
+          <template #label>
+            <div style="display: inline-block;min-width: 100px;text-align: right;    vertical-align: top;">
+              连接地址
+            </div>
+          </template>
+          <div class="content-w" >
+            <el-input v-model="currentmqtt.serverAddress" placeholder="请输入" />
+          </div>
+        </el-descriptions-item>
+        <el-descriptions-item label="用户名">
+          <template #label>
+            <div style="display: inline-block;min-width: 100px;text-align: right;    vertical-align: top;">
+              用户名
+            </div>
+          </template>
+          <div class="content-w" >
+            <el-input v-model="currentmqtt.account" placeholder="请输入" />
+          </div>
+        </el-descriptions-item>
+        <el-descriptions-item label="密码">
+          <template #label>
+            <div style="display: inline-block;min-width: 100px;text-align: right;    vertical-align: top;">
+              密码
+            </div>
+          </template>
+          <div class="content-w" >
+            <el-input v-model="currentmqtt.password" placeholder="请输入" />
+          </div>
+        </el-descriptions-item>
+
+        <el-descriptions-item >
+          <template #label>
+            <div style="display: inline-block;min-width: 100px;text-align: right;    vertical-align: top;">
+              客户端ID
+            </div>
+          </template>
+          <div class="content-w" >
+            <el-input v-model="currentmqtt.uuid" placeholder="请输入" />
+            <el-button type="primary" link @click="randomuuid" style="margin-left: 10px">随机生成</el-button>
+          </div>
+        </el-descriptions-item>
+        <el-descriptions-item >
+          <template #label>
+            <div style="display: inline-block;min-width: 100px;text-align: right;    vertical-align: top;">
+              备注
+            </div>
+          </template>
+          <div class="content-w" >
+            <el-input type="textarea" v-model="currentmqtt.remark" placeholder="请输入" />
+          </div>
+        </el-descriptions-item>
+
+      </el-descriptions>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="mqtteditshow = false">取 消</el-button>
+        <el-button type="primary" @click="savelink">保 存</el-button>
+      </div>
+    </el-dialog>
+
+    <el-dialog v-model="topiceditshow" :title="`${topicshowtype==1?'添加':'编辑'}主题`" width="30%" top="10%">
+      <el-descriptions column="1">
+
+        <el-descriptions-item >
+          <template #label>
+            <div style="display: inline-block;min-width: 100px;text-align: right;    vertical-align: top;">
+              主题地址
+            </div>
+          </template>
+          <div class="content-w" >
+            <el-input v-model="currenttopic.name" placeholder="请输入" />
+          </div>
+        </el-descriptions-item>
+
+        <el-descriptions-item >
+          <template #label>
+            <div style="display: inline-block;min-width: 100px;text-align: right;    vertical-align: top;">
+              QOS
+            </div>
+          </template>
+          <div class="content-w" >
+            <el-select v-model="currenttopic.qos" placeholder="请选择">
+              <el-option label="0" value="0"></el-option>
+              <el-option label="1" value="1"></el-option>
+              <el-option label="2" value="2"></el-option>
+            </el-select>
+          </div>
+        </el-descriptions-item>
+
+      </el-descriptions>
+
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="topiceditshow = false">取 消</el-button>
+        <el-button type="primary" @click="savetopic">保 存</el-button>
+      </div>
+    </el-dialog>
+
+  </div>
+
+</template>
+
+<script setup lang="ts" name="Units">
+import {onMounted, ref} from "vue";
+import {useRoute, useRouter} from "vue-router";
+import {listMqtt,delMqtt,addMqtt,updateMqtt} from "@/api/data/mqtt"
+import {ElMessage} from "element-plus";
+
+
+const route = useRoute();
+const router = useRouter();
+
+const mqtteditshow = ref(false);
+const tableref = ref();
+const tabledata = ref([])
+const currentmqtt = ref({})
+const showtype= ref(1)
+const topictable = ref([])
+const topiceditshow = ref(false);
+const topicshowtype = ref(1)
+
+
+const currenttopic = ref({
+  name:"",
+  qos:0
+})
+const lasttopic = ref({
+  name:"",
+  qos:0
+})
+const initdata = ()=>{
+  currentmqtt.value = {
+    serverAddress:"",
+    account:"",
+    password:"",
+    uuid:"",
+    status:0,
+    remark:"",
+  }
+}
+
+const getmqttlist = ()=>{
+  listMqtt({pageSize:10000}).then(res=>{
+      //@ts-ignore
+      tabledata.value = res.rows;
+      if(currentmqtt.value.id!=undefined && currentmqtt.value.id!=null){
+        tableref.value.setCurrentRow(currentmqtt);
+      }else{
+        tableref.value.setCurrentRow(tabledata.value[0]);
+      }
+  })
+}
+
+
+onMounted(()=>{
+  initdata();
+
+  getmqttlist();
+})
+
+const randomuuid = ()=>{
+  currentmqtt.value.uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
+    var r = Math.random() * 16 | 0, v = c == "x"? r : (r & 0x3 | 0x8);
+    return v.toString(16);
+  });
+}
+
+const addlink = ()=>{
+  initdata();
+   mqtteditshow.value = true;
+}
+
+const edittopic = (item)=>{
+    topiceditshow.value = true;
+    topicshowtype.value = 2;
+    currenttopic.value = item;
+    lasttopic.value = item;
+}
+const deltopic = (item)=>{
+  topictable.value = topictable.value.filter(v=>v.name!=item.name);
+  currentmqtt.value.serverTopic = JSON.stringify(topictable.value);
+  updateMqtt(currentmqtt.value).then(res=>{
+    ElMessage({
+      type:'success',
+      message: '修改成功',
+    });
+    getmqttlist();
+  })
+}
+const addtopic = ()=>{
+  topiceditshow.value = true;
+  topicshowtype.value = 1;
+  currenttopic.value = {
+    name:"",
+    qos:0
+  };
+}
+
+
+const savetopic = ()=>{
+
+  let list = topictable.value.filter(v=>v.name==currenttopic.value.name && v.qos==currenttopic.value.qos);
+  if(list.length>0){
+    ElMessage({
+      type:'error',
+      message: '存在相同的topic',
+    });
+    return;
+  }
+
+
+
+  if(topicshowtype.value==1){
+    topictable.value.push(currenttopic.value);
+    topiceditshow.value = false;
+  }else{
+
+    topictable.value.push(currenttopic.value);
+    topictable.value = topictable.value.filter(v=>v.name!=lasttopic.value.name);
+  }
+  currentmqtt.value.serverTopic = JSON.stringify(topictable.value);
+  topiceditshow.value = false;
+  updateMqtt(currentmqtt.value).then(res=>{
+    ElMessage({
+      type:'success',
+      message: '修改成功',
+    });
+    getmqttlist();
+  })
+}
+
+const doedit = (item,status)=>{
+   currentmqtt.value = item;
+   currentmqtt.value.status = status;
+   updateMqtt(currentmqtt.value).then(res=>{
+     ElMessage({
+       type:'success',
+       message: '成功',
+     });
+     getmqttlist();
+   });
+}
+
+const handleCurrentChange = (row)=>{
+  currentmqtt.value = row;
+  //获取topic
+  topictable.value = currentmqtt.value.serverTopic ? JSON.parse(currentmqtt.value.serverTopic) : [];
+
+}
+const dellink = (item)=>{
+  delMqtt(item.id).then(res=>{
+    getmqttlist();
+    ElMessage({
+      type:'success',
+      message: '删除成功',
+    });
+  })
+}
+
+const savelink = ()=>{
+  if(currentmqtt.value.id==undefined||currentmqtt.value.id==null){
+    addMqtt(currentmqtt.value).then(res=>{
+      getmqttlist();
+      mqtteditshow.value = false;
+      ElMessage({
+        type:'success',
+        message: '保存成功',
+      });
+    })
+  }else{
+    updateMqtt(currentmqtt.value).then(res=>{
+      getmqttlist();
+      mqtteditshow.value = false;
+      ElMessage({
+        type:'success',
+        message: '修改成功',
+      });
+    })
+  }
+}
+
+const editlink = (item)=>{
+  mqtteditshow.value = true;
+  currentmqtt.value = item;
+}
+
+
+</script>
+
+<style lang="scss" scoped>
+.card-header {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+}
+.content-w {
+  display: inline-flex;
+  width: 300px;
+}
+.dialog-footer{
+  text-align: right;
+  padding-top: 30px;
+}
+</style>