Переглянути джерело

地图组织打点及组织详情弹框 动画调试

zhangsijie 1 рік тому
батько
коміт
1782d6ea1f

+ 7 - 2
minggao/index.html

@@ -3,7 +3,7 @@
  * @Autor: lin
  * @Date: 2023-06-05 08:51:07
  * @LastEditors: lin
- * @LastEditTime: 2024-03-14 15:58:34
+ * @LastEditTime: 2024-04-11 15:22:19
 -->
 <!DOCTYPE html>
 <html>
@@ -17,7 +17,12 @@
     <div id="app"></div>
     <!-- built files will be auto injected -->
     <script src="https://webstaticimg.oss-cn-hangzhou.aliyuncs.com/bigdata_app/js/ezuikit.js"></script>
+    <script type="text/javascript">
+      window._AMapSecurityConfig = {
+        serviceHost: "https://www.yhswjc.com/_AMapService",
+      };
+    </script>
     <!-- <script src="https://webapi.amap.com/maps?v=1.4.15&key=bd1582190896ab05afb30aa8161d14c2"></script> -->
-    <script src="https://webapi.amap.com/maps?v=1.4.15&key=9ffaf42e87ed317af4e775939a95081b&plugin=AMap.PolygonEditor,AMap.MarkerCluster,AMap.InfoWindow"></script>
+    <script src="https://webapi.amap.com/maps?v=2.0&key=9ffaf42e87ed317af4e775939a95081b&plugin=AMap.PolygonEditor,AMap.MarkerCluster,AMap.InfoWindow,AMap.GeoJSON"></script>
   </body>
 </html>

Різницю між файлами не показано, бо вона завелика
+ 1230 - 268
minggao/package-lock.json


+ 1 - 0
minggao/package.json

@@ -10,6 +10,7 @@
     "build": "node build/build.js"
   },
   "dependencies": {
+    "animate.css": "^4.1.1",
     "axios": "^0.24.0",
     "dayjs": "^1.11.7",
     "echarts": "^4.9.0",

BIN
minggao/src/assets/images/newHome/centerTopBg.png


minggao/src/assets/images/newHome/Property 1=Default@2x.png → minggao/src/assets/images/newHome/close.png


minggao/src/assets/images/newHome/Property 1=Variant2@2x.png → minggao/src/assets/images/newHome/closeHover.png


BIN
minggao/src/assets/images/newHome/leftBg.png


BIN
minggao/src/assets/images/newHome/rightBg.png


+ 10 - 2
minggao/src/components/AMap/index.vue

@@ -1,3 +1,10 @@
+<!--
+ * @Description:
+ * @Autor: lin
+ * @Date: 2023-06-06 16:23:26
+ * @LastEditors: lin
+ * @LastEditTime: 2024-04-10 10:53:48
+-->
 <template>
   <div id="amap-container"></div>
 </template>
@@ -10,13 +17,13 @@ export default {
   },
   mounted() {
     console.log('mounted');
-    this.initMap();
+    // this.initMap();
   },
   methods: {
     initMap() {
       AMapLoader.load({
         key: '9ffaf42e87ed317af4e775939a95081b', // 申请好的Web端开发者Key,首次调用 load 时必填
-        version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
+        // version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
         plugins: ['AMap.PolygonEditor', 'AMap.MarkerCluster', 'AMap.InfoWindow'] // 需要使用的的插件列表,如比例尺'AMap.Scale'等
       })
         .then(AMap => {
@@ -24,6 +31,7 @@ export default {
             //设置地图容器id
             viewMode: '3D', //是否为3D地图模式
             zoom: 5, //初始化地图级别
+            mapStyle: 'amap://styles/fff0c1ac5471818a21cf82c0931f60c0',
             center: [105.602725, 37.076636] //初始化地图中心点位置
           });
         })

+ 2 - 1
minggao/src/main.js

@@ -4,6 +4,7 @@ import ElementUI from 'element-ui';
 import router from './router'
 import store from '@/store/store.js'
 import less from 'less'
+import 'animate.css'
 Vue.use(less)
 
 import './assets/js/directives'; // 实现elementui对话框可拖拽功能
@@ -56,7 +57,7 @@ const Qs = require('qs')
 Vue.prototype.$imghost = Vue.prototype.DOMIN // 翟毅飞本地图片服务器路径常量
 // Vue.prototype.$imghost = 'http://www.hnyfwlw.com:8006/projectimg' // 线上图片服务器路径常量
 Vue.prototype.$insectHost = 'https://images.weserv.nl/?url=' // 线上图片服务器路径常量
-Vue.prototype.$wsUrl = Vue.prototype.wsUrl  // 实时通信服务器url 
+Vue.prototype.$wsUrl = Vue.prototype.wsUrl  // 实时通信服务器url
 Vue.prototype.$deriveData = Vue.prototype.DOMIN // 导出
 // Vue.prototype.$deriveData = 'http://114.115.147.140:12345' // 导出
 Vue.prototype.$faultvideo = Vue.prototype.DOMIN //售后视频地址前缀

Різницю між файлами не показано, бо вона завелика
+ 1549 - 4227
minggao/src/page/home/newHome/geo.json


+ 2 - 1
minggao/src/page/home/newHome/index.vue

@@ -3,7 +3,7 @@
  * @Autor: lin
  * @Date: 2024-04-09 14:29:42
  * @LastEditors: lin
- * @LastEditTime: 2024-04-09 15:46:11
+ * @LastEditTime: 2024-04-11 17:26:18
 -->
 <template>
   <div class="bigBox">
@@ -81,6 +81,7 @@ export default {
     font-weight: 700;
     letter-spacing: 5.6px;
     padding-top: 1rem;
+    pointer-events: none;
     top: 0;
     left: 0;
     width: 100%;

+ 257 - 87
minggao/src/page/home/newHome/newHome.vue

@@ -3,22 +3,67 @@
  * @Autor: lin
  * @Date: 2024-04-09 14:26:07
  * @LastEditors: lin
- * @LastEditTime: 2024-04-09 16:50:25
+ * @LastEditTime: 2024-04-11 17:15:20
 -->
 <template>
-  <div class="box">
+  <div class="box" v-loading="loading">
     <div class="mapBox" id="newHome"></div>
+    <!-- 点击地图圆圈的详情 -->
+    <div v-if="groupDialog" class="dialog animate__animated animate__bounceInDown">
+      <div class="dialog_content">
+        <div class="dialog_close" @click="groupDialog=false"></div>
+      </div>
+    </div>
   </div>
 </template>
 
 <script>
 export default {
+  name:'newHome',
   props: {
 
   },
   data() {
     return {
-
+      timmerList: [], // 水波纹的定时器
+      getFunTimmer: [], // 函数的定时器
+      overlayList: [],
+      loading: true,
+      colorObject: {
+        0: '#3ACD9C',
+        1: '#FF5951',
+        2: '#F4A72F',
+        3: '#1890FF',
+        4: '#FAFF0A'
+      },
+      warningObject: [{
+        level: 0,
+        color: '#3ACD9C',
+        text: '无'
+      },
+      {
+        level: 1,
+        color: '#FF5951',
+        text: 'Ⅰ'
+      },
+      {
+        level: 2,
+        color: '#F4A72F',
+        text: 'Ⅱ'
+      },
+      {
+        level: 3,
+        color: '#1890FF',
+        text: 'Ⅲ'
+      },
+      {
+        level: 4,
+        color: '#FAFF0A',
+        text: 'Ⅳ'
+      }],
+      map: null,
+      deviceInfo: [],
+      groupDialog: false
     };
   },
   computed: {
@@ -27,98 +72,193 @@ export default {
   created() {
 
   },
+  beforeDestroy() {
+    this.clerrTimmerFun('fun');
+    this.clerrTimmerFun('circle');
+  },
   mounted() {
-    this.initMap()
+    this.initMap();
   },
   watch: {
 
   },
   methods: {
+    // 清除指定覆盖物
+    clearOverlayByType(type) {
+      var overlays = this.map.getAllOverlays(type);
+      for (var i = 0, l = overlays.length; i < l; i++) {
+        this.map.remove(overlays[i]);
+      }
+    },
+    // 清除所有定时器
+    clerrTimmerFun(type) {
+      if (type == 'circle') {
+        this.timmerList.forEach(timmer => {
+          clearInterval(timmer);
+        })
+      } else {
+        this.getFunTimmer.forEach(timmer => {
+          clearInterval(timmer);
+        })
+      }
+    },
+    // 获取组织水波纹信息
+    getGroupDeviceFun() {
+      this.$axios({
+        method: 'POST',
+        url: '/api/api_gateway?method=data_report.screen.device_info',
+        data: this.qs.stringify({})
+      }).then(res => {
+        this.loading = false;
+        if (!res.data.data) {
+          this.$message.error('网络连接出错或服务报错,请刷新页面重试');
+          return
+        }
+        // console.log(res.data.data);
+        // this.deviceInfo = res.data.data.devices_info;
+        this.clearOverlayByType('circle');
+        this.clearOverlayByType('circleMarker');
+        // 先把所有定时器清空
+        this.clerrTimmerFun('circle');
+        this.overlayList = [];
+        res.data.data.forEach(group => {
+          if (group.lng_lat.length == 0) return
+          this.waterAmiFun(group)
+        });
+        this.map.setFitView(this.overlayList)
+      });
+    },
+    // 根据组织ID 获取组织设备告警信息
+    getInfoByGroupId(group_id) {
+      this.$axios({
+        method: 'POST',
+        url: '/api/api_gateway?method=data_report.screen.group_pest_detail',
+        data: this.qs.stringify({ group_id })
+      }).then(res => {
+        console.log(res.data.data);
+        if (!res.data.data) {
+          this.$message.error('网络连接出错或服务报错,请刷新页面重试');
+          return
+        }
+      })
+    },
+    // 画水波纹
+    waterAmiFun(group) {
+      let { colorObject } = this;
+      let _this = this;
+      // 绘制圆
+      var circle = new AMap.Circle({
+        center: group.lng_lat, // 圆心位置
+        radius: 2500, // 半径,单位:米
+        strokeColor: "#FFFFFF", // 线颜色
+        strokeOpacity: .8, // 线透明度
+        strokeWeight: 1, // 线宽
+        fillColor: "#fff", // 填充颜色
+        fillOpacity: 0.2, // 填充透明度
+        zIndex: 100, // 层级
+        extData: group,
+        cursor: 'pointer'
+      });
+      this.map.add(circle);
+      // 水波纹点击查看组织详情
+      circle.on('click', (e) => {
+        let data = e.target._opts.extData;
+        this.getInfoByGroupId(data.org_id);
+        this.groupDialog = true;
+        console.log(data, '当前点击的圆圈是');
+      })
+      this.overlayList.push(circle);
+      // 添加水波纹效果的圆点
+      var rippleCircleMaker = new AMap.CircleMarker({
+        center: group.lng_lat, // 圆心位置
+        radius: 5, // 初始半径,单位:米
+        strokeColor: "#FFf", // 线颜色
+        strokeOpacity: 1, // 线透明度
+        strokeWeight: 1, // 线宽
+        fillColor: colorObject[group.alarm_level], // 填充颜色
+        fillOpacity: 0.9, // 填充透明度
+        zIndex: 102 // 层级
+      });
+      this.map.add(rippleCircleMaker);
+      if (group.alarm_level == 0) return; //等级为0时 不需要水波纹
+      // 添加水波纹效果的圆点
+      var rippleCircle = new AMap.Circle({
+        center: group.lng_lat, // 圆心位置
+        radius: 500, // 初始半径,单位:米
+        strokeColor: colorObject[group.alarm_level], // 线颜色
+        strokeOpacity: 0, // 线透明度
+        strokeWeight: 2, // 线宽
+        fillColor: colorObject[group.alarm_level], // 填充颜色
+        fillOpacity: 0.8, // 填充透明度
+        zIndex: 101, // 层级
+        extData: group,
+        cursor: 'pointer'
+      });
+      // 水波纹点击查看组织详情
+      rippleCircle.on('click', (e) => {
+        let data = e.target._opts.extData;
+        console.log(data, '当前点击的水波纹是');
+        this.getInfoByGroupId(data.org_id);
+      })
+      this.map.add(rippleCircle);
+
+      // 定义水波纹动画
+      var animation;
+
+      // 添加水波纹动画效果
+      function addRippleAnimation() {
+        var startRadius = 500;
+        var startOpacity = 0.8;
+        var endRadius = 2700;
+        var step = 200;
+        var opacityStep = -0.06;
+        var currentRadius = startRadius;
+        var currentOpacity = startOpacity;
+        var increasing = true;
+
+        animation = setInterval(function () {
+          if (increasing) {
+            if (currentRadius < endRadius) {
+              rippleCircle.setRadius(currentRadius); // 设置水波纹半径
+              rippleCircle.setOptions({
+                fillOpacity: currentOpacity > 0 ? currentOpacity : 0
+              });
+              currentRadius += step; // 每次半径增加 step
+              currentOpacity += opacityStep; // 每次透明度增加opacityStep
+            } else {
+              clearInterval(animation); // 清除动画
+              currentRadius = startRadius; // 重置水波纹半径为初始值
+              currentOpacity = startOpacity;
+              addRippleAnimation(); // 重新启动动画
+            }
+          }
+        }, 100); // 设置动画间隔时间,单位:毫秒
+        _this.timmerList.push(animation); // 记录定时器
+        // console.log(_this.timmerList, '_this.timmerList');
+      }
+
+      // 启动水波纹动画
+      // addRippleAnimation();
+    },
     initMap() {
-      var map = new AMap.Map(document.getElementById('newHome'), {
-        // center: this.center,
+      let _this = this;
+      let map = new AMap.Map(document.getElementById('newHome'), {
+        center: [114.3, 22.76],
         resizeEnable: true,
-        zoom: 12.5,
         // lang: 'en',
-        mapStyle: 'amap://styles/f2736173d4246171f1efaa1b61a15439',
-        layers: []
+        zoom: 11,
+        mapStyle: 'amap://styles/fff0c1ac5471818a21cf82c0931f60c0',
+        // mapStyle: "amap://styles/dark",
+        // features: ['bg', 'road'],
       });
-      map.on('complete', function () {
+      this.map = map;
+      this.map.on('complete', function () {
+        _this.getGroupDeviceFun();
+        let getGroupTimmer = setInterval(_this.getGroupDeviceFun, 60000);
+        _this.getFunTimmer.push(getGroupTimmer);
         import(`./geo.json`).then(res => {
-          console.log(res)
           addGeo(res, map)
         });
-        // 绘制圆
-        var circle = new AMap.Circle({
-          center: [114.34347, 23.889983], // 圆心位置
-          radius: 5000, // 半径,单位:米
-          strokeColor: "#FFFFFF", // 线颜色
-          strokeOpacity: 1, // 线透明度
-          strokeWeight: 2, // 线宽
-          fillColor: "#fff", // 填充颜色
-          fillOpacity: 1 // 填充透明度
-        });
-        circle.setMap(map);
-        // 添加水波纹效果的圆点
-        var rippleCircleMaker = new AMap.CircleMarker({
-          center: [114.34347, 23.889983], // 圆心位置
-          radius: 10, // 初始半径,单位:米
-          strokeColor: "#FFf", // 线颜色
-          strokeOpacity: 1, // 线透明度
-          strokeWeight: 10, // 线宽
-          fillColor: "#FF5951", // 填充颜色
-          fillOpacity: 0.9, // 填充透明度
-          zIndex: 10 // 层级
-        });
-        rippleCircleMaker.setMap(map);
-        // 添加水波纹效果的圆点
-        var rippleCircle = new AMap.Circle({
-          center: [114.34347, 23.889983], // 圆心位置
-          radius: 500, // 初始半径,单位:米
-          strokeColor: "#FF5951", // 线颜色
-          strokeOpacity: 0, // 线透明度
-          strokeWeight: 2, // 线宽
-          fillColor: "#FF5951", // 填充颜色
-          fillOpacity: 0.6, // 填充透明度
-          zIndex: 10 // 层级
-        });
-        rippleCircle.setMap(map);
-
-        // 定义水波纹动画
-        var animation;
-
-        // 添加水波纹动画效果
-        function addRippleAnimation() {
-          var startRadius = 500;
-          var startOpacity = 0.8;
-          var endRadius = 5500;
-          var step = 500;
-          var opacityStep = -0.05;
-          var currentRadius = startRadius;
-          var currentOpacity = startOpacity;
-          var increasing = true;
-
-          animation = setInterval(function () {
-            if (increasing) {
-              if (currentRadius < endRadius) {
-                rippleCircle.setRadius(currentRadius); // 设置水波纹半径
-                rippleCircle.setOptions({
-                  fillOpacity: currentOpacity > 0 ? currentOpacity : 0
-                });
-                currentRadius += step; // 每次半径增加 step
-                currentOpacity += opacityStep; // 每次透明度增加opacityStep
-              } else {
-                clearInterval(animation); // 清除动画
-                currentRadius = startRadius; // 重置水波纹半径为初始值
-                currentOpacity = startOpacity;
-                addRippleAnimation(); // 重新启动动画
-              }
-            }
-          }, 100); // 设置动画间隔时间,单位:毫秒
-        }
-
-        // 启动水波纹动画
-        addRippleAnimation();
       });
       function addGeo(Json, map) {
         let cityList = [];
@@ -133,15 +273,15 @@ export default {
               fillOpacity: .3,// 面积越大透明度越高
               strokeColor: '#B5F2FF',
               fillColor: '#64AECE',
-              extData: geojson
+              extData: geojson,
+              zIndex: 90
             });
             cityList.push(PolygonObj);
             return PolygonObj
           }
         })
         map.add(geojson);
-        map.setFitView();
-        console.log(map.getZoom());
+        // map.setFitView();
       }
     },
   },
@@ -155,15 +295,45 @@ export default {
 .box {
   position: relative;
   overflow: hidden;
-  width: 100vw;
+  width: 100%;
   height: 100vh;
 
   .mapBox {
     position: absolute;
     top: 0;
     left: 0;
-    width: 100vw;
+    width: 100%;
     height: 100vh;
   }
+  .dialog{
+    position: absolute;
+    top: 12.72vh; /* 初始位置在视图上方外面 */
+    left: 31.1vw;
+    z-index: 200;
+    width: 37.8vw;
+    height: 21.2vh;
+    background: url('../../../assets/images/newHome/centerTopBg.png') center center no-repeat;
+    background-size: 100% 100%;
+    &_content{
+      position: relative;
+      width: 100%;
+      height: 100%;
+    }
+    &_close{
+      position: absolute;
+      right: 2rem;
+      top: 2rem;
+      z-index: 201;
+      width: 4.8rem;
+      height: 4.8rem;
+      cursor: pointer;
+      background: url('../../../assets/images/newHome/close.png') center center no-repeat;
+      background-size: 100% 100%;
+      &:hover{
+        background: url('../../../assets/images/newHome/closeHover.png') center center no-repeat;
+        background-size: 100% 100%;
+      }
+    }
+  }
 }
 </style>

+ 5 - 0
minggao/src/page/recordForm/harmfulRecord.vue

@@ -244,6 +244,11 @@ export default {
         data: datas
       }).then(res => {
         console.log(res);
+        if (res.data.data) {
+          this.$message.success('操作成功');
+          this.getDataList();
+          this.exportDialog = false;
+        }
         // this.downloadFile(res, 'allot_result.xls');
       });
     },

+ 38 - 26
minggao/src/page/warning/warninglist.vue

@@ -11,11 +11,12 @@
             <el-option v-for="typeItem in lavalList" :label="typeItem.label" :value="typeItem.value"
               :key="typeItem.value"></el-option>
           </el-select>
-          <el-date-picker v-model="queryInfo.time_range" type="monthrange" start-placeholder="开始日期"
+          <el-date-picker v-model="queryInfo.time_range" type="daterange" start-placeholder="开始日期"
             end-placeholder="结束日期" @change="search" size="mini" :editable="false" value-format="timestamp">
           </el-date-picker>
+          <el-tag type="danger" size="small">预警次数:{{ total }}</el-tag>
           <el-button type="primary" @click="search" size="mini">查询</el-button>
-          <el-button type="primary" @click="addDialog=true" size="mini">发布告警</el-button>
+          <el-button type="primary" @click="addDialog = true;pestInfoList = []" size="mini">发布告警</el-button>
         </el-col>
       </el-row>
     </div>
@@ -27,32 +28,17 @@
               <span>{{ (queryInfo.page - 1) * 20 + (scope.$index + 1) }}</span>
             </template>
           </el-table-column>
-          <el-table-column prop="group" label="组织" width="120" show-overflow-tooltip></el-table-column>
-          <el-table-column prop="alarm_level" label="分类" show-overflow-tooltip>
+          <el-table-column prop="group" label="组织" show-overflow-tooltip></el-table-column>
+          <el-table-column prop="content_alias" label="预警内容" show-overflow-tooltip>
           </el-table-column>
-          <el-table-column prop="name" label="有害生物名称" show-overflow-tooltip>
+          <el-table-column prop="addtime_format" width="120" label="预警时间" show-overflow-tooltip>
           </el-table-column>
-          <el-table-column prop="num" label="数量" show-overflow-tooltip width="80">
-          </el-table-column>
-          <el-table-column prop="occurs" label="是否检疫性" width="140" align="center" show-overflow-tooltip>
-            <template slot-scope="scope">
-              {{ scope.row.is_quarantine ? '是' : '否' }}
-            </template>
-          </el-table-column>
-          <el-table-column prop="occurs" label="是否外来物种" width="140" align="center" show-overflow-tooltip>
-            <template slot-scope="scope">
-              {{ scope.row.is_export ? '是' : '否' }}
-            </template>
-          </el-table-column>
-          <el-table-column prop="occurs" label="是否新物种" width="140" align="center" show-overflow-tooltip>
-            <template slot-scope="scope">
-              {{ scope.row.is_new ? '是' : '否' }}
-            </template>
-          </el-table-column>
-          <el-table-column prop="addtime_format" label="发现时间" show-overflow-tooltip>
+          <el-table-column prop="deal_time_format" width="180" label="处理时间" show-overflow-tooltip>
           </el-table-column>
           <el-table-column label="操作" width="150" align="center" fixed="right">
             <template slot-scope="scope">
+              <el-button size="mini" type="text" v-if="scope.row.is_deal" @click="dealFun(scope.row.id)">待处理</el-button>
+              <div style="font-size: 12px;" v-else>已处理</div>
               <!-- <a class="reset" href="javascript:;" @click="handleEdit(scope.row)">编辑</a>
               <i class="line"></i>
               <a class="delete" href="javascript:;" @click="deleteData(scope.row.id)">删除</a> -->
@@ -164,7 +150,7 @@ export default {
       },
       pestLibrary:[], //害虫列表
       organizationList: [], // 组织列表
-      addDialog: true,
+      addDialog: false,
       baseForm: {
         category: '', // 类别
         group: '', // 组织,
@@ -213,6 +199,30 @@ export default {
 
   },
   methods: {
+    // 处理告警
+    dealFun(id) {
+      this.$confirm('处理后状态不可变更, 是否继续?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      })
+        .then(() => {
+          this.$axios({
+            method: 'POST',
+            url: '/api/api_gateway?method=data_report.alerm.alerm_deal',
+            data: this.qs.stringify({
+              id
+            })
+          }).then(res => {
+            if (res.data.data == true) {
+              this.$message.success('操作成功');
+              this.getDataList()
+            } else {
+              this.$message.error(res.data.message)
+            }
+          })
+        })
+    },
     // 新增害虫预警
     addPestFun() {
       this.pestInfoList.push({
@@ -280,10 +290,11 @@ export default {
         if (valid) {
           this.dialogSubmitLoading = true;
             // 添加
-            const payload = omit(this.baseForm, []);
+          const payload = omit(this.baseForm, []);
+          payload.group = payload.group.join(',');
             this.$axios({
               method: 'POST',
-              url: '/api/api_gateway?method=data_report.alerm.change_pest',
+              url: '/api/api_gateway?method=data_report.alerm.add_alerm',
               data: this.qs.stringify(payload)
             })
               .then(res => {
@@ -293,6 +304,7 @@ export default {
                   duration: 1500
                 });
                 this.resetForm(formName);
+                this.pestInfoList = [];
                 this.search();
               })
               .finally(() => {

Різницю між файлами не показано, бо вона завелика
+ 571 - 53
minggao/yarn.lock