riku
2024-07-11 505798927f75c84693cc51becf16aa525503fc92
2024.7.11
已修改22个文件
已添加10个文件
已重命名1个文件
1181 ■■■■ 文件已修改
src/api/fysp/problemApi.js 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/index.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/styles/element/index.scss 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/styles/index.scss 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components.d.ts 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/inspection/ProblemItem.vue 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/map/BaseMap.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/search/OptionTime.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/composables/fetchData.js 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/stores/map.js 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/ProCheckProxy.js 146 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/map/index.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/map/marks.js 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/map/util.js 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inspection/InspectionView.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inspection/WorkStream.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inspection/problem/ProblemTrack.vue 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inspection/problem/component/ProblemChangeChart.vue 56 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inspection/problem/component/ProblemSummary.vue 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inspection/problem/component/ProblemTable.vue 42 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inspection/problem/component/ProblemType.vue 108 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/main/MonitorView.vue 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/management/EvaluateSummary copy.vue 补丁 | 查看 | 原始文档 | blame | 历史
src/views/management/ManagementView.vue 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/management/StatisticView.vue 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/management/TaskStats.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/management/evaluate/EvaluateSummary.vue 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/management/evaluate/component/RiskArea.vue 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/management/evaluate/component/RiskCount.vue 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/monitor/DustMonitor.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/visualization/SubtaskVisual.vue 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/visualization/SupervisionVisual.vue 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/visualization/VisualizationView.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/fysp/problemApi.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,42 @@
import { $fysp } from '../index'
const id = 'IF3DgsgKxSWvTM3M'
const name = 'pcheck'
export default {
  /**
   * é—®é¢˜å®¡æ ¸
   * @param {Number} action 0:问题通过;1:问题不通过;2:整改通过;3整改不通过
   */
  checkProblem({ pId, action, remark = '', userId = id, userName = name }) {
    const params = `?pId=${pId}&action=${action}&remark=${remark}&userId=${userId}&userName=${userName}`
    return $fysp.post(`problemlist/check${params}`).then((res) => res.data)
  },
  fetchProblemType({ cityCode, districtCode, sceneTypeId }) {
    const params = `?taskTypeId=1&cityCode=${cityCode}&districtCode=${districtCode}&sceneTypeId=${sceneTypeId}`
    return $fysp.get(`problemtype/search${params}`).then((res) => res.data)
  },
  /**
   * èŽ·å–å·¡æŸ¥ä»»åŠ¡çš„é—®é¢˜å’Œæ•´æ”¹
   */
  fetchProblems(subtaskId) {
    return $fysp
      .get('problemlist/subtask', {
        params: {
          stGuid: subtaskId,
          // åŒ…含未审核以及审核不通过的问题
          all: true
        }
      })
      .then((res) => res.data)
  },
  /**
   * èŽ·å–å„é—®é¢˜ç±»åž‹å‘ç”Ÿçš„æ•°é‡ç»Ÿè®¡
   */
  fetchProblemsStatistic(area) {
    return $fysp.post('problemlist/getStatisticalResult', area).then((res) => res.data)
  }
}
src/api/index.js
@@ -11,8 +11,8 @@
let ip2_file = 'https://fyami.com.cn/'
if (debug) {
  // ip1 = 'http://192.168.0.138:8082/'
  ip1 = 'http://localhost:8080/'
  ip1 = 'http://192.168.0.138:8082/'
  // ip1 = 'http://localhost:8080/'
  // ip1_file = 'http://47.100.191.150:9005/';
  // ip2 = 'http://192.168.0.138:8080/';
  // ip2_file = 'https://fyami.com.cn/';
src/assets/styles/element/index.scss
@@ -1,15 +1,12 @@
// @forward 'element-plus/theme-chalk/src/common/var.scss' with (
//   $colors: (
//     'primary': (
//       'base': green
//     )
//   )
// );
@forward 'element-plus/theme-chalk/src/dark/var.scss' with (
  $bg-color: (
    'page': #ffffffa9,
    '': #122b54a9,
    'overlay': #122b54a9
    '': #14428be8,
    'overlay': #102f63c9
  ),
  $colors: (
    'primary': (
      'base': #e6a23c
    )
  )
);
src/assets/styles/index.scss
@@ -14,3 +14,8 @@
  font-weight: normal;
  font-style: normal;
}
.border-r-small {
  // padding: 0 8px;
  // border: 1px white solid;
}
src/components.d.ts
@@ -13,9 +13,13 @@
    ElCard: typeof import('element-plus/es')['ElCard']
    ElCascader: typeof import('element-plus/es')['ElCascader']
    ElCol: typeof import('element-plus/es')['ElCol']
    ElCollapse: typeof import('element-plus/es')['ElCollapse']
    ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
    ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
    ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
    ElDivider: typeof import('element-plus/es')['ElDivider']
    ElIcon: typeof import('element-plus/es')['ElIcon']
    ElImage: typeof import('element-plus/es')['ElImage']
    ElLink: typeof import('element-plus/es')['ElLink']
    ElOption: typeof import('element-plus/es')['ElOption']
    ElProgress: typeof import('element-plus/es')['ElProgress']
@@ -23,6 +27,7 @@
    ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
    ElSegmented: typeof import('element-plus/es')['ElSegmented']
    ElSelect: typeof import('element-plus/es')['ElSelect']
    ElSpace: typeof import('element-plus/es')['ElSpace']
    ElStatistic: typeof import('element-plus/es')['ElStatistic']
    ElTable: typeof import('element-plus/es')['ElTable']
    ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
@@ -33,6 +38,7 @@
    OptionLocation: typeof import('./components/search/OptionLocation.vue')['default']
    OptionSceneType: typeof import('./components/search/OptionSceneType.vue')['default']
    OptionTime: typeof import('./components/search/OptionTime.vue')['default']
    ProblemItem: typeof import('./components/inspection/ProblemItem.vue')['default']
    RouterLink: typeof import('vue-router')['RouterLink']
    RouterView: typeof import('vue-router')['RouterView']
    SubtaskExamineItem: typeof import('./components/inspection/SubtaskExamineItem.vue')['default']
src/components/inspection/ProblemItem.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,68 @@
<template>
  <div>
    <el-text tag="b" type="warning" size="small">{{ index }}. </el-text>
    <el-text type="warning" size="small">{{ title }}</el-text>
  </div>
  <!-- <div>
    <el-text>{{ proStatus.name }}</el-text>
  </div> -->
  <template v-for="(pic, t) in pics" :key="t">
    <template v-if="pic.path.length > 0">
      <div>
        <el-text size="small" type="info">{{ pic.title }}</el-text>
      </div>
      <el-space>
        <el-image
          v-for="(p, i) in pic.path"
          class="image"
          :key="i"
          :src="p"
          :preview-src-list="pic.path"
          :initial-index="i"
          fit="cover"
          lazy
        />
      </el-space>
    </template>
  </template>
</template>
<script setup>
import { computed } from 'vue'
import ProCheckProxy from '@/utils/ProCheckProxy'
const props = defineProps({
  problem: {
    type: Object,
    default: () => {
      return {}
    }
  },
  index: {
    type: Number,
    default: 1
  }
})
// é—®é¢˜åç§°
const title = computed(() => {
  return props.problem.problemname
})
// é—®é¢˜å›¾ç‰‡
const pics = computed(() => {
  return ProCheckProxy.proPics(props.problem)
})
// é—®é¢˜çŠ¶æ€
const proStatus = computed(() => {
  return ProCheckProxy.proStatusMap(props.problem.extension3)
})
</script>
<style scoped>
.image {
  width: 60px;
  height: 60px;
  border-radius: 2px;
}
</style>
src/components/map/BaseMap.vue
@@ -3,10 +3,9 @@
</template>
<script setup>
import { onMounted } from 'vue'
import { onMounted, inject } from 'vue'
import { createMap } from '@/utils/map/index'
// import { createMap } from '@/utils/map/baseMap'
import { inject } from 'vue'
const mapHeight = inject('mapHeight')
src/components/search/OptionTime.vue
@@ -5,6 +5,7 @@
    @change="handleChange"
    :type="type"
    placeholder="选择时间"
    :disabled-date="disabledDate"
    size="small"
    style="width: 100px"
  />
@@ -13,6 +14,7 @@
<script>
const MONTH = 'month'
const DATE = 'date'
export default {
  props: {
@@ -47,6 +49,9 @@
        default:
          return 'YYYY-MM'
      }
    },
    disabledDate(time) {
      return time.getTime() > Date.now()
    }
  },
  mounted() {
src/composables/fetchData.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,50 @@
// æŽ¥å£æ•°æ®çš„获取
import { ref, watch, computed } from 'vue';
export function useFetchData(page_size) {
  // åˆ†é¡µä¿¡æ¯
  const page = ref(1);
  const pageNum = ref(1);
  const pageSize = ref(page_size ? page_size : 20);
  const total = ref(0);
  watch(page, (nValue, oValue) => {
    if (nValue != oValue) {
      fetchData();
    }
  });
  watch(pageSize, (nValue, oValue) => {
    if (nValue != oValue) {
      fetchData();
    }
  });
  // åŠ è½½çŠ¶æ€, 0: åŠ è½½å®Œæˆ; 1: åŠ è½½ä¸­; 2: å·²å…¨éƒ¨åŠ è½½; 3: åŠ è½½å¤±è´¥;
  const loadStatus = ref(0);
  const loading = computed(() => {
    return loadStatus.value == 1;
  });
  // æ•°æ®èŽ·å–
  function fetchData(fetch) {
    loadStatus.value = 1;
    fetch(page.value, pageSize.value)
      .then((pageInfo) => {
        if (pageInfo) {
          page.value = pageInfo.page ? pageInfo.page : 1;
          pageNum.value = pageInfo.pageNum ? pageInfo.pageNum : 1;
          total.value = pageInfo.total ? pageInfo.total : 0;
        }
        loadStatus.value = 0;
      })
      .catch(() => {
        loadStatus.value = 3;
      })
      .finally(() => {
        loadStatus.value = 2;
      });
  }
  return { page, pageNum, pageSize, total, loadStatus, loading, fetchData };
}
src/stores/map.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,8 @@
import { ref } from 'vue'
import { defineStore } from 'pinia'
export const useMapStore = defineStore('map', () => {
  const focusMarker = ref()
  return { focusMarker }
})
src/utils/ProCheckProxy.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,146 @@
import { $fysp } from '@/api/index'
//问题状态
const proStatus = {
  unCheck: 'unCheck',
  pass: 'pass',
  fail: 'fail',
  change_unCheck: 'change_unCheck',
  change_fail: 'change_fail',
  change_pass: 'change_pass'
}
export default {
  //统计问题
  calProStatus(proList) {
    const status = {
      //问题数量
      proNum: proList.length,
      //整改数量
      changeNum: 0,
      //待审核数量
      uncheckNum: 0,
      //已审核通过数量
      passNum: 0,
      //未通过数量
      unpassNum: 0,
      //整改率
      changePer: '0%',
      //通过率
      passPer: '0%',
      //审核率
      checkPer: '0%'
    }
    proList.forEach((p) => {
      if (p.ischanged) status.changeNum++
      if (p.extension3 == 'fail' || p.extension3 == 'change_fail') status.unpassNum++
      else if (
        p.extension3 == 'unCheck' ||
        p.extension3 == 'change_unCheck' ||
        (p.extension3 == 'pass' && p.ischanged)
      )
        status.uncheckNum++
      else status.passNum++
      status.changePer =
        String(
          (status.changeNum / status.proNum) * 100
            ? ((status.changeNum / status.proNum) * 100).toFixed(1)
            : 0
        ) + '%'
      status.passPer =
        String(
          (status.passNum / status.proNum) * 100
            ? ((status.passNum / status.proNum) * 100).toFixed(1)
            : 0
        ) + '%'
      status.checkPer =
        String(
          ((status.passNum + status.unpassNum) / status.proNum) * 100
            ? (((status.passNum + status.unpassNum) / status.proNum) * 100).toFixed(1)
            : 0
        ) + '%'
    })
    return status
  },
  //统计问题,返回数组形式
  proStatusArray(proList) {
    const status = this.calProStatus(proList)
    return [
      { name: '问题数', value: status.proNum },
      { name: '整改数', value: status.changeNum },
      { name: '待审核', value: status.uncheckNum },
      { name: '已审核', value: status.passNum },
      { name: '未通过', value: status.unpassNum },
      { name: '整改率', value: status.changePer },
      { name: '通过率', value: status.passPer },
      { name: '审核率', value: status.checkPer }
    ]
  },
  //问题图片和整改图片
  proPics(pro) {
    const pics = [
      {
        title: '问题图片',
        path: []
      },
      {
        title: '整改图片',
        path: []
      }
    ]
    if (pro.mediafileList) {
      pro.mediafileList.forEach((m) => {
        pics[m.ischanged ? 1 : 0].path.push(`${$fysp.imgUrl}${m.extension1}${m.guid}.jpg`)
      })
    }
    return pics
  },
  //问题审核状态转换中文
  proStatusMap(p) {
    switch (p) {
      case proStatus.unCheck:
        return { name: '问题未审核', type: 'warning', index: 0, checkable: true, deletable: true, changeable: false }
      case proStatus.pass:
        return { name: '问题通过', type: 'success', index: 1, checkable: false, deletable: true, changeable: false }
      case proStatus.fail:
        return { name: '问题不通过', type: 'danger', index: 1, checkable: false, deletable: true, changeable: false }
      case proStatus.change_unCheck:
        return { name: '整改未审核', type: 'warning', index: 2, checkable: true, deletable: false, changeable: true }
      case proStatus.change_fail:
        return { name: '整改不通过', type: 'danger', index: 3, checkable: false, deletable: false, changeable: true }
      case proStatus.change_pass:
        return { name: '整改通过', type: 'success', index: 3, checkable: false, deletable: false, changeable: true }
      default:
        return { name: '问题未审核', type: 'warning', index: 0, checkable: true, deletable: true }
    }
  },
  /**
   * é—®é¢˜å®¡æ ¸åŽçŠ¶æ€å˜æ¢
   * @param {String} s å½“前问题状态
   * @param {Boolean} isPass å®¡æ ¸é€šè¿‡æˆ–驳回
   * @returns ä¸‹ä¸€ä¸ªé—®é¢˜çŠ¶æ€
   */
  proNextStatus(s, isPass) {
    let status, action
    switch (s) {
      case proStatus.unCheck:
        status = isPass ? proStatus.pass : proStatus.fail
        action = isPass ? 0 : 1
        break
      case proStatus.change_unCheck:
        status = isPass ? proStatus.change_pass : proStatus.change_fail
        action = isPass ? 2 : 3
        break
    }
    return { status: status, action: action }
  }
}
src/utils/map/index.js
@@ -64,7 +64,7 @@
    showBuildingBlock: true,
    mapStyle: 'amap://styles/e1e78509de64ddcd2efb4cb34c6fae2a',
    features: ['bg', 'road'],
    pitch: 45, // åœ°å›¾ä¿¯ä»°è§’度,有效范围 0 åº¦- 83 åº¦
    pitch: 0, // åœ°å›¾ä¿¯ä»°è§’度,有效范围 0 åº¦- 83 åº¦
    viewMode: '3D', // åœ°å›¾æ¨¡å¼
    resizeEnable: true,
    center: [121.603928, 31.252955],
src/utils/map/marks.js
@@ -127,5 +127,19 @@
    }
    return layer
  },
  drawMarker(title, lnglat, img) {
    const marker = new AMap.Marker({
      position: new AMap.LngLat(lnglat[0], lnglat[1]), // ç»çº¬åº¦å¯¹è±¡ï¼Œä¹Ÿå¯ä»¥æ˜¯ç»çº¬åº¦æž„成的一维数组[116.39, 39.9]
      title: title,
      // offset: new AMap.Pixel(-13, -12),
      // anchor: 'center',
      icon: new AMap.Icon({
        image: img,
        imageSize: [30, 30]
      })
    })
    map.add(marker)
  }
}
src/utils/map/util.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
import { map, isDragging } from '@/utils/map/index'
export default {
  setCenter(lnglat) {
    if (isDragging) {
      return
    }
    var now = new Date()
    if (this.lasttime == undefined || now.getTime() - this.lasttime.getTime() >= 1000) {
      map.setCenter(lnglat)
      this.lasttime = now
    }
  },
  addViews(view) {
    map.add(view)
  },
  removeViews(view) {
    map.remove(view)
  },
  clearViews() {
    map.clearMap()
  },
  setFitView() {
    map.setFitView()
  }
}
src/views/inspection/InspectionView.vue
@@ -1,6 +1,6 @@
<template>
  <div class="wrapper">
    <div>现场巡查</div>
    <div>业务状态中控</div>
    <WorkStream></WorkStream>
  </div>
</template>
@@ -11,7 +11,6 @@
 */
import TaskTrack from '@/views/inspection/TaskTrack.vue'
import WorkStream from '@/views/inspection/WorkStream.vue'
</script>
<style scoped>
src/views/inspection/WorkStream.vue
@@ -1,6 +1,6 @@
<template>
  <div class="border-r-small m-h-2 p-h-4">
    <el-scrollbar ref="scrollbarRef" height="calc(var(--fy-body-height) / 3 * 1 - 30px)">
    <el-scrollbar ref="scrollbarRef" :height="height">
      <div ref="scrollContentRef">
        <div v-for="item in streams" :key="item.index">
          <el-text type="primary">[{{ item.time }}]: </el-text>
@@ -15,9 +15,14 @@
  </div>
</template>
<script setup>
import { reactive, ref, onMounted } from 'vue'
import { reactive, ref, onMounted, inject } from 'vue'
import dayjs from 'dayjs'
import { unCalc } from '@/utils/css-util'
const excludeMapHeight = inject('excludeMapHeight')
const height = `calc(${unCalc(excludeMapHeight)} - 30px)`
const streams = reactive([])
const scrollContentRef = ref()
const scrollbarRef = ref()
src/views/inspection/problem/ProblemTrack.vue
@@ -2,15 +2,20 @@
  <div class="border-r-small">
    <div class="font-large">问题整改跟踪</div>
    <div>
      <el-row justify="end">
        <OptionTime v-model="time" type="date"></OptionTime>
      </el-row>
      <ProblemSummary :data="subtaskList"></ProblemSummary>
      <ProblemTable :data="subtaskList"></ProblemTable>
    </div>
    <div>
      <ProblemChangeChart></ProblemChangeChart>
    </div>
    <div>
      <ProblemType></ProblemType>
    </div>
    <el-collapse v-model="activeNames" @change="handleChange">
      <el-collapse-item title="分期趋势" name="1">
        <ProblemChangeChart ref="pChangeRef"></ProblemChangeChart>
      </el-collapse-item>
      <el-collapse-item title="问题分布" name="2">
        <ProblemType ref="pTypeRef"></ProblemType>
      </el-collapse-item>
    </el-collapse>
  </div>
</template>
@@ -29,34 +34,39 @@
  components: { ProblemSummary, ProblemTable, ProblemChangeChart, ProblemType },
  data() {
    return {
      subtaskList: []
      subtaskList: [],
      activeNames: ['1', '2'],
      time: ''
    }
  },
  watch: {},
  watch: {
    time(nV, oV) {
      if (nV != oV) {
        this.areaStore.setTimeOneDay(nV)
        this.fetchSubtask()
      }
    }
  },
  computed: {
    ...mapStores(useAreaStore)
    // area() {
    //   return {
    //     provincecode: '31',
    //     provincename: '上海市',
    //     citycode: '3100',
    //     cityname: '上海市',
    //     districtcode: '310116',
    //     districtname: '金山区',
    //     starttime: '',
    //     endtime: ''
    //   }
    // }
  },
  methods: {
    fetchSubtask() {
      taskApi.fetchSubtaskSummaryByArea(this.areaStore.area).then((res) => {
        this.subtaskList = res.data
      })
    },
    handleChange(val) {
      if (val.indexOf('1') != -1) {
        this.$refs.pChangeRef.refresh()
      }
      if (val.indexOf('2') != -1) {
        this.$refs.pTypeRef.refresh()
      }
    }
  },
  mounted() {
    this.fetchSubtask()
    // this.fetchSubtask()
  }
}
</script>
src/views/inspection/problem/component/ProblemChangeChart.vue
@@ -1,7 +1,20 @@
<template>
  <el-row justify="space-between">
    <div>分期趋势</div>
    <OptionTime v-model="time"></OptionTime>
    <el-col :span="18">
      <div>
        åœºæ™¯æ•°ï¼š{{ sceneNum }},问题总数:{{ proNum }},单场景问题均值:{{ proEachSceneNum }},
      </div>
      <div>
        æ•´æ”¹æ€»æ•°ï¼š{{ changeNum }},有效整改数:{{ changePassNum }},问题整改率:{{
          changePer
        }},有效整改率:{{ changePassPer }}
      </div>
    </el-col>
    <el-col :span="6">
      <el-row justify="end">
        <OptionTime v-model="time"></OptionTime>
      </el-row>
    </el-col>
  </el-row>
  <div ref="echart" class="line-chart"></div>
</template>
@@ -9,12 +22,39 @@
import * as echarts from 'echarts'
export default {
  data() {
    return {
      sceneNum: 51,
      proNum: 161,
      changeNum: 40,
      changePassNum: 40
    }
  },
  computed: {
    proEachSceneNum() {
      return Math.round((this.proNum / this.sceneNum) * 10) / 10
    },
    changePer() {
      if (this.proNum > 0) {
        return Math.round((this.changeNum / this.proNum) * 100) + '%'
      } else {
        return '/'
      }
    },
    changePassPer() {
      if (this.proNum > 0) {
        return Math.round((this.changePassNum / this.proNum) * 100) + '%'
      } else {
        return '/'
      }
    }
  },
  methods: {
    refresh() {
      const fontSize = 12
      const option = {
        legend: {
          data: ['问题', '整改'],
          data: ['问题数', '整改数'],
          textStyle: {
            fontSize: fontSize,
            color: 'white'
@@ -28,7 +68,7 @@
        },
        xAxis: {
          type: 'category',
          data: ['1号', '2号', '3号', '4号', '5号', '6号'],
          data: ['1号', '2号', '3号', '4号', '5号', '6号', '7号', '8号', '9号'],
          axisLabel: {
            textStyle: {
              fontSize: fontSize
@@ -48,14 +88,14 @@
        },
        series: [
          {
            name: '问题',
            name: '问题数',
            type: 'bar',
            data: [67, 45, 90, 67, 45, 90]
            data: [12, 8, 9, 7, 14, 19, 9, 7, 14]
          },
          {
            name: '整改',
            name: '整改数',
            type: 'bar',
            data: [67, 45, 90, 67, 40, 81]
            data: [6, 2, 5, 3, 6, 3, 6, 2, 5]
          }
          //   {
          //     name: '整改率',
src/views/inspection/problem/component/ProblemSummary.vue
@@ -1,7 +1,9 @@
<template>
  <div>
    é—®é¢˜æ•°: {{ summary.proNum }},整改数: {{ summary.changeNum }},整改率: {{ summary.changePer }}
  <div class="font-small">
    ä»Šæ—¥ç»Ÿè®¡ï¼šé—®é¢˜æ•°: {{ summary.proNum }},整改数: {{ summary.changeNum }},整改率:
    {{ summary.changePer }}
  </div>
  <div class="font-small">突出问题:路面积尘,问题数:13,占比:81%</div>
</template>
<script setup>
import { computed, ref } from 'vue'
@@ -23,9 +25,37 @@
  })
  if (proNum > 0) {
    changePer = Math.round((changeNum / proNum) * 100) / 100 + '%'
    changePer = Math.round((changeNum / proNum) * 100) + '%'
  }
  return { proNum, changeNum, changePer }
})
const mainPro = computed(() => {
  let res
  let total = 0,
    max = 0
  props.data.forEach((d) => {
    total += d.proNum
  })
  props.data.forEach((d) => {
    if (total > 0) {
      const per = d.proNum / total
      if (per >= max) {
        max = per
        // res.push({
        //   name: d.name,
        //   count: d.count,
        //   per: Math.round(per * 100) + '%'
        // })
        res = {
          name: d.name,
          count: d.count,
          per: Math.round(per * 100) + '%'
        }
      }
    }
  })
  return res
})
</script>
src/views/inspection/problem/component/ProblemTable.vue
@@ -6,6 +6,7 @@
    :row-class-name="tableRowClassName"
    :height="tableHeight"
    size="small"
    @row-click="handleRowClick"
  >
    <el-table-column type="index" label="" width="30"> </el-table-column>
    <el-table-column prop="scene.name" :show-overflow-tooltip="true" label="名称" width="150">
@@ -27,13 +28,22 @@
      </template>
    </el-table-column>
  </el-table>
  <div class="btn-more font-small">
    <el-link type="primary" @click="showMore = !showMore">查看更多</el-link>
  <div v-if="showMoreBtn" class="btn-more font-small">
    <el-link type="primary" @click="showMore = !showMore">
      {{ showMore ? '收起更多' : '查看更多' }}
    </el-link>
  </div>
</template>
<script setup>
import { computed, ref } from 'vue'
import dayjs from 'dayjs'
import { useMapStore } from '@/stores/map.js'
import marks from '@/utils/map/marks.js'
import mapUtil from '@/utils/map/util.js'
import scene_1 from '@/assets/icon/scene_1.png'
const mapStore = useMapStore()
const props = defineProps({
  data: {
@@ -42,7 +52,12 @@
  loading: Boolean
})
const showCount = 3
const showMore = ref(false)
const showMoreBtn = computed(() => {
  return props.data.length > showCount
})
const tableData = computed(() => {
  const l = props.data.map((value) => {
@@ -54,7 +69,13 @@
  })
  return l.sort((a, b) => {
    return dayjs(b.updateTime) - dayjs(a.updateTime)
    if (!a.updateTime) {
      return 1
    } else if (!b.updateTime) {
      return -1
    } else {
      return dayjs(b.updateTime) - dayjs(a.updateTime)
    }
  })
  // return l
})
@@ -63,7 +84,7 @@
  if (showMore.value) {
    return tableData.value
  } else {
    return tableData.value.slice(0, 3)
    return tableData.value.slice(0, showCount)
  }
})
@@ -76,9 +97,20 @@
  if (p == 0) {
    return '/'
  } else {
    return Math.round((c / p) * 100) / 100 + '%'
    return Math.round((c / p) * 100) + '%'
  }
}
function handleRowClick(row, col, event) {
  const title = row.scene.name
  const lnglat = [row.scene.longitude, row.scene.latitude]
  const img = scene_1
  mapUtil.clearViews()
  marks.drawMarker(title, lnglat, img)
  mapUtil.setFitView()
  mapStore.focusMarker = row
}
</script>
<style scoped>
.btn-more {
src/views/inspection/problem/component/ProblemType.vue
@@ -1,16 +1,95 @@
<template>
  <el-row justify="space-between">
    <div>问题分布</div>
    <OptionTime v-model="time"></OptionTime>
    <el-col :span="18">
      <div v-if="mainProType">
        çªå‡ºé—®é¢˜ï¼š{{ mainProType.name }},问题数:{{ mainProType.count }},占比{{ mainProType.per }}
        <!-- <span v-for="item in mainProType" :key="item.name">
          {{ item.name }},问题数:{{ item.count }},占比{{ item.per }}
        </span> -->
      </div>
    </el-col>
    <el-col :span="6">
      <el-row justify="end">
        <OptionTime v-model="time"></OptionTime>
      </el-row>
    </el-col>
  </el-row>
  <div ref="echart" class="line-chart"></div>
</template>
<script>
import * as echarts from 'echarts'
import { unref } from 'vue'
import dayjs from 'dayjs'
import problemApi from '@/api/fysp/problemApi.js'
import { useFetchData } from '@/composables/fetchData'
import { useAreaStore } from '@/stores/area.js'
import { mapStores } from 'pinia'
export default {
  setup() {
    const { loading, fetchData } = useFetchData()
    return { loading, fetchData }
  },
  data() {
    return {
      dataList: []
    }
  },
  computed: {
    ...mapStores(useAreaStore),
    mainProType() {
      let res
      let total = 0,
        max = 0
      this.dataList.forEach((d) => {
        total += d.count
      })
      this.dataList.forEach((d) => {
        if (total > 0) {
          const per = d.count / total
          if (per >= max) {
            max = per
            // res.push({
            //   name: d.name,
            //   count: d.count,
            //   per: Math.round(per * 100) + '%'
            // })
            res = {
              name: d.name,
              count: d.count,
              per: Math.round(per * 100) + '%'
            }
          }
        }
      })
      return res
    }
  },
  methods: {
    refresh() {
    fetchProblemsStatistic() {
      const param = unref(this.areaStore.area)
      param.starttime = dayjs(param.starttime).startOf('month').format('YYYY-MM-DD HH:mm:ss')
      param.endtime = dayjs(param.endtime).endOf('month').format('YYYY-MM-DD HH:mm:ss')
      this.fetchData((page, pageSize) => {
        return problemApi.fetchProblemsStatistic(param).then((res) => {
          this.dataList = res
          const chartData = res
            .map((item) => {
              return {
                value: item.count,
                name: item.name
              }
            })
            .sort(function (a, b) {
              return a.value - b.value
            })
          this.refresh(chartData)
        })
      })
    },
    refresh(chartData) {
      const fontSize = 12
      const option = {
        legend: {
@@ -35,18 +114,19 @@
            type: 'pie',
            radius: '55%',
            center: ['50%', '50%'],
            data: [
              { value: 24, name: '出入口(道路)扬尘' },
              { value: 20, name: '工程车辆' },
              { value: 18, name: '道路扬尘' },
              { value: 26, name: '路面硬化' },
              { value: 30, name: '渣土' }
            ].sort(function (a, b) {
              return a.value - b.value
            }),
            data: chartData,
            // data: [
            //   { value: 24, name: '出入口(道路)扬尘' },
            //   { value: 20, name: '工程车辆' },
            //   { value: 18, name: '道路扬尘' },
            //   { value: 26, name: '路面硬化' },
            //   { value: 30, name: '渣土' }
            // ].sort(function (a, b) {
            //   return a.value - b.value
            // }),
            roseType: 'radius',
            label: {
              color: 'rgba(255, 255, 255, 0.3)'
              color: 'rgba(255, 255, 255, 0.8)'
            },
            labelLine: {
              lineStyle: {
@@ -74,7 +154,7 @@
  },
  mounted() {
    this.echart = echarts.init(this.$refs.echart)
    this.refresh()
    this.fetchProblemsStatistic()
  }
}
</script>
src/views/main/MonitorView.vue
@@ -1,9 +1,9 @@
<template>
  <el-row>
    <el-col :span="7" class="page-right">
      <!-- <el-scrollbar height="var(--fy-body-height)"> -->
      <ManagementView></ManagementView>
      <!-- </el-scrollbar> -->
      <el-scrollbar height="var(--fy-body-height)">
        <ManagementView></ManagementView>
      </el-scrollbar>
    </el-col>
    <el-col :span="10">
      <el-scrollbar class="page-left-top">
@@ -32,6 +32,15 @@
const windowHeight = ref(window.innerHeight)
const areaStore = useAreaStore()
areaStore.setTimeOneDay()
areaStore.setLocation({
  pCode: '31',
  pName: '上海市',
  cCode: '3100',
  cName: '上海市',
  dCode: '310106',
  dName: '静安区'
})
areaStore.setSceneType('1')
// const headerHeight = computed(()=>{
//   return
@@ -40,16 +49,17 @@
//   console.log(res.text())
// })
provide('mapHeight', 'calc(var(--fy-body-height) / 3 * 2)')
provide('mapHeight', 'calc(var(--fy-body-height) / 4 * 3)')
provide('excludeMapHeight', 'calc(var(--fy-body-height) / 4 * 1)')
</script>
<style scoped>
.page-left-top {
  height: calc(var(--fy-body-height) / 3 * 2);
  height: calc(var(--fy-body-height) / 4 * 3);
  /* background-color: aquamarine; */
}
.page-left-bottom {
  height: calc(var(--fy-body-height) / 3 * 1);
  height: calc(var(--fy-body-height) / 4 * 1);
  /* background-color: bisque; */
}
src/views/management/EvaluateSummary copy.vue
src/views/management/ManagementView.vue
@@ -4,13 +4,13 @@
  <!-- <TaskStats ref="statusRef"></TaskStats> -->
  <EvaluateSummary :height="height"></EvaluateSummary>
  <!-- <TaskSummary ref="summaryRef"></TaskSummary> -->
  <ReInspectionView ref="summaryRef"></ReInspectionView>
  <!-- <ReInspectionView ref="summaryRef"></ReInspectionView> -->
</template>
<script>
import TaskStats from '@/views/management/TaskStats.vue'
import TaskSummary from '@/views/management/TaskSummary.vue'
import EvaluateSummary from '@/views/management/EvaluateSummary.vue'
import EvaluateSummary from '@/views/management/evaluate/EvaluateSummary.vue'
import ReInspectionView from '@/views/inspection/ReInspectionView.vue'
import ProblemTrack from '@/views/inspection/problem/ProblemTrack.vue'
import { vResize } from '@/utils/resize-observer'
@@ -33,8 +33,8 @@
  methods: {
    calcHeight() {
      const h1 = this.$refs.statusRef.$el.offsetHeight
      const h2 = this.$refs.summaryRef.$el.offsetHeight
      const h = h1 + h2
      // const h2 = this.$refs.summaryRef.$el.offsetHeight
      const h = h1
      return `calc(var(--fy-body-height) - ${h}px)`
    }
  },
@@ -42,13 +42,13 @@
    vResize.mounted(this.$refs.statusRef.$el, ({ height }) => {
      this.statusHeight = height
    })
    vResize.mounted(this.$refs.summaryRef.$el, ({ height }) => {
      this.summaryHeight = height
    })
    // vResize.mounted(this.$refs.summaryRef.$el, ({ height }) => {
    //   this.summaryHeight = height
    // })
  },
  unmounted() {
    vResize.unmounted(this.$refs.statusRef.$el)
    vResize.unmounted(this.$refs.summaryRef.$el)
    // vResize.unmounted(this.$refs.summaryRef.$el)
  }
}
</script>
src/views/management/StatisticView.vue
@@ -1,18 +1,22 @@
<template>
  <!-- <el-row> ç»Ÿè®¡ç®¡ç† </el-row> -->
  <SelfInspection></SelfInspection>
  <JointEnforcement></JointEnforcement>
  <!-- <SelfInspection></SelfInspection> -->
  <!-- <JointEnforcement></JointEnforcement> -->
  <TaskStats></TaskStats>
  <TaskSummary></TaskSummary>
  <DustMonitor></DustMonitor>
</template>
<script>
import SelfInspection from '@/views/inspection/SelfInspection.vue'
import JointEnforcement from '@/views/inspection/JointEnforcement.vue'
import TaskSummary from '@/views/management/TaskSummary.vue'
import TaskStats from '@/views/management/TaskStats.vue'
import DustMonitor from '@/views/monitor/DustMonitor.vue'
import { vResize } from '@/utils/resize-observer'
export default {
  components: { SelfInspection, JointEnforcement, TaskSummary },
  components: { SelfInspection, JointEnforcement, TaskSummary, TaskStats, DustMonitor },
  data() {
    return {
      // height: '500px',
src/views/management/TaskStats.vue
@@ -1,6 +1,6 @@
<template>
  <div class="border-r-small">
    <div class="font-large">巡查量</div>
    <div class="font-large">任务监控</div>
    <el-row justify="space-evenly">
      <el-statistic title="今日完成" :value="10"> </el-statistic>
      <el-statistic title="本周完成" :value="10"> </el-statistic>
src/views/management/evaluate/EvaluateSummary.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,55 @@
<template>
  <div class="border-r-small">
    <el-row justify="space-between">
      <div ref="titleRef" class="font-large">综合风险评估</div>
      <!-- <OptionTime v-model="time"></OptionTime> -->
    </el-row>
    <RiskCount></RiskCount>
    <RiskArea></RiskArea>
  </div>
</template>
<script>
import { unCalc } from '@/utils/css-util'
import RiskCount from './component/RiskCount.vue'
import RiskArea from './component/RiskArea.vue'
/**
 * å¯¹å®Œæˆçš„任务进行评估风险,显示高风险场景,显示复核的场景的情况
 */
export default {
  components: { RiskCount, RiskArea },
  props: {
    height: {
      type: String,
      default: '200'
    }
  },
  data() {
    return {
      tableData: [],
      tableHeight: '200'
    }
  },
  watch: {
    height(nV, oV) {
      if (nV != oV) {
        this.tableHeight = this.calcTableHeight()
      }
    }
  },
  methods: {
    calcTableHeight() {
      const h1 = this.$refs.titleRef.offsetHeight
      // const h2 = this.$refs.statisticRef.$el.offsetHeight
      const h = h1
      const r = `calc(${unCalc(this.height)} - ${h}px)`
      return r
    }
  },
  mounted() {
    this.tableHeight = this.calcTableHeight()
  }
}
</script>
<style scoped></style>
src/views/management/evaluate/component/RiskArea.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,102 @@
<template>
  <el-row justify="space-between">
    <div class="font-small">区域风险分布</div>
    <OptionTime v-model="time"></OptionTime>
  </el-row>
  <div ref="echart" class="line-chart"></div>
</template>
<script>
import * as echarts from 'echarts'
export default {
  methods: {
    refresh() {
      const fontSize = 12
      const option = {
        color: ['#f56c6c', '#e6a23c', '#67c23a'],
        legend: {
          data: ['高风险', '中风险', '低风险'],
          textStyle: {
            fontSize: fontSize,
            color: 'white'
          }
        },
        grid: {
          left: '3%',
          right: '4%',
          bottom: '3%',
          containLabel: true
        },
        xAxis: {
          type: 'category',
          data: [
            '江宁路街道',
            '石门二路街道',
            '南京西路街道',
            '静安寺街道',
            '曹家渡街道',
            '天目西路街道',
            '北站街道',
            '宝山路街道',
            '共和新路街道',
            '大宁路街道',
            '彭浦新村街道',
            '临汾路街道',
            '芷江西路街道',
            '彭浦镇'
          ],
          axisLabel: {
            rotate: 45,
            textStyle: {
              fontSize: fontSize
            },
            color: '#ffffff',
            textBorderColor: '#fff'
          }
        },
        yAxis: {
          type: 'value',
          axisLabel: {
            textStyle: {
              fontSize: fontSize,
              color: 'white'
            }
          }
        },
        series: [
          {
            name: '高风险',
            type: 'bar',
            stack: 'risk',
            barWidth: 10,
            data: [2, 0, 4, 3, 1, 0, 2, 0, 4, 3, 1, 0, 2, 1]
          },
          {
            name: '中风险',
            type: 'bar',
            stack: 'risk',
            data: [3, 1, 5, 4, 2, 1, 3, 1, 5, 4, 2, 1, 3, 1]
          },
          {
            name: '低风险',
            type: 'bar',
            stack: 'risk',
            data: [1, 1, 6, 2, 0, 0, 0, 0, 3, 1, 0, 2, 1, 0]
          }
        ]
      }
      this.echart.setOption(option)
    }
  },
  mounted() {
    this.echart = echarts.init(this.$refs.echart)
    this.refresh()
  }
}
</script>
<style scoped>
.line-chart {
  /* width: 200px; */
  height: 220px;
}
</style>
src/views/management/evaluate/component/RiskCount.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,84 @@
<template>
  <el-row style="align-items: end; gap: 8px">
    <div class="tag">
      <div>
        <span class="num-big">10</span>
        <span class="num-small red">
          24%
          <el-icon>
            <CaretTop />
          </el-icon>
        </span>
      </div>
      <div class="statistic-footer red">
        <span>高风险</span>
      </div>
    </div>
    <div class="tag">
      <div>
        <span style="font-size: 20px">12</span>
        <span class="num-small yellow">
          24%
          <el-icon>
            <CaretTop />
          </el-icon>
        </span>
      </div>
      <div class="statistic-footer yellow">
        <span>中风险</span>
      </div>
    </div>
    <div class="tag">
      <div>
        <span style="font-size: 20px">5</span>
        <span class="num-small green">
          48%
          <el-icon>
            <CaretTop />
          </el-icon>
        </span>
      </div>
      <div class="statistic-footer green">
        <span>低风险</span>
      </div>
    </div>
  </el-row>
</template>
<script></script>
<style scoped>
.tag {
  display: flex;
  flex-direction: column;
}
.num-big {
  font-size: 36px;
}
.num-small {
  font-size: 12px;
}
.statistic-footer {
  /* background-color: #ffd100; */
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  font-size: 12px;
  color: var(--el-text-color-regular);
  /* margin-top: 16px; */
}
.green {
  color: #67c23a;
}
.red {
  color: #f56c6c;
}
.yellow {
  color: #e6a23c;
}
</style>
src/views/monitor/DustMonitor.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,4 @@
<template>
  <div class="border-r-small">在线监测</div>
</template>
<script></script>
src/views/visualization/SubtaskVisual.vue
@@ -1,8 +1,26 @@
<template>
  <el-scrollbar :height="mapHeight">
  <el-scrollbar v-if="mapStore.focusMarker" :height="mapHeight">
    <el-card class="p-events-auto wrapper">
      <div>{{ subtask.name }}</div>
      <el-timeline style="max-width: 600px">
      <div class="font-small">{{ scene.name }}</div>
      <el-divider></el-divider>
      <div class="font-small">状态:{{ subtask.status }}</div>
      <div class="font-small">计划:{{ $fm.formatYMD(subtask.planstarttime) }}</div>
      <div v-if="subtask.status != '未执行'" class="font-small">
        <span>执行:{{ $fm.formatH(subtask.executionstarttime) }}</span>
        <span> - </span>
        <span>{{ $fm.formatH(subtask.executionendtime) }}</span>
      </div>
      <div class="font-small">问题:</div>
      <problem-item
        v-for="(item, i) in problemList"
        :key="item.guid"
        :index="i + 1"
        :problem="item"
      ></problem-item>
      <!-- <div v-for="item in problemList" :key="item.guid">
        {{ item.problemname }}
      </div> -->
      <!-- <el-timeline style="max-width: 600px">
        <el-timeline-item
          v-for="(activity, index) in activities"
          :key="index"
@@ -14,13 +32,18 @@
        >
          {{ activity.content }}
        </el-timeline-item>
      </el-timeline>
      </el-timeline> -->
    </el-card>
  </el-scrollbar>
</template>
<script>
import { inject } from 'vue'
import { useMapStore } from '@/stores/map.js'
import { mapStores } from 'pinia'
import problemApi from '@/api/fysp/problemApi.js'
/**
 * å…·ä½“巡查任务可视化
 * åŒ…括地图定位信息展示、巡查任务全流程平铺展示
@@ -33,53 +56,80 @@
    return { height, mapHeight }
  },
  props: {
    subtask: {
      type: Object,
      default: () => {
        return {
          guid: 'SMuheEkjswioSn7A',
          name: '中科生态数字港项目巡查中科生态数字港项目巡查',
          district: '金山区',
          planTime: '2024-06-04',
          startTime: '2024-06-04 13:31:26',
          endTime: '2024-06-04 13:33:37',
          userName: '朱正强',
          status: '已结束',
          total: 4,
          checked: 2
        }
      }
    }
    // subtask: {
    //   type: Object,
    //   default: () => {
    //     return {
    //       guid: 'SMuheEkjswioSn7A',
    //       name: '中科生态数字港项目巡查中科生态数字港项目巡查',
    //       district: '金山区',
    //       planTime: '2024-06-04',
    //       startTime: '2024-06-04 13:31:26',
    //       endTime: '2024-06-04 13:33:37',
    //       userName: '朱正强',
    //       status: '已结束',
    //       total: 4,
    //       checked: 2
    //     }
    //   }
    // }
  },
  data() {
    return {
      activities: [
        {
          content: '任务创建',
          timestamp: '2024-06-04 08:00',
          running: false
        },
        {
          content: '开始巡查',
          timestamp: '2024-06-04 09:00',
          running: false
        },
        {
          content: '结束巡查',
          timestamp: '2024-06-04 09:15',
          running: false
        },
        {
          content: '完成问题审核',
          timestamp: '2024-06-04 10:15',
          running: false
        },
        {
          content: '问题整改中...',
          timestamp: '2024-06-04 10:15',
          running: true
        }
      ]
      // activities: [
      //   {
      //     content: '任务创建',
      //     timestamp: '2024-06-04 08:00',
      //     running: false
      //   },
      //   {
      //     content: '开始巡查',
      //     timestamp: '2024-06-04 09:00',
      //     running: false
      //   },
      //   {
      //     content: '结束巡查',
      //     timestamp: '2024-06-04 09:15',
      //     running: false
      //   },
      //   {
      //     content: '完成问题审核',
      //     timestamp: '2024-06-04 10:15',
      //     running: false
      //   },
      //   {
      //     content: '问题整改中...',
      //     timestamp: '2024-06-04 10:15',
      //     running: true
      //   }
      // ]
      problemList: []
    }
  },
  computed: {
    ...mapStores(useMapStore),
    subtask() {
      return this.mapStore.focusMarker ? this.mapStore.focusMarker.subtask : {}
    },
    scene() {
      return this.mapStore.focusMarker ? this.mapStore.focusMarker.scene : {}
    },
    inspection() {
      return this.mapStore.focusMarker ? this.mapStore.focusMarker.inspection : {}
    }
  },
  watch: {
    subtask(nV, oV) {
      if (nV != oV) {
        this.fetchProblem(nV.stguid)
      }
    }
  },
  methods: {
    fetchProblem(stguid) {
      problemApi.fetchProblems(stguid).then((res) => {
        this.problemList = res
      })
    }
  }
}
@@ -92,4 +142,8 @@
  right: 0;
  /* background-color: wheat; */
}
.el-card {
  --el-card-padding: 8px;
}
</style>
src/views/visualization/SupervisionVisual.vue
@@ -1,8 +1,18 @@
<template>
  <el-row>
    <div class="p-events-auto">
      <OptionLocation :level="3" :width="170" v-model="locations"></OptionLocation>
      <OptionSceneType :type="2" :width="120" v-model="sceneType"></OptionSceneType>
      <OptionLocation
        :level="3"
        :width="170"
        :initValue="false"
        v-model="locations"
      ></OptionLocation>
      <OptionSceneType
        :type="2"
        :width="120"
        :initValue="false"
        v-model="sceneType"
      ></OptionSceneType>
      <OptionTime v-model="time"></OptionTime>
    </div>
  </el-row>
@@ -30,8 +40,18 @@
  props: {},
  data() {
    return {
      locations: {},
      sceneType: {},
      locations: {
        pCode: '31',
        pName: '上海市',
        cCode: '3100',
        cName: '上海市',
        dCode: '310106',
        dName: '静安区'
      },
      sceneType: {
        label: '工地',
        value: '1'
      },
      time: ''
    }
  },
src/views/visualization/VisualizationView.vue
@@ -2,11 +2,11 @@
  <!-- <el-row class="wrapper"> å¯è§†åŒ– </el-row> -->
  <BaseMap></BaseMap>
  <el-row class="overlay-container" :style="height">
    <el-col :span="18">
    <el-col :span="14">
      <SupervisionVisual></SupervisionVisual>
    </el-col>
    <el-col :span="6">
      <!-- <SubtaskVisual></SubtaskVisual> -->
    <el-col :span="10">
      <SubtaskVisual></SubtaskVisual>
    </el-col>
  </el-row>
</template>