xiaoxin 2 vuotta sitten
vanhempi
commit
e821abc365

+ 1 - 1
.env.development

@@ -5,7 +5,7 @@ VITE_APP_BASE_API_DATA = '/bigData'
 VITE_APP_BASE_API_DATA2 = '/bigData2'
 VITE_APP_BASE_API_LOCAL ='/local'
 VITE_SERVE="http://58.17.42.179:90/diseaseRight"
-VITE_SERVE_DATA="http://qt88.nc-ky.com/bigData"
+VITE_SERVE_DATA="http://58.17.42.179:90/bigData"
 VITE_SERVE_DATA2="http://58.17.42.179:90/bigData2"
 VITE_SERVE_LOCAL="http://58.17.42.179:90"
 

+ 20 - 0
package-lock.json

@@ -18,6 +18,7 @@
         "echarts": "^5.5.0",
         "element-plus": "^2.6.1",
         "moment": "^2.30.1",
+        "mpegts.js": "^1.7.3",
         "pinia": "^2.1.7",
         "sass": "^1.71.1",
         "vue": "^3.4.21",
@@ -1080,6 +1081,11 @@
         "node": ">=0.12"
       }
     },
+    "node_modules/es6-promise": {
+      "version": "4.2.8",
+      "resolved": "https://registry.npmmirror.com/es6-promise/-/es6-promise-4.2.8.tgz",
+      "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
+    },
     "node_modules/esbuild": {
       "version": "0.19.12",
       "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.19.12.tgz",
@@ -1328,6 +1334,15 @@
         "node": "*"
       }
     },
+    "node_modules/mpegts.js": {
+      "version": "1.7.3",
+      "resolved": "https://registry.npmmirror.com/mpegts.js/-/mpegts.js-1.7.3.tgz",
+      "integrity": "sha512-kqZ1C1IsbAQN72cK8vMrzKeM7hwrwSBbFAwVAc7PPweOeoZxCANrc7fAVDKMfYUzxdNkMTnec9tVmlxmKZB0TQ==",
+      "dependencies": {
+        "es6-promise": "^4.2.5",
+        "webworkify-webpack": "^2.1.5"
+      }
+    },
     "node_modules/muggle-string": {
       "version": "0.3.1",
       "resolved": "https://registry.npmmirror.com/muggle-string/-/muggle-string-0.3.1.tgz",
@@ -1666,6 +1681,11 @@
         "typescript": "*"
       }
     },
+    "node_modules/webworkify-webpack": {
+      "version": "2.1.5",
+      "resolved": "https://registry.npmmirror.com/webworkify-webpack/-/webworkify-webpack-2.1.5.tgz",
+      "integrity": "sha512-2akF8FIyUvbiBBdD+RoHpoTbHMQF2HwjcxfDvgztAX5YwbZNyrtfUMgvfgFVsgDhDPVTlkbb5vyasqDHfIDPQw=="
+    },
     "node_modules/yallist": {
       "version": "4.0.0",
       "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz",

+ 1 - 0
package.json

@@ -19,6 +19,7 @@
     "echarts": "^5.5.0",
     "element-plus": "^2.6.1",
     "moment": "^2.30.1",
+    "mpegts.js": "^1.7.3",
     "pinia": "^2.1.7",
     "sass": "^1.71.1",
     "vue": "^3.4.21",

+ 30 - 1
src/api/fire/index.ts

@@ -1,4 +1,6 @@
 import request from "@/utils/request";
+//引入用户相关的仓库
+import useUserStore from "@/store/modules/user";
 
 // 景区防火相关的请求地址
 enum API {
@@ -8,6 +10,15 @@ enum API {
   DISPOSEMSG_URL = "/emergencyDisposalStatistics/info",
   // 获取防火记录列表接口地址
   FIREDATA_URL = "/warningOfSmokeRecord/list",
+
+  // 查询烟雾报警数量 接口地址
+  SMOKECOUNT_URL = "/template/api/toiletBase/getWarmSmokeCount",
+
+  // 根据地址查询烟雾报警 接口地址
+  SMOKEBYPLACE_URL = "/template/api/toiletBase/getWarmSmokeByPlace",
+
+  // 处理防火预警 接口地址
+  HANDLESMOKE_URL = "/warningOfSmokeRecord/handle",
 }
 
 //获取当前防火等级
@@ -17,8 +28,26 @@ export const reqFireLevel = () => request.get(API.LEVEL_URL);
 export const reqDisposeMsg = () => request.get(API.DISPOSEMSG_URL);
 
 // 获取防火记录列表
-export const reqFireData = (data: any) => request.get(API.FIREDATA_URL, data);
+export const reqFireData = (params: any) =>
+  request.get(API.FIREDATA_URL, { params });
 
 // 获取防火记录列表单条数据详情
 export const reqFireDataById = (id: any) =>
   request.get(`/warningOfSmokeRecord/infoDetail/${id}`);
+
+// 查询烟雾报警数量
+export const reqGetSmokeCount = () =>
+  request.get(API.SMOKECOUNT_URL, { headers: { type: "local" } });
+
+// 根据地址查询烟雾报警信息
+export const reqGetSmokeByPlace = (params: any) =>
+  request.get(API.SMOKEBYPLACE_URL, { params, headers: { type: "local" } });
+
+//获取用户相关的小仓库:获取仓库内部token
+const userStore = useUserStore();
+
+// 处理防火预警
+export const reqGetHandleSmoke = (data: any) =>
+  request.put(API.HANDLESMOKE_URL, data, {
+    headers: { "Admin-Token": userStore.token },
+  });

+ 10 - 10
src/components/map/fireproofData.ts

@@ -11,12 +11,12 @@ export const fireproofData = [
       </div> 
     </div>
     `,
-    lng: 115.416074,
-    lat: 29.000106,
+    lng: 115.22,
+    lat: 29.03,
     ele: ".marker",
-    title: "宝峰景区防火",
-    left: -36,
-    right: -59,
+    title: "三爪仑虎啸峡森林防火",
+    left: 0,
+    right: 0,
   },
   {
     markerContent: `
@@ -29,12 +29,12 @@ export const fireproofData = [
       </div>
     </div>
     `,
-    lng: 115.272035,
-    lat: 29.040316,
+    lng: 115.41,
+    lat: 29.02,
     ele: ".marker",
-    title: "三爪仑景区防火",
-    left: -126,
-    right: -89,
+    title: "宝峰小湾森林防火",
+    left: 0,
+    right: 0,
   },
   {
     markerContent: `

+ 87 - 92
src/components/map/map.vue

@@ -30,17 +30,24 @@ import { radioData } from "./radioData";
 import { otherData } from "./otherData";
 // 景区点位标记数据
 import { scenicData } from "./scenicData";
+// 引入景区防火相关的接口
+import { reqGetSmokeCount } from "@/api/fire/index";
 
 const $props = defineProps({
   type: {
     type: String,
     default: "乡镇",
   },
+  showFire: {
+    type: Boolean,
+    default: false,
+  },
 });
 
 const $emit = defineEmits(["clickMarker"]);
 
 console.log($props.type);
+console.log($props.showFire);
 
 // 地图实例对象
 let map: any = null;
@@ -111,7 +118,7 @@ const initAMap = () => {
               new AMap.TileLayer.RoadNet(),
               // 添加卫星图层
               new AMap.TileLayer.Satellite({
-                opacity: 0.4,
+                opacity: 0.9,
               }),
               // 添加实时交通路况图层
               new AMap.TileLayer.Traffic({
@@ -207,102 +214,90 @@ const initAMap = () => {
 };
 
 // 监听地图类型变化重新渲染标记点
-watch(
-  () => $props.type,
-  () => {
-    console.log($props.type);
-
-    if ($props.type === "防火点位") {
-      // 更新地图描点上的数据
-      fireproofData[0].markerContent = `
-    <div class="fire"">
-      <div class="fire_text">
-         ${3}
-         <div class="icon"></div>
-      </div>
-      <div class="fire_icon">
-      </div>
-    </div>
-    `;
-      fireproofData[1].markerContent = `
-    <div class="fire"">
-      <div class="fire_text">
-         ${4}
-         <div class="icon"></div>
-      </div>
-      <div class="fire_icon">
-      </div>
-    </div>
-    `;
-      fireproofData[2].markerContent = `
-    <div class="fire"">
-      <div class="fire_text">
-         ${5}
-         <div class="icon"></div>
-      </div>
-      <div class="fire_icon">
-      </div>
-    </div>
-    `;
+watch($props, async () => {
+  console.log($props.type);
+
+  if ($props.type === "防火点位") {
+    const res = await reqGetSmokeCount();
+
+    // console.log(res);
+
+    if ((res as any).code == 200 && res.data.length) {
+      // 匹配数据 更新地图描点上的数据
+      fireproofData.forEach((ele: any) => {
+        res.data.forEach((item: any) => {
+          if (ele.title === item.place) {
+            ele.markerContent = `
+                <div class="fire"">
+                   <div class="fire_text">
+                        ${item.count}
+                   <div class="icon"></div>
+                   </div>
+                   <div class="fire_icon">
+                   </div>
+                </div>`;
+          }
+        });
+      });
     }
+  }
 
-    // 先清除之前标记点
-    markerList.value.forEach((element: any) => {
-      element.setMap(null);
-    });
+  // 先清除之前标记点
+  markerList.value.forEach((element: any) => {
+    element.setMap(null);
+  });
 
-    // 重新添加标记点并绑定事件
-    AMapLoader.load({
-      key: "d5b00a2684bdf5b38fcfbcf1f35c30bf",
-      version: "",
-    })
-      .then((AMap) => {
-        // 定义回调函数
-        function clearMarker(e: any) {
-          $emit("clickMarker", e.target.De.title, $props.type);
-        }
-
-        // 判断需要展示什么标记
-        let dataList: any = [];
-
-        // 获取标记点数据
-        dataList = getData();
-
-        //添加点标记
-        for (let i = 0; i < dataList.length; i++) {
-          // 文本内容
-          const markerContent = dataList[i].markerContent;
-
-          //Marker 经纬度
-          const position = new AMap.LngLat(dataList[i].lng, dataList[i].lat);
-
-          // 标记对象
-          const marker = new AMap.Marker({
-            // 经纬度
-            position: position,
-            //将 html 传给 content
-            content: markerContent,
-            //以 icon 的 [center bottom] 为原点
-            offset: new AMap.Pixel(dataList[i].left, dataList[i].right),
-            // 鼠标滑过点标记时的文字提示
-            title: dataList[i].title,
-            // 点标记的叠加顺序,默认12
-            // zIndex: dataList[i].zIndex ? dataList[i].zIndex : 12,
-            map: map,
-          });
+  // 重新添加标记点并绑定事件
+  AMapLoader.load({
+    key: "d5b00a2684bdf5b38fcfbcf1f35c30bf",
+    version: "",
+  })
+    .then((AMap) => {
+      // 定义回调函数
+      function clearMarker(e: any) {
+        $emit("clickMarker", e.target.De.title, $props.type);
+      }
+
+      // 判断需要展示什么标记
+      let dataList: any = [];
+
+      // 获取标记点数据
+      dataList = getData();
+
+      //添加点标记
+      for (let i = 0; i < dataList.length; i++) {
+        // 文本内容
+        const markerContent = dataList[i].markerContent;
+
+        //Marker 经纬度
+        const position = new AMap.LngLat(dataList[i].lng, dataList[i].lat);
+
+        // 标记对象
+        const marker = new AMap.Marker({
+          // 经纬度
+          position: position,
+          //将 html 传给 content
+          content: markerContent,
+          //以 icon 的 [center bottom] 为原点
+          offset: new AMap.Pixel(dataList[i].left, dataList[i].right),
+          // 鼠标滑过点标记时的文字提示
+          title: dataList[i].title,
+          // 点标记的叠加顺序,默认12
+          // zIndex: dataList[i].zIndex ? dataList[i].zIndex : 12,
+          map: map,
+        });
 
-          // 绑定点击事件
-          marker.on("click", clearMarker);
+        // 绑定点击事件
+        marker.on("click", clearMarker);
 
-          // 把标记点存储起来,方便后面清除
-          markerList.value.push(marker);
-        }
-      })
-      .catch((e) => {
-        console.error(e);
-      });
-  }
-);
+        // 把标记点存储起来,方便后面清除
+        markerList.value.push(marker);
+      }
+    })
+    .catch((e) => {
+      console.error(e);
+    });
+});
 
 // 获取标记点数据
 const getData = () => {

+ 2 - 0
src/components/map/scenicData.ts

@@ -632,6 +632,7 @@ export const scenicData = [
     right: -49,
     iframeUrl: `${baseUrl}/hik/cn/ch225_two.html`,
     rtspaddr: "rtsp://admin:hik12345@6.205.67.224:554/Streaming/Channels/102",
+    VRurl: "https://www.720yun.com/t/cavkieih02e?scene_id=33545192",
   },
   {
     markerContent: `
@@ -695,6 +696,7 @@ export const scenicData = [
     right: -33,
     iframeUrl: `${baseUrl}/hik/cn/ch40_two.html`,
     rtspaddr: "rtsp://admin:hik12345@6.205.68.39:554/Streaming/Channels/102",
+    VRurl: "https://www.720yun.com/t/67djz5hn5n5?scene_id=8195316",
   },
   // {
   //   title: "璪都红绿灯路口",

+ 1 - 1
src/utils/request.ts

@@ -5,7 +5,7 @@ import useUserStore from "@/store/modules/user";
 
 //创建axios实例
 let request = axios.create({
-  timeout: 25000,
+  timeout: 5000,
 });
 
 //请求拦截器

+ 38 - 13
src/views/analyse/center/centerAnalyse.vue

@@ -94,7 +94,7 @@
 </template>
 
 <script setup lang="ts">
-import { ref, onMounted, nextTick } from "vue";
+import { ref, onMounted, nextTick, onUnmounted } from "vue";
 import NewsListDialog from "./newsListDialog.vue";
 import ScenicDetailDialog from "./scenicDetailDialog.vue";
 import PeopleDetailDialog from "./peopleDetailDialog.vue";
@@ -144,35 +144,56 @@ const marqueeDom = ref();
 // 完成动画需要的时间
 const marqueeTime = ref();
 
+// 定时器标识
+const timer = ref();
+
 onMounted(() => {
   // 获取所有路口当日人数
-  getAllJtNumByDay();
+  getAllJtNumByDay(true);
   // 获取所有路口累计人数
-  getAllJtNumByTotal();
+  getAllJtNumByTotal(true);
   // 获取公告数据
   getNotice();
   // 获取所有景区当日人数
-  getAllNumByReal();
+  getAllNumByReal(true);
   // 获取所有景区累计人数
-  getAllNumByAdd();
+  getAllNumByAdd(true);
+
+  // 每10秒刷新数据
+  timer.value = setInterval(() => {
+    getAllJtNumByDay(false);
+    getAllJtNumByTotal(false);
+    getNotice();
+    getAllNumByReal(false);
+    getAllNumByAdd(false);
+  }, 10000);
+});
+
+onUnmounted(() => {
+  // 页面卸载时清除定时器
+  clearInterval(timer.value);
 });
 
 // 获取所有路口当日人数
-const getAllJtNumByDay = async () => {
+const getAllJtNumByDay = async (flag: boolean) => {
   const res = await reqAllJtNumByDay();
   // console.log(res);
   realValue.value = res.data[0].num;
   // 让数字跳动
-  countUpNum(realDom.value, realValue.value);
+  if (flag) {
+    countUpNum(realDom.value, realValue.value);
+  }
 };
 
 // 获取所有路口累计人数
-const getAllJtNumByTotal = async () => {
+const getAllJtNumByTotal = async (flag: boolean) => {
   const res = await reqAllJtNumByTotal();
   // console.log(res);
   addValue.value = res.data[0].num;
   // 让数字跳动
-  countUpNum(addDom.value, addValue.value);
+  if (flag) {
+    countUpNum(addDom.value, addValue.value);
+  }
 };
 
 // 获取公告数据
@@ -198,21 +219,25 @@ const getNotice = async () => {
 };
 
 // 获取所有景区当日人数
-const getAllNumByReal = async () => {
+const getAllNumByReal = async (flag: boolean) => {
   const res = await reqGetAllNumByReal();
   // console.log(res);
   realValue2.value = res.data.num * 1;
   // 让数字跳动
-  countUpNum(realDom2.value, realValue2.value);
+  if (flag) {
+    countUpNum(realDom2.value, realValue2.value);
+  }
 };
 
 // 获取所有景区累计人数
-const getAllNumByAdd = async () => {
+const getAllNumByAdd = async (flag: boolean) => {
   const res = await reqGetAllNumByAdd();
   // console.log(res);
   addValue2.value = res.data.num * 1;
   // 让数字跳动
-  countUpNum(addDom2.value, addValue2.value);
+  if (flag) {
+    countUpNum(addDom2.value, addValue2.value);
+  }
 };
 
 // 点击靖安进出人流查看详情按钮回调

+ 14 - 1
src/views/analyse/center/peopleDetailDialog.vue

@@ -30,7 +30,7 @@
 </template>
 
 <script setup lang="ts">
-import { ref, onMounted } from "vue";
+import { ref, onMounted, onUnmounted } from "vue";
 import PeopleChart from "./peopleChart.vue";
 import PeopleSlot from "./peopleSlot.vue";
 // 引入路口数据
@@ -47,9 +47,22 @@ const $emit = defineEmits(["changeShowClosePeople"]);
 // 路口详细信息数组
 const slotList = ref<any>([]);
 
+// 定时器标识
+const timer = ref();
+
 onMounted(() => {
   // 获取路口数组数据
   getList();
+
+  // 每5秒刷新数据
+  timer.value = setInterval(() => {
+    getList();
+  }, 5000);
+});
+
+onUnmounted(() => {
+  // 页面卸载时清除定时器
+  clearInterval(timer.value);
 });
 
 // 获取路口数组数据

+ 11 - 0
src/views/analyse/left/crossingDetailDialog.vue

@@ -80,6 +80,9 @@ const loading = ref(true);
 // 监控实例
 const player = ref();
 
+// 定时器标识
+const timer = ref();
+
 onMounted(() => {
   // console.log(props.detailObj);
 
@@ -89,11 +92,19 @@ onMounted(() => {
   getJtNumByTotal();
   // 获取表格数据
   getTableData();
+
+  // 每5秒刷新数据
+  timer.value = setInterval(() => {
+    getJtNumByTotal();
+    getTableData();
+  }, 5000);
 });
 
 onUnmounted(() => {
   // 页面卸载时销毁WasmPlayer实例
   player.value.destroy();
+  // 页面卸载时清除定时器
+  clearInterval(timer.value);
 });
 
 // 获取监控视频地址

+ 19 - 4
src/views/analyse/left/leftAnalyse.vue

@@ -49,7 +49,7 @@
 </template>
 
 <script setup lang="ts">
-import { ref, onMounted, nextTick } from "vue";
+import { ref, onMounted, nextTick, onUnmounted } from "vue";
 import CrossingDetailDialog from "./crossingDetailDialog.vue";
 import AnalyseMapDialog from "../analyseMapDialog.vue";
 import { countUpNum } from "@/utils/countUpNum.ts";
@@ -71,13 +71,26 @@ const showDialogMap = ref<boolean>(false);
 // 点击路口的数据
 const detailObj = ref({});
 
+// 定时器标识
+const timer = ref();
+
 onMounted(() => {
   // 获取路口数据
-  getList();
+  getList(true);
+
+  // 每10秒刷新数据
+  timer.value = setInterval(() => {
+    getList(false);
+  }, 10000);
+});
+
+onUnmounted(() => {
+  // 页面卸载时清除定时器
+  clearInterval(timer.value);
 });
 
 // 获取路口数据
-const getList = async () => {
+const getList = async (flag: boolean) => {
   const res = await reqJtNumByDay();
   // console.log(res);
   list.value = res.data;
@@ -91,7 +104,9 @@ const getList = async () => {
   });
 
   // 让数字跳动
-  getCountUpNum();
+  if (flag) {
+    getCountUpNum();
+  }
 };
 
 // 点击每一个路口回调

+ 12 - 0
src/views/analyse/left/mapCrossingDialog.vue

@@ -80,6 +80,9 @@ const dayNum = ref(0);
 // 监控实例
 const player = ref();
 
+// 定时器标识
+const timer = ref();
+
 onMounted(() => {
   // 获取视频地址
   getVideosData();
@@ -89,11 +92,20 @@ onMounted(() => {
   getJtNumByTotal();
   // 获取表格数据
   getTableData();
+
+  // 每5秒刷新数据
+  timer.value = setInterval(() => {
+    getJtNumByDay();
+    getJtNumByTotal();
+    getTableData();
+  }, 5000);
 });
 
 onUnmounted(() => {
   // 页面卸载时销毁WasmPlayer实例
   player.value.destroy();
+  // 页面卸载时清除定时器
+  clearInterval(timer.value);
 });
 
 // 监听路口变化更新数据

+ 16 - 4
src/views/analyse/right/mapScenicDialog.vue

@@ -114,18 +114,28 @@ const scenicInfo = ref();
 // 监控实例
 const player = ref();
 
+// 定时器标识
+const timer = ref();
+
 onMounted(() => {
   // 获取监控视频地址
   getVideosData();
   // 获取景点信息
   getScenicInfo();
   // 获取单个景点人数相关信息
-  getScenicInfoByNum();
+  getScenicInfoByNum(true);
+
+  // 每5秒刷新数据
+  timer.value = setInterval(() => {
+    getScenicInfoByNum(false);
+  }, 5000);
 });
 
 onUnmounted(() => {
   // 页面卸载时销毁WasmPlayer实例
   player.value.destroy();
+  // 页面卸载时清除定时器
+  clearInterval(timer.value);
 });
 
 // 监听景区变化刷新数据
@@ -136,7 +146,7 @@ watch(props.detailObj, () => {
   // 获取景点信息
   getScenicInfo();
   // 获取单个景点人数相关信息
-  getScenicInfoByNum();
+  getScenicInfoByNum(true);
 });
 
 // 获取监控视频地址
@@ -157,7 +167,7 @@ const getScenicInfo = async () => {
 };
 
 // 获取单个景点人数相关信息
-const getScenicInfoByNum = async () => {
+const getScenicInfoByNum = async (flag: boolean) => {
   const res = await reqGetScenicInfoByNum({
     place_name: props.detailObj.name,
   });
@@ -166,7 +176,9 @@ const getScenicInfoByNum = async () => {
   addValue.value = res.LjNum * 1;
   moreValue.value = res.maxNum;
   // 让数字跳动
-  getCountUpNum();
+  if (flag) {
+    getCountUpNum();
+  }
 };
 
 // 让数字跳动

+ 24 - 8
src/views/analyse/right/rightAnalyse.vue

@@ -48,7 +48,7 @@
 </template>
 
 <script setup lang="ts">
-import { ref, onMounted, nextTick } from "vue";
+import { ref, onMounted, nextTick, onUnmounted } from "vue";
 import ScenicDetailDialog from "./scenicDetailDialog.vue";
 import AnalyseMapDialog from "../analyseMapDialog.vue";
 import { countUpNum } from "@/utils/countUpNum.ts";
@@ -71,13 +71,26 @@ const list: any = ref([]);
 // 点击景区的数据
 const detailObj = ref({});
 
+// 定时器标识
+const timer = ref();
+
 onMounted(() => {
   // 获取景区列表数据
-  getData();
+  getData(true);
+
+  // 每10秒刷新数据
+  timer.value = setInterval(() => {
+    getData(false);
+  }, 10000);
+});
+
+onUnmounted(() => {
+  // 页面卸载时清除定时器
+  clearInterval(timer.value);
 });
 
 // 获取景区列表数据
-const getData = async () => {
+const getData = async (flag: boolean) => {
   const res = await reqGetNumByPlace();
   // console.log(res);
 
@@ -85,16 +98,17 @@ const getData = async () => {
     scenicData.forEach((e) => {
       if (e.title === ele.place) {
         ele.rtspaddr = e.rtspaddr;
+        ele.VRurl = e.VRurl;
       }
     });
   });
 
   list.value = res.data;
 
-  nextTick(() => {
-    // 让数字跳动
+  // 让数字跳动
+  if (flag) {
     getCountUpNum();
-  });
+  }
 };
 
 // 点击每一个景区时的回调
@@ -110,8 +124,10 @@ const handleMap = () => {
 
 // 让数字跳动
 const getCountUpNum = () => {
-  boxNum.value.forEach((ele: any) => {
-    countUpNum(ele, ele.dataset.value);
+  nextTick(() => {
+    boxNum.value.forEach((ele: any) => {
+      countUpNum(ele, ele.dataset.value);
+    });
   });
 };
 

+ 26 - 4
src/views/analyse/right/scenicDetailDialog.vue

@@ -31,6 +31,15 @@
             &nbsp;&nbsp;&nbsp;&nbsp; 电话号码:{{
               scenicInfo?.responsiblerPhone || "未知"
             }}
+            &nbsp;&nbsp;&nbsp;&nbsp;VR链接:
+            <el-link
+              v-if="props.detailObj.VRurl"
+              :href="props.detailObj.VRurl"
+              target="_blank"
+            >
+              <el-icon size="32" color="#7DC0FF"><Link /></el-icon>
+            </el-link>
+            <span v-else>暂无</span>
           </div>
         </div>
       </div>
@@ -103,6 +112,7 @@ import { reqGetScenicInfo, reqGetScenicInfoByNum } from "@/api/scenic/index";
 import { getVedio } from "@/api/video/index";
 // @ts-ignore
 import WasmPlayer from "@easydarwin/easywasmplayer";
+import { Link } from "@element-plus/icons-vue";
 
 // 父组件传递过来的数据
 const props = defineProps(["detailObj"]);
@@ -125,20 +135,30 @@ const scenicInfo = ref();
 // 监控实例
 const player = ref();
 
+// 定时器标识
+const timer = ref();
+
 onMounted(() => {
-  // console.log(props.detailObj);
+  console.log(props.detailObj);
 
   // 获取监控视频地址
   getVideosData();
   // 获取景点信息
   getScenicInfo();
   // 获取单个景点人数相关信息
-  getScenicInfoByNum();
+  getScenicInfoByNum(true);
+
+  // 每5秒刷新数据
+  timer.value = setInterval(() => {
+    getScenicInfoByNum(false);
+  }, 5000);
 });
 
 onUnmounted(() => {
   // 页面卸载时销毁WasmPlayer实例
   player.value.destroy();
+  // 页面卸载时清除定时器
+  clearInterval(timer.value);
 });
 
 // 获取监控视频地址
@@ -157,7 +177,7 @@ const getScenicInfo = async () => {
 };
 
 // 获取单个景点人数相关信息
-const getScenicInfoByNum = async () => {
+const getScenicInfoByNum = async (flag: boolean) => {
   const res = await reqGetScenicInfoByNum({
     place_name: props.detailObj.place,
   });
@@ -166,7 +186,9 @@ const getScenicInfoByNum = async () => {
   addValue.value = res.LjNum * 1;
   moreValue.value = res.maxNum;
   // 让数字跳动
-  getCountUpNum();
+  if (flag) {
+    getCountUpNum();
+  }
 };
 
 // 让数字跳动

+ 1 - 1
src/views/safe/center/centerSafe.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="center_safe">
     <!-- 地图组件 -->
-    <Map :type="currentValue" @clickMarker="clickMarker" />
+    <Map :type="currentValue" :showFire="showFire" @clickMarker="clickMarker" />
 
     <!-- 点位总计区域 -->
     <div class="center_num">

+ 111 - 22
src/views/safe/center/fireDetailDialog.vue

@@ -9,48 +9,119 @@
 
       <!-- 主体内容区域 -->
       <div class="info">
-        <div class="info_container" v-for="(item, index) in 2" :key="item">
+        <div
+          class="info_container"
+          v-for="(item, index) in dataList"
+          :key="item.id"
+        >
           <div class="info_title">火灾{{ index + 1 }}</div>
-          <div class="info_box">发生时间:2024-01-18 15:25:26</div>
-          <div class="info_box">发生地点:这里是冒烟告警的发生地点发生地点</div>
+          <div class="info_box">
+            发生时间:{{
+              dayjs(item.publish_time).format("YYYY-MM-DD HH:mm:ss")
+            }}
+          </div>
+          <div class="info_box">发生地点:{{ item.place }}</div>
           <div class="info_detail">
             告警图片:
-            <el-image
-              class="img"
-              src="https://pic.rmb.bdstatic.com/daca09fd4974fe3361289d3306db4d63.jpeg"
-              :preview-src-list="[
-                'https://pic.rmb.bdstatic.com/daca09fd4974fe3361289d3306db4d63.jpeg',
-              ]"
-              fit="cover"
-              hide-on-click-modal
-            />
-            <el-image
+            <img
               class="img"
-              src="https://pic.rmb.bdstatic.com/daca09fd4974fe3361289d3306db4d63.jpeg"
-              :preview-src-list="[
-                'https://pic.rmb.bdstatic.com/daca09fd4974fe3361289d3306db4d63.jpeg',
-              ]"
-              fit="cover"
-              hide-on-click-modal
+              :src="`http://6.200.0.4:8878${item.images}`"
+              @click="handleClickImg(item)"
             />
           </div>
           <div class="info_bts">
-            <div class="btn left">告警解除</div>
-            <div class="btn right">火灾确认</div>
+            <!-- <div class="btn left">告警解除</div> -->
+            <div class="btn right" @click="handleConfirm(item)">火灾确认</div>
           </div>
         </div>
+
+        <!-- 没有数据时展示的内容 -->
+        <div v-if="!dataList.length" class="info_nodata">暂无数据</div>
       </div>
 
       <!-- 关闭按钮区域 -->
       <div class="close" @click="handleClose"></div>
+
+      <!-- 视频弹窗区域 -->
+      <video
+        v-if="showVideo"
+        class="video"
+        controls
+        autoplay
+        muted
+        :src="videoSrc"
+      ></video>
     </div>
   </div>
 </template>
 
 <script setup lang="ts">
-defineProps(["currentFire"]);
+import { onMounted, ref } from "vue";
+// 引入景区防火相关的接口
+import { reqGetSmokeByPlace, reqGetHandleSmoke } from "@/api/fire/index";
+import dayjs from "dayjs";
+import { ElMessage, ElMessageBox } from "element-plus";
+
+const $props = defineProps(["currentFire"]);
+
 const $emit = defineEmits(["closeDialog"]);
 
+// 防火预警列表
+const dataList = ref<any>([]);
+
+// 是否展示视频弹窗
+const showVideo = ref(false);
+
+// 弹窗视频地址
+const videoSrc = ref("");
+
+onMounted(() => {
+  // 根据地址查询烟雾报警信息
+  getSmokeByPlace();
+});
+
+// 根据地址查询烟雾报警信息
+const getSmokeByPlace = async () => {
+  const res = await reqGetSmokeByPlace({
+    place: $props.currentFire,
+  });
+  // console.log(res);
+  dataList.value = res.data || [];
+};
+
+// 火灾确认按钮回调
+const handleConfirm = (item: any) => {
+  // console.log(item);
+  ElMessageBox.confirm("确定处理吗?", "提示", {
+    confirmButtonText: "确定",
+    cancelButtonText: "取消",
+    type: "warning",
+  })
+    .then(async () => {
+      const res = await reqGetHandleSmoke({
+        warningId: item.id,
+        handleDesc: "",
+      });
+      // console.log(res);
+      if ((res as any).code == 1 && (res as any).success) {
+        ElMessage.success("处理成功");
+        handleClose();
+      }
+    })
+    .catch(() => {});
+};
+
+// 点击图片时的回调
+const handleClickImg = (item: any) => {
+  // console.log(item);
+  if (item.video) {
+    showVideo.value = true;
+    videoSrc.value = `http://6.200.0.4:8878${item.video}`;
+  } else {
+    showVideo.value = false;
+  }
+};
+
 // 点击关闭按钮回调
 const handleClose = () => {
   $emit("closeDialog", false);
@@ -158,6 +229,9 @@ const handleClose = () => {
             width: 198px;
             height: 134px;
             border-radius: 6px;
+            object-fit: cover;
+            cursor: pointer;
+            background-color: rgba($color: #000000, $alpha: 0.2);
           }
         }
 
@@ -186,6 +260,12 @@ const handleClose = () => {
           }
         }
       }
+
+      .info_nodata {
+        margin-top: 150px;
+        font-size: 30px;
+        text-align: center;
+      }
     }
 
     .close {
@@ -198,6 +278,15 @@ const handleClose = () => {
       background-image: url(@/assets/images/12.png);
       background-size: 100% 100%;
     }
+
+    .video {
+      position: absolute;
+      top: -125px;
+      right: -1300px;
+      width: 1200px;
+      height: 850px;
+      border-radius: 10px;
+    }
   }
 }
 </style>

+ 1 - 0
src/views/safe/left/leftSafe.vue

@@ -97,6 +97,7 @@ onUnmounted(() => {
 const getVideosData = () => {
   scenicData.slice(0, 9).forEach(async (ele, index) => {
     const res = await getVedio(ele.rtspaddr);
+    // console.log(res);
     let player = new WasmPlayer(null, index + "leftWatch");
     player.play(res, 1);
     playerList.value.push(player);

+ 2 - 2
src/views/safe/right/fireDetailDialog.vue

@@ -23,8 +23,8 @@
         <el-image
           class="img"
           fit="cover"
-          :src="showObj.images"
-          :preview-src-list="[showObj.images]"
+          :src="`http://6.200.0.4:8878${showObj.images}`"
+          :preview-src-list="[`http://6.200.0.4:8878${showObj.images}`]"
           hide-on-click-modal
         >
         </el-image>

+ 3 - 2
src/views/safe/right/rightSafe.vue

@@ -266,12 +266,12 @@ const fireLevel = ref("");
 const videoList = ref([
   {
     id: "4",
-    name: "宝峰景区防火",
+    name: "宝峰小湾森林防火",
     rtspaddr: "rtsp://admin:hik12345@6.205.67.206:554/Streaming/Channels/102",
   },
   {
     id: "5",
-    name: "三爪仑景区防火",
+    name: "三爪仑虎啸峡森林防火",
     rtspaddr: "rtsp://admin:hik12345@6.205.67.207:554/Streaming/Channels/102",
   },
   {
@@ -392,6 +392,7 @@ const getVideosData = () => {
   videoList.value.forEach(async (ele) => {
     const res = await getVedio(ele.rtspaddr);
     let player = new WasmPlayer(null, ele.id);
+
     player.play(res, 1);
     playerList.value.push(player);
   });

+ 2 - 2
src/views/safe/right/smokeDetailDialog.vue

@@ -20,8 +20,8 @@
       <el-image
         class="img"
         fit="cover"
-        :src="showObj.images"
-        :preview-src-list="[showObj.images]"
+        :src="`http://6.200.0.4:8878${showObj.images}`"
+        :preview-src-list="[`http://6.200.0.4:8878${showObj.images}`]"
         hide-on-click-modal
       >
       </el-image>

+ 7 - 0
src/views/server/left/evaluateDetailDialog.vue

@@ -111,6 +111,7 @@
           v-model:current-page="currentPage"
           v-model:page-size="pageSize"
           :total="total"
+          @current-change="handleCurrentChange"
         />
       </div>
 
@@ -226,6 +227,12 @@ const handleSearch = () => {
   currentPage.value = 1;
   getCommentInfo();
 };
+
+// 分页回调
+const handleCurrentChange = (v: number) => {
+  currentPage.value = v;
+  getCommentInfo();
+};
 </script>
 
 <style lang="scss" scoped>

+ 2 - 1
src/views/server/left/hot.vue

@@ -2,7 +2,7 @@
   <div class="hot">
     <!-- 标题区域 -->
     <div class="hot_title">
-      <div class="title_text">销售热榜TOP3</div>
+      <div class="title_text">销售TOP热榜</div>
       <img src="@/assets/images/33.png" />
     </div>
 
@@ -16,6 +16,7 @@
           <div class="info_num" ref="infoNum" :data-value="item.total">
             {{ item.total }}
           </div>
+          <div>&nbsp;单</div>
         </div>
         <div class="item_progress">
           <el-progress

+ 1 - 1
src/views/server/left/sale.vue

@@ -39,7 +39,7 @@ const getMonthTrend = async () => {
 
   // 处理数据
   res.data.forEach((ele: any) => {
-    timeList.value.push(ele.mon.slice(-2) + "月");
+    timeList.value.push(ele.mon.slice(-2));
     valueList.value.push(ele.value);
   });
 

+ 17 - 7
src/views/server/left/stat.vue

@@ -27,8 +27,10 @@
         </div>
         <div class="box_info">
           <div class="info_top">昨日订房量统计</div>
-          <div class="info_bottom">
-            <div ref="yesterdayDom">{{ yesterdayValue }}</div>
+          <div class="info_bottom" :title="yesterdayValue + '间'">
+            <div ref="yesterdayDom">
+              {{ yesterdayValue }}
+            </div>
             <span>间</span>
           </div>
         </div>
@@ -41,7 +43,7 @@
         </div>
         <div class="box_info">
           <div class="info_top">昨日销售额统计</div>
-          <div class="info_bottom">
+          <div class="info_bottom" :title="yesdayMoneyValue + '元'">
             <div ref="yesdayMoneyDom">{{ yesdayMoneyValue }}</div>
             <span>元</span>
           </div>
@@ -55,7 +57,7 @@
         </div>
         <div class="box_info">
           <div class="info_top">累计订房量统计</div>
-          <div class="info_bottom">
+          <div class="info_bottom" :title="addValue + '间'">
             <div ref="addDom">{{ addValue }}</div>
             <span>间</span>
           </div>
@@ -69,7 +71,7 @@
         </div>
         <div class="box_info">
           <div class="info_top">累计销售额统计</div>
-          <div class="info_bottom">
+          <div class="info_bottom" :title="addMoneyValue + '元'">
             <div ref="addMoneyDom">{{ addMoneyValue }}</div>
             <span>元</span>
           </div>
@@ -183,8 +185,8 @@ const getCountUpNum = () => {
 
   .stat_content {
     display: grid;
-    gap: 20px 60px;
-    grid-template-columns: repeat(2, 1fr);
+    gap: 20px 20px;
+    grid-template-columns: repeat(2, 270px);
     grid-template-rows: repeat(2, 1fr);
     width: 548px;
     height: 200px;
@@ -218,6 +220,7 @@ const getCountUpNum = () => {
         flex-direction: column;
         justify-content: space-between;
         margin-left: 17.5px;
+        width: 200px;
         height: 70px;
 
         .info_top {
@@ -229,6 +232,13 @@ const getCountUpNum = () => {
           font-size: 35px;
           font-weight: bold;
           color: #78b7ff;
+          cursor: pointer;
+
+          div {
+            white-space: nowrap;
+            overflow: hidden;
+            text-overflow: ellipsis;
+          }
 
           span {
             align-self: center;

+ 26 - 7
src/views/server/right/parkingScene.vue

@@ -2,7 +2,7 @@
   <div class="parking_scene">
     <!-- 标题区域 -->
     <div class="title">
-      <div class="title_text">各停车场实况</div>
+      <div class="title_text">各停车场近24小时实况</div>
       <img src="@/assets/images/33.png" />
     </div>
 
@@ -57,7 +57,7 @@
 <script setup lang="ts">
 import { ref, onMounted } from "vue";
 import * as Echarts from "echarts";
-import { getNearDay } from "@/utils/getNearDay.ts";
+// import { getNearDay } from "@/utils/getNearDay.ts";
 // 引入旅游服务相关的接口
 import { reqGetAllParkingInfo, reqGetParkingInfoById } from "@/api/serve/index";
 
@@ -73,11 +73,15 @@ const parkingInfo = ref();
 // 折线图DOM元素
 const lineChart = ref(null);
 
+// 折线图x轴数据
+const xData = ref<any>([]);
+
+// 折线图y轴数据
+const yData = ref<any>([]);
+
 onMounted(() => {
   // 获取停车场列表
   getAllParkingInfo();
-  // 初始化折线图
-  initLineChart();
 });
 
 // 获取停车场列表
@@ -98,7 +102,15 @@ const getParkingInfoById = async () => {
     id: placeValue.value,
   });
   // console.log(res);
-  parkingInfo.value = res.data[0];
+
+  parkingInfo.value = res.data.parkingInfo[0];
+
+  res.data.parkingHistory.forEach((ele: any) => {
+    xData.value.push(ele.day_id.slice(-2) + ":00");
+    yData.value.push(ele.num_of_total - ele.number_of_remainder);
+  });
+  // 初始化折线图
+  initLineChart();
 };
 
 // 初始化折线图
@@ -128,7 +140,7 @@ const initLineChart = () => {
         fontSize: 16,
         margin: 20,
       },
-      data: getNearDay(7),
+      data: xData.value,
     },
     yAxis: {
       type: "value",
@@ -148,9 +160,14 @@ const initLineChart = () => {
         },
       },
     },
+    dataZoom: [
+      {
+        type: "inside",
+      },
+    ],
     series: [
       {
-        data: [160, 199, 126, 116, 216, 516, 126, 316],
+        data: yData.value,
         type: "line",
         smooth: true,
         color: "#1F92F6",
@@ -188,6 +205,8 @@ const initLineChart = () => {
 // 停车场选择框切换回调
 const handleChange = (e: any) => {
   placeValue.value = e;
+  xData.value = [];
+  yData.value = [];
   getParkingInfoById();
 };
 </script>