riku
2025-07-23 fe7fd6e4b1450c01faba724bb22b1d050e896c92
2025.7.23 监管地图(待完成)
已修改5个文件
已添加1个文件
183 ■■■■■ 文件已修改
src/components.d.ts 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/map/SceneMap.vue 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/map/marks.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/map/util.js 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/task/TaskManage.vue 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/task/components/CompTaskMap.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components.d.ts
@@ -13,7 +13,6 @@
    CompGenericWrapper: typeof import('./components/CompGenericWrapper.vue')['default']
    CompQuickSet: typeof import('./components/search-option/CompQuickSet.vue')['default']
    Content: typeof import('./components/core/Content.vue')['default']
    copy: typeof import('./components/search-option/FYOptionUserType copy.vue')['default']
    ElAffix: typeof import('element-plus/es')['ElAffix']
    ElAside: typeof import('element-plus/es')['ElAside']
    ElAvatar: typeof import('element-plus/es')['ElAvatar']
@@ -52,7 +51,10 @@
    ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
    ElMenuItemGroup: typeof import('element-plus/es')['ElMenuItemGroup']
    ElOption: typeof import('element-plus/es')['ElOption']
    ElPagination: typeof import('element-plus/es')['ElPagination']
    ElPopover: typeof import('element-plus/es')['ElPopover']
    ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
    ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
    ElRow: typeof import('element-plus/es')['ElRow']
    ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
    ElSelect: typeof import('element-plus/es')['ElSelect']
@@ -79,11 +81,9 @@
    FYImageSelectDialog: typeof import('./components/FYImageSelectDialog.vue')['default']
    FYInfoSearch: typeof import('./components/search-option/FYInfoSearch.vue')['default']
    FYList: typeof import('./components/table/FYList.vue')['default']
    FYOption: typeof import('./components/search-option/FYOption.vue')['default']
    FYOptionLocation: typeof import('./components/search-option/FYOptionLocation.vue')['default']
    FYOptionOnlineStatus: typeof import('./components/search-option/FYOptionOnlineStatus.vue')['default']
    FYOptionScene: typeof import('./components/search-option/FYOptionScene.vue')['default']
    FYOptionSupervision: typeof import('./components/search-option/FYOptionSupervision.vue')['default']
    FYOptionSupervisionStatus: typeof import('./components/search-option/FYOptionSupervisionStatus.vue')['default']
    FYOptionText: typeof import('./components/search-option/base/FYOptionText.vue')['default']
    FYOptionTime: typeof import('./components/search-option/FYOptionTime.vue')['default']
src/components/map/SceneMap.vue
@@ -9,11 +9,22 @@
    ></FYOptionScene>
    <slot name="left-top"></slot>
  </el-row>
  <el-scrollbar class="right-wrap">
    <div v-for="s in selectedSceneList" :key="s.guid">
      <el-checkbox
        v-model="s._checked"
        :label="s.name"
        @change="handleChange"
      />
      <!-- <el-text>{{ s.name }}</el-text> -->
    </div>
  </el-scrollbar>
</template>
<script setup>
import { ref, watch } from 'vue';
import { ref, watch, computed } from 'vue';
import { map, onMapMounted } from '@/utils/map/index';
import marks from '@/utils/map/marks';
import mapUtil from '@/utils/map/util';
import { sceneIcon } from '@/assets/scene-icon';
const props = defineProps({
  // åœºæ™¯ç‚¹ä½ä¿¡æ¯
@@ -24,6 +35,17 @@
let markViewList = [];
const scenetype = ref();
const selectedSceneList = computed(() => {
  return props.data.filter((v) => {
    v._checked = true;
    return (
      scenetype.value == undefined ||
      scenetype.value.value == null ||
      v.typeid + '' == scenetype.value.value
    );
  });
});
watch(
  () => props.data,
@@ -43,6 +65,12 @@
    filterMarkViews();
  }
});
function handleChange(value) {
  console.log(value);
  filterMarkViews();
}
function createSceneMarks() {
  onMapMounted(() => {
@@ -64,15 +92,15 @@
            content: ''
            // direction: 'bottom'
          });
          _extData._show = false
          ev.target.setExtData(_extData)
          _extData._show = false;
          ev.target.setExtData(_extData);
        } else {
          ev.target.setLabel({
            content: _extData.name
            // direction: 'bottom'
          });
          _extData._show = true
          ev.target.setExtData(_extData)
          _extData._show = true;
          ev.target.setExtData(_extData);
        }
      });
      allMarkViews.push(mark);
@@ -95,9 +123,22 @@
        );
      });
    }
    markViewList = markViewList.filter((v) => {
      const _index = selectedSceneList.value.findIndex((s) => {
        console.log(s.guid, v.getExtData().guid);
        s.guid == v.getExtData().guid;
      });
      return _index != -1;
    });
    map.add(markViewList);
    setTimeout(() => {
      map.setFitView(markViewList);
      // const list = markViewList.map((v) => {
      //   const _extData = v.getExtData();
      //   return [_extData.longitude, _extData.latitude];
      // });
      // mapUtil.setBound(list);
    }, 1000);
  });
}
@@ -116,4 +157,14 @@
  left: 0;
  top: 0;
}
.right-wrap {
  position: absolute;
  right: 0px;
  bottom: 0;
  height: 50%;
  background-color: white;
  border-radius: 4px;
  padding: 2px 8px;
  max-width: 300px;
}
</style>
src/utils/map/marks.js
@@ -145,7 +145,7 @@
    return layer;
  },
  createMarker({ position, img, label, extData }) {
  createMarker({ position, img, label = ' ', extData }) {
    //创建 AMap.Icon å®žä¾‹ï¼š
    const icon = new AMap.Icon({
      size: new AMap.Size(30, 30), //图标尺寸
src/utils/map/util.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,108 @@
import { map, AMap, isDragging } from '@/utils/map/index';
import marks from '@/utils/map/marks';
/**
 * åæ ‡é›†åˆçš„æœ€è¥¿å—角和最东北角
 * @param {*} list
 *  list æ˜¯æŽ¥å£èŽ·å–çš„ç‚¹ çš„æ•°ç»„
 */
const getBound = (list) => {
  const offset = 0.005;
  let south = null;
  let west = null;
  let north = null;
  let east = null;
  for (let item of list) {
    // æŽ’除无效经纬度
    if (item[0] == 0 && item[1] == 0) {
      continue;
    }
    if ((west && item[0] < west) || !west) {
      west = item[0] - offset;
    }
    if ((south && item[1] < south) || !south) {
      south = item[1] - offset;
    }
    if ((east && item[0] > east) || !east) {
      east = item[0] + offset;
    }
    if ((north && item[1] > north) || !north) {
      north = item[1] + offset;
    }
  }
  if (!south || !west || !north || !east) {
    return { sw: null, ne: null };
  } else {
    return { sw: [west, south], ne: [east, north] };
  }
};
/**
 * æ ¹æ®ä¸­å¿ƒç‚¹å‡ºå‘的半径,得到合适的地图缩放系数
 * é«˜å¾·åœ°å›¾ç¼©æ”¾ç³»æ•°æ¯å‡å°‘1,则地图展示的实际距离放大1倍
 * é«˜å¾·åœ°å›¾ç¼©æ”¾ç³»æ•°èŒƒå›´[3, 18]
 * @param {*} d
 */
const distanceToZoom = (d) => {
  let baseDis = 250,
    z = 0;
  while (baseDis < d) {
    baseDis *= 2;
    z++;
  }
  // å¤šä½™çš„地图缩放系数
  const x = (baseDis - d) / (baseDis / 2);
  z -= x;
  z = z < 0 ? 0 : z;
  z = 18 - z;
  z = z < 3 ? 3 : z;
  return z;
};
export default {
  setCenter(lnglat, ignore = false) {
    if (!ignore && isDragging) {
      return;
    }
    var now = new Date();
    if (
      this.lasttime == undefined ||
      now.getTime() - this.lasttime.getTime() >= 200
    ) {
      map.setCenter(lnglat);
      this.lasttime = now;
    }
  },
  addViews(view) {
    map.add(view);
  },
  removeViews(view) {
    map.remove(view);
  },
  clearMap() {
    marks.clearMassMarks();
    map.clearMap();
  },
  setFitView(views) {
    if (views) {
      map.setFitView(views);
    } else {
      map.setFitView();
    }
  },
  setFitSector({ p, r }) {
    this.setCenter(p);
    const z = distanceToZoom(r);
    map.setZoom(z);
  },
  setBound(lnglats_GD) {
    const { sw, ne } = getBound(lnglats_GD);
    if (!sw || !ne) {
      return;
    }
    var mybounds = new AMap.Bounds(sw, ne); // sw, ne > [xxx,xxx], [xxx,xxx]
    map.setBounds(mybounds);
  }
};
src/views/fysp/task/TaskManage.vue
@@ -214,7 +214,10 @@
      });
      return [
        { name: '场景数', value: total },
        { name: '未巡查', value: total - inspected },
        {
          name: '未巡查',
          value: total - inspected > 0 ? total - inspected : 0
        },
        { name: '已巡查', value: inspected }
      ];
    }
src/views/fysp/task/components/CompTaskMap.vue
@@ -31,6 +31,7 @@
const scenes = computed(() => {
  return props.plans
    .filter((v) => {
      // æŒ‰ç…§ç›‘管状态筛选
      if (supervisionStatus.value) {
        switch (supervisionStatus.value.value) {
          case '0':