From ff82e86becbd200adabd2ce56fba1f6b3c6c37e1 Mon Sep 17 00:00:00 2001
From: Riku <risaku@163.com>
Date: 星期一, 23 六月 2025 23:10:49 +0800
Subject: [PATCH] 2025.6.23

---
 src/views/management/TaskSummary.vue |  494 ++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 414 insertions(+), 80 deletions(-)

diff --git a/src/views/management/TaskSummary.vue b/src/views/management/TaskSummary.vue
index 7334b97..1926d9f 100644
--- a/src/views/management/TaskSummary.vue
+++ b/src/views/management/TaskSummary.vue
@@ -1,95 +1,424 @@
 <template>
-  <BaseCard>
-    <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>
+  <BaseCard title="宸℃煡姹囨��">
+    <!-- <el-row> 宸℃煡姹囨�� </el-row> -->
+    <el-segmented v-model="value" :options="options" block />
+    <div v-show="value == '浠婃棩姹囨��'">
+      <div ref="echart1" class="bar-chart"></div>
+    </div>
+    <div v-show="value == '鏈懆姹囨��'">
+      <div ref="echart2" class="bar-chart"></div>
+    </div>
+    <div v-show="value == '涓婂懆姹囨��'">
+      <div ref="echart3" class="bar-chart"></div>
+    </div>
+    <div v-show="value == '鏈湀姹囨��'">
+      <div ref="echart4" class="bar-chart"></div>
+    </div>
   </BaseCard>
 </template>
 
-<script>
-export default {
-  props: {
-    height: String
-  },
-  emits: ['update:height'],
-  data() {
-    return {
-      value: '浠婃棩姹囨��',
-      options: ['浠婃棩姹囨��', '鍛ㄥ害姹囨��', '鏈堝害姹囨��', '瀛e害姹囨��', '骞村害姹囨��'],
-      styleRed: 'color:var(--el-color-danger);',
-      styleYellow: 'color:var(--el-color-warning);',
-      styleGreen: 'color:var(--el-color-success);'
+<script setup>
+/**
+ * 1. 鍖哄煙鍒嗙被缁熻鏇村姞鐏垫椿
+ */
+import * as echarts from 'echarts'
+import { ref, onMounted } from 'vue'
+import dayjs from 'dayjs'
+import taskApi from '@/api/fysp/taskApi.js'
+
+const props = defineProps({
+  height: String
+})
+
+const emits = defineEmits(['update:height'])
+
+const value = ref('鏈湀姹囨��')
+const options = ['浠婃棩姹囨��', '鏈懆姹囨��', '涓婂懆姹囨��', '鏈湀姹囨��']
+
+const subtaskToday = ref([])
+const subtaskWeek = ref([])
+const subtaskLastWeek = ref([])
+const subtaskMonth = ref([])
+
+const echart1 = ref()
+const echart2 = ref()
+const echart3 = ref()
+const echart4 = ref()
+let echartToday
+let echartWeek
+let echartLastWeek
+let echartMonth
+
+function getParams(type) {
+  const d = dayjs()
+  return {
+    starttime: d.startOf(type).format('YYYY-MM-DD HH:mm:ss'),
+    endtime: d.endOf(type).format('YYYY-MM-DD HH:mm:ss')
+  }
+}
+
+function fetchSubtaskToday() {
+  const area = getParams('day')
+  taskApi.fetchSubtaskSummaryByArea(area).then((res) => {
+    subtaskToday.value = res.data
+    const series = refreshChartData(res.data)
+    setOption(echartToday, series)
+  })
+}
+
+function fetchSubtaskThisWeek() {
+  const area = getParams('week')
+  // 淇敼鏃舵涓哄懆涓�鍒板懆鏃�
+  area.starttime = dayjs(area.starttime).add(1, 'day').format('YYYY-MM-DD HH:mm:ss')
+  area.endtime = dayjs(area.endtime).add(1, 'day').format('YYYY-MM-DD HH:mm:ss')
+  taskApi.fetchSubtaskSummaryByArea(area).then((res) => {
+    subtaskWeek.value = res.data
+    const series = refreshChartData(res.data)
+    setOption(echartWeek, series)
+  })
+}
+
+function fetchSubtaskLastWeek() {
+  const area = getParams('week')
+  // 淇敼鏃舵涓哄懆涓�鍒板懆鏃�
+  area.starttime = dayjs(area.starttime).add(-6, 'day').format('YYYY-MM-DD HH:mm:ss')
+  area.endtime = dayjs(area.endtime).add(-6, 'day').format('YYYY-MM-DD HH:mm:ss')
+  taskApi.fetchSubtaskSummaryByArea(area).then((res) => {
+    subtaskLastWeek.value = res.data
+    const series = refreshChartData(res.data)
+    setOption(echartLastWeek, series)
+  })
+}
+
+function fetchSubtaskThisMonth() {
+  const area = getParams('month')
+  taskApi.fetchSubtaskSummaryByArea(area).then((res) => {
+    subtaskMonth.value = res.data
+    const series = refreshChartData(res.data)
+    setOption(echartMonth, series)
+  })
+}
+
+onMounted(() => {
+  echartToday = echarts.init(echart1.value)
+  echartWeek = echarts.init(echart2.value)
+  echartLastWeek = echarts.init(echart3.value)
+  echartMonth = echarts.init(echart4.value)
+  fetchSubtaskToday()
+  fetchSubtaskThisWeek()
+  fetchSubtaskLastWeek()
+  fetchSubtaskThisMonth()
+})
+
+/**chart**********************************************************************/
+function setOption(echart, series) {
+  const option = {
+    textStyle: {
+      color: 'white'
+    },
+    legend: {
+      textStyle: {
+        color: 'white'
+      }
+    },
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'shadow'
+      }
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '3%',
+      containLabel: true
+    },
+    xAxis: [
+      {
+        type: 'value'
+      }
+    ],
+    yAxis: [
+      {
+        type: 'category',
+        data: ['澶嶆牳鏁�', '鏁存敼鏁�', '闂鏁�', '瀹屾垚閲�']
+      }
+    ],
+    series: series
+  }
+  echart.setOption(option)
+}
+
+function refreshChartData(dataList) {
+  // 浠诲姟閲忋�侀棶棰樻暟銆佹暣鏀规暟
+  // 浠诲姟閲�
+  const totalCount = {
+    numByTotal: {},
+    numByDistrict: {},
+    numByStreet: {},
+    numByScene: {},
+    numByUser: {}
+  }
+  // 闂鏁�
+  const proCount = {
+    numByTotal: {},
+    numByDistrict: {},
+    numByStreet: {},
+    numByScene: {},
+    numByUser: {}
+  }
+  // 鏁存敼鏁�
+  const changeCount = {
+    numByTotal: {},
+    numByDistrict: {},
+    numByStreet: {},
+    numByScene: {},
+    numByUser: {}
+  }
+  // 澶嶆牳鏁�
+  const reCheckCount = {
+    numByTotal: {},
+    numByDistrict: {},
+    numByStreet: {},
+    numByScene: {},
+    numByUser: {}
+  }
+  const historySceneId = []
+
+  dataList.forEach((d) => {
+    const tName = '鎬昏'
+    const dName = d.subtask.districtname
+    const townName = d.scene.townname
+    const sType = d.sceneType
+    const uName = d.subtask.deployerrealname
+
+    // 浠诲姟閲忔�昏
+    totalCount.numByTotal[tName] = totalCount.numByTotal[tName]
+      ? totalCount.numByTotal[tName] + 1
+      : 1
+    // 浠诲姟閲忓垎鍖哄幙
+    totalCount.numByDistrict[dName] = totalCount.numByDistrict[dName]
+      ? totalCount.numByDistrict[dName] + 1
+      : 1
+    // 浠诲姟閲忓垎琛楅晣
+    totalCount.numByStreet[townName] = totalCount.numByStreet[townName]
+      ? totalCount.numByStreet[townName] + 1
+      : 1
+    // 浠诲姟閲忓垎鍦烘櫙绫诲瀷
+    totalCount.numByScene[sType] = totalCount.numByScene[sType]
+      ? totalCount.numByScene[sType] + 1
+      : 1
+    // 浠诲姟閲忓垎鐢ㄦ埛
+    totalCount.numByUser[uName] = totalCount.numByUser[uName] ? totalCount.numByUser[uName] + 1 : 1
+
+    // 闂鏁版�昏
+    proCount.numByTotal[tName] = proCount.numByTotal[tName]
+      ? proCount.numByTotal[tName] + d.proCheckedNum
+      : d.proCheckedNum
+    // 闂鏁板垎鍖哄幙
+    proCount.numByDistrict[dName] = proCount.numByDistrict[dName]
+      ? proCount.numByDistrict[dName] + d.proCheckedNum
+      : d.proCheckedNum
+    // 闂鏁板垎琛楅晣
+    proCount.numByStreet[townName] = proCount.numByStreet[townName]
+      ? proCount.numByStreet[townName] + d.proCheckedNum
+      : d.proCheckedNum
+    // 闂鏁板垎鍦烘櫙绫诲瀷
+    proCount.numByScene[sType] = proCount.numByScene[sType]
+      ? proCount.numByScene[sType] + d.proCheckedNum
+      : d.proCheckedNum
+    // 闂鏁板垎鐢ㄦ埛
+    proCount.numByUser[uName] = proCount.numByUser[uName]
+      ? proCount.numByUser[uName] + d.proCheckedNum
+      : d.proCheckedNum
+
+    // 鏁存敼鏁版�昏
+    changeCount.numByTotal[tName] = changeCount.numByTotal[tName]
+      ? changeCount.numByTotal[tName] + d.changeCheckedNum
+      : d.changeCheckedNum
+    // 鏁存敼鏁板垎鍖哄幙
+    changeCount.numByDistrict[dName] = changeCount.numByDistrict[dName]
+      ? changeCount.numByDistrict[dName] + d.changeCheckedNum
+      : d.changeCheckedNum
+    // 鏁存敼鏁板垎琛楅晣
+    changeCount.numByStreet[townName] = changeCount.numByStreet[townName]
+      ? changeCount.numByStreet[townName] + d.changeCheckedNum
+      : d.changeCheckedNum
+    // 鏁存敼鏁板垎鍦烘櫙绫诲瀷
+    changeCount.numByScene[sType] = changeCount.numByScene[sType]
+      ? changeCount.numByScene[sType] + d.changeCheckedNum
+      : d.changeCheckedNum
+    // 鏁存敼鏁板垎鐢ㄦ埛
+    changeCount.numByUser[uName] = changeCount.numByUser[uName]
+      ? changeCount.numByUser[uName] + d.changeCheckedNum
+      : d.changeCheckedNum
+
+    if (historySceneId.length == 0) {
+      reCheckCount.numByTotal[tName] = 0
+      reCheckCount.numByDistrict[dName] = 0
+      reCheckCount.numByScene[sType] = 0
+      reCheckCount.numByUser[uName] = 0
+    } else if (historySceneId.indexOf(d.sceneId) != -1) {
+      // 澶嶆牳鏁版�昏
+      reCheckCount.numByTotal[tName] = reCheckCount.numByTotal[tName]
+        ? reCheckCount.numByTotal[tName] + 1
+        : 1
+      // 澶嶆牳鏁板垎鍖哄幙
+      reCheckCount.numByDistrict[dName] = reCheckCount.numByDistrict[dName]
+        ? reCheckCount.numByDistrict[dName] + 1
+        : 1
+      // 澶嶆牳鏁板垎琛楅晣
+      reCheckCount.numByStreet[townName] = reCheckCount.numByStreet[townName]
+        ? reCheckCount.numByStreet[townName] + 1
+        : 1
+      // 澶嶆牳鏁板垎鍦烘櫙绫诲瀷
+      reCheckCount.numByScene[sType] = reCheckCount.numByScene[sType]
+        ? reCheckCount.numByScene[sType] + 1
+        : 1
+      // 澶嶆牳鏁板垎鐢ㄦ埛
+      reCheckCount.numByUser[uName] = reCheckCount.numByUser[uName]
+        ? reCheckCount.numByUser[uName] + 1
+        : 1
+    } else {
+      historySceneId.push(d.sceneId)
     }
-  },
-  mounted() {}
+  })
+
+  let series = {}
+  parseSeries(series, reCheckCount)
+  parseSeries(series, changeCount)
+  parseSeries(series, proCount)
+  parseSeries(series, totalCount)
+
+  const res = []
+  for (const key in series) {
+    const e = series[key]
+    res.push(e)
+  }
+
+  return res
+}
+
+function parseSeries(series, c) {
+  // c.numByTotal
+  // c.numByDistrict
+  // c.numByScene
+  // c.numByUser
+
+  for (const key in c.numByTotal) {
+    const value = c.numByTotal[key]
+    if (series[key]) {
+      series[key].data.push(value)
+    } else {
+      series[key] = {
+        name: key,
+        type: 'bar',
+        emphasis: {
+          focus: 'series'
+        },
+        label: {
+          show: true,
+          formatter: '{c}'
+          // position: [0, 10],
+        },
+        data: [value]
+      }
+    }
+  }
+  for (const key in c.numByDistrict) {
+    const value = c.numByDistrict[key]
+    if (series[key]) {
+      series[key].data.push(value)
+    } else {
+      series[key] = {
+        name: `鍖哄幙锛�${key}`,
+        type: 'bar',
+        stack: 'district',
+        emphasis: {
+          focus: 'series'
+        },
+        label: {
+          show: true,
+          formatter: '{c}'
+          // position: 'top',
+        },
+        data: [value]
+      }
+    }
+  }
+  // for (const key in c.numByStreet) {
+  //   const value = c.numByStreet[key]
+  //   if (series[key]) {
+  //     series[key].data.push(value)
+  //   } else {
+  //     series[key] = {
+  //       name: `琛楅晣锛�${key}`,
+  //       type: 'bar',
+  //       stack: 'street',
+  //       emphasis: {
+  //         focus: 'series'
+  //       },
+  //       label: {
+  //         show: true,
+  //         formatter: '{c}'
+  //         // position: 'top',
+  //       },
+  //       data: [value]
+  //     }
+  //   }
+  // }
+  for (const key in c.numByScene) {
+    const value = c.numByScene[key]
+    if (series[key]) {
+      series[key].data.push(value)
+    } else {
+      series[key] = {
+        name: `鍦烘櫙锛�${key}`,
+        type: 'bar',
+        stack: 'scene',
+        emphasis: {
+          focus: 'series'
+        },
+        label: {
+          show: true,
+          formatter: '{c}'
+          // position: [0, 10],
+        },
+        data: [value]
+      }
+    }
+  }
+  for (const key in c.numByUser) {
+    const value = c.numByUser[key]
+    if (series[key]) {
+      series[key].data.push(value)
+    } else {
+      series[key] = {
+        name: `鐢ㄦ埛锛�${key}`,
+        type: 'bar',
+        stack: 'user',
+        emphasis: {
+          focus: 'series'
+        },
+        label: {
+          show: true,
+          formatter: '{c}'
+          // position: [0, 10],
+        },
+        data: [value]
+      }
+    }
+  }
+  return series
 }
 </script>
 
 <style scoped>
-.el-segmented {
+/* .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);
@@ -125,4 +454,9 @@
 .red {
   color: var(--el-color-error);
 }
+
+.bar-chart {
+  width: 400px;
+  height: 400px;
+}
 </style>

--
Gitblit v1.9.3