소스 검색

Merge remote-tracking branch 'origin/dev' into dev

zhangyihao 6 달 전
부모
커밋
4018c6557f

+ 90 - 70
src/components/Map/YztMap/index.vue

@@ -1,23 +1,37 @@
 <template>
   <div ref="containerRef" class="map-container">
     <div ref="mapRef" id="YztMap" class="map-container" :style="{ width: width, height: height }"></div>
+    <!-- 右下工具  -->
+    <div v-show="mapState.showScale" class="zoom-text">{{ mapState.zoom }}级</div>
+    <div class="right-tool">
+      <!-- 快捷缩放 -->
+      <QuickZoom v-model:zoom="mapState.zoom" @change-step="setMapZoom" />
+      <div class="flex" style="margin-top: 5px; justify-content: center">
+        <div class="mask-btn" @click="handleShowMask">{{ showMask ? '显' : '隐' }}</div>
+<!--        <div class="model-btn" @click="switchThreeDimensional">{{ mapState.isThreeDimensional ? '3D' : '2D' }}</div>-->
+        <div class="ruler-icon" style="margin-left: 5px" @click="changeScaleControl"></div>
+      </div>
+    </div>
   </div>
 </template>
 
 <script setup lang="ts">
 import 'ol/ol.css';
-import mmJson from '@/assets/json/mm.json'
+import ScaleLine from 'ol/control/ScaleLine';
+import mmJson from '@/assets/json/mm.json';
 import { olMap } from '@/utils/olMap/olMap';
 import { PointType } from '@/api/globalMap/type';
+import QuickZoom from '@/components/Map/quickZoom.vue';
 
 interface Props {
   activeMap: string;
   // 获取需要查询点的类型
   pointType?: PointType[];
+  showMask: boolean;
 }
 const containerScale = inject('containerScale');
 const props = withDefaults(defineProps<Props>(), {});
-const emits = defineEmits(['update:drawing', 'selectGraphics']);
+const emits = defineEmits(['update:drawing', 'update:showMask', 'selectGraphics']);
 
 const mapRef = ref(null);
 const mapState = reactive({
@@ -57,10 +71,19 @@ watch(
   () => {
     if (!map) return;
     map.replaceLayers(mapList[props.activeMap]);
-    map.createVecByJson(mmJson, '茂名市');
   }
 );
-
+watch(
+  () => props.showMask,
+  () => {
+    if (props.showMask) {
+      map.createVecByJson(mmJson, '茂名市');
+    } else {
+      map.removeMask();
+    }
+  }
+);
+let scaleLine;
 const init = () => {
   map = new olMap({
     dom: mapRef.value,
@@ -90,7 +113,14 @@ const init = () => {
     onLoadCompleted: (yMap) => {
       yztMap = yMap;
       // initMouseTool(map);
-      map.createVecByJson(mmJson, '茂名市');
+      scaleLine = new ScaleLine();
+      yztMap.addControl(scaleLine);
+      yztMap.getView().on('change:resolution', () => {
+        mapState.zoom = yztMap.getView().getZoom().toFixed(2);
+      });
+      if (props.showMask) {
+        yztMap.createVecByJson(mmJson, '茂名市');
+      }
       handleResize();
     }
   });
@@ -101,33 +131,43 @@ const addMarker = (points) => {
 // 设置地图层级
 const setMapZoom = (value) => {
   if (!yztMap) return;
-  const view = yztMap.map.getView();
+  const view = yztMap.getView();
   if (value === 1) {
-    view.setCenter([113.280637, 23.125178]);
-    view.setZoom(7);
-  } else if (value === 2) {
     view.setCenter([110.925175, 21.678955]);
-    view.setZoom(11);
+    view.setZoom(7.9);
+  } else if (value === 2) {
+    view.setCenter([110.925175, 21.6789558]);
+    view.setZoom(9.21);
   } else if (value === 3) {
     view.setCenter([110.925175, 21.678955]);
-    view.setZoom(12);
+    view.setZoom(11.38);
   } else if (value === 4) {
     view.setCenter([110.925175, 21.678955]);
-    view.setZoom(15);
-  } else if (value === 5) {
-    view.setCenter([110.925175, 21.678955]);
-    view.setZoom(16);
+    view.setZoom(12.83);
   }
 };
 // 切换2D、3D
 const switchThreeDimensional = () => {
-  const view = yztMap.map.getView();
+  const view = yztMap.getView();
   mapState.isThreeDimensional = !mapState.isThreeDimensional;
   const pitch = mapState.isThreeDimensional ? 45 : 0;
   view.setPitch(pitch);
 };
+
+// 切换比例尺
+const changeScaleControl = () => {
+  mapState.showScale = !mapState.showScale;
+  if (mapState.showScale) {
+    yztMap.addControl(scaleLine);
+  } else {
+    yztMap.removeControl(scaleLine);
+  }
+};
 const clearMarker = () => {
-  this.map.clearMarker();
+  map.clearMarker();
+};
+const handleShowMask = () => {
+  emits('update:showMask', !props.showMask);
 };
 defineExpose({ addMarker, clearMarker });
 const handleResize = () => {
@@ -155,8 +195,9 @@ onUnmounted(() => {
   position: relative;
   .zoom-text {
     position: absolute;
-    bottom: 8px;
-    right: 75px;
+    bottom: 52px;
+    right: 80px;
+    color: #eaf3fc;
     font-size: 14px;
   }
   .right-tool {
@@ -164,66 +205,45 @@ onUnmounted(() => {
     bottom: 50px;
     right: 5px;
   }
-  .model-btn {
-    background-color: #022577;
-    font-size: 14px;
-    color: #889ee9;
+  .mask-btn {
+    background-color: #04327c;
+    font-size: 12px;
+    border: 1px solid #91cfff;
+    color: #eaf3fc;
     cursor: pointer;
     padding: 3px 3px;
     border-radius: 5px;
+    //margin-right: 5px;
+    cursor: pointer;
   }
-  :deep(.amap-scalecontrol) {
-    left: unset !important;
-    background-color: unset !important;
-    right: 74px;
-  }
-  :deep(.amap-scale-text) {
-    width: 230px !important;
-    text-align: left !important;
-    font-size: 14px;
-    padding-left: 20px;
-  }
-  :deep(.amap-scale-middle) {
-    width: 228px !important;
-  }
-  :deep(.amap-scale-edgeright) {
-    left: 228px !important;
-  }
-  :deep(.amap-logo),
-  :deep(.amap-copyright) {
-    display: none !important;
-  }
-  /* 自定义测距工具样式 */
-  :deep(.amap-ranger) {
-    background-color: #ffffff;
-    border: 1px solid #888888;
-    border-radius: 5px;
-    padding: 5px;
-  }
-
-  :deep(.amap-ranger .amap-toolbar) {
-    color: #333;
+  .model-btn {
+    background-color: #04327c;
     font-size: 12px;
-    padding: 5px;
+    font-family: 'SourceHanSansCN';
+    border: 1px solid #91cfff;
+    color: #eaf3fc;
+    cursor: pointer;
+    padding: 3px 3px;
+    border-radius: 5px;
+    cursor: pointer;
   }
-
-  :deep(.amap-ranger .amap-toolbar button) {
-    background-color: #022577;
-    color: #fff;
-    border: none;
-    border-radius: 4px;
-    padding: 5px;
-    margin-right: 5px;
+  .ruler-icon {
+    width: 14px;
+    height: 14px;
+    background: url('@/assets/images/map/ruler.png') no-repeat;
+    background-size: 100% 100%;
     cursor: pointer;
   }
-
-  :deep(.amap-ranger .amap-toolbar button:hover) {
-    background-color: #1a3c75;
+  :deep(.ol-scale-line) {
+    left: unset;
+    bottom: 51px;
+    right: 62px;
+    background-color: transparent;
   }
-
-  :deep(.amap-ranger .amap-toolbar .amap-toolbar-text) {
-    color: #444;
-    font-size: 14px;
+  :deep(.ol-scale-line-inner) {
+    color: #ffffff;
+    border: 1px solid #fff;
+    border-top: none;
   }
 }
 </style>

+ 40 - 7
src/components/Map/index.vue

@@ -7,6 +7,7 @@
       <!-- 快捷缩放 -->
       <QuickZoom v-model:zoom="mapState.zoom" @change-step="setMapZoom" />
       <div class="flex" style="margin-top: 5px">
+        <div class="mask-btn" @click="handleShowMask">{{ showMask ? '显' : '隐' }}</div>
         <div class="model-btn" @click="switchThreeDimensional">{{ mapState.isThreeDimensional ? '3D' : '2D' }}</div>
         <div class="ruler-icon" style="margin-left: 5px" @click="changeScaleControl"></div>
       </div>
@@ -16,6 +17,7 @@
 
 <script setup lang="ts" name="Map">
 import QuickZoom from './quickZoom.vue';
+import ScaleLine from 'ol/control/ScaleLine';
 import { useAMap } from '@/hooks/AMap/useAMap';
 import { useDrawTool } from '@/hooks/AMap/useDrawTool';
 import { getPointInfoList } from '@/api/globalMap';
@@ -44,10 +46,13 @@ import {
   getMiningOperationsDetails,
   getEmergencyTransportResourcesDetails,
   getEmergencyDisasterInfoOfficerDetails,
-  getMidmapDzzhDetails, getVehicleDetails, getVideoDrowning, getVideoForestFire, getVideoDisasterPrevention
+  getMidmapDzzhDetails,
+  getVehicleDetails,
+  getVideoDrowning,
+  getVideoForestFire,
+  getVideoDisasterPrevention
 } from '@/api/globalMap/spatialAnalysis';
 import { pointDetailTemplate } from '@/views/globalMap/data/mapData';
-import ElementResizeDetectorMaker from 'element-resize-detector';
 import useAppStore from '@/store/modules/app';
 import { getWaterList } from '@/api/globalMap/reservoir';
 import { getRescueTeamsInfo } from '@/api/globalMap/rescueTeam';
@@ -55,6 +60,7 @@ import { getRescueTeamsInfo } from '@/api/globalMap/rescueTeam';
 interface Props {
   activeMap: string;
   pointType: PointType[];
+  showMask: boolean;
 }
 
 const containerScale = inject('containerScale');
@@ -65,6 +71,7 @@ const appStore = useAppStore();
 
 const emits = defineEmits([
   'update:drawing',
+  'update:showMask',
   'selectGraphics',
   'unSelectGraphics',
   'showTextEditBox',
@@ -114,9 +121,9 @@ const mapUtils = useAMap({
     }
     map.on('zoomchange', zoomChangeHandler);
     // 添加遮罩
-    // , { strokeColor: '#ff0000',strokeWeight: 2, offset }
-    //   { strokeColor: '#2a8797', strokeOpacity: 0.6,strokeWeight: 6, fillOpacity: 0},
-    creatMask([{ strokeWeight: 2 }]);
+    if (props.showMask) {
+      creatMask([{ strokeWeight: 2 }]);
+    }
     drawTool.initMouseTool({ container: 'aMap', map, AMap });
     placeSearch = new AMap.PlaceSearch({
       pageSize: 30,
@@ -192,6 +199,7 @@ const {
   hideInfo,
   handleHover,
   creatMask,
+  removeMask,
   trackPlayback
 } = { ...mapUtils };
 const handlePointDetails = (data) => {
@@ -404,6 +412,16 @@ watch(
     switchMap(props.activeMap);
   }
 );
+watch(
+  () => props.showMask,
+  () => {
+    if (props.showMask) {
+      creatMask([{ strokeWeight: 2 }]);
+    } else {
+      removeMask();
+    }
+  }
+);
 // watch(
 //   () => props.mouseToolState,
 //   () => {
@@ -426,9 +444,9 @@ const zoomChangeHandler = () => {
 const changeScaleControl = () => {
   mapState.showScale = !mapState.showScale;
   if (mapState.showScale) {
-    map.addControl(scale);
+    map.addControl(new ScaleLine());
   } else {
-    map.removeControl(scale);
+    map.removeControl(new ScaleLine());
   }
 };
 
@@ -467,6 +485,9 @@ const getMapUtils = () => {
 const getPlaceSearch = () => {
   return placeSearch;
 };
+const handleShowMask = () => {
+  emits('update:showMask', !props.showMask);
+};
 defineExpose({ addMarker, addSearchMarker, setCenter, getMarkers, clearMarker, getMap, drawTool, handleHover, trackPlayback, getMapUtils, getPlaceSearch });
 const handleResize = () => {
   const containerWidth = !!containerScale ? containerRef.value.clientWidth * containerScale().scaleX : 1;
@@ -527,6 +548,17 @@ onUnmounted(() => {
     right: 0px;
     z-index: 2;
   }
+  .mask-btn {
+    background-color: #04327c;
+    font-size: 12px;
+    border: 1px solid #91cfff;
+    color: #eaf3fc;
+    cursor: pointer;
+    padding: 3px 3px;
+    border-radius: 5px;
+    margin-right: 5px;
+    cursor: pointer;
+  }
   .model-btn {
     background-color: #04327c;
     font-size: 12px;
@@ -536,6 +568,7 @@ onUnmounted(() => {
     cursor: pointer;
     padding: 3px 3px;
     border-radius: 5px;
+    cursor: pointer;
   }
   .ruler-icon {
     width: 14px;

+ 11 - 5
src/hooks/AMap/useAMap.ts

@@ -232,7 +232,7 @@ export function useAMap(options) {
       }
     }
   };
-
+  let maskPolygon;
   const creatMask = (options, name = '茂名市') => {
     new AMap.DistrictSearch({
       extensions: 'all',
@@ -255,7 +255,7 @@ export function useAMap(options) {
         // }
         let pathArray = [outer];
         pathArray.push.apply(pathArray, holes);
-        const polygon = new AMap.Polygon({
+        maskPolygon = new AMap.Polygon({
           pathL: pathArray,
           strokeColor: option.strokeColor ? option.strokeColor : '#268ab9',
           strokeOpacity: option.strokeOpacity ? option.strokeOpacity : 1,
@@ -263,12 +263,17 @@ export function useAMap(options) {
           fillColor: option.fillColor ? option.fillColor : '#10243b',
           fillOpacity: option.fillOpacity ? option.fillOpacity : 0.65
         });
-        polygon.setPath(pathArray);
-        map.add(polygon);
+        maskPolygon.setPath(pathArray);
+        map.add(maskPolygon);
       });
     });
   };
-
+  const removeMask = () => {
+    if (!!maskPolygon) {
+      map.remove(maskPolygon);
+      maskPolygon = null;
+    }
+  };
   let moveMarker, movePolyline, movePassedPolyline, timerId;
   const trackPlayback = (lineArr) => {
     if (timerId) {
@@ -467,6 +472,7 @@ export function useAMap(options) {
     hideInfo,
     handleHover,
     creatMask,
+    removeMask,
     trackPlayback,
     drawData
   };

+ 8 - 67
src/utils/olMap/olMap.ts

@@ -291,7 +291,8 @@ export class olMap {
   createVecByJson(json, layerName = '') {
     const format = new GeoJSON();
     const fs = format.readFeatures(json);
-    const converLayer = new VectorLayer({
+    this.removeMask();
+    this.maskLayer = new VectorLayer({
       source: new VectorSource(),
       style: new Style({
         fill: new Fill({
@@ -304,7 +305,7 @@ export class olMap {
       }),
       zIndex: 99
     });
-    this.map.addLayer(converLayer);
+    this.map.addLayer(this.maskLayer);
     const extent = [-180, -90, 180, 90];
     const polygonRing = fromExtent(extent);
     fs.forEach((x) => {
@@ -318,73 +319,13 @@ export class olMap {
     const convertFt = new Feature({
       geometry: polygonRing
     });
-    converLayer.getSource().addFeature(convertFt);
+    this.maskLayer.getSource().addFeature(convertFt);
   }
 
-  /**
-   * @description 创建矢量图层
-   * @param {String} layerName 图层名称
-   * @param {Number} zIndex 地图层级默认是0
-   * @returns
-   */
-  createVecLayer(layerName = '', zIndex = 0) {
-    const source = new SourceVector({
-      crossOrigin: 'anonymous'
-    });
-    const layer = new Vector({
-      source,
-      zIndex
-    });
-    layer.set('layerName', layerName);
-    return layer;
-  }
-  // 分布图遮罩层
-  createMask(data) {
-    this.removeMask();
-    if (!data || data.length === 0) return;
-    data.forEach((item) => {
-      if (!item.points || item.points.length === 0) return;
-      // 遮罩图层的样式
-      const maskStyle = new Style({
-        fill: new Fill({
-          color: item.color // 红色遮罩,50%透明度
-        }),
-        stroke: new Stroke({
-          color: 'rgba(159,159,159,0.7)',
-          width: 1
-        })
-      });
-
-      // 遮罩图层的矢量数据源(初始为空)
-      const maskSource = new VectorSource();
-      // 创建一个多边形特征
-      const polygonFeature = new Feature({
-        geometry: new Polygon(item.points)
-      });
-      const maskLayer = new VectorLayer({
-        source: maskSource,
-        style: maskStyle,
-        properties: {
-          name: 'mask'
-        }
-      });
-      this.map.addLayer(maskLayer);
-      // 将多边形特征添加到遮罩数据源中
-      maskSource.addFeature(polygonFeature);
-    });
-  }
   removeMask() {
-    //移除图层
-    const layersArray = this.map.getLayers().getArray();
-    const layers = [];
-    layersArray.forEach((layer) => {
-      // 检查图层是否有自定义属性,并且该属性是否匹配你要移除的图层的标识符
-      if (layer.get('name') === 'mask') {
-        layers.push(layer);
-      }
-    });
-    layers.forEach((layer) => {
-      this.map.removeLayer(layer);
-    });
+    if (this.maskLayer) {
+      this.map.removeLayer(this.maskLayer);
+      this.maskLayer = null;
+    }
   }
 }

+ 12 - 16
src/views/dataManagement/index.vue

@@ -5,28 +5,24 @@
       <transition name="fade">
         <div v-show="showSearch" class="mb-[10px]">
           <el-form ref="queryFormRef" :model="queryParams" :inline="true">
-            <el-row gutter="{20}">
-              <el-col :span="5">
-                <el-form-item style="width: 2000px" label="选择数据:" prop="planType" label-width="auto">
-                  <el-select v-model="queryParams.data" placeholder="选择数据">
-                    <el-option v-for="item in type" :key="item.value" :label="item.label" :value="item.value"></el-option>
-                  </el-select>
-                </el-form-item>
-              </el-col>
-              <el-col :span="12" class="info-col">
-                <div class="info">
+            <el-form-item style="width: 2000px" label="选择数据:" prop="planType" label-width="auto">
+              <div class="flex" style="align-items: center; justify-content: flex-start;">
+                <el-select v-model="queryParams.search" placeholder="选择数据">
+                  <el-option v-for="item in type" :key="item.value" :label="item.label" :value="item.value"></el-option>
+                </el-select>
+                <div class="info" style="margin-left: 20px">
                   <span>数据更新:{{ dataUpdateTime }}</span>
                   <span class="spacer">数源单位:{{ dataSourceUnit }}</span>
                 </div>
-              </el-col>
-            </el-row>
+              </div>
+            </el-form-item>
           </el-form>
         </div>
       </transition>
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" @click="handleAdd">录入</el-button>
+        <el-button type="primary" @click="handleAdd">录入</el-button>
         <input ref="excelFileInput" type="file" style="display: none" accept=".xlsx, .xls" @change="handleExcelUpload" />
-        <el-button class="spacer" type="primary" icon="el-icon-upload2" @click="triggerExcelUpload">批量导入</el-button>
+        <el-button class="spacer" type="primary" @click="triggerExcelUpload">批量导入</el-button>
       </el-form-item>
     </div>
     <el-table :data="tableData" style="width: 100%">
@@ -41,7 +37,7 @@
       <el-table-column prop="plannedArea" label="应建人防地下室面积(㎡)"></el-table-column>
       <el-table-column prop="actualArea" label="实建人防地下室面积(㎡)"></el-table-column>
       <el-table-column prop="updateTime" label="更新时间"></el-table-column>
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+      <el-table-column label="操作" align="center" width="150px" class-name="small-padding fixed-width">
         <template #default="scope">
           <el-text v-hasPermi="['system:menu:View']" class="common-btn-text-primary" @click="handleView(scope.row)">查看</el-text>
           <el-text v-hasPermi="['system:menu:edit']" class="common-btn-text-primary" @click="handleUpdate(scope.row)">修改</el-text>
@@ -235,6 +231,6 @@ const handlePageChange = (page) => {
 }
 
 .spacer {
-  margin-left: 50px;
+  margin-left: 15px;
 }
 </style>

+ 51 - 100
src/views/globalMap/RightMenu/CommunicationSupport.vue

@@ -2,21 +2,21 @@
   <Dialog custom-show type="lg" title="通讯保障" height="650px" hide-footer @close="handleClose">
     <div class="content">
       <div class="left-content">
-        <el-input v-model="queryParams.keyword" class="custom-input" placeholder="组织架构搜索">
+        <el-input v-model="queryParams1.keyword" class="custom-input" placeholder="组织架构搜索">
           <template #prefix>
             <el-icon class="el-input__icon"><search /></el-icon>
           </template>
         </el-input>
         <div class="tree-container">
           <div class="tree-box">
-            <el-tree :data="treeData" accordion @node-click="handleNodeClick" />
+            <el-tree :data="treeData" :props="{ value: 'deptId', label: 'deptName', children: 'children' }" accordion @node-click="handleNodeClick" />
           </div>
         </div>
       </div>
       <div class="middle-content">
         <div class="search-box">
           <el-select
-            v-model="queryParams.value1"
+            v-model="queryParams1.value1"
             class="custom-select select-box"
             placeholder="全部"
             popper-class="custom-select-popper"
@@ -24,7 +24,7 @@
           >
             <el-option v-for="level in options" :key="level.value" :label="level.name" :value="level.value"></el-option>
           </el-select>
-          <el-input v-model="queryParams.keyword" class="custom-input" placeholder="组织架构搜索">
+          <el-input v-model="queryParams1.keyword" class="custom-input" placeholder="组织架构搜索">
             <template #prefix>
               <el-icon class="el-input__icon"><search /></el-icon>
             </template>
@@ -44,9 +44,9 @@
                 <div class="td2">
                   <div :class="item.checked ? 'common-checked-active' : 'common-checked'" @click="handleChecked2(item)"></div>
                 </div>
-                <div class="td">{{ item.name }}</div>
+                <div class="td">{{ item.nickName }}</div>
                 <div class="td3">
-                  {{ item.duty }}
+                  {{ item.deptName }}
                   <div class="phone-icon"></div>
                 </div>
               </div>
@@ -66,11 +66,11 @@
         <div class="select-content">
           <div v-for="(item, index) in selectList" :key="index" class="box-item">
             <div class="line">
-              <div class="text1">{{ item.name }}</div>
+              <div class="text1">{{ item.nickName }}</div>
               <div class="text2">{{ item.duty }}</div>
             </div>
             <div class="line" style="margin-top: 20px">
-              <div class="text2">{{ item.dept }}</div>
+              <div class="text2">{{ item.deptName }}</div>
             </div>
             <div class="close-btn" @click="deleteItem(item)"></div>
           </div>
@@ -82,56 +82,26 @@
 
 <script lang="ts" setup>
 import { Search } from '@element-plus/icons-vue';
+import { listDept } from '@/api/system/dept';
+import { DeptVO } from '@/api/system/dept/types';
+import { listUser } from '@/api/system/user';
 
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const emits = defineEmits(['close']);
-let activeIndex = ref(0);
 const options = ref([{ name: '全部', value: '全部' }]);
-const queryParams = ref({
-  value1: '',
-  keyword: ''
+let queryParams1 = ref({
+  pageNum: 1,
+  pageSize: 10,
+  deptName: undefined,
+  deptCategory: undefined,
+  status: undefined
 });
-const menu = ref([{ name: '视频会商' }, { name: '无人机' }, { name: '单兵设备' }]);
-const treeData = ref([
-  {
-    label: '茂名市',
-    children: [
-      {
-        label: '茂名市委',
-        children: [
-          {
-            label: '茂名市纪委监委',
-            isLeaf: true
-          },
-          {
-            label: '茂名市委办公室',
-            isLeaf: true
-          },
-          {
-            label: '茂名市委组织部',
-            isLeaf: true
-          }
-        ]
-      },
-      {
-        label: '茂名市人大',
-        children: [
-          {
-            label: '茂名市人大常委会秘书长、副秘书长',
-            isLeaf: true
-          },
-          {
-            label: '茂名市人大常委会办公室',
-            isLeaf: true
-          },
-          {
-            label: '茂名市人大常委会研究室',
-            isLeaf: true
-          }
-        ]
-      }
-    ]
-  }
-]);
+let queryParams2 = ref({
+  pageNum: 1,
+  pageSize: 100,
+  deptId: ''
+});
+const treeData = ref([]);
 const userList = ref([]);
 const selectList = computed(() => {
   const data = [];
@@ -153,51 +123,23 @@ const getCheckedClass = () => {
   }
   return res;
 };
-const handleNodeClick = (item) => {
-  if (item.isLeaf) {
-    const data = [
-      {
-        id: 1,
-        name: '李莉莉',
-        duty: '副主任',
-        dept: '茂名市/茂名市政府/茂名应急管理局'
-      },
-      {
-        id: 2,
-        name: '何里',
-        duty: '副主任',
-        dept: '茂名市/茂名市政府/茂名应急管理局'
-      },
-      {
-        id: 3,
-        name: '张三',
-        duty: '副主任',
-        dept: '茂名市/茂名市政府/茂名应急管理局'
-      },
-      {
-        id: 4,
-        name: '张三',
-        duty: '副主任',
-        dept: '茂名市/茂名市政府/茂名应急管理局'
-      },
-      {
-        id: 5,
-        name: '张三',
-        duty: '副主任',
-        dept: '茂名市/茂名市政府/茂名应急管理局'
-      },
-      {
-        id: 6,
-        name: '张三',
-        duty: '副主任',
-        dept: '茂名市/茂名市政府/茂名应急管理局'
-      }
-    ];
+const handleNodeClick = (data) => {
+  queryParams2.value.deptId = data.deptId;
+  getPerson();
+};
+const getPerson = () => {
+  listUser(queryParams2.value).then((res) => {
+    const data = res.rows;
     data.forEach((item) => {
-      item.checked = false;
+      for (let i = 0; i < selectList.value.length; i++) {
+        if (selectList.value[i].nickName === item.nickName) {
+          item.checked = true;
+          break;
+        }
+      }
     });
     userList.value = data;
-  }
+  });
 };
 // 全选、全取消
 const handleChecked = () => {
@@ -225,7 +167,7 @@ const clearSelect = () => {
 // 清空指定项
 const deleteItem = (item) => {
   for (let i = 0; i < userList.value.length; i++) {
-    if (item.id === userList.value[i].id) {
+    if (item.deptId === userList.value[i].deptId) {
       userList.value[i].checked = false;
       break;
     }
@@ -236,6 +178,15 @@ const deleteItem = (item) => {
 const handleClose = () => {
   emits('close');
 };
+const initData = () => {
+  listDept(queryParams1.value).then((res: any) => {
+    const data = proxy?.handleTree<DeptVO>(res.data, 'deptId');
+    treeData.value = data;
+  });
+};
+onMounted(() => {
+  initData();
+});
 </script>
 
 <style lang="scss" scoped>
@@ -418,10 +369,10 @@ const handleClose = () => {
         .close-btn {
           position: absolute;
           right: 10px;
-          top: 50px;
+          top: 20px;
           cursor: pointer;
-          width: 9px;
-          height: 9px;
+          width: 18px;
+          height: 18px;
           background: url('@/assets/images/emergencyCommandMap/communication/close.png') no-repeat;
           background-size: 100% 100%;
         }

+ 3 - 0
src/views/globalMap/index.vue

@@ -7,12 +7,14 @@
         ref="map2Ref"
         :active-map="activeMap"
         :point-type="pointType"
+        v-model:showMask="showMask"
       />
       <Map
         v-else
         ref="mapRef"
         :active-map="activeMap"
         :point-type="pointType"
+        v-model:showMask="showMask"
         @handle-show-video="handleShowVideo"
         @handle-show-warehouse="handleShowWarehouse"
         @handleShowPeople="handleShowPeople"
@@ -64,6 +66,7 @@ let map;
 let mapRef = ref(null);
 let map2Ref = ref(null);
 let leftMenuRef = ref(null);
+let showMask = ref(false);
 //  vectorgraph satellite imageMap 废弃:logical satellite2 satellite3
 let activeMap = ref('satellite');
 // 附近视频菜单数据

+ 38 - 0
src/views/system/role/index.vue

@@ -144,6 +144,44 @@
         </div>
       </div>
     </div>
+    <!-- 分配角色数据权限对话框 -->
+    <el-dialog v-model="openDataScope" :title="dialog.title" width="500px" append-to-body>
+      <el-form ref="dataScopeRef" :model="form" label-width="80px">
+        <el-form-item label="角色名称:">
+          <el-input v-model="form.roleName" :disabled="true" />
+        </el-form-item>
+        <el-form-item label="权限字符:">
+          <el-input v-model="form.roleKey" :disabled="true" />
+        </el-form-item>
+        <el-form-item label="权限范围:">
+          <el-select v-model="form.dataScope" @change="dataScopeSelectChange">
+            <el-option v-for="item in dataScopeOptions" :key="item.value" :label="item.label" :value="item.value"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item v-show="form.dataScope === '2'" label="数据权限:">
+          <el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox>
+          <el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">全选/全不选</el-checkbox>
+          <el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')">父子联动</el-checkbox>
+          <el-tree
+            ref="deptRef"
+            class="tree-border"
+            :data="deptOptions"
+            show-checkbox
+            default-expand-all
+            node-key="id"
+            :check-strictly="!form.deptCheckStrictly"
+            empty-text="加载中,请稍候"
+            :props="{ label: 'label', children: 'children' }"
+          ></el-tree>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitDataScope">确 定</el-button>
+          <el-button @click="cancelDataScope">取 消</el-button>
+        </div>
+      </template>
+    </el-dialog>
   </div>
 </template>
 

+ 11 - 14
src/views/system/user/profile/index.vue

@@ -14,27 +14,27 @@
             </div>
             <ul class="list-group list-group-striped">
               <li class="list-group-item">
-                <svg-icon icon-class="user" />用户名称
+                <svg-icon icon-class="user" />用户名称
                 <div class="pull-right">{{ state.user.userName }}</div>
               </li>
               <li class="list-group-item">
-                <svg-icon icon-class="phone" />手机号码
+                <svg-icon icon-class="phone" />手机号码
                 <div class="pull-right">{{ state.user.phonenumber }}</div>
               </li>
               <li class="list-group-item">
-                <svg-icon icon-class="email" />用户邮箱
+                <svg-icon icon-class="email" />用户邮箱
                 <div class="pull-right">{{ state.user.email }}</div>
               </li>
               <li class="list-group-item">
-                <svg-icon icon-class="tree" />所属部门
+                <svg-icon icon-class="tree" />所属部门
                 <div v-if="state.user.deptName" class="pull-right">{{ state.user.deptName }} / {{ state.postGroup }}</div>
               </li>
               <li class="list-group-item">
-                <svg-icon icon-class="peoples" />所属角色
+                <svg-icon icon-class="peoples" />所属角色
                 <div class="pull-right">{{ state.roleGroup }}</div>
               </li>
               <li class="list-group-item">
-                <svg-icon icon-class="date" />创建日期
+                <svg-icon icon-class="date" />创建日期
                 <div class="pull-right">{{ state.user.createTime }}</div>
               </li>
             </ul>
@@ -55,12 +55,9 @@
             <el-tab-pane label="修改密码" name="resetPwd">
               <resetPwd />
             </el-tab-pane>
-            <el-tab-pane label="第三方应用" name="thirdParty">
-              <thirdParty :auths="state.auths" />
-            </el-tab-pane>
-            <el-tab-pane label="在线设备" name="onlineDevice">
-              <onlineDevice :devices="state.devices" />
-            </el-tab-pane>
+<!--            <el-tab-pane label="在线设备" name="onlineDevice">-->
+<!--              <onlineDevice :devices="state.devices" />-->
+<!--            </el-tab-pane>-->
           </el-tabs>
         </el-card>
       </el-col>
@@ -116,7 +113,7 @@ const getOnlines = async () => {
 
 onMounted(() => {
   getUser();
-  getAuths();
-  getOnlines();
+  // getAuths();
+  // getOnlines();
 });
 </script>

+ 3 - 3
src/views/system/user/profile/resetPwd.vue

@@ -1,12 +1,12 @@
 <template>
   <el-form ref="pwdRef" :model="user" :rules="rules" label-width="80px">
-    <el-form-item label="旧密码" prop="oldPassword">
+    <el-form-item label="旧密码" prop="oldPassword">
       <el-input v-model="user.oldPassword" placeholder="请输入旧密码" type="password" show-password />
     </el-form-item>
-    <el-form-item label="新密码" prop="newPassword">
+    <el-form-item label="新密码" prop="newPassword">
       <el-input v-model="user.newPassword" placeholder="请输入新密码" type="password" show-password />
     </el-form-item>
-    <el-form-item label="确认密码" prop="confirmPassword">
+    <el-form-item label="确认密码" prop="confirmPassword">
       <el-input v-model="user.confirmPassword" placeholder="请确认新密码" type="password" show-password />
     </el-form-item>
     <el-form-item>

+ 4 - 4
src/views/system/user/profile/userInfo.vue

@@ -1,15 +1,15 @@
 <template>
   <el-form ref="userRef" :model="userForm" :rules="rules" label-width="80px">
-    <el-form-item label="用户昵称" prop="nickName">
+    <el-form-item label="用户昵称" prop="nickName">
       <el-input v-model="userForm.nickName" maxlength="30" />
     </el-form-item>
-    <el-form-item label="手机号码" prop="phonenumber">
+    <el-form-item label="手机号码" prop="phonenumber">
       <el-input v-model="userForm.phonenumber" maxlength="11" />
     </el-form-item>
-    <el-form-item label="邮箱" prop="email">
+    <el-form-item label="邮箱" prop="email">
       <el-input v-model="userForm.email" maxlength="50" />
     </el-form-item>
-    <el-form-item label="性别">
+    <el-form-item label="性别">
       <el-radio-group v-model="userForm.sex">
         <el-radio value="0">男</el-radio>
         <el-radio value="1">女</el-radio>