wenhongquan 1 ano atrás
pai
commit
5c1565b9bc

+ 12 - 0
ruoyi-system/src/main/java/com/ruoyi/data/controller/TblDataController.java

@@ -131,8 +131,11 @@ public class TblDataController extends BaseController {
 
                 AtomicReference<Date> dataBo12Time = new AtomicReference<>();
                 try {
+                    Map<String,String> location=new HashMap<>();
                     MqttSensorDataBo dataBo12 = CacheUtils.get("sensorData", tblSensorVo.getId().toString());
                     dataBo12.getData().forEach(bo -> {
+                        if(bo.getName().contains("lat")) location.put("lat",bo.getValue());
+                        if(bo.getName().contains("lon")) location.put("lon",bo.getValue());
                         if (dataBo12Time.get() == null) dataBo12Time.set(bo.getCreateTime());
                         if (bo.getCreateTime().getTime() > dataBo12Time.get().getTime()) {
                             dataBo12Time.set(bo.getCreateTime());
@@ -141,6 +144,9 @@ public class TblDataController extends BaseController {
                     if(dataBo12Time.get()!=null){
                         a.put("lasttime", DateUtil.formatDateTime(dataBo12Time.get()));
                     }
+                    if(location.values().size()>0){
+                        a.put("location",location);
+                    }
                 }catch (Exception e){}
 
 
@@ -161,13 +167,19 @@ public class TblDataController extends BaseController {
 
                 AtomicReference<Date> dataBo12Time = new AtomicReference<>();
                 try {
+                    Map<String,String> location=new HashMap<>();
                     MqttSensorDataBo dataBo12 = CacheUtils.get("sensorData", tblSensorVo.getId().toString());
                     dataBo12.getData().forEach(bo -> {
+                        if(bo.getName().contains("lat")) location.put("lat",bo.getValue());
+                        if(bo.getName().contains("lon")) location.put("lon",bo.getValue());
                         if (dataBo12Time.get() == null) dataBo12Time.set(bo.getCreateTime());
                         if (bo.getCreateTime().getTime() > dataBo12Time.get().getTime()) {
                             dataBo12Time.set(bo.getCreateTime());
                         }
                     });
+                    if(location.values().size()>0){
+                        a.put("location",location);
+                    }
                 }catch (Exception e){}
                 if(dataBo12Time.get()==null){
                     t = new HashMap<>();

+ 2 - 0
ruoyi-system/src/main/java/com/ruoyi/data/controller/TblEquipmentSbookController.java

@@ -103,6 +103,7 @@ public class TblEquipmentSbookController extends BaseController {
         return R.ok(iTblEquipmentSbookService.queryById(id));
     }
 
+
     /**
      * 新增设备台账
      */
@@ -139,6 +140,7 @@ public class TblEquipmentSbookController extends BaseController {
         return toAjax(iTblEquipmentSbookService.deleteWithValidByIds(Arrays.asList(ids), true));
     }
 
+
 //    /**
 //     * 根据网关查询所有设备列表
 //     */

+ 12 - 1
ruoyi-system/src/main/java/com/ruoyi/data/service/impl/MqttServiceImpl.java

@@ -233,7 +233,7 @@ public class MqttServiceImpl implements MqttService {
         MQTTConnect mqttConnect = new MQTTConnect();
         try {
             System.out.println(mqttUrl);
-            mqttConnect.createMqttClient(mqttUrl, UUID.fastUUID().toString(),mqttUser,mqttPassword,new Callback());
+            mqttConnect.createMqttClient(mqttUrl, UUID.fastUUID().toString(),mqttUser,mqttPassword,new Callback("main"));
             mqttConnect.sub(mqttTopic);
         }catch (Exception e){
             e.printStackTrace();
@@ -426,6 +426,13 @@ public class MqttServiceImpl implements MqttService {
 
     class Callback implements MqttCallback {
 
+        private String type;
+        Callback(){
+            type= "default";
+        }
+        Callback(String type){
+            this.type = type;
+        }
         /**
          * MQTT 断开连接会执行此方法
          */
@@ -433,6 +440,10 @@ public class MqttServiceImpl implements MqttService {
         public void connectionLost(Throwable throwable) {
             log.info("断开了MQTT连接111 :{}", throwable.getMessage());
             log.error(throwable.getMessage(), throwable);
+            if(this.type.equals("main")){
+                MqttServiceImpl.this.createMqtt(new TblMqttBo());
+            }
+//            MqttServiceImpl.this.createMqtt(new TblMqttBo());
         }
 
         /**

+ 1 - 0
ruoyi-ui-vue3/index.html

@@ -10,6 +10,7 @@
   <link rel="stylesheet" href="./sdk/sdk.css" />
     <link rel="stylesheet" href="./sdk/helper.css" />
     <link rel="stylesheet" href="./sdk/iconfont.css" />
+         <script src="/jess/jessibuca.js"></script>
   <title>物联网平台</title>
   <!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
   <style>

+ 3 - 0
ruoyi-ui-vue3/src/views/alarm/alarmmanager/index.vue

@@ -121,6 +121,9 @@
         <el-form-item label="处理内容" >
           <el-input type="textarea" v-model="currentdata.handleContent" placeholder="请输入"></el-input>
         </el-form-item>
+         <el-form-item label="处理描述" >
+          <el-input type="textarea" v-model="currentdata.remark" placeholder="请输入"></el-input>
+        </el-form-item>
       </el-form>
 
       <div slot="footer" class="dialog-footer" style="text-align: right">

+ 36 - 2
ruoyi-ui-vue3/src/views/device/camera/index.vue

@@ -26,7 +26,8 @@
       </el-col>
       <el-col :span="18"  v-if="isvideoshow">
         <div style="height: 100%;">
-           <iframe id="FrameID" :key="currenturl" style="width: 100%;height:100%" :src="currenturl"/>
+          <div id="container" style="margin-top: 0px;width:100%;height:80vh"></div>
+           <!-- <iframe id="FrameID" :key="currenturl" style="width: 100%;height:100%" :src="currenturl"/> -->
         </div>
       </el-col>
       <el-col :span="18" v-if="!isvideoshow">
@@ -155,9 +156,36 @@ const handleClick = (node) => {
   } else {
     searchform.value.id = node.id
   }
+    isvideoshow.value = true;
+
+    setTimeout(() => {
+      var $container = document.getElementById('container');
+   jessibuca = new Jessibuca({
+            container: $container,
+            videoBuffer: 0.2, // 缓存时长
+            isResize: false,
+           text: "",
+            decoder:"/iot/jess/decoder.js",
+            loadingText: "",
+            useMSE: false,
+            debug: true,
+            showBandwidth: true, // 显示网速
+            operateBtns: {
+                fullscreen: true,
+                screenshot: false,
+                play: true,
+                audio: false,
+                recorder: false
+            },
+            forceNoOffscreen: true,
+            isNotMute: false,
+   },);
+         jessibuca.play(node.voiceOutCode);
+    }, 1000);
+
 
   currenturl.value = node.remark;
-  isvideoshow.value = true;
+
 
 
 
@@ -346,4 +374,10 @@ getVideoList();
 .layui-disabled{
     color: #000 !important;
   }
+
+   #container {
+            background: rgba(13, 14, 27, 0.7);
+            width: 50vw;
+            height: 398px;
+        }
 </style>

+ 35 - 3
ruoyi-ui-vue3/src/views/device/equipmentdash/index.vue

@@ -77,7 +77,7 @@
               <span>设备台账</span>
               <div>
                 <el-button type="primary" @click="goadd">添加</el-button>
-                <el-button type="danger">批量删除</el-button>
+                <el-button type="danger" @click="deleteall">批量删除</el-button>
                 <el-button type="primary" plain @click="ziduanshow = true">显示字段</el-button>
               </div>
             </div>
@@ -85,7 +85,7 @@
 
           <el-row>
             <el-col :span="24" style="padding-left: 10px">
-              <el-table :data="devicetabledata" :border="true">
+              <el-table :data="devicetabledata" :border="true" ref="tableref">
                 <el-table-column type="selection" width="55" />
                 <el-table-column v-for="item in columns.filter(i => i.visible)" :prop="item.prop" :label="item.label">
                   <template #default="scope" v-if="item.isTemplate">
@@ -184,10 +184,12 @@ import "@layui/layui-vue/lib/index.css";
 
 import { useRoute, useRouter } from "vue-router";
 import { listEquipmentOrganizational, addEquipmentOrganizational, updateEquipmentOrganizational, delEquipmentOrganizational } from "@/api/data/equipmentOrganizational"
-import { listEquipmentSbook, updateEquipmentSbook } from "@/api/data/equipmentSbook"
+import { listEquipmentSbook, updateEquipmentSbook,delEquipmentSbook } from "@/api/data/equipmentSbook"
 import { getDicts } from '@/api/system/dict/data'
 import { cloneDeep } from "lodash";
 
+import { ElMessage, ElMessageBox } from "element-plus";
+
 
 
 const route = useRoute();
@@ -307,6 +309,7 @@ const onchangepage = (page) => {
   getlistEquipmentSbook();
 }
 
+const tableref = ref(null);
 const getTreedata = () => {
   listEquipmentOrganizational({ pageSize: 10000 }).then(res => {
     const { rows, total, page, size } = res;
@@ -323,6 +326,35 @@ const getData = (str, data, prop) => {
   console.log(value);
   return value
 }
+
+
+const deleteall = () => {
+    let selected = tableref.value.getSelectionRows();
+    if (selected.length == 0) {
+        ElMessage.warning("请选择要删除的行");
+        return;
+    }
+
+    if (selected.length > 0) {
+        ElMessageBox.confirm(
+            `是否删除${selected.length}条数据`,
+            "警告", {
+                confirmButtonText: "确认",
+                cancelButtonText: "取消",
+                type: 'warning',
+            }
+        ).then(() => {
+
+            delEquipmentSbook(selected.map(i => i.id).join(",")).then((res) => {
+                ElMessage.success("删除成功");
+                getlistEquipmentSbook();
+            })
+
+        });
+    }
+
+}
+
 // function getlistEquipmentSbook(){
 //   listEquipmentSbook({ ...searchform.value, pageSize: pagedata.value.size, pageNum: pagedata.value.current }).then(res => {
 //     const { rows, total, page, size } = res;

+ 643 - 539
ruoyi-ui-vue3/src/views/device/sensordash/index.vue

@@ -1,27 +1,32 @@
 <template>
-    <div style="padding: 10px 15px">
-        <el-row>
-            <el-col :span="6" style="padding-right: 10px">
-                <el-card class="box-card">
-                    <template #header>
-                <div class="card-header">
-                  <span>设备区域</span>
-                  <div style="display: none">
-                    <el-button type="primary">
-                      添加
-                    </el-button>
-                  </div>
-                </div>
-</template>
+  <div style="padding: 10px 15px">
+    <el-row>
+      <el-col :span="6" style="padding-right: 10px">
+        <el-card class="box-card">
+          <template #header>
+            <div class="card-header">
+              <span>设备区域</span>
+              <div style="display: none">
+                <el-button type="primary"> 添加 </el-button>
+              </div>
+            </div>
+          </template>
           <div class="tree">
-            <LayTree :data="data" :tail-node-icon="false" :onlyIconControl="true" v-model:selectedKey="selectedKey"
-              @node-click="handleClick">
-<template #title="{ data }">
-    <div style="display: flex;align-items: center;">
-        <el-icon v-if="(data.id + '').indexOf('device') != -1">
-            <Cpu />
-        </el-icon> {{ data.name }}</div>
-</template>
+            <LayTree
+              :data="data"
+              :tail-node-icon="false"
+              :onlyIconControl="true"
+              v-model:selectedKey="selectedKey"
+              @node-click="handleClick"
+            >
+              <template #title="{ data }">
+                <div style="display: flex; align-items: center">
+                  <el-icon v-if="(data.id + '').indexOf('device') != -1">
+                    <Cpu />
+                  </el-icon>
+                  {{ data.name }}
+                </div>
+              </template>
             </LayTree>
           </div>
         </el-card>
@@ -30,23 +35,36 @@
       <el-col :span="18">
         <el-card class="box-card">
           <div style="display: flex; flex-direction: row; justify-content: space-between">
-            <div style="display: flex; flex-direction: row;">
-              <div style="
+            <div style="display: flex; flex-direction: row">
+              <div
+                style="
                   display: flex;
                   flex-direction: row;
                   flex-wrap: nowrap;
                   align-items: center;
-                ">
-                <div style="font-size: 12px; width: 100px;">传感器编号:</div>
+                "
+              >
+                <div style="font-size: 12px; width: 100px">传感器编号:</div>
                 <el-input v-model="searchform.id" placeholder="请输入"></el-input>
               </div>
-              <div style="
+              <div
+                style="
                   display: flex;
                   flex-direction: row;
                   flex-wrap: nowrap;
                   align-items: center;
-                ">
-                <div style="font-size: 12px; width: 80px;margin-right: 10px;text-align: right;">描述:</div>
+                "
+              >
+                <div
+                  style="
+                    font-size: 12px;
+                    width: 80px;
+                    margin-right: 10px;
+                    text-align: right;
+                  "
+                >
+                  描述:
+                </div>
                 <el-input v-model="searchform.desc" placeholder="请输入"></el-input>
               </div>
             </div>
@@ -57,90 +75,108 @@
           </div>
         </el-card>
 
-        <el-card class="box-card" style="margin-top: 10px;">
-<template #header>
-    <div class="card-header">
-        <span>传感器台账</span>
-        <div>
-            <el-button type="primary" @click="handleImport">导入</el-button>
-            <el-button type="primary" @click="goadd">添加</el-button>
-            <el-button type="danger" @click="deleteall">批量删除</el-button>
-            <el-button type="primary" plain @click="ziduanshow = true">显示字段</el-button>
-        </div>
-    </div>
-</template>
+        <el-card class="box-card" style="margin-top: 10px">
+          <template #header>
+            <div class="card-header">
+              <span>传感器台账</span>
+              <div>
+                <el-button type="primary" @click="handleImport">导入</el-button>
+                <el-button type="primary" @click="goadd">添加</el-button>
+                <el-button type="danger" @click="deleteall">批量删除</el-button>
+                <el-button type="primary" plain @click="ziduanshow = true"
+                  >显示字段</el-button
+                >
+              </div>
+            </div>
+          </template>
 
           <el-row>
             <el-col :span="24" style="padding-left: 10px">
               <el-table :data="devicetabledata" ref="tableref" :border="true">
                 <el-table-column type="selection" width="55" />
-                <el-table-column v-for="item in cloumdata.filter(i => i.visible)" :prop="item.prop"
-                  :label="item.label"></el-table-column>
+                <el-table-column
+                  v-for="item in cloumdata.filter((i) => i.visible)"
+                  :prop="item.prop"
+                  :label="item.label"
+                ></el-table-column>
                 <el-table-column label="协议">
-<template #default="scope">
-    <div>
-        {{ getProtocalTypeName(scope.row) }}
-    </div>
-</template>
+                  <template #default="scope">
+                    <div>
+                      {{ getProtocalTypeName(scope.row) }}
+                    </div>
+                  </template>
                 </el-table-column>
                 <el-table-column label="操作">
-<template #default="scope">
-    <div>
-        <el-button link @click="lookdata(scope.row)">
-            <el-tooltip effect="dark" content="查看数据">
-                <el-icon>
-                    <PieChart />
-                </el-icon>
-            </el-tooltip>
-        </el-button>
-
-        <el-button link @click="goedit(scope.row)">
-            <el-tooltip effect="dark" content="编辑">
-                <el-icon>
-                    <Edit />
-                </el-icon>
-            </el-tooltip>
-        </el-button>
-        <el-button link @click="cdbd(scope.row)">
-            <el-tooltip effect="dark" content="测点绑定">
-                <el-icon>
-                    <VideoPlay />
-                </el-icon>
-            </el-tooltip>
-        </el-button>
-        <el-popconfirm title="确定删除该传感器?" @confirm="deleterow(scope.row)">
-            <template #reference>
-                              <el-button link><el-tooltip effect="dark" content="删除"><el-icon>
-                                    <Delete />
-                                  </el-icon></el-tooltip></el-button>
-</template>
+                  <template #default="scope">
+                    <div>
+                      <el-button link @click="lookdata(scope.row)">
+                        <el-tooltip effect="dark" content="查看数据">
+                          <el-icon>
+                            <PieChart />
+                          </el-icon>
+                        </el-tooltip>
+                      </el-button>
+
+                      <el-button link @click="goedit(scope.row)">
+                        <el-tooltip effect="dark" content="编辑">
+                          <el-icon>
+                            <Edit />
+                          </el-icon>
+                        </el-tooltip>
+                      </el-button>
+                      <el-button link @click="cdbd(scope.row)">
+                        <el-tooltip effect="dark" content="测点绑定">
+                          <el-icon>
+                            <Link/>
+                          </el-icon>
+                        </el-tooltip>
+                      </el-button>
+                       <el-button link @click="scope.row['isOnline']=!scope.row.isOnline">
+                        <el-tooltip effect="dark" :content="scope.row.isOnline?'停止':'启动'">
+                          <el-icon>
+                            <VideoPlay v-if="!scope.row.isOnline"/>
+                            <VideoPause  v-if="scope.row.isOnline"/>
+                          </el-icon>
+                        </el-tooltip>
+                      </el-button>
+                      <el-popconfirm
+                        title="确定删除该传感器?"
+                        @confirm="deleterow(scope.row)"
+                      >
+                        <template #reference>
+                          <el-button link
+                            ><el-tooltip effect="dark" content="删除"
+                              ><el-icon>
+                                <Delete /> </el-icon></el-tooltip
+                          ></el-button>
+                        </template>
                       </el-popconfirm>
                     </div>
                   </template>
                 </el-table-column>
               </el-table>
-
-
             </el-col>
-            <el-col :span="24" style="margin-top: 10px;">
-              <el-pagination style="float: right;" small background layout="prev, pager, next" :total="pagedata.total"
-                :page-size="pagedata.pageSize" :current-page="pagedata.pageNum" @current-change="onchangepage"
-                class="mt-4" />
+            <el-col :span="24" style="margin-top: 10px">
+              <el-pagination
+                style="float: right"
+                small
+                background
+                layout="prev, pager, next"
+                :total="pagedata.total"
+                :page-size="pagedata.pageSize"
+                :current-page="pagedata.pageNum"
+                @current-change="onchangepage"
+                class="mt-4"
+              />
             </el-col>
           </el-row>
         </el-card>
       </el-col>
     </el-row>
 
-
     <el-dialog title="测点配置" v-model="cdbdshow">
-
       <div style="display: flex; flex-direction: row; justify-content: space-between">
-        <div style="display: flex; flex-direction: row;">
-
-
-
-        </div>
+        <div style="display: flex; flex-direction: row"></div>
         <div>
           <el-button type="primary" plain @click="addrow">新增</el-button>
         </div>
@@ -148,169 +184,221 @@
 
       <el-table :data="pointdata" style="margin-top: 15px" height="400px">
         <el-table-column label="变量名" prop="name">
-<template #default="scope">
-    <el-input v-model="scope.row.name">
-    </el-input>
-</template>
+          <template #default="scope">
+            <el-input v-model="scope.row.name"> </el-input>
+          </template>
         </el-table-column>
         <el-table-column label="名称" prop="label">
-<template #default="scope">
-    <el-input v-model="scope.row.label">
-    </el-input>
-</template>
+          <template #default="scope">
+            <el-input v-model="scope.row.label"> </el-input>
+          </template>
         </el-table-column>
         <el-table-column label="单位" prop="unitId">
-<template #default="scope">
-    <el-popover placement="right" :width="400" trigger="click">
-        <template #reference>
-                    <el-button plain>{{ `${scope.row.unit}(${scope.row.unitType})` }}</el-button>
-</template>
-              <el-table :data="allUnit" height="500"
-                @cellClick="(row1) => { scope.row.unit = row1.unitName; scope.row.unitType = row1.unitSymbol; }">
+          <template #default="scope">
+            <el-popover placement="right" :width="400" trigger="click">
+              <template #reference>
+                <el-button plain>{{
+                  `${scope.row.unit}(${scope.row.unitType})`
+                }}</el-button>
+              </template>
+              <el-table
+                :data="allUnit"
+                height="500"
+                @cellClick="
+                  (row1) => {
+                    scope.row.unit = row1.unitName;
+                    scope.row.unitType = row1.unitSymbol;
+                  }
+                "
+              >
                 <el-table-column property="unitName" label="单位名称" />
                 <el-table-column property="unitSymbol" label="单位符号" />
                 <el-table-column property="unitType" label="分类" />
               </el-table>
             </el-popover>
-
           </template>
         </el-table-column>
         <el-table-column label="描述" prop="desc">
-<template #default="scope">
-    <el-input v-model="scope.row.desc">
-    </el-input>
-</template>
+          <template #default="scope">
+            <el-input v-model="scope.row.desc"> </el-input>
+          </template>
         </el-table-column>
         <el-table-column label="点表配置" prop="dataPointId">
-<template #default="scope">
-    <span v-if="currentsensor.protocalType == 3">无需配置</span>
-    <div v-if="currentsensor.protocalType != 3">
-        <el-popover placement="right" :width="400" trigger="click">
-            <template #reference>
-                      <el-button plain>{{ `${(currentdatapointlist.find(i => (i.id + "") == scope.row.dataPointId) ??
-            { name: '失效' }).name}` }}</el-button>
-</template>
-                <el-table :data="currentdatapointlist" @cellClick="(row1) => { scope.row.dataPointId = row1.id; }">
+          <template #default="scope">
+            <span v-if="currentsensor.protocalType == 3">无需配置</span>
+            <div v-if="currentsensor.protocalType != 3">
+              <el-popover placement="right" :width="400" trigger="click">
+                <template #reference>
+                  <el-button plain>{{
+                    `${
+                      (
+                        currentdatapointlist.find(
+                          (i) => i.id + "" == scope.row.dataPointId
+                        ) ?? { name: "失效" }
+                      ).name
+                    }`
+                  }}</el-button>
+                </template>
+                <el-table
+                  :data="currentdatapointlist"
+                  @cellClick="
+                    (row1) => {
+                      scope.row.dataPointId = row1.id;
+                    }
+                  "
+                >
                   <el-table-column property="name" label="点位名称" />
                   <el-table-column property="valueType" label="变量类型" />
                   <el-table-column property="addr" label="地址" />
                 </el-table>
               </el-popover>
             </div>
-
-
           </template>
         </el-table-column>
         <el-table-column label="操作">
-               <template #default="scope">
-                   <el-popconfirm title="确定删除该测点?" @confirm="deldatapoint(scope.$index)">
-                       <template #reference>
-                                   <el-button link><el-tooltip effect="dark" content="删除"><el-icon>
-                                         <Delete />
-                                       </el-icon></el-tooltip></el-button>
-               </template>
+          <template #default="scope">
+            <el-popconfirm title="确定删除该测点?" @confirm="deldatapoint(scope.$index)">
+              <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>
 
-
-        <template #footer>
-            <div class="dialog-footer">
-                <el-button @click="cdbdshow = false;"> 取消 </el-button>
-                <el-button type="primary" @click="dosave"> 保存 </el-button>
-            </div>
-        </template>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="cdbdshow = false"> 取消 </el-button>
+          <el-button type="primary" @click="dosave"> 保存 </el-button>
+        </div>
+      </template>
     </el-dialog>
 
-    <el-dialog title="字段显示" v-model="ziduanshow" width="50%" @close="ziduanshow = false">
-      <div style="display: flex;flex-wrap: wrap;align-content: center;justify-content: center;align-items: center;">
-        <el-checkbox v-for="item in cloumdata" v-model="item.visible" :label="item.label" size="large" />
+    <el-dialog
+      title="字段显示"
+      v-model="ziduanshow"
+      width="50%"
+      @close="ziduanshow = false"
+    >
+      <div
+        style="
+          display: flex;
+          flex-wrap: wrap;
+          align-content: center;
+          justify-content: center;
+          align-items: center;
+        "
+      >
+        <el-checkbox
+          v-for="item in cloumdata"
+          v-model="item.visible"
+          :label="item.label"
+          size="large"
+        />
       </div>
-
     </el-dialog>
 
-    <el-dialog title="测点数据查看" v-model="datashow" width="50%" @close="datashow = false">
+    <el-dialog
+      title="测点数据查看"
+      v-model="datashow"
+      width="50%"
+      @close="datashow = false"
+    >
       <div>
         <!--        显示测点实时数据-->
-        <el-table @cellClick="doshowhistory" :data="JSON.parse(currentsensor.datapoints)" style="margin-top: 15px"
-          height="250px">
+        <el-table
+          @cellClick="doshowhistory"
+          :data="JSON.parse(currentsensor.datapoints)"
+          style="margin-top: 15px"
+          height="250px"
+        >
           <el-table-column label="变量名" prop="name">
-             <template #default="scope">
-                 <span>{{ scope.row.name }}</span>
-             </template>
+            <template #default="scope">
+              <span>{{ scope.row.name }}</span>
+            </template>
           </el-table-column>
           <el-table-column label="名称" prop="name">
-             <template #default="scope">
-                 <span>{{ scope.row.label }}</span>
-             </template>
+            <template #default="scope">
+              <span>{{ scope.row.label }}</span>
+            </template>
           </el-table-column>
           <el-table-column label="数值" prop="name">
-             <template #default="scope">
-                 <span>{{showdata(scope.row.name,scope.row.unitType)
-
-                       }}</span>
-             </template>
+            <template #default="scope">
+              <span>{{ showdata(scope.row.name, scope.row.unitType) }}</span>
+            </template>
           </el-table-column>
           <el-table-column label="单位" prop="name">
-             <template #default="scope">
-                 <span>{{ scope.row.unitType }}</span>
-             </template>
+            <template #default="scope">
+              <span>{{ scope.row.unitType }}</span>
+            </template>
           </el-table-column>
           <el-table-column label="时间" prop="name">
-             <template #default="scope">
-                 <span>{{
-                         (useWSStore().getMessage()[currentsensor.id]) ?
-                           (useWSStore().getMessage()[currentsensor.id][scope.row.name]?.time) : '-'
-                       }}</span>
-             </template>
+            <template #default="scope">
+              <span>{{
+                useWSStore().getMessage()[currentsensor.id]
+                  ? useWSStore().getMessage()[currentsensor.id][scope.row.name]?.time
+                  : "-"
+              }}</span>
+            </template>
           </el-table-column>
         </el-table>
-
       </div>
-      <div style="position: relative;">
-        <div style="margin-top: 10px" v-if="currentname != ''">变量 {{ currentname }} 数值曲线</div>
-
-        <div style="position: absolute;right:10px;top:10px">
-            <el-date-picker
-                v-model="value1"
-                style="z-index: 10000;"
-                type="datetimerange"
-                :shortcuts="shortcuts"
-                range-separator="到"
-                start-placeholder="开始时间"
-                end-placeholder="结束时间"
-                @change="doshowhistory"
-             />
+      <div style="position: relative">
+        <div style="margin-top: 10px" v-if="currentname != ''">
+          变量 {{ currentname }} 数值曲线
+        </div>
+
+        <div style="position: absolute; right: 10px; top: 10px">
+          <el-date-picker
+            v-model="value1"
+            style="z-index: 10000"
+            type="datetimerange"
+            :shortcuts="shortcuts"
+            range-separator="到"
+            start-placeholder="开始时间"
+            end-placeholder="结束时间"
+            @change="doshowhistory"
+          />
         </div>
         <!--        显示历史数据 折线图-->
         <div ref="chartlinediv" style="height: 250px" v-loading="isloading"></div>
-
-
       </div>
     </el-dialog>
 
     <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
-      <el-upload ref="uploadRef" :limit="1" accept=".xlsx, .xls" :headers="upload.headers"
-        :action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading"
-        :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag
-        :data="{deviceId:uploadParams}">
+      <el-upload
+        ref="uploadRef"
+        :limit="1"
+        accept=".xlsx, .xls"
+        :headers="upload.headers"
+        :action="upload.url + '?updateSupport=' + upload.updateSupport"
+        :disabled="upload.isUploading"
+        :on-progress="handleFileUploadProgress"
+        :on-success="handleFileSuccess"
+        :auto-upload="false"
+        drag
+        :data="{ deviceId: uploadParams }"
+      >
         <el-icon class="el-icon--upload"><upload-filled /></el-icon>
         <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
-           <template #tip>
-               <div class="el-upload__tip text-center">
-                   <span>仅允许导入xls、xlsx格式文件。</span>
-                   <!-- <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;"
+        <template #tip>
+          <div class="el-upload__tip text-center">
+            <span>仅允许导入xls、xlsx格式文件。</span>
+            <!-- <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;"
                              @click="importTemplate">下载模板</el-link> -->
-               </div>
-           </template>
+          </div>
+        </template>
       </el-upload>
-          <template #footer>
-              <div class="dialog-footer">
-                  <el-button type="primary" @click="submitFileForm">确 定</el-button>
-                  <el-button @click="upload.open = false">取 消</el-button>
-              </div>
-          </template>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitFileForm">确 定</el-button>
+          <el-button @click="upload.open = false">取 消</el-button>
+        </div>
+      </template>
     </el-dialog>
   </div>
 </template>
@@ -322,475 +410,491 @@ import { onMounted, ref, watch, watchEffect } from "vue";
 import { LayTree } from "@layui/layui-vue";
 import "@layui/layui-vue/lib/index.css";
 import { useRoute, useRouter } from "vue-router";
-import { listEquipmentOrganizational } from "@/api/data/equipmentOrganizational"
-import { listEquipmentSbook } from "@/api/data/equipmentSbook"
-import { listSensor, delSensor, addSensor, updateSensor, listSensorData, listSensorRecordData } from "@/api/data/sensor"
+import { listEquipmentOrganizational } from "@/api/data/equipmentOrganizational";
+import { listEquipmentSbook } from "@/api/data/equipmentSbook";
+import {
+  listSensor,
+  delSensor,
+  addSensor,
+  updateSensor,
+  listSensorData,
+  listSensorRecordData,
+} from "@/api/data/sensor";
 import { listDatapoint } from "@/api/data/datapoint";
 import { listUnit } from "@/api/data/unit";
-import useWSStore from "@/store/modules/websocket"
-import * as echarts from 'echarts';
-
+import useWSStore from "@/store/modules/websocket";
+import * as echarts from "echarts";
 
 import { ElMessage, ElMessageBox } from "element-plus";
 import moment from "moment";
 
 const { proxy } = getCurrentInstance();
-const { protocal_type, sensor_type, sensor_status } = proxy.useDict("protocal_type", "sensor_type", "sensor_status");
+const { protocal_type, sensor_type, sensor_status } = proxy.useDict(
+  "protocal_type",
+  "sensor_type",
+  "sensor_status"
+);
 const pointdata = ref([]);
 
 const route = useRoute();
 const router = useRouter();
 const ziduanshow = ref(false);
-
-
 const showdata = (name, un) => {
-
   let value = "-";
   try {
-    value = useWSStore().getMessage()[currentsensor.value.id][name].value
+    value = useWSStore().getMessage()[currentsensor.value.id][name].value;
     if (un == "~") {
-      return moment(value*1000).format("yyyy-MM-DD HH:mm:ss");
+      return moment(value * 1000).format("yyyy-MM-DD HH:mm:ss");
     }
-    value = value ? parseFloat(value)+"" : '-';
-  }catch(e) {
-  }
+    value = value ? parseFloat(value) + "" : "-";
+  } catch (e) {}
   return value;
-}
+};
 
 const tableref = ref(null);
-const value1 = ref([
-  moment().subtract(1,'days'),
-  moment(),
-])
+const value1 = ref([moment().subtract(1, "days"), moment()]);
 const shortcuts = [
   {
-    text: '1天',
+    text: "1天",
     value: () => {
-      const end = moment()
-      const start = moment().subtract(1, 'days');
-      return [start, end]
+      const end = moment();
+      const start = moment().subtract(1, "days");
+      return [start, end];
     },
   },
   {
-    text: '3天',
+    text: "3天",
     value: () => {
-      const end = moment()
-      const start = moment().subtract(3, 'days');
-      return [start, end]
+      const end = moment();
+      const start = moment().subtract(3, "days");
+      return [start, end];
     },
   },
   {
-    text: '1周',
+    text: "1周",
     value: () => {
-      const end = moment()
-      const start = moment().subtract(7, 'days');
-      return [start, end]
+      const end = moment();
+      const start = moment().subtract(7, "days");
+      return [start, end];
     },
   },
-]
+];
 
 const uploadParams = ref();
 
 const cloumdata = ref([
-    { label: '传感器编号', prop: 'id', visible: true },
-    { label: '传感器名称', prop: 'name', visible: true },
-    { label: '描述', prop: 'sensorDesc', visible: true },
-    { label: '状态', prop: 'statusname', visible: true },
-    { label: '类型', prop: 'sensorType', visible: true },
-])
+  { label: "传感器编号", prop: "id", visible: true },
+  { label: "传感器名称", prop: "name", visible: true },
+  { label: "描述", prop: "sensorDesc", visible: true },
+  { label: "状态", prop: "statusname", visible: true },
+  { label: "类型", prop: "sensorType", visible: true },
+]);
 
 /*** 用户导入参数 */
 const upload = reactive({
-    // 是否显示弹出层(用户导入)
-    open: false,
-    // 弹出层标题(用户导入)
-    title: "",
-    // 是否禁用上传
-    isUploading: false,
-    // 是否更新已经存在的用户数据
-    updateSupport: 0,
-    // 设置上传的请求头部
-    headers: { Authorization: "Bearer " + getToken() },
-    // 上传的地址
-    url: import.meta.env.VITE_APP_BASE_API + "/data/sensor/invoke"
+  // 是否显示弹出层(用户导入)
+  open: false,
+  // 弹出层标题(用户导入)
+  title: "",
+  // 是否禁用上传
+  isUploading: false,
+  // 是否更新已经存在的用户数据
+  updateSupport: 0,
+  // 设置上传的请求头部
+  headers: { Authorization: "Bearer " + getToken() },
+  // 上传的地址
+  url: import.meta.env.VITE_APP_BASE_API + "/data/sensor/invoke",
 });
 
-
 const onchangepage = (page) => {
-    pagedata.value.pageNum = page;
-    getalldata();
-}
+  pagedata.value.pageNum = page;
+  getalldata();
+};
 const pagedata = ref({
-    total: 0,
-    pageSize: 10,
-    pageNum: 1
+  total: 0,
+  pageSize: 10,
+  pageNum: 1,
 });
 
-const allUnit = ref([])
+const allUnit = ref([]);
 
 const deleterow = (item) => {
-    delSensor(item.id).then((res) => {
-        ElMessage.success("删除成功");
-        getalldata();
-    })
-}
+  delSensor(item.id).then((res) => {
+    ElMessage.success("删除成功");
+    getalldata();
+  });
+};
 
 const deleteall = () => {
-    let selected = tableref.value.getSelectionRows();
-    if (selected.length == 0) {
-        ElMessage.warning("请选择要删除的行");
-        return;
-    }
-
-    if (selected.length > 0) {
-        ElMessageBox.confirm(
-            `是否删除${selected.length}条数据`,
-            "警告", {
-                confirmButtonText: "确认",
-                cancelButtonText: "取消",
-                type: 'warning',
-            }
-        ).then(() => {
-
-            delSensor(selected.map(i => i.id).join(",")).then((res) => {
-                ElMessage.success("删除成功");
-                getalldata();
-            })
-
-        });
-    }
+  let selected = tableref.value.getSelectionRows();
+  if (selected.length == 0) {
+    ElMessage.warning("请选择要删除的行");
+    return;
+  }
 
-}
+  if (selected.length > 0) {
+    ElMessageBox.confirm(`是否删除${selected.length}条数据`, "警告", {
+      confirmButtonText: "确认",
+      cancelButtonText: "取消",
+      type: "warning",
+    }).then(() => {
+      delSensor(selected.map((i) => i.id).join(",")).then((res) => {
+        ElMessage.success("删除成功");
+        getalldata();
+      });
+    });
+  }
+};
 
 /** 导入按钮操作 */
 const handleImport = () => {
-    const getdeviceid = (node) => {
-        if (node.children) {
-            return node.children.map(item => {
-                return getdeviceid(item);
-            }).join(",")
-        } else {
-            if ((node.id + "").indexOf("device") > -1) {
-                return node.id;
-            } else {
-                return "";
-            }
-        }
+  const getdeviceid = (node) => {
+    if (node.children) {
+      return node.children
+        .map((item) => {
+          return getdeviceid(item);
+        })
+        .join(",");
+    } else {
+      if ((node.id + "").indexOf("device") > -1) {
+        return node.id;
+      } else {
+        return "";
+      }
     }
-    if (currentnode.value != null) {
-        let deviceids = getdeviceid(currentnode.value).split(",").filter(i => i != "").join(",");
-        console.log(deviceids.split(',').length == 1)
-        if (deviceids != null && deviceids.split(',').length == 1) {
-            uploadParams.value = deviceids.replaceAll("device_", '');
-            console.log(uploadParams.value)
-            upload.title = "传感器导入";
-            upload.open = true;
-        } else {
-            ElMessage({
-                message: '请选择传感器所属设备',
-                type: 'warning',
-            })
-        }
+  };
+  if (currentnode.value != null) {
+    let deviceids = getdeviceid(currentnode.value)
+      .split(",")
+      .filter((i) => i != "")
+      .join(",");
+    console.log(deviceids.split(",").length == 1);
+    if (deviceids != null && deviceids.split(",").length == 1) {
+      uploadParams.value = deviceids.replaceAll("device_", "");
+      console.log(uploadParams.value);
+      upload.title = "传感器导入";
+      upload.open = true;
     } else {
-        ElMessage({
-            message: '请选择传感器所属设备',
-            type: 'warning',
-        })
+      ElMessage({
+        message: "请选择传感器所属设备",
+        type: "warning",
+      });
     }
-
-
+  } else {
+    ElMessage({
+      message: "请选择传感器所属设备",
+      type: "warning",
+    });
+  }
 };
 
 function submitFileForm() {
-    proxy.$refs["uploadRef"].submit();
-    upload.open = false;
-};
+  proxy.$refs["uploadRef"].submit();
+  upload.open = false;
+}
 
 const initdata = () => {
-    searchform.value.id = '';
-    searchform.value.desc = '';
-    pagedata.value = {
-        total: 0,
-        pageSize: 10,
-        pageNum: 1
-    }
-}
+  searchform.value.id = "";
+  searchform.value.desc = "";
+  pagedata.value = {
+    total: 0,
+    pageSize: 10,
+    pageNum: 1,
+  };
+};
 
 const goadd = () => {
-    router.push("/device/sensordash/add?type=0")
-}
+  router.push("/device/sensordash/add?type=0");
+};
 
 const goedit = (item) => {
-    localStorage.setItem("currentsensor", JSON.stringify(item))
-    router.push("/device/sensordash/add?type=1")
-}
+  localStorage.setItem("currentsensor", JSON.stringify(item));
+  router.push("/device/sensordash/add?type=1");
+};
 
 const getProtocalTypeName = (item) => {
-    for (var index in protocal_type.value) {
-        if (protocal_type.value[index].value == item.protocalType) {
-            return protocal_type.value[index].label
-        }
+  for (var index in protocal_type.value) {
+    if (protocal_type.value[index].value == item.protocalType) {
+      return protocal_type.value[index].label;
     }
-}
-
-
+  }
+};
 
 const currentnode = ref(null);
 const getalldata = () => {
-    const getdeviceid = (node) => {
-        if (node.children) {
-            return node.children.map(item => {
-                return getdeviceid(item);
-            }).join(",")
-        } else {
-            if ((node.id + "").indexOf("device") > -1) {
-                return node.id;
-            } else {
-                return "";
-            }
-        }
-    }
-    let deviceids = getdeviceid(currentnode.value).split(",").filter(i => i != "").join(",");
-    console.log(deviceids)
-    if (deviceids != "") {
-      deviceids = deviceids.replaceAll("device_", "")
-        listSensor({ ...pagedata.value, params: { deviceids: deviceids, ...searchform.value }}).then(res => {
-            const { rows, total, page, size } = res;
-            pagedata.value = { total: total, pageNum: page, pageSize: 10 };
-            console.log(rows);
-            devicetabledata.value = rows.map(item => {
-                try {
-                    var statusname = sensor_status.value.find(i => i.value == item.status).label;
-                    item["statusname"] = statusname;
-                } catch (e) {
-
-                }
-                return item;
-            });
+  const getdeviceid = (node) => {
+    if (node.children) {
+      return node.children
+        .map((item) => {
+          return getdeviceid(item);
         })
+        .join(",");
     } else {
-        pagedata.value = { total: 0, pageNum: 1, pageSize: 10 };
-        devicetabledata.value = [];
+      if ((node.id + "").indexOf("device") > -1) {
+        return node.id;
+      } else {
+        return "";
+      }
     }
-}
+  };
+  let deviceids = getdeviceid(currentnode.value)
+    .split(",")
+    .filter((i) => i != "")
+    .join(",");
+  console.log(deviceids);
+  if (deviceids != "") {
+    deviceids = deviceids.replaceAll("device_", "");
+    listSensor({
+      ...pagedata.value,
+      params: { deviceids: deviceids, ...searchform.value },
+    }).then((res) => {
+      const { rows, total, page, size } = res;
+      pagedata.value = { total: total, pageNum: page, pageSize: 10 };
+      console.log(rows);
+      devicetabledata.value = rows.map((item) => {
+        try {
+          var statusname = sensor_status.value.find((i) => i.value == item.status).label;
+          item["statusname"] = statusname;
+        } catch (e) {}
+        return item;
+      });
+    });
+  } else {
+    pagedata.value = { total: 0, pageNum: 1, pageSize: 10 };
+    devicetabledata.value = [];
+  }
+};
 
 const handleClick = (node) => {
-    //循环获取子的id
-    currentnode.value = node;
-    getalldata();
+  //循环获取子的id
+  currentnode.value = node;
+  getalldata();
 };
 const selectedKey = ref(4);
 const data = ref([]);
 
-
 const getTreedata = () => {
-    listEquipmentOrganizational({ pageSize: 10000 }).then(res => {
-        const { rows, total, page, size } = res;
-        //获取设备数据
-        listEquipmentSbook({ page: 1, pageSize: 100000 }).then(res1 => {
-            res1.rows.forEach(item => {
-                item["parentId"] = item.equipmentTreeId;
-                item["id"] = "device_" + item.id;
-                rows.push(item);
-                data.value = proxy.handleTree(rows, "id", "parentId");
-            })
-        })
-    })
-}
+  listEquipmentOrganizational({ pageSize: 10000 }).then((res) => {
+    const { rows, total, page, size } = res;
+    //获取设备数据
+    listEquipmentSbook({ page: 1, pageSize: 100000 }).then((res1) => {
+      res1.rows.forEach((item) => {
+        item["parentId"] = item.equipmentTreeId;
+        item["id"] = "device_" + item.id;
+        rows.push(item);
+        data.value = proxy.handleTree(rows, "id", "parentId");
+      });
+    });
+  });
+};
 getTreedata();
 
-
 const devicetabledata = ref([]);
 const searchform = ref({
-    id: "",
-    desc: ""
+  id: "",
+  desc: "",
 });
 
 const currentdatapointlist = ref([]);
 const cdbdshow = ref(false);
 const currentsensor = ref(null);
 const cdbd = (item) => {
-    cdbdshow.value = true;
-    listDatapoint({ sensorId: item.id }).then(res => {
-        const { rows, total, page, size } = res;
-        currentdatapointlist.value = rows;
-        currentsensor.value = item;
-        try {
-            pointdata.value = JSON.parse(item.datapoints);
-        } catch (e) {}
-
-    })
-
-}
-const realtimedata = ref({})
+  cdbdshow.value = true;
+  listDatapoint({ sensorId: item.id }).then((res) => {
+    const { rows, total, page, size } = res;
+    currentdatapointlist.value = rows;
+    currentsensor.value = item;
+    try {
+      pointdata.value = JSON.parse(item.datapoints);
+    } catch (e) {}
+  });
+};
+const realtimedata = ref({});
 const datashow = ref(false);
 const lookdata = (item) => {
-    //弹窗
-    datashow.value = true;
-    currentsensor.value = item;
-    listSensorData({ page: 1, pageSize: 10000, id: item.id }).then(res => {
-        const { rows, total, page, size } = res;
-        if (rows.length > 0) {
-            if (rows[0].recordData) {
-                let data = JSON.parse(rows[0].recordData);
-                useWSStore().setMessagetype1(rows[0].tblSensor.id, data);
-            }
-        }
-
-    })
-
-    //直接接mqtt 数据
-}
+  //弹窗
+  datashow.value = true;
+  currentsensor.value = item;
+  listSensorData({ page: 1, pageSize: 10000, id: item.id }).then((res) => {
+    const { rows, total, page, size } = res;
+    if (rows.length > 0) {
+      if (rows[0].recordData) {
+        let data = JSON.parse(rows[0].recordData);
+        useWSStore().setMessagetype1(rows[0].tblSensor.id, data);
+      }
+    }
+  });
 
+  //直接接mqtt 数据
+};
 
 const deldatapoint = (index) => {
-    pointdata.value.splice(index, 1)
-}
+  pointdata.value.splice(index, 1);
+};
 
 const addrow = () => {
-    if (!pointdata.value) { pointdata.value = []; }
-    pointdata.value.push({
-        name: "",
-        unit: "",
-        unitType: "0",
-        desc: "",
-        label: "",
-        dataPointId: null
-    })
-}
+  if (!pointdata.value) {
+    pointdata.value = [];
+  }
+  pointdata.value.push({
+    name: "",
+    unit: "",
+    unitType: "0",
+    desc: "",
+    label: "",
+    dataPointId: null,
+  });
+};
 onMounted(() => {
-    listUnit({}).then(res => {
-        allUnit.value = res.data;
-    })
-})
+  listUnit({}).then((res) => {
+    allUnit.value = res.data;
+  });
+});
 
 const dosave = () => {
-    let data = JSON.stringify(pointdata.value.filter(i => i.name !== ""));
-    currentsensor.value.datapoints = data;
-    updateSensor(currentsensor.value).then(res => {
-        ElMessage.success("保存成功");
-        cdbdshow.value = false;
-        getalldata();
-    })
-}
+  let data = JSON.stringify(pointdata.value.filter((i) => i.name !== ""));
+  currentsensor.value.datapoints = data;
+  updateSensor(currentsensor.value).then((res) => {
+    ElMessage.success("保存成功");
+    cdbdshow.value = false;
+    getalldata();
+  });
+};
 
 const historytabledata = ref([]);
-const chartlinediv = ref(null)
-const currentname = ref("")
+const chartlinediv = ref(null);
+const currentname = ref("");
 const isloading = ref(false);
 watchEffect(() => {
-    if (currentsensor.value && useWSStore().getMessage()[currentsensor.value.id] && useWSStore().getMessage()[currentsensor.value.id][currentname.value]) {
-        let data = useWSStore().getMessage()[currentsensor.value.id][currentname.value];
-        var isadd = false;
-        historytabledata.value.forEach(i => {
-            if (moment(data.time).utc() - moment(i[0]).utc() > 10) {
-                isadd = true;
-            }
-        })
-      if (isadd) {
-           historytabledata.value.splice(0, 0, [moment(data.time).valueOf(), data.value])
-        }
-
+  if (
+    currentsensor.value &&
+    useWSStore().getMessage()[currentsensor.value.id] &&
+    useWSStore().getMessage()[currentsensor.value.id][currentname.value]
+  ) {
+    let data = useWSStore().getMessage()[currentsensor.value.id][currentname.value];
+    var isadd = false;
+    historytabledata.value.forEach((i) => {
+      if (moment(data.time).utc() - moment(i[0]).utc() > 10) {
+        isadd = true;
+      }
+    });
+    if (isadd) {
+      historytabledata.value.splice(0, 0, [moment(data.time).valueOf(), data.value]);
     }
-    if (historytabledata.value.length > 0) {
-        const usedmemoryInstance = echarts.init(chartlinediv.value, "macarons");
-        usedmemoryInstance.setOption({
-            tooltip: {
-                trigger: 'axis',
-                position: function(pt) {
-                    return [pt[0], '10%'];
-                }
-            },
-            xAxis: {
-                type: 'time',
-                splitLine: {
-      show: false
-    }
-            },
-            yAxis: {
-                type: 'value',
-            },
-            dataZoom: [{
-                    type: 'inside',
-                    start: 80,
-                    end: 100
-                },
-                {
-                    start: 0,
-                    end: 20
-                }
-            ],
-            series: [{
-                name: currentname.value,
-              data: historytabledata.value,
-                showSymbol: false,
-              type: 'line',
-               connectNulls: false,
-            //     lineStyle: {
-            // curveness: 0 // 设置曲率为0,使线条不弯曲,即首尾不相连
-            //   },
-        areaStyle: {},
-                smooth: true
-            }]
-        });
-        console.error(historytabledata.value)
-        window.addEventListener("resize", () => {
-            usedmemoryInstance.resize()
-        });
-    } else {
-        if (chartlinediv.value) {
-            chartlinediv.value.innerHTML = "无数据";
-        }
-
+  }
+  if (historytabledata.value.length > 0) {
+    const usedmemoryInstance = echarts.init(chartlinediv.value, "macarons");
+    usedmemoryInstance.setOption({
+      tooltip: {
+        trigger: "axis",
+        position: function (pt) {
+          return [pt[0], "10%"];
+        },
+      },
+      xAxis: {
+        type: "time",
+        splitLine: {
+          show: false,
+        },
+      },
+      yAxis: {
+        type: "value",
+      },
+      dataZoom: [
+        {
+          type: "inside",
+          start: 80,
+          end: 100,
+        },
+        {
+          start: 0,
+          end: 20,
+        },
+      ],
+      series: [
+        {
+          name: currentname.value,
+          data: historytabledata.value,
+          showSymbol: false,
+          type: "line",
+          connectNulls: false,
+          //     lineStyle: {
+          // curveness: 0 // 设置曲率为0,使线条不弯曲,即首尾不相连
+          //   },
+          areaStyle: {},
+          smooth: true,
+        },
+      ],
+    });
+    console.error(historytabledata.value);
+    window.addEventListener("resize", () => {
+      usedmemoryInstance.resize();
+    });
+  } else {
+    if (chartlinediv.value) {
+      chartlinediv.value.innerHTML = "无数据";
     }
-
-
-})
+  }
+});
 const doshowhistory = (row) => {
-  if (row != undefined && row != null && row.name!=undefined) {
+  if (row != undefined && row != null && row.name != undefined) {
     currentname.value = row.name;
   } else {
-    if (currentname.value == undefined || currentname.value == "" || currentname.value == null) {
-      ElMessage.warning("请选择监测点")
+    if (
+      currentname.value == undefined ||
+      currentname.value == "" ||
+      currentname.value == null
+    ) {
+      ElMessage.warning("请选择监测点");
       return;
     }
   }
-    isloading.value = true;
-// debugger
-
-    //获取历史数据
-    listSensorRecordData({ sensorId: currentsensor.value.id, pointName: currentname.value, pageNum: 1, pageSize: 10000, orderByColumn: "createTime", isAsc: "desc", params: { name: currentname.value, starttime: moment(value1.value[0]).format("YYYY-MM-DD HH:mm:ss"), endtime:moment(value1.value[1]).format("YYYY-MM-DD HH:mm:ss")} }).then(res => {
-        const { rows, total, page, size } = res;
-        isloading.value = false;
-        historytabledata.value = rows.map(i => {
-            return [moment(i.createTime).valueOf(), i.pointValue]
-        });
-    })
-}
-
-const inportSensor = () => {
+  isloading.value = true;
+  // debugger
+
+  //获取历史数据
+  listSensorRecordData({
+    sensorId: currentsensor.value.id,
+    pointName: currentname.value,
+    pageNum: 1,
+    pageSize: 10000,
+    orderByColumn: "createTime",
+    isAsc: "desc",
+    params: {
+      name: currentname.value,
+      starttime: moment(value1.value[0]).format("YYYY-MM-DD HH:mm:ss"),
+      endtime: moment(value1.value[1]).format("YYYY-MM-DD HH:mm:ss"),
+    },
+  }).then((res) => {
+    const { rows, total, page, size } = res;
+    isloading.value = false;
+    historytabledata.value = rows.map((i) => {
+      return [moment(i.createTime).valueOf(), i.pointValue];
+    });
+  });
+};
 
-}
+const inportSensor = () => {};
 </script>
 
 <style lang="scss">
 .layui-tree .layui-this .layui-tree-txt {
-    color: #038de0 !important;
+  color: #038de0 !important;
 }
 </style>
 
 <style lang="scss" scoped>
 .card-header {
-    display: flex;
-    flex-direction: row;
-    justify-content: space-between;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
 }
 
 .tree {
-    *,
-    *:before,
-    *:after {
-        box-sizing: content-box !important;
-    }
+  *,
+  *:before,
+  *:after {
+    box-sizing: content-box !important;
+  }
 }
 </style>

+ 31 - 1
ruoyi-ui-vue3/src/views/device/sensordash/video.vue

@@ -26,7 +26,8 @@
       </el-col>
       <el-col :span="18"  v-if="isvideoshow">
         <div style="height: 100%;">
-           <iframe id="FrameID" :key="currenturl" style="width: 100%;height:100%" :src="currenturl"/>
+           <div id="container" style="margin-top: 0px;width:100%;height:80vh"></div>
+           <!-- <iframe id="FrameID" :key="currenturl" style="width: 100%;height:100%" :src="currenturl"/> -->
         </div>
       </el-col>
       <el-col :span="18" v-if="!isvideoshow">
@@ -130,6 +131,30 @@ const handleClick = (node) => {
     searchform.value.id = node.id
   }
 
+  setTimeout(() => {
+      var $container = document.getElementById('container');
+   jessibuca = new Jessibuca({
+            container: $container,
+            videoBuffer: 0.2, // 缓存时长
+            isResize: false,
+           text: "",
+            decoder:"/iot/jess/decoder.js",
+            loadingText: "",
+            useMSE: false,
+            debug: true,
+            showBandwidth: true, // 显示网速
+            operateBtns: {
+                fullscreen: true,
+                screenshot: false,
+                play: true,
+                audio: false,
+                recorder: false
+            },
+            forceNoOffscreen: true,
+            isNotMute: false,
+   },);
+         jessibuca.play(node.voiceOutCode);
+    }, 1000);
   currenturl.value = node.remark;
   isvideoshow.value = true;
 
@@ -320,4 +345,9 @@ getVideoList();
 .layui-disabled{
     color: #000 !important;
   }
+   #container {
+            background: rgba(13, 14, 27, 0.7);
+            width: 50vw;
+            height: 398px;
+        }
 </style>

+ 4 - 0
ruoyi-ui-vue3/src/views/points/index.vue

@@ -16,6 +16,7 @@
             <el-form-item label="点表数" prop="pointNum">
               <el-input v-model="queryParams.pointNum" placeholder="请输入点表数" clearable @keyup.enter="handleQuery" />
             </el-form-item>
+
             <el-form-item label="上层位置" prop="topAddr">
               <el-input v-model="queryParams.topAddr" placeholder="请输入上层位置" clearable @keyup.enter="handleQuery" />
             </el-form-item>
@@ -101,6 +102,9 @@
         <el-form-item label="上层位置" prop="topAddr">
           <el-input v-model="form.topAddr" placeholder="请输入上层位置" />
         </el-form-item>
+        <el-form-item label="设备型号" prop="deviceType">
+              <el-input v-model="form.deviceType" placeholder="请输入设备型号"  />
+            </el-form-item>
         <el-form-item label="设备模版" prop="deviceTpl">
           <el-input v-model="form.deviceTpl" placeholder="请输入设备模版" />
         </el-form-item>

+ 47 - 5
ruoyi-ui-vue3/src/views/rules/add.vue

@@ -94,6 +94,27 @@
                   </el-select>
                 </div>
               </el-descriptions-item>
+               <el-descriptions-item>
+                <template #label>
+                  <div style="display: inline-block;min-width: 100px;text-align: right">
+                    <span style="color: red">*</span> 设备属性
+                  </div>
+                </template>
+                <div class="content-w">
+                  <el-input placeholder="请输入" v-model="ruleParam.sbsx" />
+                </div>
+              </el-descriptions-item>
+
+               <el-descriptions-item>
+                <template #label>
+                  <div style="display: inline-block;min-width: 100px;text-align: right">
+                    <span style="color: red"></span> 时间触发
+                  </div>
+                </template>
+                <div class="content-w">
+                  <el-input placeholder="请输入cron" v-model="ruleParam.sjcf" />
+                </div>
+              </el-descriptions-item>
 
               <el-descriptions-item>
                 <template #label>
@@ -275,6 +296,7 @@ import { addRuleFilter, getRuleFilter, updateRuleFilter, listRuleFilter, delRule
 import { addRuleExecute, getRuleExecute, updateRuleExecute, listRuleExecute, delRuleExecute } from "@/api/data/ruleExecute"
 
 import { ElMessage } from 'element-plus'
+import { cloneDeep } from "lodash";
 
 
 const route = useRoute();
@@ -307,6 +329,8 @@ const ruleExt = ref({
   invalidation: null
 })
 
+const sbsx=ref("")
+
 const ruleExecuteParam = ref({
   id: null,
   ruleId: null,
@@ -330,7 +354,9 @@ const ruleParam = ref({
   time: "",
   triggeringCondition: "",
   description: "",
-  remark: ""
+  remark: "",
+   sbsx: '',
+  sjcf:'',
 })
 const getEquipmentSbookList = async () => {
   listEquipmentSbook({ pageSize: 10000 }).then(res => {
@@ -359,16 +385,25 @@ const selectEquipment = (value) => {
 }
 
 const saveSensor = () => {
+  let formm = cloneDeep(ruleParam.value);
+    formm["expr1"] = JSON.stringify({
+      sbsx: ruleParam.value.sbsx,
+      sjcf:ruleParam.value.sjcf,
+    })
+    delete formm.sbsx;
+    delete formm.sjcf;
   if (objId == null) {
-    console.log(ruleParam.value);
-    addRule(ruleParam.value).then(res => {
+    // console.log(ruleParam.value);
+
+
+    addRule(formm).then(res => {
       console.log(res);
       if (res.code == 200) {
         router.back()
       }
     })
   } else {
-    updateRule(ruleParam.value).then(res => {
+    updateRule(formm).then(res => {
       console.log(res);
       if (res.code == 200) {
         router.back()
@@ -381,13 +416,20 @@ const getDetail = () => {
   getRule(objId).then(res => {
     console.log(res);
     ruleParam.value = res.data;
+    if (ruleParam.value.expr1 != null && ruleParam.value.expr1 != undefined && ruleParam.value.expr1 != "") {
+      ruleParam.value["sjcf"] = JSON.parse(ruleParam.value.expr1)["sjcf"];
+      ruleParam.value["sbsx"] = JSON.parse(ruleParam.value.expr1)["sbsx"]
+    } else {
+      ruleParam.value["sjcf"] = "";
+      ruleParam.value["sbsx"] = ""
+    }
     selectEquipment(res.data.equipmentId);
   })
 }
 
 const saveRuleFilter = () => {
   ruleFilterParam.value.ruleId = objId;
-  console.log(ruleFilterParam.value.id);
+  // console.log(ruleFilterParam.value.id);
   if (ruleFilterParam.value.id != null) {
     updateRuleFilter(ruleFilterParam.value).then(res => {
       if (res.code == 200) {

+ 34 - 3
ruoyi-ui-vue3/src/views/system/config/index.vue

@@ -108,6 +108,7 @@
                <dict-tag :options="sys_yes_no" :value="scope.row.configType" />
             </template>
          </el-table-column>
+         <el-table-column label="编码" align="center" prop="bm" :show-overflow-tooltip="true" />
          <el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true" />
          <el-table-column label="创建时间" align="center" prop="createTime" width="180">
             <template #default="scope">
@@ -151,6 +152,9 @@
                   >{{ dict.label }}</el-radio>
                </el-radio-group>
             </el-form-item>
+             <el-form-item label="参数编码" prop="bm">
+               <el-input v-model="form.bm" placeholder="请输入参数编码" />
+            </el-form-item>
             <el-form-item label="备注" prop="remark">
                <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
             </el-form-item>
@@ -167,6 +171,7 @@
 
 <script setup name="Config">
 import { listConfig, getConfig, delConfig, addConfig, updateConfig, refreshCache } from "@/api/system/config";
+import { cloneDeep } from "lodash";
 
 const { proxy } = getCurrentInstance();
 const { sys_yes_no } = proxy.useDict("sys_yes_no");
@@ -205,6 +210,16 @@ function getList() {
   loading.value = true;
   listConfig(proxy.addDateRange(queryParams.value, dateRange.value)).then(response => {
     configList.value = response.rows;
+    configList.value.forEach(function (item, index) {
+      if (item.remark != undefined) {
+      try {
+        item.bm = JSON.parse(item.remark)["bm"];
+        item.remark = JSON.parse(item.remark)["remark"];
+      }catch(e){
+
+      }
+    }
+    });
     total.value = response.total;
     loading.value = false;
   });
@@ -222,6 +237,7 @@ function reset() {
     configKey: undefined,
     configValue: undefined,
     configType: "Y",
+    bm:"",
     remark: undefined
   };
   proxy.resetForm("configRef");
@@ -255,6 +271,14 @@ function handleUpdate(row) {
   const configId = row.configId || ids.value;
   getConfig(configId).then(response => {
     form.value = response.data;
+    if (form.value.remark != undefined) {
+      try {
+        form.value.bm = JSON.parse(form.value.remark)["bm"];
+        form.value.remark = JSON.parse(form.value.remark)["remark"];
+      }catch(e){
+
+      }
+    }
     open.value = true;
     title.value = "修改参数";
   });
@@ -263,14 +287,21 @@ function handleUpdate(row) {
 function submitForm() {
   proxy.$refs["configRef"].validate(valid => {
     if (valid) {
-      if (form.value.configId != undefined) {
-        updateConfig(form.value).then(response => {
+
+      let formp = cloneDeep(form.value);
+      formp.remark = JSON.stringify({
+        bm: formp.bm,
+        remark: formp.remark
+      });
+
+      if (formp.configId != undefined) {
+        updateConfig(formp).then(response => {
           proxy.$modal.msgSuccess("修改成功");
           open.value = false;
           getList();
         });
       } else {
-        addConfig(form.value).then(response => {
+        addConfig(formp).then(response => {
           proxy.$modal.msgSuccess("新增成功");
           open.value = false;
           getList();

+ 44 - 9
ruoyi-ui-vue3/src/views/system/role/index.vue

@@ -53,7 +53,14 @@
       <el-table-column label="角色有效期" width="100">
         <template #default="scope">
           <div v-if="scope.row.roleId != 1">
-            {{ moment(scope.row.remark).format("yy-MM-DD") }}
+            {{ moment(scope.row.yxq).format("yy-MM-DD") }}
+          </div>
+        </template>
+      </el-table-column>
+       <el-table-column label="角色备注" width="100">
+        <template #default="scope">
+          <div v-if="scope.row.roleId != 1">
+            {{ scope.row.remark }}
           </div>
         </template>
       </el-table-column>
@@ -131,9 +138,12 @@
         <!-- <el-form-item label="备注"> -->
           <el-form-item label="角色有效期">
           <!-- <el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input> -->
-          <el-date-picker v-model="form.remark" type="date" placeholder="Pick a day" :disabled-date="disabledDate"
+          <el-date-picker v-model="form.yxq" type="date" placeholder="选择日期" :disabled-date="disabledDate"
             :shortcuts="shortcuts" :size="size" value-format="YYYY-MM-DD 00:00:00"/>
         </el-form-item>
+        <el-form-item label="备注">
+          <el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
+        </el-form-item>
       </el-form>
       <template #footer>
         <div class="dialog-footer">
@@ -182,6 +192,7 @@
 import { addRole, changeRoleStatus, dataScope, delRole, getRole, listRole, updateRole, deptTreeSelect } from "@/api/system/role";
 import { roleMenuTreeselect, treeselect as menuTreeselect } from "@/api/system/menu";
 import moment from "moment";
+import { cloneDeep } from "lodash";
 
 const router = useRouter();
 const { proxy } = getCurrentInstance();
@@ -239,6 +250,17 @@ function getList() {
   loading.value = true;
   listRole(proxy.addDateRange(queryParams.value, dateRange.value)).then(response => {
     roleList.value = response.rows;
+
+    roleList.value.forEach(function (item, index) {
+      if (item.remark != undefined) {
+      try {
+        item.yxq = JSON.parse(item.remark)["yxq"];
+        item.remark = JSON.parse(item.remark)["remark"];
+      }catch(e){
+      }
+    }
+    });
+
     total.value = response.total;
     loading.value = false;
   });
@@ -338,7 +360,8 @@ function reset() {
     deptIds: [],
     menuCheckStrictly: true,
     deptCheckStrictly: true,
-    remark: undefined
+    remark: undefined,
+    yxq:null,
   };
   proxy.resetForm("roleRef");
 }
@@ -356,6 +379,14 @@ function handleUpdate(row) {
   const roleMenu = getRoleMenuTreeselect(roleId);
   getRole(roleId).then(response => {
     form.value = response.data;
+    if (form.value.remark != undefined) {
+      try {
+        form.value.yxq = JSON.parse(form.value.remark)["yxq"];
+        form.value.remark = JSON.parse(form.value.remark)["remark"];
+      }catch(e){
+
+      }
+    }
     form.value.roleSort = Number(form.value.roleSort);
     open.value = true;
     nextTick(() => {
@@ -426,19 +457,23 @@ function getMenuAllCheckedKeys() {
 }
 /** 提交按钮 */
 function submitForm() {
-  console.log(form.value)
   proxy.$refs["roleRef"].validate(valid => {
     if (valid) {
-      if (form.value.roleId != undefined) {
-        form.value.menuIds = getMenuAllCheckedKeys();
-        updateRole(form.value).then(response => {
+      let formp = cloneDeep(form.value);
+      formp.remark = JSON.stringify({
+        yxq: formp.yxq,
+        remark: formp.remark
+      });
+      if (formp.roleId != undefined) {
+        formp.menuIds = getMenuAllCheckedKeys();
+        updateRole(formp).then(response => {
           proxy.$modal.msgSuccess("修改成功");
           open.value = false;
           getList();
         });
       } else {
-        form.value.menuIds = getMenuAllCheckedKeys();
-        addRole(form.value).then(response => {
+        formp.menuIds = getMenuAllCheckedKeys();
+        addRole(formp).then(response => {
           proxy.$modal.msgSuccess("新增成功");
           open.value = false;
           getList();

+ 2 - 2
ruoyi-ui-vue3/vite.config.js

@@ -30,8 +30,8 @@ export default defineConfig(({ mode, command }) => {
       proxy: {
         // https://cn.vitejs.dev/config/#server-proxy
         "/dev-api": {
-          target: "http://58.252.235.18:8084/iot/prod-api",
-          // target: "http://localhost:8989",
+          // target: "http://58.252.235.18:8084/iot/prod-api",
+          target: "http://localhost:8989",
           changeOrigin: true,
           rewrite: (p) => p.replace(/^\/dev-api/, ""),
         },