riku
2024-07-08 8756117a473facf0bf64c9e28f821b52e46cce85
完善问题整改跟踪模块
已修改14个文件
已删除1个文件
已添加8个文件
837 ■■■■ 文件已修改
index.html 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/fysp/taskApi.js 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/styles/element/index.scss 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components.d.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/stores/area.js 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/css-util.js 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/resize-observer.js 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inspection/JointEnforcement.vue 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inspection/ProblemTrack.vue 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inspection/ReInspectionView.vue 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inspection/SelfInspection.vue 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inspection/problem/ProblemTrack.vue 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inspection/problem/component/ProblemSummary.vue 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inspection/problem/component/ProblemTable.vue 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/main/MonitorView.vue 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/management/EvaluateSummary.vue 39 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/management/ManagementView.vue 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/management/StatisticView.vue 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/management/TaskStats.vue 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/management/TaskSummary.vue 165 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/visualization/SupervisionVisual.vue 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/visualization/VisualizationView.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
index.html
@@ -1,5 +1,5 @@
<!doctype html>
<html lang="en">
<html lang="en" class="dark">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
src/api/fysp/taskApi.js
@@ -34,7 +34,7 @@
  /**
   * èŽ·å–å­ä»»åŠ¡ç»Ÿè®¡ä¿¡æ¯
   */
  fetchSubtaskSummaryArea(area) {
  fetchTaskProgress(area) {
    return $fysp.post('subtask/summary/area', area).then((res) => res.data)
  },
@@ -49,5 +49,14 @@
        }
      })
      .then((res) => res.data)
  },
  /**
   * èŽ·å–å·¡æŸ¥ä»»åŠ¡é—®é¢˜ç»Ÿè®¡ä¿¡æ¯
   * @param {Object} area
   * @returns
   */
  fetchSubtaskSummaryByArea(area) {
    return $fysp.post('subtask/summary/area/problem', area).then((res) => res.data)
  }
}
src/assets/styles/element/index.scss
@@ -5,3 +5,11 @@
//     )
//   )
// );
@forward 'element-plus/theme-chalk/src/dark/var.scss' with (
  $bg-color: (
    'page': #ffffffa9,
    '': #122b54a9,
    'overlay': #122b54a9
  )
);
src/components.d.ts
@@ -11,17 +11,21 @@
    copy: typeof import('./components/search/OptionLocation copy.vue')['default']
    CoreHeader: typeof import('./components/core/CoreHeader.vue')['default']
    ElButton: typeof import('element-plus/es')['ElButton']
    ElCalendar: typeof import('element-plus/es')['ElCalendar']
    ElCard: typeof import('element-plus/es')['ElCard']
    ElCascader: typeof import('element-plus/es')['ElCascader']
    ElCol: typeof import('element-plus/es')['ElCol']
    ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
    ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
    ElFormItem: typeof import('element-plus/es')['ElFormItem']
    ElIcon: typeof import('element-plus/es')['ElIcon']
    ElLink: typeof import('element-plus/es')['ElLink']
    ElOption: typeof import('element-plus/es')['ElOption']
    ElProgress: typeof import('element-plus/es')['ElProgress']
    ElRow: typeof import('element-plus/es')['ElRow']
    ElScorllbar: typeof import('element-plus/es')['ElScorllbar']
    ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
    ElSegmented: typeof import('element-plus/es')['ElSegmented']
    ElSelect: typeof import('element-plus/es')['ElSelect']
    ElStatistic: typeof import('element-plus/es')['ElStatistic']
    ElTable: typeof import('element-plus/es')['ElTable']
src/main.js
@@ -1,6 +1,7 @@
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import 'element-plus/theme-chalk/src/dark/css-vars.scss'
import App from './App.vue'
import router from './router'
src/stores/area.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,43 @@
// åŒºåŸŸç­›é€‰çš„逻辑管理
import { defineStore } from 'pinia'
import dayjs from 'dayjs'
export const useAreaStore = defineStore('area', {
  state: () => {
    return {
      area: {
        provincecode: undefined,
        provincename: undefined,
        citycode: undefined,
        cityname: undefined,
        districtcode: undefined,
        districtname: undefined,
        starttime: undefined,
        endtime: undefined,
        scensetypeid: undefined
      }
    }
  },
  actions: {
    // è®¾ç½®è¡Œæ”¿åŒºåˆ’信息
    setLocation(location) {
      this.area.provincecode = location.pCode
      this.area.provincename = location.pName
      this.area.citycode = location.cCode
      this.area.cityname = location.cName
      this.area.districtcode = location.dCode
      this.area.districtname = location.dName
    },
    // è®¾ç½®æ—¶é—´ä¸ºç»™å®šæ—¶é—´å¯¹åº”当日的头尾
    setTimeOneDay(time) {
      const d = time ? dayjs(time) : dayjs()
      this.area.starttime = d.startOf('day').format('YYYY-MM-DD HH:mm:ss')
      this.area.endtime = d.endOf('day').format('YYYY-MM-DD HH:mm:ss')
    },
    // è®¾ç½®åœºæ™¯ç±»åž‹
    setSceneType(t) {
      this.area.scensetypeid = t
    }
  }
})
src/utils/css-util.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,21 @@
/**
 * æå–css中带有calc函数的表达式的参数部分
 * @param {String} str css中带有calc函数的表达式
 */
function unCalc(str) {
  if (str.startsWith('calc(')) {
    let _str = str.replace('calc(', '')
    _str = _str.replace(/\)/g, (match, offset, string) => {
      if (offset === string.lastIndexOf(match)) {
        return ''
      } else {
        return match
      }
    })
    return _str
  } else {
    return str
  }
}
export { unCalc }
src/utils/resize-observer.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,32 @@
//对于对象的引用是弱引用,这意味着在没有其他引用存在时垃圾回收能正确进行。在取消引用时,不需要手动删除元素,因为它们会自动被垃圾回收。
const map = new WeakMap()
// ResizeObserver是一个构造函数,用于监听元素的变化,当元素的尺寸发生变化时,会触发回调函数。
const divs = new ResizeObserver((entries) => {
  // entries是一个数组,包含所有被观察的元素的信息
  for (const entry of entries) {
    // å°†å…ƒç´ å’Œå›žè°ƒå‡½æ•°å–出
    const handler = map.get(entry.target)
    // å¦‚果回调函数存在,则调用回调函数
    if (handler) {
      handler({
        width: Math.ceil(entry.borderBoxSize[0].inlineSize), //元素的宽度
        height: Math.ceil(entry.borderBoxSize[0].blockSize) //元素的高度
      })
    }
  }
})
//获取使用指令的div的宽高.e.width和e.height
export const vResize = {
  mounted(el, binding) {
    // å°†å…ƒç´ å’Œå›žè°ƒå‡½æ•°å­˜å…¥map中
    map.set(el, binding)
    // å¼€å§‹è§‚察元素
    divs.observe(el)
  },
  unmounted(el) {
    // åœæ­¢è§‚察元素
    divs.unobserve(el)
  }
}
src/views/inspection/JointEnforcement.vue
@@ -1,6 +1,9 @@
<template>
  <div class="border-r-small" style="height: 200px">
  <div class="border-r-small">
    <div class="font-large">联合执法</div>
    <el-scrollbar height="300px">
      <el-calendar v-model="value" />
    </el-scrollbar>
  </div>
</template>
@@ -8,7 +11,7 @@
export default {
  data() {
    return {
      tasks: []
      value: new Date()
    }
  },
  watch: {},
src/views/inspection/ProblemTrack.vue
ÎļþÒÑɾ³ý
src/views/inspection/ReInspectionView.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,71 @@
<template>
  <div class="wrapper">
    <div>复核巡查</div>
    <el-table
      :data="tableData"
      v-loading="loading"
      table-layout="fixed"
      :row-class-name="tableRowClassName"
      :height="tableHeight"
      size="small"
    >
      <el-table-column
        fixed="left"
        prop="name"
        :show-overflow-tooltip="true"
        label="名称"
        width="200"
      >
      </el-table-column>
      <el-table-column prop="planTime" :show-overflow-tooltip="true" label="时间">
      </el-table-column>
      <!-- <el-table-column prop="score" :show-overflow-tooltip="true" label="评分" width="60">
      </el-table-column>
      <el-table-column prop="risk" :show-overflow-tooltip="true" label="风险" width="60">
      </el-table-column> -->
      <el-table-column prop="recheck" :show-overflow-tooltip="true" label="复核" width="60">
      </el-table-column>
    </el-table>
  </div>
</template>
<script>
/**
 * çŽ°åœºå·¡æŸ¥å®žæ—¶è·Ÿè¸ª
 */
export default {
  data() {
    return {
      tableData: [],
      tableHeight: 'calc(var(--fy-body-height) / 3 - 27px)'
    }
  },
  mounted() {
    let i = 0
    while (i < 20) {
      this.tableData.push({
        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,
        score: 90,
        risk: '高',
        recheck: 1
      })
      i++
    }
  }
}
</script>
<style scoped>
.wrapper {
  /* height: calc(var(--fy-body-height) / 3); */
}
</style>
src/views/inspection/SelfInspection.vue
@@ -1,6 +1,30 @@
<template>
  <div class="border-r-small" style="height: 200px">
  <div class="border-r-small">
    <div class="font-large">应急自巡查</div>
    <el-text>本月共发布4次自巡查,已完成0次,未完成4次</el-text>
    <el-table
      :data="tableData"
      v-loading="loading"
      table-layout="fixed"
      :row-class-name="tableRowClassName"
      :height="tableHeight"
      size="small"
    >
      <el-table-column
        fixed="left"
        prop="name"
        :show-overflow-tooltip="true"
        label="企业"
        width="200"
      >
      </el-table-column>
      <el-table-column prop="planTime" :show-overflow-tooltip="true" label="发布时间">
      </el-table-column>
      <el-table-column prop="complete" :show-overflow-tooltip="true" label="完成情况">
      </el-table-column>
      <!-- <el-table-column prop="recheck" :show-overflow-tooltip="true" label="复核" width="60">
      </el-table-column> -->
    </el-table>
  </div>
</template>
@@ -8,12 +32,26 @@
export default {
  data() {
    return {
      tasks: []
      tableData: []
    }
  },
  watch: {},
  methods: {},
  mounted() {}
  mounted() {
    let i = 0
    while (i < 4) {
      this.tableData.push({
        guid: 'SMuheEkjswioSn7A',
        name: '中科生态数字港项目',
        district: '金山区',
        planTime: '2024-06-04',
        startTime: '2024-06-04 13:31:26',
        endTime: '2024-06-04 13:33:37',
        complete: '0/6'
      })
      i++
    }
  }
}
</script>
src/views/inspection/problem/ProblemTrack.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,59 @@
<template>
  <div class="border-r-small">
    <div class="font-large">问题整改跟踪</div>
    <div>
      <ProblemSummary :data="subtaskList"></ProblemSummary>
      <ProblemTable :data="subtaskList"></ProblemTable>
    </div>
  </div>
</template>
<script>
import { useAreaStore } from '@/stores/area.js'
import { mapStores } from 'pinia'
import ProblemTable from './component/ProblemTable.vue'
import ProblemSummary from './component/ProblemSummary.vue'
import taskApi from '@/api/fysp/taskApi.js'
export default {
  components: { ProblemSummary, ProblemTable },
  data() {
    return {
      subtaskList: []
    }
  },
  watch: {},
  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
      })
    }
  },
  mounted() {
    this.fetchSubtask()
  }
}
</script>
<style scoped>
.text {
  background-color: aliceblue;
}
</style>
src/views/inspection/problem/component/ProblemSummary.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,31 @@
<template>
  <div>
    é—®é¢˜æ•°: {{ summary.proNum }},整改数: {{ summary.changeNum }},整改率: {{ summary.changePer }}
  </div>
</template>
<script setup>
import { computed, ref } from 'vue'
const props = defineProps({
  data: {
    type: Array
  },
  loading: Boolean
})
const summary = computed(() => {
  let proNum = 0,
    changeNum = 0,
    changePer = '/'
  props.data.forEach((d) => {
    proNum += d.proNum
    changeNum += d.changeNum
  })
  if (proNum > 0) {
    changePer = Math.round((changeNum / proNum) * 100) / 100 + '%'
  }
  return { proNum, changeNum, changePer }
})
</script>
src/views/inspection/problem/component/ProblemTable.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,87 @@
<template>
  <el-table
    :data="showTableData"
    v-loading="loading"
    table-layout="fixed"
    :row-class-name="tableRowClassName"
    :height="tableHeight"
    size="small"
  >
    <el-table-column type="index" label="" width="30"> </el-table-column>
    <el-table-column prop="scene.name" :show-overflow-tooltip="true" label="名称" width="150">
    </el-table-column>
    <el-table-column prop="scene.location" :show-overflow-tooltip="true" label="地址">
    </el-table-column>
    <el-table-column prop="proNum" :show-overflow-tooltip="true" label="问题" width="41">
    </el-table-column>
    <el-table-column prop="changeNum" :show-overflow-tooltip="true" label="整改" width="41">
    </el-table-column>
    <el-table-column :show-overflow-tooltip="true" label="整改率" width="54">
      <template #default="{ row }">
        {{ calPer(row.proNum, row.changeNum) }}
      </template>
    </el-table-column>
    <el-table-column prop="updateTime" :show-overflow-tooltip="true" label="时间">
      <template #default="{ row }">
        {{ $fm.formatH(row.updateTime) }}
      </template>
    </el-table-column>
  </el-table>
  <div class="btn-more font-small">
    <el-link type="primary" @click="showMore = !showMore">查看更多</el-link>
  </div>
</template>
<script setup>
import { computed, ref } from 'vue'
import dayjs from 'dayjs'
const props = defineProps({
  data: {
    type: Array
  },
  loading: Boolean
})
const showMore = ref(false)
const tableData = computed(() => {
  const l = props.data.map((value) => {
    const time = value.subtask.executionendtime
      ? value.subtask.executionendtime
      : value.subtask.executionstarttime
    value.updateTime = time
    return value
  })
  return l.sort((a, b) => {
    return dayjs(b.updateTime) - dayjs(a.updateTime)
  })
  // return l
})
const showTableData = computed(() => {
  if (showMore.value) {
    return tableData.value
  } else {
    return tableData.value.slice(0, 3)
  }
})
/**
 * è®¡ç®—整改率
 * @param {Number} p é—®é¢˜æ•°
 * @param {Number} c æ•´æ”¹æ•°
 */
function calPer(p, c) {
  if (p == 0) {
    return '/'
  } else {
    return Math.round((c / p) * 100) / 100 + '%'
  }
}
</script>
<style scoped>
.btn-more {
  text-align: center;
}
</style>
src/views/main/MonitorView.vue
@@ -1,11 +1,11 @@
<template>
  <el-row>
    <el-col :span="6" class="page-right">
      <el-scrollbar height="var(--fy-body-height)">
        <ManagementView></ManagementView>
      </el-scrollbar>
    <el-col :span="7" class="page-right">
      <!-- <el-scrollbar height="var(--fy-body-height)"> -->
      <ManagementView></ManagementView>
      <!-- </el-scrollbar> -->
    </el-col>
    <el-col :span="12">
    <el-col :span="10">
      <el-scrollbar class="page-left-top">
        <VisualizationView></VisualizationView>
      </el-scrollbar>
@@ -13,20 +13,32 @@
        <InspectionView></InspectionView>
      </el-scrollbar>
    </el-col>
    <el-col :span="6" class="page-right">
    <el-col :span="7" class="page-right">
      <el-scrollbar height="var(--fy-body-height)">
        <ManagementView></ManagementView>
        <StatisticView></StatisticView>
      </el-scrollbar>
    </el-col>
  </el-row>
</template>
<script setup>
import { provide, ref } from 'vue'
import InspectionView from '@/views/inspection/InspectionView.vue'
import ManagementView from '@/views/management/ManagementView.vue'
import StatisticView from '@/views/management/StatisticView.vue'
import VisualizationView from '@/views/visualization/VisualizationView.vue'
import { useAreaStore } from '@/stores/area.js'
import { provide } from 'vue'
const windowHeight = ref(window.innerHeight)
const areaStore = useAreaStore()
areaStore.setTimeOneDay()
// const headerHeight = computed(()=>{
//   return
// })
// fetch('../../assets/styles/layout.scss').then((res) => {
//   console.log(res.text())
// })
provide('mapHeight', 'calc(var(--fy-body-height) / 3 * 2)')
</script>
src/views/management/EvaluateSummary.vue
@@ -1,7 +1,7 @@
<template>
  <div class="border-r-small">
    <div class="font-large">风险评估</div>
    <el-row justify="space-evenly">
    <div ref="titleRef" class="font-large">综合风险评估</div>
    <el-row ref="statisticRef" justify="space-evenly">
      <el-statistic title="高风险" :value="10"> </el-statistic>
      <el-statistic title="中风险" :value="10"> </el-statistic>
      <el-statistic title="低风险" :value="10"> </el-statistic>
@@ -26,23 +26,50 @@
      </el-table-column>
      <el-table-column prop="score" :show-overflow-tooltip="true" label="评分" width="60">
      </el-table-column>
      <el-table-column prop="score" :show-overflow-tooltip="true" label="风险" width="60">
      <el-table-column prop="risk" :show-overflow-tooltip="true" label="风险" width="60">
      </el-table-column>
      <!-- <el-table-column prop="recheck" :show-overflow-tooltip="true" label="复核" width="60">
      </el-table-column> -->
    </el-table>
  </div>
</template>
<script>
import { unCalc } from '@/utils/css-util'
/**
 * å¯¹å®Œæˆçš„任务进行评估风险,显示高风险场景,显示复核的场景的情况
 */
export default {
  props: {
    height: {
      type: String,
      default: '200'
    }
  },
  data() {
    return {
      tableData: []
      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 + h2
      const r = `calc(${unCalc(this.height)} - ${h}px)`
      return r
    }
  },
  mounted() {
    this.tableHeight = this.calcTableHeight()
    let i = 0
    while (i < 20) {
      this.tableData.push({
@@ -56,7 +83,9 @@
        status: '已结束',
        total: 4,
        checked: 2,
        score: 90
        score: 90,
        risk: '高',
        recheck: 1
      })
      i++
    }
src/views/management/ManagementView.vue
@@ -1,14 +1,56 @@
<template>
  <!-- <el-row> ç»Ÿè®¡ç®¡ç† </el-row> -->
  <TaskStats></TaskStats>
  <EvaluateSummary></EvaluateSummary>
  <TaskSummary></TaskSummary>
  <ProblemTrack ref="statusRef"></ProblemTrack>
  <!-- <TaskStats ref="statusRef"></TaskStats> -->
  <EvaluateSummary :height="height"></EvaluateSummary>
  <!-- <TaskSummary ref="summaryRef"></TaskSummary> -->
  <ReInspectionView ref="summaryRef"></ReInspectionView>
</template>
<script setup>
<script>
import TaskStats from '@/views/management/TaskStats.vue'
import TaskSummary from '@/views/management/TaskSummary.vue'
import EvaluateSummary from '@/views/management/EvaluateSummary.vue'
import ReInspectionView from '@/views/inspection/ReInspectionView.vue'
import ProblemTrack from '@/views/inspection/problem/ProblemTrack.vue'
import { vResize } from '@/utils/resize-observer'
export default {
  components: { TaskStats, TaskSummary, EvaluateSummary, ReInspectionView, ProblemTrack },
  data() {
    return {
      // height: '500px',
      statusHeight: 200,
      summaryHeight: 200
    }
  },
  computed: {
    height() {
      const h = this.statusHeight + this.summaryHeight + 5
      return `calc(var(--fy-body-height) - ${h}px)`
    }
  },
  methods: {
    calcHeight() {
      const h1 = this.$refs.statusRef.$el.offsetHeight
      const h2 = this.$refs.summaryRef.$el.offsetHeight
      const h = h1 + h2
      return `calc(var(--fy-body-height) - ${h}px)`
    }
  },
  mounted() {
    vResize.mounted(this.$refs.statusRef.$el, ({ height }) => {
      this.statusHeight = height
    })
    vResize.mounted(this.$refs.summaryRef.$el, ({ height }) => {
      this.summaryHeight = height
    })
  },
  unmounted() {
    vResize.unmounted(this.$refs.statusRef.$el)
    vResize.unmounted(this.$refs.summaryRef.$el)
  }
}
</script>
<style scoped></style>
src/views/management/StatisticView.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,52 @@
<template>
  <!-- <el-row> ç»Ÿè®¡ç®¡ç† </el-row> -->
  <SelfInspection></SelfInspection>
  <JointEnforcement></JointEnforcement>
  <TaskSummary></TaskSummary>
</template>
<script>
import SelfInspection from '@/views/inspection/SelfInspection.vue'
import JointEnforcement from '@/views/inspection/JointEnforcement.vue'
import TaskSummary from '@/views/management/TaskSummary.vue'
import { vResize } from '@/utils/resize-observer'
export default {
  components: { SelfInspection, JointEnforcement, TaskSummary },
  data() {
    return {
      // height: '500px',
      statusHeight: 200,
      summaryHeight: 200
    }
  },
  computed: {
    height() {
      const h = this.statusHeight + this.summaryHeight
      return `calc(var(--fy-body-height) - ${h}px)`
    }
  },
  methods: {
    calcHeight() {
      const h1 = this.$refs.statusRef.$el.offsetHeight
      const h2 = this.$refs.summaryRef.$el.offsetHeight
      const h = h1 + h2
      return `calc(var(--fy-body-height) - ${h}px)`
    }
  },
  mounted() {
    // vResize.mounted(this.$refs.statusRef.$el, ({ height }) => {
    //   this.statusHeight = height
    // })
    // vResize.mounted(this.$refs.summaryRef.$el, ({ height }) => {
    //   this.summaryHeight = height
    // })
  },
  unmounted() {
    // vResize.unmounted(this.$refs.statusRef.$el)
    // vResize.unmounted(this.$refs.summaryRef.$el)
  }
}
</script>
<style scoped></style>
src/views/management/TaskStats.vue
@@ -29,6 +29,9 @@
 */
export default {
  components: { SelfInspection, JointEnforcement },
  props: {
    height: String
  },
  data() {
    return {
      tasks: []
src/views/management/TaskSummary.vue
@@ -1,26 +1,147 @@
<template>
  <el-row> å·¡æŸ¥æ±‡æ€» </el-row>
  <el-row>
    <el-col :span="8">
      <TaskSummaryItem title="今日汇总"></TaskSummaryItem>
    </el-col>
    <el-col :span="8">
      <TaskSummaryItem title="周度汇总"></TaskSummaryItem>
    </el-col>
    <el-col :span="8">
      <TaskSummaryItem title="月度汇总"></TaskSummaryItem>
    </el-col>
  </el-row>
  <el-row>
    <el-col :span="12">
      <TaskSummaryItem title="季度汇总"></TaskSummaryItem>
    </el-col>
    <el-col :span="12">
      <TaskSummaryItem title="年度汇总"></TaskSummaryItem>
    </el-col>
  </el-row>
  <div class="border-r-small">
    <el-row> å·¡æŸ¥æ±‡æ€» </el-row>
    <el-segmented v-model="value" :options="options" />
    <div><el-text tag="i"> è¯„ä¼° </el-text></div>
    <el-row justify="space-evenly">
      <div>
        <el-statistic title="总计" :value="10"> </el-statistic>
        <div class="statistic-footer">
          <div class="footer-item">
            <span>对比昨日</span>
            <span class="green">
              24%
              <el-icon>
                <CaretTop />
              </el-icon>
            </span>
          </div>
        </div>
      </div>
      <el-statistic title="高风险" :value="2" :value-style="styleRed"> </el-statistic>
      <el-statistic title="中风险" :value="6" :value-style="styleYellow"> </el-statistic>
      <el-statistic title="低风险" :value="2" :value-style="styleGreen"> </el-statistic>
    </el-row>
    <div><el-text tag="i"> å¤æ ¸ </el-text></div>
    <el-row justify="space-evenly">
      <div>
        <el-statistic title="需复核" :value="2"> </el-statistic>
        <div class="statistic-footer">
          <div class="footer-item">
            <span>对比昨日</span>
            <span class="green">
              24%
              <el-icon>
                <CaretTop />
              </el-icon>
            </span>
          </div>
        </div>
      </div>
      <el-statistic title="已完成" :value="2" :value-style="styleGreen"> </el-statistic>
    </el-row>
    <div><el-text tag="i"> é—®é¢˜ </el-text></div>
    <el-row justify="space-evenly">
      <div>
        <el-statistic title="总计" :value="10"> </el-statistic>
        <div class="statistic-footer">
          <div class="footer-item">
            <span>对比昨日</span>
            <span class="green">
              24%
              <el-icon>
                <CaretTop />
              </el-icon>
            </span>
          </div>
        </div>
      </div>
      <el-statistic title="待审核" :value="2" :value-style="styleRed"> </el-statistic>
      <el-statistic title="已审核" :value="6" :value-style="styleYellow"> </el-statistic>
      <el-statistic title="待整改" :value="2" :value-style="styleGreen"> </el-statistic>
      <el-statistic title="已整改" :value="2" :value-style="styleGreen"> </el-statistic>
      <el-statistic title="待确认" :value="2" :value-style="styleGreen"> </el-statistic>
    </el-row>
    <!-- <el-row>
      <el-col :span="8">
        <TaskSummaryItem title="今日汇总"></TaskSummaryItem>
      </el-col>
      <el-col :span="8">
        <TaskSummaryItem title="周度汇总"></TaskSummaryItem>
      </el-col>
      <el-col :span="8">
        <TaskSummaryItem title="月度汇总"></TaskSummaryItem>
      </el-col>
    </el-row>
    <el-row>
      <el-col :span="12">
        <TaskSummaryItem title="季度汇总"></TaskSummaryItem>
      </el-col>
      <el-col :span="12">
        <TaskSummaryItem title="年度汇总"></TaskSummaryItem>
      </el-col>
    </el-row> -->
  </div>
</template>
<script setup></script>
<script>
export default {
  props: {
    height: String
  },
  emits: ['update:height'],
  data() {
    return {
      value: '今日汇总',
      options: ['今日汇总', '周度汇总', '月度汇总', '季度汇总', '年度汇总'],
      styleRed: 'color:var(--el-color-danger);',
      styleYellow: 'color:var(--el-color-warning);',
      styleGreen: 'color:var(--el-color-success);'
    }
  },
  mounted() {}
}
</script>
<style scoped></style>
<style scoped>
.el-segmented {
  --el-segmented-item-selected-color: var(--el-text-color-primary);
  --el-segmented-item-selected-bg-color: #ffd100;
  --el-border-radius-base: 16px;
}
.el-statistic {
  --el-statistic-content-font-size: var(--el-font-size-base);
  /* background-color: aliceblue; */
}
.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; */
}
.statistic-footer .footer-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.statistic-footer .footer-item span:last-child {
  display: inline-flex;
  align-items: center;
  margin-left: 4px;
}
.green {
  color: var(--el-color-success);
}
.red {
  color: var(--el-color-error);
}
</style>
src/views/visualization/SupervisionVisual.vue
@@ -10,6 +10,9 @@
<script>
import { inject } from 'vue'
import { useAreaStore } from '@/stores/area.js'
import { mapStores } from 'pinia'
import taskApi from '@/api/fysp/taskApi.js'
import marks from '@/utils/map/marks.js'
import scene_1 from '@/assets/icon/scene_1.png'
@@ -33,23 +36,28 @@
    }
  },
  computed: {
    area() {
      return {
        provincecode: this.locations.pCode,
        provincename: this.locations.pName,
        citycode: this.locations.cCode,
        cityname: this.locations.cName,
        districtcode: this.locations.dCode,
        districtname: this.locations.dName,
        starttime: this.$fm.formatYMDH(this.time),
        scensetypeid: this.sceneType.value
      }
    }
    ...mapStores(useAreaStore)
    // area() {
    //   return {
    //     provincecode: this.locations.pCode,
    //     provincename: this.locations.pName,
    //     citycode: this.locations.cCode,
    //     cityname: this.locations.cName,
    //     districtcode: this.locations.dCode,
    //     districtname: this.locations.dName,
    //     starttime: this.$fm.formatYMDH(this.time),
    //     scensetypeid: this.sceneType.value
    //   }
    // }
  },
  methods: {
    // æŸ¥è¯¢
    fetchSubtaskSummaryArea() {
      return taskApi.fetchSubtaskSummaryArea(this.area).then((res) => {
    fetchTaskProgress() {
      this.areaStore.setLocation(this.locations)
      this.areaStore.setTimeOneDay(this.time)
      this.areaStore.setSceneType(this.sceneType.value)
      return taskApi.fetchTaskProgress(this.areaStore.area).then((res) => {
        let list = []
        res.data.forEach((e) => {
          list = list.concat(e.subTaskSummary)
@@ -62,7 +70,7 @@
    }
  },
  mounted() {
    this.fetchSubtaskSummaryArea()
    // this.fetchTaskProgress()
  }
}
</script>
src/views/visualization/VisualizationView.vue
@@ -6,7 +6,7 @@
      <SupervisionVisual></SupervisionVisual>
    </el-col>
    <el-col :span="6">
      <SubtaskVisual></SubtaskVisual>
      <!-- <SubtaskVisual></SubtaskVisual> -->
    </el-col>
  </el-row>
</template>